/*
 * Copyright (C) 2007, 2008 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 Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "Database.h"

#include <wtf/StdLibExtras.h>

#if ENABLE(DATABASE)
#include "ChangeVersionWrapper.h"
#include "CString.h"
#include "DatabaseAuthorizer.h"
#include "DatabaseTask.h"
#include "DatabaseThread.h"
#include "DatabaseTracker.h"
#include "Document.h"
#include "ExceptionCode.h"
#include "Frame.h"
#include "InspectorController.h"
#include "Logging.h"
#include "NotImplemented.h"
#include "Page.h"
#include "OriginQuotaManager.h"
#include "ScriptController.h"
#include "SQLiteDatabase.h"
#include "SQLiteFileSystem.h"
#include "SQLiteStatement.h"
#include "SQLResultSet.h"
#include "SQLTransactionClient.h"
#include "SQLTransactionCoordinator.h"

#endif // ENABLE(DATABASE)

#if USE(JSC)
#include "JSDOMWindow.h"
#endif

namespace WebCore {

// If we sleep for more the 30 seconds while blocked on SQLITE_BUSY, give up.
static const int maxSqliteBusyWaitTime = 30000;

const String& Database::databaseInfoTableName()
{
    DEFINE_STATIC_LOCAL(String, name, ("__WebKitDatabaseInfoTable__"));
    return name;
}

#if ENABLE(DATABASE)

static bool isDatabaseAvailable = true;

void Database::setIsAvailable(bool available)
{
    isDatabaseAvailable = available;
}

bool Database::isAvailable()
{
    return isDatabaseAvailable;
}

static Mutex& guidMutex()
{
    // Note: We don't have to use AtomicallyInitializedStatic here because
    // this function is called once in the constructor on the main thread
    // before any other threads that call this function are used.
    DEFINE_STATIC_LOCAL(Mutex, mutex, ());
    return mutex;
}

typedef HashMap<int, String> GuidVersionMap;
static GuidVersionMap& guidToVersionMap()
{
    DEFINE_STATIC_LOCAL(GuidVersionMap, map, ());
    return map;
}

// NOTE: Caller must lock guidMutex().
static inline void updateGuidVersionMap(int guid, String newVersion)
{
    // Ensure the the mutex is locked.
    ASSERT(!guidMutex().tryLock());

    // Note: It is not safe to put an empty string into the guidToVersionMap() map.
    // That's because the map is cross-thread, but empty strings are per-thread.
    // The copy() function makes a version of the string you can use on the current
    // thread, but we need a string we can keep in a cross-thread data structure.
    // FIXME: This is a quite-awkward restriction to have to program with.

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

typedef HashMap<int, HashSet<Database*>*> GuidDatabaseMap;
static GuidDatabaseMap& guidToDatabaseMap()
{
    DEFINE_STATIC_LOCAL(GuidDatabaseMap, map, ());
    return map;
}

static const String& databaseVersionKey()
{
    DEFINE_STATIC_LOCAL(String, key, ("WebKitDatabaseVersionKey"));
    return key;
}

static int guidForOriginAndName(const String& origin, const String& name);

PassRefPtr<Database> Database::openDatabase(ScriptExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, ExceptionCode& e)
{
    if (!DatabaseTracker::tracker().canEstablishDatabase(context, name, displayName, estimatedSize)) {
        // FIXME: There should be an exception raised here in addition to returning a null Database object.  The question has been raised with the WHATWG.
        LOG(StorageAPI, "Database %s for origin %s not allowed to be established", name.ascii().data(), context->securityOrigin()->toString().ascii().data());
        return 0;
    }

    RefPtr<Database> database = adoptRef(new Database(context, name, expectedVersion, displayName, estimatedSize));

    if (!database->openAndVerifyVersion(e)) {
        LOG(StorageAPI, "Failed to open and verify version (expected %s) of database %s", expectedVersion.ascii().data(), database->databaseDebugName().ascii().data());
        context->removeOpenDatabase(database.get());
        DatabaseTracker::tracker().removeOpenDatabase(database.get());
        return 0;
    }

    DatabaseTracker::tracker().setDatabaseDetails(context->securityOrigin(), name, displayName, estimatedSize);

    context->setHasOpenDatabases();
#if ENABLE(INSPECTOR)
    if (context->isDocument()) {
        Document* document = static_cast<Document*>(context);
        if (Page* page = document->page())
            page->inspectorController()->didOpenDatabase(database.get(), context->securityOrigin()->host(), name, expectedVersion);
    }
#endif

    return database;
}

Database::Database(ScriptExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize)
    : m_transactionInProgress(false)
    , m_isTransactionQueueEnabled(true)
    , m_scriptExecutionContext(context)
    , m_name(name.crossThreadString())
    , m_guid(0)
    , m_expectedVersion(expectedVersion.crossThreadString())
    , m_displayName(displayName.crossThreadString())
    , m_estimatedSize(estimatedSize)
    , m_deleted(false)
    , m_stopped(false)
    , m_opened(false)
{
    ASSERT(m_scriptExecutionContext.get());
    m_mainThreadSecurityOrigin = m_scriptExecutionContext->securityOrigin();
    m_databaseThreadSecurityOrigin = m_mainThreadSecurityOrigin->threadsafeCopy();
    if (m_name.isNull())
        m_name = "";

    ScriptController::initializeThreading();

    m_guid = guidForOriginAndName(securityOrigin()->toString(), name);

    {
        MutexLocker locker(guidMutex());

        HashSet<Database*>* hashSet = guidToDatabaseMap().get(m_guid);
        if (!hashSet) {
            hashSet = new HashSet<Database*>;
            guidToDatabaseMap().set(m_guid, hashSet);
        }

        hashSet->add(this);
    }

    ASSERT(m_scriptExecutionContext->databaseThread());
    m_filename = DatabaseTracker::tracker().fullPathForDatabase(securityOrigin(), m_name);

    DatabaseTracker::tracker().addOpenDatabase(this);
    context->addOpenDatabase(this);
}

class DerefContextTask : public ScriptExecutionContext::Task {
public:
    static PassOwnPtr<DerefContextTask> create()
    {
        return new DerefContextTask();
    }

    virtual void performTask(ScriptExecutionContext* context)
    {
        context->deref();
    }

    virtual bool isCleanupTask() const { return true; }
};

Database::~Database()
{
    // The reference to the ScriptExecutionContext needs to be cleared on the JavaScript thread.  If we're on that thread already, we can just let the RefPtr's destruction do the dereffing.
    if (!m_scriptExecutionContext->isContextThread()) {
        m_scriptExecutionContext->postTask(DerefContextTask::create());
        m_scriptExecutionContext.release().releaseRef();
    }
}

bool Database::openAndVerifyVersion(ExceptionCode& e)
{
    if (!m_scriptExecutionContext->databaseThread())
        return false;
    m_databaseAuthorizer = DatabaseAuthorizer::create();

    bool success = false;
    DatabaseTaskSynchronizer synchronizer;
    OwnPtr<DatabaseOpenTask> task = DatabaseOpenTask::create(this, &synchronizer, e, success);

    m_scriptExecutionContext->databaseThread()->scheduleImmediateTask(task.release());
    synchronizer.waitForTaskCompletion();

    return success;
}


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

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

    result = statement.step();
    if (result == SQLResultRow) {
        resultString = statement.getColumnText(0);
        return true;
    } else if (result == SQLResultDone) {
        resultString = String();
        return true;
    } else {
        LOG_ERROR("Error (%i) reading text result from database (%s)", result, query.ascii().data());
        return false;
    }
}

bool Database::getVersionFromDatabase(String& version)
{
    DEFINE_STATIC_LOCAL(String, getVersionQuery, ("SELECT value FROM " + databaseInfoTableName() + " WHERE key = '" + databaseVersionKey() + "';"));

    m_databaseAuthorizer->disable();

    bool result = retrieveTextResultFromDatabase(m_sqliteDatabase, getVersionQuery.threadsafeCopy(), version);
    if (!result)
        LOG_ERROR("Failed to retrieve version from database %s", databaseDebugName().ascii().data());

    m_databaseAuthorizer->enable();

    return result;
}

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

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

    statement.bindText(1, value);

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

    return true;
}

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

    m_databaseAuthorizer->disable();

    bool result = setTextValueInDatabase(m_sqliteDatabase, setVersionQuery.threadsafeCopy(), version);
    if (!result)
        LOG_ERROR("Failed to set version %s in database (%s)", version.ascii().data(), setVersionQuery.ascii().data());

    m_databaseAuthorizer->enable();

    return result;
}

bool Database::versionMatchesExpected() const
{
    if (!m_expectedVersion.isEmpty()) {
        MutexLocker locker(guidMutex());
        return m_expectedVersion == guidToVersionMap().get(m_guid);
    }

    return true;
}

void Database::markAsDeletedAndClose()
{
    if (m_deleted || !m_scriptExecutionContext->databaseThread())
        return;

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

    if (m_scriptExecutionContext->databaseThread()->terminationRequested()) {
        LOG(StorageAPI, "Database handle %p is on a terminated DatabaseThread, cannot be marked for normal closure\n", this);
        return;
    }

    m_scriptExecutionContext->databaseThread()->unscheduleDatabaseTasks(this);

    DatabaseTaskSynchronizer synchronizer;
    OwnPtr<DatabaseCloseTask> task = DatabaseCloseTask::create(this, &synchronizer);

    m_scriptExecutionContext->databaseThread()->scheduleImmediateTask(task.release());
    synchronizer.waitForTaskCompletion();
}

class ContextRemoveOpenDatabaseTask : public ScriptExecutionContext::Task {
public:
    static PassOwnPtr<ContextRemoveOpenDatabaseTask> create(PassRefPtr<Database> database)
    {
        return new ContextRemoveOpenDatabaseTask(database);
    }

    virtual void performTask(ScriptExecutionContext* context)
    {
        context->removeOpenDatabase(m_database.get());
        DatabaseTracker::tracker().removeOpenDatabase(m_database.get());
    }

    virtual bool isCleanupTask() const { return true; }

private:
    ContextRemoveOpenDatabaseTask(PassRefPtr<Database> database)
        : m_database(database)
    {
    }

    RefPtr<Database> m_database;
};

void Database::close()
{
    RefPtr<Database> protect = this;

    if (!m_opened)
        return;

    ASSERT(m_scriptExecutionContext->databaseThread());
    ASSERT(currentThread() == m_scriptExecutionContext->databaseThread()->getThreadID());
    m_sqliteDatabase.close();
    // Must ref() before calling databaseThread()->recordDatabaseClosed().
    m_scriptExecutionContext->databaseThread()->recordDatabaseClosed(this);
    m_opened = false;

    {
        MutexLocker locker(guidMutex());

        HashSet<Database*>* hashSet = guidToDatabaseMap().get(m_guid);
        ASSERT(hashSet);
        ASSERT(hashSet->contains(this));
        hashSet->remove(this);
        if (hashSet->isEmpty()) {
            guidToDatabaseMap().remove(m_guid);
            delete hashSet;
            guidToVersionMap().remove(m_guid);
        }
    }

    m_scriptExecutionContext->databaseThread()->unscheduleDatabaseTasks(this);
    m_scriptExecutionContext->postTask(ContextRemoveOpenDatabaseTask::create(this));
}

void Database::stop()
{
    // FIXME: The net effect of the following code is to remove all pending transactions and statements, but allow the current statement
    // to run to completion.  In the future we can use the sqlite3_progress_handler or sqlite3_interrupt interfaces to cancel the current
    // statement in response to close(), as well.

    // This method is meant to be used as an analog to cancelling a loader, and is used when a document is shut down as the result of
    // a page load or closing the page
    m_stopped = true;

    {
        MutexLocker locker(m_transactionInProgressMutex);
        m_isTransactionQueueEnabled = false;
        m_transactionInProgress = false;
    }
}

unsigned long long Database::maximumSize() const
{
    return DatabaseTracker::tracker().getMaxSizeForDatabase(this);
}

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

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

void Database::setAuthorizerReadOnly()
{
    ASSERT(m_databaseAuthorizer);
    m_databaseAuthorizer->setReadOnly();
}

static int guidForOriginAndName(const String& origin, const String& name)
{
    String stringID;
    if (origin.endsWith("/"))
        stringID = origin + name;
    else
        stringID = origin + "/" + name;

    // Note: We don't have to use AtomicallyInitializedStatic here because
    // this function is called once in the constructor on the main thread
    // before any other threads that call this function are used.
    DEFINE_STATIC_LOCAL(Mutex, stringIdentifierMutex, ());
    MutexLocker locker(stringIdentifierMutex);
    typedef HashMap<String, int> IDGuidMap;
    DEFINE_STATIC_LOCAL(IDGuidMap, stringIdentifierToGUIDMap, ());
    int guid = stringIdentifierToGUIDMap.get(stringID);
    if (!guid) {
        static int currentNewGUID = 1;
        guid = currentNewGUID++;
        stringIdentifierToGUIDMap.set(stringID, guid);
    }

    return guid;
}

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

void Database::performPolicyChecks()
{
    // FIXME: Code similar to the following will need to be run to enforce the per-origin size limit the spec mandates.
    // Additionally, we might need a way to pause the database thread while the UA prompts the user for permission to
    // increase the size limit

    /*
    if (m_databaseAuthorizer->lastActionIncreasedSize())
        DatabaseTracker::scheduleFileSizeCheckOnMainThread(this);
    */

    notImplemented();
}

