/*
 * 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 "Database.h"

#include "ChangeVersionData.h"
#include "ChangeVersionWrapper.h"
#include "DOMWindow.h"
#include "DatabaseAuthorizer.h"
#include "DatabaseCallback.h"
#include "DatabaseContext.h"
#include "DatabaseManager.h"
#include "DatabaseTask.h"
#include "DatabaseThread.h"
#include "DatabaseTracker.h"
#include "Document.h"
#include "JSDOMWindow.h"
#include "Logging.h"
#include "SQLError.h"
#include "SQLTransaction.h"
#include "SQLTransactionCallback.h"
#include "SQLTransactionErrorCallback.h"
#include "SQLiteDatabaseTracker.h"
#include "SQLiteStatement.h"
#include "SQLiteTransaction.h"
#include "ScriptExecutionContext.h"
#include "SecurityOrigin.h"
#include "VoidCallback.h"
#include "WindowEventLoop.h"
#include <wtf/NeverDestroyed.h>
#include <wtf/RefPtr.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/CString.h>

namespace WebCore {

// Registering "opened" databases with the DatabaseTracker
// =======================================================
// The DatabaseTracker maintains a list of databases that have been
// "opened" so that the client can call interrupt or delete on every database
// associated with a DatabaseContext.
//
// We will only call DatabaseTracker::addOpenDatabase() to add the database
// to the tracker as opened when we've succeeded in opening the database,
// and will set m_opened to true. Similarly, we only call
// DatabaseTracker::removeOpenDatabase() to remove the database from the
// tracker when we set m_opened to false in closeDatabase(). This sets up
// a simple symmetry between open and close operations, and a direct
// correlation to adding and removing databases from the tracker's list,
// thus ensuring that we have a correct list for the interrupt and
// delete operations to work on.
//
// The only databases instances not tracked by the tracker's open database
// list are the ones that have not been added yet, or the ones that we
// attempted an open on but failed to. Such instances only exist in the
// factory functions for creating database backends.
//
// The factory functions will either call openAndVerifyVersion() or
// performOpenAndVerify(). These methods will add the newly instantiated
// database backend if they succeed in opening the requested database.
// In the case of failure to open the database, the factory methods will
// simply discard the newly instantiated database backend when they return.
// The ref counting mechanims will automatically destruct the un-added
// (and un-returned) databases instances.

static const char versionKey[] = "WebKitDatabaseVersionKey";
static const char unqualifiedInfoTableName[] = "__WebKitDatabaseInfoTable__";
const unsigned long long quotaIncreaseSize = 5 * 1024 * 1024;

static const char* fullyQualifiedInfoTableName()
{
    static const char qualifier[] = "main.";
    static char qualifiedName[sizeof(qualifier) + sizeof(unqualifiedInfoTableName) - 1];

    static std::once_flag onceFlag;
    std::call_once(onceFlag, [] {
        snprintf(qualifiedName, sizeof(qualifiedName), "%s%s", qualifier, unqualifiedInfoTableName);
    });

    return qualifiedName;
}

static String formatErrorMessage(const char* message, int sqliteErrorCode, const char* sqliteErrorMessage)
{
    return makeString(message, " (", sqliteErrorCode, ' ', sqliteErrorMessage, ')');
}

static bool setTextValueInDatabase(SQLiteDatabase& db, const String& query, const String& value)
{
    SQLiteStatement statement(db, query);
    int result = statement.prepare();

    if (result != SQLITE_OK) {
        LOG_ERROR("Failed to prepare statement to set value in database (%s)", query.ascii().data());
        return false;
    }

    statement.bindText(1, value);

    result = statement.step();
    if (result != SQLITE_DONE) {
        LOG_ERROR("Failed to step statement to set value in database (%s)", query.ascii().data());
        return false;
    }

    return true;
}

static bool retrieveTextResultFromDatabase(SQLiteDatabase& db, const String& query, String& resultString)
{
    SQLiteStatement statement(db, query);
    int result = statement.prepare();

    if (result != SQLITE_OK) {
        LOG_ERROR("Error (%i) preparing statement to read text result from database (%s)", result, query.ascii().data());
        return false;
    }

    result = statement.step();
    if (result == SQLITE_ROW) {
        resultString = statement.getColumnText(0);
        return true;
    }
    if (result == SQLITE_DONE) {
        resultString = String();
        return true;
    }

    LOG_ERROR("Error (%i) reading text result from database (%s)", result, query.ascii().data());
    return false;
}

// FIXME: move all guid-related functions to a DatabaseVersionTracker class.
static Lock guidMutex;

static HashMap<DatabaseGUID, String>& guidToVersionMap()
{
    static NeverDestroyed<HashMap<DatabaseGUID, String>> map;
    return map;
}

// NOTE: Caller must lock guidMutex().
static inline void updateGUIDVersionMap(DatabaseGUID guid, const String& newVersion)
{
    // Note: It is not safe to put an empty string into the guidToVersionMap() map.
    // That's because the map is cross-thread, but empty strings are per-thread.
    // The copy() function makes a version of the string you can use on the current
    // thread, but we need a string we can keep in a cross-thread data structure.
    // FIXME: This is a quite-awkward restriction to have to program with.

    // Map empty string to null string (see comment above).
    guidToVersionMap().set(guid, newVersion.isEmpty() ? String() : newVersion.isolatedCopy());
}

static HashMap<DatabaseGUID, HashSet<Database*>>& guidToDatabaseMap()
{
    static NeverDestroyed<HashMap<DatabaseGUID, HashSet<Database*>>> map;
    return map;
}

static inline DatabaseGUID guidForOriginAndName(const String& origin, const String& name)
{
    static NeverDestroyed<HashMap<String, DatabaseGUID>> map;
    return map.get().ensure(makeString(origin, '/', name), [] {
        static DatabaseGUID lastUsedGUID;
        return ++lastUsedGUID;
    }).iterator->value;
}

Database::Database(DatabaseContext& context, const String& name, const String& expectedVersion, const String& displayName, unsigned long long estimatedSize)
    : m_document(*context.document())
    , m_contextThreadSecurityOrigin(m_document->securityOrigin().isolatedCopy())
    , m_databaseThreadSecurityOrigin(m_document->securityOrigin().isolatedCopy())
    , m_databaseContext(context)
    , m_name((name.isNull() ? emptyString() : name).isolatedCopy())
    , m_expectedVersion(expectedVersion.isolatedCopy())
    , m_displayName(displayName.isolatedCopy())
    , m_estimatedSize(estimatedSize)
    , m_filename(DatabaseManager::singleton().fullPathForDatabase(m_document->securityOrigin(), m_name))
    , m_databaseAuthorizer(DatabaseAuthorizer::create(unqualifiedInfoTableName))
{
    {
        std::lock_guard<Lock> locker(guidMutex);

        m_guid = guidForOriginAndName(securityOrigin().securityOrigin()->toString(), name);
        guidToDatabaseMap().ensure(m_guid, [] {
            return HashSet<Database*>();
        }).iterator->value.add(this);
    }

    m_databaseContext->databaseThread();

    ASSERT(m_databaseContext->existingDatabaseThread());
}

DatabaseThread& Database::databaseThread()
{
    ASSERT(m_databaseContext->existingDatabaseThread());
    return *m_databaseContext->existingDatabaseThread();
}

Database::~Database()
{
    // The reference to the Document needs to be cleared on the JavaScript thread. If we're on that thread already, we can just let the RefPtr's destruction do the dereffing.
    if (!isMainThread())
        callOnMainThread([document = WTFMove(m_document), databaseContext = WTFMove(m_databaseContext)] { });

    // SQLite is "multi-thread safe", but each database handle can only be used
    // on a single thread at a time.
    //
    // For DatabaseBackend, we open the SQLite database on the DatabaseThread,
    // and hence we should also close it on that same thread. This means that the
    // SQLite database need to be closed by another mechanism (see
    // DatabaseContext::stopDatabases()). By the time we get here, the SQLite
    // database should have already been closed.

    ASSERT(!m_opened);
}

ExceptionOr<void> Database::openAndVerifyVersion(bool setVersionInNewDatabase)
{
    DatabaseTaskSynchronizer synchronizer;
    auto& thread = databaseThread();
    if (thread.terminationRequested(&synchronizer))
        return Exception { InvalidStateError };

    ExceptionOr<void> result;
    auto task = makeUnique<DatabaseOpenTask>(*this, setVersionInNewDatabase, synchronizer, result);
    thread.scheduleImmediateTask(WTFMove(task));
    synchronizer.waitForTaskCompletion();

    return result;
}

void Database::interrupt()
{
    // It is safe to call this from any thread for an opened or closed database.
    m_sqliteDatabase.interrupt();
}

void Database::close()
{
    auto& thread = databaseThread();

    DatabaseTaskSynchronizer synchronizer;
    if (thread.terminationRequested(&synchronizer)) {
        LOG(StorageAPI, "Database handle %p is on a terminated DatabaseThread, cannot be marked for normal closure\n", this);
        return;
    }

    thread.scheduleImmediateTask(makeUnique<DatabaseCloseTask>(*this, synchronizer));

    // FIXME: iOS depends on this function blocking until the database is closed as part
    // of closing all open databases from a process assertion expiration handler.
    // See <https://bugs.webkit.org/show_bug.cgi?id=157184>.
    synchronizer.waitForTaskCompletion();
}

void Database::performClose()
{
    ASSERT(databaseThread().getThread() == &Thread::current());

    {
        LockHolder locker(m_transactionInProgressMutex);

        // Clean up transactions that have not been scheduled yet:
        // Transaction phase 1 cleanup. See comment on "What happens if a
        // transaction is interrupted?" at the top of SQLTransactionBackend.cpp.
        while (!m_transactionQueue.isEmpty())
            m_transactionQueue.takeFirst()->notifyDatabaseThreadIsShuttingDown();

        m_isTransactionQueueEnabled = false;
        m_transactionInProgress = false;
    }

    closeDatabase();

    // DatabaseThread keeps databases alive by referencing them in its
    // m_openDatabaseSet. DatabaseThread::recordDatabaseClose() will remove
    // this database from that set (which effectively deref's it). We hold on
    // to it with a local pointer here for a liitle longer, so that we can
    // unschedule any DatabaseTasks that refer to it before the database gets
    // deleted.
    Ref<Database> protectedThis(*this);
    auto& thread = databaseThread();
    thread.recordDatabaseClosed(*this);
    thread.unscheduleDatabaseTasks(*this);
}

class DoneCreatingDatabaseOnExitCaller {
public:
    DoneCreatingDatabaseOnExitCaller(Database& database)
        : m_database(database)
    {
    }

    ~DoneCreatingDatabaseOnExitCaller()
    {
        DatabaseTracker::singleton().doneCreatingDatabase(m_database);
    }

private:
    Database& m_database;
};

ExceptionOr<void> Database::performOpenAndVerify(bool shouldSetVersionInNewDatabase)
{
    DoneCreatingDatabaseOnExitCaller onExitCaller(*this);

    const int maxSqliteBusyWaitTime = 30000;

#if PLATFORM(IOS_FAMILY)
    {
        // Make sure we wait till the background removal of the empty database files finished before trying to open any database.
        auto locker = holdLock(DatabaseTracker::openDatabaseMutex());
    }
#endif

    SQLiteTransactionInProgressAutoCounter transactionCounter;

    if (!m_sqliteDatabase.open(m_filename))
        return Exception { InvalidStateError, formatErrorMessage("unable to open database", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg()) };
    if (!m_sqliteDatabase.turnOnIncrementalAutoVacuum())
        LOG_ERROR("Unable to turn on incremental auto-vacuum (%d %s)", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());

    m_sqliteDatabase.setBusyTimeout(maxSqliteBusyWaitTime);

    String currentVersion;
    {
        std::lock_guard<Lock> locker(guidMutex);

        auto entry = guidToVersionMap().find(m_guid);
        if (entry != guidToVersionMap().end()) {
            // Map null string to empty string (see updateGUIDVersionMap()).
            currentVersion = entry->value.isNull() ? emptyString() : entry->value.isolatedCopy();
            LOG(StorageAPI, "Current cached version for guid %i is %s", m_guid, currentVersion.ascii().data());
        } else {
            LOG(StorageAPI, "No cached version for guid %i", m_guid);

            SQLiteTransaction transaction(m_sqliteDatabase);
            transaction.begin();
            if (!transaction.inProgress()) {
                String message = formatErrorMessage("unable to open database, failed to start transaction", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
                m_sqliteDatabase.close();
                return Exception { InvalidStateError, WTFMove(message) };
            }

            String tableName(unqualifiedInfoTableName);
            if (!m_sqliteDatabase.tableExists(tableName)) {
                m_new = true;

                if (!m_sqliteDatabase.executeCommand("CREATE TABLE " + tableName + " (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,value TEXT NOT NULL ON CONFLICT FAIL);")) {
                    String message = formatErrorMessage("unable to open database, failed to create 'info' table", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
                    transaction.rollback();
                    m_sqliteDatabase.close();
                return Exception { InvalidStateError, WTFMove(message) };
                }
            } else if (!getVersionFromDatabase(currentVersion, false)) {
                String message = formatErrorMessage("unable to open database, failed to read current version", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
                transaction.rollback();
                m_sqliteDatabase.close();
                return Exception { InvalidStateError, WTFMove(message) };
            }

            if (currentVersion.length()) {
                LOG(StorageAPI, "Retrieved current version %s from database %s", currentVersion.ascii().data(), databaseDebugName().ascii().data());
            } else if (!m_new || shouldSetVersionInNewDatabase) {
                LOG(StorageAPI, "Setting version %s in database %s that was just created", m_expectedVersion.ascii().data(), databaseDebugName().ascii().data());
                if (!setVersionInDatabase(m_expectedVersion, false)) {
                    String message = formatErrorMessage("unable to open database, failed to write current version", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
                    transaction.rollback();
                    m_sqliteDatabase.close();
                    return Exception { InvalidStateError, WTFMove(message) };
                }
                currentVersion = m_expectedVersion;
            }
            updateGUIDVersionMap(m_guid, currentVersion);
            transaction.commit();
        }
    }

    if (currentVersion.isNull()) {
        LOG(StorageAPI, "Database %s does not have its version set", databaseDebugName().ascii().data());
        currentVersion = emptyString();
    }

    // If the expected version isn't the empty string, ensure that the current database version we have matches that version. Otherwise, set an exception.
    // If the expected version is the empty string, then we always return with whatever version of the database we have.
    if ((!m_new || shouldSetVersionInNewDatabase) && m_expectedVersion.length() && m_expectedVersion != currentVersion) {
        m_sqliteDatabase.close();
        return Exception { InvalidStateError, "unable to open database, version mismatch, '" + m_expectedVersion + "' does not match the currentVersion of '" + currentVersion + "'" };
    }

    m_sqliteDatabase.setAuthorizer(m_databaseAuthorizer.get());

    DatabaseTracker::singleton().addOpenDatabase(*this);
    m_opened = true;

    if (m_new && !shouldSetVersionInNewDatabase)
        m_expectedVersion = emptyString(); // The caller provided a creationCallback which will set the expected version.

    databaseThread().recordDatabaseOpen(*this);

    return { };
}

void Database::closeDatabase()
{
    if (!m_opened)
        return;

    m_sqliteDatabase.close();
    m_opened = false;

    // See comment at the top this file regarding calling removeOpenDatabase().
    DatabaseTracker::singleton().removeOpenDatabase(*this);

    {
        std::lock_guard<Lock> locker(guidMutex);

        auto it = guidToDatabaseMap().find(m_guid);
        ASSERT(it != guidToDatabaseMap().end());
        ASSERT(it->value.contains(this));
        it->value.remove(this);
        if (it->value.isEmpty()) {
            guidToDatabaseMap().remove(it);
            guidToVersionMap().remove(m_guid);
        }
    }
}

bool Database::getVersionFromDatabase(String& version, bool shouldCacheVersion)
{
    String query(String("SELECT value FROM ") + fullyQualifiedInfoTableName() +  " WHERE key = '" + versionKey + "';");

    m_databaseAuthorizer->disable();

    bool result = retrieveTextResultFromDatabase(m_sqliteDatabase, query, version);
    if (result) {
        if (shouldCacheVersion)
            setCachedVersion(version);
    } else
        LOG_ERROR("Failed to retrieve version from database %s", databaseDebugName().ascii().data());

    m_databaseAuthorizer->enable();

    return result;
}

bool Database::setVersionInDatabase(const String& version, bool shouldCacheVersion)
{
    // The INSERT will replace an existing entry for the database with the new version number, due to the UNIQUE ON CONFLICT REPLACE
    // clause in the CREATE statement (see Database::performOpenAndVerify()).
    String query(String("INSERT INTO ") + fullyQualifiedInfoTableName() +  " (key, value) VALUES ('" + versionKey + "', ?);");

    m_databaseAuthorizer->disable();

    bool result = setTextValueInDatabase(m_sqliteDatabase, query, version);
    if (result) {
        if (shouldCacheVersion)
            setCachedVersion(version);
    } else
        LOG_ERROR("Failed to set version %s in database (%s)", version.ascii().data(), query.ascii().data());

    m_databaseAuthorizer->enable();

    return result;
}

void Database::setExpectedVersion(const String& version)
{
    m_expectedVersion = version.isolatedCopy();
}

String Database::getCachedVersion() const
{
    std::lock_guard<Lock> locker(guidMutex);

    return guidToVersionMap().get(m_guid).isolatedCopy();
}

void Database::setCachedVersion(const String& actualVersion)
{
    std::lock_guard<Lock> locker(guidMutex);

    updateGUIDVersionMap(m_guid, actualVersion);
}

bool Database::getActualVersionForTransaction(String &actualVersion)
{
    ASSERT(m_sqliteDatabase.transactionInProgress());

    // Note: In multi-process browsers the cached value may be inaccurate.
    // So we retrieve the value from the database and update the cached value here.
    return getVersionFromDatabase(actualVersion, true);
}

void Database::scheduleTransaction()
{
    ASSERT(!m_transactionInProgressMutex.tryLock()); // Locked by caller.

    if (!m_isTransactionQueueEnabled || m_transactionQueue.isEmpty()) {
        m_transactionInProgress = false;
        return;
    }

    m_transactionInProgress = true;

    auto transaction = m_transactionQueue.takeFirst();
    auto task = makeUnique<DatabaseTransactionTask>(WTFMove(transaction));
    LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for transaction %p\n", task.get(), task->transaction());
    databaseThread().scheduleTask(WTFMove(task));
}

void Database::scheduleTransactionStep(SQLTransaction& transaction)
{
    auto& thread = databaseThread();

    auto task = makeUnique<DatabaseTransactionTask>(&transaction);
    LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for the transaction step\n", task.get());
    thread.scheduleTask(WTFMove(task));
}

void Database::inProgressTransactionCompleted()
{
    LockHolder locker(m_transactionInProgressMutex);
    m_transactionInProgress = false;
    scheduleTransaction();
}

bool Database::hasPendingTransaction()
{
    LockHolder locker(m_transactionInProgressMutex);
    return m_transactionInProgress || !m_transactionQueue.isEmpty();
}

SQLTransactionCoordinator* Database::transactionCoordinator()
{
    return databaseThread().transactionCoordinator();
}

String Database::version() const
{
    if (m_deleted)
        return String();

    // Note: In multi-process browsers the cached value may be accurate, but we cannot read the
    // actual version from the database without potentially inducing a deadlock.
    // FIXME: Add an async version getter to the DatabaseAPI.
    return getCachedVersion();
}

void Database::markAsDeletedAndClose()
{
    if (m_deleted)
        return;

    LOG(StorageAPI, "Marking %s (%p) as deleted", stringIdentifierIsolatedCopy().ascii().data(), this);
    m_deleted = true;

    close();
}

void Database::changeVersion(const String& oldVersion, const String& newVersion, RefPtr<SQLTransactionCallback>&& callback, RefPtr<SQLTransactionErrorCallback>&& errorCallback, RefPtr<VoidCallback>&& successCallback)
{
    runTransaction(WTFMove(callback), WTFMove(errorCallback), WTFMove(successCallback), ChangeVersionWrapper::create(oldVersion, newVersion), false);
}

void Database::transaction(RefPtr<SQLTransactionCallback>&& callback, RefPtr<SQLTransactionErrorCallback>&& errorCallback, RefPtr<VoidCallback>&& successCallback)
{
    runTransaction(WTFMove(callback), WTFMove(errorCallback), WTFMove(successCallback), nullptr, false);
}

void Database::readTransaction(RefPtr<SQLTransactionCallback>&& callback, RefPtr<SQLTransactionErrorCallback>&& errorCallback, RefPtr<VoidCallback>&& successCallback)
{
    runTransaction(WTFMove(callback), WTFMove(errorCallback), WTFMove(successCallback), nullptr, true);
}

String Database::stringIdentifierIsolatedCopy() const
{
    // Return a deep copy for ref counting thread safety
    return m_name.isolatedCopy();
}

String Database::displayNameIsolatedCopy() const
{
    // Return a deep copy for ref counting thread safety
    return m_displayName.isolatedCopy();
}

String Database::expectedVersionIsolatedCopy() const
{
    // Return a deep copy for ref counting thread safety
    return m_expectedVersion.isolatedCopy();
}

unsigned long long Database::estimatedSize() const
{
    return m_estimatedSize;
}

void Database::setEstimatedSize(unsigned long long estimatedSize)
{
    m_estimatedSize = estimatedSize;
    DatabaseTracker::singleton().setDatabaseDetails(securityOrigin(), m_name, m_displayName, m_estimatedSize);
}

String Database::fileNameIsolatedCopy() const
{
    // Return a deep copy for ref counting thread safety
    return m_filename.isolatedCopy();
}

DatabaseDetails Database::details() const
{
    // This code path is only used for database quota delegate calls, so file dates are irrelevant and left uninitialized.
    return DatabaseDetails(stringIdentifierIsolatedCopy(), displayNameIsolatedCopy(), estimatedSize(), 0, WTF::nullopt, WTF::nullopt);
}

void Database::disableAuthorizer()
{
    m_databaseAuthorizer->disable();
}

void Database::enableAuthorizer()
{
    m_databaseAuthorizer->enable();
}

void Database::setAuthorizerPermissions(int permissions)
{
    m_databaseAuthorizer->setPermissions(permissions);
}

bool Database::lastActionChangedDatabase()
{
    return m_databaseAuthorizer->lastActionChangedDatabase();
}

bool Database::lastActionWasInsert()
{
    return m_databaseAuthorizer->lastActionWasInsert();
}

void Database::resetDeletes()
{
    m_databaseAuthorizer->resetDeletes();
}

bool Database::hadDeletes()
{
    return m_databaseAuthorizer->hadDeletes();
}

void Database::resetAuthorizer()
{
    m_databaseAuthorizer->reset();
}

void Database::runTransaction(RefPtr<SQLTransactionCallback>&& callback, RefPtr<SQLTransactionErrorCallback>&& errorCallback, RefPtr<VoidCallback>&& successCallback, RefPtr<SQLTransactionWrapper>&& wrapper, bool readOnly)
{
    ASSERT(isMainThread());
    LockHolder locker(m_transactionInProgressMutex);
    if (!m_isTransactionQueueEnabled) {
        if (errorCallback) {
            m_document->eventLoop().queueTask(TaskSource::Networking, [errorCallback = makeRef(*errorCallback)]() {
                errorCallback->handleEvent(SQLError::create(SQLError::UNKNOWN_ERR, "database has been closed"));
            });
        }
        return;
    }

    m_transactionQueue.append(SQLTransaction::create(*this, WTFMove(callback), WTFMove(successCallback), errorCallback.copyRef(), WTFMove(wrapper), readOnly));
    if (!m_transactionInProgress)
        scheduleTransaction();
}

void Database::scheduleTransactionCallback(SQLTransaction* transaction)
{
    callOnMainThread([this, protectedThis = makeRef(*this), transaction = makeRefPtr(transaction)] {
        m_document->eventLoop().queueTask(TaskSource::Networking, [transaction = transaction.copyRef()] {
            transaction->performPendingCallback();
        });
    });
}

Vector<String> Database::performGetTableNames()
{
    disableAuthorizer();

    SQLiteStatement statement(sqliteDatabase(), "SELECT name FROM sqlite_master WHERE type='table';");
    if (statement.prepare() != SQLITE_OK) {
        LOG_ERROR("Unable to retrieve list of tables for database %s", databaseDebugName().ascii().data());
        enableAuthorizer();
        return Vector<String>();
    }

    Vector<String> tableNames;
    int result;
    while ((result = statement.step()) == SQLITE_ROW) {
        String name = statement.getColumnText(0);
        if (name != unqualifiedInfoTableName)
            tableNames.append(name);
    }

    enableAuthorizer();

    if (result != SQLITE_DONE) {
        LOG_ERROR("Error getting tables for database %s", databaseDebugName().ascii().data());
        return Vector<String>();
    }

    return tableNames;
}

void Database::incrementalVacuumIfNeeded()
{
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    int64_t freeSpaceSize = m_sqliteDatabase.freeSpaceSize();
    int64_t totalSize = m_sqliteDatabase.totalSize();
    if (totalSize <= 10 * freeSpaceSize) {
        int result = m_sqliteDatabase.runIncrementalVacuumCommand();
        if (result != SQLITE_OK)
            logErrorMessage(formatErrorMessage("error vacuuming database", result, m_sqliteDatabase.lastErrorMsg()));
    }
}

void Database::logErrorMessage(const String& message)
{
    m_document->addConsoleMessage(MessageSource::Storage, MessageLevel::Error, message);
}

Vector<String> Database::tableNames()
{
    // FIXME: Not using isolatedCopy on these strings looks ok since threads take strict turns
    // in dealing with them. However, if the code changes, this may not be true anymore.
    Vector<String> result;
    DatabaseTaskSynchronizer synchronizer;
    auto& thread = databaseThread();
    if (thread.terminationRequested(&synchronizer))
        return result;

    auto task = makeUnique<DatabaseTableNamesTask>(*this, synchronizer, result);
    thread.scheduleImmediateTask(WTFMove(task));
    synchronizer.waitForTaskCompletion();

    return result;
}

SecurityOriginData Database::securityOrigin()
{
    if (isMainThread())
        return m_contextThreadSecurityOrigin->data();
    if (databaseThread().getThread() == &Thread::current())
        return m_databaseThreadSecurityOrigin->data();
    RELEASE_ASSERT_NOT_REACHED();
}

unsigned long long Database::maximumSize()
{
    return DatabaseTracker::singleton().maximumSize(*this);
}

void Database::didCommitWriteTransaction()
{
    DatabaseTracker::singleton().scheduleNotifyDatabaseChanged(securityOrigin(), stringIdentifierIsolatedCopy());
}

bool Database::didExceedQuota()
{
    ASSERT(isMainThread());
    auto& tracker = DatabaseTracker::singleton();
    auto oldQuota = tracker.quota(securityOrigin());
    if (estimatedSize() <= oldQuota) {
        // The expected usage provided by the page is now smaller than the actual database size so we bump the expected usage to
        // oldQuota + 5MB so that the client actually increases the quota.
        setEstimatedSize(oldQuota + quotaIncreaseSize);
    }
    databaseContext().databaseExceededQuota(stringIdentifierIsolatedCopy(), details());
    return tracker.quota(securityOrigin()) > oldQuota;
}

#if !LOG_DISABLED || !ERROR_DISABLED

String Database::databaseDebugName() const
{
    return m_contextThreadSecurityOrigin->toString() + "::" + m_name;
}

#endif

} // namespace WebCore
