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
43namespace WebCore {
44namespace IDBServer {
45
46// The IndexedDB spec states the value you can get from the key generator is 2^53
47static uint64_t maxGeneratedKeyValue = 0x20000000000000;
48
49std::unique_ptr<MemoryIDBBackingStore> MemoryIDBBackingStore::create(const IDBDatabaseIdentifier& identifier)
50{
51 return std::make_unique<MemoryIDBBackingStore>(identifier);
52}
53
54MemoryIDBBackingStore::MemoryIDBBackingStore(const IDBDatabaseIdentifier& identifier)
55 : m_identifier(identifier)
56{
57}
58
59MemoryIDBBackingStore::~MemoryIDBBackingStore() = default;
60
61IDBError 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
70void 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
78IDBError 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
103IDBError 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
116IDBError 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
129IDBError 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
152IDBError 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
175IDBError 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
201IDBError 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
222IDBError 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
237IDBError 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
252IDBError 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
288void 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
300void MemoryIDBBackingStore::restoreObjectStoreForVersionChangeAbort(Ref<MemoryObjectStore>&& objectStore)
301{
302 registerObjectStore(WTFMove(objectStore));
303}
304
305IDBError 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
318IDBError 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
335IDBError 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
352IDBError 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
379IDBError 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
404IDBError 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
421IDBError 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
439IDBError 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
458IDBError 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
473IDBError 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
497IDBError 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
539IDBError 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
555void 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
565void 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
574RefPtr<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
586IDBObjectStoreInfo* MemoryIDBBackingStore::infoForObjectStore(uint64_t objectStoreIdentifier)
587{
588 ASSERT(m_databaseInfo);
589 return m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
590}
591
592void MemoryIDBBackingStore::deleteBackingStore()
593{
594 // The in-memory IDB backing store doesn't need to do any cleanup when it is deleted.
595}
596
597uint64_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)
607