Modern IDB: storage/indexeddb/dont-wedge.html sometimes ASSERTs.
[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 "IDBKeyRangeData.h"
33 #include "IDBResultData.h"
34 #include "IDBServer.h"
35 #include "IDBTransactionInfo.h"
36 #include "Logging.h"
37 #include "ScopeGuard.h"
38 #include "UniqueIDBDatabaseConnection.h"
39 #include <wtf/MainThread.h>
40 #include <wtf/NeverDestroyed.h>
41 #include <wtf/ThreadSafeRefCounted.h>
42
43 using namespace JSC;
44
45 namespace WebCore {
46 namespace IDBServer {
47     
48 UniqueIDBDatabase::UniqueIDBDatabase(IDBServer& server, const IDBDatabaseIdentifier& identifier)
49     : m_server(server)
50     , m_identifier(identifier)
51     , m_operationAndTransactionTimer(*this, &UniqueIDBDatabase::operationAndTransactionTimerFired)
52 {
53 }
54
55 UniqueIDBDatabase::~UniqueIDBDatabase()
56 {
57     LOG(IndexedDB, "UniqueIDBDatabase::~UniqueIDBDatabase() (%p)", this);
58     ASSERT(!hasAnyPendingCallbacks());
59     ASSERT(m_inProgressTransactions.isEmpty());
60     ASSERT(m_pendingTransactions.isEmpty());
61     ASSERT(m_openDatabaseConnections.isEmpty());
62 }
63
64 const IDBDatabaseInfo& UniqueIDBDatabase::info() const
65 {
66     RELEASE_ASSERT(m_databaseInfo);
67     return *m_databaseInfo;
68 }
69
70 void UniqueIDBDatabase::openDatabaseConnection(IDBConnectionToClient& connection, const IDBRequestData& requestData)
71 {
72     auto operation = ServerOpenDBRequest::create(connection, requestData);
73     m_pendingOpenDBRequests.append(WTFMove(operation));
74
75     // An open operation is already in progress, so we can't possibly handle this one yet.
76     if (m_isOpeningBackingStore)
77         return;
78
79     handleDatabaseOperations();
80 }
81
82 bool UniqueIDBDatabase::hasAnyPendingCallbacks() const
83 {
84     return !m_errorCallbacks.isEmpty()
85         || !m_keyDataCallbacks.isEmpty()
86         || !m_getResultCallbacks.isEmpty()
87         || !m_countCallbacks.isEmpty();
88 }
89
90 bool UniqueIDBDatabase::isVersionChangeInProgress()
91 {
92 #ifndef NDEBUG
93     if (m_versionChangeTransaction)
94         ASSERT(m_versionChangeDatabaseConnection);
95 #endif
96
97     return m_versionChangeDatabaseConnection;
98 }
99
100 void UniqueIDBDatabase::performCurrentOpenOperation()
101 {
102     LOG(IndexedDB, "(main) UniqueIDBDatabase::performCurrentOpenOperation (%p)", this);
103
104     ASSERT(m_currentOpenDBRequest);
105     ASSERT(m_currentOpenDBRequest->isOpenRequest());
106
107     if (!m_databaseInfo) {
108         if (!m_isOpeningBackingStore) {
109             m_isOpeningBackingStore = true;
110             m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::openBackingStore, m_identifier));
111         }
112
113         return;
114     }
115
116     // If we previously started a version change operation but were blocked by having open connections,
117     // we might now be unblocked.
118     if (m_versionChangeDatabaseConnection) {
119         if (!m_versionChangeTransaction && !hasAnyOpenConnections())
120             startVersionChangeTransaction();
121         return;
122     }
123
124     // 3.3.1 Opening a database
125     // If requested version is undefined, then let requested version be 1 if db was created in the previous step,
126     // or the current version of db otherwise.
127     uint64_t requestedVersion = m_currentOpenDBRequest->requestData().requestedVersion();
128     if (!requestedVersion)
129         requestedVersion = m_databaseInfo->version() ? m_databaseInfo->version() : 1;
130
131     // 3.3.1 Opening a database
132     // If the database version higher than the requested version, abort these steps and return a VersionError.
133     if (requestedVersion < m_databaseInfo->version()) {
134         auto result = IDBResultData::error(m_currentOpenDBRequest->requestData().requestIdentifier(), IDBError(IDBDatabaseException::VersionError));
135         m_currentOpenDBRequest->connection().didOpenDatabase(result);
136         m_currentOpenDBRequest = nullptr;
137
138         return;
139     }
140
141     Ref<UniqueIDBDatabaseConnection> connection = UniqueIDBDatabaseConnection::create(*this, m_currentOpenDBRequest->connection());
142     UniqueIDBDatabaseConnection* rawConnection = &connection.get();
143
144     if (requestedVersion == m_databaseInfo->version()) {
145         addOpenDatabaseConnection(WTFMove(connection));
146
147         auto result = IDBResultData::openDatabaseSuccess(m_currentOpenDBRequest->requestData().requestIdentifier(), *rawConnection);
148         m_currentOpenDBRequest->connection().didOpenDatabase(result);
149         m_currentOpenDBRequest = nullptr;
150
151         return;
152     }
153
154     ASSERT(!m_versionChangeDatabaseConnection);
155     m_versionChangeDatabaseConnection = rawConnection;
156
157     // 3.3.7 "versionchange" transaction steps
158     // If there's no other open connections to this database, the version change process can begin immediately.
159     if (!hasAnyOpenConnections()) {
160         startVersionChangeTransaction();
161         return;
162     }
163
164     // Otherwise we have to notify all those open connections and wait for them to close.
165     maybeNotifyConnectionsOfVersionChange();
166 }
167
168 void UniqueIDBDatabase::performCurrentDeleteOperation()
169 {
170     ASSERT(isMainThread());
171     LOG(IndexedDB, "(main) UniqueIDBDatabase::performCurrentDeleteOperation - %s", m_identifier.debugString().utf8().data());
172
173     ASSERT(m_currentOpenDBRequest);
174     ASSERT(m_currentOpenDBRequest->isDeleteRequest());
175
176     if (m_deleteBackingStoreInProgress)
177         return;
178
179     if (hasAnyOpenConnections()) {
180         maybeNotifyConnectionsOfVersionChange();
181         return;
182     }
183
184     // Even though we have no open database connections, we might have close-pending database connections
185     // that are waiting on transactions to complete.
186     if (!m_inProgressTransactions.isEmpty()) {
187         ASSERT(!m_closePendingDatabaseConnections.isEmpty());
188         return;
189     }
190
191     ASSERT(!hasAnyPendingCallbacks());
192     ASSERT(m_pendingTransactions.isEmpty());
193     ASSERT(m_openDatabaseConnections.isEmpty());
194
195     // It's possible to have multiple delete requests queued up in a row.
196     // In that scenario only the first request will actually have to delete the database.
197     // Subsequent requests can immediately notify their completion.
198
199     if (m_databaseInfo) {
200         m_deleteBackingStoreInProgress = true;
201         m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::deleteBackingStore));
202     } else {
203         ASSERT(m_mostRecentDeletedDatabaseInfo);
204         didDeleteBackingStore();
205     }
206 }
207
208 void UniqueIDBDatabase::deleteBackingStore()
209 {
210     ASSERT(!isMainThread());
211     LOG(IndexedDB, "(db) UniqueIDBDatabase::deleteBackingStore");
212
213     if (m_backingStore) {
214         m_backingStore->deleteBackingStore();
215         m_backingStore = nullptr;
216         m_backingStoreSupportsSimultaneousTransactions = false;
217     }
218
219     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didDeleteBackingStore));
220 }
221
222 void UniqueIDBDatabase::didDeleteBackingStore()
223 {
224     ASSERT(isMainThread());
225     LOG(IndexedDB, "(main) UniqueIDBDatabase::didDeleteBackingStore");
226
227     ASSERT(m_currentOpenDBRequest);
228     ASSERT(m_currentOpenDBRequest->isDeleteRequest());
229     ASSERT(!hasAnyPendingCallbacks());
230     ASSERT(m_inProgressTransactions.isEmpty());
231     ASSERT(m_pendingTransactions.isEmpty());
232     ASSERT(m_openDatabaseConnections.isEmpty());
233
234     if (m_databaseInfo)
235         m_mostRecentDeletedDatabaseInfo = WTFMove(m_databaseInfo);
236
237     ASSERT(m_mostRecentDeletedDatabaseInfo);
238     m_currentOpenDBRequest->notifyDidDeleteDatabase(*m_mostRecentDeletedDatabaseInfo);
239     m_currentOpenDBRequest = nullptr;
240
241     m_deletePending = false;
242     m_deleteBackingStoreInProgress = false;
243
244     if (m_pendingOpenDBRequests.isEmpty())
245         m_server.deleteUniqueIDBDatabase(*this);
246     else
247         invokeOperationAndTransactionTimer();
248 }
249
250 void UniqueIDBDatabase::handleDatabaseOperations()
251 {
252     ASSERT(isMainThread());
253     LOG(IndexedDB, "(main) UniqueIDBDatabase::handleDatabaseOperations - There are %zu pending", m_pendingOpenDBRequests.size());
254
255     if (m_versionChangeDatabaseConnection || m_versionChangeTransaction || m_currentOpenDBRequest) {
256         // We can't start any new open-database operations right now, but we might be able to start handling a delete operation.
257         if (!m_currentOpenDBRequest && !m_pendingOpenDBRequests.isEmpty() && m_pendingOpenDBRequests.first()->isDeleteRequest())
258             m_currentOpenDBRequest = m_pendingOpenDBRequests.takeFirst();
259
260         // Some operations (such as the first open operation after a delete) require multiple passes to completely handle
261         if (m_currentOpenDBRequest)
262             handleCurrentOperation();
263
264         return;
265     }
266
267     if (m_pendingOpenDBRequests.isEmpty())
268         return;
269
270     m_currentOpenDBRequest = m_pendingOpenDBRequests.takeFirst();
271     LOG(IndexedDB, "UniqueIDBDatabase::handleDatabaseOperations - Popped an operation, now there are %zu pending", m_pendingOpenDBRequests.size());
272
273     handleCurrentOperation();
274 }
275
276 void UniqueIDBDatabase::handleCurrentOperation()
277 {
278     ASSERT(m_currentOpenDBRequest);
279
280     RefPtr<UniqueIDBDatabase> protector(this);
281
282     if (m_currentOpenDBRequest->isOpenRequest())
283         performCurrentOpenOperation();
284     else if (m_currentOpenDBRequest->isDeleteRequest())
285         performCurrentDeleteOperation();
286     else
287         ASSERT_NOT_REACHED();
288
289     if (!m_currentOpenDBRequest)
290         invokeOperationAndTransactionTimer();
291 }
292
293 bool UniqueIDBDatabase::hasAnyOpenConnections() const
294 {
295     return !m_openDatabaseConnections.isEmpty();
296 }
297
298 static uint64_t generateUniqueCallbackIdentifier()
299 {
300     ASSERT(isMainThread());
301     static uint64_t currentID = 0;
302     return ++currentID;
303 }
304
305 uint64_t UniqueIDBDatabase::storeCallback(ErrorCallback callback)
306 {
307     uint64_t identifier = generateUniqueCallbackIdentifier();
308     ASSERT(!m_errorCallbacks.contains(identifier));
309     m_errorCallbacks.add(identifier, callback);
310     return identifier;
311 }
312
313 uint64_t UniqueIDBDatabase::storeCallback(KeyDataCallback callback)
314 {
315     uint64_t identifier = generateUniqueCallbackIdentifier();
316     ASSERT(!m_keyDataCallbacks.contains(identifier));
317     m_keyDataCallbacks.add(identifier, callback);
318     return identifier;
319 }
320
321 uint64_t UniqueIDBDatabase::storeCallback(GetResultCallback callback)
322 {
323     uint64_t identifier = generateUniqueCallbackIdentifier();
324     ASSERT(!m_getResultCallbacks.contains(identifier));
325     m_getResultCallbacks.add(identifier, callback);
326     return identifier;
327 }
328
329 uint64_t UniqueIDBDatabase::storeCallback(CountCallback callback)
330 {
331     uint64_t identifier = generateUniqueCallbackIdentifier();
332     ASSERT(!m_countCallbacks.contains(identifier));
333     m_countCallbacks.add(identifier, callback);
334     return identifier;
335 }
336
337 void UniqueIDBDatabase::handleDelete(IDBConnectionToClient& connection, const IDBRequestData& requestData)
338 {
339     LOG(IndexedDB, "(main) UniqueIDBDatabase::handleDelete");
340
341     m_pendingOpenDBRequests.append(ServerOpenDBRequest::create(connection, requestData));
342     handleDatabaseOperations();
343 }
344
345 void UniqueIDBDatabase::startVersionChangeTransaction()
346 {
347     LOG(IndexedDB, "(main) UniqueIDBDatabase::startVersionChangeTransaction");
348
349     ASSERT(!m_versionChangeTransaction);
350     ASSERT(m_currentOpenDBRequest);
351     ASSERT(m_currentOpenDBRequest->isOpenRequest());
352     ASSERT(m_versionChangeDatabaseConnection);
353
354     auto operation = WTFMove(m_currentOpenDBRequest);
355
356     uint64_t requestedVersion = operation->requestData().requestedVersion();
357     if (!requestedVersion)
358         requestedVersion = m_databaseInfo->version() ? m_databaseInfo->version() : 1;
359
360     addOpenDatabaseConnection(*m_versionChangeDatabaseConnection);
361
362     m_versionChangeTransaction = &m_versionChangeDatabaseConnection->createVersionChangeTransaction(requestedVersion);
363     m_databaseInfo->setVersion(requestedVersion);
364
365     m_inProgressTransactions.set(m_versionChangeTransaction->info().identifier(), m_versionChangeTransaction);
366     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::beginTransactionInBackingStore, m_versionChangeTransaction->info()));
367
368     auto result = IDBResultData::openDatabaseUpgradeNeeded(operation->requestData().requestIdentifier(), *m_versionChangeTransaction);
369     operation->connection().didOpenDatabase(result);
370 }
371
372 void UniqueIDBDatabase::beginTransactionInBackingStore(const IDBTransactionInfo& info)
373 {
374     LOG(IndexedDB, "(db) UniqueIDBDatabase::beginTransactionInBackingStore");
375     m_backingStore->beginTransaction(info);
376 }
377
378 void UniqueIDBDatabase::maybeNotifyConnectionsOfVersionChange()
379 {
380     ASSERT(m_currentOpenDBRequest);
381
382     if (m_currentOpenDBRequest->hasNotifiedConnectionsOfVersionChange())
383         return;
384
385     uint64_t newVersion = m_currentOpenDBRequest->isOpenRequest() ? m_currentOpenDBRequest->requestData().requestedVersion() : 0;
386     auto requestIdentifier = m_currentOpenDBRequest->requestData().requestIdentifier();
387
388     LOG(IndexedDB, "(main) UniqueIDBDatabase::notifyConnectionsOfVersionChange - %" PRIu64, newVersion);
389
390     // 3.3.7 "versionchange" transaction steps
391     // Fire a versionchange event at each connection in m_openDatabaseConnections that is open.
392     // The event must not be fired on connections which has the closePending flag set.
393     HashSet<uint64_t> connectionIdentifiers;
394     for (auto connection : m_openDatabaseConnections) {
395         if (connection->closePending())
396             continue;
397
398         connection->fireVersionChangeEvent(requestIdentifier, newVersion);
399         connectionIdentifiers.add(connection->identifier());
400     }
401
402     m_currentOpenDBRequest->notifiedConnectionsOfVersionChange(WTFMove(connectionIdentifiers));
403 }
404
405 void UniqueIDBDatabase::notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent(uint64_t connectionIdentifier)
406 {
407     LOG(IndexedDB, "UniqueIDBDatabase::notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent - %" PRIu64, connectionIdentifier);
408
409     ASSERT(m_currentOpenDBRequest);
410
411     m_currentOpenDBRequest->connectionClosedOrFiredVersionChangeEvent(connectionIdentifier);
412
413     if (m_currentOpenDBRequest->hasConnectionsPendingVersionChangeEvent())
414         return;
415
416     if (!hasAnyOpenConnections()) {
417         invokeOperationAndTransactionTimer();
418         return;
419     }
420
421     if (m_currentOpenDBRequest->hasNotifiedBlocked())
422         return;
423
424     // Since all open connections have fired their version change events but not all of them have closed,
425     // this request is officially blocked.
426     m_currentOpenDBRequest->notifyRequestBlocked(m_databaseInfo->version());
427 }
428
429 void UniqueIDBDatabase::didFireVersionChangeEvent(UniqueIDBDatabaseConnection& connection, const IDBResourceIdentifier& requestIdentifier)
430 {
431     LOG(IndexedDB, "UniqueIDBDatabase::didFireVersionChangeEvent");
432
433     if (!m_currentOpenDBRequest)
434         return;
435
436     ASSERT_UNUSED(requestIdentifier, m_currentOpenDBRequest->requestData().requestIdentifier() == requestIdentifier);
437
438     notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent(connection.identifier());
439 }
440
441 void UniqueIDBDatabase::addOpenDatabaseConnection(Ref<UniqueIDBDatabaseConnection>&& connection)
442 {
443     ASSERT(!m_openDatabaseConnections.contains(&connection.get()));
444     m_openDatabaseConnections.add(adoptRef(connection.leakRef()));
445 }
446
447 void UniqueIDBDatabase::openBackingStore(const IDBDatabaseIdentifier& identifier)
448 {
449     ASSERT(!isMainThread());
450     LOG(IndexedDB, "(db) UniqueIDBDatabase::openBackingStore (%p)", this);
451
452     ASSERT(!m_backingStore);
453     m_backingStore = m_server.createBackingStore(identifier);
454     m_backingStoreSupportsSimultaneousTransactions = m_backingStore->supportsSimultaneousTransactions();
455     auto databaseInfo = m_backingStore->getOrEstablishDatabaseInfo();
456
457     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didOpenBackingStore, databaseInfo));
458 }
459
460 void UniqueIDBDatabase::didOpenBackingStore(const IDBDatabaseInfo& info)
461 {
462     ASSERT(isMainThread());
463     LOG(IndexedDB, "(main) UniqueIDBDatabase::didOpenBackingStore");
464     
465     m_databaseInfo = std::make_unique<IDBDatabaseInfo>(info);
466
467     ASSERT(m_isOpeningBackingStore);
468     m_isOpeningBackingStore = false;
469
470     handleDatabaseOperations();
471 }
472
473 void UniqueIDBDatabase::createObjectStore(UniqueIDBDatabaseTransaction& transaction, const IDBObjectStoreInfo& info, ErrorCallback callback)
474 {
475     ASSERT(isMainThread());
476     LOG(IndexedDB, "(main) UniqueIDBDatabase::createObjectStore");
477
478     uint64_t callbackID = storeCallback(callback);
479     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateObjectStore, callbackID, transaction.info().identifier(), info));
480 }
481
482 void UniqueIDBDatabase::performCreateObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& info)
483 {
484     ASSERT(!isMainThread());
485     LOG(IndexedDB, "(db) UniqueIDBDatabase::performCreateObjectStore");
486
487     ASSERT(m_backingStore);
488     m_backingStore->createObjectStore(transactionIdentifier, info);
489
490     IDBError error;
491     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateObjectStore, callbackIdentifier, error, info));
492 }
493
494 void UniqueIDBDatabase::didPerformCreateObjectStore(uint64_t callbackIdentifier, const IDBError& error, const IDBObjectStoreInfo& info)
495 {
496     ASSERT(isMainThread());
497     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCreateObjectStore");
498
499     if (error.isNull())
500         m_databaseInfo->addExistingObjectStore(info);
501
502     performErrorCallback(callbackIdentifier, error);
503 }
504
505 void UniqueIDBDatabase::deleteObjectStore(UniqueIDBDatabaseTransaction& transaction, const String& objectStoreName, ErrorCallback callback)
506 {
507     ASSERT(isMainThread());
508     LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteObjectStore");
509
510     uint64_t callbackID = storeCallback(callback);
511
512     auto* info = m_databaseInfo->infoForExistingObjectStore(objectStoreName);
513     if (!info) {
514         performErrorCallback(callbackID, { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to delete non-existant object store") });
515         return;
516     }
517
518     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performDeleteObjectStore, callbackID, transaction.info().identifier(), info->identifier()));
519 }
520
521 void UniqueIDBDatabase::performDeleteObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier)
522 {
523     ASSERT(!isMainThread());
524     LOG(IndexedDB, "(db) UniqueIDBDatabase::performDeleteObjectStore");
525
526     ASSERT(m_backingStore);
527     m_backingStore->deleteObjectStore(transactionIdentifier, objectStoreIdentifier);
528
529     IDBError error;
530     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformDeleteObjectStore, callbackIdentifier, error, objectStoreIdentifier));
531 }
532
533 void UniqueIDBDatabase::didPerformDeleteObjectStore(uint64_t callbackIdentifier, const IDBError& error, uint64_t objectStoreIdentifier)
534 {
535     ASSERT(isMainThread());
536     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformDeleteObjectStore");
537
538     if (error.isNull())
539         m_databaseInfo->deleteObjectStore(objectStoreIdentifier);
540
541     performErrorCallback(callbackIdentifier, error);
542 }
543
544 void UniqueIDBDatabase::clearObjectStore(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, ErrorCallback callback)
545 {
546     ASSERT(isMainThread());
547     LOG(IndexedDB, "(main) UniqueIDBDatabase::clearObjectStore");
548
549     uint64_t callbackID = storeCallback(callback);
550     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performClearObjectStore, callbackID, transaction.info().identifier(), objectStoreIdentifier));
551 }
552
553 void UniqueIDBDatabase::performClearObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier)
554 {
555     ASSERT(!isMainThread());
556     LOG(IndexedDB, "(db) UniqueIDBDatabase::performClearObjectStore");
557
558     ASSERT(m_backingStore);
559     m_backingStore->clearObjectStore(transactionIdentifier, objectStoreIdentifier);
560
561     IDBError error;
562     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformClearObjectStore, callbackIdentifier, error));
563 }
564
565 void UniqueIDBDatabase::didPerformClearObjectStore(uint64_t callbackIdentifier, const IDBError& error)
566 {
567     ASSERT(isMainThread());
568     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformClearObjectStore");
569
570     performErrorCallback(callbackIdentifier, error);
571 }
572
573 void UniqueIDBDatabase::createIndex(UniqueIDBDatabaseTransaction& transaction, const IDBIndexInfo& info, ErrorCallback callback)
574 {
575     ASSERT(isMainThread());
576     LOG(IndexedDB, "(main) UniqueIDBDatabase::createIndex");
577
578     uint64_t callbackID = storeCallback(callback);
579     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateIndex, callbackID, transaction.info().identifier(), info));
580 }
581
582 void UniqueIDBDatabase::performCreateIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo& info)
583 {
584     ASSERT(!isMainThread());
585     LOG(IndexedDB, "(db) UniqueIDBDatabase::performCreateIndex");
586
587     ASSERT(m_backingStore);
588     IDBError error = m_backingStore->createIndex(transactionIdentifier, info);
589
590     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateIndex, callbackIdentifier, error, info));
591 }
592
593 void UniqueIDBDatabase::didPerformCreateIndex(uint64_t callbackIdentifier, const IDBError& error, const IDBIndexInfo& info)
594 {
595     ASSERT(isMainThread());
596     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCreateIndex");
597
598     if (error.isNull()) {
599         ASSERT(m_databaseInfo);
600         auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(info.objectStoreIdentifier());
601         ASSERT(objectStoreInfo);
602         objectStoreInfo->addExistingIndex(info);
603     }
604
605     performErrorCallback(callbackIdentifier, error);
606 }
607
608 void UniqueIDBDatabase::deleteIndex(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, const String& indexName, ErrorCallback callback)
609 {
610     ASSERT(isMainThread());
611     LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteIndex");
612
613     uint64_t callbackID = storeCallback(callback);
614
615     auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
616     if (!objectStoreInfo) {
617         performErrorCallback(callbackID, { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to delete index from non-existant object store") });
618         return;
619     }
620
621     auto* indexInfo = objectStoreInfo->infoForExistingIndex(indexName);
622     if (!indexInfo) {
623         performErrorCallback(callbackID, { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to delete non-existant index") });
624         return;
625     }
626
627     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performDeleteIndex, callbackID, transaction.info().identifier(), objectStoreIdentifier, indexInfo->identifier()));
628 }
629
630 void UniqueIDBDatabase::performDeleteIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const uint64_t indexIdentifier)
631 {
632     ASSERT(!isMainThread());
633     LOG(IndexedDB, "(db) UniqueIDBDatabase::performDeleteIndex");
634
635     ASSERT(m_backingStore);
636     m_backingStore->deleteIndex(transactionIdentifier, objectStoreIdentifier, indexIdentifier);
637
638     IDBError error;
639     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformDeleteIndex, callbackIdentifier, error, objectStoreIdentifier, indexIdentifier));
640 }
641
642 void UniqueIDBDatabase::didPerformDeleteIndex(uint64_t callbackIdentifier, const IDBError& error, uint64_t objectStoreIdentifier, uint64_t indexIdentifier)
643 {
644     ASSERT(isMainThread());
645     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformDeleteIndex");
646
647     if (error.isNull()) {
648         auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
649         if (objectStoreInfo)
650             objectStoreInfo->deleteIndex(indexIdentifier);
651     }
652
653     performErrorCallback(callbackIdentifier, error);
654 }
655
656 void UniqueIDBDatabase::putOrAdd(const IDBRequestData& requestData, const IDBKeyData& keyData, const ThreadSafeDataBuffer& valueData, IndexedDB::ObjectStoreOverwriteMode overwriteMode, KeyDataCallback callback)
657 {
658     ASSERT(isMainThread());
659     LOG(IndexedDB, "(main) UniqueIDBDatabase::putOrAdd");
660
661     uint64_t callbackID = storeCallback(callback);
662     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performPutOrAdd, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyData, valueData, overwriteMode));
663 }
664
665 VM& UniqueIDBDatabase::databaseThreadVM()
666 {
667     ASSERT(!isMainThread());
668     static VM* vm = &VM::create().leakRef();
669     return *vm;
670 }
671
672 ExecState& UniqueIDBDatabase::databaseThreadExecState()
673 {
674     ASSERT(!isMainThread());
675
676     static NeverDestroyed<Strong<JSGlobalObject>> globalObject(databaseThreadVM(), JSGlobalObject::create(databaseThreadVM(), JSGlobalObject::createStructure(databaseThreadVM(), jsNull())));
677
678     RELEASE_ASSERT(globalObject.get()->globalExec());
679     return *globalObject.get()->globalExec();
680 }
681
682 void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, const ThreadSafeDataBuffer& originalRecordValue, IndexedDB::ObjectStoreOverwriteMode overwriteMode)
683 {
684     ASSERT(!isMainThread());
685     LOG(IndexedDB, "(db) UniqueIDBDatabase::performPutOrAdd");
686
687     ASSERT(m_backingStore);
688     ASSERT(objectStoreIdentifier);
689
690     IDBKeyData usedKey;
691     IDBError error;
692
693     auto objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
694     if (!objectStoreInfo) {
695         error = IDBError(IDBDatabaseException::InvalidStateError, ASCIILiteral("Object store cannot be found in the backing store"));
696         m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
697         return;
698     }
699
700     bool usedKeyIsGenerated = false;
701     ScopeGuard generatedKeyResetter;
702     if (objectStoreInfo->autoIncrement() && !keyData.isValid()) {
703         uint64_t keyNumber;
704         error = m_backingStore->generateKeyNumber(transactionIdentifier, objectStoreIdentifier, keyNumber);
705         if (!error.isNull()) {
706             m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
707             return;
708         }
709         
710         usedKey.setNumberValue(keyNumber);
711         usedKeyIsGenerated = true;
712         generatedKeyResetter.enable([this, transactionIdentifier, objectStoreIdentifier, keyNumber]() {
713             m_backingStore->revertGeneratedKeyNumber(transactionIdentifier, objectStoreIdentifier, keyNumber);
714         });
715     } else
716         usedKey = keyData;
717
718     if (overwriteMode == IndexedDB::ObjectStoreOverwriteMode::NoOverwrite) {
719         bool keyExists;
720         error = m_backingStore->keyExistsInObjectStore(transactionIdentifier, objectStoreIdentifier, usedKey, keyExists);
721         if (error.isNull() && keyExists)
722             error = IDBError(IDBDatabaseException::ConstraintError, ASCIILiteral("Key already exists in the object store"));
723
724         if (!error.isNull()) {
725             m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
726             return;
727         }
728     }
729
730     // 3.4.1.2 Object Store Storage Operation
731     // If ObjectStore has a key path and the key is autogenerated, then inject the key into the value
732     // using steps to assign a key to a value using a key path.
733     ThreadSafeDataBuffer injectedRecordValue;
734     if (usedKeyIsGenerated && !objectStoreInfo->keyPath().isNull()) {
735         JSLockHolder locker(databaseThreadVM());
736
737         JSValue value = deserializeIDBValueDataToJSValue(databaseThreadExecState(), originalRecordValue);
738         if (value.isUndefined()) {
739             m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(IDBDatabaseException::ConstraintError, ASCIILiteral("Unable to deserialize record value for record key injection")), usedKey));
740             return;
741         }
742
743         if (!injectIDBKeyIntoScriptValue(databaseThreadExecState(), usedKey, value, objectStoreInfo->keyPath())) {
744             m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(IDBDatabaseException::ConstraintError, ASCIILiteral("Unable to inject record key into record value")), usedKey));
745             return;
746         }
747
748         auto serializedValue = SerializedScriptValue::create(&databaseThreadExecState(), value, nullptr, nullptr);
749         if (databaseThreadExecState().hadException()) {
750             m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(IDBDatabaseException::ConstraintError, ASCIILiteral("Unable to serialize record value after injecting record key")), usedKey));
751             return;
752         }
753
754         injectedRecordValue = ThreadSafeDataBuffer::copyVector(serializedValue->data());
755     }
756
757     // 3.4.1 Object Store Storage Operation
758     // ...If a record already exists in store ...
759     // then remove the record from store using the steps for deleting records from an object store...
760     // This is important because formally deleting it from from the object store also removes it from the appropriate indexes.
761     error = m_backingStore->deleteRange(transactionIdentifier, objectStoreIdentifier, usedKey);
762     if (!error.isNull()) {
763         m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
764         return;
765     }
766
767     error = m_backingStore->addRecord(transactionIdentifier, *objectStoreInfo, usedKey, injectedRecordValue.data() ? injectedRecordValue : originalRecordValue);
768     if (!error.isNull()) {
769         m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
770         return;
771     }
772
773     if (overwriteMode != IndexedDB::ObjectStoreOverwriteMode::OverwriteForCursor && objectStoreInfo->autoIncrement() && keyData.type() == IndexedDB::KeyType::Number)
774         error = m_backingStore->maybeUpdateKeyGeneratorNumber(transactionIdentifier, objectStoreIdentifier, keyData.number());
775
776     generatedKeyResetter.disable();
777     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
778 }
779
780 void UniqueIDBDatabase::didPerformPutOrAdd(uint64_t callbackIdentifier, const IDBError& error, const IDBKeyData& resultKey)
781 {
782     ASSERT(isMainThread());
783     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformPutOrAdd");
784
785     performKeyDataCallback(callbackIdentifier, error, resultKey);
786 }
787
788 void UniqueIDBDatabase::getRecord(const IDBRequestData& requestData, const IDBKeyRangeData& range, GetResultCallback callback)
789 {
790     ASSERT(isMainThread());
791     LOG(IndexedDB, "(main) UniqueIDBDatabase::getRecord");
792
793     uint64_t callbackID = storeCallback(callback);
794
795     if (uint64_t indexIdentifier = requestData.indexIdentifier())
796         m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetIndexRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), indexIdentifier, requestData.indexRecordType(), range));
797     else
798         m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), range));
799 }
800
801 void UniqueIDBDatabase::performGetRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& keyRangeData)
802 {
803     ASSERT(!isMainThread());
804     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetRecord");
805
806     ASSERT(m_backingStore);
807
808     ThreadSafeDataBuffer valueData;
809     IDBError error = m_backingStore->getRecord(transactionIdentifier, objectStoreIdentifier, keyRangeData, valueData);
810
811     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetRecord, callbackIdentifier, error, valueData));
812 }
813
814 void UniqueIDBDatabase::performGetIndexRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType recordType, const IDBKeyRangeData& range)
815 {
816     ASSERT(!isMainThread());
817     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetIndexRecord");
818
819     ASSERT(m_backingStore);
820
821     IDBGetResult result;
822     IDBError error = m_backingStore->getIndexRecord(transactionIdentifier, objectStoreIdentifier, indexIdentifier, recordType, range, result);
823
824     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetRecord, callbackIdentifier, error, result));
825 }
826
827 void UniqueIDBDatabase::didPerformGetRecord(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& result)
828 {
829     ASSERT(isMainThread());
830     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformGetRecord");
831
832     performGetResultCallback(callbackIdentifier, error, result);
833 }
834
835 void UniqueIDBDatabase::getCount(const IDBRequestData& requestData, const IDBKeyRangeData& range, CountCallback callback)
836 {
837     ASSERT(isMainThread());
838     LOG(IndexedDB, "(main) UniqueIDBDatabase::getCount");
839
840     uint64_t callbackID = storeCallback(callback);
841     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetCount, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), requestData.indexIdentifier(), range));
842 }
843
844 void UniqueIDBDatabase::performGetCount(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData& keyRangeData)
845 {
846     ASSERT(!isMainThread());
847     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetCount");
848
849     ASSERT(m_backingStore);
850     ASSERT(objectStoreIdentifier);
851
852     uint64_t count;
853     IDBError error = m_backingStore->getCount(transactionIdentifier, objectStoreIdentifier, indexIdentifier, keyRangeData, count);
854
855     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetCount, callbackIdentifier, error, count));
856 }
857
858 void UniqueIDBDatabase::didPerformGetCount(uint64_t callbackIdentifier, const IDBError& error, uint64_t count)
859 {
860     ASSERT(isMainThread());
861     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformGetCount");
862
863     performCountCallback(callbackIdentifier, error, count);
864 }
865
866 void UniqueIDBDatabase::deleteRecord(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData, ErrorCallback callback)
867 {
868     ASSERT(isMainThread());
869     LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteRecord");
870
871     uint64_t callbackID = storeCallback(callback);
872     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performDeleteRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyRangeData));
873 }
874
875 void UniqueIDBDatabase::performDeleteRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range)
876 {
877     ASSERT(!isMainThread());
878     LOG(IndexedDB, "(db) UniqueIDBDatabase::performDeleteRecord");
879
880     IDBError error = m_backingStore->deleteRange(transactionIdentifier, objectStoreIdentifier, range);
881
882     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformDeleteRecord, callbackIdentifier, error));
883 }
884
885 void UniqueIDBDatabase::didPerformDeleteRecord(uint64_t callbackIdentifier, const IDBError& error)
886 {
887     ASSERT(isMainThread());
888     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformDeleteRecord");
889
890     performErrorCallback(callbackIdentifier, error);
891 }
892
893 void UniqueIDBDatabase::openCursor(const IDBRequestData& requestData, const IDBCursorInfo& info, GetResultCallback callback)
894 {
895     ASSERT(isMainThread());
896     LOG(IndexedDB, "(main) UniqueIDBDatabase::openCursor");
897
898     uint64_t callbackID = storeCallback(callback);
899     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performOpenCursor, callbackID, requestData.transactionIdentifier(), info));
900 }
901
902 void UniqueIDBDatabase::performOpenCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo& info)
903 {
904     ASSERT(!isMainThread());
905     LOG(IndexedDB, "(db) UniqueIDBDatabase::performOpenCursor");
906
907     IDBGetResult result;
908     IDBError error = m_backingStore->openCursor(transactionIdentifier, info, result);
909
910     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformOpenCursor, callbackIdentifier, error, result));
911 }
912
913 void UniqueIDBDatabase::didPerformOpenCursor(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& result)
914 {
915     ASSERT(isMainThread());
916     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformOpenCursor");
917
918     performGetResultCallback(callbackIdentifier, error, result);
919 }
920
921 void UniqueIDBDatabase::iterateCursor(const IDBRequestData& requestData, const IDBKeyData& key, unsigned long count, GetResultCallback callback)
922 {
923     ASSERT(isMainThread());
924     LOG(IndexedDB, "(main) UniqueIDBDatabase::iterateCursor");
925
926     uint64_t callbackID = storeCallback(callback);
927     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performIterateCursor, callbackID, requestData.transactionIdentifier(), requestData.cursorIdentifier(), key, count));
928 }
929
930 void UniqueIDBDatabase::performIterateCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, const IDBKeyData& key, unsigned long count)
931 {
932     ASSERT(!isMainThread());
933     LOG(IndexedDB, "(db) UniqueIDBDatabase::performIterateCursor");
934
935     IDBGetResult result;
936     IDBError error = m_backingStore->iterateCursor(transactionIdentifier, cursorIdentifier, key, count, result);
937
938     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformIterateCursor, callbackIdentifier, error, result));
939 }
940
941 void UniqueIDBDatabase::didPerformIterateCursor(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& result)
942 {
943     ASSERT(isMainThread());
944     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformIterateCursor");
945
946     performGetResultCallback(callbackIdentifier, error, result);
947 }
948
949 void UniqueIDBDatabase::commitTransaction(UniqueIDBDatabaseTransaction& transaction, ErrorCallback callback)
950 {
951     ASSERT(isMainThread());
952     LOG(IndexedDB, "(main) UniqueIDBDatabase::commitTransaction");
953
954     ASSERT(&transaction.databaseConnection().database() == this);
955
956     if (m_versionChangeTransaction == &transaction) {
957         ASSERT(!m_versionChangeDatabaseConnection || &m_versionChangeTransaction->databaseConnection() == m_versionChangeDatabaseConnection);
958         ASSERT(m_databaseInfo->version() == transaction.info().newVersion());
959
960         invokeOperationAndTransactionTimer();
961     }
962
963     uint64_t callbackID = storeCallback(callback);
964     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCommitTransaction, callbackID, transaction.info().identifier()));
965 }
966
967 void UniqueIDBDatabase::performCommitTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier)
968 {
969     ASSERT(!isMainThread());
970     LOG(IndexedDB, "(db) UniqueIDBDatabase::performCommitTransaction");
971
972     IDBError error = m_backingStore->commitTransaction(transactionIdentifier);
973     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCommitTransaction, callbackIdentifier, error, transactionIdentifier));
974 }
975
976 void UniqueIDBDatabase::didPerformCommitTransaction(uint64_t callbackIdentifier, const IDBError& error, const IDBResourceIdentifier& transactionIdentifier)
977 {
978     ASSERT(isMainThread());
979     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCommitTransaction");
980
981     inProgressTransactionCompleted(transactionIdentifier);
982
983     performErrorCallback(callbackIdentifier, error);
984 }
985
986 void UniqueIDBDatabase::abortTransaction(UniqueIDBDatabaseTransaction& transaction, ErrorCallback callback)
987 {
988     ASSERT(isMainThread());
989     LOG(IndexedDB, "(main) UniqueIDBDatabase::abortTransaction");
990
991     ASSERT(&transaction.databaseConnection().database() == this);
992
993     uint64_t callbackID = storeCallback(callback);
994     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performAbortTransaction, callbackID, transaction.info().identifier()));
995 }
996
997 void UniqueIDBDatabase::didFinishHandlingVersionChange(UniqueIDBDatabaseTransaction& transaction)
998 {
999     ASSERT(isMainThread());
1000     LOG(IndexedDB, "(main) UniqueIDBDatabase::didFinishHandlingVersionChange");
1001
1002     ASSERT(m_versionChangeTransaction);
1003     ASSERT_UNUSED(transaction, m_versionChangeTransaction == &transaction);
1004
1005     m_versionChangeTransaction = nullptr;
1006     m_versionChangeDatabaseConnection = nullptr;
1007
1008     invokeOperationAndTransactionTimer();
1009 }
1010
1011 void UniqueIDBDatabase::performAbortTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier)
1012 {
1013     ASSERT(!isMainThread());
1014     LOG(IndexedDB, "(db) UniqueIDBDatabase::performAbortTransaction");
1015
1016     IDBError error = m_backingStore->abortTransaction(transactionIdentifier);
1017     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformAbortTransaction, callbackIdentifier, error, transactionIdentifier));
1018 }
1019
1020 void UniqueIDBDatabase::didPerformAbortTransaction(uint64_t callbackIdentifier, const IDBError& error, const IDBResourceIdentifier& transactionIdentifier)
1021 {
1022     ASSERT(isMainThread());
1023     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformAbortTransaction");
1024
1025     if (m_versionChangeTransaction && m_versionChangeTransaction->info().identifier() == transactionIdentifier) {
1026         ASSERT(!m_versionChangeDatabaseConnection || &m_versionChangeTransaction->databaseConnection() == m_versionChangeDatabaseConnection);
1027         ASSERT(m_versionChangeTransaction->originalDatabaseInfo());
1028         m_databaseInfo = std::make_unique<IDBDatabaseInfo>(*m_versionChangeTransaction->originalDatabaseInfo());
1029     }
1030
1031     inProgressTransactionCompleted(transactionIdentifier);
1032
1033     performErrorCallback(callbackIdentifier, error);
1034 }
1035
1036 void UniqueIDBDatabase::transactionDestroyed(UniqueIDBDatabaseTransaction& transaction)
1037 {
1038     if (m_versionChangeTransaction == &transaction)
1039         m_versionChangeTransaction = nullptr;
1040 }
1041
1042 void UniqueIDBDatabase::connectionClosedFromClient(UniqueIDBDatabaseConnection& connection)
1043 {
1044     ASSERT(isMainThread());
1045     LOG(IndexedDB, "(main) UniqueIDBDatabase::connectionClosedFromClient");
1046
1047     if (m_versionChangeDatabaseConnection == &connection)
1048         m_versionChangeDatabaseConnection = nullptr;
1049
1050     ASSERT(m_openDatabaseConnections.contains(&connection));
1051
1052     Deque<RefPtr<UniqueIDBDatabaseTransaction>> pendingTransactions;
1053     while (!m_pendingTransactions.isEmpty()) {
1054         auto transaction = m_pendingTransactions.takeFirst();
1055         if (&transaction->databaseConnection() != &connection)
1056             pendingTransactions.append(WTFMove(transaction));
1057     }
1058
1059     if (!pendingTransactions.isEmpty())
1060         m_pendingTransactions.swap(pendingTransactions);
1061
1062     RefPtr<UniqueIDBDatabaseConnection> refConnection(&connection);
1063     m_openDatabaseConnections.remove(&connection);
1064
1065     if (m_currentOpenDBRequest)
1066         notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent(connection.identifier());
1067
1068     if (connection.hasNonFinishedTransactions()) {
1069         m_closePendingDatabaseConnections.add(WTFMove(refConnection));
1070         return;
1071     }
1072
1073     // Now that a database connection has closed, previously blocked operations might be runnable.
1074     invokeOperationAndTransactionTimer();
1075 }
1076
1077 void UniqueIDBDatabase::enqueueTransaction(Ref<UniqueIDBDatabaseTransaction>&& transaction)
1078 {
1079     LOG(IndexedDB, "UniqueIDBDatabase::enqueueTransaction - %s", transaction->info().loggingString().utf8().data());
1080
1081     ASSERT(transaction->info().mode() != IndexedDB::TransactionMode::VersionChange);
1082
1083     m_pendingTransactions.append(WTFMove(transaction));
1084
1085     invokeOperationAndTransactionTimer();
1086 }
1087
1088 void UniqueIDBDatabase::invokeOperationAndTransactionTimer()
1089 {
1090     LOG(IndexedDB, "UniqueIDBDatabase::invokeOperationAndTransactionTimer()");
1091     if (!m_operationAndTransactionTimer.isActive())
1092         m_operationAndTransactionTimer.startOneShot(0);
1093 }
1094
1095 void UniqueIDBDatabase::operationAndTransactionTimerFired()
1096 {
1097     LOG(IndexedDB, "(main) UniqueIDBDatabase::operationAndTransactionTimerFired");
1098
1099     RefPtr<UniqueIDBDatabase> protector(this);
1100
1101     // The current operation might require multiple attempts to handle, so try to
1102     // make further progress on it now.
1103     if (m_currentOpenDBRequest)
1104         handleCurrentOperation();
1105
1106     if (!m_currentOpenDBRequest)
1107         handleDatabaseOperations();
1108
1109     bool hadDeferredTransactions = false;
1110     auto transaction = takeNextRunnableTransaction(hadDeferredTransactions);
1111
1112     if (transaction) {
1113         m_inProgressTransactions.set(transaction->info().identifier(), transaction);
1114         for (auto objectStore : transaction->objectStoreIdentifiers()) {
1115             m_objectStoreTransactionCounts.add(objectStore);
1116             if (!transaction->isReadOnly()) {
1117                 m_objectStoreWriteTransactions.add(objectStore);
1118                 ASSERT(m_objectStoreTransactionCounts.count(objectStore) == 1);
1119             }
1120         }
1121
1122         activateTransactionInBackingStore(*transaction);
1123
1124         // If no transactions were deferred, it's possible we can start another transaction right now.
1125         if (!hadDeferredTransactions)
1126             invokeOperationAndTransactionTimer();
1127     }
1128 }
1129
1130 void UniqueIDBDatabase::activateTransactionInBackingStore(UniqueIDBDatabaseTransaction& transaction)
1131 {
1132     LOG(IndexedDB, "(main) UniqueIDBDatabase::activateTransactionInBackingStore");
1133
1134     RefPtr<UniqueIDBDatabase> self(this);
1135     RefPtr<UniqueIDBDatabaseTransaction> refTransaction(&transaction);
1136
1137     auto callback = [this, self, refTransaction](const IDBError& error) {
1138         refTransaction->didActivateInBackingStore(error);
1139     };
1140
1141     uint64_t callbackID = storeCallback(callback);
1142     m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performActivateTransactionInBackingStore, callbackID, transaction.info()));
1143 }
1144
1145 void UniqueIDBDatabase::performActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBTransactionInfo& info)
1146 {
1147     LOG(IndexedDB, "(db) UniqueIDBDatabase::performActivateTransactionInBackingStore");
1148
1149     IDBError error = m_backingStore->beginTransaction(info);
1150     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformActivateTransactionInBackingStore, callbackIdentifier, error));
1151 }
1152
1153 void UniqueIDBDatabase::didPerformActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBError& error)
1154 {
1155     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformActivateTransactionInBackingStore");
1156
1157     invokeOperationAndTransactionTimer();
1158
1159     performErrorCallback(callbackIdentifier, error);
1160 }
1161
1162 template<typename T> bool scopesOverlap(const T& aScopes, const Vector<uint64_t>& bScopes)
1163 {
1164     for (auto scope : bScopes) {
1165         if (aScopes.contains(scope))
1166             return true;
1167     }
1168
1169     return false;
1170 }
1171
1172 RefPtr<UniqueIDBDatabaseTransaction> UniqueIDBDatabase::takeNextRunnableTransaction(bool& hadDeferredTransactions)
1173 {
1174     hadDeferredTransactions = false;
1175     if (!m_backingStoreSupportsSimultaneousTransactions && !m_inProgressTransactions.isEmpty()) {
1176         LOG(IndexedDB, "UniqueIDBDatabase::takeNextRunnableTransaction - Backing store only supports 1 transaction, and we already have 1");
1177         return nullptr;
1178     }
1179
1180     Deque<RefPtr<UniqueIDBDatabaseTransaction>> deferredTransactions;
1181     RefPtr<UniqueIDBDatabaseTransaction> currentTransaction;
1182
1183     HashSet<uint64_t> deferredReadWriteScopes;
1184
1185     while (!m_pendingTransactions.isEmpty()) {
1186         currentTransaction = m_pendingTransactions.takeFirst();
1187
1188         switch (currentTransaction->info().mode()) {
1189         case IndexedDB::TransactionMode::ReadOnly: {
1190             bool hasOverlappingScopes = scopesOverlap(deferredReadWriteScopes, currentTransaction->objectStoreIdentifiers());
1191             hasOverlappingScopes |= scopesOverlap(m_objectStoreWriteTransactions, currentTransaction->objectStoreIdentifiers());
1192
1193             if (hasOverlappingScopes)
1194                 deferredTransactions.append(WTFMove(currentTransaction));
1195
1196             break;
1197         }
1198         case IndexedDB::TransactionMode::ReadWrite: {
1199             bool hasOverlappingScopes = scopesOverlap(m_objectStoreTransactionCounts, currentTransaction->objectStoreIdentifiers());
1200             hasOverlappingScopes |= scopesOverlap(deferredReadWriteScopes, currentTransaction->objectStoreIdentifiers());
1201
1202             if (hasOverlappingScopes) {
1203                 for (auto objectStore : currentTransaction->objectStoreIdentifiers())
1204                     deferredReadWriteScopes.add(objectStore);
1205                 deferredTransactions.append(WTFMove(currentTransaction));
1206             }
1207
1208             break;
1209         }
1210         case IndexedDB::TransactionMode::VersionChange:
1211             // Version change transactions should never be scheduled in the traditional manner.
1212             RELEASE_ASSERT_NOT_REACHED();
1213         }
1214
1215         // If we didn't defer the currentTransaction above, it can be run now.
1216         if (currentTransaction)
1217             break;
1218     }
1219
1220     hadDeferredTransactions = !deferredTransactions.isEmpty();
1221     if (!hadDeferredTransactions)
1222         return currentTransaction;
1223
1224     // Prepend the deferred transactions back on the beginning of the deque for future scheduling passes.
1225     while (!deferredTransactions.isEmpty())
1226         m_pendingTransactions.prepend(deferredTransactions.takeLast());
1227
1228     return currentTransaction;
1229 }
1230
1231 void UniqueIDBDatabase::inProgressTransactionCompleted(const IDBResourceIdentifier& transactionIdentifier)
1232 {
1233     auto transaction = m_inProgressTransactions.take(transactionIdentifier);
1234     ASSERT(transaction);
1235
1236     for (auto objectStore : transaction->objectStoreIdentifiers()) {
1237         if (!transaction->isReadOnly()) {
1238             m_objectStoreWriteTransactions.remove(objectStore);
1239             ASSERT(m_objectStoreTransactionCounts.count(objectStore) == 1);
1240         }
1241         m_objectStoreTransactionCounts.remove(objectStore);
1242     }
1243
1244     if (!transaction->databaseConnection().hasNonFinishedTransactions())
1245         m_closePendingDatabaseConnections.remove(&transaction->databaseConnection());
1246
1247     // Previously blocked operations might be runnable.
1248     invokeOperationAndTransactionTimer();
1249 }
1250
1251 void UniqueIDBDatabase::performErrorCallback(uint64_t callbackIdentifier, const IDBError& error)
1252 {
1253     auto callback = m_errorCallbacks.take(callbackIdentifier);
1254     ASSERT(callback);
1255     callback(error);
1256 }
1257
1258 void UniqueIDBDatabase::performKeyDataCallback(uint64_t callbackIdentifier, const IDBError& error, const IDBKeyData& resultKey)
1259 {
1260     auto callback = m_keyDataCallbacks.take(callbackIdentifier);
1261     ASSERT(callback);
1262     callback(error, resultKey);
1263 }
1264
1265 void UniqueIDBDatabase::performGetResultCallback(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& resultData)
1266 {
1267     auto callback = m_getResultCallbacks.take(callbackIdentifier);
1268     ASSERT(callback);
1269     callback(error, resultData);
1270 }
1271
1272 void UniqueIDBDatabase::performCountCallback(uint64_t callbackIdentifier, const IDBError& error, uint64_t count)
1273 {
1274     auto callback = m_countCallbacks.take(callbackIdentifier);
1275     ASSERT(callback);
1276     callback(error, count);
1277 }
1278
1279 } // namespace IDBServer
1280 } // namespace WebCore
1281
1282 #endif // ENABLE(INDEXED_DATABASE)