/*
 * Copyright (C) 2008, 2009, 2010, 2011 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
 * 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 "ApplicationCacheStorage.h"

#include "ApplicationCache.h"
#include "ApplicationCacheGroup.h"
#include "ApplicationCacheHost.h"
#include "ApplicationCacheResource.h"
#include "SQLiteDatabaseTracker.h"
#include "SQLiteStatement.h"
#include "SQLiteTransaction.h"
#include "SecurityOrigin.h"
#include "SecurityOriginData.h"
#include <wtf/FileSystem.h>
#include <wtf/StdLibExtras.h>
#include <wtf/URL.h>
#include <wtf/UUID.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>

namespace WebCore {

template <class T>
class StorageIDJournal {
public:  
    ~StorageIDJournal()
    {
        for (auto& record : m_records)
            record.restore();
    }

    void add(T* resource, unsigned storageID)
    {
        m_records.append(Record(resource, storageID));
    }

    void commit()
    {
        m_records.clear();
    }

private:
    class Record {
    public:
        Record() : m_resource(nullptr), m_storageID(0) { }
        Record(T* resource, unsigned storageID) : m_resource(resource), m_storageID(storageID) { }

        void restore()
        {
            m_resource->setStorageID(m_storageID);
        }

    private:
        T* m_resource;
        unsigned m_storageID;
    };

    Vector<Record> m_records;
};

static unsigned urlHostHash(const URL& url)
{
    StringView host = url.host();
    if (host.is8Bit())
        return AlreadyHashed::avoidDeletedValue(StringHasher::computeHashAndMaskTop8Bits(host.characters8(), host.length()));
    return AlreadyHashed::avoidDeletedValue(StringHasher::computeHashAndMaskTop8Bits(host.characters16(), host.length()));
}

ApplicationCacheGroup* ApplicationCacheStorage::loadCacheGroup(const URL& manifestURL)
{
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    openDatabase(false);
    if (!m_database.isOpen())
        return nullptr;

    SQLiteStatement statement(m_database, "SELECT id, manifestURL, newestCache FROM CacheGroups WHERE newestCache IS NOT NULL AND manifestURL=?");
    if (statement.prepare() != SQLITE_OK)
        return nullptr;
    
    statement.bindText(1, manifestURL);
   
    int result = statement.step();
    if (result == SQLITE_DONE)
        return nullptr;
    
    if (result != SQLITE_ROW) {
        LOG_ERROR("Could not load cache group, error \"%s\"", m_database.lastErrorMsg());
        return nullptr;
    }
    
    unsigned newestCacheStorageID = static_cast<unsigned>(statement.getColumnInt64(2));

    auto cache = loadCache(newestCacheStorageID);
    if (!cache)
        return nullptr;
        
    auto& group = *new ApplicationCacheGroup(*this, manifestURL);
    group.setStorageID(static_cast<unsigned>(statement.getColumnInt64(0)));
    group.setNewestCache(cache.releaseNonNull());
    return &group;
}    

ApplicationCacheGroup* ApplicationCacheStorage::findOrCreateCacheGroup(const URL& manifestURL)
{
    ASSERT(!manifestURL.hasFragmentIdentifier());

    auto result = m_cachesInMemory.add(manifestURL, nullptr);
    if (!result.isNewEntry) {
        ASSERT(result.iterator->value);
        return result.iterator->value;
    }

    // Look up the group in the database
    auto* group = loadCacheGroup(manifestURL);
    
    // If the group was not found we need to create it
    if (!group) {
        group = new ApplicationCacheGroup(*this, manifestURL);
        m_cacheHostSet.add(urlHostHash(manifestURL));
    }

    result.iterator->value = group;
    return group;
}

ApplicationCacheGroup* ApplicationCacheStorage::findInMemoryCacheGroup(const URL& manifestURL) const
{
    return m_cachesInMemory.get(manifestURL);
}

void ApplicationCacheStorage::loadManifestHostHashes()
{
    static bool hasLoadedHashes = false;
    
    if (hasLoadedHashes)
        return;
    
    // We set this flag to true before the database has been opened
    // to avoid trying to open the database over and over if it doesn't exist.
    hasLoadedHashes = true;
    
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    openDatabase(false);
    if (!m_database.isOpen())
        return;

    // Fetch the host hashes.
    SQLiteStatement statement(m_database, "SELECT manifestHostHash FROM CacheGroups");    
    if (statement.prepare() != SQLITE_OK)
        return;
    
    while (statement.step() == SQLITE_ROW)
        m_cacheHostSet.add(static_cast<unsigned>(statement.getColumnInt64(0)));
}    

ApplicationCacheGroup* ApplicationCacheStorage::cacheGroupForURL(const URL& url)
{
    ASSERT(!url.hasFragmentIdentifier());
    
    loadManifestHostHashes();
    
    // Hash the host name and see if there's a manifest with the same host.
    if (!m_cacheHostSet.contains(urlHostHash(url)))
        return nullptr;

    // Check if a cache already exists in memory.
    for (const auto& group : m_cachesInMemory.values()) {
        ASSERT(!group->isObsolete());

        if (!protocolHostAndPortAreEqual(url, group->manifestURL()))
            continue;
        
        if (ApplicationCache* cache = group->newestCache()) {
            ApplicationCacheResource* resource = cache->resourceForURL(url);
            if (!resource)
                continue;
            if (resource->type() & ApplicationCacheResource::Foreign)
                continue;
            return group;
        }
    }
    
    if (!m_database.isOpen())
        return nullptr;
        
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    // Check the database. Look for all cache groups with a newest cache.
    SQLiteStatement statement(m_database, "SELECT id, manifestURL, newestCache FROM CacheGroups WHERE newestCache IS NOT NULL");
    if (statement.prepare() != SQLITE_OK)
        return nullptr;
    
    int result;
    while ((result = statement.step()) == SQLITE_ROW) {
        URL manifestURL = URL({ }, statement.getColumnText(1));

        if (m_cachesInMemory.contains(manifestURL))
            continue;

        if (!protocolHostAndPortAreEqual(url, manifestURL))
            continue;

        // We found a cache group that matches. Now check if the newest cache has a resource with
        // a matching URL.
        unsigned newestCacheID = static_cast<unsigned>(statement.getColumnInt64(2));
        auto cache = loadCache(newestCacheID);
        if (!cache)
            continue;

        auto* resource = cache->resourceForURL(url);
        if (!resource)
            continue;
        if (resource->type() & ApplicationCacheResource::Foreign)
            continue;

        auto& group = *new ApplicationCacheGroup(*this, manifestURL);
        group.setStorageID(static_cast<unsigned>(statement.getColumnInt64(0)));
        group.setNewestCache(cache.releaseNonNull());
        m_cachesInMemory.set(group.manifestURL(), &group);

        return &group;
    }

    if (result != SQLITE_DONE)
        LOG_ERROR("Could not load cache group, error \"%s\"", m_database.lastErrorMsg());
    
    return nullptr;
}

ApplicationCacheGroup* ApplicationCacheStorage::fallbackCacheGroupForURL(const URL& url)
{
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    ASSERT(!url.hasFragmentIdentifier());

    // Check if an appropriate cache already exists in memory.
    for (auto* group : m_cachesInMemory.values()) {
        ASSERT(!group->isObsolete());

        if (ApplicationCache* cache = group->newestCache()) {
            URL fallbackURL;
            if (cache->isURLInOnlineWhitelist(url))
                continue;
            if (!cache->urlMatchesFallbackNamespace(url, &fallbackURL))
                continue;
            if (cache->resourceForURL(fallbackURL)->type() & ApplicationCacheResource::Foreign)
                continue;
            return group;
        }
    }
    
    if (!m_database.isOpen())
        return nullptr;
        
    // Check the database. Look for all cache groups with a newest cache.
    SQLiteStatement statement(m_database, "SELECT id, manifestURL, newestCache FROM CacheGroups WHERE newestCache IS NOT NULL");
    if (statement.prepare() != SQLITE_OK)
        return nullptr;
    
    int result;
    while ((result = statement.step()) == SQLITE_ROW) {
        URL manifestURL = URL({ }, statement.getColumnText(1));

        if (m_cachesInMemory.contains(manifestURL))
            continue;

        // Fallback namespaces always have the same origin as manifest URL, so we can avoid loading caches that cannot match.
        if (!protocolHostAndPortAreEqual(url, manifestURL))
            continue;

        // We found a cache group that matches. Now check if the newest cache has a resource with
        // a matching fallback namespace.
        unsigned newestCacheID = static_cast<unsigned>(statement.getColumnInt64(2));
        auto cache = loadCache(newestCacheID);

        URL fallbackURL;
        if (cache->isURLInOnlineWhitelist(url))
            continue;
        if (!cache->urlMatchesFallbackNamespace(url, &fallbackURL))
            continue;
        if (cache->resourceForURL(fallbackURL)->type() & ApplicationCacheResource::Foreign)
            continue;

        auto& group = *new ApplicationCacheGroup(*this, manifestURL);
        group.setStorageID(static_cast<unsigned>(statement.getColumnInt64(0)));
        group.setNewestCache(cache.releaseNonNull());

        m_cachesInMemory.set(group.manifestURL(), &group);

        return &group;
    }

    if (result != SQLITE_DONE)
        LOG_ERROR("Could not load cache group, error \"%s\"", m_database.lastErrorMsg());
    
    return nullptr;
}

void ApplicationCacheStorage::cacheGroupDestroyed(ApplicationCacheGroup& group)
{
    if (group.isObsolete()) {
        ASSERT(!group.storageID());
        ASSERT(m_cachesInMemory.get(group.manifestURL()) != &group);
        return;
    }

    ASSERT(m_cachesInMemory.get(group.manifestURL()) == &group);

    m_cachesInMemory.remove(group.manifestURL());
    
    // If the cache group is half-created, we don't want it in the saved set (as it is not stored in database).
    if (!group.storageID())
        m_cacheHostSet.remove(urlHostHash(group.manifestURL()));
}

void ApplicationCacheStorage::cacheGroupMadeObsolete(ApplicationCacheGroup& group)
{
    ASSERT(m_cachesInMemory.get(group.manifestURL()) == &group);
    ASSERT(m_cacheHostSet.contains(urlHostHash(group.manifestURL())));

    if (auto* newestCache = group.newestCache())
        remove(newestCache);

    m_cachesInMemory.remove(group.manifestURL());
    m_cacheHostSet.remove(urlHostHash(group.manifestURL()));
}

void ApplicationCacheStorage::setMaximumSize(int64_t size)
{
    m_maximumSize = size;
}

int64_t ApplicationCacheStorage::maximumSize() const
{
    return m_maximumSize;
}

bool ApplicationCacheStorage::isMaximumSizeReached() const
{
    return m_isMaximumSizeReached;
}

int64_t ApplicationCacheStorage::spaceNeeded(int64_t cacheToSave)
{
    int64_t spaceNeeded = 0;
    long long fileSize = 0;
    if (!FileSystem::getFileSize(m_cacheFile, fileSize))
        return 0;

    int64_t currentSize = fileSize + flatFileAreaSize();

    // Determine the amount of free space we have available.
    int64_t totalAvailableSize = 0;
    if (m_maximumSize < currentSize) {
        // The max size is smaller than the actual size of the app cache file.
        // This can happen if the client previously imposed a larger max size
        // value and the app cache file has already grown beyond the current
        // max size value.
        // The amount of free space is just the amount of free space inside
        // the database file. Note that this is always 0 if SQLite is compiled
        // with AUTO_VACUUM = 1.
        totalAvailableSize = m_database.freeSpaceSize();
    } else {
        // The max size is the same or larger than the current size.
        // The amount of free space available is the amount of free space
        // inside the database file plus the amount we can grow until we hit
        // the max size.
        totalAvailableSize = (m_maximumSize - currentSize) + m_database.freeSpaceSize();
    }

    // The space needed to be freed in order to accommodate the failed cache is
    // the size of the failed cache minus any already available free space.
    spaceNeeded = cacheToSave - totalAvailableSize;
    // The space needed value must be positive (or else the total already
    // available free space would be larger than the size of the failed cache and
    // saving of the cache should have never failed).
    ASSERT(spaceNeeded);
    return spaceNeeded;
}

void ApplicationCacheStorage::setDefaultOriginQuota(int64_t quota)
{
    m_defaultOriginQuota = quota;
}

bool ApplicationCacheStorage::calculateQuotaForOrigin(const SecurityOrigin& origin, int64_t& quota)
{
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    // If an Origin record doesn't exist, then the COUNT will be 0 and quota will be 0.
    // Using the count to determine if a record existed or not is a safe way to determine
    // if a quota of 0 is real, from the record, or from null.
    SQLiteStatement statement(m_database, "SELECT COUNT(quota), quota FROM Origins WHERE origin=?");
    if (statement.prepare() != SQLITE_OK)
        return false;

    statement.bindText(1, origin.data().databaseIdentifier());
    int result = statement.step();

    // Return the quota, or if it was null the default.
    if (result == SQLITE_ROW) {
        bool wasNoRecord = statement.getColumnInt64(0) == 0;
        quota = wasNoRecord ? m_defaultOriginQuota : statement.getColumnInt64(1);
        return true;
    }

    LOG_ERROR("Could not get the quota of an origin, error \"%s\"", m_database.lastErrorMsg());
    return false;
}

bool ApplicationCacheStorage::calculateUsageForOrigin(const SecurityOrigin* origin, int64_t& usage)
{
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    // If an Origins record doesn't exist, then the SUM will be null,
    // which will become 0, as expected, when converting to a number.
    SQLiteStatement statement(m_database, "SELECT SUM(Caches.size)"
                                          "  FROM CacheGroups"
                                          " INNER JOIN Origins ON CacheGroups.origin = Origins.origin"
                                          " INNER JOIN Caches ON CacheGroups.id = Caches.cacheGroup"
                                          " WHERE Origins.origin=?");
    if (statement.prepare() != SQLITE_OK)
        return false;

    statement.bindText(1, origin->data().databaseIdentifier());
    int result = statement.step();

    if (result == SQLITE_ROW) {
        usage = statement.getColumnInt64(0);
        return true;
    }

    LOG_ERROR("Could not get the quota of an origin, error \"%s\"", m_database.lastErrorMsg());
    return false;
}

bool ApplicationCacheStorage::calculateRemainingSizeForOriginExcludingCache(const SecurityOrigin& origin, ApplicationCache* cache, int64_t& remainingSize)
{
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    openDatabase(false);
    if (!m_database.isOpen())
        return false;

    // Remaining size = total origin quota - size of all caches with origin excluding the provided cache.
    // Keep track of the number of caches so we can tell if the result was a calculation or not.
    const char* query;
    int64_t excludingCacheIdentifier = cache ? cache->storageID() : 0;
    if (excludingCacheIdentifier != 0) {
        query = "SELECT COUNT(Caches.size), Origins.quota - SUM(Caches.size)"
                "  FROM CacheGroups"
                " INNER JOIN Origins ON CacheGroups.origin = Origins.origin"
                " INNER JOIN Caches ON CacheGroups.id = Caches.cacheGroup"
                " WHERE Origins.origin=?"
                "   AND Caches.id!=?";
    } else {
        query = "SELECT COUNT(Caches.size), Origins.quota - SUM(Caches.size)"
                "  FROM CacheGroups"
                " INNER JOIN Origins ON CacheGroups.origin = Origins.origin"
                " INNER JOIN Caches ON CacheGroups.id = Caches.cacheGroup"
                " WHERE Origins.origin=?";
    }

    SQLiteStatement statement(m_database, query);
    if (statement.prepare() != SQLITE_OK)
        return false;

    statement.bindText(1, origin.data().databaseIdentifier());
    if (excludingCacheIdentifier != 0)
        statement.bindInt64(2, excludingCacheIdentifier);
    int result = statement.step();

    // If the count was 0 that then we have to query the origin table directly
    // for its quota. Otherwise we can use the calculated value.
    if (result == SQLITE_ROW) {
        int64_t numberOfCaches = statement.getColumnInt64(0);
        if (numberOfCaches == 0)
            calculateQuotaForOrigin(origin, remainingSize);
        else
            remainingSize = statement.getColumnInt64(1);
        return true;
    }

    LOG_ERROR("Could not get the remaining size of an origin's quota, error \"%s\"", m_database.lastErrorMsg());
    return false;
}

bool ApplicationCacheStorage::storeUpdatedQuotaForOrigin(const SecurityOrigin* origin, int64_t quota)
{
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    openDatabase(true);
    if (!m_database.isOpen())
        return false;

    if (!ensureOriginRecord(origin))
        return false;

    SQLiteStatement updateStatement(m_database, "UPDATE Origins SET quota=? WHERE origin=?");
    if (updateStatement.prepare() != SQLITE_OK)
        return false;

    updateStatement.bindInt64(1, quota);
    updateStatement.bindText(2, origin->data().databaseIdentifier());

    return executeStatement(updateStatement);
}

bool ApplicationCacheStorage::executeSQLCommand(const String& sql)
{
    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
    ASSERT(m_database.isOpen());
    
    bool result = m_database.executeCommand(sql);
    if (!result)
        LOG_ERROR("Application Cache Storage: failed to execute statement \"%s\" error \"%s\"", 
                  sql.utf8().data(), m_database.lastErrorMsg());

    return result;
}

// Update the schemaVersion when the schema of any the Application Cache
// SQLite tables changes. This allows the database to be rebuilt when
// a new, incompatible change has been introduced to the database schema.
static const int schemaVersion = 7;
    
void ApplicationCacheStorage::verifySchemaVersion()
{
    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());

    int version = SQLiteStatement(m_database, "PRAGMA user_version").getColumnInt(0);
    if (version == schemaVersion)
        return;

    // Version will be 0 if we just created an empty file. Trying to delete tables would cause errors, because they don't exist yet.
    if (version)
        deleteTables();

    // Update user version.
    SQLiteTransaction setDatabaseVersion(m_database);
    setDatabaseVersion.begin();

    char userVersionSQL[32];
    int unusedNumBytes = snprintf(userVersionSQL, sizeof(userVersionSQL), "PRAGMA user_version=%d", schemaVersion);
    ASSERT_UNUSED(unusedNumBytes, static_cast<int>(sizeof(userVersionSQL)) >= unusedNumBytes);

    SQLiteStatement statement(m_database, userVersionSQL);
    if (statement.prepare() != SQLITE_OK)
        return;
    
    executeStatement(statement);
    setDatabaseVersion.commit();
}
    
void ApplicationCacheStorage::openDatabase(bool createIfDoesNotExist)
{
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    if (m_database.isOpen())
        return;

    // The cache directory should never be null, but if it for some weird reason is we bail out.
    if (m_cacheDirectory.isNull())
        return;

    m_cacheFile = FileSystem::pathByAppendingComponent(m_cacheDirectory, "ApplicationCache.db");
    if (!createIfDoesNotExist && !FileSystem::fileExists(m_cacheFile))
        return;

    FileSystem::makeAllDirectories(m_cacheDirectory);
    m_database.open(m_cacheFile);
    
    if (!m_database.isOpen())
        return;
    
    verifySchemaVersion();
    
    // Create tables
    executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheGroups (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "manifestHostHash INTEGER NOT NULL ON CONFLICT FAIL, manifestURL TEXT UNIQUE ON CONFLICT FAIL, newestCache INTEGER, origin TEXT)");
    executeSQLCommand("CREATE TABLE IF NOT EXISTS Caches (id INTEGER PRIMARY KEY AUTOINCREMENT, cacheGroup INTEGER, size INTEGER)");
    executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheWhitelistURLs (url TEXT NOT NULL ON CONFLICT FAIL, cache INTEGER NOT NULL ON CONFLICT FAIL)");
    executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheAllowsAllNetworkRequests (wildcard INTEGER NOT NULL ON CONFLICT FAIL, cache INTEGER NOT NULL ON CONFLICT FAIL)");
    executeSQLCommand("CREATE TABLE IF NOT EXISTS FallbackURLs (namespace TEXT NOT NULL ON CONFLICT FAIL, fallbackURL TEXT NOT NULL ON CONFLICT FAIL, "
                      "cache INTEGER NOT NULL ON CONFLICT FAIL)");
    executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheEntries (cache INTEGER NOT NULL ON CONFLICT FAIL, type INTEGER, resource INTEGER NOT NULL)");
    executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheResources (id INTEGER PRIMARY KEY AUTOINCREMENT, url TEXT NOT NULL ON CONFLICT FAIL, "
                      "statusCode INTEGER NOT NULL, responseURL TEXT NOT NULL, mimeType TEXT, textEncodingName TEXT, headers TEXT, data INTEGER NOT NULL ON CONFLICT FAIL)");
    executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheResourceData (id INTEGER PRIMARY KEY AUTOINCREMENT, data BLOB, path TEXT)");
    executeSQLCommand("CREATE TABLE IF NOT EXISTS DeletedCacheResources (id INTEGER PRIMARY KEY AUTOINCREMENT, path TEXT)");
    executeSQLCommand("CREATE TABLE IF NOT EXISTS Origins (origin TEXT UNIQUE ON CONFLICT IGNORE, quota INTEGER NOT NULL ON CONFLICT FAIL)");

    // When a cache is deleted, all its entries and its whitelist should be deleted.
    executeSQLCommand("CREATE TRIGGER IF NOT EXISTS CacheDeleted AFTER DELETE ON Caches"
                      " FOR EACH ROW BEGIN"
                      "  DELETE FROM CacheEntries WHERE cache = OLD.id;"
                      "  DELETE FROM CacheWhitelistURLs WHERE cache = OLD.id;"
                      "  DELETE FROM CacheAllowsAllNetworkRequests WHERE cache = OLD.id;"
                      "  DELETE FROM FallbackURLs WHERE cache = OLD.id;"
                      " END");

    // When a cache entry is deleted, its resource should also be deleted.
    executeSQLCommand("CREATE TRIGGER IF NOT EXISTS CacheEntryDeleted AFTER DELETE ON CacheEntries"
                      " FOR EACH ROW BEGIN"
                      "  DELETE FROM CacheResources WHERE id = OLD.resource;"
                      " END");

    // When a cache resource is deleted, its data blob should also be deleted.
    executeSQLCommand("CREATE TRIGGER IF NOT EXISTS CacheResourceDeleted AFTER DELETE ON CacheResources"
                      " FOR EACH ROW BEGIN"
                      "  DELETE FROM CacheResourceData WHERE id = OLD.data;"
                      " END");
    
    // When a cache resource is deleted, if it contains a non-empty path, that path should
    // be added to the DeletedCacheResources table so the flat file at that path can
    // be deleted at a later time.
    executeSQLCommand("CREATE TRIGGER IF NOT EXISTS CacheResourceDataDeleted AFTER DELETE ON CacheResourceData"
                      " FOR EACH ROW"
                      " WHEN OLD.path NOT NULL BEGIN"
                      "  INSERT INTO DeletedCacheResources (path) values (OLD.path);"
                      " END");
}

bool ApplicationCacheStorage::executeStatement(SQLiteStatement& statement)
{
    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
    bool result = statement.executeCommand();
    if (!result)
        LOG_ERROR("Application Cache Storage: failed to execute statement \"%s\" error \"%s\"", 
                  statement.query().utf8().data(), m_database.lastErrorMsg());
    
    return result;
}    

bool ApplicationCacheStorage::store(ApplicationCacheGroup* group, GroupStorageIDJournal* journal)
{
    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
    ASSERT(group->storageID() == 0);
    ASSERT(journal);

    // For some reason, an app cache may be partially written to disk. In particular, there may be
    // a cache group with an identical manifest URL and associated cache entries. We want to remove
    // this cache group and its associated cache entries so that we can create it again (below) as
    // a way to repair it.
    deleteCacheGroupRecord(group->manifestURL());

    SQLiteStatement statement(m_database, "INSERT INTO CacheGroups (manifestHostHash, manifestURL, origin) VALUES (?, ?, ?)");
    if (statement.prepare() != SQLITE_OK)
        return false;

    statement.bindInt64(1, urlHostHash(group->manifestURL()));
    statement.bindText(2, group->manifestURL());
    statement.bindText(3, group->origin().data().databaseIdentifier());

    if (!executeStatement(statement))
        return false;

    unsigned groupStorageID = static_cast<unsigned>(m_database.lastInsertRowID());

    if (!ensureOriginRecord(&group->origin()))
        return false;

    group->setStorageID(groupStorageID);
    journal->add(group, 0);
    return true;
}    

bool ApplicationCacheStorage::store(ApplicationCache* cache, ResourceStorageIDJournal* storageIDJournal)
{
    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
    ASSERT(cache->storageID() == 0);
    ASSERT(cache->group()->storageID() != 0);
    ASSERT(storageIDJournal);
    
    SQLiteStatement statement(m_database, "INSERT INTO Caches (cacheGroup, size) VALUES (?, ?)");
    if (statement.prepare() != SQLITE_OK)
        return false;

    statement.bindInt64(1, cache->group()->storageID());
    statement.bindInt64(2, cache->estimatedSizeInStorage());

    if (!executeStatement(statement))
        return false;
    
    unsigned cacheStorageID = static_cast<unsigned>(m_database.lastInsertRowID());

    // Store all resources
    for (auto& resource : cache->resources().values()) {
        unsigned oldStorageID = resource->storageID();
        if (!store(resource.get(), cacheStorageID))
            return false;

        // Storing the resource succeeded. Log its old storageID in case
        // it needs to be restored later.
        storageIDJournal->add(resource.get(), oldStorageID);
    }
    
    // Store the online whitelist
    const Vector<URL>& onlineWhitelist = cache->onlineWhitelist();
    {
        for (auto& whitelistURL : onlineWhitelist) {
            SQLiteStatement statement(m_database, "INSERT INTO CacheWhitelistURLs (url, cache) VALUES (?, ?)");
            statement.prepare();

            statement.bindText(1, whitelistURL);
            statement.bindInt64(2, cacheStorageID);

            if (!executeStatement(statement))
                return false;
        }
    }

    // Store online whitelist wildcard flag.
    {
        SQLiteStatement statement(m_database, "INSERT INTO CacheAllowsAllNetworkRequests (wildcard, cache) VALUES (?, ?)");
        statement.prepare();

        statement.bindInt64(1, cache->allowsAllNetworkRequests());
        statement.bindInt64(2, cacheStorageID);

        if (!executeStatement(statement))
            return false;
    }
    
    // Store fallback URLs.
    const FallbackURLVector& fallbackURLs = cache->fallbackURLs();
    {
        for (auto& fallbackURL : fallbackURLs) {
            SQLiteStatement statement(m_database, "INSERT INTO FallbackURLs (namespace, fallbackURL, cache) VALUES (?, ?, ?)");
            statement.prepare();

            statement.bindText(1, fallbackURL.first);
            statement.bindText(2, fallbackURL.second);
            statement.bindInt64(3, cacheStorageID);

            if (!executeStatement(statement))
                return false;
        }
    }

    cache->setStorageID(cacheStorageID);
    return true;
}

bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, unsigned cacheStorageID)
{
    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
    ASSERT(cacheStorageID);
    ASSERT(!resource->storageID());
    
    openDatabase(true);

    // openDatabase(true) could still fail, for example when cacheStorage is full or no longer available.
    if (!m_database.isOpen())
        return false;

    // First, insert the data
    SQLiteStatement dataStatement(m_database, "INSERT INTO CacheResourceData (data, path) VALUES (?, ?)");
    if (dataStatement.prepare() != SQLITE_OK)
        return false;
    

    String fullPath;
    if (!resource->path().isEmpty())
        dataStatement.bindText(2, FileSystem::pathGetFileName(resource->path()));
    else if (shouldStoreResourceAsFlatFile(resource)) {
        // First, check to see if creating the flat file would violate the maximum total quota. We don't need
        // to check the per-origin quota here, as it was already checked in storeNewestCache().
        if (m_database.totalSize() + flatFileAreaSize() + static_cast<int64_t>(resource->data().size()) > m_maximumSize) {
            m_isMaximumSizeReached = true;
            return false;
        }
        
        String flatFileDirectory = FileSystem::pathByAppendingComponent(m_cacheDirectory, m_flatFileSubdirectoryName);
        FileSystem::makeAllDirectories(flatFileDirectory);

        String extension;
        
        String fileName = resource->response().suggestedFilename();
        size_t dotIndex = fileName.reverseFind('.');
        if (dotIndex != notFound && dotIndex < (fileName.length() - 1))
            extension = fileName.substring(dotIndex);

        String path;
        if (!writeDataToUniqueFileInDirectory(resource->data(), flatFileDirectory, path, extension))
            return false;
        
        fullPath = FileSystem::pathByAppendingComponent(flatFileDirectory, path);
        resource->setPath(fullPath);
        dataStatement.bindText(2, path);
    } else {
        if (resource->data().size())
            dataStatement.bindBlob(1, resource->data().data(), resource->data().size());
    }
    
    if (!dataStatement.executeCommand()) {
        // Clean up the file which we may have written to:
        if (!fullPath.isEmpty())
            FileSystem::deleteFile(fullPath);

        return false;
    }

    unsigned dataId = static_cast<unsigned>(m_database.lastInsertRowID());

    // Then, insert the resource
    
    // Serialize the headers
    StringBuilder stringBuilder;
    
    for (const auto& header : resource->response().httpHeaderFields()) {
        stringBuilder.append(header.key);
        stringBuilder.append(':');
        stringBuilder.append(header.value);
        stringBuilder.append('\n');
    }
    
    String headers = stringBuilder.toString();
    
    SQLiteStatement resourceStatement(m_database, "INSERT INTO CacheResources (url, statusCode, responseURL, headers, data, mimeType, textEncodingName) VALUES (?, ?, ?, ?, ?, ?, ?)");
    if (resourceStatement.prepare() != SQLITE_OK)
        return false;
    
    // The same ApplicationCacheResource are used in ApplicationCacheResource::size()
    // to calculate the approximate size of an ApplicationCacheResource object. If
    // you change the code below, please also change ApplicationCacheResource::size().
    resourceStatement.bindText(1, resource->url());
    resourceStatement.bindInt64(2, resource->response().httpStatusCode());
    resourceStatement.bindText(3, resource->response().url());
    resourceStatement.bindText(4, headers);
    resourceStatement.bindInt64(5, dataId);
    resourceStatement.bindText(6, resource->response().mimeType());
    resourceStatement.bindText(7, resource->response().textEncodingName());

    if (!executeStatement(resourceStatement))
        return false;

    unsigned resourceId = static_cast<unsigned>(m_database.lastInsertRowID());
    
    // Finally, insert the cache entry
    SQLiteStatement entryStatement(m_database, "INSERT INTO CacheEntries (cache, type, resource) VALUES (?, ?, ?)");
    if (entryStatement.prepare() != SQLITE_OK)
        return false;
    
    entryStatement.bindInt64(1, cacheStorageID);
    entryStatement.bindInt64(2, resource->type());
    entryStatement.bindInt64(3, resourceId);
    
    if (!executeStatement(entryStatement))
        return false;
    
    // Did we successfully write the resource data to a file? If so,
    // release the resource's data and free up a potentially large amount
    // of memory:
    if (!fullPath.isEmpty())
        resource->data().clear();

    resource->setStorageID(resourceId);
    return true;
}

bool ApplicationCacheStorage::storeUpdatedType(ApplicationCacheResource* resource, ApplicationCache* cache)
{
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    ASSERT_UNUSED(cache, cache->storageID());
    ASSERT(resource->storageID());

    // First, insert the data
    SQLiteStatement entryStatement(m_database, "UPDATE CacheEntries SET type=? WHERE resource=?");
    if (entryStatement.prepare() != SQLITE_OK)
        return false;

    entryStatement.bindInt64(1, resource->type());
    entryStatement.bindInt64(2, resource->storageID());

    return executeStatement(entryStatement);
}

bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, ApplicationCache* cache)
{
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    ASSERT(cache->storageID());
    
    openDatabase(true);

    if (!m_database.isOpen())
        return false;
 
    m_isMaximumSizeReached = false;
    m_database.setMaximumSize(m_maximumSize - flatFileAreaSize());

    SQLiteTransaction storeResourceTransaction(m_database);
    storeResourceTransaction.begin();
    
    if (!store(resource, cache->storageID())) {
        checkForMaxSizeReached();
        return false;
    }

    // A resource was added to the cache. Update the total data size for the cache.
    SQLiteStatement sizeUpdateStatement(m_database, "UPDATE Caches SET size=size+? WHERE id=?");
    if (sizeUpdateStatement.prepare() != SQLITE_OK)
        return false;

    sizeUpdateStatement.bindInt64(1, resource->estimatedSizeInStorage());
    sizeUpdateStatement.bindInt64(2, cache->storageID());

    if (!executeStatement(sizeUpdateStatement))
        return false;
    
    storeResourceTransaction.commit();
    return true;
}

bool ApplicationCacheStorage::ensureOriginRecord(const SecurityOrigin* origin)
{
    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
    SQLiteStatement insertOriginStatement(m_database, "INSERT INTO Origins (origin, quota) VALUES (?, ?)");
    if (insertOriginStatement.prepare() != SQLITE_OK)
        return false;

    insertOriginStatement.bindText(1, origin->data().databaseIdentifier());
    insertOriginStatement.bindInt64(2, m_defaultOriginQuota);
    if (!executeStatement(insertOriginStatement))
        return false;

    return true;
}

bool ApplicationCacheStorage::checkOriginQuota(ApplicationCacheGroup* group, ApplicationCache* oldCache, ApplicationCache* newCache, int64_t& totalSpaceNeeded)
{
    // Check if the oldCache with the newCache would reach the per-origin quota.
    int64_t remainingSpaceInOrigin;
    auto& origin = group->origin();
    if (calculateRemainingSizeForOriginExcludingCache(origin, oldCache, remainingSpaceInOrigin)) {
        if (remainingSpaceInOrigin < newCache->estimatedSizeInStorage()) {
            int64_t quota;
            if (calculateQuotaForOrigin(origin, quota)) {
                totalSpaceNeeded = quota - remainingSpaceInOrigin + newCache->estimatedSizeInStorage();
                return false;
            }

            ASSERT_NOT_REACHED();
            totalSpaceNeeded = 0;
            return false;
        }
    }

    return true;
}

bool ApplicationCacheStorage::storeNewestCache(ApplicationCacheGroup& group, ApplicationCache* oldCache, FailureReason& failureReason)
{
    openDatabase(true);

    if (!m_database.isOpen())
        return false;

    m_isMaximumSizeReached = false;
    m_database.setMaximumSize(m_maximumSize - flatFileAreaSize());

    SQLiteTransaction storeCacheTransaction(m_database);
    
    storeCacheTransaction.begin();

    // Check if this would reach the per-origin quota.
    int64_t totalSpaceNeededIgnored;
    if (!checkOriginQuota(&group, oldCache, group.newestCache(), totalSpaceNeededIgnored)) {
        failureReason = OriginQuotaReached;
        return false;
    }

    GroupStorageIDJournal groupStorageIDJournal;
    if (!group.storageID()) {
        // Store the group
        if (!store(&group, &groupStorageIDJournal)) {
            checkForMaxSizeReached();
            failureReason = isMaximumSizeReached() ? TotalQuotaReached : DiskOrOperationFailure;
            return false;
        }
    }
    
    ASSERT(group.newestCache());
    ASSERT(!group.isObsolete());
    ASSERT(!group.newestCache()->storageID());
    
    // Log the storageID changes to the in-memory resource objects. The journal
    // object will roll them back automatically in case a database operation
    // fails and this method returns early.
    ResourceStorageIDJournal resourceStorageIDJournal;

    // Store the newest cache
    if (!store(group.newestCache(), &resourceStorageIDJournal)) {
        checkForMaxSizeReached();
        failureReason = isMaximumSizeReached() ? TotalQuotaReached : DiskOrOperationFailure;
        return false;
    }
    
    // Update the newest cache in the group.
    
    SQLiteStatement statement(m_database, "UPDATE CacheGroups SET newestCache=? WHERE id=?");
    if (statement.prepare() != SQLITE_OK) {
        failureReason = DiskOrOperationFailure;
        return false;
    }
    
    statement.bindInt64(1, group.newestCache()->storageID());
    statement.bindInt64(2, group.storageID());
    
    if (!executeStatement(statement)) {
        failureReason = DiskOrOperationFailure;
        return false;
    }
    
    groupStorageIDJournal.commit();
    resourceStorageIDJournal.commit();
    storeCacheTransaction.commit();
    return true;
}

bool ApplicationCacheStorage::storeNewestCache(ApplicationCacheGroup& group)
{
    // Ignore the reason for failing, just attempt the store.
    FailureReason ignoredFailureReason;
    return storeNewestCache(group, nullptr, ignoredFailureReason);
}

template<typename CharacterType>
static inline void parseHeader(const CharacterType* header, unsigned headerLength, ResourceResponse& response)
{
    ASSERT(find(header, headerLength, ':') != notFound);
    unsigned colonPosition = find(header, headerLength, ':');

    // Save memory by putting the header names into atomic strings so each is stored only once,
    // even though the setHTTPHeaderField function does not require an atomic string.
    AtomString headerName { header, colonPosition };
    String headerValue { header + colonPosition + 1, headerLength - colonPosition - 1 };

    response.setHTTPHeaderField(headerName, headerValue);
}

static inline void parseHeaders(const String& headers, ResourceResponse& response)
{
    unsigned startPos = 0;
    size_t endPos;
    while ((endPos = headers.find('\n', startPos)) != notFound) {
        ASSERT(startPos != endPos);

        if (headers.is8Bit())
            parseHeader(headers.characters8() + startPos, endPos - startPos, response);
        else
            parseHeader(headers.characters16() + startPos, endPos - startPos, response);
        
        startPos = endPos + 1;
    }
    
    if (startPos != headers.length()) {
        if (headers.is8Bit())
            parseHeader(headers.characters8(), headers.length(), response);
        else
            parseHeader(headers.characters16(), headers.length(), response);
    }
}
    
RefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storageID)
{
    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
    SQLiteStatement cacheStatement(m_database,
                                   "SELECT url, statusCode, type, mimeType, textEncodingName, headers, CacheResourceData.data, CacheResourceData.path FROM CacheEntries INNER JOIN CacheResources ON CacheEntries.resource=CacheResources.id "
                                   "INNER JOIN CacheResourceData ON CacheResourceData.id=CacheResources.data WHERE CacheEntries.cache=?");
    if (cacheStatement.prepare() != SQLITE_OK) {
        LOG_ERROR("Could not prepare cache statement, error \"%s\"", m_database.lastErrorMsg());
        return nullptr;
    }
    
    cacheStatement.bindInt64(1, storageID);

    auto cache = ApplicationCache::create();

    String flatFileDirectory = FileSystem::pathByAppendingComponent(m_cacheDirectory, m_flatFileSubdirectoryName);

    int result;
    while ((result = cacheStatement.step()) == SQLITE_ROW) {
        URL url({ }, cacheStatement.getColumnText(0));
        
        int httpStatusCode = cacheStatement.getColumnInt(1);

        unsigned type = static_cast<unsigned>(cacheStatement.getColumnInt64(2));

        Vector<char> blob;
        cacheStatement.getColumnBlobAsVector(6, blob);
        
        auto data = SharedBuffer::create(WTFMove(blob));
        
        String path = cacheStatement.getColumnText(7);
        long long size = 0;
        if (path.isEmpty())
            size = data->size();
        else {
            path = FileSystem::pathByAppendingComponent(flatFileDirectory, path);
            FileSystem::getFileSize(path, size);
        }
        
        String mimeType = cacheStatement.getColumnText(3);
        String textEncodingName = cacheStatement.getColumnText(4);
        
        ResourceResponse response(url, mimeType, size, textEncodingName);
        response.setHTTPStatusCode(httpStatusCode);

        String headers = cacheStatement.getColumnText(5);
        parseHeaders(headers, response);
        
        auto resource = ApplicationCacheResource::create(url, response, type, WTFMove(data), path);

        if (type & ApplicationCacheResource::Manifest)
            cache->setManifestResource(WTFMove(resource));
        else
            cache->addResource(WTFMove(resource));
    }

    if (result != SQLITE_DONE)
        LOG_ERROR("Could not load cache resources, error \"%s\"", m_database.lastErrorMsg());

    if (!cache->manifestResource()) {
        LOG_ERROR("Could not load application cache because there was no manifest resource");
        return nullptr;
    }

    // Load the online whitelist
    SQLiteStatement whitelistStatement(m_database, "SELECT url FROM CacheWhitelistURLs WHERE cache=?");
    if (whitelistStatement.prepare() != SQLITE_OK)
        return nullptr;
    whitelistStatement.bindInt64(1, storageID);
    
    Vector<URL> whitelist;
    while ((result = whitelistStatement.step()) == SQLITE_ROW) 
        whitelist.append(URL({ }, whitelistStatement.getColumnText(0)));

    if (result != SQLITE_DONE)
        LOG_ERROR("Could not load cache online whitelist, error \"%s\"", m_database.lastErrorMsg());

    cache->setOnlineWhitelist(whitelist);

    // Load online whitelist wildcard flag.
    SQLiteStatement whitelistWildcardStatement(m_database, "SELECT wildcard FROM CacheAllowsAllNetworkRequests WHERE cache=?");
    if (whitelistWildcardStatement.prepare() != SQLITE_OK)
        return nullptr;
    whitelistWildcardStatement.bindInt64(1, storageID);
    
    result = whitelistWildcardStatement.step();
    if (result != SQLITE_ROW)
        LOG_ERROR("Could not load cache online whitelist wildcard flag, error \"%s\"", m_database.lastErrorMsg());

    cache->setAllowsAllNetworkRequests(whitelistWildcardStatement.getColumnInt64(0));

    if (whitelistWildcardStatement.step() != SQLITE_DONE)
        LOG_ERROR("Too many rows for online whitelist wildcard flag");

    // Load fallback URLs.
    SQLiteStatement fallbackStatement(m_database, "SELECT namespace, fallbackURL FROM FallbackURLs WHERE cache=?");
    if (fallbackStatement.prepare() != SQLITE_OK)
        return nullptr;
    fallbackStatement.bindInt64(1, storageID);
    
    FallbackURLVector fallbackURLs;
    while ((result = fallbackStatement.step()) == SQLITE_ROW) 
        fallbackURLs.append(std::make_pair(URL({ }, fallbackStatement.getColumnText(0)), URL({ }, fallbackStatement.getColumnText(1))));

    if (result != SQLITE_DONE)
        LOG_ERROR("Could not load fallback URLs, error \"%s\"", m_database.lastErrorMsg());

    cache->setFallbackURLs(fallbackURLs);
    
    cache->setStorageID(storageID);

    return cache;
}    
    
void ApplicationCacheStorage::remove(ApplicationCache* cache)
{
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    if (!cache->storageID())
        return;
    
    openDatabase(false);
    if (!m_database.isOpen())
        return;

    ASSERT(cache->group());
    ASSERT(cache->group()->storageID());

    // All associated data will be deleted by database triggers.
    SQLiteStatement statement(m_database, "DELETE FROM Caches WHERE id=?");
    if (statement.prepare() != SQLITE_OK)
        return;
    
    statement.bindInt64(1, cache->storageID());
    executeStatement(statement);

    cache->clearStorageID();

    if (cache->group()->newestCache() == cache) {
        // Currently, there are no triggers on the cache group, which is why the cache had to be removed separately above.
        SQLiteStatement groupStatement(m_database, "DELETE FROM CacheGroups WHERE id=?");
        if (groupStatement.prepare() != SQLITE_OK)
            return;
        
        groupStatement.bindInt64(1, cache->group()->storageID());
        executeStatement(groupStatement);

        cache->group()->clearStorageID();
    }
    
    checkForDeletedResources();
}    

void ApplicationCacheStorage::empty()
{
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    openDatabase(false);
    
    if (!m_database.isOpen())
        return;
    
    // Clear cache groups, caches, cache resources, and origins.
    executeSQLCommand("DELETE FROM CacheGroups");
    executeSQLCommand("DELETE FROM Caches");
    executeSQLCommand("DELETE FROM Origins");
    
    // Clear the storage IDs for the caches in memory.
    // The caches will still work, but cached resources will not be saved to disk 
    // until a cache update process has been initiated.
    for (auto* group : m_cachesInMemory.values())
        group->clearStorageID();

    checkForDeletedResources();
}
    
void ApplicationCacheStorage::deleteTables()
{
    empty();
    m_database.clearAllTables();
}
    
bool ApplicationCacheStorage::shouldStoreResourceAsFlatFile(ApplicationCacheResource* resource)
{
    auto& type = resource->response().mimeType();
    return startsWithLettersIgnoringASCIICase(type, "audio/") || startsWithLettersIgnoringASCIICase(type, "video/");
}
    
bool ApplicationCacheStorage::writeDataToUniqueFileInDirectory(SharedBuffer& data, const String& directory, String& path, const String& fileExtension)
{
    String fullPath;
    
    do {
        path = FileSystem::encodeForFileName(createCanonicalUUIDString()) + fileExtension;
        // Guard against the above function being called on a platform which does not implement
        // createCanonicalUUIDString().
        ASSERT(!path.isEmpty());
        if (path.isEmpty())
            return false;
        
        fullPath = FileSystem::pathByAppendingComponent(directory, path);
    } while (FileSystem::directoryName(fullPath) != directory || FileSystem::fileExists(fullPath));
    
    FileSystem::PlatformFileHandle handle = FileSystem::openFile(fullPath, FileSystem::FileOpenMode::Write);
    if (!handle)
        return false;
    
    int64_t writtenBytes = FileSystem::writeToFile(handle, data.data(), data.size());
    FileSystem::closeFile(handle);
    
    if (writtenBytes != static_cast<int64_t>(data.size())) {
        FileSystem::deleteFile(fullPath);
        return false;
    }
    
    return true;
}

Optional<Vector<URL>> ApplicationCacheStorage::manifestURLs()
{
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    openDatabase(false);
    if (!m_database.isOpen())
        return WTF::nullopt;

    SQLiteStatement selectURLs(m_database, "SELECT manifestURL FROM CacheGroups");

    if (selectURLs.prepare() != SQLITE_OK)
        return WTF::nullopt;

    Vector<URL> urls;
    while (selectURLs.step() == SQLITE_ROW)
        urls.append(URL({ }, selectURLs.getColumnText(0)));

    return urls;
}

bool ApplicationCacheStorage::deleteCacheGroupRecord(const String& manifestURL)
{
    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
    SQLiteStatement idStatement(m_database, "SELECT id FROM CacheGroups WHERE manifestURL=?");
    if (idStatement.prepare() != SQLITE_OK)
        return false;

    idStatement.bindText(1, manifestURL);

    int result = idStatement.step();
    if (result != SQLITE_ROW)
        return false;

    int64_t groupId = idStatement.getColumnInt64(0);

    SQLiteStatement cacheStatement(m_database, "DELETE FROM Caches WHERE cacheGroup=?");
    if (cacheStatement.prepare() != SQLITE_OK)
        return false;

    SQLiteStatement groupStatement(m_database, "DELETE FROM CacheGroups WHERE id=?");
    if (groupStatement.prepare() != SQLITE_OK)
        return false;

    cacheStatement.bindInt64(1, groupId);
    executeStatement(cacheStatement);
    groupStatement.bindInt64(1, groupId);
    executeStatement(groupStatement);
    return true;
}

bool ApplicationCacheStorage::deleteCacheGroup(const String& manifestURL)
{
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    SQLiteTransaction deleteTransaction(m_database);

    // Check to see if the group is in memory.
    if (auto* group = m_cachesInMemory.get(manifestURL))
        cacheGroupMadeObsolete(*group);
    else {
        // The cache group is not in memory, so remove it from the disk.
        openDatabase(false);
        if (!m_database.isOpen())
            return false;
        if (!deleteCacheGroupRecord(manifestURL)) {
            LOG_ERROR("Could not delete cache group record, error \"%s\"", m_database.lastErrorMsg());
            return false;
        }
    }

    deleteTransaction.commit();

    checkForDeletedResources();

    return true;
}

void ApplicationCacheStorage::vacuumDatabaseFile()
{
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    openDatabase(false);
    if (!m_database.isOpen())
        return;

    m_database.runVacuumCommand();
}

void ApplicationCacheStorage::checkForMaxSizeReached()
{
    if (m_database.lastError() == SQLITE_FULL)
        m_isMaximumSizeReached = true;
}
    
void ApplicationCacheStorage::checkForDeletedResources()
{
    openDatabase(false);
    if (!m_database.isOpen())
        return;

    // Select only the paths in DeletedCacheResources that do not also appear in CacheResourceData:
    SQLiteStatement selectPaths(m_database, "SELECT DeletedCacheResources.path "
        "FROM DeletedCacheResources "
        "LEFT JOIN CacheResourceData "
        "ON DeletedCacheResources.path = CacheResourceData.path "
        "WHERE (SELECT DeletedCacheResources.path == CacheResourceData.path) IS NULL");
    
    if (selectPaths.prepare() != SQLITE_OK)
        return;
    
    if (selectPaths.step() != SQLITE_ROW)
        return;
    
    do {
        String path = selectPaths.getColumnText(0);
        if (path.isEmpty())
            continue;
        
        String flatFileDirectory = FileSystem::pathByAppendingComponent(m_cacheDirectory, m_flatFileSubdirectoryName);
        String fullPath = FileSystem::pathByAppendingComponent(flatFileDirectory, path);
        
        // Don't exit the flatFileDirectory! This should only happen if the "path" entry contains a directory 
        // component, but protect against it regardless.
        if (FileSystem::directoryName(fullPath) != flatFileDirectory)
            continue;
        
        FileSystem::deleteFile(fullPath);
    } while (selectPaths.step() == SQLITE_ROW);
    
    executeSQLCommand("DELETE FROM DeletedCacheResources");
}
    
long long ApplicationCacheStorage::flatFileAreaSize()
{
    openDatabase(false);
    if (!m_database.isOpen())
        return 0;
    
    SQLiteStatement selectPaths(m_database, "SELECT path FROM CacheResourceData WHERE path NOT NULL");

    if (selectPaths.prepare() != SQLITE_OK) {
        LOG_ERROR("Could not load flat file cache resource data, error \"%s\"", m_database.lastErrorMsg());
        return 0;
    }

    long long totalSize = 0;
    String flatFileDirectory = FileSystem::pathByAppendingComponent(m_cacheDirectory, m_flatFileSubdirectoryName);
    while (selectPaths.step() == SQLITE_ROW) {
        String path = selectPaths.getColumnText(0);
        String fullPath = FileSystem::pathByAppendingComponent(flatFileDirectory, path);
        long long pathSize = 0;
        if (!FileSystem::getFileSize(fullPath, pathSize))
            continue;
        totalSize += pathSize;
    }
    
    return totalSize;
}

Vector<Ref<SecurityOrigin>> ApplicationCacheStorage::originsWithCache()
{
    auto urls = manifestURLs();
    if (!urls)
        return { };

    // Multiple manifest URLs might share the same SecurityOrigin, so we might be creating extra, wasted origins here.
    // The current schema doesn't allow for a more efficient way of building this list.
    Vector<Ref<SecurityOrigin>> origins;
    origins.reserveInitialCapacity(urls->size());
    for (auto& url : *urls)
        origins.uncheckedAppend(SecurityOrigin::create(url));
    return origins;
}

void ApplicationCacheStorage::deleteAllEntries()
{
    empty();
    vacuumDatabaseFile();
}

void ApplicationCacheStorage::deleteAllCaches()
{
    auto origins = originsWithCache();
    for (auto& origin : origins)
        deleteCacheForOrigin(origin);

    vacuumDatabaseFile();
}

void ApplicationCacheStorage::deleteCacheForOrigin(const SecurityOrigin& securityOrigin)
{
    auto urls = manifestURLs();
    if (!urls) {
        LOG_ERROR("Failed to retrieve ApplicationCache manifest URLs");
        return;
    }

    URL originURL(URL(), securityOrigin.toString());

    for (const auto& url : *urls) {
        if (!protocolHostAndPortAreEqual(url, originURL))
            continue;

        if (auto* group = findInMemoryCacheGroup(url))
            group->makeObsolete();
        else
            deleteCacheGroup(url);
    }
}

int64_t ApplicationCacheStorage::diskUsageForOrigin(const SecurityOrigin& securityOrigin)
{
    int64_t usage = 0;
    calculateUsageForOrigin(&securityOrigin, usage);
    return usage;
}

ApplicationCacheStorage::ApplicationCacheStorage(const String& cacheDirectory, const String& flatFileSubdirectoryName)
    : m_cacheDirectory(cacheDirectory)
    , m_flatFileSubdirectoryName(flatFileSubdirectoryName)
{
}

} // namespace WebCore
