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