/*
 * Copyright (C) 2007, 2008, 2013 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.
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "SQLTransaction.h"

#include "Database.h"
#include "DatabaseAuthorizer.h"
#include "DatabaseContext.h"
#include "DatabaseThread.h"
#include "DatabaseTracker.h"
#include "Document.h"
#include "Logging.h"
#include "OriginLock.h"
#include "SQLError.h"
#include "SQLStatement.h"
#include "SQLStatementCallback.h"
#include "SQLStatementErrorCallback.h"
#include "SQLTransactionBackend.h"
#include "SQLTransactionCallback.h"
#include "SQLTransactionCoordinator.h"
#include "SQLTransactionErrorCallback.h"
#include "SQLiteTransaction.h"
#include "VoidCallback.h"
#include "WindowEventLoop.h"
#include <wtf/Optional.h>
#include <wtf/StdLibExtras.h>
#include <wtf/Vector.h>

namespace WebCore {

Ref<SQLTransaction> SQLTransaction::create(Ref<Database>&& database, RefPtr<SQLTransactionCallback>&& callback, RefPtr<VoidCallback>&& successCallback, RefPtr<SQLTransactionErrorCallback>&& errorCallback, RefPtr<SQLTransactionWrapper>&& wrapper, bool readOnly)
{
    return adoptRef(*new SQLTransaction(WTFMove(database), WTFMove(callback), WTFMove(successCallback), WTFMove(errorCallback), WTFMove(wrapper), readOnly));
}

SQLTransaction::SQLTransaction(Ref<Database>&& database, RefPtr<SQLTransactionCallback>&& callback, RefPtr<VoidCallback>&& successCallback, RefPtr<SQLTransactionErrorCallback>&& errorCallback, RefPtr<SQLTransactionWrapper>&& wrapper, bool readOnly)
    : m_database(WTFMove(database))
    , m_callbackWrapper(WTFMove(callback), &m_database->document())
    , m_successCallbackWrapper(WTFMove(successCallback), &m_database->document())
    , m_errorCallbackWrapper(WTFMove(errorCallback), &m_database->document())
    , m_wrapper(WTFMove(wrapper))
    , m_nextStep(&SQLTransaction::acquireLock)
    , m_readOnly(readOnly)
    , m_backend(*this)
{
}

SQLTransaction::~SQLTransaction() = default;

ExceptionOr<void> SQLTransaction::executeSql(const String& sqlStatement, Optional<Vector<SQLValue>>&& arguments, RefPtr<SQLStatementCallback>&& callback, RefPtr<SQLStatementErrorCallback>&& callbackError)
{
    if (!m_executeSqlAllowed || !m_database->opened())
        return Exception { InvalidStateError };

    int permissions = DatabaseAuthorizer::ReadWriteMask;
    if (!m_database->databaseContext().allowDatabaseAccess())
        permissions |= DatabaseAuthorizer::NoAccessMask;
    else if (m_readOnly)
        permissions |= DatabaseAuthorizer::ReadOnlyMask;

    auto statement = makeUnique<SQLStatement>(m_database, sqlStatement, arguments.valueOr(Vector<SQLValue> { }), WTFMove(callback), WTFMove(callbackError), permissions);

    if (m_database->deleted())
        statement->setDatabaseDeletedError();

    enqueueStatement(WTFMove(statement));

    return { };
}

void SQLTransaction::lockAcquired()
{
    m_lockAcquired = true;

    m_backend.m_requestedState = SQLTransactionState::OpenTransactionAndPreflight;
    m_database->scheduleTransactionStep(*this);
}

void SQLTransaction::performNextStep()
{
    m_backend.computeNextStateAndCleanupIfNeeded();
    m_backend.runStateMachine();
}

void SQLTransaction::performPendingCallback()
{
    ASSERT(isMainThread());
    LOG(StorageAPI, "Callback %s\n", debugStepName(m_nextStep));

    ASSERT(m_nextStep == &SQLTransaction::deliverTransactionCallback
           || m_nextStep == &SQLTransaction::deliverTransactionErrorCallback
           || m_nextStep == &SQLTransaction::deliverStatementCallback
           || m_nextStep == &SQLTransaction::deliverQuotaIncreaseCallback
           || m_nextStep == &SQLTransaction::deliverSuccessCallback);

    checkAndHandleClosedDatabase();

    if (m_nextStep)
        (this->*m_nextStep)();
}

void SQLTransaction::notifyDatabaseThreadIsShuttingDown()
{
    callOnMainThread([this, protectedThis = makeRef(*this)]() mutable {
        callErrorCallbackDueToInterruption();
    });

    m_backend.notifyDatabaseThreadIsShuttingDown();
}

void SQLTransaction::callErrorCallbackDueToInterruption()
{
    ASSERT(isMainThread());
    auto errorCallback = m_errorCallbackWrapper.unwrap();
    if (!errorCallback)
        return;

    m_database->document().eventLoop().queueTask(TaskSource::Networking, m_database->document(), [errorCallback = WTFMove(errorCallback)]() mutable {
        errorCallback->handleEvent(SQLError::create(SQLError::DATABASE_ERR, "the database was closed"));
    });
}

void SQLTransaction::enqueueStatement(std::unique_ptr<SQLStatement> statement)
{
    LockHolder locker(m_statementMutex);
    m_statementQueue.append(WTFMove(statement));
}

SQLTransaction::StateFunction SQLTransaction::stateFunctionFor(SQLTransactionState state)
{
    static const StateFunction stateFunctions[] = {
        &SQLTransaction::unreachableState,                // 0. illegal
        &SQLTransaction::unreachableState,                // 1. idle
        &SQLTransaction::unreachableState,                // 2. acquireLock
        &SQLTransaction::unreachableState,                // 3. openTransactionAndPreflight
        &SQLTransaction::unreachableState,                // 4. runStatements
        &SQLTransaction::unreachableState,                // 5. postflightAndCommit
        &SQLTransaction::unreachableState,                // 6. cleanupAndTerminate
        &SQLTransaction::unreachableState,                // 7. cleanupAfterTransactionErrorCallback
        &SQLTransaction::deliverTransactionCallback,      // 8.
        &SQLTransaction::deliverTransactionErrorCallback, // 9.
        &SQLTransaction::deliverStatementCallback,        // 10.
        &SQLTransaction::deliverQuotaIncreaseCallback,    // 11.
        &SQLTransaction::deliverSuccessCallback           // 12.
    };

    ASSERT(WTF_ARRAY_LENGTH(stateFunctions) == static_cast<int>(SQLTransactionState::NumberOfStates));
    ASSERT(state < SQLTransactionState::NumberOfStates);

    return stateFunctions[static_cast<int>(state)];
}

// requestTransitToState() can be called from the backend. Hence, it should
// NOT be modifying SQLTransactionBackend in general. The only safe field to
// modify is m_requestedState which is meant for this purpose.
void SQLTransaction::requestTransitToState(SQLTransactionState nextState)
{
    LOG(StorageAPI, "Scheduling %s for transaction %p\n", nameForSQLTransactionState(nextState), this);
    m_requestedState = nextState;
    m_database->scheduleTransactionCallback(this);
}

void SQLTransaction::checkAndHandleClosedDatabase()
{
    if (m_database->opened())
        return;

    // If the database was stopped, don't do anything and cancel queued work
    LOG(StorageAPI, "Database was stopped or interrupted - cancelling work for this transaction");

    LockHolder locker(m_statementMutex);
    m_statementQueue.clear();
    m_nextStep = nullptr;

    callErrorCallbackDueToInterruption();

    // Release the unneeded callbacks, to break reference cycles.
    m_callbackWrapper.clear();
    m_successCallbackWrapper.clear();
    m_errorCallbackWrapper.clear();

    // The next steps should be executed only if we're on the DB thread.
    if (m_database->databaseThread().getThread() != &Thread::current())
        return;

    // The current SQLite transaction should be stopped, as well
    if (m_sqliteTransaction) {
        m_sqliteTransaction->stop();
        m_sqliteTransaction = nullptr;
    }

    if (m_lockAcquired)
        m_database->transactionCoordinator()->releaseLock(*this);
}

void SQLTransaction::scheduleCallback(void (SQLTransaction::*step)())
{
    m_nextStep = step;

    LOG(StorageAPI, "Scheduling %s for transaction %p\n", debugStepName(step), this);
    m_database->scheduleTransactionCallback(this);
}

void SQLTransaction::acquireLock()
{
    m_database->transactionCoordinator()->acquireLock(*this);
}

void SQLTransaction::openTransactionAndPreflight()
{
    ASSERT(!m_database->sqliteDatabase().transactionInProgress());
    ASSERT(m_lockAcquired);

    LOG(StorageAPI, "Opening and preflighting transaction %p", this);

    // If the database was deleted, jump to the error callback
    if (m_database->deleted()) {
        m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "unable to open a transaction, because the user deleted the database");

        handleTransactionError();
        return;
    }

    // Set the maximum usage for this transaction if this transactions is not read-only
    if (!m_readOnly) {
        acquireOriginLock();
        m_database->sqliteDatabase().setMaximumSize(m_database->maximumSize());
    }

    ASSERT(!m_sqliteTransaction);
    m_sqliteTransaction = makeUnique<SQLiteTransaction>(m_database->sqliteDatabase(), m_readOnly);

    m_database->resetDeletes();
    m_database->disableAuthorizer();
    m_sqliteTransaction->begin();
    m_database->enableAuthorizer();

    // Spec 4.3.2.1+2: Open a transaction to the database, jumping to the error callback if that fails
    if (!m_sqliteTransaction->inProgress()) {
        ASSERT(!m_database->sqliteDatabase().transactionInProgress());
        m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "unable to begin transaction", m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg());
        m_sqliteTransaction = nullptr;

        handleTransactionError();
        return;
    }

    // Note: We intentionally retrieve the actual version even with an empty expected version.
    // In multi-process browsers, we take this opportinutiy to update the cached value for
    // the actual version. In single-process browsers, this is just a map lookup.
    String actualVersion;
    if (!m_database->getActualVersionForTransaction(actualVersion)) {
        m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "unable to read version", m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg());
        m_database->disableAuthorizer();
        m_sqliteTransaction = nullptr;
        m_database->enableAuthorizer();

        handleTransactionError();
        return;
    }

    auto expectedVersion = m_database->expectedVersionIsolatedCopy();
    m_hasVersionMismatch = !expectedVersion.isEmpty() && expectedVersion != actualVersion;

    // Spec 4.3.2.3: Perform preflight steps, jumping to the error callback if they fail
    if (m_wrapper && !m_wrapper->performPreflight(*this)) {
        m_database->disableAuthorizer();
        m_sqliteTransaction = nullptr;
        m_database->enableAuthorizer();
        m_transactionError = m_wrapper->sqlError();
        if (!m_transactionError)
            m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction preflight");

        handleTransactionError();
        return;
    }

    // Spec 4.3.2.4: Invoke the transaction callback with the new SQLTransaction object
    if (m_callbackWrapper.hasCallback()) {
        scheduleCallback(&SQLTransaction::deliverTransactionCallback);
        return;
    }

    // If we have no callback to make, skip pass to the state after:
    runStatements();
}

void SQLTransaction::runStatements()
{
    ASSERT(m_lockAcquired);

    // If there is a series of statements queued up that are all successful and have no associated
    // SQLStatementCallback objects, then we can burn through the queue
    do {
        if (m_shouldRetryCurrentStatement && !m_sqliteTransaction->wasRolledBackBySqlite()) {
            m_shouldRetryCurrentStatement = false;
            // FIXME - Another place that needs fixing up after <rdar://problem/5628468> is addressed.
            // See ::openTransactionAndPreflight() for discussion

            // Reset the maximum size here, as it was increased to allow us to retry this statement.
            // m_shouldRetryCurrentStatement is set to true only when a statement exceeds
            // the quota, which can happen only in a read-write transaction. Therefore, there
            // is no need to check here if the transaction is read-write.
            m_database->sqliteDatabase().setMaximumSize(m_database->maximumSize());
        } else {
            // If the current statement has already been run, failed due to quota constraints, and we're not retrying it,
            // that means it ended in an error. Handle it now
            if (m_currentStatement && m_currentStatement->lastExecutionFailedDueToQuota()) {
                handleCurrentStatementError();
                break;
            }

            // Otherwise, advance to the next statement
            getNextStatement();
        }
    } while (runCurrentStatement());

    // If runCurrentStatement() returned false, that means either there was no current statement to run,
    // or the current statement requires a callback to complete. In the later case, it also scheduled
    // the callback or performed any other additional work so we can return.
    if (!m_currentStatement)
        postflightAndCommit();
}

void SQLTransaction::cleanupAndTerminate()
{
    ASSERT(m_lockAcquired);

    // Spec 4.3.2.9: End transaction steps. There is no next step.
    LOG(StorageAPI, "Transaction %p is complete\n", this);
    ASSERT(!m_database->sqliteDatabase().transactionInProgress());

    // Phase 5 cleanup. See comment on the SQLTransaction life-cycle above.
    m_backend.doCleanup();
    m_database->inProgressTransactionCompleted();
}

void SQLTransaction::cleanupAfterTransactionErrorCallback()
{
    ASSERT(m_lockAcquired);

    LOG(StorageAPI, "Transaction %p is complete with an error\n", this);
    m_database->disableAuthorizer();
    if (m_sqliteTransaction) {
        // Spec 4.3.2.10: Rollback the transaction.
        m_sqliteTransaction->rollback();

        ASSERT(!m_database->sqliteDatabase().transactionInProgress());
        m_sqliteTransaction = nullptr;
    }
    m_database->enableAuthorizer();

    releaseOriginLockIfNeeded();

    ASSERT(!m_database->sqliteDatabase().transactionInProgress());

    cleanupAndTerminate();
}

void SQLTransaction::deliverTransactionCallback()
{
    bool shouldDeliverErrorCallback = false;

    // Spec 4.3.2 4: Invoke the transaction callback with the new SQLTransaction object
    RefPtr<SQLTransactionCallback> callback = m_callbackWrapper.unwrap();
    if (callback) {
        m_executeSqlAllowed = true;

        auto result = callback->handleEvent(*this);
        shouldDeliverErrorCallback = result.type() == CallbackResultType::ExceptionThrown;

        m_executeSqlAllowed = false;
    }

    // Spec 4.3.2 5: If the transaction callback was null or raised an exception, jump to the error callback
    if (shouldDeliverErrorCallback) {
        m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "the SQLTransactionCallback was null or threw an exception");
        return deliverTransactionErrorCallback();
    }

    m_backend.requestTransitToState(SQLTransactionState::RunStatements);
}

void SQLTransaction::deliverTransactionErrorCallback()
{
    ASSERT(m_transactionError);

    // Spec 4.3.2.10: If exists, invoke error callback with the last
    // error to have occurred in this transaction.
    RefPtr<SQLTransactionErrorCallback> errorCallback = m_errorCallbackWrapper.unwrap();
    if (errorCallback) {
        m_database->document().eventLoop().queueTask(TaskSource::Networking, m_database->document(), [errorCallback = WTFMove(errorCallback), transactionError = m_transactionError]() mutable {
            errorCallback->handleEvent(*transactionError);
        });
    }

    clearCallbackWrappers();

    // Spec 4.3.2.10: Rollback the transaction.
    m_backend.requestTransitToState(SQLTransactionState::CleanupAfterTransactionErrorCallback);
}

void SQLTransaction::deliverStatementCallback()
{
    ASSERT(m_currentStatement);

    // Spec 4.3.2.6.6 and 4.3.2.6.3: If the statement callback went wrong, jump to the transaction error callback
    // Otherwise, continue to loop through the statement queue
    m_executeSqlAllowed = true;
    bool result = m_currentStatement->performCallback(*this);
    m_executeSqlAllowed = false;

    if (result) {
        m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "the statement callback raised an exception or statement error callback did not return false");

        if (m_errorCallbackWrapper.hasCallback())
            return deliverTransactionErrorCallback();

        // No error callback, so fast-forward to:
        // Transaction Step 11 - Rollback the transaction.
        m_backend.requestTransitToState(SQLTransactionState::CleanupAfterTransactionErrorCallback);
        return;
    }

    m_backend.requestTransitToState(SQLTransactionState::RunStatements);
}

void SQLTransaction::deliverQuotaIncreaseCallback()
{
    ASSERT(m_currentStatement);
    ASSERT(!m_shouldRetryCurrentStatement);

    m_shouldRetryCurrentStatement = m_database->didExceedQuota();

    m_backend.requestTransitToState(SQLTransactionState::RunStatements);
}

void SQLTransaction::deliverSuccessCallback()
{
    // Spec 4.3.2.8: Deliver success callback.
    RefPtr<VoidCallback> successCallback = m_successCallbackWrapper.unwrap();
    if (successCallback) {
        m_database->document().eventLoop().queueTask(TaskSource::Networking, m_database->document(), [successCallback = WTFMove(successCallback)]() mutable {
            successCallback->handleEvent();
        });
    }

    clearCallbackWrappers();

    // Schedule a "post-success callback" step to return control to the database thread in case there
    // are further transactions queued up for this Database
    m_backend.requestTransitToState(SQLTransactionState::CleanupAndTerminate);
}

// This state function is used as a stub function to plug unimplemented states
// in the state dispatch table. They are unimplemented because they should
// never be reached in the course of correct execution.
void SQLTransaction::unreachableState()
{
    ASSERT_NOT_REACHED();
}

void SQLTransaction::computeNextStateAndCleanupIfNeeded()
{
    // Only honor the requested state transition if we're not supposed to be
    // cleaning up and shutting down:
    if (m_database->opened()) {
        setStateToRequestedState();
        ASSERT(m_nextState == SQLTransactionState::End
            || m_nextState == SQLTransactionState::DeliverTransactionCallback
            || m_nextState == SQLTransactionState::DeliverTransactionErrorCallback
            || m_nextState == SQLTransactionState::DeliverStatementCallback
            || m_nextState == SQLTransactionState::DeliverQuotaIncreaseCallback
            || m_nextState == SQLTransactionState::DeliverSuccessCallback);

        LOG(StorageAPI, "Callback %s\n", nameForSQLTransactionState(m_nextState));
        return;
    } else
        callErrorCallbackDueToInterruption();

    clearCallbackWrappers();
    m_backend.requestTransitToState(SQLTransactionState::CleanupAndTerminate);
}

void SQLTransaction::clearCallbackWrappers()
{
    // Release the unneeded callbacks, to break reference cycles.
    m_callbackWrapper.clear();
    m_successCallbackWrapper.clear();
    m_errorCallbackWrapper.clear();
}

void SQLTransaction::getNextStatement()
{
    m_currentStatement = nullptr;

    LockHolder locker(m_statementMutex);
    if (!m_statementQueue.isEmpty())
        m_currentStatement = m_statementQueue.takeFirst();
}

bool SQLTransaction::runCurrentStatement()
{
    if (!m_currentStatement) {
        // No more statements to run. So move on to the next state.
        return false;
    }

    m_database->resetAuthorizer();

    if (m_hasVersionMismatch)
        m_currentStatement->setVersionMismatchedError();

    if (m_currentStatement->execute(m_database)) {
        if (m_database->lastActionChangedDatabase()) {
            // Flag this transaction as having changed the database for later delegate notification
            m_modifiedDatabase = true;
        }

        if (m_currentStatement->hasStatementCallback()) {
            scheduleCallback(&SQLTransaction::deliverStatementCallback);
            return false;
        }

        // If we get here, then the statement doesn't have a callback to invoke.
        // We can move on to the next statement. Hence, stay in this state.
        return true;
    }

    if (m_currentStatement->lastExecutionFailedDueToQuota()) {
        scheduleCallback(&SQLTransaction::deliverQuotaIncreaseCallback);
        return false;
    }

    handleCurrentStatementError();
    return false;
}

void SQLTransaction::handleCurrentStatementError()
{
    // Spec 4.3.2.6.6: error - Call the statement's error callback, but if there was no error callback,
    // or the transaction was rolled back, jump to the transaction error callback
    if (m_currentStatement->hasStatementErrorCallback() && !m_sqliteTransaction->wasRolledBackBySqlite()) {
        scheduleCallback(&SQLTransaction::deliverStatementCallback);
        return;
    }

    m_transactionError = m_currentStatement->sqlError();
    if (!m_transactionError)
        m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "the statement failed to execute");

    handleTransactionError();
}

void SQLTransaction::handleTransactionError()
{
    ASSERT(m_transactionError);
    if (m_errorCallbackWrapper.hasCallback()) {
        scheduleCallback(&SQLTransaction::deliverTransactionErrorCallback);
        return;
    }

    // No error callback, so fast-forward to the next state and rollback the
    // transaction.
    m_backend.cleanupAfterTransactionErrorCallback();
}

void SQLTransaction::postflightAndCommit()
{
    ASSERT(m_lockAcquired);

    // Spec 4.3.2.7: Perform postflight steps, jumping to the error callback if they fail.
    if (m_wrapper && !m_wrapper->performPostflight(*this)) {
        m_transactionError = m_wrapper->sqlError();
        if (!m_transactionError)
            m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction postflight");

        handleTransactionError();
        return;
    }

    // Spec 4.3.2.7: Commit the transaction, jumping to the error callback if that fails.
    ASSERT(m_sqliteTransaction);

    m_database->disableAuthorizer();
    m_sqliteTransaction->commit();
    m_database->enableAuthorizer();

    releaseOriginLockIfNeeded();

    // If the commit failed, the transaction will still be marked as "in progress"
    if (m_sqliteTransaction->inProgress()) {
        if (m_wrapper)
            m_wrapper->handleCommitFailedAfterPostflight(*this);
        m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "unable to commit transaction", m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg());

        handleTransactionError();
        return;
    }

    // Vacuum the database if anything was deleted.
    if (m_database->hadDeletes())
        m_database->incrementalVacuumIfNeeded();

    // The commit was successful. If the transaction modified this database, notify the delegates.
    if (m_modifiedDatabase)
        m_database->didCommitWriteTransaction();

    // Spec 4.3.2.8: Deliver success callback, if there is one.
    scheduleCallback(&SQLTransaction::deliverSuccessCallback);
}

void SQLTransaction::acquireOriginLock()
{
    ASSERT(!m_originLock);
    m_originLock = DatabaseTracker::singleton().originLockFor(m_database->securityOrigin());
    m_originLock->lock();
}

void SQLTransaction::releaseOriginLockIfNeeded()
{
    if (m_originLock) {
        m_originLock->unlock();
        m_originLock = nullptr;
    }
}

#if !LOG_DISABLED
const char* SQLTransaction::debugStepName(void (SQLTransaction::*step)())
{
    if (step == &SQLTransaction::acquireLock)
        return "acquireLock";
    if (step == &SQLTransaction::openTransactionAndPreflight)
        return "openTransactionAndPreflight";
    if (step == &SQLTransaction::runStatements)
        return "runStatements";
    if (step == &SQLTransaction::postflightAndCommit)
        return "postflightAndCommit";
    if (step == &SQLTransaction::cleanupAfterTransactionErrorCallback)
        return "cleanupAfterTransactionErrorCallback";
    if (step == &SQLTransaction::deliverTransactionCallback)
        return "deliverTransactionCallback";
    if (step == &SQLTransaction::deliverTransactionErrorCallback)
        return "deliverTransactionErrorCallback";
    if (step == &SQLTransaction::deliverStatementCallback)
        return "deliverStatementCallback";
    if (step == &SQLTransaction::deliverQuotaIncreaseCallback)
        return "deliverQuotaIncreaseCallback";
    if (step == &SQLTransaction::deliverSuccessCallback)
        return "deliverSuccessCallback";

    ASSERT_NOT_REACHED();
    return "UNKNOWN";
}
#endif

} // namespace WebCore