bool Database::performOpenAndVerify(ExceptionCode& e)
{
    if (!m_sqliteDatabase.open(m_filename)) {
        LOG_ERROR("Unable to open database at path %s", m_filename.ascii().data());
        e = INVALID_STATE_ERR;
        return false;
    }

    ASSERT(m_databaseAuthorizer);
    m_sqliteDatabase.setAuthorizer(m_databaseAuthorizer);
    m_sqliteDatabase.setBusyTimeout(maxSqliteBusyWaitTime);

    String currentVersion;
    {
        MutexLocker locker(guidMutex());

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

            if (!m_sqliteDatabase.tableExists(databaseInfoTableName())) {
                if (!m_sqliteDatabase.executeCommand("CREATE TABLE " + databaseInfoTableName() + " (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,value TEXT NOT NULL ON CONFLICT FAIL);")) {
                    LOG_ERROR("Unable to create table %s in database %s", databaseInfoTableName().ascii().data(), databaseDebugName().ascii().data());
                    e = INVALID_STATE_ERR;
                    // Close the handle to the database file.
                    m_sqliteDatabase.close();
                    return false;
                }
            }

            if (!getVersionFromDatabase(currentVersion)) {
                LOG_ERROR("Failed to get current version from database %s", databaseDebugName().ascii().data());
                e = INVALID_STATE_ERR;
                // Close the handle to the database file.
                m_sqliteDatabase.close();
                return false;
            }
            if (currentVersion.length()) {
                LOG(StorageAPI, "Retrieved current version %s from database %s", currentVersion.ascii().data(), databaseDebugName().ascii().data());
            } else {
                LOG(StorageAPI, "Setting version %s in database %s that was just created", m_expectedVersion.ascii().data(), databaseDebugName().ascii().data());
                if (!setVersionInDatabase(m_expectedVersion)) {
                    LOG_ERROR("Failed to set version %s in database %s", m_expectedVersion.ascii().data(), databaseDebugName().ascii().data());
                    e = INVALID_STATE_ERR;
                    // Close the handle to the database file.
                    m_sqliteDatabase.close();
                    return false;
                }
                currentVersion = m_expectedVersion;
            }

            updateGuidVersionMap(m_guid, currentVersion);
        }
    }

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

    // If the expected version isn't the empty string, ensure that the current database version we have matches that version. Otherwise, set an exception.
    // If the expected version is the empty string, then we always return with whatever version of the database we have.
    if (m_expectedVersion.length() && m_expectedVersion != currentVersion) {
        LOG(StorageAPI, "page expects version %s from database %s, which actually has version name %s - openDatabase() call will fail", m_expectedVersion.ascii().data(),
            databaseDebugName().ascii().data(), currentVersion.ascii().data());
        e = INVALID_STATE_ERR;
        // Close the handle to the database file.
        m_sqliteDatabase.close();
        return false;
    }

    // All checks passed and we still have a handle to this database file.
    // Make sure DatabaseThread closes it when DatabaseThread goes away.
    m_opened = true;
    if (m_scriptExecutionContext->databaseThread())
        m_scriptExecutionContext->databaseThread()->recordDatabaseOpen(this);

    return true;
}

