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