void CookieDatabaseBackingStore::sendChangesToDatabaseTimerFired()
{
    dispatchMessage(createMethodCallMessage(&CookieDatabaseBackingStore::invokeSendChangesToDatabase, this));
}
void CookieDatabaseBackingStore::open(const String& cookieJar)
{
    dispatchMessage(createMethodCallMessage(&CookieDatabaseBackingStore::invokeOpen, this, cookieJar));
}
void CookieDatabaseBackingStore::removeAll()
{
    dispatchMessage(createMethodCallMessage(&CookieDatabaseBackingStore::invokeRemoveAll, this));
}
void CookieDatabaseBackingStore::invokeOpen(const String& cookieJar)
{
    ASSERT(isCurrentThread());
    if (m_db.isOpen())
        close();

    if (!m_db.open(cookieJar)) {
        LOG_ERROR("Could not open the cookie database. No cookie will be stored!");
        LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg());
        return;
    }

    m_db.executeCommand("PRAGMA locking_mode=EXCLUSIVE;");
    m_db.executeCommand("PRAGMA journal_mode=WAL;");

    const String primaryKeyFields("PRIMARY KEY (protocol, host, path, name)");
    const String databaseFields("name TEXT, value TEXT, host TEXT, path TEXT, expiry DOUBLE, lastAccessed DOUBLE, isSecure INTEGER, isHttpOnly INTEGER, creationTime DOUBLE, protocol TEXT");

    StringBuilder createTableQuery;
    createTableQuery.append("CREATE TABLE IF NOT EXISTS ");
    createTableQuery.append(m_tableName);
    // This table schema is compliant with Mozilla's.
    createTableQuery.append(" (" + databaseFields + ", " + primaryKeyFields+");");

    m_db.setBusyTimeout(1000);

    if (!m_db.executeCommand(createTableQuery.toString())) {
        LOG_ERROR("Could not create the table to store the cookies into. No cookie will be stored!");
        LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg());
        close();
        return;
    }

    StringBuilder insertQuery;
    insertQuery.append("INSERT OR REPLACE INTO ");
    insertQuery.append(m_tableName);
    insertQuery.append(" (name, value, host, path, expiry, lastAccessed, isSecure, isHttpOnly, creationTime, protocol) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10);");

    m_insertStatement = new SQLiteStatement(m_db, insertQuery.toString());
    if (m_insertStatement->prepare()) {
        LOG_ERROR("Cannot save cookies");
        LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg());
    }

    StringBuilder updateQuery;
    updateQuery.append("UPDATE ");
    updateQuery.append(m_tableName);
    // The where statement is chosen to match CookieMap key.
    updateQuery.append(" SET name = ?1, value = ?2, host = ?3, path = ?4, expiry = ?5, lastAccessed = ?6, isSecure = ?7, isHttpOnly = ?8, creationTime = ?9, protocol = ?10 where name = ?1 and host = ?3 and path = ?4;");
    m_updateStatement = new SQLiteStatement(m_db, updateQuery.toString());

    if (m_updateStatement->prepare()) {
        LOG_ERROR("Cannot update cookies");
        LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg());
    }

    StringBuilder deleteQuery;
    deleteQuery.append("DELETE FROM ");
    deleteQuery.append(m_tableName);
    // The where statement is chosen to match CookieMap key.
    deleteQuery.append(" WHERE name=?1 and host=?2 and path=?3 and protocol=?4;");
    m_deleteStatement = new SQLiteStatement(m_db, deleteQuery.toString());

    if (m_deleteStatement->prepare()) {
        LOG_ERROR("Cannot delete cookies");
        LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg());
    }

    BlackBerry::Platform::webKitThreadMessageClient()->dispatchMessage(createMethodCallMessage(&CookieManager::getBackingStoreCookies, &cookieManager()));
}