void Database::changeVersion(const String& oldVersion, const String& newVersion,
                             PassRefPtr<SQLTransactionCallback> callback, PassRefPtr<SQLTransactionErrorCallback> errorCallback,
                             PassRefPtr<VoidCallback> successCallback)
{
    m_transactionQueue.append(SQLTransaction::create(this, callback, errorCallback, successCallback, ChangeVersionWrapper::create(oldVersion, newVersion)));
    MutexLocker locker(m_transactionInProgressMutex);
    if (!m_transactionInProgress)
        scheduleTransaction();
}

void Database::transaction(PassRefPtr<SQLTransactionCallback> callback, PassRefPtr<SQLTransactionErrorCallback> errorCallback,
                           PassRefPtr<VoidCallback> successCallback, bool readOnly)
{
    m_transactionQueue.append(SQLTransaction::create(this, callback, errorCallback, successCallback, 0, readOnly));
    MutexLocker locker(m_transactionInProgressMutex);
    if (!m_transactionInProgress)
        scheduleTransaction();
}

void Database::scheduleTransaction()
{
    ASSERT(!m_transactionInProgressMutex.tryLock()); // Locked by caller.
    RefPtr<SQLTransaction> transaction;

    if (m_isTransactionQueueEnabled && !m_transactionQueue.isEmpty()) {
        transaction = m_transactionQueue.first();
        m_transactionQueue.removeFirst();
    }

    if (transaction && m_scriptExecutionContext->databaseThread()) {
        OwnPtr<DatabaseTransactionTask> task = DatabaseTransactionTask::create(transaction);
        LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for transaction %p\n", task.get(), task->transaction());
        m_transactionInProgress = true;
        m_scriptExecutionContext->databaseThread()->scheduleTask(task.release());
    } else
        m_transactionInProgress = false;
}

