15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011 Google Inc. All rights reserved.
3926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Copyright (C) 2013 Apple Inc. All rights reserved.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1.  Redistributions of source code must retain the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     notice, this list of conditions and the following disclaimer.
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2.  Redistributions in binary form must reproduce the above copyright
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     notice, this list of conditions and the following disclaimer in the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     documentation and/or other materials provided with the distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     its contributors may be used to endorse or promote products derived
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     from this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/DatabaseBackendBase.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/ExceptionCode.h"
341e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/Logging.h"
3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/DatabaseAuthorizer.h"
3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/DatabaseBase.h"
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/DatabaseContext.h"
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/DatabaseManager.h"
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/DatabaseTracker.h"
4051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "modules/webdatabase/sqlite/SQLiteStatement.h"
4151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "modules/webdatabase/sqlite/SQLiteTransaction.h"
4251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/weborigin/DatabaseIdentifier.h"
4351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "public/platform/Platform.h"
4451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "public/platform/WebDatabaseObserver.h"
4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/HashMap.h"
4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/HashSet.h"
4753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/PassRefPtr.h"
4853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/StdLibExtras.h"
4953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/text/CString.h"
5053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/text/StringHash.h"
5153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
52926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// Registering "opened" databases with the DatabaseTracker
53926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// =======================================================
54926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// The DatabaseTracker maintains a list of databases that have been
55926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// "opened" so that the client can call interrupt or delete on every database
56bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)// associated with a DatabaseContext.
57926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//
58926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// We will only call DatabaseTracker::addOpenDatabase() to add the database
59926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// to the tracker as opened when we've succeeded in opening the database,
60926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// and will set m_opened to true. Similarly, we only call
61926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// DatabaseTracker::removeOpenDatabase() to remove the database from the
62926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// tracker when we set m_opened to false in closeDatabase(). This sets up
63926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// a simple symmetry between open and close operations, and a direct
64926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// correlation to adding and removing databases from the tracker's list,
65926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// thus ensuring that we have a correct list for the interrupt and
66926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// delete operations to work on.
67926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//
68926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// The only databases instances not tracked by the tracker's open database
69926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// list are the ones that have not been added yet, or the ones that we
70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// attempted an open on but failed to. Such instances only exist in the
71926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// DatabaseServer's factory methods for creating database backends.
72926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//
73926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// The factory methods will either call openAndVerifyVersion() or
74926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// performOpenAndVerify(). These methods will add the newly instantiated
75926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// database backend if they succeed in opening the requested database.
76926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// In the case of failure to open the database, the factory methods will
77926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// simply discard the newly instantiated database backend when they return.
78926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// The ref counting mechanims will automatically destruct the un-added
79926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// (and un-returned) databases instances.
80926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const char versionKey[] = "WebKitDatabaseVersionKey";
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const char infoTableName[] = "__WebKitDatabaseInfoTable__";
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static String formatErrorMessage(const char* message, int sqliteErrorCode, const char* sqliteErrorMessage)
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return String::format("%s (%d %s)", message, sqliteErrorCode, sqliteErrorMessage);
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool retrieveTextResultFromDatabase(SQLiteDatabase& db, const String& query, String& resultString)
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SQLiteStatement statement(db, query);
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int result = statement.prepare();
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (result != SQLResultOk) {
97a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        WTF_LOG_ERROR("Error (%i) preparing statement to read text result from database (%s)", result, query.ascii().data());
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result = statement.step();
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (result == SQLResultRow) {
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        resultString = statement.getColumnText(0);
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (result == SQLResultDone) {
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        resultString = String();
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
111a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    WTF_LOG_ERROR("Error (%i) reading text result from database (%s)", result, query.ascii().data());
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool setTextValueInDatabase(SQLiteDatabase& db, const String& query, const String& value)
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SQLiteStatement statement(db, query);
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int result = statement.prepare();
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (result != SQLResultOk) {
121a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        WTF_LOG_ERROR("Failed to prepare statement to set value in database (%s)", query.ascii().data());
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    statement.bindText(1, value);
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result = statement.step();
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (result != SQLResultDone) {
129a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        WTF_LOG_ERROR("Failed to step statement to set value in database (%s)", query.ascii().data());
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FIXME: move all guid-related functions to a DatabaseVersionTracker class.
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static Mutex& guidMutex()
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return mutex;
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)typedef HashMap<DatabaseGuid, String> GuidVersionMap;
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static GuidVersionMap& guidToVersionMap()
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Ensure the the mutex is locked.
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!guidMutex().tryLock());
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(GuidVersionMap, map, ());
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return map;
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// NOTE: Caller must lock guidMutex().
153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static inline void updateGuidVersionMap(DatabaseGuid guid, String newVersion)
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Ensure the the mutex is locked.
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!guidMutex().tryLock());
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Note: It is not safe to put an empty string into the guidToVersionMap() map.
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // That's because the map is cross-thread, but empty strings are per-thread.
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The copy() function makes a version of the string you can use on the current
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // thread, but we need a string we can keep in a cross-thread data structure.
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: This is a quite-awkward restriction to have to program with.
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Map null string to empty string (see comment above).
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    guidToVersionMap().set(guid, newVersion.isEmpty() ? String() : newVersion.isolatedCopy());
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)typedef HashMap<DatabaseGuid, HashSet<DatabaseBackendBase*>*> GuidDatabaseMap;
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static GuidDatabaseMap& guidToDatabaseMap()
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Ensure the the mutex is locked.
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!guidMutex().tryLock());
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(GuidDatabaseMap, map, ());
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return map;
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static DatabaseGuid guidForOriginAndName(const String& origin, const String& name)
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Ensure the the mutex is locked.
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!guidMutex().tryLock());
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String stringID = origin + "/" + name;
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    typedef HashMap<String, int> IDGuidMap;
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(IDGuidMap, stringIdentifierToGUIDMap, ());
186926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    DatabaseGuid guid = stringIdentifierToGUIDMap.get(stringID);
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!guid) {
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        static int currentNewGUID = 1;
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        guid = currentNewGUID++;
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        stringIdentifierToGUIDMap.set(stringID, guid);
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return guid;
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// static
197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)const char* DatabaseBackendBase::databaseInfoTableName()
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return infoTableName;
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
202bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)DatabaseBackendBase::DatabaseBackendBase(PassRefPtr<DatabaseContext> databaseContext, const String& name,
203926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    const String& expectedVersion, const String& displayName, unsigned long estimatedSize, DatabaseType databaseType)
204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    : m_databaseContext(databaseContext)
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_name(name.isolatedCopy())
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_expectedVersion(expectedVersion.isolatedCopy())
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_displayName(displayName.isolatedCopy())
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_estimatedSize(estimatedSize)
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_guid(0)
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_opened(false)
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_new(false)
212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_isSyncDatabase(databaseType == DatabaseType::Sync)
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_contextThreadSecurityOrigin = m_databaseContext->securityOrigin()->isolatedCopy();
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_databaseAuthorizer = DatabaseAuthorizer::create(infoTableName);
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_name.isNull())
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_name = "";
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        MutexLocker locker(guidMutex());
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_guid = guidForOriginAndName(securityOrigin()->toString(), name);
224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        HashSet<DatabaseBackendBase*>* hashSet = guidToDatabaseMap().get(m_guid);
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!hashSet) {
226926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            hashSet = new HashSet<DatabaseBackendBase*>;
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            guidToDatabaseMap().set(m_guid, hashSet);
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        hashSet->add(this);
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_filename = DatabaseManager::manager().fullPathForDatabase(securityOrigin(), m_name);
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
236926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DatabaseBackendBase::~DatabaseBackendBase()
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
238926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // SQLite is "multi-thread safe", but each database handle can only be used
239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // on a single thread at a time.
240926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    //
241926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // For DatabaseBackend, we open the SQLite database on the DatabaseThread,
242926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // and hence we should also close it on that same thread. This means that the
243926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // SQLite database need to be closed by another mechanism (see
244926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // DatabaseContext::stopDatabases()). By the time we get here, the SQLite
245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // database should have already been closed.
246926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!m_opened);
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
250926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::closeDatabase()
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_opened)
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_sqliteDatabase.close();
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_opened = false;
257926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // See comment at the top this file regarding calling removeOpenDatabase().
258926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    DatabaseTracker::tracker().removeOpenDatabase(this);
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        MutexLocker locker(guidMutex());
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
262926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        HashSet<DatabaseBackendBase*>* hashSet = guidToDatabaseMap().get(m_guid);
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(hashSet);
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(hashSet->contains(this));
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        hashSet->remove(this);
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (hashSet->isEmpty()) {
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            guidToDatabaseMap().remove(m_guid);
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            delete hashSet;
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            guidToVersionMap().remove(m_guid);
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
274926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)String DatabaseBackendBase::version() const
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Note: In multi-process browsers the cached value may be accurate, but we cannot read the
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // actual version from the database without potentially inducing a deadlock.
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: Add an async version getter to the DatabaseAPI.
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return getCachedVersion();
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
282926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)class DoneCreatingDatabaseOnExitCaller {
283926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)public:
284926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    DoneCreatingDatabaseOnExitCaller(DatabaseBackendBase* database)
285926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        : m_database(database)
286926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        , m_openSucceeded(false)
287926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
288926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
289926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ~DoneCreatingDatabaseOnExitCaller()
290926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
291926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!m_openSucceeded)
292926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            DatabaseTracker::tracker().failedToOpenDatabase(m_database);
293926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
294926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
295926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    void setOpenSucceeded() { m_openSucceeded = true; }
296926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)private:
298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    DatabaseBackendBase* m_database;
299926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    bool m_openSucceeded;
300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
301926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
302926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool DatabaseBackendBase::performOpenAndVerify(bool shouldSetVersionInNewDatabase, DatabaseError& error, String& errorMessage)
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
304926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    DoneCreatingDatabaseOnExitCaller onExitCaller(this);
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(errorMessage.isEmpty());
306926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(error == DatabaseError::None); // Better not have any errors already.
307926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    error = DatabaseError::InvalidDatabaseState; // Presumed failure. We'll clear it if we succeed below.
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const int maxSqliteBusyWaitTime = 30000;
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_sqliteDatabase.open(m_filename, true)) {
312e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        reportOpenDatabaseResult(1, InvalidStateError, m_sqliteDatabase.lastError());
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        errorMessage = formatErrorMessage("unable to open database", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_sqliteDatabase.turnOnIncrementalAutoVacuum())
317a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        WTF_LOG_ERROR("Unable to turn on incremental auto-vacuum (%d %s)", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_sqliteDatabase.setBusyTimeout(maxSqliteBusyWaitTime);
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String currentVersion;
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        MutexLocker locker(guidMutex());
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        GuidVersionMap::iterator entry = guidToVersionMap().find(m_guid);
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (entry != guidToVersionMap().end()) {
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Map null string to empty string (see updateGuidVersionMap()).
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            currentVersion = entry->value.isNull() ? emptyString() : entry->value.isolatedCopy();
329a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            WTF_LOG(StorageAPI, "Current cached version for guid %i is %s", m_guid, currentVersion.ascii().data());
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Note: In multi-process browsers the cached value may be inaccurate, but
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // we cannot read the actual version from the database without potentially
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // inducing a form of deadlock, a busytimeout error when trying to
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // access the database. So we'll use the cached value if we're unable to read
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // the value from the database file without waiting.
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // FIXME: Add an async openDatabase method to the DatabaseAPI.
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            const int noSqliteBusyWaitTime = 0;
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_sqliteDatabase.setBusyTimeout(noSqliteBusyWaitTime);
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            String versionFromDatabase;
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (getVersionFromDatabase(versionFromDatabase, false)) {
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                currentVersion = versionFromDatabase;
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                updateGuidVersionMap(m_guid, currentVersion);
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_sqliteDatabase.setBusyTimeout(maxSqliteBusyWaitTime);
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
346a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            WTF_LOG(StorageAPI, "No cached version for guid %i", m_guid);
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            SQLiteTransaction transaction(m_sqliteDatabase);
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            transaction.begin();
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!transaction.inProgress()) {
351e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                reportOpenDatabaseResult(2, InvalidStateError, m_sqliteDatabase.lastError());
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                errorMessage = formatErrorMessage("unable to open database, failed to start transaction", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                m_sqliteDatabase.close();
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            String tableName(infoTableName);
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!m_sqliteDatabase.tableExists(tableName)) {
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                m_new = true;
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!m_sqliteDatabase.executeCommand("CREATE TABLE " + tableName + " (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,value TEXT NOT NULL ON CONFLICT FAIL);")) {
362e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                    reportOpenDatabaseResult(3, InvalidStateError, m_sqliteDatabase.lastError());
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    errorMessage = formatErrorMessage("unable to open database, failed to create 'info' table", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    transaction.rollback();
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    m_sqliteDatabase.close();
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return false;
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } else if (!getVersionFromDatabase(currentVersion, false)) {
369e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                reportOpenDatabaseResult(4, InvalidStateError, m_sqliteDatabase.lastError());
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                errorMessage = formatErrorMessage("unable to open database, failed to read current version", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                transaction.rollback();
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                m_sqliteDatabase.close();
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (currentVersion.length()) {
377a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                WTF_LOG(StorageAPI, "Retrieved current version %s from database %s", currentVersion.ascii().data(), databaseDebugName().ascii().data());
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } else if (!m_new || shouldSetVersionInNewDatabase) {
379a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                WTF_LOG(StorageAPI, "Setting version %s in database %s that was just created", m_expectedVersion.ascii().data(), databaseDebugName().ascii().data());
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!setVersionInDatabase(m_expectedVersion, false)) {
381e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                    reportOpenDatabaseResult(5, InvalidStateError, m_sqliteDatabase.lastError());
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    errorMessage = formatErrorMessage("unable to open database, failed to write current version", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    transaction.rollback();
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    m_sqliteDatabase.close();
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return false;
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                currentVersion = m_expectedVersion;
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            updateGuidVersionMap(m_guid, currentVersion);
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            transaction.commit();
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (currentVersion.isNull()) {
395a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        WTF_LOG(StorageAPI, "Database %s does not have its version set", databaseDebugName().ascii().data());
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        currentVersion = "";
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the expected version isn't the empty string, ensure that the current database version we have matches that version. Otherwise, set an exception.
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the expected version is the empty string, then we always return with whatever version of the database we have.
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ((!m_new || shouldSetVersionInNewDatabase) && m_expectedVersion.length() && m_expectedVersion != currentVersion) {
402e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        reportOpenDatabaseResult(6, InvalidStateError, 0);
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        errorMessage = "unable to open database, version mismatch, '" + m_expectedVersion + "' does not match the currentVersion of '" + currentVersion + "'";
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_sqliteDatabase.close();
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_databaseAuthorizer);
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_sqliteDatabase.setAuthorizer(m_databaseAuthorizer);
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // See comment at the top this file regarding calling addOpenDatabase().
412926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    DatabaseTracker::tracker().addOpenDatabase(this);
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_opened = true;
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
415926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Declare success:
416926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    error = DatabaseError::None; // Clear the presumed error from above.
417926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    onExitCaller.setOpenSucceeded();
418926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_new && !shouldSetVersionInNewDatabase)
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_expectedVersion = ""; // The caller provided a creationCallback which will set the expected version.
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    reportOpenDatabaseResult(0, -1, 0); // OK
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
426926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)SecurityOrigin* DatabaseBackendBase::securityOrigin() const
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_contextThreadSecurityOrigin.get();
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
431926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)String DatabaseBackendBase::stringIdentifier() const
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Return a deep copy for ref counting thread safety
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_name.isolatedCopy();
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
437926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)String DatabaseBackendBase::displayName() const
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Return a deep copy for ref counting thread safety
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_displayName.isolatedCopy();
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
443926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)unsigned long DatabaseBackendBase::estimatedSize() const
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_estimatedSize;
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
448926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)String DatabaseBackendBase::fileName() const
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Return a deep copy for ref counting thread safety
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_filename.isolatedCopy();
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
454926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DatabaseDetails DatabaseBackendBase::details() const
455926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
456926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return DatabaseDetails(stringIdentifier(), displayName(), estimatedSize(), 0);
457926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
458926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
459926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool DatabaseBackendBase::getVersionFromDatabase(String& version, bool shouldCacheVersion)
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String query(String("SELECT value FROM ") + infoTableName +  " WHERE key = '" + versionKey + "';");
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_databaseAuthorizer->disable();
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool result = retrieveTextResultFromDatabase(m_sqliteDatabase, query, version);
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (result) {
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (shouldCacheVersion)
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            setCachedVersion(version);
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else
470a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        WTF_LOG_ERROR("Failed to retrieve version from database %s", databaseDebugName().ascii().data());
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_databaseAuthorizer->enable();
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
477926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool DatabaseBackendBase::setVersionInDatabase(const String& version, bool shouldCacheVersion)
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The INSERT will replace an existing entry for the database with the new version number, due to the UNIQUE ON CONFLICT REPLACE
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // clause in the CREATE statement (see Database::performOpenAndVerify()).
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String query(String("INSERT INTO ") + infoTableName +  " (key, value) VALUES ('" + versionKey + "', ?);");
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_databaseAuthorizer->disable();
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool result = setTextValueInDatabase(m_sqliteDatabase, query, version);
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (result) {
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (shouldCacheVersion)
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            setCachedVersion(version);
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else
490a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        WTF_LOG_ERROR("Failed to set version %s in database (%s)", version.ascii().data(), query.ascii().data());
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_databaseAuthorizer->enable();
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
497926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::setExpectedVersion(const String& version)
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_expectedVersion = version.isolatedCopy();
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
502926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)String DatabaseBackendBase::getCachedVersion() const
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    MutexLocker locker(guidMutex());
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return guidToVersionMap().get(m_guid).isolatedCopy();
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
508926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::setCachedVersion(const String& actualVersion)
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Update the in memory database version map.
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    MutexLocker locker(guidMutex());
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateGuidVersionMap(m_guid, actualVersion);
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
515926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool DatabaseBackendBase::getActualVersionForTransaction(String &actualVersion)
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_sqliteDatabase.transactionInProgress());
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Note: In multi-process browsers the cached value may be inaccurate.
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // So we retrieve the value from the database and update the cached value here.
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return getVersionFromDatabase(actualVersion, true);
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
523926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::disableAuthorizer()
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_databaseAuthorizer);
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_databaseAuthorizer->disable();
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
529926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::enableAuthorizer()
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_databaseAuthorizer);
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_databaseAuthorizer->enable();
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
535926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::setAuthorizerReadOnly()
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_databaseAuthorizer);
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_databaseAuthorizer->setReadOnly();
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::setAuthorizerPermissions(int permissions)
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_databaseAuthorizer);
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_databaseAuthorizer->setPermissions(permissions);
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
547926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool DatabaseBackendBase::lastActionChangedDatabase()
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_databaseAuthorizer);
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_databaseAuthorizer->lastActionChangedDatabase();
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
553926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool DatabaseBackendBase::lastActionWasInsert()
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_databaseAuthorizer);
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_databaseAuthorizer->lastActionWasInsert();
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
559926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::resetDeletes()
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_databaseAuthorizer);
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_databaseAuthorizer->resetDeletes();
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
565926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool DatabaseBackendBase::hadDeletes()
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_databaseAuthorizer);
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_databaseAuthorizer->hadDeletes();
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
571926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::resetAuthorizer()
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_databaseAuthorizer)
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_databaseAuthorizer->reset();
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
577926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)unsigned long long DatabaseBackendBase::maximumSize() const
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return DatabaseTracker::tracker().getMaxSizeForDatabase(this);
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
582926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::incrementalVacuumIfNeeded()
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int64_t freeSpaceSize = m_sqliteDatabase.freeSpaceSize();
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int64_t totalSize = m_sqliteDatabase.totalSize();
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (totalSize <= 10 * freeSpaceSize) {
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int result = m_sqliteDatabase.runIncrementalVacuumCommand();
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        reportVacuumDatabaseResult(result);
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (result != SQLResultOk)
590926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            m_frontend->logErrorMessage(formatErrorMessage("error vacuuming database", result, m_sqliteDatabase.lastErrorMsg()));
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
594926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::interrupt()
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_sqliteDatabase.interrupt();
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
599926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool DatabaseBackendBase::isInterrupted()
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    MutexLocker locker(m_sqliteDatabase.databaseMutex());
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_sqliteDatabase.isInterrupted();
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// These are used to generate histograms of errors seen with websql.
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// See about:histograms in chromium.
607926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::reportOpenDatabaseResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode)
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
60951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (blink::Platform::current()->databaseObserver()) {
61051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        blink::Platform::current()->databaseObserver()->reportOpenDatabaseResult(
61151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            createDatabaseIdentifierFromSecurityOrigin(securityOrigin()),
61251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            stringIdentifier(), isSyncDatabase(),
61351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            errorSite, webSqlErrorCode, sqliteErrorCode);
61451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
617926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::reportChangeVersionResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode)
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
61951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (blink::Platform::current()->databaseObserver()) {
62051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        blink::Platform::current()->databaseObserver()->reportChangeVersionResult(
62151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            createDatabaseIdentifierFromSecurityOrigin(securityOrigin()),
62251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            stringIdentifier(), isSyncDatabase(),
62351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            errorSite, webSqlErrorCode, sqliteErrorCode);
62451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
627926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::reportStartTransactionResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode)
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
62951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (blink::Platform::current()->databaseObserver()) {
63051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        blink::Platform::current()->databaseObserver()->reportStartTransactionResult(
63151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            createDatabaseIdentifierFromSecurityOrigin(securityOrigin()),
63251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            stringIdentifier(), isSyncDatabase(),
63351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            errorSite, webSqlErrorCode, sqliteErrorCode);
63451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
637926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::reportCommitTransactionResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode)
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
63951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (blink::Platform::current()->databaseObserver()) {
64051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        blink::Platform::current()->databaseObserver()->reportCommitTransactionResult(
64151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            createDatabaseIdentifierFromSecurityOrigin(securityOrigin()),
64251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            stringIdentifier(), isSyncDatabase(),
64351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            errorSite, webSqlErrorCode, sqliteErrorCode);
64451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
647926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::reportExecuteStatementResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode)
6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
64951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (blink::Platform::current()->databaseObserver()) {
65051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        blink::Platform::current()->databaseObserver()->reportExecuteStatementResult(
65151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            createDatabaseIdentifierFromSecurityOrigin(securityOrigin()),
65251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            stringIdentifier(), isSyncDatabase(),
65351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            errorSite, webSqlErrorCode, sqliteErrorCode);
65451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
657926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseBackendBase::reportVacuumDatabaseResult(int sqliteErrorCode)
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
65951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (blink::Platform::current()->databaseObserver()) {
66051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        blink::Platform::current()->databaseObserver()->reportVacuumDatabaseResult(
66151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            createDatabaseIdentifierFromSecurityOrigin(securityOrigin()),
66251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            stringIdentifier(), isSyncDatabase(), sqliteErrorCode);
66351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
668