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) |
607 | |