void Database::scheduleTransactionStep(SQLTransaction* transaction, bool immediately)
{
    if (!m_scriptExecutionContext->databaseThread())
        return;

    OwnPtr<DatabaseTransactionTask> task = DatabaseTransactionTask::create(transaction);
    LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for the transaction step\n", task.get());
    if (immediately)
        m_scriptExecutionContext->databaseThread()->scheduleImmediateTask(task.release());
    else
        m_scriptExecutionContext->databaseThread()->scheduleTask(task.release());
}

class DeliverPendingCallbackTask : public ScriptExecutionContext::Task {
public:
    static PassOwnPtr<DeliverPendingCallbackTask> create(PassRefPtr<SQLTransaction> transaction)
    {
        return new DeliverPendingCallbackTask(transaction);
    }

    virtual void performTask(ScriptExecutionContext*)
    {
        m_transaction->performPendingCallback();
    }

private:
    DeliverPendingCallbackTask(PassRefPtr<SQLTransaction> transaction)
        : m_transaction(transaction)
    {
    }

    RefPtr<SQLTransaction> m_transaction;
};

void Database::scheduleTransactionCallback(SQLTransaction* transaction)
{
    m_scriptExecutionContext->postTask(DeliverPendingCallbackTask::create(transaction));
}

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

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

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

    enableAuthorizer();

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

    return tableNames;
}

