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