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