/*
 * 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.isHeld());

    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);"_s)) {
            // 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);"_s)) {
            // FIXME: and here
            LOG_ERROR("Failed to create Databases table");
        }
    }
}

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

    // If the database will fit, allow its creation.
    auto requirement = usage + std::max<uint64_t>(1u, 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, uint64_t estimatedSize)
{
    Locker 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, uint64_t estimatedSize)
{
    Locker 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.isHeld());
    openTrackerDatabase(DontCreateIfDoesNotExist);
    if (!m_database.isOpen())
        return false;

    auto statement = m_database.prepareStatement("SELECT origin FROM Origins where origin=?;"_s);
    if (!statement) {
        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.isHeld());
    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:
    auto statement = m_database.prepareStatement("SELECT guid FROM Databases WHERE origin=? AND name=?;"_s);

    if (!statement)
        return false;

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

    return statement->step() == SQLITE_ROW;
}

uint64_t 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
    Locker lockDatabase { m_databaseGuard };
    auto origin = database.securityOrigin();

    auto quota = quotaNoLock(origin);
    auto diskUsage = usage(origin);
    auto databaseFileSize = SQLiteFileSystem::databaseFileSize(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.
    uint64_t 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.isHeld());

    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();

    {
        auto statement = m_database.prepareStatement("SELECT path FROM Databases WHERE origin=? AND name=?;"_s);
        if (!statement)
            return String();

        statement->bindText(1, originIdentifier);
        statement->bindText(2, name);

        int result = statement->step();
        if (result == SQLITE_ROW)
            return SQLiteFileSystem::appendDatabaseFileNameToPath(originPath, statement->columnText(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();
        }
    }

    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)
{
    Locker lockDatabase { m_databaseGuard };
    return fullPathForDatabaseNoLock(origin, name, createIfNotExists).isolatedCopy();
}

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

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

    auto statement = m_database.prepareStatement("SELECT origin FROM Origins"_s);
    if (!statement) {
        LOG_ERROR("Failed to prepare statement.");
        return { };
    }

    Vector<SecurityOriginData> origins;
    int stepResult;
    while ((stepResult = statement->step()) == SQLITE_ROW)
        origins.append(SecurityOriginData::fromDatabaseIdentifier(statement->columnText(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.isHeld());
    openTrackerDatabase(DontCreateIfDoesNotExist);
    if (!m_database.isOpen())
        return { };

    auto statement = m_database.prepareStatement("SELECT name FROM Databases where origin=?;"_s);
    if (!statement)
        return { };

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

    Vector<String> names;
    int result;
    while ((result = statement->step()) == SQLITE_ROW)
        names.append(statement->columnText(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;
    {
        Locker 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;

    {
        Locker lockDatabase { m_databaseGuard };

        openTrackerDatabase(DontCreateIfDoesNotExist);
        if (!m_database.isOpen())
            return DatabaseDetails();
        auto statement = m_database.prepareStatement("SELECT displayName, estimatedSize FROM Databases WHERE origin=? AND name=?"_s);
        if (!statement)
            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->columnText(0);
        expectedUsage = statement->columnInt64(1);
    }

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

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

    Locker lockDatabase { m_databaseGuard };

    openTrackerDatabase(CreateIfDoesNotExist);
    if (!m_database.isOpen())
        return;

    {
        auto statement = m_database.prepareStatement("SELECT guid FROM Databases WHERE origin=? AND name=?"_s);
        if (!statement)
            return;

        statement->bindText(1, originIdentifier);
        statement->bindText(2, name);

        int result = statement->step();
        if (result == SQLITE_ROW)
            guid = statement->columnInt64(0);

        if (!guid) {
            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;
        }
    }

    auto updateStatement = m_database.prepareStatement("UPDATE Databases SET displayName=?, estimatedSize=? WHERE guid=?"_s);
    if (!updateStatement)
        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)
{
    Locker lockDatabase { m_databaseGuard };
    doneCreatingDatabase(database.securityOrigin(), database.stringIdentifierIsolatedCopy());
}

Vector<Ref<Database>> DatabaseTracker::openDatabases()
{
    Vector<Ref<Database>> openDatabases;
    {
        Locker 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)
{
    Locker 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)
{
    Locker 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)
{
    Locker 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.isHeld());

    // 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));
}

uint64_t DatabaseTracker::usage(const SecurityOriginData& origin)
{
    String originPath = this->originPath(origin);
    uint64_t diskUsage = 0;
    for (auto& fileName : FileSystem::listDirectory(originPath)) {
        if (fileName.endsWith(".db"))
            diskUsage += SQLiteFileSystem::databaseFileSize(FileSystem::pathByAppendingComponent(originPath, fileName));
    }
    return diskUsage;
}

uint64_t DatabaseTracker::quotaNoLock(const SecurityOriginData& origin)
{
    ASSERT(m_databaseGuard.isHeld());
    uint64_t quota = 0;

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

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

    if (statement->step() == SQLITE_ROW)
        quota = statement->columnInt64(0);

    return quota;
}

uint64_t DatabaseTracker::quota(const SecurityOriginData& origin)
{
    Locker lockDatabase { m_databaseGuard };
    return quotaNoLock(origin);
}

void DatabaseTracker::setQuota(const SecurityOriginData& origin, uint64_t quota)
{
    Locker lockDatabase { m_databaseGuard };

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

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

    bool originEntryExists = hasEntryForOriginNoLock(origin);
    if (!originEntryExists) {
        auto statement = m_database.prepareStatement("INSERT INTO Origins VALUES (?, ?)"_s);
        if (!statement) {
            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 {
        auto statement = m_database.prepareStatement("UPDATE Origins SET quota=? WHERE origin=?"_s);
        bool error = !statement;
        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.isHeld());
    openTrackerDatabase(CreateIfDoesNotExist);
    if (!m_database.isOpen())
        return false;

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

    auto statement = m_database.prepareStatement("INSERT INTO Databases (origin, name, path) VALUES (?, ?, ?);"_s);

    if (!statement)
        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::fileModificationTime(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;
    {
        Locker 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
        auto originPath = this->originPath(origin);
        for (const auto& fileName : FileSystem::listDirectory(originPath)) {
            if (!FileSystem::deleteFile(FileSystem::pathByAppendingComponent(originPath, fileName)))
                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;
    }

    {
        Locker lockDatabase { m_databaseGuard };
        deleteOriginLockFor(origin);
        doneDeletingOrigin(origin);

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

        {
            auto statement = m_database.prepareStatement("DELETE FROM Databases WHERE origin=?"_s);
            if (!statement) {
                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;
            }

            auto originStatement = m_database.prepareStatement("DELETE FROM Origins WHERE origin=?"_s);
            if (!originStatement) {
                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()) {
            auto statement = m_database.prepareStatement("SELECT origin FROM Origins"_s);
            if (!statement)
                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.isHeld());
    // 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.isHeld());

    // 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.isHeld());

    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.isHeld());

    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.isHeld());
    return !creatingDatabase(origin, name) && !isDeletingDatabase(origin, name);
}

void DatabaseTracker::recordDeletingDatabase(const SecurityOriginData& origin, const String& name)
{
    ASSERT(m_databaseGuard.isHeld());
    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.isHeld());
    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.isHeld());
    auto* nameSet = m_beingDeleted.get(origin);
    return nameSet && nameSet->contains(name);
}

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

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

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

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

bool DatabaseTracker::deleteDatabase(const SecurityOriginData& origin, const String& name)
{
    {
        Locker 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());
        Locker lockDatabase { m_databaseGuard };
        doneDeletingDatabase(origin, name);
        return false;
    }

    Locker lockDatabase { m_databaseGuard };

    auto statement = m_database.prepareStatement("DELETE FROM Databases WHERE origin=? AND name=?"_s);
    if (!statement) {
        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
    {
        Locker 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.
    {
        Locker 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)

// FIXME: This uses m_database without locking m_databaseGuard.
void DatabaseTracker::removeDeletedOpenedDatabases() WTF_IGNORES_THREAD_SAFETY_ANALYSIS
{
    // 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.
        Locker 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.
    {
        Locker 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;
                    if (auto statement = m_database.prepareStatement("SELECT path FROM Databases WHERE origin=? AND name=?;"_s)) {
                        statement->bindText(1, origin.databaseIdentifier());
                        statement->bindText(2, databaseName);
                        if (statement->step() == SQLITE_ROW)
                            databaseFileName = statement->columnText(0);
                    }
                    
                    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::pathFileName(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)
{
    auto size = FileSystem::fileSize(path);
    return 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.
    {
        auto lockStatement = database.prepareStatement("PRAGMA locking_mode=EXCLUSIVE;"_s);
        if (!lockStatement)
            return false;
        int result = lockStatement->step();
        if (result != SQLITE_ROW && result != SQLITE_DONE)
            return false;
    }

    if (!database.executeCommand("BEGIN EXCLUSIVE TRANSACTION;"_s))
        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';"_s))
        return false;

    database.executeCommand("COMMIT TRANSACTION;"_s);

    database.close();

    return SQLiteFileSystem::deleteDatabaseFile(path);
}

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

// We are not using WTF_ACQUIRES_LOCK(openDatabaseLock) because the call sites are ObjC functions and cannot be annotated.
void DatabaseTracker::emptyDatabaseFilesRemovalTaskWillBeScheduled() WTF_IGNORES_THREAD_SAFETY_ANALYSIS
{
    // 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();
}

// We are not using WTF_RELEASES_LOCK(openDatabaseLock) because the call sites are ObjC functions and cannot be annotated.
void DatabaseTracker::emptyDatabaseFilesRemovalTaskDidFinish() WTF_IGNORES_THREAD_SAFETY_ANALYSIS
{
    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)
{
    Locker locker { notificationLock };
    notificationQueue().append(std::make_pair(origin.isolatedCopy(), name.isolatedCopy()));
    scheduleForNotification();
}

static bool notificationScheduled = false;

void DatabaseTracker::scheduleForNotification()
{
    ASSERT(notificationLock.isHeld());

    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;
    {
        Locker locker { 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
