f93f4d85c7cc2c3ba0a7e85ba248b4cf533ecb96
[WebKit-https.git] / Source / WebKit2 / DatabaseProcess / IndexedDB / UniqueIDBDatabase.cpp
1 /*
2  * Copyright (C) 2013 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) && ENABLE(DATABASE_PROCESS)
30
31 #include "AsyncRequest.h"
32 #include "AsyncTask.h"
33 #include "DataReference.h"
34 #include "DatabaseProcess.h"
35 #include "DatabaseProcessIDBConnection.h"
36 #include "Logging.h"
37 #include "UniqueIDBDatabaseBackingStoreSQLite.h"
38 #include "WebCrossThreadCopier.h"
39 #include <WebCore/FileSystem.h>
40 #include <WebCore/IDBDatabaseMetadata.h>
41 #include <WebCore/IDBGetResult.h>
42 #include <WebCore/IDBKeyData.h>
43 #include <WebCore/IDBKeyRangeData.h>
44 #include <WebCore/SecurityOrigin.h>
45 #include <wtf/MainThread.h>
46 #include <wtf/text/WTFString.h>
47
48 using namespace WebCore;
49
50 namespace WebKit {
51
52 String UniqueIDBDatabase::calculateAbsoluteDatabaseFilename(const String& absoluteDatabaseDirectory)
53 {
54     return pathByAppendingComponent(absoluteDatabaseDirectory, "IndexedDB.sqlite3");
55 }
56
57 UniqueIDBDatabase::UniqueIDBDatabase(const UniqueIDBDatabaseIdentifier& identifier)
58     : m_identifier(identifier)
59     , m_acceptingNewRequests(true)
60     , m_didGetMetadataFromBackingStore(false)
61 {
62     m_inMemory = !canShareDatabases(identifier.openingOrigin(), identifier.mainFrameOrigin());
63     if (m_inMemory)
64         return;
65
66     // *********
67     // IMPORTANT: Do not change the directory structure for indexed databases on disk without first consulting a reviewer from Apple (<rdar://problem/17454712>)
68     // *********
69
70     // Each unique Indexed Database exists in a directory named for the database, which exists in a directory representing its opening origin.
71     m_databaseRelativeDirectory = pathByAppendingComponent(databaseFilenameIdentifier(identifier.openingOrigin()), filenameForDatabaseName());
72
73     DatabaseProcess::singleton().ensureIndexedDatabaseRelativePathExists(m_databaseRelativeDirectory);
74 }
75
76 UniqueIDBDatabase::~UniqueIDBDatabase()
77 {
78     ASSERT(!m_acceptingNewRequests);
79     ASSERT(m_pendingMetadataRequests.isEmpty());
80 }
81
82 String UniqueIDBDatabase::filenameForDatabaseName() const
83 {
84     ASSERT(!m_identifier.databaseName().isNull());
85
86     if (m_identifier.databaseName().isEmpty())
87         return "%00";
88
89     String filename = encodeForFileName(m_identifier.databaseName());
90     filename.replace('.', "%2E");
91
92     return filename;
93 }
94
95 String UniqueIDBDatabase::databaseFilenameIdentifier(const SecurityOriginData& originData) const
96 {
97     Ref<SecurityOrigin> securityOrigin(SecurityOrigin::create(originData.protocol, originData.host, originData.port));
98     return securityOrigin.get().databaseIdentifier();
99 }
100
101 bool UniqueIDBDatabase::canShareDatabases(const SecurityOriginData& openingOrigin, const SecurityOriginData& mainFrameOrigin) const
102 {
103     // For now, an origin's database access is predicated on equality with the other origin.
104     // We might need to make this more nuanced later.
105     return openingOrigin == mainFrameOrigin;
106 }
107
108 void UniqueIDBDatabase::registerConnection(DatabaseProcessIDBConnection& connection)
109 {
110     ASSERT(!m_connections.contains(&connection));
111     m_connections.add(&connection);
112 }
113
114 void UniqueIDBDatabase::unregisterConnection(DatabaseProcessIDBConnection& connection)
115 {
116     ASSERT(m_connections.contains(&connection));
117     resetAllTransactions(connection);
118     m_connections.remove(&connection);
119
120     if (m_connections.isEmpty() && m_pendingTransactionRollbacks.isEmpty()) {
121         shutdown(UniqueIDBDatabaseShutdownType::NormalShutdown);
122         DatabaseProcess::singleton().removeUniqueIDBDatabase(*this);
123     }
124 }
125
126 void UniqueIDBDatabase::shutdown(UniqueIDBDatabaseShutdownType type)
127 {
128     ASSERT(RunLoop::isMain());
129
130     if (!m_acceptingNewRequests)
131         return;
132
133     m_acceptingNewRequests = false;
134
135     // Balanced by an adoptRef in ::didShutdownBackingStore()
136     ref();
137
138     {
139         DeprecatedMutexLocker locker(m_databaseTaskMutex);
140         m_databaseTasks.clear();
141     }
142
143     postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::shutdownBackingStore, type, absoluteDatabaseDirectory()), DatabaseTaskType::Shutdown);
144 }
145
146 void UniqueIDBDatabase::shutdownBackingStore(UniqueIDBDatabaseShutdownType type, const String& databaseDirectory)
147 {
148     ASSERT(!RunLoop::isMain());
149
150     m_backingStore = nullptr;
151
152     if (type == UniqueIDBDatabaseShutdownType::DeleteShutdown) {
153         String dbFilename = UniqueIDBDatabase::calculateAbsoluteDatabaseFilename(databaseDirectory);
154         LOG(IDB, "UniqueIDBDatabase::shutdownBackingStore deleting file '%s' on disk", dbFilename.utf8().data());
155         deleteFile(dbFilename);
156         deleteEmptyDirectory(databaseDirectory);
157     }
158
159     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didShutdownBackingStore, type), DatabaseTaskType::Shutdown);
160 }
161
162 void UniqueIDBDatabase::didShutdownBackingStore(UniqueIDBDatabaseShutdownType type)
163 {
164     ASSERT(RunLoop::isMain());
165
166     // Balanced by a ref in ::shutdown()
167     RefPtr<UniqueIDBDatabase> protector(adoptRef(this));
168
169     // Empty out remaining main thread tasks.
170     while (performNextMainThreadTask()) {
171     }
172
173     // No more requests will be handled, so abort all outstanding requests.
174     for (const auto& request : m_pendingMetadataRequests)
175         request->requestAborted();
176     for (const auto& request : m_pendingTransactionRequests.values())
177         request->requestAborted();
178     for (const auto& request : m_pendingDatabaseTasks.values())
179         request->requestAborted();
180
181     m_pendingMetadataRequests.clear();
182     m_pendingTransactionRequests.clear();
183     m_pendingDatabaseTasks.clear();
184
185     if (m_pendingShutdownTask)
186         m_pendingShutdownTask->completeRequest(type);
187
188     m_pendingShutdownTask = nullptr;
189 }
190
191 void UniqueIDBDatabase::deleteDatabase(std::function<void (bool)> successCallback)
192 {
193     ASSERT(RunLoop::isMain());
194
195     if (!m_acceptingNewRequests) {
196         // Someone else has already shutdown this database, so we can't request a delete.
197         callOnMainThread([successCallback] {
198             successCallback(false);
199         });
200         return;
201     }
202
203     RefPtr<UniqueIDBDatabase> protector(this);
204     m_pendingShutdownTask = AsyncRequestImpl<UniqueIDBDatabaseShutdownType>::create([this, protector, successCallback](UniqueIDBDatabaseShutdownType type) {
205         // If the shutdown just completed was a Delete shutdown then we succeeded.
206         // If not report failure instead of trying again.
207         successCallback(type == UniqueIDBDatabaseShutdownType::DeleteShutdown);
208     }, [this, protector, successCallback] {
209         successCallback(false);
210     });
211
212     shutdown(UniqueIDBDatabaseShutdownType::DeleteShutdown);
213 }
214
215 void UniqueIDBDatabase::getOrEstablishIDBDatabaseMetadata(std::function<void (bool, const IDBDatabaseMetadata&)> completionCallback)
216 {
217     ASSERT(RunLoop::isMain());
218
219     if (!m_acceptingNewRequests) {
220         completionCallback(false, IDBDatabaseMetadata());
221         return;
222     }
223
224     // If we've already retrieved metadata from the backing store, return it now.
225     if (m_didGetMetadataFromBackingStore) {
226         if (m_metadata)
227             completionCallback(true, *m_metadata);
228         else
229             completionCallback(false, IDBDatabaseMetadata());
230
231         return;
232     }
233
234     // If this is the first unanswered metadata request, then later we need to
235     // post a task to open the backing store and get metadata.
236     bool shouldOpenBackingStore = m_pendingMetadataRequests.isEmpty();
237
238     // Then remember this metadata request to be answered later.
239     RefPtr<AsyncRequest> request = AsyncRequestImpl<>::create([completionCallback, this] {
240         completionCallback(!!m_metadata, m_metadata ? *m_metadata : IDBDatabaseMetadata());
241     }, [completionCallback] {
242         // The boolean flag to the completion callback represents whether the
243         // attempt to get/establish metadata succeeded or failed.
244         // Since we're aborting the attempt, it failed, so we always pass in false.
245         completionCallback(false, IDBDatabaseMetadata());
246     });
247
248     m_pendingMetadataRequests.append(request.release());
249
250     if (shouldOpenBackingStore)
251         postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::openBackingStoreAndReadMetadata, m_identifier, absoluteDatabaseDirectory()));
252 }
253
254 void UniqueIDBDatabase::openBackingStoreAndReadMetadata(const UniqueIDBDatabaseIdentifier& identifier, const String& databaseDirectory)
255 {
256     ASSERT(!RunLoop::isMain());
257     ASSERT(!m_backingStore);
258
259     if (m_inMemory) {
260         LOG_ERROR("Support for in-memory databases not yet implemented");
261         return;
262     }
263
264     m_backingStore = UniqueIDBDatabaseBackingStoreSQLite::create(identifier, databaseDirectory);
265     std::unique_ptr<IDBDatabaseMetadata> metadata = m_backingStore->getOrEstablishMetadata();
266
267     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didOpenBackingStoreAndReadMetadata, metadata ? *metadata : IDBDatabaseMetadata(), !!metadata));
268 }
269
270 void UniqueIDBDatabase::didOpenBackingStoreAndReadMetadata(const IDBDatabaseMetadata& metadata, bool success)
271 {
272     ASSERT(RunLoop::isMain());
273     ASSERT(!m_metadata);
274
275     m_didGetMetadataFromBackingStore = true;
276
277     if (success)
278         m_metadata = std::make_unique<IDBDatabaseMetadata>(metadata);
279
280     while (!m_pendingMetadataRequests.isEmpty()) {
281         RefPtr<AsyncRequest> request = m_pendingMetadataRequests.takeFirst();
282         request->completeRequest();
283     }
284 }
285
286 void UniqueIDBDatabase::openTransaction(const IDBIdentifier& transactionIdentifier, const Vector<int64_t>& objectStoreIDs, IndexedDB::TransactionMode mode, std::function<void (bool)> successCallback)
287 {
288     postTransactionOperation(transactionIdentifier, createAsyncTask(*this, &UniqueIDBDatabase::openBackingStoreTransaction, transactionIdentifier, objectStoreIDs, mode), successCallback);
289 }
290
291 void UniqueIDBDatabase::beginTransaction(const IDBIdentifier& transactionIdentifier, std::function<void (bool)> successCallback)
292 {
293     postTransactionOperation(transactionIdentifier, createAsyncTask(*this, &UniqueIDBDatabase::beginBackingStoreTransaction, transactionIdentifier), successCallback);
294 }
295
296 void UniqueIDBDatabase::commitTransaction(const IDBIdentifier& transactionIdentifier, std::function<void (bool)> successCallback)
297 {
298     postTransactionOperation(transactionIdentifier, createAsyncTask(*this, &UniqueIDBDatabase::commitBackingStoreTransaction, transactionIdentifier), successCallback);
299 }
300
301 void UniqueIDBDatabase::resetTransaction(const IDBIdentifier& transactionIdentifier, std::function<void (bool)> successCallback)
302 {
303     postTransactionOperation(transactionIdentifier, createAsyncTask(*this, &UniqueIDBDatabase::resetBackingStoreTransaction, transactionIdentifier), successCallback);
304 }
305
306 void UniqueIDBDatabase::rollbackTransaction(const IDBIdentifier& transactionIdentifier, std::function<void (bool)> successCallback)
307 {
308     postTransactionOperation(transactionIdentifier, createAsyncTask(*this, &UniqueIDBDatabase::rollbackBackingStoreTransaction, transactionIdentifier), successCallback);
309 }
310
311 void UniqueIDBDatabase::postTransactionOperation(const IDBIdentifier& transactionIdentifier, std::unique_ptr<AsyncTask> task, std::function<void (bool)> successCallback)
312 {
313     ASSERT(RunLoop::isMain());
314
315     if (!m_acceptingNewRequests) {
316         successCallback(false);
317         return;
318     }
319
320     if (m_pendingTransactionRequests.contains(transactionIdentifier)) {
321         LOG_ERROR("Attempting to queue an operation for a transaction that already has an operation pending. Each transaction should only have one operation pending at a time.");
322         successCallback(false);
323         return;
324     }
325
326     postDatabaseTask(WTF::move(task));
327
328     RefPtr<AsyncRequest> request = AsyncRequestImpl<bool>::create([successCallback](bool success) {
329         successCallback(success);
330     }, [successCallback] {
331         successCallback(false);
332     });
333
334     m_pendingTransactionRequests.add(transactionIdentifier, request.release());
335 }
336
337 void UniqueIDBDatabase::didCompleteTransactionOperation(const IDBIdentifier& transactionIdentifier, bool success)
338 {
339     ASSERT(RunLoop::isMain());
340
341     RefPtr<AsyncRequest> request = m_pendingTransactionRequests.take(transactionIdentifier);
342
343     if (request)
344         request->completeRequest(success);
345
346     if (m_pendingTransactionRollbacks.contains(transactionIdentifier))
347         finalizeRollback(transactionIdentifier);
348 }
349
350 void UniqueIDBDatabase::changeDatabaseVersion(const IDBIdentifier& transactionIdentifier, uint64_t newVersion, std::function<void (bool)> successCallback)
351 {
352     ASSERT(RunLoop::isMain());
353
354     if (!m_acceptingNewRequests) {
355         successCallback(false);
356         return;
357     }
358
359     uint64_t oldVersion = m_metadata->version;
360     m_metadata->version = newVersion;
361
362     RefPtr<AsyncRequest> request = AsyncRequestImpl<bool>::create([this, oldVersion, successCallback](bool success) {
363         if (!success)
364             m_metadata->version = oldVersion;
365         successCallback(success);
366     }, [this, oldVersion, successCallback] {
367         m_metadata->version = oldVersion;
368         successCallback(false);
369     });
370
371     uint64_t requestID = request->requestID();
372     m_pendingDatabaseTasks.add(requestID, request.release());
373
374     postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::changeDatabaseVersionInBackingStore, requestID, transactionIdentifier, newVersion));
375 }
376
377 void UniqueIDBDatabase::didChangeDatabaseVersion(uint64_t requestID, bool success)
378 {
379     didCompleteBoolRequest(requestID, success);
380 }
381
382 void UniqueIDBDatabase::didCreateObjectStore(uint64_t requestID, bool success)
383 {
384     didCompleteBoolRequest(requestID, success);
385 }
386
387 void UniqueIDBDatabase::didDeleteObjectStore(uint64_t requestID, bool success)
388 {
389     didCompleteBoolRequest(requestID, success);
390 }
391
392 void UniqueIDBDatabase::didClearObjectStore(uint64_t requestID, bool success)
393 {
394     didCompleteBoolRequest(requestID, success);
395 }
396
397 void UniqueIDBDatabase::didCreateIndex(uint64_t requestID, bool success)
398 {
399     didCompleteBoolRequest(requestID, success);
400 }
401
402 void UniqueIDBDatabase::didDeleteIndex(uint64_t requestID, bool success)
403 {
404     didCompleteBoolRequest(requestID, success);
405 }
406
407 void UniqueIDBDatabase::didCompleteBoolRequest(uint64_t requestID, bool success)
408 {
409     m_pendingDatabaseTasks.take(requestID).get().completeRequest(success);
410 }
411
412 void UniqueIDBDatabase::createObjectStore(const IDBIdentifier& transactionIdentifier, const IDBObjectStoreMetadata& metadata, std::function<void (bool)> successCallback)
413 {
414     ASSERT(RunLoop::isMain());
415
416     if (!m_acceptingNewRequests) {
417         successCallback(false);
418         return;
419     }
420
421     ASSERT(!m_metadata->objectStores.contains(metadata.id));
422     m_metadata->objectStores.set(metadata.id, metadata);
423     int64_t addedObjectStoreID = metadata.id;
424
425     RefPtr<AsyncRequest> request = AsyncRequestImpl<bool>::create([this, addedObjectStoreID, successCallback](bool success) {
426         if (!success)
427             m_metadata->objectStores.remove(addedObjectStoreID);
428         successCallback(success);
429     }, [this, addedObjectStoreID, successCallback] {
430         m_metadata->objectStores.remove(addedObjectStoreID);
431         successCallback(false);
432     });
433
434     uint64_t requestID = request->requestID();
435     m_pendingDatabaseTasks.add(requestID, request.release());
436
437     postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::createObjectStoreInBackingStore, requestID, transactionIdentifier, metadata));
438 }
439
440 void UniqueIDBDatabase::deleteObjectStore(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, std::function<void (bool)> successCallback)
441 {
442     ASSERT(RunLoop::isMain());
443
444     if (!m_acceptingNewRequests) {
445         successCallback(false);
446         return;
447     }
448
449     ASSERT(m_metadata->objectStores.contains(objectStoreID));
450     IDBObjectStoreMetadata metadata = m_metadata->objectStores.take(objectStoreID);
451
452     RefPtr<AsyncRequest> request = AsyncRequestImpl<bool>::create([this, metadata, successCallback](bool success) {
453         if (!success)
454             m_metadata->objectStores.set(metadata.id, metadata);
455         successCallback(success);
456     }, [this, metadata, successCallback] {
457         m_metadata->objectStores.set(metadata.id, metadata);
458         successCallback(false);
459     });
460
461     uint64_t requestID = request->requestID();
462     m_pendingDatabaseTasks.add(requestID, request.release());
463
464     postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::deleteObjectStoreInBackingStore, requestID, transactionIdentifier, objectStoreID));
465 }
466
467 void UniqueIDBDatabase::clearObjectStore(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, std::function<void (bool)> successCallback)
468 {
469     ASSERT(RunLoop::isMain());
470
471     if (!m_acceptingNewRequests) {
472         successCallback(false);
473         return;
474     }
475
476     ASSERT(m_metadata->objectStores.contains(objectStoreID));
477
478     RefPtr<AsyncRequest> request = AsyncRequestImpl<bool>::create([this, successCallback](bool success) {
479         successCallback(success);
480     }, [this, successCallback] {
481         successCallback(false);
482     });
483
484     uint64_t requestID = request->requestID();
485     m_pendingDatabaseTasks.add(requestID, request.release());
486
487     postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::clearObjectStoreInBackingStore, requestID, transactionIdentifier, objectStoreID));
488 }
489
490 void UniqueIDBDatabase::createIndex(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const IDBIndexMetadata& metadata, std::function<void (bool)> successCallback)
491 {
492     ASSERT(RunLoop::isMain());
493
494     if (!m_acceptingNewRequests) {
495         successCallback(false);
496         return;
497     }
498
499     ASSERT(m_metadata->objectStores.contains(objectStoreID));
500     ASSERT(!m_metadata->objectStores.get(objectStoreID).indexes.contains(metadata.id));
501     m_metadata->objectStores.get(objectStoreID).indexes.set(metadata.id, metadata);
502     int64_t addedIndexID = metadata.id;
503
504     RefPtr<AsyncRequest> request = AsyncRequestImpl<bool>::create([this, objectStoreID, addedIndexID, successCallback](bool success) {
505         if (!success) {
506             auto objectStoreFind = m_metadata->objectStores.find(objectStoreID);
507             if (objectStoreFind != m_metadata->objectStores.end())
508                 objectStoreFind->value.indexes.remove(addedIndexID);
509         }
510         successCallback(success);
511     }, [this, objectStoreID, addedIndexID, successCallback] {
512         auto objectStoreFind = m_metadata->objectStores.find(objectStoreID);
513         if (objectStoreFind != m_metadata->objectStores.end())
514             objectStoreFind->value.indexes.remove(addedIndexID);
515         successCallback(false);
516     });
517
518     uint64_t requestID = request->requestID();
519     m_pendingDatabaseTasks.add(requestID, request.release());
520
521     postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::createIndexInBackingStore, requestID, transactionIdentifier, objectStoreID, metadata));
522 }
523
524 void UniqueIDBDatabase::deleteIndex(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, std::function<void (bool)> successCallback)
525 {
526     ASSERT(RunLoop::isMain());
527
528     if (!m_acceptingNewRequests) {
529         successCallback(false);
530         return;
531     }
532
533     ASSERT(m_metadata->objectStores.contains(objectStoreID));
534     ASSERT(m_metadata->objectStores.get(objectStoreID).indexes.contains(indexID));
535
536     IDBIndexMetadata metadata = m_metadata->objectStores.get(objectStoreID).indexes.take(indexID);
537
538     RefPtr<AsyncRequest> request = AsyncRequestImpl<bool>::create([this, objectStoreID, metadata, successCallback](bool success) {
539         if (!success) {
540             auto objectStoreFind = m_metadata->objectStores.find(objectStoreID);
541             if (objectStoreFind != m_metadata->objectStores.end())
542                 objectStoreFind->value.indexes.set(metadata.id, metadata);
543         }
544         successCallback(success);
545     }, [this, objectStoreID, metadata, successCallback] {
546         auto objectStoreFind = m_metadata->objectStores.find(objectStoreID);
547         if (objectStoreFind != m_metadata->objectStores.end())
548             objectStoreFind->value.indexes.set(metadata.id, metadata);
549         successCallback(false);
550     });
551
552     uint64_t requestID = request->requestID();
553     m_pendingDatabaseTasks.add(requestID, request.release());
554
555     postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::deleteIndexInBackingStore, requestID, transactionIdentifier, objectStoreID, indexID));
556 }
557
558 void UniqueIDBDatabase::putRecord(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const IDBKeyData& keyData, const IPC::DataReference& value, int64_t putMode, const Vector<int64_t>& indexIDs, const Vector<Vector<IDBKeyData>>& indexKeys, std::function<void (const IDBKeyData&, uint32_t, const String&)> callback)
559 {
560     ASSERT(RunLoop::isMain());
561
562     if (!m_acceptingNewRequests) {
563         callback(IDBKeyData(), INVALID_STATE_ERR, "Unable to put record into database because it has shut down");
564         return;
565     }
566
567     ASSERT(m_metadata->objectStores.contains(objectStoreID));
568
569     RefPtr<AsyncRequest> request = AsyncRequestImpl<IDBKeyData, uint32_t, String>::create([this, callback](const IDBKeyData& keyData, uint32_t errorCode, const String& errorMessage) {
570         callback(keyData, errorCode, errorMessage);
571     }, [this, callback] {
572         callback(IDBKeyData(), INVALID_STATE_ERR, "Unable to put record into database");
573     });
574
575     uint64_t requestID = request->requestID();
576     m_pendingDatabaseTasks.add(requestID, request.release());
577
578     postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::putRecordInBackingStore, requestID, transactionIdentifier, m_metadata->objectStores.get(objectStoreID), keyData, value.vector(), putMode, indexIDs, indexKeys));
579 }
580
581 void UniqueIDBDatabase::getRecord(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, const IDBKeyRangeData& keyRangeData, IndexedDB::CursorType cursorType, std::function<void (const IDBGetResult&, uint32_t, const String&)> callback)
582 {
583     ASSERT(RunLoop::isMain());
584
585     if (!m_acceptingNewRequests) {
586         callback(IDBGetResult(), INVALID_STATE_ERR, "Unable to get record from database because it has shut down");
587         return;
588     }
589
590     ASSERT(m_metadata->objectStores.contains(objectStoreID));
591
592     RefPtr<AsyncRequest> request = AsyncRequestImpl<IDBGetResult, uint32_t, String>::create([this, callback](const IDBGetResult& result, uint32_t errorCode, const String& errorMessage) {
593         callback(result, errorCode, errorMessage);
594     }, [this, callback] {
595         callback(IDBGetResult(), INVALID_STATE_ERR, "Unable to get record from database");
596     });
597
598     uint64_t requestID = request->requestID();
599     m_pendingDatabaseTasks.add(requestID, request.release());
600
601     postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::getRecordFromBackingStore, requestID, transactionIdentifier, m_metadata->objectStores.get(objectStoreID), indexID, keyRangeData, cursorType));
602 }
603
604 void UniqueIDBDatabase::openCursor(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, IndexedDB::CursorDirection cursorDirection, IndexedDB::CursorType cursorType, IDBDatabaseBackend::TaskType taskType, const IDBKeyRangeData& keyRangeData, std::function<void (int64_t, const IDBKeyData&, const IDBKeyData&, PassRefPtr<SharedBuffer>, uint32_t, const String&)> callback)
605 {
606     ASSERT(RunLoop::isMain());
607
608     if (!m_acceptingNewRequests) {
609         callback(0, nullptr, nullptr, nullptr, INVALID_STATE_ERR, "Unable to open cursor in database because it has shut down");
610         return;
611     }
612
613     ASSERT(m_metadata->objectStores.contains(objectStoreID));
614
615     RefPtr<AsyncRequest> request = AsyncRequestImpl<int64_t, IDBKeyData, IDBKeyData, PassRefPtr<SharedBuffer>, uint32_t, String>::create([this, callback](int64_t cursorID, const IDBKeyData& key, const IDBKeyData& primaryKey, PassRefPtr<SharedBuffer> value, uint32_t errorCode, const String& errorMessage) {
616         callback(cursorID, key, primaryKey, value, errorCode, errorMessage);
617     }, [this, callback] {
618         callback(0, nullptr, nullptr, nullptr, INVALID_STATE_ERR, "Unable to get record from database");
619     });
620
621     uint64_t requestID = request->requestID();
622     m_pendingDatabaseTasks.add(requestID, request.release());
623
624     postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::openCursorInBackingStore, requestID, transactionIdentifier, objectStoreID, indexID, cursorDirection, cursorType, taskType, keyRangeData));
625 }
626
627 void UniqueIDBDatabase::cursorAdvance(const IDBIdentifier& cursorIdentifier, uint64_t count, std::function<void (const IDBKeyData&, const IDBKeyData&, PassRefPtr<SharedBuffer>, uint32_t, const String&)> callback)
628 {
629     ASSERT(RunLoop::isMain());
630
631     if (!m_acceptingNewRequests) {
632         callback(nullptr, nullptr, nullptr, INVALID_STATE_ERR, "Unable to advance cursor in database because it has shut down");
633         return;
634     }
635
636     RefPtr<AsyncRequest> request = AsyncRequestImpl<IDBKeyData, IDBKeyData, PassRefPtr<SharedBuffer>, uint32_t, String>::create([this, callback](const IDBKeyData& key, const IDBKeyData& primaryKey, PassRefPtr<SharedBuffer> value, uint32_t errorCode, const String& errorMessage) {
637         callback(key, primaryKey, value, errorCode, errorMessage);
638     }, [this, callback] {
639         callback(nullptr, nullptr, nullptr, INVALID_STATE_ERR, "Unable to advance cursor in database");
640     });
641
642     uint64_t requestID = request->requestID();
643     m_pendingDatabaseTasks.add(requestID, request.release());
644
645     postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::advanceCursorInBackingStore, requestID, cursorIdentifier, count));
646 }
647
648 void UniqueIDBDatabase::cursorIterate(const IDBIdentifier& cursorIdentifier, const IDBKeyData& key, std::function<void (const IDBKeyData&, const IDBKeyData&, PassRefPtr<SharedBuffer>, uint32_t, const String&)> callback)
649 {
650     ASSERT(RunLoop::isMain());
651
652     if (!m_acceptingNewRequests) {
653         callback(nullptr, nullptr, nullptr, INVALID_STATE_ERR, "Unable to iterate cursor in database because it has shut down");
654         return;
655     }
656
657     RefPtr<AsyncRequest> request = AsyncRequestImpl<IDBKeyData, IDBKeyData, PassRefPtr<SharedBuffer>, uint32_t, String>::create([this, callback](const IDBKeyData& key, const IDBKeyData& primaryKey, PassRefPtr<SharedBuffer> value, uint32_t errorCode, const String& errorMessage) {
658         callback(key, primaryKey, value, errorCode, errorMessage);
659     }, [this, callback] {
660         callback(nullptr, nullptr, nullptr, INVALID_STATE_ERR, "Unable to iterate cursor in database");
661     });
662
663     uint64_t requestID = request->requestID();
664     m_pendingDatabaseTasks.add(requestID, request.release());
665
666     postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::iterateCursorInBackingStore, requestID, cursorIdentifier, key));
667 }
668
669 void UniqueIDBDatabase::count(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, const IDBKeyRangeData& keyRangeData, std::function<void (int64_t, uint32_t, const String&)> callback)
670 {
671     ASSERT(RunLoop::isMain());
672
673     if (!m_acceptingNewRequests) {
674         callback(0, INVALID_STATE_ERR, "Unable to get count from database because it has shut down");
675         return;
676     }
677
678     RefPtr<AsyncRequest> request = AsyncRequestImpl<int64_t, uint32_t, String>::create([this, callback](int64_t count, uint32_t errorCode, const String& errorMessage) {
679         callback(count, errorCode, errorMessage);
680     }, [this, callback] {
681         callback(0, INVALID_STATE_ERR, "Unable to get count from database");
682     });
683
684     uint64_t requestID = request->requestID();
685     m_pendingDatabaseTasks.add(requestID, request.release());
686
687     postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::countInBackingStore, requestID, transactionIdentifier, objectStoreID, indexID, keyRangeData));
688 }
689
690 void UniqueIDBDatabase::deleteRange(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const IDBKeyRangeData& keyRangeData, std::function<void (uint32_t, const String&)> callback)
691 {
692     ASSERT(RunLoop::isMain());
693
694     if (!m_acceptingNewRequests) {
695         callback(INVALID_STATE_ERR, "Unable to deleteRange from database because it has shut down");
696         return;
697     }
698
699     RefPtr<AsyncRequest> request = AsyncRequestImpl<uint32_t, String>::create([callback](uint32_t errorCode, const String& errorMessage) {
700         callback(errorCode, errorMessage);
701     }, [callback] {
702         callback(INVALID_STATE_ERR, "Unable to deleteRange from database");
703     });
704
705     uint64_t requestID = request->requestID();
706     m_pendingDatabaseTasks.add(requestID, request.release());
707
708     postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::deleteRangeInBackingStore, requestID, transactionIdentifier, objectStoreID, keyRangeData));
709 }
710
711 void UniqueIDBDatabase::openBackingStoreTransaction(const IDBIdentifier& transactionIdentifier, const Vector<int64_t>& objectStoreIDs, IndexedDB::TransactionMode mode)
712 {
713     ASSERT(!RunLoop::isMain());
714     ASSERT(m_backingStore);
715
716     bool success = m_backingStore->establishTransaction(transactionIdentifier, objectStoreIDs, mode);
717
718     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didEstablishTransaction, transactionIdentifier, success));
719     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didCompleteTransactionOperation, transactionIdentifier, success));
720 }
721
722 void UniqueIDBDatabase::beginBackingStoreTransaction(const IDBIdentifier& transactionIdentifier)
723 {
724     ASSERT(!RunLoop::isMain());
725     ASSERT(m_backingStore);
726
727     bool success = m_backingStore->beginTransaction(transactionIdentifier);
728
729     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didCompleteTransactionOperation, transactionIdentifier, success));
730 }
731
732 void UniqueIDBDatabase::commitBackingStoreTransaction(const IDBIdentifier& transactionIdentifier)
733 {
734     ASSERT(!RunLoop::isMain());
735     ASSERT(m_backingStore);
736
737     bool success = m_backingStore->commitTransaction(transactionIdentifier);
738
739     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didCompleteTransactionOperation, transactionIdentifier, success));
740 }
741
742 void UniqueIDBDatabase::resetBackingStoreTransaction(const IDBIdentifier& transactionIdentifier)
743 {
744     ASSERT(!RunLoop::isMain());
745     ASSERT(m_backingStore);
746
747     bool success = m_backingStore->resetTransaction(transactionIdentifier);
748
749     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didResetTransaction, transactionIdentifier, success));
750     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didCompleteTransactionOperation, transactionIdentifier, success));
751 }
752
753 void UniqueIDBDatabase::rollbackBackingStoreTransaction(const IDBIdentifier& transactionIdentifier)
754 {
755     ASSERT(!RunLoop::isMain());
756     ASSERT(m_backingStore);
757
758     bool success = m_backingStore->rollbackTransaction(transactionIdentifier);
759
760     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didCompleteTransactionOperation, transactionIdentifier, success));
761 }
762
763 void UniqueIDBDatabase::changeDatabaseVersionInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, uint64_t newVersion)
764 {
765     ASSERT(!RunLoop::isMain());
766     ASSERT(m_backingStore);
767
768     bool success = m_backingStore->changeDatabaseVersion(transactionIdentifier, newVersion);
769
770     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didChangeDatabaseVersion, requestID, success));
771 }
772
773 void UniqueIDBDatabase::createObjectStoreInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, const IDBObjectStoreMetadata& metadata)
774 {
775     ASSERT(!RunLoop::isMain());
776     ASSERT(m_backingStore);
777
778     bool success = m_backingStore->createObjectStore(transactionIdentifier, metadata);
779
780     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didCreateObjectStore, requestID, success));
781 }
782
783 void UniqueIDBDatabase::deleteObjectStoreInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID)
784 {
785     ASSERT(!RunLoop::isMain());
786     ASSERT(m_backingStore);
787
788     bool success = m_backingStore->deleteObjectStore(transactionIdentifier, objectStoreID);
789
790     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didDeleteObjectStore, requestID, success));
791 }
792
793 void UniqueIDBDatabase::clearObjectStoreInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID)
794 {
795     ASSERT(!RunLoop::isMain());
796     ASSERT(m_backingStore);
797
798     bool success = m_backingStore->clearObjectStore(transactionIdentifier, objectStoreID);
799
800     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didClearObjectStore, requestID, success));
801 }
802
803 void UniqueIDBDatabase::createIndexInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const IDBIndexMetadata& metadata)
804 {
805     ASSERT(!RunLoop::isMain());
806     ASSERT(m_backingStore);
807
808     bool success = m_backingStore->createIndex(transactionIdentifier, objectStoreID, metadata);
809
810     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didCreateIndex, requestID, success));
811 }
812
813 void UniqueIDBDatabase::deleteIndexInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID)
814 {
815     ASSERT(!RunLoop::isMain());
816     ASSERT(m_backingStore);
817
818     bool success = m_backingStore->deleteIndex(transactionIdentifier, objectStoreID, indexID);
819
820     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didDeleteIndex, requestID, success));
821 }
822
823 void UniqueIDBDatabase::putRecordInBackingStore(uint64_t requestID, const IDBIdentifier& transaction, const IDBObjectStoreMetadata& objectStoreMetadata, const IDBKeyData& inputKeyData, const Vector<uint8_t>& value, int64_t putMode, const Vector<int64_t>& indexIDs, const Vector<Vector<IDBKeyData>>& indexKeys)
824 {
825     ASSERT(!RunLoop::isMain());
826     ASSERT(m_backingStore);
827
828     bool keyWasGenerated = false;
829     IDBKeyData key;
830     int64_t keyNumber = 0;
831
832     if (putMode != IDBDatabaseBackend::CursorUpdate && objectStoreMetadata.autoIncrement && inputKeyData.isNull) {
833         if (!m_backingStore->generateKeyNumber(transaction, objectStoreMetadata.id, keyNumber)) {
834             postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didPutRecordInBackingStore, requestID, IDBKeyData(), IDBDatabaseException::UnknownError, ASCIILiteral("Internal backing store error checking for key existence")));
835             return;
836         }
837         key.setNumberValue(keyNumber);
838         keyWasGenerated = true;
839     } else
840         key = inputKeyData;
841
842     if (putMode == IDBDatabaseBackend::AddOnly) {
843         bool keyExists;
844         if (!m_backingStore->keyExistsInObjectStore(transaction, objectStoreMetadata.id, key, keyExists)) {
845             postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didPutRecordInBackingStore, requestID, IDBKeyData(), IDBDatabaseException::UnknownError, ASCIILiteral("Internal backing store error checking for key existence")));
846             return;
847         }
848         if (keyExists) {
849             postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didPutRecordInBackingStore, requestID, IDBKeyData(), IDBDatabaseException::ConstraintError, ASCIILiteral("Key already exists in the object store")));
850             return;
851         }
852     }
853
854     // The spec says that even if we're about to overwrite the record, perform the steps to delete it first.
855     // This is important because formally deleting it from from the object store also removes it from the appropriate indexes.
856     if (!m_backingStore->deleteRecord(transaction, objectStoreMetadata.id, key)) {
857         postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didPutRecordInBackingStore, requestID, IDBKeyData(), IDBDatabaseException::UnknownError, ASCIILiteral("Replacing an existing key in backing store, unable to delete previous record.")));
858         return;
859     }
860
861     if (!m_backingStore->putRecord(transaction, objectStoreMetadata.id, key, value.data(), value.size())) {
862         postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didPutRecordInBackingStore, requestID, IDBKeyData(), IDBDatabaseException::UnknownError, ASCIILiteral("Internal backing store error putting a record")));
863         return;
864     }
865
866     ASSERT(indexIDs.size() == indexKeys.size());
867     for (size_t i = 0; i < indexIDs.size(); ++i) {
868         for (size_t j = 0; j < indexKeys[i].size(); ++j) {
869             if (!m_backingStore->putIndexRecord(transaction, objectStoreMetadata.id, indexIDs[i], key, indexKeys[i][j])) {
870                 postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didPutRecordInBackingStore, requestID, IDBKeyData(), IDBDatabaseException::UnknownError, ASCIILiteral("Internal backing store error writing index key")));
871                 return;
872             }
873         }
874     }
875
876     m_backingStore->notifyCursorsOfChanges(transaction, objectStoreMetadata.id);
877
878     if (putMode != IDBDatabaseBackend::CursorUpdate && objectStoreMetadata.autoIncrement && key.type == IDBKey::NumberType) {
879         if (!m_backingStore->updateKeyGeneratorNumber(transaction, objectStoreMetadata.id, keyNumber, keyWasGenerated)) {
880             postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didPutRecordInBackingStore, requestID, IDBKeyData(), IDBDatabaseException::UnknownError, ASCIILiteral("Internal backing store error updating key generator")));
881             return;
882         }
883     }
884
885     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didPutRecordInBackingStore, requestID, key, 0, String(StringImpl::empty())));
886 }
887
888 void UniqueIDBDatabase::didPutRecordInBackingStore(uint64_t requestID, const IDBKeyData& keyData, uint32_t errorCode, const String& errorMessage)
889 {
890     m_pendingDatabaseTasks.take(requestID).get().completeRequest(keyData, errorCode, errorMessage);
891 }
892
893 void UniqueIDBDatabase::getRecordFromBackingStore(uint64_t requestID, const IDBIdentifier& transaction, const IDBObjectStoreMetadata& objectStoreMetadata, int64_t indexID, const IDBKeyRangeData& keyRangeData, IndexedDB::CursorType cursorType)
894 {
895     ASSERT(!RunLoop::isMain());
896     ASSERT(m_backingStore);
897
898     RefPtr<IDBKeyRange> keyRange = keyRangeData.maybeCreateIDBKeyRange();
899     ASSERT(keyRange);
900     if (!keyRange) {
901         postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didGetRecordFromBackingStore, requestID, IDBGetResult(), IDBDatabaseException::UnknownError, ASCIILiteral("Invalid IDBKeyRange requested from backing store")));
902         return;
903     }
904
905     if (indexID == IDBIndexMetadata::InvalidId) {
906         // IDBObjectStore get record
907         RefPtr<SharedBuffer> result;
908
909         if (keyRange->isOnlyKey()) {
910             if (!m_backingStore->getKeyRecordFromObjectStore(transaction, objectStoreMetadata.id, *keyRange->lower(), result))
911                 postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didGetRecordFromBackingStore, requestID, IDBGetResult(), IDBDatabaseException::UnknownError, ASCIILiteral("Failed to get key record from object store in backing store")));
912             else {
913                 IDBGetResult getResult = result ? IDBGetResult(result.release(), keyRange->lower(), objectStoreMetadata.keyPath) : IDBGetResult();
914                 postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didGetRecordFromBackingStore, requestID, getResult, 0, String(StringImpl::empty())));
915             }
916
917             return;
918         }
919
920         RefPtr<IDBKey> resultKey;
921
922         if (!m_backingStore->getKeyRangeRecordFromObjectStore(transaction, objectStoreMetadata.id, *keyRange, result, resultKey))
923             postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didGetRecordFromBackingStore, requestID, IDBGetResult(), IDBDatabaseException::UnknownError, ASCIILiteral("Failed to get key range record from object store in backing store")));
924         else {
925             IDBGetResult getResult = result ? IDBGetResult(result.release(), resultKey.release(), objectStoreMetadata.keyPath) : IDBGetResult();
926             postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didGetRecordFromBackingStore, requestID, getResult, 0, String(StringImpl::empty())));
927         }
928
929         return;
930     }
931
932     // IDBIndex get record
933
934     IDBGetResult result;
935     if (!m_backingStore->getIndexRecord(transaction, objectStoreMetadata.id, indexID, keyRangeData, cursorType, result)) {
936         postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didGetRecordFromBackingStore, requestID, IDBGetResult(), IDBDatabaseException::UnknownError, ASCIILiteral("Failed to get index record from backing store")));
937         return;
938     }
939
940     // We must return a key path to know how to inject the result key into the result value object.
941     result.keyPath = objectStoreMetadata.keyPath;
942
943     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didGetRecordFromBackingStore, requestID, result, 0, String(StringImpl::empty())));
944 }
945
946 void UniqueIDBDatabase::didGetRecordFromBackingStore(uint64_t requestID, const IDBGetResult& result, uint32_t errorCode, const String& errorMessage)
947 {
948     m_pendingDatabaseTasks.take(requestID).get().completeRequest(result, errorCode, errorMessage);
949 }
950
951 void UniqueIDBDatabase::openCursorInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, IndexedDB::CursorDirection cursorDirection, IndexedDB::CursorType cursorType, IDBDatabaseBackend::TaskType taskType, const IDBKeyRangeData& keyRange)
952 {
953     ASSERT(!RunLoop::isMain());
954     ASSERT(m_backingStore);
955
956     int64_t cursorID = 0;
957     IDBKeyData key;
958     IDBKeyData primaryKey;
959     Vector<uint8_t> valueBuffer;
960     int32_t errorCode = 0;
961     String errorMessage;
962     bool success = m_backingStore->openCursor(transactionIdentifier, objectStoreID, indexID, cursorDirection, cursorType, taskType, keyRange, cursorID, key, primaryKey, valueBuffer);
963
964     if (!success) {
965         errorCode = IDBDatabaseException::UnknownError;
966         errorMessage = ASCIILiteral("Unknown error opening cursor in backing store");
967     }
968
969     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didOpenCursorInBackingStore, requestID, cursorID, key, primaryKey, valueBuffer, errorCode, errorMessage));
970 }
971
972 void UniqueIDBDatabase::didOpenCursorInBackingStore(uint64_t requestID, int64_t cursorID, const IDBKeyData& key, const IDBKeyData& primaryKey, const Vector<uint8_t>& valueBuffer, uint32_t errorCode, const String& errorMessage)
973 {
974     m_pendingDatabaseTasks.take(requestID).get().completeRequest(cursorID, key, primaryKey, SharedBuffer::create(valueBuffer.data(), valueBuffer.size()), errorCode, errorMessage);
975 }
976
977 void UniqueIDBDatabase::advanceCursorInBackingStore(uint64_t requestID, const IDBIdentifier& cursorIdentifier, uint64_t count)
978 {
979     IDBKeyData key;
980     IDBKeyData primaryKey;
981     Vector<uint8_t> valueBuffer;
982     int32_t errorCode = 0;
983     String errorMessage;
984     bool success = m_backingStore->advanceCursor(cursorIdentifier, count, key, primaryKey, valueBuffer);
985
986     if (!success) {
987         errorCode = IDBDatabaseException::UnknownError;
988         errorMessage = ASCIILiteral("Unknown error advancing cursor in backing store");
989     }
990
991     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didAdvanceCursorInBackingStore, requestID, key, primaryKey, valueBuffer, errorCode, errorMessage));
992 }
993
994 void UniqueIDBDatabase::didAdvanceCursorInBackingStore(uint64_t requestID, const IDBKeyData& key, const IDBKeyData& primaryKey, const Vector<uint8_t>& valueBuffer, uint32_t errorCode, const String& errorMessage)
995 {
996     m_pendingDatabaseTasks.take(requestID).get().completeRequest(key, primaryKey, SharedBuffer::create(valueBuffer.data(), valueBuffer.size()), errorCode, errorMessage);
997 }
998
999 void UniqueIDBDatabase::iterateCursorInBackingStore(uint64_t requestID, const IDBIdentifier& cursorIdentifier, const IDBKeyData& iterateKey)
1000 {
1001     IDBKeyData key;
1002     IDBKeyData primaryKey;
1003     Vector<uint8_t> valueBuffer;
1004     int32_t errorCode = 0;
1005     String errorMessage;
1006     bool success = m_backingStore->iterateCursor(cursorIdentifier, iterateKey, key, primaryKey, valueBuffer);
1007
1008     if (!success) {
1009         errorCode = IDBDatabaseException::UnknownError;
1010         errorMessage = ASCIILiteral("Unknown error iterating cursor in backing store");
1011     }
1012
1013     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didIterateCursorInBackingStore, requestID, key, primaryKey, valueBuffer, errorCode, errorMessage));
1014 }
1015
1016 void UniqueIDBDatabase::didIterateCursorInBackingStore(uint64_t requestID, const IDBKeyData& key, const IDBKeyData& primaryKey, const Vector<uint8_t>& valueBuffer, uint32_t errorCode, const String& errorMessage)
1017 {
1018     m_pendingDatabaseTasks.take(requestID).get().completeRequest(key, primaryKey, SharedBuffer::create(valueBuffer.data(), valueBuffer.size()), errorCode, errorMessage);
1019 }
1020
1021 void UniqueIDBDatabase::countInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, const IDBKeyRangeData& keyRangeData)
1022 {
1023     int64_t count;
1024
1025     if (!m_backingStore->count(transactionIdentifier, objectStoreID, indexID, keyRangeData, count)) {
1026         LOG_ERROR("Failed to get count from backing store.");
1027         postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didCountInBackingStore, requestID, 0, IDBDatabaseException::UnknownError, ASCIILiteral("Failed to get count from backing store")));
1028
1029         return;
1030     }
1031
1032     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didCountInBackingStore, requestID, count, 0, String(StringImpl::empty())));
1033 }
1034
1035 void UniqueIDBDatabase::didCountInBackingStore(uint64_t requestID, int64_t count, uint32_t errorCode, const String& errorMessage)
1036 {
1037     m_pendingDatabaseTasks.take(requestID).get().completeRequest(count, errorCode, errorMessage);
1038 }
1039
1040 void UniqueIDBDatabase::deleteRangeInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const IDBKeyRangeData& keyRangeData)
1041 {
1042     if (!m_backingStore->deleteRange(transactionIdentifier, objectStoreID, keyRangeData)) {
1043         LOG_ERROR("Failed to delete range from backing store.");
1044         postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didDeleteRangeInBackingStore, requestID, IDBDatabaseException::UnknownError, ASCIILiteral("Failed to get count from backing store")));
1045
1046         return;
1047     }
1048
1049     m_backingStore->notifyCursorsOfChanges(transactionIdentifier, objectStoreID);
1050
1051     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didDeleteRangeInBackingStore, requestID, 0, String(StringImpl::empty())));
1052 }
1053
1054 void UniqueIDBDatabase::didDeleteRangeInBackingStore(uint64_t requestID, uint32_t errorCode, const String& errorMessage)
1055 {
1056     m_pendingDatabaseTasks.take(requestID).get().completeRequest(errorCode, errorMessage);
1057 }
1058
1059 void UniqueIDBDatabase::didEstablishTransaction(const IDBIdentifier& transactionIdentifier, bool success)
1060 {
1061     ASSERT(RunLoop::isMain());
1062     if (!success)
1063         return;
1064
1065     auto transactions = m_establishedTransactions.add(&transactionIdentifier.connection(), HashSet<IDBIdentifier>());
1066     transactions.iterator->value.add(transactionIdentifier);
1067 }
1068
1069 void UniqueIDBDatabase::didResetTransaction(const IDBIdentifier& transactionIdentifier, bool success)
1070 {
1071     ASSERT(RunLoop::isMain());
1072     if (!success)
1073         return;
1074
1075     auto transactions = m_establishedTransactions.find(&transactionIdentifier.connection());
1076     if (transactions != m_establishedTransactions.end())
1077         transactions.get()->value.remove(transactionIdentifier);
1078 }
1079
1080 void UniqueIDBDatabase::resetAllTransactions(const DatabaseProcessIDBConnection& connection)
1081 {
1082     ASSERT(RunLoop::isMain());
1083     auto transactions = m_establishedTransactions.find(&connection);
1084     if (transactions == m_establishedTransactions.end() || !m_acceptingNewRequests)
1085         return;
1086
1087     for (auto& transactionIdentifier : transactions.get()->value) {
1088         m_pendingTransactionRollbacks.add(transactionIdentifier);
1089         if (!m_pendingTransactionRequests.contains(transactionIdentifier))
1090             finalizeRollback(transactionIdentifier);
1091     }
1092 }
1093
1094 void UniqueIDBDatabase::finalizeRollback(const WebKit::IDBIdentifier& transactionId)
1095 {
1096     ASSERT(RunLoop::isMain());
1097     ASSERT(m_pendingTransactionRollbacks.contains(transactionId));
1098     ASSERT(!m_pendingTransactionRequests.contains(transactionId));
1099     rollbackTransaction(transactionId, [this, transactionId](bool) {
1100         ASSERT(RunLoop::isMain());
1101         if (m_pendingTransactionRequests.contains(transactionId))
1102             return;
1103
1104         ASSERT(m_pendingTransactionRollbacks.contains(transactionId));
1105         m_pendingTransactionRollbacks.remove(transactionId);
1106         resetTransaction(transactionId, [this, transactionId](bool) {
1107             if (m_acceptingNewRequests && m_connections.isEmpty() && m_pendingTransactionRollbacks.isEmpty()) {
1108                 shutdown(UniqueIDBDatabaseShutdownType::NormalShutdown);
1109                 DatabaseProcess::singleton().removeUniqueIDBDatabase(*this);
1110             }
1111         });
1112     });
1113 }
1114
1115 String UniqueIDBDatabase::absoluteDatabaseDirectory() const
1116 {
1117     ASSERT(RunLoop::isMain());
1118     return DatabaseProcess::singleton().absoluteIndexedDatabasePathFromDatabaseRelativePath(m_databaseRelativeDirectory);
1119 }
1120
1121 void UniqueIDBDatabase::postMainThreadTask(std::unique_ptr<AsyncTask> task, DatabaseTaskType taskType)
1122 {
1123     ASSERT(!RunLoop::isMain());
1124
1125     if (!m_acceptingNewRequests && taskType == DatabaseTaskType::Normal)
1126         return;
1127
1128     DeprecatedMutexLocker locker(m_mainThreadTaskMutex);
1129
1130     m_mainThreadTasks.append(WTF::move(task));
1131
1132     RefPtr<UniqueIDBDatabase> database(this);
1133     RunLoop::main().dispatch([database] {
1134         database->performNextMainThreadTask();
1135     });
1136 }
1137
1138 bool UniqueIDBDatabase::performNextMainThreadTask()
1139 {
1140     ASSERT(RunLoop::isMain());
1141
1142     bool moreTasks;
1143
1144     std::unique_ptr<AsyncTask> task;
1145     {
1146         DeprecatedMutexLocker locker(m_mainThreadTaskMutex);
1147
1148         // This database might be shutting down, in which case the task queue might be empty.
1149         if (m_mainThreadTasks.isEmpty())
1150             return false;
1151
1152         task = m_mainThreadTasks.takeFirst();
1153         moreTasks = !m_mainThreadTasks.isEmpty();
1154     }
1155
1156     task->performTask();
1157
1158     return moreTasks;
1159 }
1160
1161 void UniqueIDBDatabase::postDatabaseTask(std::unique_ptr<AsyncTask> task, DatabaseTaskType taskType)
1162 {
1163     ASSERT(RunLoop::isMain());
1164
1165     if (!m_acceptingNewRequests && taskType == DatabaseTaskType::Normal)
1166         return;
1167
1168     DeprecatedMutexLocker locker(m_databaseTaskMutex);
1169
1170     m_databaseTasks.append(WTF::move(task));
1171
1172     RefPtr<UniqueIDBDatabase> database(this);
1173     DatabaseProcess::singleton().queue().dispatch([database] {
1174         database->performNextDatabaseTask();
1175     });
1176 }
1177
1178 void UniqueIDBDatabase::performNextDatabaseTask()
1179 {
1180     ASSERT(!RunLoop::isMain());
1181
1182     // It is possible that this database might be shutting down on the main thread.
1183     // In this case, immediately after releasing m_databaseTaskMutex, this database might get deleted.
1184     // We take a ref() to make sure the database is still live while this last task is performed.
1185     RefPtr<UniqueIDBDatabase> protector(this);
1186
1187     std::unique_ptr<AsyncTask> task;
1188     {
1189         DeprecatedMutexLocker locker(m_databaseTaskMutex);
1190
1191         // This database might be shutting down on the main thread, in which case the task queue might be empty.
1192         if (m_databaseTasks.isEmpty())
1193             return;
1194
1195         task = m_databaseTasks.takeFirst();
1196     }
1197
1198     task->performTask();
1199 }
1200
1201 } // namespace WebKit
1202
1203 #endif // ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)