Home | History | Annotate | Download | only in webdatabase
      1 /*
      2  * Copyright (C) 2010 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "modules/webdatabase/DatabaseSync.h"
     33 
     34 #include "bindings/v8/ExceptionState.h"
     35 #include "core/dom/ExceptionCode.h"
     36 #include "core/dom/ExecutionContext.h"
     37 #include "platform/Logging.h"
     38 #include "modules/webdatabase/DatabaseCallback.h"
     39 #include "modules/webdatabase/DatabaseContext.h"
     40 #include "modules/webdatabase/DatabaseManager.h"
     41 #include "modules/webdatabase/DatabaseTracker.h"
     42 #include "modules/webdatabase/SQLError.h"
     43 #include "modules/webdatabase/SQLTransactionSync.h"
     44 #include "modules/webdatabase/SQLTransactionSyncCallback.h"
     45 #include "wtf/PassRefPtr.h"
     46 #include "wtf/RefPtr.h"
     47 #include "wtf/text/CString.h"
     48 
     49 namespace WebCore {
     50 
     51 PassRefPtrWillBeRawPtr<DatabaseSync> DatabaseSync::create(ExecutionContext*, PassRefPtrWillBeRawPtr<DatabaseBackendBase> backend)
     52 {
     53     return static_cast<DatabaseSync*>(backend.get());
     54 }
     55 
     56 DatabaseSync::DatabaseSync(DatabaseContext* databaseContext,
     57     const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize)
     58     : DatabaseBackendSync(databaseContext, name, expectedVersion, displayName, estimatedSize)
     59     , DatabaseBase(databaseContext->executionContext())
     60 {
     61     ScriptWrappable::init(this);
     62     setFrontend(this);
     63 }
     64 
     65 DatabaseSync::~DatabaseSync()
     66 {
     67     if (executionContext())
     68         ASSERT(executionContext()->isContextThread());
     69 }
     70 
     71 void DatabaseSync::trace(Visitor* visitor)
     72 {
     73     DatabaseBackendSync::trace(visitor);
     74 }
     75 
     76 void DatabaseSync::changeVersion(const String& oldVersion, const String& newVersion, PassOwnPtr<SQLTransactionSyncCallback> changeVersionCallback, ExceptionState& exceptionState)
     77 {
     78     ASSERT(executionContext()->isContextThread());
     79 
     80     if (sqliteDatabase().transactionInProgress()) {
     81         reportChangeVersionResult(1, SQLError::DATABASE_ERR, 0);
     82         setLastErrorMessage("unable to changeVersion from within a transaction");
     83         exceptionState.throwDOMException(SQLDatabaseError, "Unable to change version from within a transaction.");
     84         return;
     85     }
     86 
     87     RefPtrWillBeRawPtr<SQLTransactionSync> transaction = SQLTransactionSync::create(this, changeVersionCallback, false);
     88     transaction->begin(exceptionState);
     89     if (exceptionState.hadException()) {
     90         ASSERT(!lastErrorMessage().isEmpty());
     91         return;
     92     }
     93 
     94     String actualVersion;
     95     if (!getVersionFromDatabase(actualVersion)) {
     96         reportChangeVersionResult(2, SQLError::UNKNOWN_ERR, sqliteDatabase().lastError());
     97         setLastErrorMessage("unable to read the current version", sqliteDatabase().lastError(), sqliteDatabase().lastErrorMsg());
     98         exceptionState.throwDOMException(UnknownError, SQLError::unknownErrorMessage);
     99         return;
    100     }
    101 
    102     if (actualVersion != oldVersion) {
    103         reportChangeVersionResult(3, SQLError::VERSION_ERR, 0);
    104         setLastErrorMessage("current version of the database and `oldVersion` argument do not match");
    105         exceptionState.throwDOMException(VersionError, SQLError::versionErrorMessage);
    106         return;
    107     }
    108 
    109 
    110     transaction->execute(exceptionState);
    111     if (exceptionState.hadException()) {
    112         ASSERT(!lastErrorMessage().isEmpty());
    113         return;
    114     }
    115 
    116     if (!setVersionInDatabase(newVersion)) {
    117         reportChangeVersionResult(4, SQLError::UNKNOWN_ERR, sqliteDatabase().lastError());
    118         setLastErrorMessage("unable to set the new version", sqliteDatabase().lastError(), sqliteDatabase().lastErrorMsg());
    119         exceptionState.throwDOMException(UnknownError, SQLError::unknownErrorMessage);
    120         return;
    121     }
    122 
    123     transaction->commit(exceptionState);
    124     if (exceptionState.hadException()) {
    125         ASSERT(!lastErrorMessage().isEmpty());
    126         setCachedVersion(oldVersion);
    127         return;
    128     }
    129 
    130     reportChangeVersionResult(0, -1, 0); // OK
    131 
    132     setExpectedVersion(newVersion);
    133     setLastErrorMessage("");
    134 }
    135 
    136 void DatabaseSync::transaction(PassOwnPtr<SQLTransactionSyncCallback> callback, ExceptionState& exceptionState)
    137 {
    138     runTransaction(callback, false, exceptionState);
    139 }
    140 
    141 void DatabaseSync::readTransaction(PassOwnPtr<SQLTransactionSyncCallback> callback, ExceptionState& exceptionState)
    142 {
    143     runTransaction(callback, true, exceptionState);
    144 }
    145 
    146 void DatabaseSync::rollbackTransaction(SQLTransactionSync& transaction)
    147 {
    148     ASSERT(!lastErrorMessage().isEmpty());
    149     transaction.rollback();
    150     setLastErrorMessage("");
    151     return;
    152 }
    153 
    154 void DatabaseSync::runTransaction(PassOwnPtr<SQLTransactionSyncCallback> callback, bool readOnly, ExceptionState& exceptionState)
    155 {
    156     ASSERT(executionContext()->isContextThread());
    157 
    158     if (sqliteDatabase().transactionInProgress()) {
    159         setLastErrorMessage("unable to start a transaction from within a transaction");
    160         exceptionState.throwDOMException(SQLDatabaseError, "Unable to start a transaction from within a transaction.");
    161         return;
    162     }
    163 
    164     RefPtrWillBeRawPtr<SQLTransactionSync> transaction = SQLTransactionSync::create(this, callback, readOnly);
    165     transaction->begin(exceptionState);
    166     if (exceptionState.hadException()) {
    167         rollbackTransaction(*transaction);
    168         return;
    169     }
    170 
    171     transaction->execute(exceptionState);
    172     if (exceptionState.hadException()) {
    173         rollbackTransaction(*transaction);
    174         return;
    175     }
    176 
    177     transaction->commit(exceptionState);
    178     if (exceptionState.hadException()) {
    179         rollbackTransaction(*transaction);
    180         return;
    181     }
    182 
    183     setLastErrorMessage("");
    184 }
    185 
    186 void DatabaseSync::closeImmediately()
    187 {
    188     ASSERT(executionContext()->isContextThread());
    189 
    190     if (!opened())
    191         return;
    192 
    193     logErrorMessage("forcibly closing database");
    194     closeDatabase();
    195 }
    196 
    197 void DatabaseSync::observeTransaction(SQLTransactionSync& transaction)
    198 {
    199 #if ENABLE(OILPAN)
    200     m_observers.add(&transaction, adoptPtr(new TransactionObserver(transaction)));
    201 #endif
    202 }
    203 
    204 #if ENABLE(OILPAN)
    205 DatabaseSync::TransactionObserver::~TransactionObserver()
    206 {
    207     m_transaction.rollbackIfInProgress();
    208 }
    209 #endif
    210 
    211 } // namespace WebCore
    212