Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / server / UniqueIDBDatabase.cpp
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 "UniqueIDBDatabase.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBCursorInfo.h"
32 #include "IDBKeyRangeData.h"
33 #include "IDBResultData.h"
34 #include "IDBServer.h"
35 #include "IDBTransactionInfo.h"
36 #include "Logging.h"
37 #include "UniqueIDBDatabaseConnection.h"
38 #include <wtf/MainThread.h>
39 #include <wtf/NeverDestroyed.h>
40 #include <wtf/ThreadSafeRefCounted.h>
41
42 using namespace JSC;
43
44 namespace WebCore {
45 namespace IDBServer {
46     
47 UniqueIDBDatabase::UniqueIDBDatabase(IDBServer& server, const IDBDatabaseIdentifier& identifier)
48     : m_server(server)
49     , m_identifier(identifier)
50     , m_operationAndTransactionTimer(*this, &UniqueIDBDatabase::operationAndTransactionTimerFired)
51 {
52 }
53
54 UniqueIDBDatabase::~UniqueIDBDatabase()
55 {
56     LOG(IndexedDB, "UniqueIDBDatabase::~UniqueIDBDatabase() (%p)", this);
57     ASSERT(!hasAnyPendingCallbacks());
58     ASSERT(m_inProgressTransactions.isEmpty());
59     ASSERT(m_pendingTransactions.isEmpty());
60     ASSERT(m_openDatabaseConnections.isEmpty());
61 }
62
63 const IDBDatabaseInfo& UniqueIDBDatabase::info() const
64 {
65     RELEASE_ASSERT(m_databaseInfo);
66     return *m_databaseInfo;
67 }
68
69 void UniqueIDBDatabase::openDatabaseConnection(IDBConnectionToClient& connection, const IDBRequestData& requestData)
70 {
71     auto operation = ServerOpenDBRequest::create(connection, requestData);
72     m_pendingOpenDBRequests.append(WTFMove(operation));
73
74     // An open operation is already in progress, so we can't possibly handle this one yet.
75     if (m_isOpeningBackingStore)
76         return;
77
78     handleDatabaseOperations();
79 }
80
81 bool UniqueIDBDatabase::hasAnyPendingCallbacks() const
82 {
83     return !m_errorCallbacks.isEmpty()
84         || !m_keyDataCallbacks.isEmpty()
85         || !m_getResultCallbacks.isEmpty()
86         || !m_countCallbacks.isEmpty();
87 }
88
89 bool UniqueIDBDatabase::isVersionChangeInProgress()
90 {
91 #ifndef NDEBUG
92     if (m_versionChangeTransaction)
93         ASSERT(m_versionChangeDatabaseConnection);
94 #endif
95
96     return m_versionChangeDatabaseConnection;
97 }
98
99 void UniqueIDBDatabase::performCurrentOpenOperation()
100 {
101     LOG(IndexedDB, "(main) UniqueIDBDatabase::performCurrentOpenOperation");
102
103     ASSERT(m_currentOpenDBRequest);
104     ASSERT(m_currentOpenDBRequest->isOpenRequest());
105
106     if (!m_databaseInfo) {
107         m_isOpeningBackingStore = true;
108         m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::openBackingStore, m_identifier));
109         return;
110     }
111
112     // If we previously started a version change operation but were blocked by having open connections,
113     // we might now be unblocked.
114     if (m_versionChangeDatabaseConnection) {
115         if (!m_versionChangeTransaction && !hasAnyOpenConnections())
116             startVersionChangeTransaction();
117         return;
118     }
119
120     // 3.3.1 Opening a database
121     // If requested version is undefined, then let requested version be 1 if db was created in the previous step,
122     // or the current version of db otherwise.
123     uint64_t requestedVersion = m_currentOpenDBRequest->requestData().requestedVersion();
124     if (!requestedVersion)
125         requestedVersion = m_databaseInfo->version() ? m_databaseInfo->version() : 1;
126
127     // 3.3.1 Opening a database
128     // If the database version higher than the requested version, abort these steps and return a VersionError.
129     if (requestedVersion < m_databaseInfo->version()) {
130         auto result = IDBResultData::error(m_currentOpenDBRequest->requestData().requestIdentifier(), IDBError(IDBDatabaseException::VersionError));
131         m_currentOpenDBRequest->connection().didOpenDatabase(result);
132         m_currentOpenDBRequest = nullptr;
133
134         return;
135     }
136
137     Ref<UniqueIDBDatabaseConnection> connection = UniqueIDBDatabaseConnection::create(*this, m_currentOpenDBRequest->connection());
138     UniqueIDBDatabaseConnection* rawConnection = &connection.get();
139
140     if (requestedVersion == m_databaseInfo->version()) {
141         addOpenDatabaseConnection(WTFMove(connection));
142
143         auto result = IDBResultData::openDatabaseSuccess(m_currentOpenDBRequest->requestData().requestIdentifier(), *rawConnection);
144         m_currentOpenDBRequest->connection().didOpenDatabase(result);
145         m_currentOpenDBRequest = nullptr;
146
147         return;
148     }
149
150     ASSERT(!m_versionChangeDatabaseConnection);
151     m_versionChangeDatabaseConnection = rawConnection;
152
153     // 3.3.7 "versionchange" transaction steps
154     // If there's no other open connections to this database, the version change process can begin immediately.
155     if (!hasAnyOpenConnections()) {
156         startVersionChangeTransaction();
157         return;
158     }
159
160     // Otherwise we have to notify all those open connections and wait for them to close.
161     maybeNotifyConnectionsOfVersionChange();
162 }
163
164 void UniqueIDBDatabase::performCurrentDeleteOperation()
165 {
166     ASSERT(isMainThread());
167     LOG(IndexedDB, "(main) UniqueIDBDatabase::performCurrentDeleteOperation");
168
169     ASSERT(m_databaseInfo);
170     ASSERT(m_currentOpenDBRequest);
171     ASSERT(m_currentOpenDBRequest->isDeleteRequest());
172
173     if (m_deleteBackingStoreInProgress)
174         return;
175
176     if (hasAnyOpenConnections()) {
177         maybeNotifyConnectionsOfVersionChange();
178         return;
179     }
180
181     ASSERT(!hasAnyPendingCallbacks());
182     ASSERT(m_inProgressTransactions.isEmpty());
183     ASSERT(m_pendingTransactions.isEmpty());
184     ASSERT(m_openDatabaseConnections.isEmpty());
185
186     m_deleteBackingStoreInProgress = true;
187     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::deleteBackingStore));
188 }
189
190 void UniqueIDBDatabase::deleteBackingStore()
191 {
192     ASSERT(!isMainThread());
193     LOG(IndexedDB, "(db) UniqueIDBDatabase::deleteBackingStore");
194
195     if (m_backingStore) {
196         m_backingStore->deleteBackingStore();
197         m_backingStore = nullptr;
198     }
199
200     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didDeleteBackingStore));
201 }
202
203 void UniqueIDBDatabase::didDeleteBackingStore()
204 {
205     ASSERT(isMainThread());
206     LOG(IndexedDB, "(main) UniqueIDBDatabase::didDeleteBackingStore");
207
208     ASSERT(m_databaseInfo);
209     ASSERT(m_currentOpenDBRequest);
210     ASSERT(m_currentOpenDBRequest->isDeleteRequest());
211     ASSERT(!hasAnyPendingCallbacks());
212     ASSERT(m_inProgressTransactions.isEmpty());
213     ASSERT(m_pendingTransactions.isEmpty());
214     ASSERT(m_openDatabaseConnections.isEmpty());
215
216     m_currentOpenDBRequest->notifyDidDeleteDatabase(*m_databaseInfo);
217     m_currentOpenDBRequest = nullptr;
218     m_databaseInfo = nullptr;
219     m_deletePending = false;
220     m_deleteBackingStoreInProgress = false;
221
222     if (m_pendingOpenDBRequests.isEmpty())
223         m_server.deleteUniqueIDBDatabase(*this);
224     else
225         invokeOperationAndTransactionTimer();
226 }
227
228 void UniqueIDBDatabase::handleDatabaseOperations()
229 {
230     ASSERT(isMainThread());
231     LOG(IndexedDB, "(main) UniqueIDBDatabase::handleDatabaseOperations - There are %zu pending", m_pendingOpenDBRequests.size());
232
233     if (m_versionChangeDatabaseConnection || m_versionChangeTransaction || m_currentOpenDBRequest) {
234         // We can't start any new open-database operations right now, but we might be able to start handling a delete operation.
235         if (!m_currentOpenDBRequest && !m_pendingOpenDBRequests.isEmpty() && m_pendingOpenDBRequests.first()->isDeleteRequest())
236             m_currentOpenDBRequest = m_pendingOpenDBRequests.takeFirst();
237
238         // Some operations (such as the first open operation after a delete) require multiple passes to completely handle
239         if (m_currentOpenDBRequest)
240             handleCurrentOperation();
241
242         return;
243     }
244
245     if (m_pendingOpenDBRequests.isEmpty())
246         return;
247
248     m_currentOpenDBRequest = m_pendingOpenDBRequests.takeFirst();
249     LOG(IndexedDB, "UniqueIDBDatabase::handleDatabaseOperations - Popped an operation, now there are %zu pending", m_pendingOpenDBRequests.size());
250
251     handleCurrentOperation();
252 }
253
254 void UniqueIDBDatabase::handleCurrentOperation()
255 {
256     ASSERT(m_currentOpenDBRequest);
257
258     RefPtr<UniqueIDBDatabase> protector(this);
259
260     if (m_currentOpenDBRequest->isOpenRequest())
261         performCurrentOpenOperation();
262     else if (m_currentOpenDBRequest->isDeleteRequest())
263         performCurrentDeleteOperation();
264     else
265         ASSERT_NOT_REACHED();
266
267     if (!m_currentOpenDBRequest)
268         invokeOperationAndTransactionTimer();
269 }
270
271 bool UniqueIDBDatabase::hasAnyOpenConnections() const
272 {
273     return !m_openDatabaseConnections.isEmpty();
274 }
275
276 static uint64_t generateUniqueCallbackIdentifier()
277 {
278     ASSERT(isMainThread());
279     static uint64_t currentID = 0;
280     return ++currentID;
281 }
282
283 uint64_t UniqueIDBDatabase::storeCallback(ErrorCallback callback)
284 {
285     uint64_t identifier = generateUniqueCallbackIdentifier();
286     ASSERT(!m_errorCallbacks.contains(identifier));
287     m_errorCallbacks.add(identifier, callback);
288     return identifier;
289 }
290
291 uint64_t UniqueIDBDatabase::storeCallback(KeyDataCallback callback)
292 {
293     uint64_t identifier = generateUniqueCallbackIdentifier();
294     ASSERT(!m_keyDataCallbacks.contains(identifier));
295     m_keyDataCallbacks.add(identifier, callback);
296     return identifier;
297 }
298
299 uint64_t UniqueIDBDatabase::storeCallback(GetResultCallback callback)
300 {
301     uint64_t identifier = generateUniqueCallbackIdentifier();
302     ASSERT(!m_getResultCallbacks.contains(identifier));
303     m_getResultCallbacks.add(identifier, callback);
304     return identifier;
305 }
306
307 uint64_t UniqueIDBDatabase::storeCallback(CountCallback callback)
308 {
309     uint64_t identifier = generateUniqueCallbackIdentifier();
310     ASSERT(!m_countCallbacks.contains(identifier));
311     m_countCallbacks.add(identifier, callback);
312     return identifier;
313 }
314
315 void UniqueIDBDatabase::handleDelete(IDBConnectionToClient& connection, const IDBRequestData& requestData)
316 {
317     LOG(IndexedDB, "(main) UniqueIDBDatabase::handleDelete");
318
319     m_pendingOpenDBRequests.append(ServerOpenDBRequest::create(connection, requestData));
320     handleDatabaseOperations();
321 }
322
323 void UniqueIDBDatabase::startVersionChangeTransaction()
324 {
325     LOG(IndexedDB, "(main) UniqueIDBDatabase::startVersionChangeTransaction");
326
327     ASSERT(!m_versionChangeTransaction);
328     ASSERT(m_currentOpenDBRequest);
329     ASSERT(m_currentOpenDBRequest->isOpenRequest());
330     ASSERT(m_versionChangeDatabaseConnection);
331
332     auto operation = WTFMove(m_currentOpenDBRequest);
333
334     uint64_t requestedVersion = operation->requestData().requestedVersion();
335     if (!requestedVersion)
336         requestedVersion = m_databaseInfo->version() ? m_databaseInfo->version() : 1;
337
338     addOpenDatabaseConnection(*m_versionChangeDatabaseConnection);
339
340     m_versionChangeTransaction = &m_versionChangeDatabaseConnection->createVersionChangeTransaction(requestedVersion);
341     m_databaseInfo->setVersion(requestedVersion);
342
343     m_inProgressTransactions.set(m_versionChangeTransaction->info().identifier(), m_versionChangeTransaction);
344     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::beginTransactionInBackingStore, m_versionChangeTransaction->info()));
345
346     auto result = IDBResultData::openDatabaseUpgradeNeeded(operation->requestData().requestIdentifier(), *m_versionChangeTransaction);
347     operation->connection().didOpenDatabase(result);
348 }
349
350 void UniqueIDBDatabase::beginTransactionInBackingStore(const IDBTransactionInfo& info)
351 {
352     LOG(IndexedDB, "(db) UniqueIDBDatabase::beginTransactionInBackingStore");
353     m_backingStore->beginTransaction(info);
354 }
355
356 void UniqueIDBDatabase::maybeNotifyConnectionsOfVersionChange()
357 {
358     ASSERT(m_currentOpenDBRequest);
359
360     if (m_currentOpenDBRequest->hasNotifiedConnectionsOfVersionChange())
361         return;
362
363     uint64_t newVersion = m_currentOpenDBRequest->isOpenRequest() ? m_currentOpenDBRequest->requestData().requestedVersion() : 0;
364     auto requestIdentifier = m_currentOpenDBRequest->requestData().requestIdentifier();
365
366     LOG(IndexedDB, "(main) UniqueIDBDatabase::notifyConnectionsOfVersionChange - %" PRIu64, newVersion);
367
368     // 3.3.7 "versionchange" transaction steps
369     // Fire a versionchange event at each connection in m_openDatabaseConnections that is open.
370     // The event must not be fired on connections which has the closePending flag set.
371     HashSet<uint64_t> connectionIdentifiers;
372     for (auto connection : m_openDatabaseConnections) {
373         if (connection->closePending())
374             continue;
375
376         connection->fireVersionChangeEvent(requestIdentifier, newVersion);
377         connectionIdentifiers.add(connection->identifier());
378     }
379
380     m_currentOpenDBRequest->notifiedConnectionsOfVersionChange(WTFMove(connectionIdentifiers));
381 }
382
383 void UniqueIDBDatabase::notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent(uint64_t connectionIdentifier)
384 {
385     LOG(IndexedDB, "UniqueIDBDatabase::notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent - %" PRIu64, connectionIdentifier);
386
387     ASSERT(m_currentOpenDBRequest);
388
389     m_currentOpenDBRequest->connectionClosedOrFiredVersionChangeEvent(connectionIdentifier);
390
391     if (m_currentOpenDBRequest->hasConnectionsPendingVersionChangeEvent())
392         return;
393
394     if (!hasAnyOpenConnections()) {
395         invokeOperationAndTransactionTimer();
396         return;
397     }
398
399     if (m_currentOpenDBRequest->hasNotifiedBlocked())
400         return;
401
402     // Since all open connections have fired their version change events but not all of them have closed,
403     // this request is officially blocked.
404     m_currentOpenDBRequest->notifyRequestBlocked(m_databaseInfo->version());
405 }
406
407 void UniqueIDBDatabase::didFireVersionChangeEvent(UniqueIDBDatabaseConnection& connection, const IDBResourceIdentifier& requestIdentifier)
408 {
409     LOG(IndexedDB, "UniqueIDBDatabase::didFireVersionChangeEvent");
410
411     if (!m_currentOpenDBRequest)
412         return;
413
414     ASSERT_UNUSED(requestIdentifier, m_currentOpenDBRequest->requestData().requestIdentifier() == requestIdentifier);
415
416     notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent(connection.identifier());
417 }
418
419 void UniqueIDBDatabase::addOpenDatabaseConnection(Ref<UniqueIDBDatabaseConnection>&& connection)
420 {
421     ASSERT(!m_openDatabaseConnections.contains(&connection.get()));
422     m_openDatabaseConnections.add(adoptRef(connection.leakRef()));
423 }
424
425 void UniqueIDBDatabase::openBackingStore(const IDBDatabaseIdentifier& identifier)
426 {
427     ASSERT(!isMainThread());
428     LOG(IndexedDB, "(db) UniqueIDBDatabase::openBackingStore");
429
430     ASSERT(!m_backingStore);
431     m_backingStore = m_server.createBackingStore(identifier);
432     auto databaseInfo = m_backingStore->getOrEstablishDatabaseInfo();
433
434     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didOpenBackingStore, databaseInfo));
435 }
436
437 void UniqueIDBDatabase::didOpenBackingStore(const IDBDatabaseInfo& info)
438 {
439     ASSERT(isMainThread());
440     LOG(IndexedDB, "(main) UniqueIDBDatabase::didOpenBackingStore");
441     
442     m_databaseInfo = std::make_unique<IDBDatabaseInfo>(info);
443
444     ASSERT(m_isOpeningBackingStore);
445     m_isOpeningBackingStore = false;
446
447     handleDatabaseOperations();
448 }
449
450 void UniqueIDBDatabase::createObjectStore(UniqueIDBDatabaseTransaction& transaction, const IDBObjectStoreInfo& info, ErrorCallback callback)
451 {
452     ASSERT(isMainThread());
453     LOG(IndexedDB, "(main) UniqueIDBDatabase::createObjectStore");
454
455     uint64_t callbackID = storeCallback(callback);
456     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateObjectStore, callbackID, transaction.info().identifier(), info));
457 }
458
459 void UniqueIDBDatabase::performCreateObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& info)
460 {
461     ASSERT(!isMainThread());
462     LOG(IndexedDB, "(db) UniqueIDBDatabase::performCreateObjectStore");
463
464     ASSERT(m_backingStore);
465     m_backingStore->createObjectStore(transactionIdentifier, info);
466
467     IDBError error;
468     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateObjectStore, callbackIdentifier, error, info));
469 }
470
471 void UniqueIDBDatabase::didPerformCreateObjectStore(uint64_t callbackIdentifier, const IDBError& error, const IDBObjectStoreInfo& info)
472 {
473     ASSERT(isMainThread());
474     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCreateObjectStore");
475
476     if (error.isNull())
477         m_databaseInfo->addExistingObjectStore(info);
478
479     performErrorCallback(callbackIdentifier, error);
480 }
481
482 void UniqueIDBDatabase::deleteObjectStore(UniqueIDBDatabaseTransaction& transaction, const String& objectStoreName, ErrorCallback callback)
483 {
484     ASSERT(isMainThread());
485     LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteObjectStore");
486
487     uint64_t callbackID = storeCallback(callback);
488     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performDeleteObjectStore, callbackID, transaction.info().identifier(), objectStoreName));
489 }
490
491 void UniqueIDBDatabase::performDeleteObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const String& objectStoreName)
492 {
493     ASSERT(!isMainThread());
494     LOG(IndexedDB, "(db) UniqueIDBDatabase::performDeleteObjectStore");
495
496     ASSERT(m_backingStore);
497     m_backingStore->deleteObjectStore(transactionIdentifier, objectStoreName);
498
499     IDBError error;
500     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformDeleteObjectStore, callbackIdentifier, error, objectStoreName));
501 }
502
503 void UniqueIDBDatabase::didPerformDeleteObjectStore(uint64_t callbackIdentifier, const IDBError& error, const String& objectStoreName)
504 {
505     ASSERT(isMainThread());
506     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformDeleteObjectStore");
507
508     if (error.isNull())
509         m_databaseInfo->deleteObjectStore(objectStoreName);
510
511     performErrorCallback(callbackIdentifier, error);
512 }
513
514 void UniqueIDBDatabase::clearObjectStore(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, ErrorCallback callback)
515 {
516     ASSERT(isMainThread());
517     LOG(IndexedDB, "(main) UniqueIDBDatabase::clearObjectStore");
518
519     uint64_t callbackID = storeCallback(callback);
520     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performClearObjectStore, callbackID, transaction.info().identifier(), objectStoreIdentifier));
521 }
522
523 void UniqueIDBDatabase::performClearObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier)
524 {
525     ASSERT(!isMainThread());
526     LOG(IndexedDB, "(db) UniqueIDBDatabase::performClearObjectStore");
527
528     ASSERT(m_backingStore);
529     m_backingStore->clearObjectStore(transactionIdentifier, objectStoreIdentifier);
530
531     IDBError error;
532     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformClearObjectStore, callbackIdentifier, error));
533 }
534
535 void UniqueIDBDatabase::didPerformClearObjectStore(uint64_t callbackIdentifier, const IDBError& error)
536 {
537     ASSERT(isMainThread());
538     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformClearObjectStore");
539
540     performErrorCallback(callbackIdentifier, error);
541 }
542
543 void UniqueIDBDatabase::createIndex(UniqueIDBDatabaseTransaction& transaction, const IDBIndexInfo& info, ErrorCallback callback)
544 {
545     ASSERT(isMainThread());
546     LOG(IndexedDB, "(main) UniqueIDBDatabase::createIndex");
547
548     uint64_t callbackID = storeCallback(callback);
549     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateIndex, callbackID, transaction.info().identifier(), info));
550 }
551
552 void UniqueIDBDatabase::performCreateIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo& info)
553 {
554     ASSERT(!isMainThread());
555     LOG(IndexedDB, "(db) UniqueIDBDatabase::performCreateIndex");
556
557     ASSERT(m_backingStore);
558     IDBError error = m_backingStore->createIndex(transactionIdentifier, info);
559
560     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateIndex, callbackIdentifier, error, info));
561 }
562
563 void UniqueIDBDatabase::didPerformCreateIndex(uint64_t callbackIdentifier, const IDBError& error, const IDBIndexInfo& info)
564 {
565     ASSERT(isMainThread());
566     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCreateIndex");
567
568     if (error.isNull()) {
569         ASSERT(m_databaseInfo);
570         auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(info.objectStoreIdentifier());
571         ASSERT(objectStoreInfo);
572         objectStoreInfo->addExistingIndex(info);
573     }
574
575     performErrorCallback(callbackIdentifier, error);
576 }
577
578 void UniqueIDBDatabase::deleteIndex(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, const String& indexName, ErrorCallback callback)
579 {
580     ASSERT(isMainThread());
581     LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteIndex");
582
583     uint64_t callbackID = storeCallback(callback);
584     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performDeleteIndex, callbackID, transaction.info().identifier(), objectStoreIdentifier, indexName));
585 }
586
587 void UniqueIDBDatabase::performDeleteIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const String& indexName)
588 {
589     ASSERT(!isMainThread());
590     LOG(IndexedDB, "(db) UniqueIDBDatabase::performDeleteIndex");
591
592     ASSERT(m_backingStore);
593     m_backingStore->deleteIndex(transactionIdentifier, objectStoreIdentifier, indexName);
594
595     IDBError error;
596     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformDeleteIndex, callbackIdentifier, error, objectStoreIdentifier, indexName));
597 }
598
599 void UniqueIDBDatabase::didPerformDeleteIndex(uint64_t callbackIdentifier, const IDBError& error, uint64_t objectStoreIdentifier, const String& indexName)
600 {
601     ASSERT(isMainThread());
602     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformDeleteIndex");
603
604     if (error.isNull()) {
605         auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
606         if (objectStoreInfo)
607             objectStoreInfo->deleteIndex(indexName);
608     }
609
610     performErrorCallback(callbackIdentifier, error);
611 }
612
613 void UniqueIDBDatabase::putOrAdd(const IDBRequestData& requestData, const IDBKeyData& keyData, const ThreadSafeDataBuffer& valueData, IndexedDB::ObjectStoreOverwriteMode overwriteMode, KeyDataCallback callback)
614 {
615     ASSERT(isMainThread());
616     LOG(IndexedDB, "(main) UniqueIDBDatabase::putOrAdd");
617
618     uint64_t callbackID = storeCallback(callback);
619     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performPutOrAdd, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyData, valueData, overwriteMode));
620 }
621
622 VM& UniqueIDBDatabase::databaseThreadVM()
623 {
624     ASSERT(!isMainThread());
625     static VM* vm = &VM::create().leakRef();
626     return *vm;
627 }
628
629 ExecState& UniqueIDBDatabase::databaseThreadExecState()
630 {
631     ASSERT(!isMainThread());
632
633     static NeverDestroyed<Strong<JSGlobalObject>> globalObject(databaseThreadVM(), JSGlobalObject::create(databaseThreadVM(), JSGlobalObject::createStructure(databaseThreadVM(), jsNull())));
634
635     RELEASE_ASSERT(globalObject.get()->globalExec());
636     return *globalObject.get()->globalExec();
637 }
638
639 void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, const ThreadSafeDataBuffer& originalRecordValue, IndexedDB::ObjectStoreOverwriteMode overwriteMode)
640 {
641     ASSERT(!isMainThread());
642     LOG(IndexedDB, "(db) UniqueIDBDatabase::performPutOrAdd");
643
644     ASSERT(m_backingStore);
645     ASSERT(objectStoreIdentifier);
646
647     IDBKeyData usedKey;
648     IDBError error;
649
650     auto objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
651     if (!objectStoreInfo) {
652         error = IDBError(IDBDatabaseException::InvalidStateError, ASCIILiteral("Object store cannot be found in the backing store"));
653         m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
654         return;
655     }
656
657     bool usedKeyIsGenerated = false;
658     if (objectStoreInfo->autoIncrement() && !keyData.isValid()) {
659         uint64_t keyNumber;
660         error = m_backingStore->generateKeyNumber(transactionIdentifier, objectStoreIdentifier, keyNumber);
661         if (!error.isNull()) {
662             m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
663             return;
664         }
665         
666         usedKey.setNumberValue(keyNumber);
667         usedKeyIsGenerated = true;
668     } else
669         usedKey = keyData;
670
671     if (overwriteMode == IndexedDB::ObjectStoreOverwriteMode::NoOverwrite) {
672         bool keyExists;
673         error = m_backingStore->keyExistsInObjectStore(transactionIdentifier, objectStoreIdentifier, usedKey, keyExists);
674         if (error.isNull() && keyExists)
675             error = IDBError(IDBDatabaseException::ConstraintError, ASCIILiteral("Key already exists in the object store"));
676
677         if (!error.isNull()) {
678             m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
679             return;
680         }
681     }
682
683     // 3.4.1.2 Object Store Storage Operation
684     // If ObjectStore has a key path and the key is autogenerated, then inject the key into the value
685     // using steps to assign a key to a value using a key path.
686     ThreadSafeDataBuffer injectedRecordValue;
687     if (usedKeyIsGenerated && !objectStoreInfo->keyPath().isNull()) {
688         JSLockHolder locker(databaseThreadVM());
689
690         JSValue value = deserializeIDBValueDataToJSValue(databaseThreadExecState(), originalRecordValue);
691         if (value.isUndefined()) {
692             m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(IDBDatabaseException::ConstraintError, ASCIILiteral("Unable to deserialize record value for record key injection")), usedKey));
693             return;
694         }
695
696         if (!injectIDBKeyIntoScriptValue(databaseThreadExecState(), usedKey, value, objectStoreInfo->keyPath())) {
697             m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(IDBDatabaseException::ConstraintError, ASCIILiteral("Unable to inject record key into record value")), usedKey));
698             return;
699         }
700
701         auto serializedValue = SerializedScriptValue::create(&databaseThreadExecState(), value, nullptr, nullptr);
702         if (databaseThreadExecState().hadException()) {
703             m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(IDBDatabaseException::ConstraintError, ASCIILiteral("Unable to serialize record value after injecting record key")), usedKey));
704             return;
705         }
706
707         injectedRecordValue = ThreadSafeDataBuffer::copyVector(serializedValue->data());
708     }
709
710     // 3.4.1 Object Store Storage Operation
711     // ...If a record already exists in store ...
712     // then remove the record from store using the steps for deleting records from an object store...
713     // This is important because formally deleting it from from the object store also removes it from the appropriate indexes.
714     error = m_backingStore->deleteRange(transactionIdentifier, objectStoreIdentifier, usedKey);
715     if (!error.isNull()) {
716         m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
717         return;
718     }
719
720     error = m_backingStore->addRecord(transactionIdentifier, objectStoreIdentifier, usedKey, injectedRecordValue.data() ? injectedRecordValue : originalRecordValue);
721     if (!error.isNull()) {
722         m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
723         return;
724     }
725
726     if (overwriteMode != IndexedDB::ObjectStoreOverwriteMode::OverwriteForCursor && objectStoreInfo->autoIncrement() && keyData.type() == IndexedDB::KeyType::Number)
727         error = m_backingStore->maybeUpdateKeyGeneratorNumber(transactionIdentifier, objectStoreIdentifier, keyData.number());
728
729     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
730 }
731
732 void UniqueIDBDatabase::didPerformPutOrAdd(uint64_t callbackIdentifier, const IDBError& error, const IDBKeyData& resultKey)
733 {
734     ASSERT(isMainThread());
735     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformPutOrAdd");
736
737     performKeyDataCallback(callbackIdentifier, error, resultKey);
738 }
739
740 void UniqueIDBDatabase::getRecord(const IDBRequestData& requestData, const IDBKeyRangeData& range, GetResultCallback callback)
741 {
742     ASSERT(isMainThread());
743     LOG(IndexedDB, "(main) UniqueIDBDatabase::getRecord");
744
745     uint64_t callbackID = storeCallback(callback);
746
747     if (uint64_t indexIdentifier = requestData.indexIdentifier())
748         m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetIndexRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), indexIdentifier, requestData.indexRecordType(), range));
749     else
750         m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), range));
751 }
752
753 void UniqueIDBDatabase::performGetRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& keyRangeData)
754 {
755     ASSERT(!isMainThread());
756     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetRecord");
757
758     ASSERT(m_backingStore);
759
760     ThreadSafeDataBuffer valueData;
761     IDBError error = m_backingStore->getRecord(transactionIdentifier, objectStoreIdentifier, keyRangeData, valueData);
762
763     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetRecord, callbackIdentifier, error, valueData));
764 }
765
766 void UniqueIDBDatabase::performGetIndexRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType recordType, const IDBKeyRangeData& range)
767 {
768     ASSERT(!isMainThread());
769     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetIndexRecord");
770
771     ASSERT(m_backingStore);
772
773     IDBGetResult result;
774     IDBError error = m_backingStore->getIndexRecord(transactionIdentifier, objectStoreIdentifier, indexIdentifier, recordType, range, result);
775
776     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetRecord, callbackIdentifier, error, result));
777 }
778
779 void UniqueIDBDatabase::didPerformGetRecord(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& result)
780 {
781     ASSERT(isMainThread());
782     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformGetRecord");
783
784     performGetResultCallback(callbackIdentifier, error, result);
785 }
786
787 void UniqueIDBDatabase::getCount(const IDBRequestData& requestData, const IDBKeyRangeData& range, CountCallback callback)
788 {
789     ASSERT(isMainThread());
790     LOG(IndexedDB, "(main) UniqueIDBDatabase::getCount");
791
792     uint64_t callbackID = storeCallback(callback);
793     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetCount, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), requestData.indexIdentifier(), range));
794 }
795
796 void UniqueIDBDatabase::performGetCount(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData& keyRangeData)
797 {
798     ASSERT(!isMainThread());
799     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetCount");
800
801     ASSERT(m_backingStore);
802     ASSERT(objectStoreIdentifier);
803
804     uint64_t count;
805     IDBError error = m_backingStore->getCount(transactionIdentifier, objectStoreIdentifier, indexIdentifier, keyRangeData, count);
806
807     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetCount, callbackIdentifier, error, count));
808 }
809
810 void UniqueIDBDatabase::didPerformGetCount(uint64_t callbackIdentifier, const IDBError& error, uint64_t count)
811 {
812     ASSERT(isMainThread());
813     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformGetCount");
814
815     performCountCallback(callbackIdentifier, error, count);
816 }
817
818 void UniqueIDBDatabase::deleteRecord(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData, ErrorCallback callback)
819 {
820     ASSERT(isMainThread());
821     LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteRecord");
822
823     uint64_t callbackID = storeCallback(callback);
824     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performDeleteRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyRangeData));
825 }
826
827 void UniqueIDBDatabase::performDeleteRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range)
828 {
829     ASSERT(!isMainThread());
830     LOG(IndexedDB, "(db) UniqueIDBDatabase::performDeleteRecord");
831
832     IDBError error = m_backingStore->deleteRange(transactionIdentifier, objectStoreIdentifier, range);
833
834     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformDeleteRecord, callbackIdentifier, error));
835 }
836
837 void UniqueIDBDatabase::didPerformDeleteRecord(uint64_t callbackIdentifier, const IDBError& error)
838 {
839     ASSERT(isMainThread());
840     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformDeleteRecord");
841
842     performErrorCallback(callbackIdentifier, error);
843 }
844
845 void UniqueIDBDatabase::openCursor(const IDBRequestData& requestData, const IDBCursorInfo& info, GetResultCallback callback)
846 {
847     ASSERT(isMainThread());
848     LOG(IndexedDB, "(main) UniqueIDBDatabase::openCursor");
849
850     uint64_t callbackID = storeCallback(callback);
851     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performOpenCursor, callbackID, requestData.transactionIdentifier(), info));
852 }
853
854 void UniqueIDBDatabase::performOpenCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo& info)
855 {
856     ASSERT(!isMainThread());
857     LOG(IndexedDB, "(db) UniqueIDBDatabase::performOpenCursor");
858
859     IDBGetResult result;
860     IDBError error = m_backingStore->openCursor(transactionIdentifier, info, result);
861
862     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformOpenCursor, callbackIdentifier, error, result));
863 }
864
865 void UniqueIDBDatabase::didPerformOpenCursor(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& result)
866 {
867     ASSERT(isMainThread());
868     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformOpenCursor");
869
870     performGetResultCallback(callbackIdentifier, error, result);
871 }
872
873 void UniqueIDBDatabase::iterateCursor(const IDBRequestData& requestData, const IDBKeyData& key, unsigned long count, GetResultCallback callback)
874 {
875     ASSERT(isMainThread());
876     LOG(IndexedDB, "(main) UniqueIDBDatabase::iterateCursor");
877
878     uint64_t callbackID = storeCallback(callback);
879     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performIterateCursor, callbackID, requestData.transactionIdentifier(), requestData.cursorIdentifier(), key, count));
880 }
881
882 void UniqueIDBDatabase::performIterateCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, const IDBKeyData& key, unsigned long count)
883 {
884     ASSERT(!isMainThread());
885     LOG(IndexedDB, "(db) UniqueIDBDatabase::performIterateCursor");
886
887     IDBGetResult result;
888     IDBError error = m_backingStore->iterateCursor(transactionIdentifier, cursorIdentifier, key, count, result);
889
890     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformIterateCursor, callbackIdentifier, error, result));
891 }
892
893 void UniqueIDBDatabase::didPerformIterateCursor(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& result)
894 {
895     ASSERT(isMainThread());
896     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformIterateCursor");
897
898     performGetResultCallback(callbackIdentifier, error, result);
899 }
900
901 void UniqueIDBDatabase::commitTransaction(UniqueIDBDatabaseTransaction& transaction, ErrorCallback callback)
902 {
903     ASSERT(isMainThread());
904     LOG(IndexedDB, "(main) UniqueIDBDatabase::commitTransaction");
905
906     ASSERT(&transaction.databaseConnection().database() == this);
907
908     if (m_versionChangeTransaction == &transaction) {
909         ASSERT(&m_versionChangeTransaction->databaseConnection() == m_versionChangeDatabaseConnection);
910         ASSERT(m_databaseInfo->version() == transaction.info().newVersion());
911
912         invokeOperationAndTransactionTimer();
913     }
914
915     uint64_t callbackID = storeCallback(callback);
916     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCommitTransaction, callbackID, transaction.info().identifier()));
917 }
918
919 void UniqueIDBDatabase::performCommitTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier)
920 {
921     ASSERT(!isMainThread());
922     LOG(IndexedDB, "(db) UniqueIDBDatabase::performCommitTransaction");
923
924     IDBError error = m_backingStore->commitTransaction(transactionIdentifier);
925     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCommitTransaction, callbackIdentifier, error, transactionIdentifier));
926 }
927
928 void UniqueIDBDatabase::didPerformCommitTransaction(uint64_t callbackIdentifier, const IDBError& error, const IDBResourceIdentifier& transactionIdentifier)
929 {
930     ASSERT(isMainThread());
931     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCommitTransaction");
932
933     inProgressTransactionCompleted(transactionIdentifier);
934
935     performErrorCallback(callbackIdentifier, error);
936 }
937
938 void UniqueIDBDatabase::abortTransaction(UniqueIDBDatabaseTransaction& transaction, ErrorCallback callback)
939 {
940     ASSERT(isMainThread());
941     LOG(IndexedDB, "(main) UniqueIDBDatabase::abortTransaction");
942
943     ASSERT(&transaction.databaseConnection().database() == this);
944
945     uint64_t callbackID = storeCallback(callback);
946     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performAbortTransaction, callbackID, transaction.info().identifier()));
947 }
948
949 void UniqueIDBDatabase::didFinishHandlingVersionChange(UniqueIDBDatabaseTransaction& transaction)
950 {
951     ASSERT(isMainThread());
952     LOG(IndexedDB, "(main) UniqueIDBDatabase::didFinishHandlingVersionChange");
953
954     ASSERT(m_versionChangeTransaction);
955     ASSERT_UNUSED(transaction, m_versionChangeTransaction == &transaction);
956
957     m_versionChangeTransaction = nullptr;
958     m_versionChangeDatabaseConnection = nullptr;
959
960     invokeOperationAndTransactionTimer();
961 }
962
963 void UniqueIDBDatabase::performAbortTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier)
964 {
965     ASSERT(!isMainThread());
966     LOG(IndexedDB, "(db) UniqueIDBDatabase::performAbortTransaction");
967
968     IDBError error = m_backingStore->abortTransaction(transactionIdentifier);
969     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformAbortTransaction, callbackIdentifier, error, transactionIdentifier));
970 }
971
972 void UniqueIDBDatabase::didPerformAbortTransaction(uint64_t callbackIdentifier, const IDBError& error, const IDBResourceIdentifier& transactionIdentifier)
973 {
974     ASSERT(isMainThread());
975     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformAbortTransaction");
976
977     if (m_versionChangeTransaction && m_versionChangeTransaction->info().identifier() == transactionIdentifier) {
978         ASSERT(&m_versionChangeTransaction->databaseConnection() == m_versionChangeDatabaseConnection);
979         ASSERT(m_versionChangeTransaction->originalDatabaseInfo());
980         m_databaseInfo = std::make_unique<IDBDatabaseInfo>(*m_versionChangeTransaction->originalDatabaseInfo());
981     }
982
983     inProgressTransactionCompleted(transactionIdentifier);
984
985     performErrorCallback(callbackIdentifier, error);
986 }
987
988 void UniqueIDBDatabase::transactionDestroyed(UniqueIDBDatabaseTransaction& transaction)
989 {
990     if (m_versionChangeTransaction == &transaction)
991         m_versionChangeTransaction = nullptr;
992 }
993
994 void UniqueIDBDatabase::connectionClosedFromClient(UniqueIDBDatabaseConnection& connection)
995 {
996     ASSERT(isMainThread());
997     LOG(IndexedDB, "(main) UniqueIDBDatabase::connectionClosedFromClient");
998
999     if (m_versionChangeDatabaseConnection == &connection)
1000         m_versionChangeDatabaseConnection = nullptr;
1001
1002     ASSERT(m_openDatabaseConnections.contains(&connection));
1003
1004     if (m_currentOpenDBRequest)
1005         notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent(connection.identifier());
1006
1007     Deque<RefPtr<UniqueIDBDatabaseTransaction>> pendingTransactions;
1008     while (!m_pendingTransactions.isEmpty()) {
1009         auto transaction = m_pendingTransactions.takeFirst();
1010         if (&transaction->databaseConnection() != &connection)
1011             pendingTransactions.append(WTFMove(transaction));
1012     }
1013
1014     if (!pendingTransactions.isEmpty())
1015         m_pendingTransactions.swap(pendingTransactions);
1016
1017     auto removedConnection = m_openDatabaseConnections.take(&connection);
1018     if (removedConnection->hasNonFinishedTransactions()) {
1019         m_closePendingDatabaseConnections.add(WTFMove(removedConnection));
1020         return;
1021     }
1022
1023     // Now that a database connection has closed, previously blocked operations might be runnable.
1024     invokeOperationAndTransactionTimer();
1025 }
1026
1027 void UniqueIDBDatabase::enqueueTransaction(Ref<UniqueIDBDatabaseTransaction>&& transaction)
1028 {
1029     LOG(IndexedDB, "UniqueIDBDatabase::enqueueTransaction");
1030
1031     ASSERT(transaction->info().mode() != IndexedDB::TransactionMode::VersionChange);
1032
1033     m_pendingTransactions.append(WTFMove(transaction));
1034
1035     invokeOperationAndTransactionTimer();
1036 }
1037
1038 void UniqueIDBDatabase::invokeOperationAndTransactionTimer()
1039 {
1040     LOG(IndexedDB, "UniqueIDBDatabase::invokeOperationAndTransactionTimer()");
1041     if (!m_operationAndTransactionTimer.isActive())
1042         m_operationAndTransactionTimer.startOneShot(0);
1043 }
1044
1045 void UniqueIDBDatabase::operationAndTransactionTimerFired()
1046 {
1047     LOG(IndexedDB, "(main) UniqueIDBDatabase::operationAndTransactionTimerFired");
1048
1049     RefPtr<UniqueIDBDatabase> protector(this);
1050
1051     // The current operation might require multiple attempts to handle, so try to
1052     // make further progress on it now.
1053     if (m_currentOpenDBRequest)
1054         handleCurrentOperation();
1055
1056     if (!m_currentOpenDBRequest)
1057         handleDatabaseOperations();
1058
1059     bool hadDeferredTransactions = false;
1060     auto transaction = takeNextRunnableTransaction(hadDeferredTransactions);
1061
1062     if (transaction) {
1063         m_inProgressTransactions.set(transaction->info().identifier(), transaction);
1064         for (auto objectStore : transaction->objectStoreIdentifiers())
1065             m_objectStoreTransactionCounts.add(objectStore);
1066
1067         activateTransactionInBackingStore(*transaction);
1068
1069         // If no transactions were deferred, it's possible we can start another transaction right now.
1070         if (!hadDeferredTransactions)
1071             invokeOperationAndTransactionTimer();
1072     }
1073 }
1074
1075 void UniqueIDBDatabase::activateTransactionInBackingStore(UniqueIDBDatabaseTransaction& transaction)
1076 {
1077     LOG(IndexedDB, "(main) UniqueIDBDatabase::activateTransactionInBackingStore");
1078
1079     RefPtr<UniqueIDBDatabase> self(this);
1080     RefPtr<UniqueIDBDatabaseTransaction> refTransaction(&transaction);
1081
1082     auto callback = [this, self, refTransaction](const IDBError& error) {
1083         refTransaction->didActivateInBackingStore(error);
1084     };
1085
1086     uint64_t callbackID = storeCallback(callback);
1087     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performActivateTransactionInBackingStore, callbackID, transaction.info()));
1088 }
1089
1090 void UniqueIDBDatabase::performActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBTransactionInfo& info)
1091 {
1092     LOG(IndexedDB, "(db) UniqueIDBDatabase::performActivateTransactionInBackingStore");
1093
1094     IDBError error = m_backingStore->beginTransaction(info);
1095     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformActivateTransactionInBackingStore, callbackIdentifier, error));
1096 }
1097
1098 void UniqueIDBDatabase::didPerformActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBError& error)
1099 {
1100     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformActivateTransactionInBackingStore");
1101
1102     invokeOperationAndTransactionTimer();
1103
1104     performErrorCallback(callbackIdentifier, error);
1105 }
1106
1107 template<typename T> bool scopesOverlap(const T& aScopes, const Vector<uint64_t>& bScopes)
1108 {
1109     for (auto scope : bScopes) {
1110         if (aScopes.contains(scope))
1111             return true;
1112     }
1113
1114     return false;
1115 }
1116
1117 RefPtr<UniqueIDBDatabaseTransaction> UniqueIDBDatabase::takeNextRunnableTransaction(bool& hadDeferredTransactions)
1118 {
1119     Deque<RefPtr<UniqueIDBDatabaseTransaction>> deferredTransactions;
1120     RefPtr<UniqueIDBDatabaseTransaction> currentTransaction;
1121
1122     while (!m_pendingTransactions.isEmpty()) {
1123         currentTransaction = m_pendingTransactions.takeFirst();
1124
1125         switch (currentTransaction->info().mode()) {
1126         case IndexedDB::TransactionMode::ReadOnly:
1127             // If there are any deferred transactions, the first one is a read-write transaction we need to unblock.
1128             // Therefore, skip this read-only transaction if its scope overlaps with that read-write transaction.
1129             if (!deferredTransactions.isEmpty()) {
1130                 ASSERT(deferredTransactions.first()->info().mode() == IndexedDB::TransactionMode::ReadWrite);
1131                 if (scopesOverlap(deferredTransactions.first()->objectStoreIdentifiers(), currentTransaction->objectStoreIdentifiers()))
1132                     deferredTransactions.append(WTFMove(currentTransaction));
1133             }
1134
1135             break;
1136         case IndexedDB::TransactionMode::ReadWrite:
1137             // If this read-write transaction's scope overlaps with running transactions, it must be deferred.
1138             if (scopesOverlap(m_objectStoreTransactionCounts, currentTransaction->objectStoreIdentifiers()))
1139                 deferredTransactions.append(WTFMove(currentTransaction));
1140
1141             break;
1142         case IndexedDB::TransactionMode::VersionChange:
1143             // Version change transactions should never be scheduled in the traditional manner.
1144             RELEASE_ASSERT_NOT_REACHED();
1145         }
1146
1147         // If we didn't defer the currentTransaction above, it can be run now.
1148         if (currentTransaction)
1149             break;
1150     }
1151
1152     hadDeferredTransactions = !deferredTransactions.isEmpty();
1153     if (!hadDeferredTransactions)
1154         return currentTransaction;
1155
1156     // Prepend the deferred transactions back on the beginning of the deque for future scheduling passes.
1157     while (!deferredTransactions.isEmpty())
1158         m_pendingTransactions.prepend(deferredTransactions.takeLast());
1159
1160     return currentTransaction;
1161 }
1162
1163 void UniqueIDBDatabase::inProgressTransactionCompleted(const IDBResourceIdentifier& transactionIdentifier)
1164 {
1165     auto transaction = m_inProgressTransactions.take(transactionIdentifier);
1166     ASSERT(transaction);
1167
1168     for (auto objectStore : transaction->objectStoreIdentifiers())
1169         m_objectStoreTransactionCounts.remove(objectStore);
1170
1171     if (!transaction->databaseConnection().hasNonFinishedTransactions())
1172         m_closePendingDatabaseConnections.remove(&transaction->databaseConnection());
1173
1174     // Previously blocked operations might be runnable.
1175     invokeOperationAndTransactionTimer();
1176 }
1177
1178 void UniqueIDBDatabase::performErrorCallback(uint64_t callbackIdentifier, const IDBError& error)
1179 {
1180     auto callback = m_errorCallbacks.take(callbackIdentifier);
1181     ASSERT(callback);
1182     callback(error);
1183 }
1184
1185 void UniqueIDBDatabase::performKeyDataCallback(uint64_t callbackIdentifier, const IDBError& error, const IDBKeyData& resultKey)
1186 {
1187     auto callback = m_keyDataCallbacks.take(callbackIdentifier);
1188     ASSERT(callback);
1189     callback(error, resultKey);
1190 }
1191
1192 void UniqueIDBDatabase::performGetResultCallback(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& resultData)
1193 {
1194     auto callback = m_getResultCallbacks.take(callbackIdentifier);
1195     ASSERT(callback);
1196     callback(error, resultData);
1197 }
1198
1199 void UniqueIDBDatabase::performCountCallback(uint64_t callbackIdentifier, const IDBError& error, uint64_t count)
1200 {
1201     auto callback = m_countCallbacks.take(callbackIdentifier);
1202     ASSERT(callback);
1203     callback(error, count);
1204 }
1205
1206 } // namespace IDBServer
1207 } // namespace WebCore
1208
1209 #endif // ENABLE(INDEXED_DATABASE)