4ef69da7a0d7e77f80118d6523de0aea922b0333
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / server / UniqueIDBDatabase.cpp
1 /*
2  * Copyright (C) 2015, 2016 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 "IDBGetAllRecordsData.h"
33 #include "IDBGetAllResult.h"
34 #include "IDBGetRecordData.h"
35 #include "IDBKeyRangeData.h"
36 #include "IDBResultData.h"
37 #include "IDBServer.h"
38 #include "IDBTransactionInfo.h"
39 #include "IDBValue.h"
40 #include "Logging.h"
41 #include "ScopeGuard.h"
42 #include "SerializedScriptValue.h"
43 #include "UniqueIDBDatabaseConnection.h"
44 #include <heap/HeapInlines.h>
45 #include <runtime/AuxiliaryBarrierInlines.h>
46 #include <runtime/StructureInlines.h>
47 #include <wtf/MainThread.h>
48 #include <wtf/NeverDestroyed.h>
49 #include <wtf/ThreadSafeRefCounted.h>
50
51 using namespace JSC;
52
53 namespace WebCore {
54 namespace IDBServer {
55
56 UniqueIDBDatabase::UniqueIDBDatabase(IDBServer& server, const IDBDatabaseIdentifier& identifier)
57     : m_server(server)
58     , m_identifier(identifier)
59     , m_operationAndTransactionTimer(*this, &UniqueIDBDatabase::operationAndTransactionTimerFired)
60 {
61     LOG(IndexedDB, "UniqueIDBDatabase::UniqueIDBDatabase() (%p) %s", this, m_identifier.debugString().utf8().data());
62 }
63
64 UniqueIDBDatabase::~UniqueIDBDatabase()
65 {
66     LOG(IndexedDB, "UniqueIDBDatabase::~UniqueIDBDatabase() (%p) %s", this, m_identifier.debugString().utf8().data());
67     ASSERT(isMainThread());
68     ASSERT(!hasAnyPendingCallbacks());
69     ASSERT(!hasUnfinishedTransactions());
70     ASSERT(m_pendingTransactions.isEmpty());
71     ASSERT(m_openDatabaseConnections.isEmpty());
72     ASSERT(m_clientClosePendingDatabaseConnections.isEmpty());
73     ASSERT(m_serverClosePendingDatabaseConnections.isEmpty());
74     ASSERT(!m_queuedTaskCount);
75 }
76
77 const IDBDatabaseInfo& UniqueIDBDatabase::info() const
78 {
79     RELEASE_ASSERT(m_databaseInfo);
80     return *m_databaseInfo;
81 }
82
83 void UniqueIDBDatabase::openDatabaseConnection(IDBConnectionToClient& connection, const IDBRequestData& requestData)
84 {
85     LOG(IndexedDB, "UniqueIDBDatabase::openDatabaseConnection");
86     ASSERT(!m_hardClosedForUserDelete);
87
88     m_pendingOpenDBRequests.add(ServerOpenDBRequest::create(connection, requestData));
89
90     // An open operation is already in progress, so we can't possibly handle this one yet.
91     if (m_isOpeningBackingStore)
92         return;
93
94     handleDatabaseOperations();
95 }
96
97 bool UniqueIDBDatabase::hasAnyPendingCallbacks() const
98 {
99     return !m_errorCallbacks.isEmpty()
100         || !m_keyDataCallbacks.isEmpty()
101         || !m_getResultCallbacks.isEmpty()
102         || !m_getAllResultsCallbacks.isEmpty()
103         || !m_countCallbacks.isEmpty();
104 }
105
106 bool UniqueIDBDatabase::isVersionChangeInProgress()
107 {
108 #if !LOG_DISABLED
109     if (m_versionChangeTransaction)
110         ASSERT(m_versionChangeDatabaseConnection);
111 #endif
112
113     return m_versionChangeDatabaseConnection;
114 }
115
116 void UniqueIDBDatabase::performCurrentOpenOperation()
117 {
118     LOG(IndexedDB, "(main) UniqueIDBDatabase::performCurrentOpenOperation (%p)", this);
119
120     ASSERT(m_currentOpenDBRequest);
121     ASSERT(m_currentOpenDBRequest->isOpenRequest());
122
123     if (!m_databaseInfo) {
124         if (!m_isOpeningBackingStore) {
125             m_isOpeningBackingStore = true;
126             postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::openBackingStore, m_identifier));
127         }
128
129         return;
130     }
131
132     // If we previously started a version change operation but were blocked by having open connections,
133     // we might now be unblocked.
134     if (m_versionChangeDatabaseConnection) {
135         if (!m_versionChangeTransaction && !hasAnyOpenConnections())
136             startVersionChangeTransaction();
137         return;
138     }
139
140     // 3.3.1 Opening a database
141     // If requested version is undefined, then let requested version be 1 if db was created in the previous step,
142     // or the current version of db otherwise.
143     uint64_t requestedVersion = m_currentOpenDBRequest->requestData().requestedVersion();
144     if (!requestedVersion)
145         requestedVersion = m_databaseInfo->version() ? m_databaseInfo->version() : 1;
146
147     // 3.3.1 Opening a database
148     // If the database version higher than the requested version, abort these steps and return a VersionError.
149     if (requestedVersion < m_databaseInfo->version()) {
150         auto result = IDBResultData::error(m_currentOpenDBRequest->requestData().requestIdentifier(), IDBError(IDBDatabaseException::VersionError));
151         m_currentOpenDBRequest->connection().didOpenDatabase(result);
152         m_currentOpenDBRequest = nullptr;
153
154         return;
155     }
156
157     if (!m_backingStoreOpenError.isNull()) {
158         auto result = IDBResultData::error(m_currentOpenDBRequest->requestData().requestIdentifier(), m_backingStoreOpenError);
159         m_currentOpenDBRequest->connection().didOpenDatabase(result);
160         m_currentOpenDBRequest = nullptr;
161
162         return;
163     }
164
165     Ref<UniqueIDBDatabaseConnection> connection = UniqueIDBDatabaseConnection::create(*this, *m_currentOpenDBRequest);
166
167     if (requestedVersion == m_databaseInfo->version()) {
168         auto* rawConnection = &connection.get();
169         addOpenDatabaseConnection(WTFMove(connection));
170
171         auto result = IDBResultData::openDatabaseSuccess(m_currentOpenDBRequest->requestData().requestIdentifier(), *rawConnection);
172         m_currentOpenDBRequest->connection().didOpenDatabase(result);
173         m_currentOpenDBRequest = nullptr;
174
175         return;
176     }
177
178     ASSERT(!m_versionChangeDatabaseConnection);
179     m_versionChangeDatabaseConnection = WTFMove(connection);
180
181     // 3.3.7 "versionchange" transaction steps
182     // If there's no other open connections to this database, the version change process can begin immediately.
183     if (!hasAnyOpenConnections()) {
184         startVersionChangeTransaction();
185         return;
186     }
187
188     // Otherwise we have to notify all those open connections and wait for them to close.
189     maybeNotifyConnectionsOfVersionChange();
190 }
191
192 void UniqueIDBDatabase::performCurrentDeleteOperation()
193 {
194     ASSERT(isMainThread());
195     LOG(IndexedDB, "(main) UniqueIDBDatabase::performCurrentDeleteOperation - %s", m_identifier.debugString().utf8().data());
196
197     ASSERT(m_currentOpenDBRequest);
198     ASSERT(m_currentOpenDBRequest->isDeleteRequest());
199
200     if (m_deleteBackingStoreInProgress)
201         return;
202
203     if (hasAnyOpenConnections()) {
204         maybeNotifyConnectionsOfVersionChange();
205         return;
206     }
207
208     if (hasUnfinishedTransactions())
209         return;
210
211     ASSERT(!hasAnyPendingCallbacks());
212     ASSERT(m_pendingTransactions.isEmpty());
213     ASSERT(m_openDatabaseConnections.isEmpty());
214
215     // It's possible to have multiple delete requests queued up in a row.
216     // In that scenario only the first request will actually have to delete the database.
217     // Subsequent requests can immediately notify their completion.
218
219     if (!m_deleteBackingStoreInProgress) {
220         if (!m_databaseInfo && m_mostRecentDeletedDatabaseInfo)
221             didDeleteBackingStore(0);
222         else {
223             m_deleteBackingStoreInProgress = true;
224             postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::deleteBackingStore, m_identifier));
225         }
226     }
227 }
228
229 void UniqueIDBDatabase::deleteBackingStore(const IDBDatabaseIdentifier& identifier)
230 {
231     ASSERT(!isMainThread());
232     LOG(IndexedDB, "(db) UniqueIDBDatabase::deleteBackingStore");
233
234     uint64_t deletedVersion = 0;
235
236     if (m_backingStore) {
237         m_backingStore->deleteBackingStore();
238         m_backingStore = nullptr;
239         m_backingStoreSupportsSimultaneousTransactions = false;
240         m_backingStoreIsEphemeral = false;
241     } else {
242         auto backingStore = m_server.createBackingStore(identifier);
243
244         IDBDatabaseInfo databaseInfo;
245         auto error = backingStore->getOrEstablishDatabaseInfo(databaseInfo);
246         if (!error.isNull())
247             LOG_ERROR("Error getting database info from database %s that we are trying to delete", identifier.debugString().utf8().data());
248
249         deletedVersion = databaseInfo.version();
250         backingStore->deleteBackingStore();
251     }
252
253     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didDeleteBackingStore, deletedVersion));
254 }
255
256 void UniqueIDBDatabase::performUnconditionalDeleteBackingStore()
257 {
258     ASSERT(!isMainThread());
259     LOG(IndexedDB, "(db) UniqueIDBDatabase::performUnconditionalDeleteBackingStore");
260
261     if (!m_backingStore)
262         return;
263
264     m_backingStore->deleteBackingStore();
265     m_backingStore = nullptr;
266     m_backingStoreSupportsSimultaneousTransactions = false;
267     m_backingStoreIsEphemeral = false;
268 }
269
270 void UniqueIDBDatabase::didDeleteBackingStore(uint64_t deletedVersion)
271 {
272     ASSERT(isMainThread());
273     LOG(IndexedDB, "(main) UniqueIDBDatabase::didDeleteBackingStore");
274
275     ASSERT(!hasAnyPendingCallbacks());
276     ASSERT(!hasUnfinishedTransactions());
277     ASSERT(m_pendingTransactions.isEmpty());
278     ASSERT(m_openDatabaseConnections.isEmpty());
279
280     // It's possible that the openDBRequest was cancelled from client-side after the delete was already dispatched to the backingstore.
281     // So it's okay if we don't have a currentOpenDBRequest, but if we do it has to be a deleteRequest.
282     ASSERT(!m_currentOpenDBRequest || m_currentOpenDBRequest->isDeleteRequest());
283
284     if (m_databaseInfo)
285         m_mostRecentDeletedDatabaseInfo = WTFMove(m_databaseInfo);
286
287     // If this UniqueIDBDatabase was brought into existence for the purpose of deleting the file on disk,
288     // we won't have a m_mostRecentDeletedDatabaseInfo. In that case, we'll manufacture one using the
289     // passed in deletedVersion argument.
290     if (!m_mostRecentDeletedDatabaseInfo)
291         m_mostRecentDeletedDatabaseInfo = std::make_unique<IDBDatabaseInfo>(m_identifier.databaseName(), deletedVersion);
292
293     if (m_currentOpenDBRequest) {
294         m_currentOpenDBRequest->notifyDidDeleteDatabase(*m_mostRecentDeletedDatabaseInfo);
295         m_currentOpenDBRequest = nullptr;
296     }
297
298     m_deleteBackingStoreInProgress = false;
299
300     if (m_clientClosePendingDatabaseConnections.isEmpty() && m_pendingOpenDBRequests.isEmpty()) {
301         m_server.closeUniqueIDBDatabase(*this);
302         return;
303     }
304
305     invokeOperationAndTransactionTimer();
306 }
307
308 void UniqueIDBDatabase::didPerformUnconditionalDeleteBackingStore()
309 {
310     // This function is a placeholder so the database thread can message back to the main thread.
311     ASSERT(m_hardClosedForUserDelete);
312 }
313
314 void UniqueIDBDatabase::handleDatabaseOperations()
315 {
316     ASSERT(isMainThread());
317     LOG(IndexedDB, "(main) UniqueIDBDatabase::handleDatabaseOperations - There are %u pending", m_pendingOpenDBRequests.size());
318     ASSERT(!m_hardClosedForUserDelete);
319
320     if (m_deleteBackingStoreInProgress)
321         return;
322
323     if (m_versionChangeDatabaseConnection || m_versionChangeTransaction || m_currentOpenDBRequest) {
324         // We can't start any new open-database operations right now, but we might be able to start handling a delete operation.
325         if (!m_currentOpenDBRequest && !m_pendingOpenDBRequests.isEmpty() && m_pendingOpenDBRequests.first()->isDeleteRequest())
326             m_currentOpenDBRequest = m_pendingOpenDBRequests.takeFirst();
327
328         // Some operations (such as the first open operation after a delete) require multiple passes to completely handle
329         if (m_currentOpenDBRequest)
330             handleCurrentOperation();
331
332         return;
333     }
334
335     if (m_pendingOpenDBRequests.isEmpty())
336         return;
337
338     m_currentOpenDBRequest = m_pendingOpenDBRequests.takeFirst();
339     LOG(IndexedDB, "UniqueIDBDatabase::handleDatabaseOperations - Popped an operation, now there are %u pending", m_pendingOpenDBRequests.size());
340
341     handleCurrentOperation();
342 }
343
344 void UniqueIDBDatabase::handleCurrentOperation()
345 {
346     LOG(IndexedDB, "(main) UniqueIDBDatabase::handleCurrentOperation");
347     ASSERT(!m_hardClosedForUserDelete);
348     ASSERT(m_currentOpenDBRequest);
349
350     RefPtr<UniqueIDBDatabase> protectedThis(this);
351
352     if (m_currentOpenDBRequest->isOpenRequest())
353         performCurrentOpenOperation();
354     else if (m_currentOpenDBRequest->isDeleteRequest())
355         performCurrentDeleteOperation();
356     else
357         ASSERT_NOT_REACHED();
358
359     if (!m_currentOpenDBRequest)
360         invokeOperationAndTransactionTimer();
361 }
362
363 bool UniqueIDBDatabase::hasAnyOpenConnections() const
364 {
365     return !m_openDatabaseConnections.isEmpty();
366 }
367
368 static uint64_t generateUniqueCallbackIdentifier()
369 {
370     ASSERT(isMainThread());
371     static uint64_t currentID = 0;
372     return ++currentID;
373 }
374
375 uint64_t UniqueIDBDatabase::storeCallbackOrFireError(ErrorCallback callback)
376 {
377     if (m_hardClosedForUserDelete) {
378         callback(IDBError::userDeleteError());
379         return 0;
380     }
381
382     uint64_t identifier = generateUniqueCallbackIdentifier();
383     ASSERT(!m_errorCallbacks.contains(identifier));
384     m_errorCallbacks.add(identifier, callback);
385     return identifier;
386 }
387
388 uint64_t UniqueIDBDatabase::storeCallbackOrFireError(KeyDataCallback callback)
389 {
390     if (m_hardClosedForUserDelete) {
391         callback(IDBError::userDeleteError(), { });
392         return 0;
393     }
394
395     uint64_t identifier = generateUniqueCallbackIdentifier();
396     ASSERT(!m_keyDataCallbacks.contains(identifier));
397     m_keyDataCallbacks.add(identifier, callback);
398     return identifier;
399 }
400
401 uint64_t UniqueIDBDatabase::storeCallbackOrFireError(GetResultCallback callback)
402 {
403     if (m_hardClosedForUserDelete) {
404         callback(IDBError::userDeleteError(), { });
405         return 0;
406     }
407
408     uint64_t identifier = generateUniqueCallbackIdentifier();
409     ASSERT(!m_getResultCallbacks.contains(identifier));
410     m_getResultCallbacks.add(identifier, callback);
411     return identifier;
412 }
413
414 uint64_t UniqueIDBDatabase::storeCallbackOrFireError(GetAllResultsCallback callback)
415 {
416     if (m_hardClosedForUserDelete) {
417         callback(IDBError::userDeleteError(), { });
418         return 0;
419     }
420
421     uint64_t identifier = generateUniqueCallbackIdentifier();
422     ASSERT(!m_getAllResultsCallbacks.contains(identifier));
423     m_getAllResultsCallbacks.add(identifier, callback);
424     return identifier;
425 }
426
427 uint64_t UniqueIDBDatabase::storeCallbackOrFireError(CountCallback callback)
428 {
429     if (m_hardClosedForUserDelete) {
430         callback(IDBError::userDeleteError(), 0);
431         return 0;
432     }
433
434     uint64_t identifier = generateUniqueCallbackIdentifier();
435     ASSERT(!m_countCallbacks.contains(identifier));
436     m_countCallbacks.add(identifier, callback);
437     return identifier;
438 }
439
440 void UniqueIDBDatabase::handleDelete(IDBConnectionToClient& connection, const IDBRequestData& requestData)
441 {
442     LOG(IndexedDB, "(main) UniqueIDBDatabase::handleDelete");
443     ASSERT(!m_hardClosedForUserDelete);
444
445     m_pendingOpenDBRequests.add(ServerOpenDBRequest::create(connection, requestData));
446     handleDatabaseOperations();
447 }
448
449 void UniqueIDBDatabase::startVersionChangeTransaction()
450 {
451     LOG(IndexedDB, "(main) UniqueIDBDatabase::startVersionChangeTransaction");
452
453     ASSERT(!m_versionChangeTransaction);
454     ASSERT(m_currentOpenDBRequest);
455     ASSERT(m_currentOpenDBRequest->isOpenRequest());
456     ASSERT(m_versionChangeDatabaseConnection);
457
458     auto operation = WTFMove(m_currentOpenDBRequest);
459
460     uint64_t requestedVersion = operation->requestData().requestedVersion();
461     if (!requestedVersion)
462         requestedVersion = m_databaseInfo->version() ? m_databaseInfo->version() : 1;
463
464     addOpenDatabaseConnection(*m_versionChangeDatabaseConnection);
465
466     m_versionChangeTransaction = &m_versionChangeDatabaseConnection->createVersionChangeTransaction(requestedVersion);
467     m_databaseInfo->setVersion(requestedVersion);
468
469     m_inProgressTransactions.set(m_versionChangeTransaction->info().identifier(), m_versionChangeTransaction);
470     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::beginTransactionInBackingStore, m_versionChangeTransaction->info()));
471
472     auto result = IDBResultData::openDatabaseUpgradeNeeded(operation->requestData().requestIdentifier(), *m_versionChangeTransaction);
473     operation->connection().didOpenDatabase(result);
474 }
475
476 void UniqueIDBDatabase::beginTransactionInBackingStore(const IDBTransactionInfo& info)
477 {
478     LOG(IndexedDB, "(db) UniqueIDBDatabase::beginTransactionInBackingStore");
479     m_backingStore->beginTransaction(info);
480 }
481
482 void UniqueIDBDatabase::maybeNotifyConnectionsOfVersionChange()
483 {
484     ASSERT(m_currentOpenDBRequest);
485
486     if (m_currentOpenDBRequest->hasNotifiedConnectionsOfVersionChange())
487         return;
488
489     uint64_t newVersion = m_currentOpenDBRequest->isOpenRequest() ? m_currentOpenDBRequest->requestData().requestedVersion() : 0;
490     auto requestIdentifier = m_currentOpenDBRequest->requestData().requestIdentifier();
491
492     LOG(IndexedDB, "(main) UniqueIDBDatabase::notifyConnectionsOfVersionChange - %" PRIu64, newVersion);
493
494     // 3.3.7 "versionchange" transaction steps
495     // Fire a versionchange event at each connection in m_openDatabaseConnections that is open.
496     // The event must not be fired on connections which has the closePending flag set.
497     HashSet<uint64_t> connectionIdentifiers;
498     for (auto connection : m_openDatabaseConnections) {
499         if (connection->closePending())
500             continue;
501
502         connection->fireVersionChangeEvent(requestIdentifier, newVersion);
503         connectionIdentifiers.add(connection->identifier());
504     }
505
506     m_currentOpenDBRequest->notifiedConnectionsOfVersionChange(WTFMove(connectionIdentifiers));
507 }
508
509 void UniqueIDBDatabase::notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent(uint64_t connectionIdentifier)
510 {
511     LOG(IndexedDB, "UniqueIDBDatabase::notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent - %" PRIu64, connectionIdentifier);
512
513     ASSERT(m_currentOpenDBRequest);
514
515     m_currentOpenDBRequest->connectionClosedOrFiredVersionChangeEvent(connectionIdentifier);
516
517     if (m_currentOpenDBRequest->hasConnectionsPendingVersionChangeEvent())
518         return;
519
520     if (!hasAnyOpenConnections()) {
521         invokeOperationAndTransactionTimer();
522         return;
523     }
524
525     if (m_currentOpenDBRequest->hasNotifiedBlocked())
526         return;
527
528     // Since all open connections have fired their version change events but not all of them have closed,
529     // this request is officially blocked.
530     m_currentOpenDBRequest->notifyRequestBlocked(m_databaseInfo->version());
531 }
532
533 void UniqueIDBDatabase::didFireVersionChangeEvent(UniqueIDBDatabaseConnection& connection, const IDBResourceIdentifier& requestIdentifier)
534 {
535     LOG(IndexedDB, "UniqueIDBDatabase::didFireVersionChangeEvent");
536
537     if (!m_currentOpenDBRequest)
538         return;
539
540     ASSERT_UNUSED(requestIdentifier, m_currentOpenDBRequest->requestData().requestIdentifier() == requestIdentifier);
541
542     notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent(connection.identifier());
543 }
544
545 void UniqueIDBDatabase::openDBRequestCancelled(const IDBResourceIdentifier& requestIdentifier)
546 {
547     LOG(IndexedDB, "UniqueIDBDatabase::openDBRequestCancelled - %s", requestIdentifier.loggingString().utf8().data());
548
549     if (m_currentOpenDBRequest && m_currentOpenDBRequest->requestData().requestIdentifier() == requestIdentifier)
550         m_currentOpenDBRequest = nullptr;
551
552     if (m_versionChangeDatabaseConnection && m_versionChangeDatabaseConnection->openRequestIdentifier() == requestIdentifier) {
553         ASSERT(!m_versionChangeTransaction || m_versionChangeTransaction->databaseConnection().openRequestIdentifier() == requestIdentifier);
554         ASSERT(!m_versionChangeTransaction || &m_versionChangeTransaction->databaseConnection() == m_versionChangeDatabaseConnection);
555
556         connectionClosedFromClient(*m_versionChangeDatabaseConnection);
557     }
558
559     for (auto& request : m_pendingOpenDBRequests) {
560         if (request->requestData().requestIdentifier() == requestIdentifier) {
561             m_pendingOpenDBRequests.remove(request);
562             return;
563         }
564     }
565 }
566
567 void UniqueIDBDatabase::addOpenDatabaseConnection(Ref<UniqueIDBDatabaseConnection>&& connection)
568 {
569     ASSERT(!m_openDatabaseConnections.contains(&connection.get()));
570     m_openDatabaseConnections.add(adoptRef(connection.leakRef()));
571 }
572
573 void UniqueIDBDatabase::openBackingStore(const IDBDatabaseIdentifier& identifier)
574 {
575     ASSERT(!isMainThread());
576     LOG(IndexedDB, "(db) UniqueIDBDatabase::openBackingStore (%p)", this);
577
578     ASSERT(!m_backingStore);
579     m_backingStore = m_server.createBackingStore(identifier);
580     m_backingStoreSupportsSimultaneousTransactions = m_backingStore->supportsSimultaneousTransactions();
581     m_backingStoreIsEphemeral = m_backingStore->isEphemeral();
582
583     IDBDatabaseInfo databaseInfo;
584     auto error = m_backingStore->getOrEstablishDatabaseInfo(databaseInfo);
585
586     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didOpenBackingStore, databaseInfo, error));
587 }
588
589 void UniqueIDBDatabase::didOpenBackingStore(const IDBDatabaseInfo& info, const IDBError& error)
590 {
591     ASSERT(isMainThread());
592     LOG(IndexedDB, "(main) UniqueIDBDatabase::didOpenBackingStore");
593     
594     m_databaseInfo = std::make_unique<IDBDatabaseInfo>(info);
595     m_backingStoreOpenError = error;
596
597     ASSERT(m_isOpeningBackingStore);
598     m_isOpeningBackingStore = false;
599
600     handleDatabaseOperations();
601 }
602
603 void UniqueIDBDatabase::createObjectStore(UniqueIDBDatabaseTransaction& transaction, const IDBObjectStoreInfo& info, ErrorCallback callback)
604 {
605     ASSERT(isMainThread());
606     LOG(IndexedDB, "(main) UniqueIDBDatabase::createObjectStore");
607
608     uint64_t callbackID = storeCallbackOrFireError(callback);
609     if (!callbackID)
610         return;
611
612     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateObjectStore, callbackID, transaction.info().identifier(), info));
613 }
614
615 void UniqueIDBDatabase::performCreateObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& info)
616 {
617     ASSERT(!isMainThread());
618     LOG(IndexedDB, "(db) UniqueIDBDatabase::performCreateObjectStore");
619
620     ASSERT(m_backingStore);
621     m_backingStore->createObjectStore(transactionIdentifier, info);
622
623     IDBError error;
624     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateObjectStore, callbackIdentifier, error, info));
625 }
626
627 void UniqueIDBDatabase::didPerformCreateObjectStore(uint64_t callbackIdentifier, const IDBError& error, const IDBObjectStoreInfo& info)
628 {
629     ASSERT(isMainThread());
630     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCreateObjectStore");
631
632     if (error.isNull())
633         m_databaseInfo->addExistingObjectStore(info);
634
635     performErrorCallback(callbackIdentifier, error);
636 }
637
638 void UniqueIDBDatabase::deleteObjectStore(UniqueIDBDatabaseTransaction& transaction, const String& objectStoreName, ErrorCallback callback)
639 {
640     ASSERT(isMainThread());
641     LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteObjectStore");
642
643     uint64_t callbackID = storeCallbackOrFireError(callback);
644     if (!callbackID)
645         return;
646
647     auto* info = m_databaseInfo->infoForExistingObjectStore(objectStoreName);
648     if (!info) {
649         performErrorCallback(callbackID, { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to delete non-existant object store") });
650         return;
651     }
652
653     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performDeleteObjectStore, callbackID, transaction.info().identifier(), info->identifier()));
654 }
655
656 void UniqueIDBDatabase::performDeleteObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier)
657 {
658     ASSERT(!isMainThread());
659     LOG(IndexedDB, "(db) UniqueIDBDatabase::performDeleteObjectStore");
660
661     ASSERT(m_backingStore);
662     m_backingStore->deleteObjectStore(transactionIdentifier, objectStoreIdentifier);
663
664     IDBError error;
665     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformDeleteObjectStore, callbackIdentifier, error, objectStoreIdentifier));
666 }
667
668 void UniqueIDBDatabase::didPerformDeleteObjectStore(uint64_t callbackIdentifier, const IDBError& error, uint64_t objectStoreIdentifier)
669 {
670     ASSERT(isMainThread());
671     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformDeleteObjectStore");
672
673     if (error.isNull())
674         m_databaseInfo->deleteObjectStore(objectStoreIdentifier);
675
676     performErrorCallback(callbackIdentifier, error);
677 }
678
679 void UniqueIDBDatabase::renameObjectStore(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, const String& newName, ErrorCallback callback)
680 {
681     ASSERT(isMainThread());
682     LOG(IndexedDB, "(main) UniqueIDBDatabase::renameObjectStore");
683
684     uint64_t callbackID = storeCallbackOrFireError(callback);
685     if (!callbackID)
686         return;
687
688     auto* info = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
689     if (!info) {
690         performErrorCallback(callbackID, { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to rename non-existant object store") });
691         return;
692     }
693
694     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performRenameObjectStore, callbackID, transaction.info().identifier(), objectStoreIdentifier, newName));
695 }
696
697 void UniqueIDBDatabase::performRenameObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const String& newName)
698 {
699     ASSERT(!isMainThread());
700     LOG(IndexedDB, "(db) UniqueIDBDatabase::performRenameObjectStore");
701
702     ASSERT(m_backingStore);
703     m_backingStore->renameObjectStore(transactionIdentifier, objectStoreIdentifier, newName);
704
705     IDBError error;
706     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformRenameObjectStore, callbackIdentifier, error, objectStoreIdentifier, newName));
707 }
708
709 void UniqueIDBDatabase::didPerformRenameObjectStore(uint64_t callbackIdentifier, const IDBError& error, uint64_t objectStoreIdentifier, const String& newName)
710 {
711     ASSERT(isMainThread());
712     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformRenameObjectStore");
713
714     if (error.isNull())
715         m_databaseInfo->renameObjectStore(objectStoreIdentifier, newName);
716
717     performErrorCallback(callbackIdentifier, error);
718 }
719
720 void UniqueIDBDatabase::clearObjectStore(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, ErrorCallback callback)
721 {
722     ASSERT(isMainThread());
723     LOG(IndexedDB, "(main) UniqueIDBDatabase::clearObjectStore");
724
725     uint64_t callbackID = storeCallbackOrFireError(callback);
726     if (!callbackID)
727         return;
728     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performClearObjectStore, callbackID, transaction.info().identifier(), objectStoreIdentifier));
729 }
730
731 void UniqueIDBDatabase::performClearObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier)
732 {
733     ASSERT(!isMainThread());
734     LOG(IndexedDB, "(db) UniqueIDBDatabase::performClearObjectStore");
735
736     ASSERT(m_backingStore);
737     m_backingStore->clearObjectStore(transactionIdentifier, objectStoreIdentifier);
738
739     IDBError error;
740     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformClearObjectStore, callbackIdentifier, error));
741 }
742
743 void UniqueIDBDatabase::didPerformClearObjectStore(uint64_t callbackIdentifier, const IDBError& error)
744 {
745     ASSERT(isMainThread());
746     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformClearObjectStore");
747
748     performErrorCallback(callbackIdentifier, error);
749 }
750
751 void UniqueIDBDatabase::createIndex(UniqueIDBDatabaseTransaction& transaction, const IDBIndexInfo& info, ErrorCallback callback)
752 {
753     ASSERT(isMainThread());
754     LOG(IndexedDB, "(main) UniqueIDBDatabase::createIndex");
755
756     uint64_t callbackID = storeCallbackOrFireError(callback);
757     if (!callbackID)
758         return;
759     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateIndex, callbackID, transaction.info().identifier(), info));
760 }
761
762 void UniqueIDBDatabase::performCreateIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo& info)
763 {
764     ASSERT(!isMainThread());
765     LOG(IndexedDB, "(db) UniqueIDBDatabase::performCreateIndex");
766
767     ASSERT(m_backingStore);
768     IDBError error = m_backingStore->createIndex(transactionIdentifier, info);
769
770     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateIndex, callbackIdentifier, error, info));
771 }
772
773 void UniqueIDBDatabase::didPerformCreateIndex(uint64_t callbackIdentifier, const IDBError& error, const IDBIndexInfo& info)
774 {
775     ASSERT(isMainThread());
776     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCreateIndex");
777
778     if (error.isNull()) {
779         ASSERT(m_databaseInfo);
780         auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(info.objectStoreIdentifier());
781         ASSERT(objectStoreInfo);
782         objectStoreInfo->addExistingIndex(info);
783     }
784
785     performErrorCallback(callbackIdentifier, error);
786 }
787
788 void UniqueIDBDatabase::deleteIndex(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, const String& indexName, ErrorCallback callback)
789 {
790     ASSERT(isMainThread());
791     LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteIndex");
792
793     uint64_t callbackID = storeCallbackOrFireError(callback);
794     if (!callbackID)
795         return;
796
797     auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
798     if (!objectStoreInfo) {
799         performErrorCallback(callbackID, { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to delete index from non-existant object store") });
800         return;
801     }
802
803     auto* indexInfo = objectStoreInfo->infoForExistingIndex(indexName);
804     if (!indexInfo) {
805         performErrorCallback(callbackID, { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to delete non-existant index") });
806         return;
807     }
808
809     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performDeleteIndex, callbackID, transaction.info().identifier(), objectStoreIdentifier, indexInfo->identifier()));
810 }
811
812 void UniqueIDBDatabase::performDeleteIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const uint64_t indexIdentifier)
813 {
814     ASSERT(!isMainThread());
815     LOG(IndexedDB, "(db) UniqueIDBDatabase::performDeleteIndex");
816
817     ASSERT(m_backingStore);
818     m_backingStore->deleteIndex(transactionIdentifier, objectStoreIdentifier, indexIdentifier);
819
820     IDBError error;
821     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformDeleteIndex, callbackIdentifier, error, objectStoreIdentifier, indexIdentifier));
822 }
823
824 void UniqueIDBDatabase::didPerformDeleteIndex(uint64_t callbackIdentifier, const IDBError& error, uint64_t objectStoreIdentifier, uint64_t indexIdentifier)
825 {
826     ASSERT(isMainThread());
827     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformDeleteIndex");
828
829     if (error.isNull()) {
830         auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
831         if (objectStoreInfo)
832             objectStoreInfo->deleteIndex(indexIdentifier);
833     }
834
835     performErrorCallback(callbackIdentifier, error);
836 }
837
838 void UniqueIDBDatabase::renameIndex(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, ErrorCallback callback)
839 {
840     ASSERT(isMainThread());
841     LOG(IndexedDB, "(main) UniqueIDBDatabase::renameIndex");
842
843     uint64_t callbackID = storeCallbackOrFireError(callback);
844     if (!callbackID)
845         return;
846
847     auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
848     if (!objectStoreInfo) {
849         performErrorCallback(callbackID, { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to rename index in non-existant object store") });
850         return;
851     }
852
853     auto* indexInfo = objectStoreInfo->infoForExistingIndex(indexIdentifier);
854     if (!indexInfo) {
855         performErrorCallback(callbackID, { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to rename non-existant index") });
856         return;
857     }
858
859     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performRenameIndex, callbackID, transaction.info().identifier(), objectStoreIdentifier, indexIdentifier, newName));
860 }
861
862 void UniqueIDBDatabase::performRenameIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName)
863 {
864     ASSERT(!isMainThread());
865     LOG(IndexedDB, "(db) UniqueIDBDatabase::performRenameIndex");
866
867     ASSERT(m_backingStore);
868     m_backingStore->renameIndex(transactionIdentifier, objectStoreIdentifier, indexIdentifier, newName);
869
870     IDBError error;
871     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformRenameIndex, callbackIdentifier, error, objectStoreIdentifier, indexIdentifier, newName));
872 }
873
874 void UniqueIDBDatabase::didPerformRenameIndex(uint64_t callbackIdentifier, const IDBError& error, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName)
875 {
876     ASSERT(isMainThread());
877     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformRenameIndex");
878
879     if (error.isNull()) {
880         auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
881         ASSERT(objectStoreInfo);
882         if (objectStoreInfo) {
883             auto* indexInfo = objectStoreInfo->infoForExistingIndex(indexIdentifier);
884             ASSERT(indexInfo);
885             indexInfo->rename(newName);
886         }
887     }
888
889     performErrorCallback(callbackIdentifier, error);
890 }
891
892 void UniqueIDBDatabase::putOrAdd(const IDBRequestData& requestData, const IDBKeyData& keyData, const IDBValue& value, IndexedDB::ObjectStoreOverwriteMode overwriteMode, KeyDataCallback callback)
893 {
894     ASSERT(isMainThread());
895     LOG(IndexedDB, "(main) UniqueIDBDatabase::putOrAdd");
896
897     uint64_t callbackID = storeCallbackOrFireError(callback);
898     if (!callbackID)
899         return;
900     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performPutOrAdd, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyData, value, overwriteMode));
901 }
902
903 VM& UniqueIDBDatabase::databaseThreadVM()
904 {
905     ASSERT(!isMainThread());
906     static VM* vm = &VM::create().leakRef();
907     return *vm;
908 }
909
910 ExecState& UniqueIDBDatabase::databaseThreadExecState()
911 {
912     ASSERT(!isMainThread());
913
914     static NeverDestroyed<Strong<JSGlobalObject>> globalObject(databaseThreadVM(), JSGlobalObject::create(databaseThreadVM(), JSGlobalObject::createStructure(databaseThreadVM(), jsNull())));
915
916     RELEASE_ASSERT(globalObject.get()->globalExec());
917     return *globalObject.get()->globalExec();
918 }
919
920 void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, const IDBValue& originalRecordValue, IndexedDB::ObjectStoreOverwriteMode overwriteMode)
921 {
922     ASSERT(!isMainThread());
923     LOG(IndexedDB, "(db) UniqueIDBDatabase::performPutOrAdd");
924
925     ASSERT(m_backingStore);
926     ASSERT(objectStoreIdentifier);
927
928     IDBKeyData usedKey;
929     IDBError error;
930
931     auto* objectStoreInfo = m_backingStore->infoForObjectStore(objectStoreIdentifier);
932     if (!objectStoreInfo) {
933         error = IDBError(IDBDatabaseException::InvalidStateError, ASCIILiteral("Object store cannot be found in the backing store"));
934         postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
935         return;
936     }
937
938     bool usedKeyIsGenerated = false;
939     ScopeGuard generatedKeyResetter;
940     if (objectStoreInfo->autoIncrement() && !keyData.isValid()) {
941         uint64_t keyNumber;
942         error = m_backingStore->generateKeyNumber(transactionIdentifier, objectStoreIdentifier, keyNumber);
943         if (!error.isNull()) {
944             postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
945             return;
946         }
947         
948         usedKey.setNumberValue(keyNumber);
949         usedKeyIsGenerated = true;
950         generatedKeyResetter.enable([this, transactionIdentifier, objectStoreIdentifier, keyNumber]() {
951             m_backingStore->revertGeneratedKeyNumber(transactionIdentifier, objectStoreIdentifier, keyNumber);
952         });
953     } else
954         usedKey = keyData;
955
956     if (overwriteMode == IndexedDB::ObjectStoreOverwriteMode::NoOverwrite) {
957         bool keyExists;
958         error = m_backingStore->keyExistsInObjectStore(transactionIdentifier, objectStoreIdentifier, usedKey, keyExists);
959         if (error.isNull() && keyExists)
960             error = IDBError(IDBDatabaseException::ConstraintError, ASCIILiteral("Key already exists in the object store"));
961
962         if (!error.isNull()) {
963             postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
964             return;
965         }
966     }
967
968     // 3.4.1.2 Object Store Storage Operation
969     // If ObjectStore has a key path and the key is autogenerated, then inject the key into the value
970     // using steps to assign a key to a value using a key path.
971     ThreadSafeDataBuffer injectedRecordValue;
972     if (usedKeyIsGenerated && objectStoreInfo->keyPath()) {
973         VM& vm = databaseThreadVM();
974         JSLockHolder locker(vm);
975         auto scope = DECLARE_THROW_SCOPE(vm);
976
977         auto value = deserializeIDBValueToJSValue(databaseThreadExecState(), originalRecordValue.data());
978         if (value.isUndefined()) {
979             postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(IDBDatabaseException::ConstraintError, ASCIILiteral("Unable to deserialize record value for record key injection")), usedKey));
980             return;
981         }
982
983         if (!injectIDBKeyIntoScriptValue(databaseThreadExecState(), usedKey, value, objectStoreInfo->keyPath().value())) {
984             postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(IDBDatabaseException::ConstraintError, ASCIILiteral("Unable to inject record key into record value")), usedKey));
985             return;
986         }
987
988         auto serializedValue = SerializedScriptValue::create(databaseThreadExecState(), value);
989         if (UNLIKELY(scope.exception())) {
990             postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(IDBDatabaseException::ConstraintError, ASCIILiteral("Unable to serialize record value after injecting record key")), usedKey));
991             return;
992         }
993
994         injectedRecordValue = ThreadSafeDataBuffer::copyVector(serializedValue->data());
995     }
996
997     // 3.4.1 Object Store Storage Operation
998     // ...If a record already exists in store ...
999     // then remove the record from store using the steps for deleting records from an object store...
1000     // This is important because formally deleting it from from the object store also removes it from the appropriate indexes.
1001     error = m_backingStore->deleteRange(transactionIdentifier, objectStoreIdentifier, usedKey);
1002     if (!error.isNull()) {
1003         postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
1004         return;
1005     }
1006
1007     if (injectedRecordValue.data())
1008         error = m_backingStore->addRecord(transactionIdentifier, *objectStoreInfo, usedKey, { injectedRecordValue, originalRecordValue.blobURLs(), originalRecordValue.blobFilePaths() });
1009     else
1010         error = m_backingStore->addRecord(transactionIdentifier, *objectStoreInfo, usedKey, originalRecordValue);
1011
1012     if (!error.isNull()) {
1013         postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
1014         return;
1015     }
1016
1017     if (overwriteMode != IndexedDB::ObjectStoreOverwriteMode::OverwriteForCursor && objectStoreInfo->autoIncrement() && keyData.type() == IndexedDB::KeyType::Number)
1018         error = m_backingStore->maybeUpdateKeyGeneratorNumber(transactionIdentifier, objectStoreIdentifier, keyData.number());
1019
1020     generatedKeyResetter.disable();
1021     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
1022 }
1023
1024 void UniqueIDBDatabase::didPerformPutOrAdd(uint64_t callbackIdentifier, const IDBError& error, const IDBKeyData& resultKey)
1025 {
1026     ASSERT(isMainThread());
1027     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformPutOrAdd");
1028
1029     performKeyDataCallback(callbackIdentifier, error, resultKey);
1030 }
1031
1032 void UniqueIDBDatabase::getRecord(const IDBRequestData& requestData, const IDBGetRecordData& getRecordData, GetResultCallback callback)
1033 {
1034     ASSERT(isMainThread());
1035     LOG(IndexedDB, "(main) UniqueIDBDatabase::getRecord");
1036
1037     uint64_t callbackID = storeCallbackOrFireError(callback);
1038     if (!callbackID)
1039         return;
1040
1041     if (uint64_t indexIdentifier = requestData.indexIdentifier())
1042         postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetIndexRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), indexIdentifier, requestData.indexRecordType(), getRecordData.keyRangeData));
1043     else
1044         postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), getRecordData.keyRangeData));
1045 }
1046
1047 void UniqueIDBDatabase::getAllRecords(const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData, GetAllResultsCallback callback)
1048 {
1049     ASSERT(isMainThread());
1050     LOG(IndexedDB, "(main) UniqueIDBDatabase::getAllRecords");
1051
1052     uint64_t callbackID = storeCallbackOrFireError(callback);
1053     if (!callbackID)
1054         return;
1055
1056     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetAllRecords, callbackID, requestData.transactionIdentifier(), getAllRecordsData));
1057 }
1058
1059 void UniqueIDBDatabase::performGetRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& keyRangeData)
1060 {
1061     ASSERT(!isMainThread());
1062     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetRecord");
1063
1064     ASSERT(m_backingStore);
1065
1066     IDBGetResult result;
1067     IDBError error = m_backingStore->getRecord(transactionIdentifier, objectStoreIdentifier, keyRangeData, result);
1068
1069     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetRecord, callbackIdentifier, error, result));
1070 }
1071
1072 void UniqueIDBDatabase::performGetIndexRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType recordType, const IDBKeyRangeData& range)
1073 {
1074     ASSERT(!isMainThread());
1075     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetIndexRecord");
1076
1077     ASSERT(m_backingStore);
1078
1079     IDBGetResult result;
1080     IDBError error = m_backingStore->getIndexRecord(transactionIdentifier, objectStoreIdentifier, indexIdentifier, recordType, range, result);
1081
1082     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetRecord, callbackIdentifier, error, result));
1083 }
1084
1085 void UniqueIDBDatabase::didPerformGetRecord(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& result)
1086 {
1087     ASSERT(isMainThread());
1088     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformGetRecord");
1089
1090     performGetResultCallback(callbackIdentifier, error, result);
1091 }
1092
1093 void UniqueIDBDatabase::performGetAllRecords(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData& getAllRecordsData)
1094 {
1095     ASSERT(!isMainThread());
1096     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetAllRecords");
1097
1098     ASSERT(m_backingStore);
1099
1100     IDBGetAllResult result;
1101     IDBError error = m_backingStore->getAllRecords(transactionIdentifier, getAllRecordsData, result);
1102
1103     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetAllRecords, callbackIdentifier, error, WTFMove(result)));
1104 }
1105
1106 void UniqueIDBDatabase::didPerformGetAllRecords(uint64_t callbackIdentifier, const IDBError& error, const IDBGetAllResult& result)
1107 {
1108     ASSERT(isMainThread());
1109     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformGetAllRecords");
1110
1111     performGetAllResultsCallback(callbackIdentifier, error, result);
1112 }
1113
1114 void UniqueIDBDatabase::getCount(const IDBRequestData& requestData, const IDBKeyRangeData& range, CountCallback callback)
1115 {
1116     ASSERT(isMainThread());
1117     LOG(IndexedDB, "(main) UniqueIDBDatabase::getCount");
1118
1119     uint64_t callbackID = storeCallbackOrFireError(callback);
1120     if (!callbackID)
1121         return;
1122     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetCount, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), requestData.indexIdentifier(), range));
1123 }
1124
1125 void UniqueIDBDatabase::performGetCount(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData& keyRangeData)
1126 {
1127     ASSERT(!isMainThread());
1128     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetCount");
1129
1130     ASSERT(m_backingStore);
1131     ASSERT(objectStoreIdentifier);
1132
1133     uint64_t count;
1134     IDBError error = m_backingStore->getCount(transactionIdentifier, objectStoreIdentifier, indexIdentifier, keyRangeData, count);
1135
1136     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetCount, callbackIdentifier, error, count));
1137 }
1138
1139 void UniqueIDBDatabase::didPerformGetCount(uint64_t callbackIdentifier, const IDBError& error, uint64_t count)
1140 {
1141     ASSERT(isMainThread());
1142     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformGetCount");
1143
1144     performCountCallback(callbackIdentifier, error, count);
1145 }
1146
1147 void UniqueIDBDatabase::deleteRecord(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData, ErrorCallback callback)
1148 {
1149     ASSERT(isMainThread());
1150     LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteRecord");
1151
1152     uint64_t callbackID = storeCallbackOrFireError(callback);
1153     if (!callbackID)
1154         return;
1155     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performDeleteRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyRangeData));
1156 }
1157
1158 void UniqueIDBDatabase::performDeleteRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range)
1159 {
1160     ASSERT(!isMainThread());
1161     LOG(IndexedDB, "(db) UniqueIDBDatabase::performDeleteRecord");
1162
1163     IDBError error = m_backingStore->deleteRange(transactionIdentifier, objectStoreIdentifier, range);
1164
1165     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformDeleteRecord, callbackIdentifier, error));
1166 }
1167
1168 void UniqueIDBDatabase::didPerformDeleteRecord(uint64_t callbackIdentifier, const IDBError& error)
1169 {
1170     ASSERT(isMainThread());
1171     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformDeleteRecord");
1172
1173     performErrorCallback(callbackIdentifier, error);
1174 }
1175
1176 void UniqueIDBDatabase::openCursor(const IDBRequestData& requestData, const IDBCursorInfo& info, GetResultCallback callback)
1177 {
1178     ASSERT(isMainThread());
1179     LOG(IndexedDB, "(main) UniqueIDBDatabase::openCursor");
1180
1181     uint64_t callbackID = storeCallbackOrFireError(callback);
1182     if (!callbackID)
1183         return;
1184     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performOpenCursor, callbackID, requestData.transactionIdentifier(), info));
1185 }
1186
1187 void UniqueIDBDatabase::performOpenCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo& info)
1188 {
1189     ASSERT(!isMainThread());
1190     LOG(IndexedDB, "(db) UniqueIDBDatabase::performOpenCursor");
1191
1192     IDBGetResult result;
1193     IDBError error = m_backingStore->openCursor(transactionIdentifier, info, result);
1194
1195     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformOpenCursor, callbackIdentifier, error, result));
1196 }
1197
1198 void UniqueIDBDatabase::didPerformOpenCursor(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& result)
1199 {
1200     ASSERT(isMainThread());
1201     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformOpenCursor");
1202
1203     performGetResultCallback(callbackIdentifier, error, result);
1204 }
1205
1206 void UniqueIDBDatabase::iterateCursor(const IDBRequestData& requestData, const IDBKeyData& key, unsigned long count, GetResultCallback callback)
1207 {
1208     ASSERT(isMainThread());
1209     LOG(IndexedDB, "(main) UniqueIDBDatabase::iterateCursor");
1210
1211     uint64_t callbackID = storeCallbackOrFireError(callback);
1212     if (!callbackID)
1213         return;
1214     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performIterateCursor, callbackID, requestData.transactionIdentifier(), requestData.cursorIdentifier(), key, count));
1215 }
1216
1217 void UniqueIDBDatabase::performIterateCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, const IDBKeyData& key, unsigned long count)
1218 {
1219     ASSERT(!isMainThread());
1220     LOG(IndexedDB, "(db) UniqueIDBDatabase::performIterateCursor");
1221
1222     IDBGetResult result;
1223     IDBError error = m_backingStore->iterateCursor(transactionIdentifier, cursorIdentifier, key, count, result);
1224
1225     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformIterateCursor, callbackIdentifier, error, result));
1226 }
1227
1228 void UniqueIDBDatabase::didPerformIterateCursor(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& result)
1229 {
1230     ASSERT(isMainThread());
1231     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformIterateCursor");
1232
1233     performGetResultCallback(callbackIdentifier, error, result);
1234 }
1235
1236 bool UniqueIDBDatabase::prepareToFinishTransaction(UniqueIDBDatabaseTransaction& transaction)
1237 {
1238     auto takenTransaction = m_inProgressTransactions.take(transaction.info().identifier());
1239     if (!takenTransaction)
1240         return false;
1241
1242     ASSERT(!m_finishingTransactions.contains(transaction.info().identifier()));
1243     m_finishingTransactions.set(transaction.info().identifier(), WTFMove(takenTransaction));
1244
1245     return true;
1246 }
1247
1248 void UniqueIDBDatabase::commitTransaction(UniqueIDBDatabaseTransaction& transaction, ErrorCallback callback)
1249 {
1250     ASSERT(isMainThread());
1251     LOG(IndexedDB, "(main) UniqueIDBDatabase::commitTransaction - %s", transaction.info().identifier().loggingString().utf8().data());
1252
1253     ASSERT(&transaction.databaseConnection().database() == this);
1254
1255     uint64_t callbackID = storeCallbackOrFireError(callback);
1256     if (!callbackID)
1257         return;
1258
1259     if (!prepareToFinishTransaction(transaction)) {
1260         if (!m_openDatabaseConnections.contains(&transaction.databaseConnection())) {
1261             // This database connection is closing or has already closed, so there is no point in messaging back to it about the commit failing.
1262             forgetErrorCallback(callbackID);
1263             return;
1264         }
1265
1266         performErrorCallback(callbackID, { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to commit transaction that is already finishing") });
1267         return;
1268     }
1269
1270     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCommitTransaction, callbackID, transaction.info().identifier()));
1271 }
1272
1273 void UniqueIDBDatabase::performCommitTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier)
1274 {
1275     ASSERT(!isMainThread());
1276     LOG(IndexedDB, "(db) UniqueIDBDatabase::performCommitTransaction - %s", transactionIdentifier.loggingString().utf8().data());
1277
1278     IDBError error = m_backingStore->commitTransaction(transactionIdentifier);
1279     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCommitTransaction, callbackIdentifier, error, transactionIdentifier));
1280 }
1281
1282 void UniqueIDBDatabase::didPerformCommitTransaction(uint64_t callbackIdentifier, const IDBError& error, const IDBResourceIdentifier& transactionIdentifier)
1283 {
1284     ASSERT(isMainThread());
1285     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCommitTransaction - %s", transactionIdentifier.loggingString().utf8().data());
1286
1287     performErrorCallback(callbackIdentifier, error);
1288
1289     transactionCompleted(m_finishingTransactions.take(transactionIdentifier));
1290 }
1291
1292 void UniqueIDBDatabase::abortTransaction(UniqueIDBDatabaseTransaction& transaction, ErrorCallback callback)
1293 {
1294     ASSERT(isMainThread());
1295     LOG(IndexedDB, "(main) UniqueIDBDatabase::abortTransaction - %s", transaction.info().identifier().loggingString().utf8().data());
1296
1297     ASSERT(&transaction.databaseConnection().database() == this);
1298
1299     uint64_t callbackID = storeCallbackOrFireError(callback);
1300     if (!callbackID)
1301         return;
1302
1303     if (!prepareToFinishTransaction(transaction)) {
1304         if (!m_openDatabaseConnections.contains(&transaction.databaseConnection())) {
1305             // This database connection is closing or has already closed, so there is no point in messaging back to it about the abort failing.
1306             forgetErrorCallback(callbackID);
1307             return;
1308         }
1309
1310         performErrorCallback(callbackID, { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to abort transaction that is already finishing") });
1311         return;
1312     }
1313
1314     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performAbortTransaction, callbackID, transaction.info().identifier()));
1315 }
1316
1317 void UniqueIDBDatabase::didFinishHandlingVersionChange(UniqueIDBDatabaseConnection& connection, const IDBResourceIdentifier& transactionIdentifier)
1318 {
1319     ASSERT(isMainThread());
1320     LOG(IndexedDB, "(main) UniqueIDBDatabase::didFinishHandlingVersionChange");
1321
1322     ASSERT_UNUSED(transactionIdentifier, !m_versionChangeTransaction || m_versionChangeTransaction->info().identifier() == transactionIdentifier);
1323     ASSERT_UNUSED(connection, !m_versionChangeDatabaseConnection || m_versionChangeDatabaseConnection.get() == &connection);
1324
1325     m_versionChangeTransaction = nullptr;
1326     m_versionChangeDatabaseConnection = nullptr;
1327
1328     if (m_hardClosedForUserDelete) {
1329         maybeFinishHardClose();
1330         return;
1331     }
1332
1333     invokeOperationAndTransactionTimer();
1334 }
1335
1336 void UniqueIDBDatabase::performAbortTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier)
1337 {
1338     ASSERT(!isMainThread());
1339     LOG(IndexedDB, "(db) UniqueIDBDatabase::performAbortTransaction - %s", transactionIdentifier.loggingString().utf8().data());
1340
1341     IDBError error = m_backingStore->abortTransaction(transactionIdentifier);
1342     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformAbortTransaction, callbackIdentifier, error, transactionIdentifier));
1343 }
1344
1345 void UniqueIDBDatabase::didPerformAbortTransaction(uint64_t callbackIdentifier, const IDBError& error, const IDBResourceIdentifier& transactionIdentifier)
1346 {
1347     ASSERT(isMainThread());
1348     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformAbortTransaction - %s", transactionIdentifier.loggingString().utf8().data());
1349
1350     auto transaction = m_finishingTransactions.take(transactionIdentifier);
1351     ASSERT(transaction);
1352
1353     if (m_versionChangeTransaction && m_versionChangeTransaction->info().identifier() == transactionIdentifier) {
1354         ASSERT(m_versionChangeTransaction == transaction);
1355         ASSERT(!m_versionChangeDatabaseConnection || &m_versionChangeTransaction->databaseConnection() == m_versionChangeDatabaseConnection);
1356         ASSERT(m_versionChangeTransaction->originalDatabaseInfo());
1357         m_databaseInfo = std::make_unique<IDBDatabaseInfo>(*m_versionChangeTransaction->originalDatabaseInfo());
1358     }
1359
1360     performErrorCallback(callbackIdentifier, error);
1361
1362     transactionCompleted(WTFMove(transaction));
1363 }
1364
1365 void UniqueIDBDatabase::transactionDestroyed(UniqueIDBDatabaseTransaction& transaction)
1366 {
1367     if (m_versionChangeTransaction == &transaction)
1368         m_versionChangeTransaction = nullptr;
1369 }
1370
1371 void UniqueIDBDatabase::connectionClosedFromClient(UniqueIDBDatabaseConnection& connection)
1372 {
1373     ASSERT(isMainThread());
1374     LOG(IndexedDB, "(main) UniqueIDBDatabase::connectionClosedFromClient - %s (%" PRIu64 ")", connection.openRequestIdentifier().loggingString().utf8().data(), connection.identifier());
1375
1376     Ref<UniqueIDBDatabaseConnection> protectedConnection(connection);
1377     m_openDatabaseConnections.remove(&connection);
1378
1379     if (m_versionChangeDatabaseConnection == &connection) {
1380         if (m_versionChangeTransaction) {
1381             m_clientClosePendingDatabaseConnections.add(WTFMove(m_versionChangeDatabaseConnection));
1382
1383             auto transactionIdentifier = m_versionChangeTransaction->info().identifier();
1384             if (m_inProgressTransactions.contains(transactionIdentifier)) {
1385                 ASSERT(!m_finishingTransactions.contains(transactionIdentifier));
1386                 connection.abortTransactionWithoutCallback(*m_versionChangeTransaction);
1387             }
1388
1389             return;
1390         }
1391
1392         m_versionChangeDatabaseConnection = nullptr;
1393     }
1394
1395     Deque<RefPtr<UniqueIDBDatabaseTransaction>> pendingTransactions;
1396     while (!m_pendingTransactions.isEmpty()) {
1397         auto transaction = m_pendingTransactions.takeFirst();
1398         if (&transaction->databaseConnection() != &connection)
1399             pendingTransactions.append(WTFMove(transaction));
1400     }
1401
1402     if (!pendingTransactions.isEmpty())
1403         m_pendingTransactions.swap(pendingTransactions);
1404
1405     Deque<RefPtr<UniqueIDBDatabaseTransaction>> transactionsToAbort;
1406     for (auto& transaction : m_inProgressTransactions.values()) {
1407         if (&transaction->databaseConnection() == &connection)
1408             transactionsToAbort.append(transaction);
1409     }
1410
1411     for (auto& transaction : transactionsToAbort)
1412         transaction->abortWithoutCallback();
1413
1414     if (m_currentOpenDBRequest)
1415         notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent(connection.identifier());
1416
1417     if (connection.hasNonFinishedTransactions()) {
1418         m_clientClosePendingDatabaseConnections.add(WTFMove(protectedConnection));
1419         return;
1420     }
1421
1422     if (m_hardClosedForUserDelete) {
1423         maybeFinishHardClose();
1424         return;
1425     }
1426
1427     // Now that a database connection has closed, previously blocked operations might be runnable.
1428     invokeOperationAndTransactionTimer();
1429 }
1430
1431 void UniqueIDBDatabase::connectionClosedFromServer(UniqueIDBDatabaseConnection& connection)
1432 {
1433     ASSERT(isMainThread());
1434     LOG(IndexedDB, "UniqueIDBDatabase::connectionClosedFromServer - %s (%" PRIu64 ")", connection.openRequestIdentifier().loggingString().utf8().data(), connection.identifier());
1435
1436     if (m_clientClosePendingDatabaseConnections.contains(&connection)) {
1437         ASSERT(!m_openDatabaseConnections.contains(&connection));
1438         ASSERT(!m_serverClosePendingDatabaseConnections.contains(&connection));
1439         return;
1440     }
1441
1442     Ref<UniqueIDBDatabaseConnection> protectedConnection(connection);
1443     m_openDatabaseConnections.remove(&connection);
1444
1445     connection.connectionToClient().didCloseFromServer(connection, IDBError::userDeleteError());
1446
1447     m_serverClosePendingDatabaseConnections.add(WTFMove(protectedConnection));
1448 }
1449
1450 void UniqueIDBDatabase::confirmDidCloseFromServer(UniqueIDBDatabaseConnection& connection)
1451 {
1452     ASSERT(isMainThread());
1453     LOG(IndexedDB, "UniqueIDBDatabase::confirmDidCloseFromServer - %s (%" PRIu64 ")", connection.openRequestIdentifier().loggingString().utf8().data(), connection.identifier());
1454
1455     ASSERT(m_serverClosePendingDatabaseConnections.contains(&connection));
1456     m_serverClosePendingDatabaseConnections.remove(&connection);
1457 }
1458
1459 void UniqueIDBDatabase::enqueueTransaction(Ref<UniqueIDBDatabaseTransaction>&& transaction)
1460 {
1461     LOG(IndexedDB, "UniqueIDBDatabase::enqueueTransaction - %s", transaction->info().loggingString().utf8().data());
1462     ASSERT(!m_hardClosedForUserDelete);
1463
1464     ASSERT(transaction->info().mode() != IDBTransactionMode::Versionchange);
1465
1466     m_pendingTransactions.append(WTFMove(transaction));
1467
1468     invokeOperationAndTransactionTimer();
1469 }
1470
1471 bool UniqueIDBDatabase::isCurrentlyInUse() const
1472 {
1473     return !m_openDatabaseConnections.isEmpty() || !m_clientClosePendingDatabaseConnections.isEmpty() || !m_pendingOpenDBRequests.isEmpty() || m_currentOpenDBRequest || m_versionChangeDatabaseConnection || m_versionChangeTransaction || m_isOpeningBackingStore || m_deleteBackingStoreInProgress;
1474 }
1475
1476 bool UniqueIDBDatabase::hasUnfinishedTransactions() const
1477 {
1478     return !m_inProgressTransactions.isEmpty() || !m_finishingTransactions.isEmpty();
1479 }
1480
1481 void UniqueIDBDatabase::invokeOperationAndTransactionTimer()
1482 {
1483     LOG(IndexedDB, "UniqueIDBDatabase::invokeOperationAndTransactionTimer()");
1484     ASSERT(!m_hardClosedForUserDelete);
1485
1486     if (!m_operationAndTransactionTimer.isActive())
1487         m_operationAndTransactionTimer.startOneShot(0);
1488 }
1489
1490 void UniqueIDBDatabase::operationAndTransactionTimerFired()
1491 {
1492     LOG(IndexedDB, "(main) UniqueIDBDatabase::operationAndTransactionTimerFired");
1493     ASSERT(!m_hardClosedForUserDelete);
1494
1495     RefPtr<UniqueIDBDatabase> protectedThis(this);
1496
1497     // This UniqueIDBDatabase might be no longer in use by any web page.
1498     // Assuming it is not ephemeral, the server should now close it to free up resources.
1499     if (!m_backingStoreIsEphemeral && !isCurrentlyInUse()) {
1500         ASSERT(m_pendingTransactions.isEmpty());
1501         ASSERT(!hasUnfinishedTransactions());
1502         m_server.closeUniqueIDBDatabase(*this);
1503         return;
1504     }
1505
1506     // The current operation might require multiple attempts to handle, so try to
1507     // make further progress on it now.
1508     if (m_currentOpenDBRequest)
1509         handleCurrentOperation();
1510
1511     if (!m_currentOpenDBRequest)
1512         handleDatabaseOperations();
1513
1514     bool hadDeferredTransactions = false;
1515     auto transaction = takeNextRunnableTransaction(hadDeferredTransactions);
1516
1517     if (transaction) {
1518         m_inProgressTransactions.set(transaction->info().identifier(), transaction);
1519         for (auto objectStore : transaction->objectStoreIdentifiers()) {
1520             m_objectStoreTransactionCounts.add(objectStore);
1521             if (!transaction->isReadOnly()) {
1522                 m_objectStoreWriteTransactions.add(objectStore);
1523                 ASSERT(m_objectStoreTransactionCounts.count(objectStore) == 1);
1524             }
1525         }
1526
1527         activateTransactionInBackingStore(*transaction);
1528
1529         // If no transactions were deferred, it's possible we can start another transaction right now.
1530         if (!hadDeferredTransactions)
1531             invokeOperationAndTransactionTimer();
1532     }
1533 }
1534
1535 void UniqueIDBDatabase::activateTransactionInBackingStore(UniqueIDBDatabaseTransaction& transaction)
1536 {
1537     LOG(IndexedDB, "(main) UniqueIDBDatabase::activateTransactionInBackingStore");
1538
1539     RefPtr<UniqueIDBDatabase> protectedThis(this);
1540     RefPtr<UniqueIDBDatabaseTransaction> refTransaction(&transaction);
1541
1542     auto callback = [this, protectedThis, refTransaction](const IDBError& error) {
1543         refTransaction->didActivateInBackingStore(error);
1544     };
1545
1546     uint64_t callbackID = storeCallbackOrFireError(callback);
1547     if (!callbackID)
1548         return;
1549     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performActivateTransactionInBackingStore, callbackID, transaction.info()));
1550 }
1551
1552 void UniqueIDBDatabase::performActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBTransactionInfo& info)
1553 {
1554     LOG(IndexedDB, "(db) UniqueIDBDatabase::performActivateTransactionInBackingStore");
1555
1556     IDBError error = m_backingStore->beginTransaction(info);
1557     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformActivateTransactionInBackingStore, callbackIdentifier, error));
1558 }
1559
1560 void UniqueIDBDatabase::didPerformActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBError& error)
1561 {
1562     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformActivateTransactionInBackingStore");
1563
1564     invokeOperationAndTransactionTimer();
1565
1566     performErrorCallback(callbackIdentifier, error);
1567 }
1568
1569 template<typename T> bool scopesOverlap(const T& aScopes, const Vector<uint64_t>& bScopes)
1570 {
1571     for (auto scope : bScopes) {
1572         if (aScopes.contains(scope))
1573             return true;
1574     }
1575
1576     return false;
1577 }
1578
1579 RefPtr<UniqueIDBDatabaseTransaction> UniqueIDBDatabase::takeNextRunnableTransaction(bool& hadDeferredTransactions)
1580 {
1581     hadDeferredTransactions = false;
1582
1583     if (m_pendingTransactions.isEmpty())
1584         return nullptr;
1585
1586     if (!m_backingStoreSupportsSimultaneousTransactions && hasUnfinishedTransactions()) {
1587         LOG(IndexedDB, "UniqueIDBDatabase::takeNextRunnableTransaction - Backing store only supports 1 transaction, and we already have 1");
1588         return nullptr;
1589     }
1590
1591     Deque<RefPtr<UniqueIDBDatabaseTransaction>> deferredTransactions;
1592     RefPtr<UniqueIDBDatabaseTransaction> currentTransaction;
1593
1594     HashSet<uint64_t> deferredReadWriteScopes;
1595
1596     while (!m_pendingTransactions.isEmpty()) {
1597         currentTransaction = m_pendingTransactions.takeFirst();
1598
1599         switch (currentTransaction->info().mode()) {
1600         case IDBTransactionMode::Readonly: {
1601             bool hasOverlappingScopes = scopesOverlap(deferredReadWriteScopes, currentTransaction->objectStoreIdentifiers());
1602             hasOverlappingScopes |= scopesOverlap(m_objectStoreWriteTransactions, currentTransaction->objectStoreIdentifiers());
1603
1604             if (hasOverlappingScopes)
1605                 deferredTransactions.append(WTFMove(currentTransaction));
1606
1607             break;
1608         }
1609         case IDBTransactionMode::Readwrite: {
1610             bool hasOverlappingScopes = scopesOverlap(m_objectStoreTransactionCounts, currentTransaction->objectStoreIdentifiers());
1611             hasOverlappingScopes |= scopesOverlap(deferredReadWriteScopes, currentTransaction->objectStoreIdentifiers());
1612
1613             if (hasOverlappingScopes) {
1614                 for (auto objectStore : currentTransaction->objectStoreIdentifiers())
1615                     deferredReadWriteScopes.add(objectStore);
1616                 deferredTransactions.append(WTFMove(currentTransaction));
1617             }
1618
1619             break;
1620         }
1621         case IDBTransactionMode::Versionchange:
1622             // Version change transactions should never be scheduled in the traditional manner.
1623             RELEASE_ASSERT_NOT_REACHED();
1624         }
1625
1626         // If we didn't defer the currentTransaction above, it can be run now.
1627         if (currentTransaction)
1628             break;
1629     }
1630
1631     hadDeferredTransactions = !deferredTransactions.isEmpty();
1632     if (!hadDeferredTransactions)
1633         return currentTransaction;
1634
1635     // Prepend the deferred transactions back on the beginning of the deque for future scheduling passes.
1636     while (!deferredTransactions.isEmpty())
1637         m_pendingTransactions.prepend(deferredTransactions.takeLast());
1638
1639     return currentTransaction;
1640 }
1641
1642 void UniqueIDBDatabase::transactionCompleted(RefPtr<UniqueIDBDatabaseTransaction>&& transaction)
1643 {
1644     ASSERT(transaction);
1645     ASSERT(!m_inProgressTransactions.contains(transaction->info().identifier()));
1646     ASSERT(!m_finishingTransactions.contains(transaction->info().identifier()));
1647
1648     for (auto objectStore : transaction->objectStoreIdentifiers()) {
1649         if (!transaction->isReadOnly()) {
1650             m_objectStoreWriteTransactions.remove(objectStore);
1651             ASSERT(m_objectStoreTransactionCounts.count(objectStore) == 1);
1652         }
1653         m_objectStoreTransactionCounts.remove(objectStore);
1654     }
1655
1656     if (!transaction->databaseConnection().hasNonFinishedTransactions())
1657         m_clientClosePendingDatabaseConnections.remove(&transaction->databaseConnection());
1658
1659     if (m_versionChangeTransaction == transaction)
1660         m_versionChangeTransaction = nullptr;
1661
1662     // It's possible that this database had its backing store deleted but there were a few outstanding asynchronous operations.
1663     // If this transaction completing was the last of those operations, we can finally delete this UniqueIDBDatabase.
1664     if (m_clientClosePendingDatabaseConnections.isEmpty() && m_pendingOpenDBRequests.isEmpty() && !m_databaseInfo) {
1665         m_server.closeUniqueIDBDatabase(*this);
1666         return;
1667     }
1668
1669     // Previously blocked operations might be runnable.
1670     if (!m_hardClosedForUserDelete)
1671         invokeOperationAndTransactionTimer();
1672     else
1673         maybeFinishHardClose();
1674 }
1675
1676 void UniqueIDBDatabase::postDatabaseTask(CrossThreadTask&& task)
1677 {
1678     ASSERT(isMainThread());
1679     m_databaseQueue.append(WTFMove(task));
1680     ++m_queuedTaskCount;
1681
1682     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::executeNextDatabaseTask));
1683 }
1684
1685 void UniqueIDBDatabase::postDatabaseTaskReply(CrossThreadTask&& task)
1686 {
1687     ASSERT(!isMainThread());
1688     m_databaseReplyQueue.append(WTFMove(task));
1689     ++m_queuedTaskCount;
1690
1691     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::executeNextDatabaseTaskReply));
1692 }
1693
1694 void UniqueIDBDatabase::executeNextDatabaseTask()
1695 {
1696     ASSERT(!isMainThread());
1697     ASSERT(m_queuedTaskCount);
1698
1699     auto task = m_databaseQueue.tryGetMessage();
1700     ASSERT(task);
1701
1702     // Performing the task might end up removing the last reference to this.
1703     Ref<UniqueIDBDatabase> protectedThis(*this);
1704
1705     task->performTask();
1706     --m_queuedTaskCount;
1707
1708     // Release the ref in the main thread to ensure it's deleted there as expected in case of being the last reference.
1709     callOnMainThread([protectedThis = WTFMove(protectedThis)] {
1710     });
1711 }
1712
1713 void UniqueIDBDatabase::executeNextDatabaseTaskReply()
1714 {
1715     ASSERT(isMainThread());
1716     ASSERT(m_queuedTaskCount);
1717
1718     auto task = m_databaseReplyQueue.tryGetMessage();
1719     ASSERT(task);
1720
1721     // Performing the task might end up removing the last reference to this.
1722     Ref<UniqueIDBDatabase> protectedThis(*this);
1723
1724     task->performTask();
1725     --m_queuedTaskCount;
1726
1727     // If this database was force closed (e.g. for a user delete) and there are no more
1728     // cleanup tasks left, delete this.
1729     maybeFinishHardClose();
1730 }
1731
1732 void UniqueIDBDatabase::maybeFinishHardClose()
1733 {
1734     if (m_hardCloseProtector && isDoneWithHardClose()) {
1735         callOnMainThread([this] {
1736             ASSERT(isDoneWithHardClose());
1737             m_hardCloseProtector = nullptr;
1738         });
1739     }
1740 }
1741
1742 bool UniqueIDBDatabase::isDoneWithHardClose()
1743 {
1744     return !m_queuedTaskCount && m_clientClosePendingDatabaseConnections.isEmpty() && m_serverClosePendingDatabaseConnections.isEmpty();
1745 }
1746
1747 static void errorOpenDBRequestForUserDelete(ServerOpenDBRequest& request)
1748 {
1749     auto result = IDBResultData::error(request.requestData().requestIdentifier(), IDBError::userDeleteError());
1750     if (request.isOpenRequest())
1751         request.connection().didOpenDatabase(result);
1752     else
1753         request.connection().didDeleteDatabase(result);
1754 }
1755
1756 void UniqueIDBDatabase::immediateCloseForUserDelete()
1757 {
1758     LOG(IndexedDB, "UniqueIDBDatabase::immediateCloseForUserDelete - Cancelling (%i, %i, %i, %i) callbacks", m_errorCallbacks.size(), m_keyDataCallbacks.size(), m_getResultCallbacks.size(), m_countCallbacks.size());
1759
1760     // Error out all transactions
1761     Vector<IDBResourceIdentifier> inProgressIdentifiers;
1762     copyKeysToVector(m_inProgressTransactions, inProgressIdentifiers);
1763     for (auto& identifier : inProgressIdentifiers)
1764         m_inProgressTransactions.get(identifier)->abortWithoutCallback();
1765
1766     ASSERT(m_inProgressTransactions.isEmpty());
1767
1768     m_pendingTransactions.clear();
1769     m_objectStoreTransactionCounts.clear();
1770     m_objectStoreWriteTransactions.clear();
1771
1772     // Error out all pending callbacks
1773     Vector<uint64_t> callbackIdentifiers;
1774     IDBError error = IDBError::userDeleteError();
1775     IDBKeyData keyData;
1776     IDBGetResult getResult;
1777
1778     copyKeysToVector(m_errorCallbacks, callbackIdentifiers);
1779     for (auto identifier : callbackIdentifiers)
1780         performErrorCallback(identifier, error);
1781
1782     callbackIdentifiers.clear();
1783     copyKeysToVector(m_keyDataCallbacks, callbackIdentifiers);
1784     for (auto identifier : callbackIdentifiers)
1785         performKeyDataCallback(identifier, error, keyData);
1786
1787     callbackIdentifiers.clear();
1788     copyKeysToVector(m_getResultCallbacks, callbackIdentifiers);
1789     for (auto identifier : callbackIdentifiers)
1790         performGetResultCallback(identifier, error, getResult);
1791
1792     callbackIdentifiers.clear();
1793     copyKeysToVector(m_countCallbacks, callbackIdentifiers);
1794     for (auto identifier : callbackIdentifiers)
1795         performCountCallback(identifier, error, 0);
1796
1797     // Error out all IDBOpenDBRequests
1798     if (m_currentOpenDBRequest) {
1799         errorOpenDBRequestForUserDelete(*m_currentOpenDBRequest);
1800         m_currentOpenDBRequest = nullptr;
1801     }
1802
1803     for (auto& request : m_pendingOpenDBRequests)
1804         errorOpenDBRequestForUserDelete(*request);
1805
1806     m_pendingOpenDBRequests.clear();
1807
1808     // Close all open connections
1809     ListHashSet<RefPtr<UniqueIDBDatabaseConnection>> openDatabaseConnections = m_openDatabaseConnections;
1810     for (auto& connection : openDatabaseConnections)
1811         connectionClosedFromServer(*connection);
1812
1813     // Cancel the operation timer
1814     m_operationAndTransactionTimer.stop();
1815
1816     // Set up the database to remain alive-but-inert until all of its background activity finishes and all
1817     // database connections confirm that they have closed.
1818     m_hardClosedForUserDelete = true;
1819     m_hardCloseProtector = this;
1820
1821     // Have the database unconditionally delete itself on the database task queue.
1822     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performUnconditionalDeleteBackingStore));
1823
1824     // Remove the database from the IDBServer's set of open databases.
1825     // If there is no in-progress background thread activity for this database, it will be deleted here.
1826     m_server.closeUniqueIDBDatabase(*this);
1827 }
1828
1829 void UniqueIDBDatabase::performErrorCallback(uint64_t callbackIdentifier, const IDBError& error)
1830 {
1831     auto callback = m_errorCallbacks.take(callbackIdentifier);
1832     ASSERT(callback || m_hardClosedForUserDelete);
1833     if (callback)
1834         callback(error);
1835 }
1836
1837 void UniqueIDBDatabase::performKeyDataCallback(uint64_t callbackIdentifier, const IDBError& error, const IDBKeyData& resultKey)
1838 {
1839     auto callback = m_keyDataCallbacks.take(callbackIdentifier);
1840     ASSERT(callback || m_hardClosedForUserDelete);
1841     if (callback)
1842         callback(error, resultKey);
1843 }
1844
1845 void UniqueIDBDatabase::performGetResultCallback(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& resultData)
1846 {
1847     auto callback = m_getResultCallbacks.take(callbackIdentifier);
1848     ASSERT(callback || m_hardClosedForUserDelete);
1849     if (callback)
1850         callback(error, resultData);
1851 }
1852
1853 void UniqueIDBDatabase::performGetAllResultsCallback(uint64_t callbackIdentifier, const IDBError& error, const IDBGetAllResult& resultData)
1854 {
1855     auto callback = m_getAllResultsCallbacks.take(callbackIdentifier);
1856     ASSERT(callback || m_hardClosedForUserDelete);
1857     if (callback)
1858         callback(error, resultData);
1859 }
1860
1861 void UniqueIDBDatabase::performCountCallback(uint64_t callbackIdentifier, const IDBError& error, uint64_t count)
1862 {
1863     auto callback = m_countCallbacks.take(callbackIdentifier);
1864     ASSERT(callback || m_hardClosedForUserDelete);
1865     if (callback)
1866         callback(error, count);
1867 }
1868
1869 void UniqueIDBDatabase::forgetErrorCallback(uint64_t callbackIdentifier)
1870 {
1871     ASSERT(m_errorCallbacks.contains(callbackIdentifier));
1872     m_errorCallbacks.remove(callbackIdentifier);
1873 }
1874
1875 } // namespace IDBServer
1876 } // namespace WebCore
1877
1878 #endif // ENABLE(INDEXED_DATABASE)