IndexedDB 2.0: Encapsulate cursor iteration parameters for easy future expansion.
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / server / MemoryIDBBackingStore.cpp
1 /*
2  * Copyright (C) 2015 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 "MemoryIDBBackingStore.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBCursorInfo.h"
32 #include "IDBGetAllRecordsData.h"
33 #include "IDBGetResult.h"
34 #include "IDBIndexInfo.h"
35 #include "IDBIterateCursorData.h"
36 #include "IDBKeyRangeData.h"
37 #include "Logging.h"
38 #include "MemoryIndexCursor.h"
39 #include "MemoryObjectStore.h"
40 #include "MemoryObjectStoreCursor.h"
41
42 namespace WebCore {
43 namespace IDBServer {
44
45 // The IndexedDB spec states the value you can get from the key generator is 2^53
46 static uint64_t maxGeneratedKeyValue = 0x20000000000000;
47
48 std::unique_ptr<MemoryIDBBackingStore> MemoryIDBBackingStore::create(const IDBDatabaseIdentifier& identifier)
49 {
50     return std::make_unique<MemoryIDBBackingStore>(identifier);
51 }
52
53 MemoryIDBBackingStore::MemoryIDBBackingStore(const IDBDatabaseIdentifier& identifier)
54     : m_identifier(identifier)
55 {
56 }
57
58 MemoryIDBBackingStore::~MemoryIDBBackingStore()
59 {
60 }
61
62 IDBError MemoryIDBBackingStore::getOrEstablishDatabaseInfo(IDBDatabaseInfo& info)
63 {
64     if (!m_databaseInfo)
65         m_databaseInfo = std::make_unique<IDBDatabaseInfo>(m_identifier.databaseName(), 0);
66
67     info = *m_databaseInfo;
68     return { };
69 }
70
71 void MemoryIDBBackingStore::setDatabaseInfo(const IDBDatabaseInfo& info)
72 {
73     // It is not valid to directly set database info on a backing store that hasn't already set its own database info.
74     ASSERT(m_databaseInfo);
75
76     m_databaseInfo = std::make_unique<IDBDatabaseInfo>(info);
77 }
78
79 IDBError MemoryIDBBackingStore::beginTransaction(const IDBTransactionInfo& info)
80 {
81     LOG(IndexedDB, "MemoryIDBBackingStore::beginTransaction");
82
83     if (m_transactions.contains(info.identifier()))
84         return { IDBDatabaseException::InvalidStateError, "Backing store asked to create transaction it already has a record of" };
85
86     auto transaction = MemoryBackingStoreTransaction::create(*this, info);
87
88     // VersionChange transactions are scoped to "every object store".
89     if (transaction->isVersionChange()) {
90         for (auto& objectStore : m_objectStoresByIdentifier.values())
91             transaction->addExistingObjectStore(*objectStore);
92     } else if (transaction->isWriting()) {
93         for (auto& iterator : m_objectStoresByName) {
94             if (info.objectStores().contains(iterator.key))
95                 transaction->addExistingObjectStore(*iterator.value);
96         }
97     }
98
99     m_transactions.set(info.identifier(), WTFMove(transaction));
100
101     return { };
102 }
103
104 IDBError MemoryIDBBackingStore::abortTransaction(const IDBResourceIdentifier& transactionIdentifier)
105 {
106     LOG(IndexedDB, "MemoryIDBBackingStore::abortTransaction - %s", transactionIdentifier.loggingString().utf8().data());
107
108     auto transaction = m_transactions.take(transactionIdentifier);
109     if (!transaction)
110         return { IDBDatabaseException::InvalidStateError, "Backing store asked to abort transaction it didn't have record of" };
111
112     transaction->abort();
113
114     return { };
115 }
116
117 IDBError MemoryIDBBackingStore::commitTransaction(const IDBResourceIdentifier& transactionIdentifier)
118 {
119     LOG(IndexedDB, "MemoryIDBBackingStore::commitTransaction - %s", transactionIdentifier.loggingString().utf8().data());
120
121     auto transaction = m_transactions.take(transactionIdentifier);
122     if (!transaction)
123         return { IDBDatabaseException::InvalidStateError, "Backing store asked to commit transaction it didn't have record of" };
124
125     transaction->commit();
126
127     return { };
128 }
129
130 IDBError MemoryIDBBackingStore::createObjectStore(const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& info)
131 {
132     LOG(IndexedDB, "MemoryIDBBackingStore::createObjectStore - adding OS %s with ID %" PRIu64, info.name().utf8().data(), info.identifier());
133
134     ASSERT(m_databaseInfo);
135     if (m_databaseInfo->hasObjectStore(info.name()))
136         return { IDBDatabaseException::ConstraintError };
137
138     ASSERT(!m_objectStoresByIdentifier.contains(info.identifier()));
139     auto objectStore = MemoryObjectStore::create(info);
140
141     m_databaseInfo->addExistingObjectStore(info);
142
143     auto rawTransaction = m_transactions.get(transactionIdentifier);
144     ASSERT(rawTransaction);
145     ASSERT(rawTransaction->isVersionChange());
146
147     rawTransaction->addNewObjectStore(objectStore.get());
148     registerObjectStore(WTFMove(objectStore));
149
150     return { };
151 }
152
153 IDBError MemoryIDBBackingStore::deleteObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier)
154 {
155     LOG(IndexedDB, "MemoryIDBBackingStore::deleteObjectStore");
156
157     ASSERT(m_databaseInfo);
158     if (!m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier))
159         return { IDBDatabaseException::ConstraintError };
160
161     auto transaction = m_transactions.get(transactionIdentifier);
162     ASSERT(transaction);
163     ASSERT(transaction->isVersionChange());
164
165     auto objectStore = takeObjectStoreByIdentifier(objectStoreIdentifier);
166     ASSERT(objectStore);
167     if (!objectStore)
168         return { IDBDatabaseException::ConstraintError };
169
170     m_databaseInfo->deleteObjectStore(objectStore->info().name());
171     transaction->objectStoreDeleted(*objectStore);
172
173     return { };
174 }
175
176 IDBError MemoryIDBBackingStore::renameObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const String& newName)
177 {
178     LOG(IndexedDB, "MemoryIDBBackingStore::renameObjectStore");
179
180     ASSERT(m_databaseInfo);
181     if (!m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier))
182         return { IDBDatabaseException::ConstraintError };
183
184     auto transaction = m_transactions.get(transactionIdentifier);
185     ASSERT(transaction);
186     ASSERT(transaction->isVersionChange());
187
188     auto objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
189     ASSERT(objectStore);
190     if (!objectStore)
191         return { IDBDatabaseException::ConstraintError };
192
193     String oldName = objectStore->info().name();
194     objectStore->rename(newName);
195     transaction->objectStoreRenamed(*objectStore, oldName);
196
197     m_databaseInfo->renameObjectStore(objectStoreIdentifier, newName);
198
199     return { };
200 }
201
202 IDBError MemoryIDBBackingStore::clearObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier)
203 {
204     LOG(IndexedDB, "MemoryIDBBackingStore::clearObjectStore");
205     ASSERT(objectStoreIdentifier);
206
207     ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
208
209 #if !LOG_DISABLED
210     auto transaction = m_transactions.get(transactionIdentifier);
211     ASSERT(transaction->isWriting());
212 #endif
213
214     auto objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
215     if (!objectStore)
216         return { IDBDatabaseException::ConstraintError };
217
218     objectStore->clear();
219
220     return { };
221 }
222
223 IDBError MemoryIDBBackingStore::createIndex(const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo& info)
224 {
225     LOG(IndexedDB, "MemoryIDBBackingStore::createIndex");
226
227     auto rawTransaction = m_transactions.get(transactionIdentifier);
228     ASSERT(rawTransaction);
229     ASSERT(rawTransaction->isVersionChange());
230
231     auto* objectStore = m_objectStoresByIdentifier.get(info.objectStoreIdentifier());
232     if (!objectStore)
233         return { IDBDatabaseException::ConstraintError };
234
235     return objectStore->createIndex(*rawTransaction, info);
236 }
237
238 IDBError MemoryIDBBackingStore::deleteIndex(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier)
239 {
240     LOG(IndexedDB, "MemoryIDBBackingStore::deleteIndex");
241
242     auto rawTransaction = m_transactions.get(transactionIdentifier);
243     ASSERT(rawTransaction);
244     ASSERT(rawTransaction->isVersionChange());
245
246     auto* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
247     if (!objectStore)
248         return { IDBDatabaseException::ConstraintError };
249
250     return objectStore->deleteIndex(*rawTransaction, indexIdentifier);
251 }
252
253 IDBError MemoryIDBBackingStore::renameIndex(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName)
254 {
255     LOG(IndexedDB, "MemoryIDBBackingStore::renameIndex");
256
257     ASSERT(m_databaseInfo);
258     auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
259     if (!objectStoreInfo)
260         return { IDBDatabaseException::ConstraintError };
261
262     auto* indexInfo = objectStoreInfo->infoForExistingIndex(indexIdentifier);
263     if (!indexInfo)
264         return { IDBDatabaseException::ConstraintError };
265
266     auto transaction = m_transactions.get(transactionIdentifier);
267     ASSERT(transaction);
268     ASSERT(transaction->isVersionChange());
269
270     auto objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
271     ASSERT(objectStore);
272     if (!objectStore)
273         return { IDBDatabaseException::ConstraintError };
274
275     auto* index = objectStore->indexForIdentifier(indexIdentifier);
276     ASSERT(index);
277     if (!index)
278         return { IDBDatabaseException::ConstraintError };
279
280     String oldName = index->info().name();
281     objectStore->renameIndex(*index, newName);
282     transaction->indexRenamed(*index, oldName);
283
284     indexInfo->rename(newName);
285
286     return { };
287 }
288
289 void MemoryIDBBackingStore::removeObjectStoreForVersionChangeAbort(MemoryObjectStore& objectStore)
290 {
291     LOG(IndexedDB, "MemoryIDBBackingStore::removeObjectStoreForVersionChangeAbort");
292
293     if (!m_objectStoresByIdentifier.contains(objectStore.info().identifier()))
294         return;
295
296     ASSERT(m_objectStoresByIdentifier.get(objectStore.info().identifier()) == &objectStore);
297
298     unregisterObjectStore(objectStore);
299 }
300
301 void MemoryIDBBackingStore::restoreObjectStoreForVersionChangeAbort(Ref<MemoryObjectStore>&& objectStore)
302 {
303     registerObjectStore(WTFMove(objectStore));
304 }
305
306 IDBError MemoryIDBBackingStore::keyExistsInObjectStore(const IDBResourceIdentifier&, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, bool& keyExists)
307 {
308     LOG(IndexedDB, "MemoryIDBBackingStore::keyExistsInObjectStore");
309
310     ASSERT(objectStoreIdentifier);
311
312     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
313     RELEASE_ASSERT(objectStore);
314
315     keyExists = objectStore->containsRecord(keyData);
316     return { };
317 }
318
319 IDBError MemoryIDBBackingStore::deleteRange(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range)
320 {
321     LOG(IndexedDB, "MemoryIDBBackingStore::deleteRange");
322
323     ASSERT(objectStoreIdentifier);
324
325     if (!m_transactions.contains(transactionIdentifier))
326         return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found to delete from") };
327
328     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
329     if (!objectStore)
330         return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found") };
331
332     objectStore->deleteRange(range);
333     return { };
334 }
335
336 IDBError MemoryIDBBackingStore::addRecord(const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& objectStoreInfo, const IDBKeyData& keyData, const IDBValue& value)
337 {
338     LOG(IndexedDB, "MemoryIDBBackingStore::addRecord");
339
340     ASSERT(objectStoreInfo.identifier());
341
342     auto transaction = m_transactions.get(transactionIdentifier);
343     if (!transaction)
344         return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found to put record") };
345
346     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreInfo.identifier());
347     if (!objectStore)
348         return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found to put record") };
349
350     return objectStore->addRecord(*transaction, keyData, value);
351 }
352
353 IDBError MemoryIDBBackingStore::getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range, IDBGetResult& outValue)
354 {
355     LOG(IndexedDB, "MemoryIDBBackingStore::getRecord");
356
357     ASSERT(objectStoreIdentifier);
358
359     if (!m_transactions.contains(transactionIdentifier))
360         return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found to get record") };
361
362     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
363     if (!objectStore)
364         return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found") };
365
366     outValue = objectStore->valueForKeyRange(range);
367     return { };
368 }
369
370 IDBError MemoryIDBBackingStore::getAllRecords(const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData& getAllRecordsData, IDBGetAllResult& result)
371 {
372     LOG(IndexedDB, "MemoryIDBBackingStore::getAllRecords");
373
374     ASSERT(getAllRecordsData.objectStoreIdentifier);
375
376     if (!m_transactions.contains(transactionIdentifier))
377         return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found to get all records") };
378
379     auto* objectStore = m_objectStoresByIdentifier.get(getAllRecordsData.objectStoreIdentifier);
380     if (!objectStore)
381         return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found") };
382
383     if (getAllRecordsData.indexIdentifier) {
384         auto* index = objectStore->indexForIdentifier(getAllRecordsData.indexIdentifier);
385         if (!index)
386             return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store index found") };
387
388         index->getAllRecords(getAllRecordsData.keyRangeData, getAllRecordsData.count, getAllRecordsData.getAllType, result);
389     } else
390         objectStore->getAllRecords(getAllRecordsData.keyRangeData, getAllRecordsData.count, getAllRecordsData.getAllType, result);
391
392     return { };
393 }
394
395 IDBError MemoryIDBBackingStore::getIndexRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType recordType, const IDBKeyRangeData& range, IDBGetResult& outValue)
396 {
397     LOG(IndexedDB, "MemoryIDBBackingStore::getIndexRecord");
398
399     ASSERT(objectStoreIdentifier);
400
401     if (!m_transactions.contains(transactionIdentifier))
402         return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found to get record") };
403
404     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
405     if (!objectStore)
406         return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found") };
407
408     outValue = objectStore->indexValueForKeyRange(indexIdentifier, recordType, range);
409     return { };
410 }
411
412 IDBError MemoryIDBBackingStore::getCount(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData& range, uint64_t& outCount)
413 {
414     LOG(IndexedDB, "MemoryIDBBackingStore::getCount");
415
416     ASSERT(objectStoreIdentifier);
417
418     if (!m_transactions.contains(transactionIdentifier))
419         return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found to get count") };
420
421     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
422     if (!objectStore)
423         return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found") };
424
425     outCount = objectStore->countForKeyRange(indexIdentifier, range);
426
427     return { };
428 }
429
430 IDBError MemoryIDBBackingStore::generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t& keyNumber)
431 {
432     LOG(IndexedDB, "MemoryIDBBackingStore::generateKeyNumber");
433     ASSERT(objectStoreIdentifier);
434     ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
435     ASSERT_UNUSED(transactionIdentifier, m_transactions.get(transactionIdentifier)->isWriting());
436
437     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
438     RELEASE_ASSERT(objectStore);
439
440     keyNumber = objectStore->currentKeyGeneratorValue();
441     if (keyNumber > maxGeneratedKeyValue)
442         return { IDBDatabaseException::ConstraintError, "Cannot generate new key value over 2^53 for object store operation" };
443
444     objectStore->setKeyGeneratorValue(keyNumber + 1);
445
446     return { };
447 }
448
449 IDBError MemoryIDBBackingStore::revertGeneratedKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t keyNumber)
450 {
451     LOG(IndexedDB, "MemoryIDBBackingStore::revertGeneratedKeyNumber");
452     ASSERT(objectStoreIdentifier);
453     ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
454     ASSERT_UNUSED(transactionIdentifier, m_transactions.get(transactionIdentifier)->isWriting());
455
456     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
457     RELEASE_ASSERT(objectStore);
458
459     objectStore->setKeyGeneratorValue(keyNumber);
460
461     return { };
462 }
463
464 IDBError MemoryIDBBackingStore::maybeUpdateKeyGeneratorNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, double newKeyNumber)
465 {
466     LOG(IndexedDB, "MemoryIDBBackingStore::maybeUpdateKeyGeneratorNumber");
467     ASSERT(objectStoreIdentifier);
468     ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
469     ASSERT_UNUSED(transactionIdentifier, m_transactions.get(transactionIdentifier)->isWriting());
470
471     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
472     RELEASE_ASSERT(objectStore);
473
474     if (newKeyNumber < objectStore->currentKeyGeneratorValue())
475         return { };
476
477     uint64_t newKeyInteger(newKeyNumber);
478     if (newKeyInteger <= uint64_t(newKeyNumber))
479         ++newKeyInteger;
480
481     ASSERT(newKeyInteger > uint64_t(newKeyNumber));
482
483     objectStore->setKeyGeneratorValue(newKeyInteger);
484
485     return { };
486 }
487
488 IDBError MemoryIDBBackingStore::openCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo& info, IDBGetResult& outData)
489 {
490     LOG(IndexedDB, "MemoryIDBBackingStore::openCursor");
491
492     ASSERT(!MemoryCursor::cursorForIdentifier(info.identifier()));
493
494     if (!m_transactions.contains(transactionIdentifier))
495         return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found in which to open a cursor") };
496
497     switch (info.cursorSource()) {
498     case IndexedDB::CursorSource::ObjectStore: {
499         auto* objectStore = m_objectStoresByIdentifier.get(info.sourceIdentifier());
500         if (!objectStore)
501             return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found") };
502
503         MemoryCursor* cursor = objectStore->maybeOpenCursor(info);
504         if (!cursor)
505             return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not create object store cursor in backing store") };
506
507         cursor->currentData(outData);
508         break;
509     }
510     case IndexedDB::CursorSource::Index:
511         auto* objectStore = m_objectStoresByIdentifier.get(info.objectStoreIdentifier());
512         if (!objectStore)
513             return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found") };
514
515         auto* index = objectStore->indexForIdentifier(info.sourceIdentifier());
516         if (!index)
517             return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store index found") };
518
519         MemoryCursor* cursor = index->maybeOpenCursor(info);
520         if (!cursor)
521             return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not create index cursor in backing store") };
522
523         cursor->currentData(outData);
524         break;
525     }
526
527     return { };
528 }
529
530 IDBError MemoryIDBBackingStore::iterateCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, const IDBIterateCursorData& data, IDBGetResult& outData)
531 {
532     LOG(IndexedDB, "MemoryIDBBackingStore::iterateCursor");
533
534     if (!m_transactions.contains(transactionIdentifier))
535         return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found in which to iterate cursor") };
536
537     auto* cursor = MemoryCursor::cursorForIdentifier(cursorIdentifier);
538     if (!cursor)
539         return { IDBDatabaseException::UnknownError, ASCIILiteral("No backing store cursor found in which to iterate cursor") };
540
541     cursor->iterate(data.keyData, data.count, outData);
542
543     return { };
544 }
545
546 void MemoryIDBBackingStore::registerObjectStore(Ref<MemoryObjectStore>&& objectStore)
547 {
548     ASSERT(!m_objectStoresByIdentifier.contains(objectStore->info().identifier()));
549     ASSERT(!m_objectStoresByName.contains(objectStore->info().name()));
550
551     m_objectStoresByName.set(objectStore->info().name(), &objectStore.get());
552     m_objectStoresByIdentifier.set(objectStore->info().identifier(), WTFMove(objectStore));
553 }
554
555 void MemoryIDBBackingStore::unregisterObjectStore(MemoryObjectStore& objectStore)
556 {
557     ASSERT(m_objectStoresByIdentifier.contains(objectStore.info().identifier()));
558     ASSERT(m_objectStoresByName.contains(objectStore.info().name()));
559
560     m_objectStoresByName.remove(objectStore.info().name());
561     m_objectStoresByIdentifier.remove(objectStore.info().identifier());
562 }
563
564 RefPtr<MemoryObjectStore> MemoryIDBBackingStore::takeObjectStoreByIdentifier(uint64_t identifier)
565 {
566     auto objectStoreByIdentifier = m_objectStoresByIdentifier.take(identifier);
567     if (!objectStoreByIdentifier)
568         return nullptr;
569
570     auto objectStore = m_objectStoresByName.take(objectStoreByIdentifier->info().name());
571     ASSERT_UNUSED(objectStore, objectStore);
572
573     return objectStoreByIdentifier;
574 }
575
576 IDBObjectStoreInfo* MemoryIDBBackingStore::infoForObjectStore(uint64_t objectStoreIdentifier)
577 {
578     ASSERT(m_databaseInfo);
579     return m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
580 }
581
582 void MemoryIDBBackingStore::deleteBackingStore()
583 {
584     // The in-memory IDB backing store doesn't need to do any cleanup when it is deleted.
585 }
586
587 } // namespace IDBServer
588 } // namespace WebCore
589
590 #endif // ENABLE(INDEXED_DATABASE)