Home | History | Annotate | Download | only in indexeddb
      1 /*
      2  * Copyright (C) 2012 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
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "modules/indexeddb/IDBOpenDBRequest.h"
     28 
     29 #include "bindings/v8/Nullable.h"
     30 #include "core/dom/ExceptionCode.h"
     31 #include "core/dom/ExecutionContext.h"
     32 #include "modules/indexeddb/IDBDatabase.h"
     33 #include "modules/indexeddb/IDBDatabaseCallbacks.h"
     34 #include "modules/indexeddb/IDBPendingTransactionMonitor.h"
     35 #include "modules/indexeddb/IDBTracing.h"
     36 #include "modules/indexeddb/IDBVersionChangeEvent.h"
     37 
     38 using blink::WebIDBDatabase;
     39 
     40 namespace WebCore {
     41 
     42 IDBOpenDBRequest* IDBOpenDBRequest::create(ScriptState* scriptState, IDBDatabaseCallbacks* callbacks, int64_t transactionId, int64_t version)
     43 {
     44     IDBOpenDBRequest* request = adoptRefCountedGarbageCollectedWillBeNoop(new IDBOpenDBRequest(scriptState, callbacks, transactionId, version));
     45     request->suspendIfNeeded();
     46     return request;
     47 }
     48 
     49 IDBOpenDBRequest::IDBOpenDBRequest(ScriptState* scriptState, IDBDatabaseCallbacks* callbacks, int64_t transactionId, int64_t version)
     50     : IDBRequest(scriptState, IDBAny::createNull(), 0)
     51     , m_databaseCallbacks(callbacks)
     52     , m_transactionId(transactionId)
     53     , m_version(version)
     54 {
     55     ASSERT(!resultAsAny());
     56     ScriptWrappable::init(this);
     57 }
     58 
     59 IDBOpenDBRequest::~IDBOpenDBRequest()
     60 {
     61 }
     62 
     63 void IDBOpenDBRequest::trace(Visitor* visitor)
     64 {
     65     visitor->trace(m_databaseCallbacks);
     66     IDBRequest::trace(visitor);
     67 }
     68 
     69 const AtomicString& IDBOpenDBRequest::interfaceName() const
     70 {
     71     return EventTargetNames::IDBOpenDBRequest;
     72 }
     73 
     74 void IDBOpenDBRequest::onBlocked(int64_t oldVersion)
     75 {
     76     IDB_TRACE("IDBOpenDBRequest::onBlocked()");
     77     if (!shouldEnqueueEvent())
     78         return;
     79     Nullable<unsigned long long> newVersionNullable = (m_version == IDBDatabaseMetadata::DefaultIntVersion) ? Nullable<unsigned long long>() : Nullable<unsigned long long>(m_version);
     80     enqueueEvent(IDBVersionChangeEvent::create(EventTypeNames::blocked, oldVersion, newVersionNullable));
     81 }
     82 
     83 void IDBOpenDBRequest::onUpgradeNeeded(int64_t oldVersion, PassOwnPtr<WebIDBDatabase> backend, const IDBDatabaseMetadata& metadata, blink::WebIDBDataLoss dataLoss, String dataLossMessage)
     84 {
     85     IDB_TRACE("IDBOpenDBRequest::onUpgradeNeeded()");
     86     if (m_contextStopped || !executionContext()) {
     87         OwnPtr<WebIDBDatabase> db = backend;
     88         db->abort(m_transactionId);
     89         db->close();
     90         return;
     91     }
     92     if (!shouldEnqueueEvent())
     93         return;
     94 
     95     ASSERT(m_databaseCallbacks);
     96 
     97     IDBDatabase* idbDatabase = IDBDatabase::create(executionContext(), backend, m_databaseCallbacks.release());
     98     idbDatabase->setMetadata(metadata);
     99 
    100     if (oldVersion == IDBDatabaseMetadata::NoIntVersion) {
    101         // This database hasn't had an integer version before.
    102         oldVersion = IDBDatabaseMetadata::DefaultIntVersion;
    103     }
    104     IDBDatabaseMetadata oldMetadata(metadata);
    105     oldMetadata.intVersion = oldVersion;
    106 
    107     m_transaction = IDBTransaction::create(executionContext(), m_transactionId, idbDatabase, this, oldMetadata);
    108     setResult(IDBAny::create(idbDatabase));
    109 
    110     if (m_version == IDBDatabaseMetadata::NoIntVersion)
    111         m_version = 1;
    112     enqueueEvent(IDBVersionChangeEvent::create(EventTypeNames::upgradeneeded, oldVersion, m_version, dataLoss, dataLossMessage));
    113 }
    114 
    115 void IDBOpenDBRequest::onSuccess(PassOwnPtr<WebIDBDatabase> backend, const IDBDatabaseMetadata& metadata)
    116 {
    117     IDB_TRACE("IDBOpenDBRequest::onSuccess()");
    118     if (m_contextStopped || !executionContext()) {
    119         OwnPtr<WebIDBDatabase> db = backend;
    120         if (db)
    121             db->close();
    122         return;
    123     }
    124     if (!shouldEnqueueEvent())
    125         return;
    126 
    127     IDBDatabase* idbDatabase = 0;
    128     if (resultAsAny()) {
    129         // Previous onUpgradeNeeded call delivered the backend.
    130         ASSERT(!backend.get());
    131         idbDatabase = resultAsAny()->idbDatabase();
    132         ASSERT(idbDatabase);
    133         ASSERT(!m_databaseCallbacks);
    134     } else {
    135         ASSERT(backend.get());
    136         ASSERT(m_databaseCallbacks);
    137         idbDatabase = IDBDatabase::create(executionContext(), backend, m_databaseCallbacks.release());
    138         setResult(IDBAny::create(idbDatabase));
    139     }
    140     idbDatabase->setMetadata(metadata);
    141     enqueueEvent(Event::create(EventTypeNames::success));
    142 }
    143 
    144 void IDBOpenDBRequest::onSuccess(int64_t oldVersion)
    145 {
    146     IDB_TRACE("IDBOpenDBRequest::onSuccess()");
    147     if (!shouldEnqueueEvent())
    148         return;
    149     if (oldVersion == IDBDatabaseMetadata::NoIntVersion) {
    150         // This database hasn't had an integer version before.
    151         oldVersion = IDBDatabaseMetadata::DefaultIntVersion;
    152     }
    153     setResult(IDBAny::createUndefined());
    154     enqueueEvent(IDBVersionChangeEvent::create(EventTypeNames::success, oldVersion, Nullable<unsigned long long>()));
    155 }
    156 
    157 bool IDBOpenDBRequest::shouldEnqueueEvent() const
    158 {
    159     if (m_contextStopped || !executionContext())
    160         return false;
    161     ASSERT(m_readyState == PENDING || m_readyState == DONE);
    162     if (m_requestAborted)
    163         return false;
    164     return true;
    165 }
    166 
    167 bool IDBOpenDBRequest::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event)
    168 {
    169     // If the connection closed between onUpgradeNeeded and the delivery of the "success" event,
    170     // an "error" event should be fired instead.
    171     if (event->type() == EventTypeNames::success && resultAsAny()->type() == IDBAny::IDBDatabaseType && resultAsAny()->idbDatabase()->isClosePending()) {
    172         dequeueEvent(event.get());
    173         setResult(0);
    174         onError(DOMError::create(AbortError, "The connection was closed."));
    175         return false;
    176     }
    177 
    178     return IDBRequest::dispatchEvent(event);
    179 }
    180 
    181 } // namespace WebCore
    182