SQLTransactionClient* Database::transactionClient() const
{
    return m_scriptExecutionContext->databaseThread()->transactionClient();
}

SQLTransactionCoordinator* Database::transactionCoordinator() const
{
    return m_scriptExecutionContext->databaseThread()->transactionCoordinator();
}

String Database::version() const
{
    if (m_deleted)
        return String();
    MutexLocker locker(guidMutex());
    return guidToVersionMap().get(m_guid).threadsafeCopy();
}

Vector<String> Database::tableNames()
{
    // FIXME: Not using threadsafeCopy on these strings looks ok since threads take strict turns
    // in dealing with them. However, if the code changes, this may not be true anymore.
    Vector<String> result;
    if (!m_scriptExecutionContext->databaseThread())
        return result;

    DatabaseTaskSynchronizer synchronizer;
    OwnPtr<DatabaseTableNamesTask> task = DatabaseTableNamesTask::create(this, &synchronizer, result);

    m_scriptExecutionContext->databaseThread()->scheduleImmediateTask(task.release());
    synchronizer.waitForTaskCompletion();

    return result;
}

void Database::setExpectedVersion(const String& version)
{
    m_expectedVersion = version.threadsafeCopy();
    // Update the in memory database version map.
    MutexLocker locker(guidMutex());
    updateGuidVersionMap(m_guid, version);
}

SecurityOrigin* Database::securityOrigin() const
{
    if (scriptExecutionContext()->isContextThread())
        return m_mainThreadSecurityOrigin.get();
    if (currentThread() == m_scriptExecutionContext->databaseThread()->getThreadID())
        return m_databaseThreadSecurityOrigin.get();
    return 0;
}

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

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

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

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

#endif // ENABLE(DATABASE)

} // namespace WebCore
