1 | /* |
2 | * Copyright (C) 2015 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
23 | * THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #include "config.h" |
27 | #include "UniqueIDBDatabaseTransaction.h" |
28 | |
29 | #if ENABLE(INDEXED_DATABASE) |
30 | |
31 | #include "IDBError.h" |
32 | #include "IDBIterateCursorData.h" |
33 | #include "IDBResultData.h" |
34 | #include "IDBServer.h" |
35 | #include "Logging.h" |
36 | #include "UniqueIDBDatabase.h" |
37 | |
38 | namespace WebCore { |
39 | namespace IDBServer { |
40 | |
41 | Ref<UniqueIDBDatabaseTransaction> UniqueIDBDatabaseTransaction::create(UniqueIDBDatabaseConnection& connection, const IDBTransactionInfo& info) |
42 | { |
43 | return adoptRef(*new UniqueIDBDatabaseTransaction(connection, info)); |
44 | } |
45 | |
46 | UniqueIDBDatabaseTransaction::UniqueIDBDatabaseTransaction(UniqueIDBDatabaseConnection& connection, const IDBTransactionInfo& info) |
47 | : m_databaseConnection(connection) |
48 | , m_transactionInfo(info) |
49 | { |
50 | auto database = m_databaseConnection->database(); |
51 | ASSERT(database); |
52 | |
53 | if (m_transactionInfo.mode() == IDBTransactionMode::Versionchange) |
54 | m_originalDatabaseInfo = std::make_unique<IDBDatabaseInfo>(database->info()); |
55 | |
56 | auto& server = database->server(); |
57 | m_server = makeWeakPtr(server); |
58 | server.registerTransaction(*this); |
59 | } |
60 | |
61 | UniqueIDBDatabaseTransaction::~UniqueIDBDatabaseTransaction() |
62 | { |
63 | if (auto database = m_databaseConnection->database()) |
64 | database->transactionDestroyed(*this); |
65 | |
66 | if (m_server) |
67 | m_server->unregisterTransaction(*this); |
68 | } |
69 | |
70 | IDBDatabaseInfo* UniqueIDBDatabaseTransaction::originalDatabaseInfo() const |
71 | { |
72 | ASSERT(m_transactionInfo.mode() == IDBTransactionMode::Versionchange); |
73 | return m_originalDatabaseInfo.get(); |
74 | } |
75 | |
76 | void UniqueIDBDatabaseTransaction::abort() |
77 | { |
78 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::abort" ); |
79 | |
80 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
81 | |
82 | auto database = m_databaseConnection->database(); |
83 | ASSERT(database); |
84 | |
85 | database->abortTransaction(*this, UniqueIDBDatabase::WaitForPendingTasks::Yes, [this, protectedThis](const IDBError& error) { |
86 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::abort (callback)" ); |
87 | m_databaseConnection->didAbortTransaction(*this, error); |
88 | }); |
89 | } |
90 | |
91 | void UniqueIDBDatabaseTransaction::abortWithoutCallback() |
92 | { |
93 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::abortWithoutCallback" ); |
94 | |
95 | m_databaseConnection->abortTransactionWithoutCallback(*this); |
96 | } |
97 | |
98 | bool UniqueIDBDatabaseTransaction::isVersionChange() const |
99 | { |
100 | return m_transactionInfo.mode() == IDBTransactionMode::Versionchange; |
101 | } |
102 | |
103 | bool UniqueIDBDatabaseTransaction::isReadOnly() const |
104 | { |
105 | return m_transactionInfo.mode() == IDBTransactionMode::Readonly; |
106 | } |
107 | |
108 | void UniqueIDBDatabaseTransaction::commit() |
109 | { |
110 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::commit" ); |
111 | |
112 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
113 | |
114 | auto database = m_databaseConnection->database(); |
115 | if (!database || database->hardClosedForUserDelete()) |
116 | return; |
117 | |
118 | database->commitTransaction(*this, [this, protectedThis](const IDBError& error) { |
119 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::commit (callback)" ); |
120 | m_databaseConnection->didCommitTransaction(*this, error); |
121 | }); |
122 | } |
123 | |
124 | void UniqueIDBDatabaseTransaction::createObjectStore(const IDBRequestData& requestData, const IDBObjectStoreInfo& info) |
125 | { |
126 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::createObjectStore" ); |
127 | |
128 | ASSERT(isVersionChange()); |
129 | ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier()); |
130 | |
131 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
132 | |
133 | auto database = m_databaseConnection->database(); |
134 | ASSERT(database); |
135 | |
136 | database->createObjectStore(*this, info, [this, protectedThis, requestData](const IDBError& error) { |
137 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::createObjectStore (callback)" ); |
138 | if (error.isNull()) |
139 | m_databaseConnection->didCreateObjectStore(IDBResultData::createObjectStoreSuccess(requestData.requestIdentifier())); |
140 | else |
141 | m_databaseConnection->didCreateObjectStore(IDBResultData::error(requestData.requestIdentifier(), error)); |
142 | }); |
143 | } |
144 | |
145 | void UniqueIDBDatabaseTransaction::deleteObjectStore(const IDBRequestData& requestData, const String& objectStoreName) |
146 | { |
147 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::deleteObjectStore" ); |
148 | |
149 | ASSERT(isVersionChange()); |
150 | ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier()); |
151 | |
152 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
153 | |
154 | auto database = m_databaseConnection->database(); |
155 | ASSERT(database); |
156 | |
157 | database->deleteObjectStore(*this, objectStoreName, [this, protectedThis, requestData](const IDBError& error) { |
158 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::deleteObjectStore (callback)" ); |
159 | if (error.isNull()) |
160 | m_databaseConnection->didDeleteObjectStore(IDBResultData::deleteObjectStoreSuccess(requestData.requestIdentifier())); |
161 | else |
162 | m_databaseConnection->didDeleteObjectStore(IDBResultData::error(requestData.requestIdentifier(), error)); |
163 | }); |
164 | } |
165 | |
166 | void UniqueIDBDatabaseTransaction::renameObjectStore(const IDBRequestData& requestData, uint64_t objectStoreIdentifier, const String& newName) |
167 | { |
168 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::renameObjectStore" ); |
169 | |
170 | ASSERT(isVersionChange()); |
171 | ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier()); |
172 | |
173 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
174 | |
175 | auto database = m_databaseConnection->database(); |
176 | ASSERT(database); |
177 | |
178 | database->renameObjectStore(*this, objectStoreIdentifier, newName, [this, protectedThis, requestData](const IDBError& error) { |
179 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::renameObjectStore (callback)" ); |
180 | if (error.isNull()) |
181 | m_databaseConnection->didRenameObjectStore(IDBResultData::renameObjectStoreSuccess(requestData.requestIdentifier())); |
182 | else |
183 | m_databaseConnection->didRenameObjectStore(IDBResultData::error(requestData.requestIdentifier(), error)); |
184 | }); |
185 | } |
186 | |
187 | void UniqueIDBDatabaseTransaction::clearObjectStore(const IDBRequestData& requestData, uint64_t objectStoreIdentifier) |
188 | { |
189 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::clearObjectStore" ); |
190 | |
191 | ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier()); |
192 | |
193 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
194 | |
195 | auto database = m_databaseConnection->database(); |
196 | ASSERT(database); |
197 | |
198 | database->clearObjectStore(*this, objectStoreIdentifier, [this, protectedThis, requestData](const IDBError& error) { |
199 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::clearObjectStore (callback)" ); |
200 | if (error.isNull()) |
201 | m_databaseConnection->didClearObjectStore(IDBResultData::clearObjectStoreSuccess(requestData.requestIdentifier())); |
202 | else |
203 | m_databaseConnection->didClearObjectStore(IDBResultData::error(requestData.requestIdentifier(), error)); |
204 | }); |
205 | } |
206 | |
207 | void UniqueIDBDatabaseTransaction::createIndex(const IDBRequestData& requestData, const IDBIndexInfo& info) |
208 | { |
209 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::createIndex" ); |
210 | |
211 | ASSERT(isVersionChange()); |
212 | ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier()); |
213 | |
214 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
215 | |
216 | auto database = m_databaseConnection->database(); |
217 | ASSERT(database); |
218 | |
219 | database->createIndex(*this, info, [this, protectedThis, requestData](const IDBError& error) { |
220 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::createIndex (callback)" ); |
221 | if (error.isNull()) |
222 | m_databaseConnection->didCreateIndex(IDBResultData::createIndexSuccess(requestData.requestIdentifier())); |
223 | else |
224 | m_databaseConnection->didCreateIndex(IDBResultData::error(requestData.requestIdentifier(), error)); |
225 | }); |
226 | } |
227 | |
228 | void UniqueIDBDatabaseTransaction::deleteIndex(const IDBRequestData& requestData, uint64_t objectStoreIdentifier, const String& indexName) |
229 | { |
230 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::deleteIndex" ); |
231 | |
232 | ASSERT(isVersionChange()); |
233 | ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier()); |
234 | |
235 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
236 | |
237 | auto database = m_databaseConnection->database(); |
238 | ASSERT(database); |
239 | |
240 | database->deleteIndex(*this, objectStoreIdentifier, indexName, [this, protectedThis, requestData](const IDBError& error) { |
241 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::createIndex (callback)" ); |
242 | if (error.isNull()) |
243 | m_databaseConnection->didDeleteIndex(IDBResultData::deleteIndexSuccess(requestData.requestIdentifier())); |
244 | else |
245 | m_databaseConnection->didDeleteIndex(IDBResultData::error(requestData.requestIdentifier(), error)); |
246 | }); |
247 | } |
248 | |
249 | void UniqueIDBDatabaseTransaction::renameIndex(const IDBRequestData& requestData, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName) |
250 | { |
251 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::renameIndex" ); |
252 | |
253 | ASSERT(isVersionChange()); |
254 | ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier()); |
255 | |
256 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
257 | |
258 | auto database = m_databaseConnection->database(); |
259 | ASSERT(database); |
260 | |
261 | database->renameIndex(*this, objectStoreIdentifier, indexIdentifier, newName, [this, protectedThis, requestData](const IDBError& error) { |
262 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::renameIndex (callback)" ); |
263 | if (error.isNull()) |
264 | m_databaseConnection->didRenameIndex(IDBResultData::renameIndexSuccess(requestData.requestIdentifier())); |
265 | else |
266 | m_databaseConnection->didRenameIndex(IDBResultData::error(requestData.requestIdentifier(), error)); |
267 | }); |
268 | } |
269 | |
270 | |
271 | void UniqueIDBDatabaseTransaction::putOrAdd(const IDBRequestData& requestData, const IDBKeyData& keyData, const IDBValue& value, IndexedDB::ObjectStoreOverwriteMode overwriteMode) |
272 | { |
273 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::putOrAdd" ); |
274 | |
275 | ASSERT(!isReadOnly()); |
276 | ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier()); |
277 | |
278 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
279 | |
280 | auto database = m_databaseConnection->database(); |
281 | ASSERT(database); |
282 | |
283 | database->putOrAdd(requestData, keyData, value, overwriteMode, [this, protectedThis, requestData](const IDBError& error, const IDBKeyData& key) { |
284 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::putOrAdd (callback)" ); |
285 | |
286 | if (error.isNull()) |
287 | m_databaseConnection->connectionToClient().didPutOrAdd(IDBResultData::putOrAddSuccess(requestData.requestIdentifier(), key)); |
288 | else |
289 | m_databaseConnection->connectionToClient().didPutOrAdd(IDBResultData::error(requestData.requestIdentifier(), error)); |
290 | }); |
291 | } |
292 | |
293 | void UniqueIDBDatabaseTransaction::getRecord(const IDBRequestData& requestData, const IDBGetRecordData& getRecordData) |
294 | { |
295 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getRecord" ); |
296 | |
297 | ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier()); |
298 | |
299 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
300 | |
301 | auto database = m_databaseConnection->database(); |
302 | ASSERT(database); |
303 | |
304 | database->getRecord(requestData, getRecordData, [this, protectedThis, requestData](const IDBError& error, const IDBGetResult& result) { |
305 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getRecord (callback)" ); |
306 | |
307 | if (error.isNull()) |
308 | m_databaseConnection->connectionToClient().didGetRecord(IDBResultData::getRecordSuccess(requestData.requestIdentifier(), result)); |
309 | else |
310 | m_databaseConnection->connectionToClient().didGetRecord(IDBResultData::error(requestData.requestIdentifier(), error)); |
311 | }); |
312 | } |
313 | |
314 | void UniqueIDBDatabaseTransaction::getAllRecords(const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData) |
315 | { |
316 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getAllRecords" ); |
317 | |
318 | ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier()); |
319 | |
320 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
321 | |
322 | auto database = m_databaseConnection->database(); |
323 | ASSERT(database); |
324 | |
325 | database->getAllRecords(requestData, getAllRecordsData, [this, protectedThis, requestData](const IDBError& error, const IDBGetAllResult& result) { |
326 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getAllRecords (callback)" ); |
327 | |
328 | if (error.isNull()) |
329 | m_databaseConnection->connectionToClient().didGetAllRecords(IDBResultData::getAllRecordsSuccess(requestData.requestIdentifier(), result)); |
330 | else |
331 | m_databaseConnection->connectionToClient().didGetAllRecords(IDBResultData::error(requestData.requestIdentifier(), error)); |
332 | }); |
333 | } |
334 | |
335 | void UniqueIDBDatabaseTransaction::getCount(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData) |
336 | { |
337 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getCount" ); |
338 | |
339 | ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier()); |
340 | |
341 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
342 | |
343 | auto database = m_databaseConnection->database(); |
344 | ASSERT(database); |
345 | |
346 | database->getCount(requestData, keyRangeData, [this, protectedThis, requestData](const IDBError& error, uint64_t count) { |
347 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getCount (callback)" ); |
348 | |
349 | if (error.isNull()) |
350 | m_databaseConnection->connectionToClient().didGetCount(IDBResultData::getCountSuccess(requestData.requestIdentifier(), count)); |
351 | else |
352 | m_databaseConnection->connectionToClient().didGetCount(IDBResultData::error(requestData.requestIdentifier(), error)); |
353 | }); |
354 | } |
355 | |
356 | void UniqueIDBDatabaseTransaction::deleteRecord(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData) |
357 | { |
358 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::deleteRecord" ); |
359 | |
360 | ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier()); |
361 | |
362 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
363 | |
364 | auto database = m_databaseConnection->database(); |
365 | ASSERT(database); |
366 | |
367 | database->deleteRecord(requestData, keyRangeData, [this, protectedThis, requestData](const IDBError& error) { |
368 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::deleteRecord (callback)" ); |
369 | |
370 | if (error.isNull()) |
371 | m_databaseConnection->connectionToClient().didDeleteRecord(IDBResultData::deleteRecordSuccess(requestData.requestIdentifier())); |
372 | else |
373 | m_databaseConnection->connectionToClient().didDeleteRecord(IDBResultData::error(requestData.requestIdentifier(), error)); |
374 | }); |
375 | } |
376 | |
377 | void UniqueIDBDatabaseTransaction::openCursor(const IDBRequestData& requestData, const IDBCursorInfo& info) |
378 | { |
379 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::openCursor" ); |
380 | |
381 | ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier()); |
382 | |
383 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
384 | |
385 | auto database = m_databaseConnection->database(); |
386 | ASSERT(database); |
387 | |
388 | database->openCursor(requestData, info, [this, protectedThis, requestData](const IDBError& error, const IDBGetResult& result) { |
389 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::openCursor (callback)" ); |
390 | |
391 | if (error.isNull()) |
392 | m_databaseConnection->connectionToClient().didOpenCursor(IDBResultData::openCursorSuccess(requestData.requestIdentifier(), result)); |
393 | else |
394 | m_databaseConnection->connectionToClient().didOpenCursor(IDBResultData::error(requestData.requestIdentifier(), error)); |
395 | }); |
396 | } |
397 | |
398 | void UniqueIDBDatabaseTransaction::iterateCursor(const IDBRequestData& requestData, const IDBIterateCursorData& data) |
399 | { |
400 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::iterateCursor" ); |
401 | |
402 | ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier()); |
403 | |
404 | RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this); |
405 | |
406 | auto database = m_databaseConnection->database(); |
407 | ASSERT(database); |
408 | |
409 | database->iterateCursor(requestData, data, [this, protectedThis, requestData](const IDBError& error, const IDBGetResult& result) { |
410 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::iterateCursor (callback)" ); |
411 | |
412 | if (error.isNull()) |
413 | m_databaseConnection->connectionToClient().didIterateCursor(IDBResultData::iterateCursorSuccess(requestData.requestIdentifier(), result)); |
414 | else |
415 | m_databaseConnection->connectionToClient().didIterateCursor(IDBResultData::error(requestData.requestIdentifier(), error)); |
416 | }); |
417 | } |
418 | |
419 | const Vector<uint64_t>& UniqueIDBDatabaseTransaction::objectStoreIdentifiers() |
420 | { |
421 | if (!m_objectStoreIdentifiers.isEmpty()) |
422 | return m_objectStoreIdentifiers; |
423 | |
424 | auto& info = m_databaseConnection->database()->info(); |
425 | for (const auto& objectStoreName : info.objectStoreNames()) { |
426 | auto objectStoreInfo = info.infoForExistingObjectStore(objectStoreName); |
427 | ASSERT(objectStoreInfo); |
428 | if (!objectStoreInfo) |
429 | continue; |
430 | |
431 | if (m_transactionInfo.objectStores().contains(objectStoreName)) |
432 | m_objectStoreIdentifiers.append(objectStoreInfo->identifier()); |
433 | } |
434 | |
435 | return m_objectStoreIdentifiers; |
436 | } |
437 | |
438 | void UniqueIDBDatabaseTransaction::didActivateInBackingStore(const IDBError& error) |
439 | { |
440 | LOG(IndexedDB, "UniqueIDBDatabaseTransaction::didActivateInBackingStore" ); |
441 | |
442 | m_databaseConnection->connectionToClient().didStartTransaction(m_transactionInfo.identifier(), error); |
443 | } |
444 | |
445 | } // namespace IDBServer |
446 | } // namespace WebCore |
447 | |
448 | #endif // ENABLE(INDEXED_DATABASE) |
449 | |