/*
 * Copyright (C) 2015, 2016 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 "UniqueIDBDatabase.h"

#if ENABLE(INDEXED_DATABASE)

#include "IDBBindingUtilities.h"
#include "IDBCursorInfo.h"
#include "IDBGetAllRecordsData.h"
#include "IDBGetAllResult.h"
#include "IDBGetRecordData.h"
#include "IDBIterateCursorData.h"
#include "IDBKeyRangeData.h"
#include "IDBResultData.h"
#include "IDBServer.h"
#include "IDBTransactionInfo.h"
#include "IDBValue.h"
#include "Logging.h"
#include "SerializedScriptValue.h"
#include "StorageQuotaManager.h"
#include "UniqueIDBDatabaseConnection.h"
#include <JavaScriptCore/AuxiliaryBarrierInlines.h>
#include <JavaScriptCore/JSCInlines.h>
#include <JavaScriptCore/StrongInlines.h>
#include <wtf/MainThread.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/Scope.h>

namespace WebCore {
using namespace JSC;
namespace IDBServer {

static const uint64_t defaultWriteOperationCost = 4;

static inline uint64_t estimateSize(const IDBKeyData& keyData)
{
    uint64_t size = 4;
    switch (keyData.type()) {
    case IndexedDB::KeyType::String:
        size += keyData.string().sizeInBytes();
        break;
    case IndexedDB::KeyType::Binary: {
        size += keyData.binary().size();
        break;
    }
    case IndexedDB::KeyType::Array:
        for (auto& data : keyData.array())
            size += estimateSize(data);
        break;
    default:
        break;
    }
    return size;
}

static inline uint64_t estimateSize(const IDBValue& value)
{
    uint64_t size = 4;
    size += value.data().size();
    for (auto& url : value.blobURLs())
        size += url.sizeInBytes();
    for (auto& path : value.blobFilePaths())
        size += path.sizeInBytes();
    return size;
}

static inline uint64_t estimateSize(const IDBKeyPath& keyPath)
{
    return WTF::switchOn(keyPath, [](const String& path) {
        return static_cast<uint64_t>(path.sizeInBytes());
    }, [](const Vector<String>& paths) {
        uint64_t size = 0;
        for (auto path : paths)
            size += path.sizeInBytes();
        return size;
    });
}

static inline uint64_t estimateSize(const IDBIndexInfo& info)
{
    uint64_t size = 4;
    size += info.name().sizeInBytes();
    size += estimateSize(info.keyPath());
    return size;
}

static inline uint64_t estimateSize(const IDBObjectStoreInfo& info)
{
    uint64_t size = 4;
    size += info.name().sizeInBytes();
    if (auto keyPath = info.keyPath())
        size += estimateSize(*keyPath);
    return size;
}

UniqueIDBDatabase::UniqueIDBDatabase(IDBServer& server, const IDBDatabaseIdentifier& identifier)
    : m_server(server)
    , m_identifier(identifier)
    , m_operationAndTransactionTimer(*this, &UniqueIDBDatabase::operationAndTransactionTimerFired)
{
    LOG(IndexedDB, "UniqueIDBDatabase::UniqueIDBDatabase() (%p) %s", this, m_identifier.debugString().utf8().data());
}

UniqueIDBDatabase::~UniqueIDBDatabase()
{
    LOG(IndexedDB, "UniqueIDBDatabase::~UniqueIDBDatabase() (%p) %s", this, m_identifier.debugString().utf8().data());
    ASSERT(isMainThread());
    ASSERT(!hasAnyPendingCallbacks());
    ASSERT(!hasUnfinishedTransactions());
    ASSERT(m_pendingTransactions.isEmpty());
    ASSERT(m_openDatabaseConnections.isEmpty());
    ASSERT(m_clientClosePendingDatabaseConnections.isEmpty());
    ASSERT(m_serverClosePendingDatabaseConnections.isEmpty());

    RELEASE_ASSERT(m_databaseQueue.isKilled());
    RELEASE_ASSERT(m_databaseReplyQueue.isKilled());
    RELEASE_ASSERT(!m_backingStore);
}

const IDBDatabaseInfo& UniqueIDBDatabase::info() const
{
    RELEASE_ASSERT(m_databaseInfo);
    return *m_databaseInfo;
}

void UniqueIDBDatabase::openDatabaseConnection(IDBConnectionToClient& connection, const IDBRequestData& requestData)
{
    LOG(IndexedDB, "UniqueIDBDatabase::openDatabaseConnection");
    ASSERT(!m_hardClosedForUserDelete);
    ASSERT(isMainThread());

    m_pendingOpenDBRequests.add(ServerOpenDBRequest::create(connection, requestData));

    // An open operation is already in progress, so we can't possibly handle this one yet.
    if (m_isOpeningBackingStore)
        return;

    handleDatabaseOperations();
}

bool UniqueIDBDatabase::hasAnyPendingCallbacks() const
{
    return !m_errorCallbacks.isEmpty()
        || !m_keyDataCallbacks.isEmpty()
        || !m_getResultCallbacks.isEmpty()
        || !m_getAllResultsCallbacks.isEmpty()
        || !m_countCallbacks.isEmpty();
}

bool UniqueIDBDatabase::isVersionChangeInProgress()
{
#if !LOG_DISABLED
    if (m_versionChangeTransaction)
        ASSERT(m_versionChangeDatabaseConnection);
#endif

    return m_versionChangeDatabaseConnection;
}

static inline String quotaErrorMessageName(const char* taskName)
{
    return makeString("Failed to ", taskName, " in database because not enough space for domain");
}

void UniqueIDBDatabase::requestSpace(UniqueIDBDatabaseTransaction& transaction, uint64_t taskSize, const char* taskName, CompletionHandler<void(IDBError&&)>&& callback)
{
    m_server->requestSpace(m_identifier.origin(), taskSize, [weakThis = makeWeakPtr(this), this, weakTransaction = makeWeakPtr(transaction), taskName, callback = WTFMove(callback)](auto decision) mutable {
        if (!weakThis) {
            callback(IDBError { UnknownError });
            return;
        }

        if (!weakTransaction) {
            callback(IDBError { UnknownError });
            return;
        }
        if (m_owningPointerForClose) {
            // We are closing the database, there is no point in trying to modify the database at that point.
            callback(IDBError { UnknownError });
            return;
        }

        switch (decision) {
        case StorageQuotaManager::Decision::Deny:
            callback(IDBError { QuotaExceededError, quotaErrorMessageName(taskName) });
            return;
        case StorageQuotaManager::Decision::Grant:
            callback(IDBError { });
        };
    });
}

void UniqueIDBDatabase::waitForRequestSpaceCompletion(UniqueIDBDatabaseTransaction& transaction, CompletionHandler<void(IDBError&&)>&& callback)
{
    requestSpace(transaction, 0, "", WTFMove(callback));
}

void UniqueIDBDatabase::startSpaceIncreaseTask(uint64_t identifier, uint64_t taskSize)
{
    m_server->increasePotentialSpaceUsed(m_identifier.origin(), taskSize);
    ASSERT(!m_pendingSpaceIncreaseTasks.contains(identifier));
    m_pendingSpaceIncreaseTasks.add(identifier, taskSize);
}

void UniqueIDBDatabase::finishSpaceIncreaseTask(uint64_t identifier, bool isTaskSuccessful)
{
    auto iterator = m_pendingSpaceIncreaseTasks.find(identifier);
    ASSERT(iterator != m_pendingSpaceIncreaseTasks.end());
    m_server->decreasePotentialSpaceUsed(m_identifier.origin(), iterator->value);
    if (isTaskSuccessful)
        m_server->increaseSpaceUsed(m_identifier.origin(), iterator->value);
    m_pendingSpaceIncreaseTasks.remove(iterator);
}

void UniqueIDBDatabase::performCurrentOpenOperation()
{
    LOG(IndexedDB, "(main) UniqueIDBDatabase::performCurrentOpenOperation (%p)", this);

    ASSERT(m_currentOpenDBRequest);
    ASSERT(m_currentOpenDBRequest->isOpenRequest());

    if (!m_databaseInfo) {
        if (!m_isOpeningBackingStore) {
            m_isOpeningBackingStore = true;
            // We do not know whether this is an existing or a new database.
            // We set a small cost so that it is not possible to open an infinite number of database.
            m_server->requestSpace(m_identifier.origin(), defaultWriteOperationCost, [this, weakThis = makeWeakPtr(this)](auto decision) mutable {
                if (!weakThis)
                    return;

                if (m_owningPointerForClose)
                    return;

                switch (decision) {
                case StorageQuotaManager::Decision::Deny: {
                    auto result = IDBResultData::error(m_currentOpenDBRequest->requestData().requestIdentifier(), IDBError { QuotaExceededError, quotaErrorMessageName("openDatabase") });
                    m_currentOpenDBRequest->connection().didOpenDatabase(result);
                    m_currentOpenDBRequest = nullptr;
                    m_isOpeningBackingStore = false;
                    break;
                }
                case StorageQuotaManager::Decision::Grant:
                    auto callbackID = this->generateUniqueCallbackIdentifier();
                    startSpaceIncreaseTask(callbackID, defaultWriteOperationCost);
                    this->postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::openBackingStore, m_identifier, callbackID));
                };
            });
        }
        return;
    }

    // If we previously started a version change operation but were blocked by having open connections,
    // we might now be unblocked.
    if (m_versionChangeDatabaseConnection) {
        if (!m_versionChangeTransaction && !hasAnyOpenConnections())
            startVersionChangeTransaction();
        return;
    }

    // 3.3.1 Opening a database
    // If requested version is undefined, then let requested version be 1 if db was created in the previous step,
    // or the current version of db otherwise.
    uint64_t requestedVersion = m_currentOpenDBRequest->requestData().requestedVersion();
    if (!requestedVersion)
        requestedVersion = m_databaseInfo->version() ? m_databaseInfo->version() : 1;

    // 3.3.1 Opening a database
    // If the database version higher than the requested version, abort these steps and return a VersionError.
    if (requestedVersion < m_databaseInfo->version()) {
        auto result = IDBResultData::error(m_currentOpenDBRequest->requestData().requestIdentifier(), IDBError(VersionError));
        m_currentOpenDBRequest->connection().didOpenDatabase(result);
        m_currentOpenDBRequest = nullptr;

        return;
    }

    if (!m_backingStoreOpenError.isNull()) {
        auto result = IDBResultData::error(m_currentOpenDBRequest->requestData().requestIdentifier(), m_backingStoreOpenError);
        m_currentOpenDBRequest->connection().didOpenDatabase(result);
        m_currentOpenDBRequest = nullptr;

        return;
    }

    Ref<UniqueIDBDatabaseConnection> connection = UniqueIDBDatabaseConnection::create(*this, *m_currentOpenDBRequest);

    if (requestedVersion == m_databaseInfo->version()) {
        auto* rawConnection = &connection.get();
        addOpenDatabaseConnection(WTFMove(connection));

        auto result = IDBResultData::openDatabaseSuccess(m_currentOpenDBRequest->requestData().requestIdentifier(), *rawConnection);
        m_currentOpenDBRequest->connection().didOpenDatabase(result);
        m_currentOpenDBRequest = nullptr;

        return;
    }

    ASSERT(!m_versionChangeDatabaseConnection);
    m_versionChangeDatabaseConnection = WTFMove(connection);

    // 3.3.7 "versionchange" transaction steps
    // If there's no other open connections to this database, the version change process can begin immediately.
    if (!hasAnyOpenConnections()) {
        startVersionChangeTransaction();
        return;
    }

    // Otherwise we have to notify all those open connections and wait for them to close.
    maybeNotifyConnectionsOfVersionChange();
}

void UniqueIDBDatabase::performCurrentDeleteOperation()
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::performCurrentDeleteOperation - %s", m_identifier.debugString().utf8().data());

    ASSERT(m_currentOpenDBRequest);
    ASSERT(m_currentOpenDBRequest->isDeleteRequest());

    if (m_deleteBackingStoreInProgress)
        return;

    if (hasAnyOpenConnections()) {
        maybeNotifyConnectionsOfVersionChange();
        return;
    }

    if (hasUnfinishedTransactions())
        return;

    ASSERT(!hasAnyPendingCallbacks());
    ASSERT(m_pendingTransactions.isEmpty());
    ASSERT(m_openDatabaseConnections.isEmpty());

    // It's possible to have multiple delete requests queued up in a row.
    // In that scenario only the first request will actually have to delete the database.
    // Subsequent requests can immediately notify their completion.

    if (!m_deleteBackingStoreInProgress) {
        if (!m_databaseInfo && m_mostRecentDeletedDatabaseInfo)
            didDeleteBackingStore(0);
        else {
            m_deleteBackingStoreInProgress = true;
            postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::deleteBackingStore, m_identifier));
        }
    }
}

void UniqueIDBDatabase::deleteBackingStore(const IDBDatabaseIdentifier& identifier)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::deleteBackingStore");

    uint64_t deletedVersion = 0;

    if (m_backingStore) {
        m_backingStore->deleteBackingStore();

        m_backingStore = nullptr;
        m_backingStoreSupportsSimultaneousTransactions = false;
        m_backingStoreIsEphemeral = false;
    } else {
        auto backingStore = m_server->createBackingStore(identifier);

        IDBDatabaseInfo databaseInfo;
        auto error = backingStore->getOrEstablishDatabaseInfo(databaseInfo);
        if (!error.isNull())
            LOG_ERROR("Error getting database info from database %s that we are trying to delete", identifier.debugString().utf8().data());

        deletedVersion = databaseInfo.version();
        backingStore->deleteBackingStore();
    }

    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didDeleteBackingStore, deletedVersion));
}

void UniqueIDBDatabase::performUnconditionalDeleteBackingStore()
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performUnconditionalDeleteBackingStore");

    if (m_backingStore)
        m_backingStore->deleteBackingStore();

    shutdownForClose();
}

void UniqueIDBDatabase::scheduleShutdownForClose()
{
    ASSERT(isMainThread());

    m_operationAndTransactionTimer.stop();

    RELEASE_ASSERT(!m_owningPointerForClose);
    m_owningPointerForClose = m_server->closeAndTakeUniqueIDBDatabase(*this);

    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::shutdownForClose));
}

void UniqueIDBDatabase::shutdownForClose()
{
    ASSERT(!isMainThread());
    ASSERT(m_owningPointerForClose.get() == this);

    LOG(IndexedDB, "(db) UniqueIDBDatabase::shutdownForClose");

    if (m_backingStore)
        m_backingStore->close();

    m_backingStore = nullptr;
    m_backingStoreSupportsSimultaneousTransactions = false;
    m_backingStoreIsEphemeral = false;

    if (!m_databaseQueue.isEmpty()) {
        postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::shutdownForClose));
        return;
    }
    m_databaseQueue.kill();

    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didShutdownForClose));
}

void UniqueIDBDatabase::didShutdownForClose()
{
    ASSERT(m_databaseReplyQueue.isEmpty());
    m_databaseReplyQueue.kill();
}

void UniqueIDBDatabase::didDeleteBackingStore(uint64_t deletedVersion)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didDeleteBackingStore");

    ASSERT(!hasAnyPendingCallbacks());
    ASSERT(!hasUnfinishedTransactions());
    ASSERT(m_pendingTransactions.isEmpty());
    ASSERT(m_openDatabaseConnections.isEmpty());
    ASSERT(!m_backingStore);

    // It's possible that the openDBRequest was cancelled from client-side after the delete was already dispatched to the backingstore.
    // So it's okay if we don't have a currentOpenDBRequest, but if we do it has to be a deleteRequest.
    ASSERT(!m_currentOpenDBRequest || m_currentOpenDBRequest->isDeleteRequest());

    if (m_databaseInfo)
        m_mostRecentDeletedDatabaseInfo = WTFMove(m_databaseInfo);

    // If this UniqueIDBDatabase was brought into existence for the purpose of deleting the file on disk,
    // we won't have a m_mostRecentDeletedDatabaseInfo. In that case, we'll manufacture one using the
    // passed in deletedVersion argument.
    if (!m_mostRecentDeletedDatabaseInfo)
        m_mostRecentDeletedDatabaseInfo = makeUnique<IDBDatabaseInfo>(m_identifier.databaseName(), deletedVersion);

    if (m_currentOpenDBRequest) {
        m_currentOpenDBRequest->notifyDidDeleteDatabase(*m_mostRecentDeletedDatabaseInfo);
        m_currentOpenDBRequest = nullptr;
    }

    m_deleteBackingStoreInProgress = false;

    if (m_hardClosedForUserDelete)
        return;

    invokeOperationAndTransactionTimer();
}

void UniqueIDBDatabase::clearStalePendingOpenDBRequests()
{
    while (!m_pendingOpenDBRequests.isEmpty() && m_pendingOpenDBRequests.first()->connection().isClosed())
        m_pendingOpenDBRequests.removeFirst();
}

void UniqueIDBDatabase::handleDatabaseOperations()
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::handleDatabaseOperations - There are %u pending", m_pendingOpenDBRequests.size());
    ASSERT(!m_hardClosedForUserDelete);

    if (m_deleteBackingStoreInProgress || m_isOpeningBackingStore)
        return;

    clearStalePendingOpenDBRequests();

    if (m_versionChangeDatabaseConnection || m_versionChangeTransaction || (m_currentOpenDBRequest && !m_currentOpenDBRequest->connection().isClosed())) {
        // We can't start any new open-database operations right now, but we might be able to start handling a delete operation.
        if (!m_currentOpenDBRequest && !m_pendingOpenDBRequests.isEmpty() && m_pendingOpenDBRequests.first()->isDeleteRequest())
            m_currentOpenDBRequest = m_pendingOpenDBRequests.takeFirst();

        // Some operations (such as the first open operation after a delete) require multiple passes to completely handle
        if (m_currentOpenDBRequest)
            handleCurrentOperation();

        return;
    }

    if (m_pendingOpenDBRequests.isEmpty()) {
        m_currentOpenDBRequest = nullptr;
        return;
    }

    m_currentOpenDBRequest = m_pendingOpenDBRequests.takeFirst();
    LOG(IndexedDB, "UniqueIDBDatabase::handleDatabaseOperations - Popped an operation, now there are %u pending", m_pendingOpenDBRequests.size());

    handleCurrentOperation();
}

void UniqueIDBDatabase::handleCurrentOperation()
{
    LOG(IndexedDB, "(main) UniqueIDBDatabase::handleCurrentOperation");
    ASSERT(!m_hardClosedForUserDelete);
    ASSERT(m_currentOpenDBRequest);

    if (m_currentOpenDBRequest->isOpenRequest())
        performCurrentOpenOperation();
    else if (m_currentOpenDBRequest->isDeleteRequest())
        performCurrentDeleteOperation();
    else
        ASSERT_NOT_REACHED();

    if (!m_currentOpenDBRequest)
        invokeOperationAndTransactionTimer();
}

bool UniqueIDBDatabase::hasAnyOpenConnections() const
{
    return !m_openDatabaseConnections.isEmpty();
}

bool UniqueIDBDatabase::allConnectionsAreClosedOrClosing() const
{
    for (auto& connection : m_openDatabaseConnections) {
        if (!connection->connectionIsClosing())
            return false;
    }

    return true;
}

uint64_t UniqueIDBDatabase::generateUniqueCallbackIdentifier()
{
    ASSERT(isMainThread());
    static uint64_t currentID = 0;
    return ++currentID;
}

uint64_t UniqueIDBDatabase::storeCallbackOrFireError(ErrorCallback&& callback)
{
    if (m_hardClosedForUserDelete) {
        callback(IDBError::userDeleteError());
        return 0;
    }

    uint64_t identifier = generateUniqueCallbackIdentifier();
    ASSERT(!m_errorCallbacks.contains(identifier));
    m_errorCallbacks.add(identifier, WTFMove(callback));

    m_callbackQueue.append(identifier);
    return identifier;
}

uint64_t UniqueIDBDatabase::storeCallbackOrFireError(KeyDataCallback&& callback)
{
    if (m_hardClosedForUserDelete) {
        callback(IDBError::userDeleteError(), { });
        return 0;
    }

    uint64_t identifier = generateUniqueCallbackIdentifier();
    ASSERT(!m_keyDataCallbacks.contains(identifier));
    m_keyDataCallbacks.add(identifier, WTFMove(callback));

    m_callbackQueue.append(identifier);
    return identifier;
}

uint64_t UniqueIDBDatabase::storeCallbackOrFireError(GetResultCallback&& callback)
{
    if (m_hardClosedForUserDelete) {
        callback(IDBError::userDeleteError(), { });
        return 0;
    }

    uint64_t identifier = generateUniqueCallbackIdentifier();
    ASSERT(!m_getResultCallbacks.contains(identifier));
    m_getResultCallbacks.add(identifier, WTFMove(callback));
    m_callbackQueue.append(identifier);
    return identifier;
}

uint64_t UniqueIDBDatabase::storeCallbackOrFireError(GetAllResultsCallback&& callback)
{
    if (m_hardClosedForUserDelete) {
        callback(IDBError::userDeleteError(), { });
        return 0;
    }

    uint64_t identifier = generateUniqueCallbackIdentifier();
    ASSERT(!m_getAllResultsCallbacks.contains(identifier));
    m_getAllResultsCallbacks.add(identifier, WTFMove(callback));
    m_callbackQueue.append(identifier);
    return identifier;
}

uint64_t UniqueIDBDatabase::storeCallbackOrFireError(CountCallback&& callback)
{
    if (m_hardClosedForUserDelete) {
        callback(IDBError::userDeleteError(), 0);
        return 0;
    }

    uint64_t identifier = generateUniqueCallbackIdentifier();
    ASSERT(!m_countCallbacks.contains(identifier));
    m_countCallbacks.add(identifier, WTFMove(callback));
    m_callbackQueue.append(identifier);
    return identifier;
}

void UniqueIDBDatabase::handleDelete(IDBConnectionToClient& connection, const IDBRequestData& requestData)
{
    LOG(IndexedDB, "(main) UniqueIDBDatabase::handleDelete");
    ASSERT(!m_hardClosedForUserDelete);

    m_pendingOpenDBRequests.add(ServerOpenDBRequest::create(connection, requestData));
    handleDatabaseOperations();
}

void UniqueIDBDatabase::startVersionChangeTransaction()
{
    LOG(IndexedDB, "(main) UniqueIDBDatabase::startVersionChangeTransaction");

    ASSERT(!m_versionChangeTransaction);
    ASSERT(m_currentOpenDBRequest);
    ASSERT(m_currentOpenDBRequest->isOpenRequest());
    ASSERT(m_versionChangeDatabaseConnection);

    uint64_t requestedVersion = m_currentOpenDBRequest->requestData().requestedVersion();
    if (!requestedVersion)
        requestedVersion = m_databaseInfo->version() ? m_databaseInfo->version() : 1;

    m_versionChangeTransaction = &m_versionChangeDatabaseConnection->createVersionChangeTransaction(requestedVersion);
    m_inProgressTransactions.set(m_versionChangeTransaction->info().identifier(), m_versionChangeTransaction);

    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performStartVersionChangeTransaction, m_versionChangeTransaction->info()));
}

void UniqueIDBDatabase::performStartVersionChangeTransaction(const IDBTransactionInfo& info)
{
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performStartVersionChangeTransaction");

    IDBError error = m_backingStore->beginTransaction(info);
    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformStartVersionChangeTransaction, error));
}

void UniqueIDBDatabase::didPerformStartVersionChangeTransaction(const IDBError& error)
{
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformStartVersionChangeTransaction");

    // Open request may already be canceled by client or user, or connection to client is lost.
    if (!m_versionChangeDatabaseConnection)
        return;
    
    ASSERT(m_currentOpenDBRequest);
    ASSERT(m_versionChangeTransaction);
    auto operation = WTFMove(m_currentOpenDBRequest);
    IDBResultData result;
    if (error.isNull()) {
        addOpenDatabaseConnection(*m_versionChangeDatabaseConnection);
        m_databaseInfo->setVersion(m_versionChangeTransaction->info().newVersion());
        result = IDBResultData::openDatabaseUpgradeNeeded(operation->requestData().requestIdentifier(), *m_versionChangeTransaction);
        operation->connection().didOpenDatabase(result);
    } else {
        m_versionChangeDatabaseConnection->abortTransactionWithoutCallback(*m_versionChangeTransaction);
        m_versionChangeDatabaseConnection = nullptr;
        result = IDBResultData::error(operation->requestData().requestIdentifier(), error);
        operation->connection().didOpenDatabase(result);
    }

    invokeOperationAndTransactionTimer();
}

void UniqueIDBDatabase::maybeNotifyConnectionsOfVersionChange()
{
    ASSERT(m_currentOpenDBRequest);

    if (m_currentOpenDBRequest->hasNotifiedConnectionsOfVersionChange())
        return;

    uint64_t newVersion = m_currentOpenDBRequest->isOpenRequest() ? m_currentOpenDBRequest->requestData().requestedVersion() : 0;
    auto requestIdentifier = m_currentOpenDBRequest->requestData().requestIdentifier();

    LOG(IndexedDB, "(main) UniqueIDBDatabase::notifyConnectionsOfVersionChange - %" PRIu64, newVersion);

    // 3.3.7 "versionchange" transaction steps
    // Fire a versionchange event at each connection in m_openDatabaseConnections that is open.
    // The event must not be fired on connections which has the closePending flag set.
    HashSet<uint64_t> connectionIdentifiers;
    for (const auto& connection : m_openDatabaseConnections) {
        if (connection->closePending())
            continue;

        connection->fireVersionChangeEvent(requestIdentifier, newVersion);
        connectionIdentifiers.add(connection->identifier());
    }

    if (!connectionIdentifiers.isEmpty())
        m_currentOpenDBRequest->notifiedConnectionsOfVersionChange(WTFMove(connectionIdentifiers));
    else
        m_currentOpenDBRequest->maybeNotifyRequestBlocked(m_databaseInfo->version());
}

void UniqueIDBDatabase::notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent(uint64_t connectionIdentifier)
{
    LOG(IndexedDB, "UniqueIDBDatabase::notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent - %" PRIu64, connectionIdentifier);

    ASSERT(m_currentOpenDBRequest);

    m_currentOpenDBRequest->connectionClosedOrFiredVersionChangeEvent(connectionIdentifier);

    if (m_currentOpenDBRequest->hasConnectionsPendingVersionChangeEvent())
        return;

    if (!hasAnyOpenConnections() || allConnectionsAreClosedOrClosing()) {
        invokeOperationAndTransactionTimer();
        return;
    }

    // Since all open connections have fired their version change events but not all of them have closed,
    // this request is officially blocked.
    m_currentOpenDBRequest->maybeNotifyRequestBlocked(m_databaseInfo->version());
}

void UniqueIDBDatabase::didFireVersionChangeEvent(UniqueIDBDatabaseConnection& connection, const IDBResourceIdentifier& requestIdentifier)
{
    LOG(IndexedDB, "UniqueIDBDatabase::didFireVersionChangeEvent");

    if (!m_currentOpenDBRequest)
        return;

    ASSERT_UNUSED(requestIdentifier, m_currentOpenDBRequest->requestData().requestIdentifier() == requestIdentifier);

    notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent(connection.identifier());
}

void UniqueIDBDatabase::openDBRequestCancelled(const IDBResourceIdentifier& requestIdentifier)
{
    LOG(IndexedDB, "UniqueIDBDatabase::openDBRequestCancelled - %s", requestIdentifier.loggingString().utf8().data());

    if (m_currentOpenDBRequest && m_currentOpenDBRequest->requestData().requestIdentifier() == requestIdentifier)
        m_currentOpenDBRequest = nullptr;

    if (m_versionChangeDatabaseConnection && m_versionChangeDatabaseConnection->openRequestIdentifier() == requestIdentifier) {
        ASSERT(!m_versionChangeTransaction || m_versionChangeTransaction->databaseConnection().openRequestIdentifier() == requestIdentifier);
        ASSERT(!m_versionChangeTransaction || &m_versionChangeTransaction->databaseConnection() == m_versionChangeDatabaseConnection);

        connectionClosedFromClient(*m_versionChangeDatabaseConnection);
    }

    for (auto& request : m_pendingOpenDBRequests) {
        if (request->requestData().requestIdentifier() == requestIdentifier) {
            m_pendingOpenDBRequests.remove(request);
            return;
        }
    }
}

void UniqueIDBDatabase::addOpenDatabaseConnection(Ref<UniqueIDBDatabaseConnection>&& connection)
{
    ASSERT(!m_openDatabaseConnections.contains(&connection.get()));
    m_openDatabaseConnections.add(adoptRef(connection.leakRef()));
}

void UniqueIDBDatabase::openBackingStore(const IDBDatabaseIdentifier& identifier, uint64_t taskIdentifier)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::openBackingStore (%p)", this);

    ASSERT(!m_backingStore);
    m_backingStore = m_server->createBackingStore(identifier);
    m_backingStoreSupportsSimultaneousTransactions = m_backingStore->supportsSimultaneousTransactions();
    m_backingStoreIsEphemeral = m_backingStore->isEphemeral();

    IDBDatabaseInfo databaseInfo;
    auto error = m_backingStore->getOrEstablishDatabaseInfo(databaseInfo);

    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didOpenBackingStore, databaseInfo, error,  taskIdentifier));
}

void UniqueIDBDatabase::didOpenBackingStore(const IDBDatabaseInfo& info, const IDBError& error, uint64_t taskIdentifier)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didOpenBackingStore");
    
    m_databaseInfo = makeUnique<IDBDatabaseInfo>(info);
    m_backingStoreOpenError = error;

    ASSERT(m_isOpeningBackingStore);
    m_isOpeningBackingStore = false;

    finishSpaceIncreaseTask(taskIdentifier, error.isNull());

    if (m_hardClosedForUserDelete)
        return;

    handleDatabaseOperations();
}

void UniqueIDBDatabase::createObjectStore(UniqueIDBDatabaseTransaction& transaction, const IDBObjectStoreInfo& info, ErrorCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::createObjectStore");

    auto taskSize = defaultWriteOperationCost + estimateSize(info);
    requestSpace(transaction, taskSize, "createObjectStore", [this, taskSize, &transaction, info, callback = WTFMove(callback)](auto error) mutable {
        if (!error.isNull() && *error.code() != QuotaExceededError) {
            callback(WTFMove(error));
            return;
        }
        this->createObjectStoreAfterQuotaCheck(taskSize, transaction, info, WTFMove(callback), error);
    });
}

void UniqueIDBDatabase::createObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, const IDBObjectStoreInfo& info, ErrorCallback callback, const IDBError& quotaError)
{
    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;

    startSpaceIncreaseTask(callbackID, taskSize);
    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateObjectStore, callbackID, transaction.info().identifier(), info,  quotaError));
}

void UniqueIDBDatabase::performCreateObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& info, const IDBError& quotaError)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performCreateObjectStore");

    if (!quotaError.isNull()) {
        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateObjectStore, callbackIdentifier, quotaError, info));
        return;
    }

    ASSERT(m_backingStore);
    m_backingStore->createObjectStore(transactionIdentifier, info);

    IDBError error;
    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateObjectStore, callbackIdentifier, error, info));
}

void UniqueIDBDatabase::didPerformCreateObjectStore(uint64_t callbackIdentifier, const IDBError& error, const IDBObjectStoreInfo& info)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCreateObjectStore");

    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
    if (error.isNull())
        m_databaseInfo->addExistingObjectStore(info);

    performErrorCallback(callbackIdentifier, error);
}

void UniqueIDBDatabase::deleteObjectStore(UniqueIDBDatabaseTransaction& transaction, const String& objectStoreName, ErrorCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteObjectStore");

    waitForRequestSpaceCompletion(transaction, [this, &transaction, objectStoreName, callback = WTFMove(callback)](auto&& error) mutable {
        if (!error.isNull()) {
            callback(WTFMove(error));
            return;
        }
        this->deleteObjectStoreAfterQuotaCheck(transaction, objectStoreName, WTFMove(callback));
    });
}

void UniqueIDBDatabase::deleteObjectStoreAfterQuotaCheck(UniqueIDBDatabaseTransaction& transaction, const String& objectStoreName, ErrorCallback callback)
{
    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;

    auto* info = m_databaseInfo->infoForExistingObjectStore(objectStoreName);
    if (!info) {
        performErrorCallback(callbackID, IDBError { UnknownError, "Attempt to delete non-existant object store"_s });
        return;
    }

    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performDeleteObjectStore, callbackID, transaction.info().identifier(), info->identifier()));
}

void UniqueIDBDatabase::performDeleteObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performDeleteObjectStore");

    ASSERT(m_backingStore);
    m_backingStore->deleteObjectStore(transactionIdentifier, objectStoreIdentifier);

    IDBError error;
    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformDeleteObjectStore, callbackIdentifier, error, objectStoreIdentifier));
}

void UniqueIDBDatabase::didPerformDeleteObjectStore(uint64_t callbackIdentifier, const IDBError& error, uint64_t objectStoreIdentifier)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformDeleteObjectStore");

    if (error.isNull())
        m_databaseInfo->deleteObjectStore(objectStoreIdentifier);

    performErrorCallback(callbackIdentifier, error);
}

void UniqueIDBDatabase::renameObjectStore(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, const String& newName, ErrorCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::renameObjectStore");

    auto taskSize = defaultWriteOperationCost + newName.sizeInBytes();
    requestSpace(transaction, taskSize, "renameObjectStore", [this, taskSize, &transaction, objectStoreIdentifier, newName, callback = WTFMove(callback)](auto error) mutable {
        if (!error.isNull() && *error.code() != QuotaExceededError) {
            callback(WTFMove(error));
            return;
        }
        this->renameObjectStoreAfterQuotaCheck(taskSize, transaction, objectStoreIdentifier, newName, WTFMove(callback), error);
    });
}

void UniqueIDBDatabase::renameObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, const String& newName, ErrorCallback callback, const IDBError& quotaError)
{
    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;

    IDBError error = quotaError;
    auto* info = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
    if (!info)
        error = IDBError { UnknownError, "Attempt to rename non-existant object store"_s };

    startSpaceIncreaseTask(callbackID, taskSize);
    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performRenameObjectStore, callbackID, transaction.info().identifier(), objectStoreIdentifier, newName, error));
}

void UniqueIDBDatabase::performRenameObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const String& newName, const IDBError& error)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performRenameObjectStore");

    if (!error.isNull()) {
        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformRenameObjectStore, callbackIdentifier, error, objectStoreIdentifier, newName));
        return;
    }

    ASSERT(m_backingStore);
    m_backingStore->renameObjectStore(transactionIdentifier, objectStoreIdentifier, newName);

    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformRenameObjectStore, callbackIdentifier, error, objectStoreIdentifier, newName));
}

void UniqueIDBDatabase::didPerformRenameObjectStore(uint64_t callbackIdentifier, const IDBError& error, uint64_t objectStoreIdentifier, const String& newName)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformRenameObjectStore");

    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
    if (error.isNull())
        m_databaseInfo->renameObjectStore(objectStoreIdentifier, newName);

    performErrorCallback(callbackIdentifier, error);
}

void UniqueIDBDatabase::clearObjectStore(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, ErrorCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::clearObjectStore");

    waitForRequestSpaceCompletion(transaction, [this, &transaction, objectStoreIdentifier, callback = WTFMove(callback)](auto&& error) mutable {
        if (!error.isNull()) {
            callback(WTFMove(error));
            return;
        }
        this->clearObjectStoreAfetQuotaCheck(transaction, objectStoreIdentifier, WTFMove(callback));
    });
}

void UniqueIDBDatabase::clearObjectStoreAfetQuotaCheck(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, ErrorCallback callback)
{
    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;
    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performClearObjectStore, callbackID, transaction.info().identifier(), objectStoreIdentifier));
}

void UniqueIDBDatabase::performClearObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performClearObjectStore");

    ASSERT(m_backingStore);
    m_backingStore->clearObjectStore(transactionIdentifier, objectStoreIdentifier);

    IDBError error;
    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformClearObjectStore, callbackIdentifier, error));
}

void UniqueIDBDatabase::didPerformClearObjectStore(uint64_t callbackIdentifier, const IDBError& error)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformClearObjectStore");

    performErrorCallback(callbackIdentifier, error);
}

void UniqueIDBDatabase::createIndex(UniqueIDBDatabaseTransaction& transaction, const IDBIndexInfo& info, ErrorCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::createIndex");

    auto taskSize = defaultWriteOperationCost + estimateSize(info);
    requestSpace(transaction, taskSize, "createIndex", [this, taskSize, &transaction, info, callback = WTFMove(callback)](auto error) mutable {
        if (!error.isNull() && *error.code() != QuotaExceededError) {
            callback(WTFMove(error));
            return;
        }
        this->createIndexAfterQuotaCheck(taskSize, transaction, info, WTFMove(callback), error);
    });
}

void UniqueIDBDatabase::createIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, const IDBIndexInfo& info, ErrorCallback callback, const IDBError& quotaError)
{
    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;

    startSpaceIncreaseTask(callbackID, taskSize);
    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateIndex, callbackID, transaction.info().identifier(), info, quotaError));
}

void UniqueIDBDatabase::performCreateIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo& info, const IDBError& quotaError)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performCreateIndex");

    if (!quotaError.isNull()) {
        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateIndex, callbackIdentifier, quotaError, info));
        return;
    }

    IDBError error;
    ASSERT(m_backingStore);
    if (!m_backingStore) {
        RELEASE_LOG_ERROR(IndexedDB, "%p - UniqueIDBDatabase::performCreateIndex: m_backingStore is null", this);
        error = IDBError(InvalidStateError, "Backing store is invalid for call to create index"_s);
        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateIndex, callbackIdentifier, error, info));
        return;
    }

    error = m_backingStore->createIndex(transactionIdentifier, info);
    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateIndex, callbackIdentifier, error, info));
}

void UniqueIDBDatabase::didPerformCreateIndex(uint64_t callbackIdentifier, const IDBError& error, const IDBIndexInfo& info)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCreateIndex");

    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());

    if (error.isNull()) {
        ASSERT(m_databaseInfo);
        auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(info.objectStoreIdentifier());
        ASSERT(objectStoreInfo);
        objectStoreInfo->addExistingIndex(info);
    }

    performErrorCallback(callbackIdentifier, error);
}

void UniqueIDBDatabase::deleteIndex(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, const String& indexName, ErrorCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteIndex");

    waitForRequestSpaceCompletion(transaction, [this, &transaction, objectStoreIdentifier, indexName, callback = WTFMove(callback)](auto&& error) mutable {
        if (!error.isNull()) {
            callback(WTFMove(error));
            return;
        }
        this->deleteIndexAfterQuotaCheck(transaction, objectStoreIdentifier, indexName, WTFMove(callback));
    });
}

void UniqueIDBDatabase::deleteIndexAfterQuotaCheck(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, const String& indexName, ErrorCallback callback)
{
    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;

    auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
    if (!objectStoreInfo) {
        performErrorCallback(callbackID, IDBError { UnknownError, "Attempt to delete index from non-existant object store"_s });
        return;
    }

    auto* indexInfo = objectStoreInfo->infoForExistingIndex(indexName);
    if (!indexInfo) {
        performErrorCallback(callbackID, IDBError { UnknownError, "Attempt to delete non-existant index"_s });
        return;
    }

    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performDeleteIndex, callbackID, transaction.info().identifier(), objectStoreIdentifier, indexInfo->identifier()));
}

void UniqueIDBDatabase::performDeleteIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const uint64_t indexIdentifier)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performDeleteIndex");

    ASSERT(m_backingStore);
    m_backingStore->deleteIndex(transactionIdentifier, objectStoreIdentifier, indexIdentifier);

    IDBError error;
    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformDeleteIndex, callbackIdentifier, error, objectStoreIdentifier, indexIdentifier));
}

void UniqueIDBDatabase::didPerformDeleteIndex(uint64_t callbackIdentifier, const IDBError& error, uint64_t objectStoreIdentifier, uint64_t indexIdentifier)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformDeleteIndex");

    if (error.isNull()) {
        auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
        if (objectStoreInfo)
            objectStoreInfo->deleteIndex(indexIdentifier);
    }

    performErrorCallback(callbackIdentifier, error);
}

void UniqueIDBDatabase::renameIndex(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, ErrorCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::renameIndex");

    auto taskSize = defaultWriteOperationCost + newName.sizeInBytes();
    requestSpace(transaction, taskSize, "renameIndex", [this, taskSize, &transaction, objectStoreIdentifier, indexIdentifier, newName, callback = WTFMove(callback)](auto error) mutable {
        if (!error.isNull() && *error.code() != QuotaExceededError) {
            callback(WTFMove(error));
            return;
        }
        this->renameIndexAfterQuotaCheck(taskSize, transaction, objectStoreIdentifier, indexIdentifier, newName, WTFMove(callback), error);
    });
}

void UniqueIDBDatabase::renameIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, ErrorCallback callback, const IDBError& quotaError)
{
    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;

    IDBError error = quotaError;
    auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
    if (!objectStoreInfo)
        error = IDBError { UnknownError, "Attempt to rename index in non-existant object store"_s };

    auto* indexInfo = objectStoreInfo->infoForExistingIndex(indexIdentifier);
    if (!indexInfo)
        error = IDBError { UnknownError, "Attempt to rename non-existant index"_s };

    startSpaceIncreaseTask(callbackID, taskSize);
    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performRenameIndex, callbackID, transaction.info().identifier(), objectStoreIdentifier, indexIdentifier, newName, error));
}

void UniqueIDBDatabase::performRenameIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, const IDBError& error)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performRenameIndex");

    if (!error.isNull()) {
        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformRenameIndex, callbackIdentifier, error, objectStoreIdentifier, indexIdentifier, newName));
        return;
    }

    ASSERT(m_backingStore);
    m_backingStore->renameIndex(transactionIdentifier, objectStoreIdentifier, indexIdentifier, newName);

    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformRenameIndex, callbackIdentifier, error, objectStoreIdentifier, indexIdentifier, newName));
}

void UniqueIDBDatabase::didPerformRenameIndex(uint64_t callbackIdentifier, const IDBError& error, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformRenameIndex");

    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
    if (error.isNull()) {
        auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
        ASSERT(objectStoreInfo);
        if (objectStoreInfo) {
            auto* indexInfo = objectStoreInfo->infoForExistingIndex(indexIdentifier);
            ASSERT(indexInfo);
            indexInfo->rename(newName);
        }
    }

    performErrorCallback(callbackIdentifier, error);
}

void UniqueIDBDatabase::putOrAdd(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBKeyData& keyData, const IDBValue& value, IndexedDB::ObjectStoreOverwriteMode overwriteMode, KeyDataCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::putOrAdd");

    auto taskSize = defaultWriteOperationCost + estimateSize(keyData) + estimateSize(value);
    ASSERT(m_databaseInfo);
    auto* objectStore = m_databaseInfo->infoForExistingObjectStore(requestData.objectStoreIdentifier());
    if (objectStore)
        taskSize += objectStore->indexNames().size() * taskSize;

    requestSpace(transaction, taskSize, "putOrAdd", [this, taskSize, requestData, keyData, value, callback = WTFMove(callback), overwriteMode](auto error) mutable {
        if (!error.isNull() && *error.code() != QuotaExceededError) {
            callback(WTFMove(error), { });
            return;
        }
        this->putOrAddAfterQuotaCheck(taskSize, requestData, keyData, value, overwriteMode, WTFMove(callback), error);
    });
}

void UniqueIDBDatabase::putOrAddAfterQuotaCheck(uint64_t taskSize, const IDBRequestData& requestData, const IDBKeyData& keyData, const IDBValue& value, IndexedDB::ObjectStoreOverwriteMode overwriteMode, KeyDataCallback callback, const IDBError& quotaError)
{
    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;

    startSpaceIncreaseTask(callbackID, taskSize);
    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performPutOrAdd, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyData, value, overwriteMode, quotaError));
}

void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, const IDBValue& originalRecordValue, IndexedDB::ObjectStoreOverwriteMode overwriteMode, const IDBError& quotaError)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performPutOrAdd");

    ASSERT(m_backingStore);
    ASSERT(objectStoreIdentifier);

    IDBKeyData usedKey;
    IDBError error;

    if (!quotaError.isNull()) {
        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, quotaError, usedKey));
        return;
    }

    if (!m_backingStore) {
        RELEASE_LOG_ERROR(IndexedDB, "%p - UniqueIDBDatabase::performPutOrAdd: m_backingStore is null", this);
        error = IDBError(InvalidStateError, "Backing store is invalid for call to put or add"_s);
        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
        return;
    }

    auto* objectStoreInfo = m_backingStore->infoForObjectStore(objectStoreIdentifier);
    if (!objectStoreInfo) {
        error = IDBError(InvalidStateError, "Object store cannot be found in the backing store"_s);
        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
        return;
    }

    bool usedKeyIsGenerated = false;
    uint64_t keyNumber;
    auto generatedKeyResetter = WTF::makeScopeExit([this, transactionIdentifier, objectStoreIdentifier, &keyNumber, &usedKeyIsGenerated]() {
        if (usedKeyIsGenerated)
            m_backingStore->revertGeneratedKeyNumber(transactionIdentifier, objectStoreIdentifier, keyNumber);
    });
    if (objectStoreInfo->autoIncrement() && !keyData.isValid()) {
        error = m_backingStore->generateKeyNumber(transactionIdentifier, objectStoreIdentifier, keyNumber);
        if (!error.isNull()) {
            postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
            return;
        }
        
        usedKey.setNumberValue(keyNumber);
        usedKeyIsGenerated = true;
    } else
        usedKey = keyData;

    if (overwriteMode == IndexedDB::ObjectStoreOverwriteMode::NoOverwrite) {
        bool keyExists;
        error = m_backingStore->keyExistsInObjectStore(transactionIdentifier, objectStoreIdentifier, usedKey, keyExists);
        if (error.isNull() && keyExists)
            error = IDBError(ConstraintError, "Key already exists in the object store"_s);

        if (!error.isNull()) {
            postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
            return;
        }
    }

    // 3.4.1 Object Store Storage Operation
    // ...If a record already exists in store ...
    // then remove the record from store using the steps for deleting records from an object store...
    // This is important because formally deleting it from from the object store also removes it from the appropriate indexes.
    error = m_backingStore->deleteRange(transactionIdentifier, objectStoreIdentifier, usedKey);
    if (!error.isNull()) {
        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
        return;
    }

    error = m_backingStore->addRecord(transactionIdentifier, *objectStoreInfo, usedKey, originalRecordValue);

    if (!error.isNull()) {
        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
        return;
    }

    if (overwriteMode != IndexedDB::ObjectStoreOverwriteMode::OverwriteForCursor && objectStoreInfo->autoIncrement() && keyData.type() == IndexedDB::KeyType::Number)
        error = m_backingStore->maybeUpdateKeyGeneratorNumber(transactionIdentifier, objectStoreIdentifier, keyData.number());

    generatedKeyResetter.release();
    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
}

void UniqueIDBDatabase::didPerformPutOrAdd(uint64_t callbackIdentifier, const IDBError& error, const IDBKeyData& resultKey)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformPutOrAdd");

    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
    performKeyDataCallback(callbackIdentifier, error, resultKey);
}

void UniqueIDBDatabase::getRecord(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBGetRecordData& getRecordData, GetResultCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::getRecord");

    waitForRequestSpaceCompletion(transaction, [this, requestData, getRecordData, callback = WTFMove(callback)](auto&& error) mutable {
        if (!error.isNull()) {
            callback(WTFMove(error), { });
            return;
        }
        this->getRecordAfterQuotaCheck(requestData, getRecordData, WTFMove(callback));
    });
}

void UniqueIDBDatabase::getRecordAfterQuotaCheck(const IDBRequestData& requestData, const IDBGetRecordData& getRecordData, GetResultCallback callback)
{
    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;

    if (uint64_t indexIdentifier = requestData.indexIdentifier())
        postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetIndexRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), indexIdentifier, requestData.indexRecordType(), getRecordData.keyRangeData));
    else
        postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), getRecordData.keyRangeData, getRecordData.type));
}

void UniqueIDBDatabase::getAllRecords(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData, GetAllResultsCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::getAllRecords");

    waitForRequestSpaceCompletion(transaction, [this, requestData, getAllRecordsData, callback = WTFMove(callback)](auto&& error) mutable {
        if (!error.isNull()) {
            callback(WTFMove(error), { });
            return;
        }
        this->getAllRecordsAfterQuotaCheck(requestData, getAllRecordsData, WTFMove(callback));
    });
}

void UniqueIDBDatabase::getAllRecordsAfterQuotaCheck(const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData, GetAllResultsCallback callback)
{
    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;

    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetAllRecords, callbackID, requestData.transactionIdentifier(), getAllRecordsData));
}

void UniqueIDBDatabase::performGetRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& keyRangeData, IDBGetRecordDataType type)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetRecord");

    ASSERT(m_backingStore);

    IDBGetResult result;
    IDBError error = m_backingStore->getRecord(transactionIdentifier, objectStoreIdentifier, keyRangeData, type, result);

    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetRecord, callbackIdentifier, error, result));
}

void UniqueIDBDatabase::performGetIndexRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType recordType, const IDBKeyRangeData& range)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetIndexRecord");

    ASSERT(m_backingStore);

    IDBGetResult result;
    IDBError error = m_backingStore->getIndexRecord(transactionIdentifier, objectStoreIdentifier, indexIdentifier, recordType, range, result);

    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetRecord, callbackIdentifier, error, result));
}

void UniqueIDBDatabase::didPerformGetRecord(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& result)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformGetRecord");

    performGetResultCallback(callbackIdentifier, error, result);
}

void UniqueIDBDatabase::performGetAllRecords(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData& getAllRecordsData)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetAllRecords");

    ASSERT(m_backingStore);

    IDBGetAllResult result;
    IDBError error = m_backingStore->getAllRecords(transactionIdentifier, getAllRecordsData, result);

    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetAllRecords, callbackIdentifier, error, WTFMove(result)));
}

void UniqueIDBDatabase::didPerformGetAllRecords(uint64_t callbackIdentifier, const IDBError& error, const IDBGetAllResult& result)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformGetAllRecords");

    performGetAllResultsCallback(callbackIdentifier, error, result);
}

void UniqueIDBDatabase::getCount(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBKeyRangeData& range, CountCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::getCount");

    waitForRequestSpaceCompletion(transaction, [this, requestData, range, callback = WTFMove(callback)](auto&& error) mutable {
        if (!error.isNull()) {
            callback(WTFMove(error), { });
            return;
        }
        this->getCountAfterQuotaCheck(requestData, range, WTFMove(callback));
    });
}

void UniqueIDBDatabase::getCountAfterQuotaCheck(const IDBRequestData& requestData, const IDBKeyRangeData& range, CountCallback callback)
{
    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;
    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetCount, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), requestData.indexIdentifier(), range));
}

void UniqueIDBDatabase::performGetCount(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData& keyRangeData)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetCount");

    ASSERT(m_backingStore);
    ASSERT(objectStoreIdentifier);

    uint64_t count;
    IDBError error = m_backingStore->getCount(transactionIdentifier, objectStoreIdentifier, indexIdentifier, keyRangeData, count);

    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetCount, callbackIdentifier, error, count));
}

void UniqueIDBDatabase::didPerformGetCount(uint64_t callbackIdentifier, const IDBError& error, uint64_t count)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformGetCount");

    performCountCallback(callbackIdentifier, error, count);
}

void UniqueIDBDatabase::deleteRecord(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData, ErrorCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteRecord");

    waitForRequestSpaceCompletion(transaction, [this, requestData, keyRangeData, callback = WTFMove(callback)](auto&& error) mutable {
        if (!error.isNull()) {
            callback(WTFMove(error));
            return;
        }
        this->deleteRecordAfterQuotaCheck(requestData, keyRangeData, WTFMove(callback));
    });
}

void UniqueIDBDatabase::deleteRecordAfterQuotaCheck(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData, ErrorCallback callback)
{
    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;
    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performDeleteRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyRangeData));
}

void UniqueIDBDatabase::performDeleteRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performDeleteRecord");

    IDBError error = m_backingStore->deleteRange(transactionIdentifier, objectStoreIdentifier, range);

    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformDeleteRecord, callbackIdentifier, error));
}

void UniqueIDBDatabase::didPerformDeleteRecord(uint64_t callbackIdentifier, const IDBError& error)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformDeleteRecord");

    performErrorCallback(callbackIdentifier, error);
}

void UniqueIDBDatabase::openCursor(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBCursorInfo& info, GetResultCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::openCursor");

    waitForRequestSpaceCompletion(transaction, [this, requestData, info, callback = WTFMove(callback)](auto&& error) mutable {
        if (!error.isNull()) {
            callback(WTFMove(error), { });
            return;
        }
        this->openCursorAfterQuotaCheck(requestData, info, WTFMove(callback));
    });
}

void UniqueIDBDatabase::openCursorAfterQuotaCheck(const IDBRequestData& requestData, const IDBCursorInfo& info, GetResultCallback callback)
{
    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;
    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performOpenCursor, callbackID, requestData.transactionIdentifier(), info));
}

void UniqueIDBDatabase::performOpenCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo& info)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performOpenCursor");

    IDBGetResult result;
    IDBError error = m_backingStore->openCursor(transactionIdentifier, info, result);

    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformOpenCursor, callbackIdentifier, error, result));
}

void UniqueIDBDatabase::didPerformOpenCursor(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& result)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformOpenCursor");

    performGetResultCallback(callbackIdentifier, error, result);
}

void UniqueIDBDatabase::iterateCursor(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBIterateCursorData& data, GetResultCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::iterateCursor");

    waitForRequestSpaceCompletion(transaction, [this, requestData, data, callback = WTFMove(callback)](auto&& error) mutable {
        if (!error.isNull()) {
            callback(WTFMove(error), { });
            return;
        }
        this->iterateCursorAfterQuotaCheck(requestData, data, WTFMove(callback));
    });
}

void UniqueIDBDatabase::iterateCursorAfterQuotaCheck(const IDBRequestData& requestData, const IDBIterateCursorData& data, GetResultCallback callback)
{
    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;
    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performIterateCursor, callbackID, requestData.transactionIdentifier(), requestData.cursorIdentifier(), data));
}

void UniqueIDBDatabase::performIterateCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, const IDBIterateCursorData& data)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performIterateCursor");

    IDBGetResult result;
    IDBError error = m_backingStore->iterateCursor(transactionIdentifier, cursorIdentifier, data, result);

    if (error.isNull()) {
        auto addResult = m_cursorPrefetches.add(cursorIdentifier);
        if (addResult.isNewEntry)
            postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performPrefetchCursor, transactionIdentifier, cursorIdentifier));
    }

    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformIterateCursor, callbackIdentifier, error, result));
}

void UniqueIDBDatabase::performPrefetchCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier)
{
    ASSERT(!isMainThread());
    ASSERT(m_cursorPrefetches.contains(cursorIdentifier));
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performPrefetchCursor");

    if (m_hardClosedForUserDelete || !m_backingStore->prefetchCursor(transactionIdentifier, cursorIdentifier))
        m_cursorPrefetches.remove(cursorIdentifier);
    else
        postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performPrefetchCursor, transactionIdentifier, cursorIdentifier));
}

void UniqueIDBDatabase::didPerformIterateCursor(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& result)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformIterateCursor");

    performGetResultCallback(callbackIdentifier, error, result);
}

bool UniqueIDBDatabase::prepareToFinishTransaction(UniqueIDBDatabaseTransaction& transaction, UniqueIDBDatabaseTransaction::State state)
{
    auto takenTransaction = m_inProgressTransactions.take(transaction.info().identifier());
    if (!takenTransaction)
        return false;

    ASSERT(!m_finishingTransactions.contains(transaction.info().identifier()));
    takenTransaction->setState(state);
    m_finishingTransactions.set(transaction.info().identifier(), WTFMove(takenTransaction));

    return true;
}

void UniqueIDBDatabase::commitTransaction(UniqueIDBDatabaseTransaction& transaction, ErrorCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::commitTransaction - %s", transaction.info().identifier().loggingString().utf8().data());

    ASSERT(transaction.databaseConnection().database() == this);

    waitForRequestSpaceCompletion(transaction, [this, &transaction, callback = WTFMove(callback)](auto&& error) mutable {
        if (!error.isNull()) {
            callback(WTFMove(error));
            return;
        }
        this->commitTransactionAfterQuotaCheck(transaction, WTFMove(callback));
    });
}

void UniqueIDBDatabase::commitTransactionAfterQuotaCheck(UniqueIDBDatabaseTransaction& transaction, ErrorCallback callback)
{
    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;

    if (!prepareToFinishTransaction(transaction, UniqueIDBDatabaseTransaction::State::Committing)) {
        if (!m_openDatabaseConnections.contains(&transaction.databaseConnection())) {
            // This database connection is closing or has already closed, so there is no point in messaging back to it about the commit failing.
            forgetErrorCallback(callbackID);
            return;
        }

        performErrorCallback(callbackID, IDBError { UnknownError, "Attempt to commit transaction that is already finishing"_s });
        return;
    }

    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCommitTransaction, callbackID, transaction.info().identifier()));
}

void UniqueIDBDatabase::performCommitTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performCommitTransaction - %s", transactionIdentifier.loggingString().utf8().data());

    IDBError error = m_backingStore->commitTransaction(transactionIdentifier);
    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCommitTransaction, callbackIdentifier, error, transactionIdentifier));
}

void UniqueIDBDatabase::didPerformCommitTransaction(uint64_t callbackIdentifier, const IDBError& error, const IDBResourceIdentifier& transactionIdentifier)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCommitTransaction - %s", transactionIdentifier.loggingString().utf8().data());

    IDBError result = error;
    auto transaction = m_finishingTransactions.get(transactionIdentifier);
    switch (transaction->state()) {
    case UniqueIDBDatabaseTransaction::State::Aborted:
        result = IDBError { UnknownError, "Transaction is already aborted"_s };
        break;
    case UniqueIDBDatabaseTransaction::State::Committed:
        result = transaction->result();
        break;
    case UniqueIDBDatabaseTransaction::State::Committing:
        break;
    case UniqueIDBDatabaseTransaction::State::Running:
    case UniqueIDBDatabaseTransaction::State::Aborting:
        ASSERT_NOT_REACHED();
    }

    performErrorCallback(callbackIdentifier, result);

    transactionCompleted(m_finishingTransactions.take(transactionIdentifier));
}

void UniqueIDBDatabase::abortTransaction(UniqueIDBDatabaseTransaction& transaction, WaitForPendingTasks waitForPendingTasks, ErrorCallback callback)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::abortTransaction - %s", transaction.info().identifier().loggingString().utf8().data());

    ASSERT(transaction.databaseConnection().database() == this);

    if (waitForPendingTasks == WaitForPendingTasks::Yes) {
        waitForRequestSpaceCompletion(transaction, [this, &transaction, callback = WTFMove(callback)](auto&& error) mutable {
            if (!error.isNull()) {
                callback(WTFMove(error));
                return;
            }
            this->abortTransaction(transaction, WaitForPendingTasks::No, WTFMove(callback));
        });
        return;
    }

    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;

    if (!prepareToFinishTransaction(transaction, UniqueIDBDatabaseTransaction::State::Aborting)) {
        if (!m_openDatabaseConnections.contains(&transaction.databaseConnection())) {
            // This database connection is closing or has already closed, so there is no point in messaging back to it about the abort failing.
            forgetErrorCallback(callbackID);
            return;
        }

        performErrorCallback(callbackID, IDBError { UnknownError, "Attempt to abort transaction that is already finishing"_s });
        return;
    }

    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performAbortTransaction, callbackID, transaction.info().identifier()));
}

void UniqueIDBDatabase::didFinishHandlingVersionChange(UniqueIDBDatabaseConnection& connection, const IDBResourceIdentifier& transactionIdentifier)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didFinishHandlingVersionChange");

    ASSERT_UNUSED(transactionIdentifier, !m_versionChangeTransaction || m_versionChangeTransaction->info().identifier() == transactionIdentifier);
    ASSERT_UNUSED(connection, !m_versionChangeDatabaseConnection || m_versionChangeDatabaseConnection.get() == &connection);

    m_versionChangeTransaction = nullptr;
    m_versionChangeDatabaseConnection = nullptr;

    if (m_hardClosedForUserDelete) {
        maybeFinishHardClose();
        return;
    }

    invokeOperationAndTransactionTimer();
}

void UniqueIDBDatabase::performAbortTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier)
{
    ASSERT(!isMainThread());
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performAbortTransaction - %s", transactionIdentifier.loggingString().utf8().data());

    IDBError error = m_backingStore->abortTransaction(transactionIdentifier);
    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformAbortTransaction, callbackIdentifier, error, transactionIdentifier));
}

void UniqueIDBDatabase::didPerformAbortTransaction(uint64_t callbackIdentifier, const IDBError& error, const IDBResourceIdentifier& transactionIdentifier)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformAbortTransaction - %s", transactionIdentifier.loggingString().utf8().data());

    auto transaction = m_finishingTransactions.take(transactionIdentifier);
    ASSERT(transaction);

    if (m_versionChangeTransaction && m_versionChangeTransaction->info().identifier() == transactionIdentifier) {
        ASSERT(m_versionChangeTransaction == transaction);
        ASSERT(!m_versionChangeDatabaseConnection || &m_versionChangeTransaction->databaseConnection() == m_versionChangeDatabaseConnection);
        ASSERT(m_versionChangeTransaction->originalDatabaseInfo());
        m_databaseInfo = makeUnique<IDBDatabaseInfo>(*m_versionChangeTransaction->originalDatabaseInfo());
    }

    IDBError result = transaction->state() == UniqueIDBDatabaseTransaction::State::Aborted ? transaction->result() : error;
    performErrorCallback(callbackIdentifier, result);

    transactionCompleted(WTFMove(transaction));
}

void UniqueIDBDatabase::transactionDestroyed(UniqueIDBDatabaseTransaction& transaction)
{
    if (m_versionChangeTransaction == &transaction)
        m_versionChangeTransaction = nullptr;
}

void UniqueIDBDatabase::connectionClosedFromClient(UniqueIDBDatabaseConnection& connection)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::connectionClosedFromClient - %s (%" PRIu64 ")", connection.openRequestIdentifier().loggingString().utf8().data(), connection.identifier());

    if (m_serverClosePendingDatabaseConnections.contains(&connection)) {
        m_serverClosePendingDatabaseConnections.remove(&connection);
        if (m_hardClosedForUserDelete)
            maybeFinishHardClose();
        return;
    }

    Ref<UniqueIDBDatabaseConnection> protectedConnection(connection);
    m_openDatabaseConnections.remove(&connection);

    if (m_versionChangeDatabaseConnection == &connection) {
        if (m_versionChangeTransaction) {
            m_clientClosePendingDatabaseConnections.add(WTFMove(m_versionChangeDatabaseConnection));

            auto transactionIdentifier = m_versionChangeTransaction->info().identifier();
            if (m_inProgressTransactions.contains(transactionIdentifier)) {
                ASSERT(!m_finishingTransactions.contains(transactionIdentifier));
                connection.abortTransactionWithoutCallback(*m_versionChangeTransaction);
            }

            return;
        }

        m_versionChangeDatabaseConnection = nullptr;
    }

    Deque<RefPtr<UniqueIDBDatabaseTransaction>> pendingTransactions;
    while (!m_pendingTransactions.isEmpty()) {
        auto transaction = m_pendingTransactions.takeFirst();
        if (&transaction->databaseConnection() != &connection)
            pendingTransactions.append(WTFMove(transaction));
    }

    if (!pendingTransactions.isEmpty())
        m_pendingTransactions.swap(pendingTransactions);

    Deque<RefPtr<UniqueIDBDatabaseTransaction>> transactionsToAbort;
    for (auto& transaction : m_inProgressTransactions.values()) {
        if (&transaction->databaseConnection() == &connection)
            transactionsToAbort.append(transaction);
    }

    for (auto& transaction : transactionsToAbort)
        transaction->abortWithoutCallback();

    if (m_currentOpenDBRequest)
        notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent(connection.identifier());

    if (connection.hasNonFinishedTransactions()) {
        m_clientClosePendingDatabaseConnections.add(WTFMove(protectedConnection));
        return;
    }

    if (m_hardClosedForUserDelete) {
        maybeFinishHardClose();
        return;
    }

    // Now that a database connection has closed, previously blocked operations might be runnable.
    invokeOperationAndTransactionTimer();
}

void UniqueIDBDatabase::connectionClosedFromServer(UniqueIDBDatabaseConnection& connection)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "UniqueIDBDatabase::connectionClosedFromServer - %s (%" PRIu64 ")", connection.openRequestIdentifier().loggingString().utf8().data(), connection.identifier());

    if (m_clientClosePendingDatabaseConnections.contains(&connection)) {
        ASSERT(!m_openDatabaseConnections.contains(&connection));
        ASSERT(!m_serverClosePendingDatabaseConnections.contains(&connection));
        return;
    }

    Ref<UniqueIDBDatabaseConnection> protectedConnection(connection);
    m_openDatabaseConnections.remove(&connection);

    connection.connectionToClient().didCloseFromServer(connection, IDBError::userDeleteError());

    m_serverClosePendingDatabaseConnections.add(WTFMove(protectedConnection));
}

void UniqueIDBDatabase::confirmDidCloseFromServer(UniqueIDBDatabaseConnection& connection)
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "UniqueIDBDatabase::confirmDidCloseFromServer - %s (%" PRIu64 ")", connection.openRequestIdentifier().loggingString().utf8().data(), connection.identifier());

    if (!m_serverClosePendingDatabaseConnections.contains(&connection))
        return;
    m_serverClosePendingDatabaseConnections.remove(&connection);

    if (m_hardClosedForUserDelete)
        maybeFinishHardClose();
}

void UniqueIDBDatabase::enqueueTransaction(Ref<UniqueIDBDatabaseTransaction>&& transaction)
{
    LOG(IndexedDB, "UniqueIDBDatabase::enqueueTransaction - %s", transaction->info().loggingString().utf8().data());
    ASSERT(!m_hardClosedForUserDelete);

    ASSERT(transaction->info().mode() != IDBTransactionMode::Versionchange);

    m_pendingTransactions.append(WTFMove(transaction));

    invokeOperationAndTransactionTimer();
}

bool UniqueIDBDatabase::isCurrentlyInUse() const
{
    return !m_openDatabaseConnections.isEmpty() || !m_clientClosePendingDatabaseConnections.isEmpty() || !m_pendingOpenDBRequests.isEmpty() || m_currentOpenDBRequest || m_versionChangeDatabaseConnection || m_versionChangeTransaction || m_isOpeningBackingStore || m_deleteBackingStoreInProgress;
}

bool UniqueIDBDatabase::hasUnfinishedTransactions() const
{
    return !m_inProgressTransactions.isEmpty() || !m_finishingTransactions.isEmpty();
}

void UniqueIDBDatabase::invokeOperationAndTransactionTimer()
{
    LOG(IndexedDB, "UniqueIDBDatabase::invokeOperationAndTransactionTimer()");
    RELEASE_ASSERT(!m_hardClosedForUserDelete);
    RELEASE_ASSERT(!m_owningPointerForClose);

    if (!m_operationAndTransactionTimer.isActive())
        m_operationAndTransactionTimer.startOneShot(0_s);
}

void UniqueIDBDatabase::operationAndTransactionTimerFired()
{
    LOG(IndexedDB, "(main) UniqueIDBDatabase::operationAndTransactionTimerFired");
    ASSERT(!m_hardClosedForUserDelete);
    ASSERT(isMainThread());

    // This UniqueIDBDatabase might be no longer in use by any web page.
    // Assuming it is not ephemeral, the server should now close it to free up resources.
    if (!m_backingStoreIsEphemeral && !isCurrentlyInUse()) {
        ASSERT(m_pendingTransactions.isEmpty());
        ASSERT(!hasUnfinishedTransactions());

        scheduleShutdownForClose();
        return;
    }

    // The current operation might require multiple attempts to handle, so try to
    // make further progress on it now.
    if (m_currentOpenDBRequest && !m_currentOpenDBRequest->connection().isClosed())
        handleCurrentOperation();
    else
        handleDatabaseOperations();

    bool hadDeferredTransactions = false;
    auto transaction = takeNextRunnableTransaction(hadDeferredTransactions);

    if (transaction) {
        m_inProgressTransactions.set(transaction->info().identifier(), transaction);
        for (auto objectStore : transaction->objectStoreIdentifiers()) {
            m_objectStoreTransactionCounts.add(objectStore);
            if (!transaction->isReadOnly()) {
                m_objectStoreWriteTransactions.add(objectStore);
                ASSERT(m_objectStoreTransactionCounts.count(objectStore) == 1 || m_hardClosedForUserDelete);
            }
        }

        activateTransactionInBackingStore(*transaction);

        // If no transactions were deferred, it's possible we can start another transaction right now.
        if (!hadDeferredTransactions)
            invokeOperationAndTransactionTimer();
    }
}

void UniqueIDBDatabase::activateTransactionInBackingStore(UniqueIDBDatabaseTransaction& transaction)
{
    LOG(IndexedDB, "(main) UniqueIDBDatabase::activateTransactionInBackingStore");
    ASSERT(isMainThread());

    RefPtr<UniqueIDBDatabaseTransaction> refTransaction(&transaction);

    ErrorCallback callback = [refTransaction](const IDBError& error) {
        refTransaction->didActivateInBackingStore(error);
    };

    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    if (!callbackID)
        return;
    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performActivateTransactionInBackingStore, callbackID, transaction.info()));
}

void UniqueIDBDatabase::performActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBTransactionInfo& info)
{
    LOG(IndexedDB, "(db) UniqueIDBDatabase::performActivateTransactionInBackingStore");

    IDBError error = m_backingStore->beginTransaction(info);
    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformActivateTransactionInBackingStore, callbackIdentifier, error));
}

void UniqueIDBDatabase::didPerformActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBError& error)
{
    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformActivateTransactionInBackingStore");

    if (m_hardClosedForUserDelete)
        return;

    invokeOperationAndTransactionTimer();

    performErrorCallback(callbackIdentifier, error);
}

template<typename T> bool scopesOverlap(const T& aScopes, const Vector<uint64_t>& bScopes)
{
    for (auto scope : bScopes) {
        if (aScopes.contains(scope))
            return true;
    }

    return false;
}

RefPtr<UniqueIDBDatabaseTransaction> UniqueIDBDatabase::takeNextRunnableTransaction(bool& hadDeferredTransactions)
{
    hadDeferredTransactions = false;

    if (m_pendingTransactions.isEmpty())
        return nullptr;

    if (!m_backingStoreSupportsSimultaneousTransactions && hasUnfinishedTransactions()) {
        LOG(IndexedDB, "UniqueIDBDatabase::takeNextRunnableTransaction - Backing store only supports 1 transaction, and we already have 1");
        return nullptr;
    }

    Deque<RefPtr<UniqueIDBDatabaseTransaction>> deferredTransactions;
    RefPtr<UniqueIDBDatabaseTransaction> currentTransaction;

    HashSet<uint64_t> deferredReadWriteScopes;

    while (!m_pendingTransactions.isEmpty()) {
        currentTransaction = m_pendingTransactions.takeFirst();

        switch (currentTransaction->info().mode()) {
        case IDBTransactionMode::Readonly: {
            bool hasOverlappingScopes = scopesOverlap(deferredReadWriteScopes, currentTransaction->objectStoreIdentifiers());
            hasOverlappingScopes |= scopesOverlap(m_objectStoreWriteTransactions, currentTransaction->objectStoreIdentifiers());

            if (hasOverlappingScopes)
                deferredTransactions.append(WTFMove(currentTransaction));

            break;
        }
        case IDBTransactionMode::Readwrite: {
            bool hasOverlappingScopes = scopesOverlap(m_objectStoreTransactionCounts, currentTransaction->objectStoreIdentifiers());
            hasOverlappingScopes |= scopesOverlap(deferredReadWriteScopes, currentTransaction->objectStoreIdentifiers());

            if (hasOverlappingScopes) {
                for (auto objectStore : currentTransaction->objectStoreIdentifiers())
                    deferredReadWriteScopes.add(objectStore);
                deferredTransactions.append(WTFMove(currentTransaction));
            }

            break;
        }
        case IDBTransactionMode::Versionchange:
            // Version change transactions should never be scheduled in the traditional manner.
            RELEASE_ASSERT_NOT_REACHED();
        }

        // If we didn't defer the currentTransaction above, it can be run now.
        if (currentTransaction)
            break;
    }

    hadDeferredTransactions = !deferredTransactions.isEmpty();
    if (!hadDeferredTransactions)
        return currentTransaction;

    // Prepend the deferred transactions back on the beginning of the deque for future scheduling passes.
    while (!deferredTransactions.isEmpty())
        m_pendingTransactions.prepend(deferredTransactions.takeLast());

    return currentTransaction;
}

void UniqueIDBDatabase::transactionCompleted(RefPtr<UniqueIDBDatabaseTransaction>&& transaction)
{
    ASSERT(transaction);
    ASSERT(!m_inProgressTransactions.contains(transaction->info().identifier()));
    ASSERT(!m_finishingTransactions.contains(transaction->info().identifier()));
    ASSERT(isMainThread());

    for (auto objectStore : transaction->objectStoreIdentifiers()) {
        if (!transaction->isReadOnly()) {
            m_objectStoreWriteTransactions.remove(objectStore);
            ASSERT(m_objectStoreTransactionCounts.count(objectStore) == 1 || m_hardClosedForUserDelete);
        }
        m_objectStoreTransactionCounts.remove(objectStore);
    }

    if (!transaction->databaseConnection().hasNonFinishedTransactions())
        m_clientClosePendingDatabaseConnections.remove(&transaction->databaseConnection());

    if (m_versionChangeTransaction == transaction)
        m_versionChangeTransaction = nullptr;

    // It's possible that this database had its backing store deleted but there were a few outstanding asynchronous operations.
    // If this transaction completing was the last of those operations, we can finally delete this UniqueIDBDatabase.
    if (m_clientClosePendingDatabaseConnections.isEmpty() && m_pendingOpenDBRequests.isEmpty() && !m_databaseInfo) {
        scheduleShutdownForClose();
        return;
    }

    // Previously blocked operations might be runnable.
    if (!m_hardClosedForUserDelete)
        invokeOperationAndTransactionTimer();
    else
        maybeFinishHardClose();
}

void UniqueIDBDatabase::postDatabaseTask(CrossThreadTask&& task)
{
    m_databaseQueue.append(WTFMove(task));
    m_server->postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::executeNextDatabaseTask));
}

void UniqueIDBDatabase::postDatabaseTaskReply(CrossThreadTask&& task)
{
    m_databaseReplyQueue.append(WTFMove(task));
    m_server->postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::executeNextDatabaseTaskReply));
}

void UniqueIDBDatabase::executeNextDatabaseTask()
{
    ASSERT(!isMainThread());
    ASSERT(!m_databaseQueue.isKilled());

    auto task = m_databaseQueue.tryGetMessage();
    ASSERT(task);

    task->performTask();
}

void UniqueIDBDatabase::executeNextDatabaseTaskReply()
{
    ASSERT(isMainThread());
    ASSERT(!m_databaseReplyQueue.isKilled());

    auto task = m_databaseReplyQueue.tryGetMessage();
    ASSERT(task);

    task->performTask();

    // If this database was force closed (e.g. for a user delete) and there are no more
    // cleanup tasks left, delete this.
    maybeFinishHardClose();
}

void UniqueIDBDatabase::maybeFinishHardClose()
{
    if (m_owningPointerForClose && isDoneWithHardClose()) {
        if (m_owningPointerReleaseScheduled)
            return;
        m_owningPointerReleaseScheduled = true;

        callOnMainThread([this] {
            ASSERT(isDoneWithHardClose());
            m_owningPointerForClose = nullptr;
        });
    }
}

bool UniqueIDBDatabase::isDoneWithHardClose()
{
    return m_databaseReplyQueue.isKilled() && m_clientClosePendingDatabaseConnections.isEmpty() && m_serverClosePendingDatabaseConnections.isEmpty();
}

static void errorOpenDBRequestForUserDelete(ServerOpenDBRequest& request)
{
    auto result = IDBResultData::error(request.requestData().requestIdentifier(), IDBError::userDeleteError());
    if (request.isOpenRequest())
        request.connection().didOpenDatabase(result);
    else
        request.connection().didDeleteDatabase(result);
}

void UniqueIDBDatabase::immediateCloseForUserDelete()
{
    LOG(IndexedDB, "UniqueIDBDatabase::immediateCloseForUserDelete - Cancelling (%i, %i, %i, %i) callbacks", m_errorCallbacks.size(), m_keyDataCallbacks.size(), m_getResultCallbacks.size(), m_countCallbacks.size());

    ASSERT(isMainThread());

    // Error out all transactions
    for (auto& identifier : copyToVector(m_inProgressTransactions.keys()))
        m_inProgressTransactions.get(identifier)->abortWithoutCallback();

    ASSERT(m_inProgressTransactions.isEmpty());

    for (auto& transaction : m_pendingTransactions)
        transaction->databaseConnection().deleteTransaction(*transaction);
    m_pendingTransactions.clear();
    m_objectStoreTransactionCounts.clear();
    m_objectStoreWriteTransactions.clear();

    // Error out all pending callbacks
    IDBError error = IDBError::userDeleteError();
    IDBKeyData keyData;
    IDBGetResult getResult;
    IDBGetAllResult getAllResult;

    while (!m_callbackQueue.isEmpty()) {
        auto identifier = m_callbackQueue.first();
        if (m_errorCallbacks.contains(identifier))
            performErrorCallback(identifier, error);
        else if (m_keyDataCallbacks.contains(identifier))
            performKeyDataCallback(identifier, error, keyData);
        else if (m_getResultCallbacks.contains(identifier))
            performGetResultCallback(identifier, error, getResult);
        else if (m_countCallbacks.contains(identifier))
            performCountCallback(identifier, error, 0);
        else if (m_getAllResultsCallbacks.contains(identifier))
            performGetAllResultsCallback(identifier, error, getAllResult);
        else
            ASSERT_NOT_REACHED();
    }

    // Error out all IDBOpenDBRequests
    if (m_currentOpenDBRequest) {
        errorOpenDBRequestForUserDelete(*m_currentOpenDBRequest);
        m_currentOpenDBRequest = nullptr;
    }

    for (auto& request : m_pendingOpenDBRequests)
        errorOpenDBRequestForUserDelete(*request);

    m_pendingOpenDBRequests.clear();

    // Close all open connections
    auto openDatabaseConnections = m_openDatabaseConnections;
    for (auto& connection : openDatabaseConnections)
        connectionClosedFromServer(*connection);

    if (m_versionChangeDatabaseConnection) {
        connectionClosedFromServer(*m_versionChangeDatabaseConnection);
        m_versionChangeDatabaseConnection = nullptr;
    }

    // Cancel the operation timer
    m_operationAndTransactionTimer.stop();

    // Set up the database to remain alive-but-inert until all of its background activity finishes and all
    // database connections confirm that they have closed.
    m_hardClosedForUserDelete = true;

    // If this database already owns itself, it is already closing on the background thread.
    // After that close completes, the next database thread task will be "delete all currently closed databases"
    // which will also cover this database.
    if (m_owningPointerForClose)
        return;

    // Otherwise, this database is still potentially active.
    // So we'll have it own itself and then perform a clean unconditional delete on the background thread.
    m_owningPointerForClose = m_server->closeAndTakeUniqueIDBDatabase(*this);
    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performUnconditionalDeleteBackingStore));
}

void UniqueIDBDatabase::performErrorCallback(uint64_t callbackIdentifier, const IDBError& error)
{
    auto callback = m_errorCallbacks.take(callbackIdentifier);
    ASSERT(callback || m_hardClosedForUserDelete);
    if (callback) {
        callback(error);
        ASSERT(m_callbackQueue.first() == callbackIdentifier);
        m_callbackQueue.removeFirst();
    }
}

void UniqueIDBDatabase::performKeyDataCallback(uint64_t callbackIdentifier, const IDBError& error, const IDBKeyData& resultKey)
{
    auto callback = m_keyDataCallbacks.take(callbackIdentifier);
    ASSERT(callback || m_hardClosedForUserDelete);
    if (callback) {
        callback(error, resultKey);
        ASSERT(m_callbackQueue.first() == callbackIdentifier);
        m_callbackQueue.removeFirst();
    }
}

void UniqueIDBDatabase::performGetResultCallback(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& resultData)
{
    auto callback = m_getResultCallbacks.take(callbackIdentifier);
    ASSERT(callback || m_hardClosedForUserDelete);
    if (callback) {
        callback(error, resultData);
        ASSERT(m_callbackQueue.first() == callbackIdentifier);
        m_callbackQueue.removeFirst();
    }
}

void UniqueIDBDatabase::performGetAllResultsCallback(uint64_t callbackIdentifier, const IDBError& error, const IDBGetAllResult& resultData)
{
    auto callback = m_getAllResultsCallbacks.take(callbackIdentifier);
    ASSERT(callback || m_hardClosedForUserDelete);
    if (callback) {
        callback(error, resultData);
        ASSERT(m_callbackQueue.first() == callbackIdentifier);
        m_callbackQueue.removeFirst();
    }
}

void UniqueIDBDatabase::performCountCallback(uint64_t callbackIdentifier, const IDBError& error, uint64_t count)
{
    auto callback = m_countCallbacks.take(callbackIdentifier);
    ASSERT(callback || m_hardClosedForUserDelete);
    if (callback) {
        callback(error, count);
        ASSERT(m_callbackQueue.first() == callbackIdentifier);
        m_callbackQueue.removeFirst();
    }
}

void UniqueIDBDatabase::forgetErrorCallback(uint64_t callbackIdentifier)
{
    ASSERT(m_errorCallbacks.contains(callbackIdentifier));
    ASSERT(m_callbackQueue.last() == callbackIdentifier);
    m_callbackQueue.removeLast();
    m_errorCallbacks.remove(callbackIdentifier);
}

void UniqueIDBDatabase::abortTransactionOnMainThread(UniqueIDBDatabaseTransaction& transaction)
{
    transaction.setResult(m_backingStore->abortTransaction(transaction.info().identifier()));
    transaction.setState(UniqueIDBDatabaseTransaction::State::Aborted);
}

void UniqueIDBDatabase::commitTransactionOnMainThread(UniqueIDBDatabaseTransaction& transaction)
{
    transaction.setResult(m_backingStore->commitTransaction(transaction.info().identifier()));
    transaction.setState(UniqueIDBDatabaseTransaction::State::Committed);
}

void UniqueIDBDatabase::finishActiveTransactions()
{
    ASSERT(isMainThread());

    for (auto& identifier : copyToVector(m_inProgressTransactions.keys())) {
        auto transaction = m_inProgressTransactions.get(identifier);
        abortTransactionOnMainThread(*transaction);
    }

    for (auto& identifier : copyToVector(m_finishingTransactions.keys())) {
        if (!m_backingStore->hasTransaction(identifier))
            continue;

        auto transaction = m_finishingTransactions.get(identifier);
        switch (transaction->state()) {
        case UniqueIDBDatabaseTransaction::State::Aborting:
            abortTransactionOnMainThread(*transaction);
            break;
        case UniqueIDBDatabaseTransaction::State::Committing:
            commitTransactionOnMainThread(*transaction);
            break;
        case UniqueIDBDatabaseTransaction::State::Running:
        case UniqueIDBDatabaseTransaction::State::Aborted:
        case UniqueIDBDatabaseTransaction::State::Committed:
            ASSERT_NOT_REACHED();
        }
    }
}

} // namespace IDBServer
} // namespace WebCore

#endif // ENABLE(INDEXED_DATABASE)
