/*
 * Copyright (C) 2007, 2008, 2012, 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 "DatabaseTracker.h"

#include "Database.h"
#include "DatabaseContext.h"
#include "DatabaseManager.h"
#include "DatabaseManagerClient.h"
#include "DatabaseThread.h"
#include "Logging.h"
#include "OriginLock.h"
#include "SecurityOrigin.h"
#include "SecurityOriginData.h"
#include "SecurityOriginHash.h"
#include "SQLiteFileSystem.h"
#include "SQLiteStatement.h"
#include "SQLiteTransaction.h"
#include <wtf/FileSystem.h>
#include <wtf/MainThread.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/StdLibExtras.h>
#include <wtf/UUID.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>

#if PLATFORM(IOS_FAMILY)
#include "WebCoreThread.h"
#endif

namespace WebCore {

static Vector<String> isolatedCopy(const Vector<String>& original)
{
    Vector<String> copy;
    copy.reserveInitialCapacity(original.size());
    for (auto& string : original)
        copy.uncheckedAppend(string.isolatedCopy());
    return copy;
}

std::unique_ptr<DatabaseTracker> DatabaseTracker::trackerWithDatabasePath(const String& databasePath)
{
    return std::unique_ptr<DatabaseTracker>(new DatabaseTracker(databasePath));
}

static DatabaseTracker* staticTracker = nullptr;

void DatabaseTracker::initializeTracker(const String& databasePath)
{
    ASSERT(!staticTracker);
    if (staticTracker)
        return;
    staticTracker = new DatabaseTracker(databasePath);
}

bool DatabaseTracker::isInitialized()
{
    return !!staticTracker;
}

DatabaseTracker& DatabaseTracker::singleton()
{
    if (!staticTracker)
        staticTracker = new DatabaseTracker(emptyString());
    return *staticTracker;
}

DatabaseTracker::DatabaseTracker(const String& databasePath)
    : m_databaseDirectoryPath(databasePath.isolatedCopy())
{
}

String DatabaseTracker::trackerDatabasePath() const
{
    return SQLiteFileSystem::appendDatabaseFileNameToPath(m_databaseDirectoryPath.isolatedCopy(), "Databases.db");
}

void DatabaseTracker::openTrackerDatabase(TrackerCreationAction createAction)
{
    ASSERT(!m_databaseGuard.tryLock());

    if (m_database.isOpen())
        return;

    // If createIfDoesNotExist is false, SQLiteFileSystem::ensureDatabaseFileExists()
    // will return false if the database file does not exist.
    // If createIfDoesNotExist is true, SQLiteFileSystem::ensureDatabaseFileExists()
    // will attempt to create the path to the database file if it does not
    // exists yet. It'll return true if the path already exists, or if it
    // successfully creates the path. Else, it will return false.
    String databasePath = trackerDatabasePath();
    if (!SQLiteFileSystem::ensureDatabaseFileExists(databasePath, createAction == CreateIfDoesNotExist))
        return;

    if (!m_database.open(databasePath)) {
        // FIXME: What do do here?
        LOG_ERROR("Failed to open databasePath %s.", databasePath.utf8().data());
        return;
    }
    m_database.disableThreadingChecks();

    if (!m_database.tableExists("Origins")) {
        if (!m_database.executeCommand("CREATE TABLE Origins (origin TEXT UNIQUE ON CONFLICT REPLACE, quota INTEGER NOT NULL ON CONFLICT FAIL);")) {
            // FIXME: and here
            LOG_ERROR("Failed to create Origins table");
        }
    }

    if (!m_database.tableExists("Databases")) {
        if (!m_database.executeCommand("CREATE TABLE Databases (guid INTEGER PRIMARY KEY AUTOINCREMENT, origin TEXT, name TEXT, displayName TEXT, estimatedSize INTEGER, path TEXT);")) {
            // FIXME: and here
            LOG_ERROR("Failed to create Databases table");
        }
    }
}

ExceptionOr<void> DatabaseTracker::hasAdequateQuotaForOrigin(const SecurityOriginData& origin, unsigned long long estimatedSize)
{
    ASSERT(!m_databaseGuard.tryLock());
    auto usage = this->usage(origin);

    // If the database will fit, allow its creation.
    auto requirement = usage + std::max<unsigned long long>(1, estimatedSize);
    if (requirement < usage) {
        // The estimated size is so big it causes an overflow; don't allow creation.
        return Exception { SecurityError };
    }
    if (requirement > quotaNoLock(origin))
        return Exception { QuotaExceededError };
    return { };
}

ExceptionOr<void> DatabaseTracker::canEstablishDatabase(DatabaseContext& context, const String& name, unsigned long long estimatedSize)
{
    LockHolder lockDatabase(m_databaseGuard);

    // FIXME: What guarantees this context.securityOrigin() is non-null?
    auto origin = context.securityOrigin();

    if (isDeletingDatabaseOrOriginFor(origin, name))
        return Exception { SecurityError };

    recordCreatingDatabase(origin, name);

    // If a database already exists, ignore the passed-in estimated size and say it's OK.
    if (hasEntryForDatabase(origin, name))
        return { };

    auto result = hasAdequateQuotaForOrigin(origin, estimatedSize);
    if (!result.hasException())
        return { };

    // If we get here, then we do not have enough quota for one of the
    // following reasons as indicated by the set error:
    //
    // If the error is DatabaseSizeOverflowed, then this means the requested
    // estimatedSize if so unreasonably large that it can cause an overflow in
    // the usage budget computation. In that case, there's nothing more we can
    // do, and there's no need for a retry. Hence, we should indicate that
    // we're done with our attempt to create the database.
    //
    // If the error is DatabaseSizeExceededQuota, then we'll give the client
    // a chance to update the quota and call retryCanEstablishDatabase() to try
    // again. Hence, we don't call doneCreatingDatabase() yet in that case.

    auto exception = result.releaseException();
    if (exception.code() != QuotaExceededError)
        doneCreatingDatabase(origin, name);

    return exception;
}

// Note: a thought about performance: hasAdequateQuotaForOrigin() was also
// called in canEstablishDatabase(), and hence, we're repeating some work within
// hasAdequateQuotaForOrigin(). However, retryCanEstablishDatabase() should only
// be called in the rare even if canEstablishDatabase() fails. Since it is rare,
// we should not bother optimizing it. It is more beneficial to keep
// hasAdequateQuotaForOrigin() simple and correct (i.e. bug free), and just
// re-use it. Also note that the path for opening a database involves IO, and
// hence should not be a performance critical path anyway. 
ExceptionOr<void> DatabaseTracker::retryCanEstablishDatabase(DatabaseContext& context, const String& name, unsigned long long estimatedSize)
{
    LockHolder lockDatabase(m_databaseGuard);

    // FIXME: What guarantees context.securityOrigin() is non-null?
    auto origin = context.securityOrigin();

    // We have already eliminated other types of errors in canEstablishDatabase().
    // The only reason we're in retryCanEstablishDatabase() is because we gave
    // the client a chance to update the quota and are rechecking it here.
    // If we fail this check, the only possible reason this time should be due
    // to inadequate quota.
    auto result = hasAdequateQuotaForOrigin(origin, estimatedSize);
    if (!result.hasException())
        return { };

    auto exception = result.releaseException();
    ASSERT(exception.code() == QuotaExceededError);
    doneCreatingDatabase(origin, name);

    return exception;
}

bool DatabaseTracker::hasEntryForOriginNoLock(const SecurityOriginData& origin)
{
    ASSERT(!m_databaseGuard.tryLock());
    openTrackerDatabase(DontCreateIfDoesNotExist);
    if (!m_database.isOpen())
        return false;

    SQLiteStatement statement(m_database, "SELECT origin FROM Origins where origin=?;");
    if (statement.prepare() != SQLITE_OK) {
        LOG_ERROR("Failed to prepare statement.");
        return false;
    }

    statement.bindText(1, origin.databaseIdentifier());

    return statement.step() == SQLITE_ROW;
}

bool DatabaseTracker::hasEntryForDatabase(const SecurityOriginData& origin, const String& databaseIdentifier)
{
    ASSERT(!m_databaseGuard.tryLock());
    openTrackerDatabase(DontCreateIfDoesNotExist);
    if (!m_database.isOpen()) {
        // No "tracker database". Hence, no entry for the database of interest.
        return false;
    }

    // We've got a tracker database. Set up a query to ask for the db of interest:
    SQLiteStatement statement(m_database, "SELECT guid FROM Databases WHERE origin=? AND name=?;");

    if (statement.prepare() != SQLITE_OK)
        return false;

    statement.bindText(1, origin.databaseIdentifier());
    statement.bindText(2, databaseIdentifier);

    return statement.step() == SQLITE_ROW;
}

unsigned long long DatabaseTracker::maximumSize(Database& database)
{
    // The maximum size for a database is the full quota for its origin, minus the current usage within the origin,
    // plus the current usage of the given database
    LockHolder lockDatabase(m_databaseGuard);
    auto origin = database.securityOrigin();

    unsigned long long quota = quotaNoLock(origin);
    unsigned long long diskUsage = usage(origin);
    unsigned long long databaseFileSize = SQLiteFileSystem::getDatabaseFileSize(database.fileNameIsolatedCopy());
    ASSERT(databaseFileSize <= diskUsage);

    if (diskUsage > quota)
        return databaseFileSize;

    // A previous error may have allowed the origin to exceed its quota, or may
    // have allowed this database to exceed our cached estimate of the origin
    // disk usage. Don't multiply that error through integer underflow, or the
    // effective quota will permanently become 2^64.
    unsigned long long maxSize = quota - diskUsage + databaseFileSize;
    if (maxSize > quota)
        maxSize = databaseFileSize;
    return maxSize;
}

void DatabaseTracker::closeAllDatabases(CurrentQueryBehavior currentQueryBehavior)
{
    for (auto& database : openDatabases()) {
        if (currentQueryBehavior == CurrentQueryBehavior::Interrupt)
            database->interrupt();
        database->close();
    }
}

String DatabaseTracker::originPath(const SecurityOriginData& origin) const
{
    return SQLiteFileSystem::appendDatabaseFileNameToPath(m_databaseDirectoryPath.isolatedCopy(), origin.databaseIdentifier());
}

static String generateDatabaseFileName()
{
    return makeString(createCanonicalUUIDString(), ".db");
}

String DatabaseTracker::fullPathForDatabaseNoLock(const SecurityOriginData& origin, const String& name, bool createIfNotExists)
{
    ASSERT(!m_databaseGuard.tryLock());

    String originIdentifier = origin.databaseIdentifier();
    String originPath = this->originPath(origin);

    // Make sure the path for this SecurityOrigin exists
    if (createIfNotExists && !SQLiteFileSystem::ensureDatabaseDirectoryExists(originPath))
        return String();

    // See if we have a path for this database yet
    if (!m_database.isOpen())
        return String();
    SQLiteStatement statement(m_database, "SELECT path FROM Databases WHERE origin=? AND name=?;");

    if (statement.prepare() != SQLITE_OK)
        return String();

    statement.bindText(1, originIdentifier);
    statement.bindText(2, name);

    int result = statement.step();

    if (result == SQLITE_ROW)
        return SQLiteFileSystem::appendDatabaseFileNameToPath(originPath, statement.getColumnText(0));
    if (!createIfNotExists)
        return String();

    if (result != SQLITE_DONE) {
        LOG_ERROR("Failed to retrieve filename from Database Tracker for origin %s, name %s", originIdentifier.utf8().data(), name.utf8().data());
        return String();
    }
    statement.finalize();

    String fileName = generateDatabaseFileName();

    if (!addDatabase(origin, name, fileName))
        return String();

    // If this origin's quota is being tracked (open handle to a database in this origin), add this new database
    // to the quota manager now
    String fullFilePath = SQLiteFileSystem::appendDatabaseFileNameToPath(originPath, fileName);

    return fullFilePath;
}

String DatabaseTracker::fullPathForDatabase(const SecurityOriginData& origin, const String& name, bool createIfNotExists)
{
    LockHolder lockDatabase(m_databaseGuard);
    return fullPathForDatabaseNoLock(origin, name, createIfNotExists).isolatedCopy();
}

Vector<SecurityOriginData> DatabaseTracker::origins()
{
    LockHolder lockDatabase(m_databaseGuard);

    openTrackerDatabase(DontCreateIfDoesNotExist);
    if (!m_database.isOpen())
        return { };

    SQLiteStatement statement(m_database, "SELECT origin FROM Origins");
    if (statement.prepare() != SQLITE_OK) {
        LOG_ERROR("Failed to prepare statement.");
        return { };
    }

    Vector<SecurityOriginData> origins;
    int stepResult;
    while ((stepResult = statement.step()) == SQLITE_ROW)
        origins.append(SecurityOriginData::fromDatabaseIdentifier(statement.getColumnText(0))->isolatedCopy());
    origins.shrinkToFit();

    if (stepResult != SQLITE_DONE)
        LOG_ERROR("Failed to read in all origins from the database.");

    return origins;
}

Vector<String> DatabaseTracker::databaseNamesNoLock(const SecurityOriginData& origin)
{
    ASSERT(!m_databaseGuard.tryLock());
    openTrackerDatabase(DontCreateIfDoesNotExist);
    if (!m_database.isOpen())
        return { };

    SQLiteStatement statement(m_database, "SELECT name FROM Databases where origin=?;");
    if (statement.prepare() != SQLITE_OK)
        return { };

    statement.bindText(1, origin.databaseIdentifier());

    Vector<String> names;
    int result;
    while ((result = statement.step()) == SQLITE_ROW)
        names.append(statement.getColumnText(0));
    names.shrinkToFit();

    if (result != SQLITE_DONE) {
        LOG_ERROR("Failed to retrieve all database names for origin %s", origin.databaseIdentifier().utf8().data());
        return { };
    }

    return names;
}

Vector<String> DatabaseTracker::databaseNames(const SecurityOriginData& origin)
{
    Vector<String> names;
    {
        LockHolder lockDatabase(m_databaseGuard);
        names = databaseNamesNoLock(origin);
    }
    return isolatedCopy(names);
}

DatabaseDetails DatabaseTracker::detailsForNameAndOrigin(const String& name, const SecurityOriginData& origin)
{
    String originIdentifier = origin.databaseIdentifier();
    String displayName;
    int64_t expectedUsage;

    {
        LockHolder lockDatabase(m_databaseGuard);

        openTrackerDatabase(DontCreateIfDoesNotExist);
        if (!m_database.isOpen())
            return DatabaseDetails();
        SQLiteStatement statement(m_database, "SELECT displayName, estimatedSize FROM Databases WHERE origin=? AND name=?");
        if (statement.prepare() != SQLITE_OK)
            return DatabaseDetails();

        statement.bindText(1, originIdentifier);
        statement.bindText(2, name);

        int result = statement.step();
        if (result == SQLITE_DONE)
            return DatabaseDetails();

        if (result != SQLITE_ROW) {
            LOG_ERROR("Error retrieving details for database %s in origin %s from tracker database", name.utf8().data(), originIdentifier.utf8().data());
            return DatabaseDetails();
        }
        displayName = statement.getColumnText(0);
        expectedUsage = statement.getColumnInt64(1);
    }

    String path = fullPathForDatabase(origin, name, false);
    if (path.isEmpty())
        return DatabaseDetails(name, displayName, expectedUsage, 0, WTF::nullopt, WTF::nullopt);
    return DatabaseDetails(name, displayName, expectedUsage, SQLiteFileSystem::getDatabaseFileSize(path), SQLiteFileSystem::databaseCreationTime(path), SQLiteFileSystem::databaseModificationTime(path));
}

void DatabaseTracker::setDatabaseDetails(const SecurityOriginData& origin, const String& name, const String& displayName, unsigned long long estimatedSize)
{
    String originIdentifier = origin.databaseIdentifier();
    int64_t guid = 0;

    LockHolder lockDatabase(m_databaseGuard);

    openTrackerDatabase(CreateIfDoesNotExist);
    if (!m_database.isOpen())
        return;
    SQLiteStatement statement(m_database, "SELECT guid FROM Databases WHERE origin=? AND name=?");
    if (statement.prepare() != SQLITE_OK)
        return;

    statement.bindText(1, originIdentifier);
    statement.bindText(2, name);

    int result = statement.step();
    if (result == SQLITE_ROW)
        guid = statement.getColumnInt64(0);
    statement.finalize();

    if (guid == 0) {
        if (result != SQLITE_DONE)
            LOG_ERROR("Error to determing existence of database %s in origin %s in tracker database", name.utf8().data(), originIdentifier.utf8().data());
        else {
            // This case should never occur - we should never be setting database details for a database that doesn't already exist in the tracker
            // But since the tracker file is an external resource not under complete control of our code, it's somewhat invalid to make this an ASSERT case
            // So we'll print an error instead
            LOG_ERROR("Could not retrieve guid for database %s in origin %s from the tracker database - it is invalid to set database details on a database that doesn't already exist in the tracker", name.utf8().data(), originIdentifier.utf8().data());
        }
        return;
    }

    SQLiteStatement updateStatement(m_database, "UPDATE Databases SET displayName=?, estimatedSize=? WHERE guid=?");
    if (updateStatement.prepare() != SQLITE_OK)
        return;

    updateStatement.bindText(1, displayName);
    updateStatement.bindInt64(2, estimatedSize);
    updateStatement.bindInt64(3, guid);

    if (updateStatement.step() != SQLITE_DONE) {
        LOG_ERROR("Failed to update details for database %s in origin %s", name.utf8().data(), originIdentifier.utf8().data());
        return;
    }

    if (m_client)
        m_client->dispatchDidModifyDatabase(origin, name);
}

void DatabaseTracker::doneCreatingDatabase(Database& database)
{
    LockHolder lockDatabase(m_databaseGuard);
    doneCreatingDatabase(database.securityOrigin(), database.stringIdentifierIsolatedCopy());
}

Vector<Ref<Database>> DatabaseTracker::openDatabases()
{
    Vector<Ref<Database>> openDatabases;
    {
        LockHolder openDatabaseMapLock(m_openDatabaseMapGuard);

        if (m_openDatabaseMap) {
            for (auto& nameMap : m_openDatabaseMap->values()) {
                for (auto& set : nameMap->values()) {
                    for (auto& database : *set)
                        openDatabases.append(*database);
                }
            }
        }
    }
    return openDatabases;
}

void DatabaseTracker::addOpenDatabase(Database& database)
{
    LockHolder openDatabaseMapLock(m_openDatabaseMapGuard);

    if (!m_openDatabaseMap)
        m_openDatabaseMap = makeUnique<DatabaseOriginMap>();

    auto origin = database.securityOrigin();

    auto* nameMap = m_openDatabaseMap->get(origin);
    if (!nameMap) {
        nameMap = new DatabaseNameMap;
        m_openDatabaseMap->add(origin.isolatedCopy(), nameMap);
    }

    String name = database.stringIdentifierIsolatedCopy();
    auto* databaseSet = nameMap->get(name);
    if (!databaseSet) {
        databaseSet = new DatabaseSet;
        nameMap->set(name.isolatedCopy(), databaseSet);
    }

    databaseSet->add(&database);

    LOG(StorageAPI, "Added open Database %s (%p)\n", database.stringIdentifierIsolatedCopy().utf8().data(), &database);
}

void DatabaseTracker::removeOpenDatabase(Database& database)
{
    LockHolder openDatabaseMapLock(m_openDatabaseMapGuard);

    if (!m_openDatabaseMap) {
        ASSERT_NOT_REACHED();
        return;
    }

    DatabaseNameMap* nameMap = m_openDatabaseMap->get(database.securityOrigin());
    if (!nameMap) {
        ASSERT_NOT_REACHED();
        return;
    }

    String name = database.stringIdentifierIsolatedCopy();
    auto* databaseSet = nameMap->get(name);
    if (!databaseSet) {
        ASSERT_NOT_REACHED();
        return;
    }

    databaseSet->remove(&database);

    LOG(StorageAPI, "Removed open Database %s (%p)\n", database.stringIdentifierIsolatedCopy().utf8().data(), &database);

    if (!databaseSet->isEmpty())
        return;

    nameMap->remove(name);
    delete databaseSet;

    if (!nameMap->isEmpty())
        return;

    m_openDatabaseMap->remove(database.securityOrigin());
    delete nameMap;
}

RefPtr<OriginLock> DatabaseTracker::originLockFor(const SecurityOriginData& origin)
{
    LockHolder lockDatabase(m_databaseGuard);
    String databaseIdentifier = origin.databaseIdentifier();

    // The originLockMap is accessed from multiple DatabaseThreads since
    // different script contexts can be writing to different databases from
    // the same origin. Hence, the databaseIdentifier key needs to be an
    // isolated copy. An isolated copy gives us a value whose refCounting is
    // thread-safe, since our copy is guarded by the m_databaseGuard mutex.
    databaseIdentifier = databaseIdentifier.isolatedCopy();

    OriginLockMap::AddResult addResult =
        m_originLockMap.add(databaseIdentifier, RefPtr<OriginLock>());
    if (!addResult.isNewEntry)
        return addResult.iterator->value;

    String path = originPath(origin);
    RefPtr<OriginLock> lock = adoptRef(*new OriginLock(path));
    ASSERT(lock);
    addResult.iterator->value = lock;

    return lock;
}

void DatabaseTracker::deleteOriginLockFor(const SecurityOriginData& origin)
{
    ASSERT(!m_databaseGuard.tryLock());

    // There is not always an instance of an OriginLock associated with an origin.
    // For example, if the OriginLock lock file was created by a previous run of
    // the browser which has now terminated, and the current browser process
    // has not executed any database transactions from this origin that would
    // have created the OriginLock instance in memory. In this case, we will have
    // a lock file but not an OriginLock instance in memory.

    // This function is only called if we are already deleting all the database
    // files in this origin. We'll give the OriginLock one chance to do an
    // orderly clean up first when we remove its ref from the m_originLockMap.
    // This may or may not be possible depending on whether other threads are
    // also using the OriginLock at the same time. After that, we will delete the lock file.

    m_originLockMap.remove(origin.databaseIdentifier());
    OriginLock::deleteLockFile(originPath(origin));
}

unsigned long long DatabaseTracker::usage(const SecurityOriginData& origin)
{
    String originPath = this->originPath(origin);
    unsigned long long diskUsage = 0;
    for (auto& fileName : FileSystem::listDirectory(originPath, "*.db"_s))
        diskUsage += SQLiteFileSystem::getDatabaseFileSize(fileName);
    return diskUsage;
}

unsigned long long DatabaseTracker::quotaNoLock(const SecurityOriginData& origin)
{
    ASSERT(!m_databaseGuard.tryLock());
    unsigned long long quota = 0;

    openTrackerDatabase(DontCreateIfDoesNotExist);
    if (!m_database.isOpen())
        return quota;

    SQLiteStatement statement(m_database, "SELECT quota FROM Origins where origin=?;");
    if (statement.prepare() != SQLITE_OK) {
        LOG_ERROR("Failed to prepare statement.");
        return quota;
    }
    statement.bindText(1, origin.databaseIdentifier());

    if (statement.step() == SQLITE_ROW)
        quota = statement.getColumnInt64(0);

    return quota;
}

unsigned long long DatabaseTracker::quota(const SecurityOriginData& origin)
{
    LockHolder lockDatabase(m_databaseGuard);
    return quotaNoLock(origin);
}

void DatabaseTracker::setQuota(const SecurityOriginData& origin, unsigned long long quota)
{
    LockHolder lockDatabase(m_databaseGuard);

    if (quotaNoLock(origin) == quota)
        return;

    openTrackerDatabase(CreateIfDoesNotExist);
    if (!m_database.isOpen())
        return;
    
    bool insertedNewOrigin = false;

    bool originEntryExists = hasEntryForOriginNoLock(origin);
    if (!originEntryExists) {
        SQLiteStatement statement(m_database, "INSERT INTO Origins VALUES (?, ?)");
        if (statement.prepare() != SQLITE_OK) {
            LOG_ERROR("Unable to establish origin %s in the tracker", origin.databaseIdentifier().utf8().data());
        } else {
            statement.bindText(1, origin.databaseIdentifier());
            statement.bindInt64(2, quota);

            if (statement.step() != SQLITE_DONE)
                LOG_ERROR("Unable to establish origin %s in the tracker", origin.databaseIdentifier().utf8().data());
            else
                insertedNewOrigin = true;
        }
    } else {
        SQLiteStatement statement(m_database, "UPDATE Origins SET quota=? WHERE origin=?");
        bool error = statement.prepare() != SQLITE_OK;
        if (!error) {
            statement.bindInt64(1, quota);
            statement.bindText(2, origin.databaseIdentifier());

            error = !statement.executeCommand();
        }

        if (error)
            LOG_ERROR("Failed to set quota %llu in tracker database for origin %s", quota, origin.databaseIdentifier().utf8().data());
    }

    if (m_client) {
        if (insertedNewOrigin)
            m_client->dispatchDidAddNewOrigin();
        m_client->dispatchDidModifyOrigin(origin);
    }
}

bool DatabaseTracker::addDatabase(const SecurityOriginData& origin, const String& name, const String& path)
{
    ASSERT(!m_databaseGuard.tryLock());
    openTrackerDatabase(CreateIfDoesNotExist);
    if (!m_database.isOpen())
        return false;

    // New database should never be added until the origin has been established
    ASSERT(hasEntryForOriginNoLock(origin));

    SQLiteStatement statement(m_database, "INSERT INTO Databases (origin, name, path) VALUES (?, ?, ?);");

    if (statement.prepare() != SQLITE_OK)
        return false;

    statement.bindText(1, origin.databaseIdentifier());
    statement.bindText(2, name);
    statement.bindText(3, path);

    if (!statement.executeCommand()) {
        LOG_ERROR("Failed to add database %s to origin %s: %s\n", name.utf8().data(), origin.databaseIdentifier().utf8().data(), m_database.lastErrorMsg());
        return false;
    }

    if (m_client)
        m_client->dispatchDidModifyOrigin(origin);

    return true;
}

void DatabaseTracker::deleteAllDatabasesImmediately()
{
    // This method is only intended for use by DumpRenderTree / WebKitTestRunner.
    // Actually deleting the databases is necessary to reset to a known state before running
    // each test case, but may be unsafe in deployment use cases (where multiple applications
    // may be accessing the same databases concurrently).
    for (auto& origin : origins())
        deleteOrigin(origin, DeletionMode::Immediate);
}

void DatabaseTracker::deleteDatabasesModifiedSince(WallTime time)
{
    for (auto& origin : origins()) {
        Vector<String> databaseNames = this->databaseNames(origin);
        Vector<String> databaseNamesToDelete;
        databaseNamesToDelete.reserveInitialCapacity(databaseNames.size());
        for (const auto& databaseName : databaseNames) {
            auto fullPath = fullPathForDatabase(origin, databaseName, false);

            // If the file doesn't exist, we previously deleted it but failed to remove the information
            // from the tracker database. We want to delete all of the information associated with this
            // database from the tracker database, so still add its name to databaseNamesToDelete.
            if (FileSystem::fileExists(fullPath)) {
                auto modificationTime = FileSystem::getFileModificationTime(fullPath);
                if (!modificationTime)
                    continue;

                if (modificationTime.value() < time)
                    continue;
            }

            databaseNamesToDelete.uncheckedAppend(databaseName);
        }

        if (databaseNames.size() == databaseNamesToDelete.size())
            deleteOrigin(origin);
        else {
            for (const auto& databaseName : databaseNamesToDelete)
                deleteDatabase(origin, databaseName);
        }
    }
}

// It is the caller's responsibility to make sure that nobody is trying to create, delete, open, or close databases in this origin while the deletion is
// taking place.
bool DatabaseTracker::deleteOrigin(const SecurityOriginData& origin)
{
    return deleteOrigin(origin, DeletionMode::Default);
}

bool DatabaseTracker::deleteOrigin(const SecurityOriginData& origin, DeletionMode deletionMode)
{
    Vector<String> databaseNames;
    {
        LockHolder lockDatabase(m_databaseGuard);
        openTrackerDatabase(DontCreateIfDoesNotExist);
        if (!m_database.isOpen())
            return false;

        databaseNames = databaseNamesNoLock(origin);
        if (databaseNames.isEmpty())
            LOG_ERROR("Unable to retrieve list of database names for origin %s", origin.databaseIdentifier().utf8().data());

        if (!canDeleteOrigin(origin)) {
            LOG_ERROR("Tried to delete an origin (%s) while either creating database in it or already deleting it", origin.databaseIdentifier().utf8().data());
            ASSERT_NOT_REACHED();
            return false;
        }
        recordDeletingOrigin(origin);
    }

    // We drop the lock here because holding locks during a call to deleteDatabaseFile will deadlock.
    bool failedToDeleteAnyDatabaseFile = false;
    for (auto& name : databaseNames) {
        if (FileSystem::fileExists(fullPathForDatabase(origin, name, false)) && !deleteDatabaseFile(origin, name, deletionMode)) {
            // Even if the file can't be deleted, we want to try and delete the rest, don't return early here.
            LOG_ERROR("Unable to delete file for database %s in origin %s", name.utf8().data(), origin.databaseIdentifier().utf8().data());
            failedToDeleteAnyDatabaseFile = true;
        }
    }

    // If databaseNames is empty, delete everything in the directory containing the databases for this origin.
    // This condition indicates that we previously tried to remove the origin but didn't get all of the way
    // through the deletion process. Because we have lost track of the databases for this origin,
    // we can assume that no other process is accessing them. This means it should be safe to delete them outright.
    if (databaseNames.isEmpty()) {
#if PLATFORM(COCOA)
        RELEASE_LOG_ERROR(DatabaseTracker, "Unable to retrieve list of database names for origin");
#endif
        for (const auto& file : FileSystem::listDirectory(originPath(origin), "*")) {
            if (!FileSystem::deleteFile(file))
                failedToDeleteAnyDatabaseFile = true;
        }
    }

    // If we failed to delete any database file, don't remove the origin from the tracker
    // database because we didn't successfully remove all of its data.
    if (failedToDeleteAnyDatabaseFile) {
#if PLATFORM(COCOA)
        RELEASE_LOG_ERROR(DatabaseTracker, "Failed to delete database for origin");
#endif
        return false;
    }

    {
        LockHolder lockDatabase(m_databaseGuard);
        deleteOriginLockFor(origin);
        doneDeletingOrigin(origin);

        SQLiteTransaction transaction(m_database);
        transaction.begin();

        SQLiteStatement statement(m_database, "DELETE FROM Databases WHERE origin=?");
        if (statement.prepare() != SQLITE_OK) {
            LOG_ERROR("Unable to prepare deletion of databases from origin %s from tracker", origin.databaseIdentifier().utf8().data());
            return false;
        }

        statement.bindText(1, origin.databaseIdentifier());

        if (!statement.executeCommand()) {
            LOG_ERROR("Unable to execute deletion of databases from origin %s from tracker", origin.databaseIdentifier().utf8().data());
            return false;
        }

        SQLiteStatement originStatement(m_database, "DELETE FROM Origins WHERE origin=?");
        if (originStatement.prepare() != SQLITE_OK) {
            LOG_ERROR("Unable to prepare deletion of origin %s from tracker", origin.databaseIdentifier().utf8().data());
            return false;
        }

        originStatement.bindText(1, origin.databaseIdentifier());

        if (!originStatement.executeCommand()) {
            LOG_ERROR("Unable to execute deletion of databases from origin %s from tracker", origin.databaseIdentifier().utf8().data());
            return false;
        }

        transaction.commit();

        SQLiteFileSystem::deleteEmptyDatabaseDirectory(originPath(origin));

        bool isEmpty = true;

        openTrackerDatabase(DontCreateIfDoesNotExist);
        if (m_database.isOpen()) {
            SQLiteStatement statement(m_database, "SELECT origin FROM Origins");
            if (statement.prepare() != SQLITE_OK)
                LOG_ERROR("Failed to prepare statement.");
            else if (statement.step() == SQLITE_ROW)
                isEmpty = false;
        }

        // If we removed the last origin, do some additional deletion.
        if (isEmpty) {
            if (m_database.isOpen())
                m_database.close();
           SQLiteFileSystem::deleteDatabaseFile(trackerDatabasePath());
           SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_databaseDirectoryPath);
        }

        if (m_client) {
            m_client->dispatchDidModifyOrigin(origin);
            m_client->dispatchDidDeleteDatabaseOrigin();
            for (auto& name : databaseNames)
                m_client->dispatchDidModifyDatabase(origin, name);
        }
    }
    return true;
}

bool DatabaseTracker::isDeletingDatabaseOrOriginFor(const SecurityOriginData& origin, const String& name)
{
    ASSERT(!m_databaseGuard.tryLock());
    // Can't create a database while someone else is deleting it; there's a risk of leaving untracked database debris on the disk.
    return isDeletingDatabase(origin, name) || isDeletingOrigin(origin);
}

void DatabaseTracker::recordCreatingDatabase(const SecurityOriginData& origin, const String& name)
{
    ASSERT(!m_databaseGuard.tryLock());

    // We don't use HashMap::ensure here to avoid making an isolated copy of the origin every time.
    auto* nameSet = m_beingCreated.get(origin);
    if (!nameSet) {
        auto ownedSet = makeUnique<HashCountedSet<String>>();
        nameSet = ownedSet.get();
        m_beingCreated.add(origin.isolatedCopy(), WTFMove(ownedSet));
    }
    nameSet->add(name.isolatedCopy());
}

void DatabaseTracker::doneCreatingDatabase(const SecurityOriginData& origin, const String& name)
{
    ASSERT(!m_databaseGuard.tryLock());

    ASSERT(m_beingCreated.contains(origin));

    auto iterator = m_beingCreated.find(origin);
    if (iterator == m_beingCreated.end())
        return;

    auto& countedSet = *iterator->value;
    ASSERT(countedSet.contains(name));

    if (countedSet.remove(name) && countedSet.isEmpty())
        m_beingCreated.remove(iterator);
}

bool DatabaseTracker::creatingDatabase(const SecurityOriginData& origin, const String& name)
{
    ASSERT(!m_databaseGuard.tryLock());

    auto iterator = m_beingCreated.find(origin);
    return iterator != m_beingCreated.end() && iterator->value->contains(name);
}

bool DatabaseTracker::canDeleteDatabase(const SecurityOriginData& origin, const String& name)
{
    ASSERT(!m_databaseGuard.tryLock());
    return !creatingDatabase(origin, name) && !isDeletingDatabase(origin, name);
}

void DatabaseTracker::recordDeletingDatabase(const SecurityOriginData& origin, const String& name)
{
    ASSERT(!m_databaseGuard.tryLock());
    ASSERT(canDeleteDatabase(origin, name));

    // We don't use HashMap::ensure here to avoid making an isolated copy of the origin every time.
    auto* nameSet = m_beingDeleted.get(origin);
    if (!nameSet) {
        auto ownedSet = makeUnique<HashSet<String>>();
        nameSet = ownedSet.get();
        m_beingDeleted.add(origin.isolatedCopy(), WTFMove(ownedSet));
    }
    ASSERT(!nameSet->contains(name));
    nameSet->add(name.isolatedCopy());
}

void DatabaseTracker::doneDeletingDatabase(const SecurityOriginData& origin, const String& name)
{
    ASSERT(!m_databaseGuard.tryLock());
    ASSERT(m_beingDeleted.contains(origin));

    auto iterator = m_beingDeleted.find(origin);
    if (iterator == m_beingDeleted.end())
        return;

    ASSERT(iterator->value->contains(name));
    iterator->value->remove(name);
    if (iterator->value->isEmpty())
        m_beingDeleted.remove(iterator);
}

bool DatabaseTracker::isDeletingDatabase(const SecurityOriginData& origin, const String& name)
{
    ASSERT(!m_databaseGuard.tryLock());
    auto* nameSet = m_beingDeleted.get(origin);
    return nameSet && nameSet->contains(name);
}

bool DatabaseTracker::canDeleteOrigin(const SecurityOriginData& origin)
{
    ASSERT(!m_databaseGuard.tryLock());
    return !(isDeletingOrigin(origin) || m_beingCreated.get(origin));
}

bool DatabaseTracker::isDeletingOrigin(const SecurityOriginData& origin)
{
    ASSERT(!m_databaseGuard.tryLock());
    return m_originsBeingDeleted.contains(origin);
}

void DatabaseTracker::recordDeletingOrigin(const SecurityOriginData& origin)
{
    ASSERT(!m_databaseGuard.tryLock());
    ASSERT(!isDeletingOrigin(origin));
    m_originsBeingDeleted.add(origin.isolatedCopy());
}

void DatabaseTracker::doneDeletingOrigin(const SecurityOriginData& origin)
{
    ASSERT(!m_databaseGuard.tryLock());
    ASSERT(isDeletingOrigin(origin));
    m_originsBeingDeleted.remove(origin);
}

bool DatabaseTracker::deleteDatabase(const SecurityOriginData& origin, const String& name)
{
    {
        LockHolder lockDatabase(m_databaseGuard);
        openTrackerDatabase(DontCreateIfDoesNotExist);
        if (!m_database.isOpen())
            return false;

        if (!canDeleteDatabase(origin, name)) {
            ASSERT_NOT_REACHED();
            return false;
        }
        recordDeletingDatabase(origin, name);
    }

    // We drop the lock here because holding locks during a call to deleteDatabaseFile will deadlock.
    if (FileSystem::fileExists(fullPathForDatabase(origin, name, false)) && !deleteDatabaseFile(origin, name, DeletionMode::Default)) {
        LOG_ERROR("Unable to delete file for database %s in origin %s", name.utf8().data(), origin.databaseIdentifier().utf8().data());
        LockHolder lockDatabase(m_databaseGuard);
        doneDeletingDatabase(origin, name);
        return false;
    }

    LockHolder lockDatabase(m_databaseGuard);

    SQLiteStatement statement(m_database, "DELETE FROM Databases WHERE origin=? AND name=?");
    if (statement.prepare() != SQLITE_OK) {
        LOG_ERROR("Unable to prepare deletion of database %s from origin %s from tracker", name.utf8().data(), origin.databaseIdentifier().utf8().data());
        doneDeletingDatabase(origin, name);
        return false;
    }

    statement.bindText(1, origin.databaseIdentifier());
    statement.bindText(2, name);

    if (!statement.executeCommand()) {
        LOG_ERROR("Unable to execute deletion of database %s from origin %s from tracker", name.utf8().data(), origin.databaseIdentifier().utf8().data());
        doneDeletingDatabase(origin, name);
        return false;
    }

    if (m_client) {
        m_client->dispatchDidModifyOrigin(origin);
        m_client->dispatchDidModifyDatabase(origin, name);
        m_client->dispatchDidDeleteDatabase();
    }
    doneDeletingDatabase(origin, name);
    
    return true;
}

// deleteDatabaseFile has to release locks between looking up the list of databases to close and closing them.  While this is in progress, the caller
// is responsible for making sure no new databases are opened in the file to be deleted.
bool DatabaseTracker::deleteDatabaseFile(const SecurityOriginData& origin, const String& name, DeletionMode deletionMode)
{
    String fullPath = fullPathForDatabase(origin, name, false);
    if (fullPath.isEmpty())
        return true;

#ifndef NDEBUG
    {
        LockHolder lockDatabase(m_databaseGuard);
        ASSERT(isDeletingDatabaseOrOriginFor(origin, name));
    }
#endif

    Vector<Ref<Database>> deletedDatabases;

    // Make sure not to hold the any locks when calling
    // Database::markAsDeletedAndClose(), since that can cause a deadlock
    // during the synchronous DatabaseThread call it triggers.
    {
        LockHolder openDatabaseMapLock(m_openDatabaseMapGuard);
        if (m_openDatabaseMap) {
            if (auto* nameMap = m_openDatabaseMap->get(origin)) {
                if (auto* databaseSet = nameMap->get(name)) {
                    for (auto& database : *databaseSet)
                        deletedDatabases.append(*database);
                }
            }
        }
    }

    for (auto& database : deletedDatabases)
        database->markAsDeletedAndClose();

#if PLATFORM(IOS_FAMILY)
    if (deletionMode == DeletionMode::Deferred) {
        // Other background processes may still be accessing this database. Deleting the database directly
        // would nuke the POSIX file locks, potentially causing Safari/WebApp to corrupt the new db if it's running in the background.
        // We'll instead truncate the database file to 0 bytes. If another process is operating on this same database file after
        // the truncation, it should get an error since the database file is no longer valid. When Safari is launched
        // next time, it'll go through the database files and clean up any zero-bytes ones.
        SQLiteDatabase database;
        if (!database.open(fullPath))
            return false;
        return SQLiteFileSystem::truncateDatabaseFile(database.sqlite3Handle());
    }
#else
    UNUSED_PARAM(deletionMode);
#endif

    return SQLiteFileSystem::deleteDatabaseFile(fullPath);
}
    
#if PLATFORM(IOS_FAMILY)

void DatabaseTracker::removeDeletedOpenedDatabases()
{
    // This is called when another app has deleted a database.  Go through all opened databases in this
    // tracker and close any that's no longer being tracked in the database.
    
    {
        // Acquire the lock before calling openTrackerDatabase.
        LockHolder lockDatabase(m_databaseGuard);
        openTrackerDatabase(DontCreateIfDoesNotExist);
    }

    if (!m_database.isOpen())
        return;
    
    // Keep track of which opened databases have been deleted.
    Vector<RefPtr<Database>> deletedDatabases;
    Vector<std::pair<SecurityOriginData, Vector<String>>> deletedDatabaseNames;

    // Make sure not to hold the m_openDatabaseMapGuard mutex when calling
    // Database::markAsDeletedAndClose(), since that can cause a deadlock
    // during the synchronous DatabaseThread call it triggers.
    {
        LockHolder openDatabaseMapLock(m_openDatabaseMapGuard);
        if (m_openDatabaseMap) {
            for (auto& openDatabase : *m_openDatabaseMap) {
                auto& origin = openDatabase.key;
                DatabaseNameMap* databaseNameMap = openDatabase.value;
                Vector<String> deletedDatabaseNamesForThisOrigin;

                // Loop through all opened databases in this origin.  Get the current database file path of each database and see if
                // it still matches the path stored in the opened database object.
                for (auto& databases : *databaseNameMap) {
                    String databaseName = databases.key;
                    String databaseFileName;
                    SQLiteStatement statement(m_database, "SELECT path FROM Databases WHERE origin=? AND name=?;");
                    if (statement.prepare() == SQLITE_OK) {
                        statement.bindText(1, origin.databaseIdentifier());
                        statement.bindText(2, databaseName);
                        if (statement.step() == SQLITE_ROW)
                            databaseFileName = statement.getColumnText(0);
                        statement.finalize();
                    }
                    
                    bool foundDeletedDatabase = false;
                    for (auto& db : *databases.value) {
                        // We are done if this database has already been marked as deleted.
                        if (db->deleted())
                            continue;
                        
                        // If this database has been deleted or if its database file no longer matches the current version, this database is no longer valid and it should be marked as deleted.
                        if (databaseFileName.isNull() || databaseFileName != FileSystem::pathGetFileName(db->fileNameIsolatedCopy())) {
                            deletedDatabases.append(db);
                            foundDeletedDatabase = true;
                        }
                    }
                    
                    // If the database no longer exists, we should remember to send that information to the client later.
                    if (m_client && foundDeletedDatabase && databaseFileName.isNull())
                        deletedDatabaseNamesForThisOrigin.append(databaseName);
                }
                
                if (!deletedDatabaseNamesForThisOrigin.isEmpty())
                    deletedDatabaseNames.append({ origin, WTFMove(deletedDatabaseNamesForThisOrigin) });
            }
        }
    }
    
    for (auto& deletedDatabase : deletedDatabases)
        deletedDatabase->markAsDeletedAndClose();

    for (auto& deletedDatabase : deletedDatabaseNames) {
        auto& origin = deletedDatabase.first;
        m_client->dispatchDidModifyOrigin(origin);
        for (auto& databaseName : deletedDatabase.second)
            m_client->dispatchDidModifyDatabase(origin, databaseName);
    }
}
    
static bool isZeroByteFile(const String& path)
{
    long long size = 0;
    return FileSystem::getFileSize(path, size) && !size;
}
    
bool DatabaseTracker::deleteDatabaseFileIfEmpty(const String& path)
{
    if (!isZeroByteFile(path))
        return false;
    
    SQLiteDatabase database;
    if (!database.open(path))
        return false;
    
    // Specify that we want the exclusive locking mode, so after the next write,
    // we'll be holding the lock to this database file.
    SQLiteStatement lockStatement(database, "PRAGMA locking_mode=EXCLUSIVE;");
    if (lockStatement.prepare() != SQLITE_OK)
        return false;
    int result = lockStatement.step();
    if (result != SQLITE_ROW && result != SQLITE_DONE)
        return false;
    lockStatement.finalize();

    if (!database.executeCommand("BEGIN EXCLUSIVE TRANSACTION;"))
        return false;

    // At this point, we hold the exclusive lock to this file.
    // Check that the database doesn't contain any tables.
    if (!database.executeCommand("SELECT name FROM sqlite_master WHERE type='table';"))
        return false;

    database.executeCommand("COMMIT TRANSACTION;");

    database.close();

    return SQLiteFileSystem::deleteDatabaseFile(path);
}

static Lock openDatabaseLock;
Lock& DatabaseTracker::openDatabaseMutex()
{
    return openDatabaseLock;
}

void DatabaseTracker::emptyDatabaseFilesRemovalTaskWillBeScheduled()
{
    // Lock the database from opening any database until we are done with scanning the file system for
    // zero byte database files to remove.
    openDatabaseLock.lock();
}

void DatabaseTracker::emptyDatabaseFilesRemovalTaskDidFinish()
{
    openDatabaseLock.unlock();
}

#endif

void DatabaseTracker::setClient(DatabaseManagerClient* client)
{
    m_client = client;
}

static Lock notificationLock;

using NotificationQueue = Vector<std::pair<SecurityOriginData, String>>;

static NotificationQueue& notificationQueue()
{
    static NeverDestroyed<NotificationQueue> queue;
    return queue;
}

void DatabaseTracker::scheduleNotifyDatabaseChanged(const SecurityOriginData& origin, const String& name)
{
    auto locker = holdLock(notificationLock);
    notificationQueue().append(std::make_pair(origin.isolatedCopy(), name.isolatedCopy()));
    scheduleForNotification();
}

static bool notificationScheduled = false;

void DatabaseTracker::scheduleForNotification()
{
    ASSERT(!notificationLock.tryLock());

    if (!notificationScheduled) {
        callOnMainThread([] {
            notifyDatabasesChanged();
        });
        notificationScheduled = true;
    }
}

void DatabaseTracker::notifyDatabasesChanged()
{
    // Note that if DatabaseTracker ever becomes non-singleton, we'll have to amend this notification
    // mechanism to include which tracker the notification goes out on as well.
    auto& tracker = DatabaseTracker::singleton();

    NotificationQueue notifications;
    {
        auto locker = holdLock(notificationLock);
        notifications.swap(notificationQueue());
        notificationScheduled = false;
    }

    if (!tracker.m_client)
        return;

    for (auto& notification : notifications)
        tracker.m_client->dispatchDidModifyDatabase(notification.first, notification.second);
}


} // namespace WebCore
