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