/*
 * Copyright (C) 2012 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 "DatabaseManager.h"

#include "Database.h"
#include "DatabaseCallback.h"
#include "DatabaseContext.h"
#include "DatabaseTask.h"
#include "DatabaseTracker.h"
#include "Document.h"
#include "InspectorInstrumentation.h"
#include "Logging.h"
#include "PlatformStrategies.h"
#include "ScriptController.h"
#include "SecurityOrigin.h"
#include "SecurityOriginData.h"
#include <wtf/NeverDestroyed.h>

namespace WebCore {

class DatabaseManager::ProposedDatabase {
public:
    ProposedDatabase(DatabaseManager&, SecurityOrigin&, const String& name, const String& displayName, unsigned long estimatedSize);
    ~ProposedDatabase();

    SecurityOrigin& origin() { return m_origin; }
    DatabaseDetails& details() { return m_details; }

private:
    DatabaseManager& m_manager;
    Ref<SecurityOrigin> m_origin;
    DatabaseDetails m_details;
};

DatabaseManager::ProposedDatabase::ProposedDatabase(DatabaseManager& manager, SecurityOrigin& origin, const String& name, const String& displayName, unsigned long estimatedSize)
    : m_manager(manager)
    , m_origin(origin.isolatedCopy())
    , m_details(name.isolatedCopy(), displayName.isolatedCopy(), estimatedSize, 0, WTF::nullopt, WTF::nullopt)
{
    m_manager.addProposedDatabase(*this);
}

inline DatabaseManager::ProposedDatabase::~ProposedDatabase()
{
    m_manager.removeProposedDatabase(*this);
}

DatabaseManager& DatabaseManager::singleton()
{
    static NeverDestroyed<DatabaseManager> instance;
    return instance;
}

void DatabaseManager::initialize(const String& databasePath)
{
    platformInitialize(databasePath);
    DatabaseTracker::initializeTracker(databasePath);
}

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

bool DatabaseManager::isAvailable()
{
    return m_databaseIsAvailable;
}

void DatabaseManager::setIsAvailable(bool available)
{
    m_databaseIsAvailable = available;
}

Ref<DatabaseContext> DatabaseManager::databaseContext(Document& document)
{
    if (auto databaseContext = document.databaseContext())
        return *databaseContext;
    return adoptRef(*new DatabaseContext(document));
}

#if LOG_DISABLED

static inline void logOpenDatabaseError(Document&, const String&)
{
}

#else

static void logOpenDatabaseError(Document& document, const String& name)
{
    LOG(StorageAPI, "Database %s for origin %s not allowed to be established", name.utf8().data(), document.securityOrigin().toString().utf8().data());
}

#endif

ExceptionOr<Ref<Database>> DatabaseManager::openDatabaseBackend(Document& document, const String& name, const String& expectedVersion, const String& displayName, unsigned estimatedSize, bool setVersionInNewDatabase)
{
    auto backend = tryToOpenDatabaseBackend(document, name, expectedVersion, displayName, estimatedSize, setVersionInNewDatabase, FirstTryToOpenDatabase);

    if (backend.hasException()) {
        if (backend.exception().code() == QuotaExceededError) {
            // Notify the client that we've exceeded the database quota.
            // The client may want to increase the quota, and we'll give it
            // one more try after if that is the case.
            {
                ProposedDatabase proposedDatabase { *this, document.securityOrigin(), name, displayName, estimatedSize };
                this->databaseContext(document)->databaseExceededQuota(name, proposedDatabase.details());
            }
            backend = tryToOpenDatabaseBackend(document, name, expectedVersion, displayName, estimatedSize, setVersionInNewDatabase, RetryOpenDatabase);
        }
    }

    if (backend.hasException()) {
        if (backend.exception().code() == InvalidStateError)
            logErrorMessage(document, backend.exception().message());
        else
            logOpenDatabaseError(document, name);
    }

    return backend;
}

ExceptionOr<Ref<Database>> DatabaseManager::tryToOpenDatabaseBackend(Document& document, const String& name, const String& expectedVersion, const String& displayName, unsigned estimatedSize, bool setVersionInNewDatabase,
    OpenAttempt attempt)
{
    auto* page = document.page();
    if (!page || page->usesEphemeralSession())
        return Exception { SecurityError };

    auto backendContext = this->databaseContext(document);

    ExceptionOr<void> preflightResult;
    switch (attempt) {
    case FirstTryToOpenDatabase:
        preflightResult = DatabaseTracker::singleton().canEstablishDatabase(backendContext, name, estimatedSize);
        break;
    case RetryOpenDatabase:
        preflightResult = DatabaseTracker::singleton().retryCanEstablishDatabase(backendContext, name, estimatedSize);
        break;
    }
    if (preflightResult.hasException())
        return preflightResult.releaseException();

    auto database = adoptRef(*new Database(backendContext, name, expectedVersion, displayName, estimatedSize));

    auto openResult = database->openAndVerifyVersion(setVersionInNewDatabase);
    if (openResult.hasException())
        return openResult.releaseException();

    // FIXME: What guarantees backendContext.securityOrigin() is non-null?
    DatabaseTracker::singleton().setDatabaseDetails(backendContext->securityOrigin(), name, displayName, estimatedSize);
    return database;
}

void DatabaseManager::addProposedDatabase(ProposedDatabase& database)
{
    std::lock_guard<Lock> lock { m_proposedDatabasesMutex };
    m_proposedDatabases.add(&database);
}

void DatabaseManager::removeProposedDatabase(ProposedDatabase& database)
{
    std::lock_guard<Lock> lock { m_proposedDatabasesMutex };
    m_proposedDatabases.remove(&database);
}

ExceptionOr<Ref<Database>> DatabaseManager::openDatabase(Document& document, const String& name, const String& expectedVersion, const String& displayName, unsigned estimatedSize, RefPtr<DatabaseCallback>&& creationCallback)
{
    ScriptController::initializeThreading();

    bool setVersionInNewDatabase = !creationCallback;
    auto openResult = openDatabaseBackend(document, name, expectedVersion, displayName, estimatedSize, setVersionInNewDatabase);
    if (openResult.hasException())
        return openResult.releaseException();

    RefPtr<Database> database = openResult.releaseReturnValue();

    auto databaseContext = this->databaseContext(document);
    databaseContext->setHasOpenDatabases();
    InspectorInstrumentation::didOpenDatabase(*database);

    if (database->isNew() && creationCallback.get()) {
        LOG(StorageAPI, "Scheduling DatabaseCreationCallbackTask for database %p\n", database.get());
        database->setHasPendingCreationEvent(true);
        database->m_document->postTask([creationCallback, database] (ScriptExecutionContext&) {
            creationCallback->handleEvent(*database);
            database->setHasPendingCreationEvent(false);
        });
    }

    return database.releaseNonNull();
}

bool DatabaseManager::hasOpenDatabases(Document& document)
{
    auto databaseContext = document.databaseContext();
    return databaseContext && databaseContext->hasOpenDatabases();
}

void DatabaseManager::stopDatabases(Document& document, DatabaseTaskSynchronizer* synchronizer)
{
    auto databaseContext = document.databaseContext();
    if (!databaseContext || !databaseContext->stopDatabases(synchronizer)) {
        if (synchronizer)
            synchronizer->taskCompleted();
    }
}

String DatabaseManager::fullPathForDatabase(SecurityOrigin& origin, const String& name, bool createIfDoesNotExist)
{
    {
        std::lock_guard<Lock> lock { m_proposedDatabasesMutex };
        for (auto* proposedDatabase : m_proposedDatabases) {
            if (proposedDatabase->details().name() == name && proposedDatabase->origin().equal(&origin))
                return String();
        }
    }
    return DatabaseTracker::singleton().fullPathForDatabase(origin.data(), name, createIfDoesNotExist);
}

DatabaseDetails DatabaseManager::detailsForNameAndOrigin(const String& name, SecurityOrigin& origin)
{
    {
        std::lock_guard<Lock> lock { m_proposedDatabasesMutex };
        for (auto* proposedDatabase : m_proposedDatabases) {
            if (proposedDatabase->details().name() == name && proposedDatabase->origin().equal(&origin)) {
                ASSERT(&proposedDatabase->details().thread() == &Thread::current() || isMainThread());
                return proposedDatabase->details();
            }
        }
    }

    return DatabaseTracker::singleton().detailsForNameAndOrigin(name, origin.data());
}

void DatabaseManager::logErrorMessage(Document& document, const String& message)
{
    document.addConsoleMessage(MessageSource::Storage, MessageLevel::Error, message);
}

#if !PLATFORM(COCOA)
void DatabaseManager::platformInitialize(const String& databasePath)
{
    UNUSED_PARAM(databasePath);
}
#endif

} // namespace WebCore
