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