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