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