/*
 * 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 Computer, 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 "modules/webdatabase/SQLTransaction.h"

#include "bindings/core/v8/ExceptionState.h"
#include "core/dom/ExceptionCode.h"
#include "core/html/VoidCallback.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "modules/webdatabase/Database.h"
#include "modules/webdatabase/DatabaseAuthorizer.h"
#include "modules/webdatabase/DatabaseContext.h"
#include "modules/webdatabase/DatabaseThread.h"
#include "modules/webdatabase/SQLError.h"
#include "modules/webdatabase/SQLStatementCallback.h"
#include "modules/webdatabase/SQLStatementErrorCallback.h"
#include "modules/webdatabase/SQLTransactionBackend.h"
#include "modules/webdatabase/SQLTransactionCallback.h"
#include "modules/webdatabase/SQLTransactionClient.h"  // FIXME: Should be used in the backend only.
#include "modules/webdatabase/SQLTransactionErrorCallback.h"
#include "modules/webdatabase/StorageLog.h"
#include "wtf/StdLibExtras.h"
#include "wtf/Vector.h"

namespace blink {

SQLTransaction* SQLTransaction::create(
    Database* db,
    SQLTransactionCallback* callback,
    VoidCallback* successCallback,
    SQLTransactionErrorCallback* errorCallback,
    bool readOnly) {
  return new SQLTransaction(db, callback, successCallback, errorCallback,
                            readOnly);
}

SQLTransaction::SQLTransaction(Database* db,
                               SQLTransactionCallback* callback,
                               VoidCallback* successCallback,
                               SQLTransactionErrorCallback* errorCallback,
                               bool readOnly)
    : m_database(db),
      m_callback(callback),
      m_successCallback(successCallback),
      m_errorCallback(errorCallback),
      m_executeSqlAllowed(false),
      m_readOnly(readOnly) {
  DCHECK(isMainThread());
  ASSERT(m_database);
  InspectorInstrumentation::asyncTaskScheduled(db->getExecutionContext(),
                                               "SQLTransaction", this, true);
}

SQLTransaction::~SQLTransaction() {}

DEFINE_TRACE(SQLTransaction) {
  visitor->trace(m_database);
  visitor->trace(m_backend);
  visitor->trace(m_callback);
  visitor->trace(m_successCallback);
  visitor->trace(m_errorCallback);
}

bool SQLTransaction::hasCallback() const {
  return m_callback;
}

bool SQLTransaction::hasSuccessCallback() const {
  return m_successCallback;
}

bool SQLTransaction::hasErrorCallback() const {
  return m_errorCallback;
}

void SQLTransaction::setBackend(SQLTransactionBackend* backend) {
  ASSERT(!m_backend);
  m_backend = backend;
}

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::sendToBackendState,  // 4. runStatements
      &SQLTransaction::unreachableState,    // 5. postflightAndCommit
      &SQLTransaction::sendToBackendState,  // 6. cleanupAndTerminate
      &SQLTransaction::
          sendToBackendState,  // 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) {
#if DCHECK_IS_ON()
  STORAGE_DVLOG(1) << "Scheduling " << nameForSQLTransactionState(nextState)
                   << " for transaction " << this;
#endif
  m_requestedState = nextState;
  m_database->scheduleTransactionCallback(this);
}

SQLTransactionState SQLTransaction::nextStateForTransactionError() {
  ASSERT(m_transactionError);
  if (hasErrorCallback())
    return SQLTransactionState::DeliverTransactionErrorCallback;

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

SQLTransactionState SQLTransaction::deliverTransactionCallback() {
  bool shouldDeliverErrorCallback = false;
  InspectorInstrumentation::AsyncTask asyncTask(
      m_database->getExecutionContext(), this);

  // Spec 4.3.2 4: Invoke the transaction callback with the new SQLTransaction
  // object.
  if (SQLTransactionCallback* callback = m_callback.release()) {
    m_executeSqlAllowed = true;
    shouldDeliverErrorCallback = !callback->handleEvent(this);
    m_executeSqlAllowed = false;
  }

  // Spec 4.3.2 5: If the transaction callback was null or raised an exception,
  // jump to the error callback.
  SQLTransactionState nextState = SQLTransactionState::RunStatements;
  if (shouldDeliverErrorCallback) {
    m_database->reportStartTransactionResult(5, SQLError::kUnknownErr, 0);
    m_transactionError = SQLErrorData::create(
        SQLError::kUnknownErr,
        "the SQLTransactionCallback was null or threw an exception");
    nextState = SQLTransactionState::DeliverTransactionErrorCallback;
  }
  m_database->reportStartTransactionResult(0, -1, 0);  // OK
  return nextState;
}

SQLTransactionState SQLTransaction::deliverTransactionErrorCallback() {
  InspectorInstrumentation::AsyncTask asyncTask(
      m_database->getExecutionContext(), this);
  InspectorInstrumentation::asyncTaskCanceled(m_database->getExecutionContext(),
                                              this);

  // Spec 4.3.2.10: If exists, invoke error callback with the last
  // error to have occurred in this transaction.
  if (SQLTransactionErrorCallback* errorCallback = m_errorCallback.release()) {
    // If we get here with an empty m_transactionError, then the backend
    // must be waiting in the idle state waiting for this state to finish.
    // Hence, it's thread safe to fetch the backend transactionError without
    // a lock.
    if (!m_transactionError) {
      ASSERT(m_backend->transactionError());
      m_transactionError = SQLErrorData::create(*m_backend->transactionError());
    }
    ASSERT(m_transactionError);
    errorCallback->handleEvent(SQLError::create(*m_transactionError));

    m_transactionError = nullptr;
  }

  clearCallbacks();

  // Spec 4.3.2.10: Rollback the transaction.
  return SQLTransactionState::CleanupAfterTransactionErrorCallback;
}

SQLTransactionState SQLTransaction::deliverStatementCallback() {
  DCHECK(isMainThread());
  // 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;

  SQLStatement* currentStatement = m_backend->currentStatement();
  ASSERT(currentStatement);

  bool result = currentStatement->performCallback(this);

  m_executeSqlAllowed = false;

  if (result) {
    m_database->reportCommitTransactionResult(2, SQLError::kUnknownErr, 0);
    m_transactionError =
        SQLErrorData::create(SQLError::kUnknownErr,
                             "the statement callback raised an exception or "
                             "statement error callback did not return false");
    return nextStateForTransactionError();
  }
  return SQLTransactionState::RunStatements;
}

SQLTransactionState SQLTransaction::deliverQuotaIncreaseCallback() {
  DCHECK(isMainThread());
  ASSERT(m_backend->currentStatement());

  bool shouldRetryCurrentStatement =
      m_database->transactionClient()->didExceedQuota(database());
  m_backend->setShouldRetryCurrentStatement(shouldRetryCurrentStatement);

  return SQLTransactionState::RunStatements;
}

SQLTransactionState SQLTransaction::deliverSuccessCallback() {
  DCHECK(isMainThread());
  InspectorInstrumentation::AsyncTask asyncTask(
      m_database->getExecutionContext(), this);
  InspectorInstrumentation::asyncTaskCanceled(m_database->getExecutionContext(),
                                              this);

  // Spec 4.3.2.8: Deliver success callback.
  if (VoidCallback* successCallback = m_successCallback.release())
    successCallback->handleEvent();

  clearCallbacks();

  // Schedule a "post-success callback" step to return control to the database
  // thread in case there are further transactions queued up for this Database.
  return 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.
SQLTransactionState SQLTransaction::unreachableState() {
  ASSERT_NOT_REACHED();
  return SQLTransactionState::End;
}

SQLTransactionState SQLTransaction::sendToBackendState() {
  ASSERT(m_nextState != SQLTransactionState::Idle);
  m_backend->requestTransitToState(m_nextState);
  return SQLTransactionState::Idle;
}

void SQLTransaction::performPendingCallback() {
  DCHECK(isMainThread());
  computeNextStateAndCleanupIfNeeded();
  runStateMachine();
}

void SQLTransaction::executeSQL(const String& sqlStatement,
                                const Vector<SQLValue>& arguments,
                                SQLStatementCallback* callback,
                                SQLStatementErrorCallback* callbackError,
                                ExceptionState& exceptionState) {
  DCHECK(isMainThread());
  if (!m_executeSqlAllowed) {
    exceptionState.throwDOMException(InvalidStateError,
                                     "SQL execution is disallowed.");
    return;
  }

  if (!m_database->opened()) {
    exceptionState.throwDOMException(InvalidStateError,
                                     "The database has not been opened.");
    return;
  }

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

  SQLStatement* statement =
      SQLStatement::create(m_database.get(), callback, callbackError);
  m_backend->executeSQL(statement, sqlStatement, arguments, permissions);
}

void SQLTransaction::executeSql(ScriptState* scriptState,
                                const String& sqlStatement,
                                ExceptionState& exceptionState) {
  executeSQL(sqlStatement, Vector<SQLValue>(), nullptr, nullptr,
             exceptionState);
}

void SQLTransaction::executeSql(ScriptState* scriptState,
                                const String& sqlStatement,
                                const Nullable<Vector<ScriptValue>>& arguments,
                                SQLStatementCallback* callback,
                                SQLStatementErrorCallback* callbackError,
                                ExceptionState& exceptionState) {
  Vector<SQLValue> sqlValues;
  if (!arguments.isNull())
    sqlValues = toImplArray<Vector<SQLValue>>(
        arguments.get(), scriptState->isolate(), exceptionState);
  executeSQL(sqlStatement, sqlValues, callback, callbackError, exceptionState);
}

bool 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);
#if DCHECK_IS_ON()
    STORAGE_DVLOG(1) << "Callback " << nameForSQLTransactionState(m_nextState);
#endif
    return false;
  }

  clearCallbacks();
  m_nextState = SQLTransactionState::CleanupAndTerminate;

  return true;
}

void SQLTransaction::clearCallbacks() {
  m_callback.clear();
  m_successCallback.clear();
  m_errorCallback.clear();
}

SQLTransactionErrorCallback* SQLTransaction::releaseErrorCallback() {
  return m_errorCallback.release();
}

}  // namespace blink
