blob: 59dd41073d8bd4ea4fc533f972e6dea1805255fc [file] [log] [blame]
/*
* Copyright (C) 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "MemoryIDBBackingStore.h"
#if ENABLE(INDEXED_DATABASE)
#include "IDBCursorInfo.h"
#include "IDBGetAllRecordsData.h"
#include "IDBGetRecordData.h"
#include "IDBGetResult.h"
#include "IDBIndexInfo.h"
#include "IDBIterateCursorData.h"
#include "IDBKeyRangeData.h"
#include "Logging.h"
#include "MemoryIndexCursor.h"
#include "MemoryObjectStore.h"
#include "MemoryObjectStoreCursor.h"
namespace WebCore {
namespace IDBServer {
// The IndexedDB spec states the value you can get from the key generator is 2^53
static uint64_t maxGeneratedKeyValue = 0x20000000000000;
std::unique_ptr<MemoryIDBBackingStore> MemoryIDBBackingStore::create(PAL::SessionID sessionID, const IDBDatabaseIdentifier& identifier)
{
return makeUnique<MemoryIDBBackingStore>(sessionID, identifier);
}
MemoryIDBBackingStore::MemoryIDBBackingStore(PAL::SessionID sessionID, const IDBDatabaseIdentifier& identifier)
: m_identifier(identifier)
, m_sessionID(sessionID)
{
}
MemoryIDBBackingStore::~MemoryIDBBackingStore() = default;
IDBError MemoryIDBBackingStore::getOrEstablishDatabaseInfo(IDBDatabaseInfo& info, const LockHolder&)
{
return getOrEstablishDatabaseInfo(info);
}
IDBError MemoryIDBBackingStore::getOrEstablishDatabaseInfo(IDBDatabaseInfo& info)
{
if (!m_databaseInfo)
m_databaseInfo = makeUnique<IDBDatabaseInfo>(m_identifier.databaseName(), 0);
info = *m_databaseInfo;
return IDBError { };
}
void MemoryIDBBackingStore::setDatabaseInfo(const IDBDatabaseInfo& info)
{
// It is not valid to directly set database info on a backing store that hasn't already set its own database info.
ASSERT(m_databaseInfo);
m_databaseInfo = makeUnique<IDBDatabaseInfo>(info);
}
IDBError MemoryIDBBackingStore::beginTransaction(const IDBTransactionInfo& info, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::beginTransaction");
if (m_transactions.contains(info.identifier()))
return IDBError { InvalidStateError, "Backing store asked to create transaction it already has a record of" };
auto transaction = MemoryBackingStoreTransaction::create(*this, info);
// VersionChange transactions are scoped to "every object store".
if (transaction->isVersionChange()) {
for (auto& objectStore : m_objectStoresByIdentifier.values())
transaction->addExistingObjectStore(*objectStore);
} else if (transaction->isWriting()) {
for (auto& iterator : m_objectStoresByName) {
if (info.objectStores().contains(iterator.key))
transaction->addExistingObjectStore(*iterator.value);
}
}
m_transactions.set(info.identifier(), WTFMove(transaction));
return IDBError { };
}
IDBError MemoryIDBBackingStore::abortTransaction(const IDBResourceIdentifier& transactionIdentifier, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::abortTransaction - %s", transactionIdentifier.loggingString().utf8().data());
auto transaction = m_transactions.take(transactionIdentifier);
if (!transaction)
return IDBError { InvalidStateError, "Backing store asked to abort transaction it didn't have record of" };
transaction->abort();
return IDBError { };
}
IDBError MemoryIDBBackingStore::commitTransaction(const IDBResourceIdentifier& transactionIdentifier, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::commitTransaction - %s", transactionIdentifier.loggingString().utf8().data());
auto transaction = m_transactions.take(transactionIdentifier);
if (!transaction)
return IDBError { InvalidStateError, "Backing store asked to commit transaction it didn't have record of" };
transaction->commit();
return IDBError { };
}
IDBError MemoryIDBBackingStore::createObjectStore(const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& info, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::createObjectStore - adding OS %s with ID %" PRIu64, info.name().utf8().data(), info.identifier());
ASSERT(m_databaseInfo);
if (m_databaseInfo->hasObjectStore(info.name()))
return IDBError { ConstraintError };
ASSERT(!m_objectStoresByIdentifier.contains(info.identifier()));
auto objectStore = MemoryObjectStore::create(m_sessionID, info);
m_databaseInfo->addExistingObjectStore(info);
auto rawTransaction = m_transactions.get(transactionIdentifier);
ASSERT(rawTransaction);
ASSERT(rawTransaction->isVersionChange());
rawTransaction->addNewObjectStore(objectStore.get());
registerObjectStore(WTFMove(objectStore));
return IDBError { };
}
IDBError MemoryIDBBackingStore::deleteObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::deleteObjectStore");
ASSERT(m_databaseInfo);
if (!m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier))
return IDBError { ConstraintError };
auto transaction = m_transactions.get(transactionIdentifier);
ASSERT(transaction);
ASSERT(transaction->isVersionChange());
auto objectStore = takeObjectStoreByIdentifier(objectStoreIdentifier);
ASSERT(objectStore);
if (!objectStore)
return IDBError { ConstraintError };
m_databaseInfo->deleteObjectStore(objectStore->info().name());
transaction->objectStoreDeleted(*objectStore);
return IDBError { };
}
IDBError MemoryIDBBackingStore::renameObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const String& newName, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::renameObjectStore");
ASSERT(m_databaseInfo);
if (!m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier))
return IDBError { ConstraintError };
auto transaction = m_transactions.get(transactionIdentifier);
ASSERT(transaction);
ASSERT(transaction->isVersionChange());
auto objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
ASSERT(objectStore);
if (!objectStore)
return IDBError { ConstraintError };
String oldName = objectStore->info().name();
objectStore->rename(newName);
transaction->objectStoreRenamed(*objectStore, oldName);
m_objectStoresByName.remove(oldName);
m_objectStoresByName.set(newName, objectStore);
m_databaseInfo->renameObjectStore(objectStoreIdentifier, newName);
return IDBError { };
}
IDBError MemoryIDBBackingStore::clearObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::clearObjectStore");
ASSERT(objectStoreIdentifier);
ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
#ifndef NDEBUG
auto transaction = m_transactions.get(transactionIdentifier);
ASSERT(transaction->isWriting());
#endif
auto objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
if (!objectStore)
return IDBError { ConstraintError };
objectStore->clear();
return IDBError { };
}
IDBError MemoryIDBBackingStore::createIndex(const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo& info, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::createIndex");
ASSERT(m_databaseInfo);
auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(info.objectStoreIdentifier());
if (!objectStoreInfo)
return IDBError { ConstraintError };
auto rawTransaction = m_transactions.get(transactionIdentifier);
ASSERT(rawTransaction);
ASSERT(rawTransaction->isVersionChange());
auto* objectStore = m_objectStoresByIdentifier.get(info.objectStoreIdentifier());
if (!objectStore)
return IDBError { ConstraintError };
auto error = objectStore->createIndex(*rawTransaction, info);
if (error.isNull())
objectStoreInfo->addExistingIndex(info);
return error;
}
IDBError MemoryIDBBackingStore::deleteIndex(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::deleteIndex");
ASSERT(m_databaseInfo);
auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
if (!objectStoreInfo)
return IDBError { ConstraintError };
auto* indexInfo = objectStoreInfo->infoForExistingIndex(indexIdentifier);
if (!indexInfo)
return IDBError { ConstraintError };
auto rawTransaction = m_transactions.get(transactionIdentifier);
ASSERT(rawTransaction);
ASSERT(rawTransaction->isVersionChange());
auto* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
if (!objectStore)
return IDBError { ConstraintError };
auto error = objectStore->deleteIndex(*rawTransaction, indexIdentifier);
if (!error.isNull())
objectStoreInfo->deleteIndex(indexIdentifier);
return error;
}
IDBError MemoryIDBBackingStore::renameIndex(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::renameIndex");
ASSERT(m_databaseInfo);
auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
if (!objectStoreInfo)
return IDBError { ConstraintError };
auto* indexInfo = objectStoreInfo->infoForExistingIndex(indexIdentifier);
if (!indexInfo)
return IDBError { ConstraintError };
auto transaction = m_transactions.get(transactionIdentifier);
ASSERT(transaction);
ASSERT(transaction->isVersionChange());
auto objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
ASSERT(objectStore);
if (!objectStore)
return IDBError { ConstraintError };
auto* index = objectStore->indexForIdentifier(indexIdentifier);
ASSERT(index);
if (!index)
return IDBError { ConstraintError };
String oldName = index->info().name();
objectStore->renameIndex(*index, newName);
transaction->indexRenamed(*index, oldName);
indexInfo->rename(newName);
return IDBError { };
}
void MemoryIDBBackingStore::removeObjectStoreForVersionChangeAbort(MemoryObjectStore& objectStore)
{
LOG(IndexedDB, "MemoryIDBBackingStore::removeObjectStoreForVersionChangeAbort");
if (!m_objectStoresByIdentifier.contains(objectStore.info().identifier()))
return;
ASSERT(m_objectStoresByIdentifier.get(objectStore.info().identifier()) == &objectStore);
unregisterObjectStore(objectStore);
}
void MemoryIDBBackingStore::restoreObjectStoreForVersionChangeAbort(Ref<MemoryObjectStore>&& objectStore)
{
registerObjectStore(WTFMove(objectStore));
}
IDBError MemoryIDBBackingStore::keyExistsInObjectStore(const IDBResourceIdentifier&, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, bool& keyExists, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::keyExistsInObjectStore");
ASSERT(objectStoreIdentifier);
MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
RELEASE_ASSERT(objectStore);
keyExists = objectStore->containsRecord(keyData);
return IDBError { };
}
IDBError MemoryIDBBackingStore::deleteRange(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::deleteRange");
ASSERT(objectStoreIdentifier);
if (!m_transactions.contains(transactionIdentifier))
return IDBError { UnknownError, "No backing store transaction found to delete from"_s };
MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
if (!objectStore)
return IDBError { UnknownError, "No backing store object store found"_s };
objectStore->deleteRange(range);
return IDBError { };
}
IDBError MemoryIDBBackingStore::addRecord(const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& objectStoreInfo, const IDBKeyData& keyData, const IDBValue& value, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::addRecord");
ASSERT(objectStoreInfo.identifier());
auto transaction = m_transactions.get(transactionIdentifier);
if (!transaction)
return IDBError { UnknownError, "No backing store transaction found to put record"_s };
MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreInfo.identifier());
if (!objectStore)
return IDBError { UnknownError, "No backing store object store found to put record"_s };
return objectStore->addRecord(*transaction, keyData, value);
}
IDBError MemoryIDBBackingStore::getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range, IDBGetRecordDataType type, IDBGetResult& outValue, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::getRecord");
ASSERT(objectStoreIdentifier);
if (!m_transactions.contains(transactionIdentifier))
return IDBError { UnknownError, "No backing store transaction found to get record"_s };
MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
if (!objectStore)
return IDBError { UnknownError, "No backing store object store found"_s };
switch (type) {
case IDBGetRecordDataType::KeyAndValue: {
auto key = objectStore->lowestKeyWithRecordInRange(range);
outValue = { key, key.isNull() ? ThreadSafeDataBuffer() : objectStore->valueForKey(key), objectStore->info().keyPath() };
break;
}
case IDBGetRecordDataType::KeyOnly:
outValue = objectStore->lowestKeyWithRecordInRange(range);
break;
}
return IDBError { };
}
IDBError MemoryIDBBackingStore::getAllRecords(const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData& getAllRecordsData, IDBGetAllResult& result, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::getAllRecords");
ASSERT(getAllRecordsData.objectStoreIdentifier);
if (!m_transactions.contains(transactionIdentifier))
return IDBError { UnknownError, "No backing store transaction found to get all records"_s };
auto* objectStore = m_objectStoresByIdentifier.get(getAllRecordsData.objectStoreIdentifier);
if (!objectStore)
return IDBError { UnknownError, "No backing store object store found"_s };
if (getAllRecordsData.indexIdentifier) {
auto* index = objectStore->indexForIdentifier(getAllRecordsData.indexIdentifier);
if (!index)
return IDBError { UnknownError, "No backing store index found"_s };
index->getAllRecords(getAllRecordsData.keyRangeData, getAllRecordsData.count, getAllRecordsData.getAllType, result);
} else
objectStore->getAllRecords(getAllRecordsData.keyRangeData, getAllRecordsData.count, getAllRecordsData.getAllType, result);
return IDBError { };
}
IDBError MemoryIDBBackingStore::getIndexRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType recordType, const IDBKeyRangeData& range, IDBGetResult& outValue, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::getIndexRecord");
ASSERT(objectStoreIdentifier);
if (!m_transactions.contains(transactionIdentifier))
return IDBError { UnknownError, "No backing store transaction found to get record"_s };
MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
if (!objectStore)
return IDBError { UnknownError, "No backing store object store found"_s };
outValue = objectStore->indexValueForKeyRange(indexIdentifier, recordType, range);
return IDBError { };
}
IDBError MemoryIDBBackingStore::getCount(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData& range, uint64_t& outCount, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::getCount");
ASSERT(objectStoreIdentifier);
if (!m_transactions.contains(transactionIdentifier))
return IDBError { UnknownError, "No backing store transaction found to get count"_s };
MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
if (!objectStore)
return IDBError { UnknownError, "No backing store object store found"_s };
outCount = objectStore->countForKeyRange(indexIdentifier, range);
return IDBError { };
}
IDBError MemoryIDBBackingStore::generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t& keyNumber, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::generateKeyNumber");
ASSERT(objectStoreIdentifier);
ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
ASSERT_UNUSED(transactionIdentifier, m_transactions.get(transactionIdentifier)->isWriting());
MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
RELEASE_ASSERT(objectStore);
keyNumber = objectStore->currentKeyGeneratorValue();
if (keyNumber > maxGeneratedKeyValue)
return IDBError { ConstraintError, "Cannot generate new key value over 2^53 for object store operation" };
objectStore->setKeyGeneratorValue(keyNumber + 1);
return IDBError { };
}
IDBError MemoryIDBBackingStore::revertGeneratedKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t keyNumber, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::revertGeneratedKeyNumber");
ASSERT(objectStoreIdentifier);
ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
ASSERT_UNUSED(transactionIdentifier, m_transactions.get(transactionIdentifier)->isWriting());
MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
RELEASE_ASSERT(objectStore);
objectStore->setKeyGeneratorValue(keyNumber);
return IDBError { };
}
IDBError MemoryIDBBackingStore::maybeUpdateKeyGeneratorNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, double newKeyNumber, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::maybeUpdateKeyGeneratorNumber");
ASSERT(objectStoreIdentifier);
ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
ASSERT_UNUSED(transactionIdentifier, m_transactions.get(transactionIdentifier)->isWriting());
MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
RELEASE_ASSERT(objectStore);
if (newKeyNumber < objectStore->currentKeyGeneratorValue())
return IDBError { };
if (newKeyNumber >= (double)maxGeneratedKeyValue) {
objectStore->setKeyGeneratorValue(maxGeneratedKeyValue + 1);
return IDBError { };
}
uint64_t newKeyInteger(newKeyNumber);
if (newKeyInteger <= uint64_t(newKeyNumber))
++newKeyInteger;
ASSERT(newKeyInteger > uint64_t(newKeyNumber));
objectStore->setKeyGeneratorValue(newKeyInteger);
return IDBError { };
}
IDBError MemoryIDBBackingStore::openCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo& info, IDBGetResult& outData, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::openCursor");
ASSERT(!MemoryCursor::cursorForIdentifier(info.identifier()));
if (!m_transactions.contains(transactionIdentifier))
return IDBError { UnknownError, "No backing store transaction found in which to open a cursor"_s };
switch (info.cursorSource()) {
case IndexedDB::CursorSource::ObjectStore: {
auto* objectStore = m_objectStoresByIdentifier.get(info.sourceIdentifier());
if (!objectStore)
return IDBError { UnknownError, "No backing store object store found"_s };
MemoryCursor* cursor = objectStore->maybeOpenCursor(info);
if (!cursor)
return IDBError { UnknownError, "Could not create object store cursor in backing store"_s };
cursor->currentData(outData);
break;
}
case IndexedDB::CursorSource::Index:
auto* objectStore = m_objectStoresByIdentifier.get(info.objectStoreIdentifier());
if (!objectStore)
return IDBError { UnknownError, "No backing store object store found"_s };
auto* index = objectStore->indexForIdentifier(info.sourceIdentifier());
if (!index)
return IDBError { UnknownError, "No backing store index found"_s };
MemoryCursor* cursor = index->maybeOpenCursor(info);
if (!cursor)
return IDBError { UnknownError, "Could not create index cursor in backing store"_s };
cursor->currentData(outData);
break;
}
return IDBError { };
}
IDBError MemoryIDBBackingStore::iterateCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, const IDBIterateCursorData& data, IDBGetResult& outData, const LockHolder&)
{
LOG(IndexedDB, "MemoryIDBBackingStore::iterateCursor");
if (!m_transactions.contains(transactionIdentifier))
return IDBError { UnknownError, "No backing store transaction found in which to iterate cursor"_s };
auto* cursor = MemoryCursor::cursorForIdentifier(cursorIdentifier);
if (!cursor)
return IDBError { UnknownError, "No backing store cursor found in which to iterate cursor"_s };
cursor->iterate(data.keyData, data.primaryKeyData, data.count, outData);
return IDBError { };
}
void MemoryIDBBackingStore::registerObjectStore(Ref<MemoryObjectStore>&& objectStore)
{
ASSERT(!m_objectStoresByIdentifier.contains(objectStore->info().identifier()));
ASSERT(!m_objectStoresByName.contains(objectStore->info().name()));
auto identifier = objectStore->info().identifier();
m_objectStoresByName.set(objectStore->info().name(), &objectStore.get());
m_objectStoresByIdentifier.set(identifier, WTFMove(objectStore));
}
void MemoryIDBBackingStore::unregisterObjectStore(MemoryObjectStore& objectStore)
{
ASSERT(m_objectStoresByIdentifier.contains(objectStore.info().identifier()));
ASSERT(m_objectStoresByName.contains(objectStore.info().name()));
m_objectStoresByName.remove(objectStore.info().name());
m_objectStoresByIdentifier.remove(objectStore.info().identifier());
}
RefPtr<MemoryObjectStore> MemoryIDBBackingStore::takeObjectStoreByIdentifier(uint64_t identifier)
{
auto objectStoreByIdentifier = m_objectStoresByIdentifier.take(identifier);
if (!objectStoreByIdentifier)
return nullptr;
auto objectStore = m_objectStoresByName.take(objectStoreByIdentifier->info().name());
ASSERT_UNUSED(objectStore, objectStore);
return objectStoreByIdentifier;
}
IDBObjectStoreInfo* MemoryIDBBackingStore::infoForObjectStore(uint64_t objectStoreIdentifier, const LockHolder&)
{
ASSERT(m_databaseInfo);
return m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
}
void MemoryIDBBackingStore::deleteBackingStore(const LockHolder&)
{
// The in-memory IDB backing store doesn't need to do any cleanup when it is deleted.
}
void MemoryIDBBackingStore::close(const LockHolder&)
{
}
} // namespace IDBServer
} // namespace WebCore
#endif // ENABLE(INDEXED_DATABASE)