Home | History | Annotate | Download | only in indexeddb
      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
      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/IDBIndex.h"
     28 
     29 #include "bindings/core/v8/ExceptionState.h"
     30 #include "bindings/modules/v8/IDBBindingUtilities.h"
     31 #include "core/dom/ExceptionCode.h"
     32 #include "core/dom/ExecutionContext.h"
     33 #include "modules/indexeddb/IDBDatabase.h"
     34 #include "modules/indexeddb/IDBKey.h"
     35 #include "modules/indexeddb/IDBObjectStore.h"
     36 #include "modules/indexeddb/IDBTracing.h"
     37 #include "modules/indexeddb/IDBTransaction.h"
     38 #include "modules/indexeddb/WebIDBCallbacksImpl.h"
     39 #include "public/platform/WebIDBKeyRange.h"
     40 
     41 using blink::WebIDBCallbacks;
     42 using blink::WebIDBCursor;
     43 using blink::WebIDBDatabase;
     44 
     45 namespace blink {
     46 
     47 IDBIndex::IDBIndex(const IDBIndexMetadata& metadata, IDBObjectStore* objectStore, IDBTransaction* transaction)
     48     : m_metadata(metadata)
     49     , m_objectStore(objectStore)
     50     , m_transaction(transaction)
     51     , m_deleted(false)
     52 {
     53     ASSERT(m_objectStore);
     54     ASSERT(m_transaction);
     55     ASSERT(m_metadata.id != IDBIndexMetadata::InvalidId);
     56 }
     57 
     58 IDBIndex::~IDBIndex()
     59 {
     60 }
     61 
     62 void IDBIndex::trace(Visitor* visitor)
     63 {
     64     visitor->trace(m_objectStore);
     65     visitor->trace(m_transaction);
     66 }
     67 
     68 ScriptValue IDBIndex::keyPath(ScriptState* scriptState) const
     69 {
     70     return idbAnyToScriptValue(scriptState, IDBAny::create(m_metadata.keyPath));
     71 }
     72 
     73 IDBRequest* IDBIndex::openCursor(ScriptState* scriptState, const ScriptValue& range, const String& directionString, ExceptionState& exceptionState)
     74 {
     75     IDB_TRACE("IDBIndex::openCursor");
     76     if (isDeleted()) {
     77         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::indexDeletedErrorMessage);
     78         return 0;
     79     }
     80     if (m_transaction->isFinished() || m_transaction->isFinishing()) {
     81         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
     82         return 0;
     83     }
     84     if (!m_transaction->isActive()) {
     85         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
     86         return 0;
     87     }
     88     WebIDBCursorDirection direction = IDBCursor::stringToDirection(directionString, exceptionState);
     89     if (exceptionState.hadException())
     90         return 0;
     91 
     92     IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), range, exceptionState);
     93     if (exceptionState.hadException())
     94         return 0;
     95 
     96     if (!backendDB()) {
     97         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
     98         return 0;
     99     }
    100 
    101     return openCursor(scriptState, keyRange, direction);
    102 }
    103 
    104 IDBRequest* IDBIndex::openCursor(ScriptState* scriptState, IDBKeyRange* keyRange, WebIDBCursorDirection direction)
    105 {
    106     IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get());
    107     request->setCursorDetails(IndexedDB::CursorKeyAndValue, direction);
    108     backendDB()->openCursor(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, direction, false, WebIDBTaskTypeNormal, WebIDBCallbacksImpl::create(request).leakPtr());
    109     return request;
    110 }
    111 
    112 IDBRequest* IDBIndex::count(ScriptState* scriptState, const ScriptValue& range, ExceptionState& exceptionState)
    113 {
    114     IDB_TRACE("IDBIndex::count");
    115     if (isDeleted()) {
    116         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::indexDeletedErrorMessage);
    117         return 0;
    118     }
    119     if (m_transaction->isFinished() || m_transaction->isFinishing()) {
    120         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
    121         return 0;
    122     }
    123     if (!m_transaction->isActive()) {
    124         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
    125         return 0;
    126     }
    127 
    128     IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), range, exceptionState);
    129     if (exceptionState.hadException())
    130         return 0;
    131 
    132     if (!backendDB()) {
    133         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
    134         return 0;
    135     }
    136 
    137     IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get());
    138     backendDB()->count(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, WebIDBCallbacksImpl::create(request).leakPtr());
    139     return request;
    140 }
    141 
    142 IDBRequest* IDBIndex::openKeyCursor(ScriptState* scriptState, const ScriptValue& range, const String& directionString, ExceptionState& exceptionState)
    143 {
    144     IDB_TRACE("IDBIndex::openKeyCursor");
    145     if (isDeleted()) {
    146         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::indexDeletedErrorMessage);
    147         return 0;
    148     }
    149     if (m_transaction->isFinished() || m_transaction->isFinishing()) {
    150         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
    151         return 0;
    152     }
    153     if (!m_transaction->isActive()) {
    154         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
    155         return 0;
    156     }
    157     WebIDBCursorDirection direction = IDBCursor::stringToDirection(directionString, exceptionState);
    158     if (exceptionState.hadException())
    159         return 0;
    160 
    161     IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), range, exceptionState);
    162     if (exceptionState.hadException())
    163         return 0;
    164     if (!backendDB()) {
    165         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
    166         return 0;
    167     }
    168 
    169     IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get());
    170     request->setCursorDetails(IndexedDB::CursorKeyOnly, direction);
    171     backendDB()->openCursor(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, direction, true, WebIDBTaskTypeNormal, WebIDBCallbacksImpl::create(request).leakPtr());
    172     return request;
    173 }
    174 
    175 IDBRequest* IDBIndex::get(ScriptState* scriptState, const ScriptValue& key, ExceptionState& exceptionState)
    176 {
    177     IDB_TRACE("IDBIndex::get");
    178     return getInternal(scriptState, key, exceptionState, false);
    179 }
    180 
    181 IDBRequest* IDBIndex::getKey(ScriptState* scriptState, const ScriptValue& key, ExceptionState& exceptionState)
    182 {
    183     IDB_TRACE("IDBIndex::getKey");
    184     return getInternal(scriptState, key, exceptionState, true);
    185 }
    186 
    187 IDBRequest* IDBIndex::getInternal(ScriptState* scriptState, const ScriptValue& key, ExceptionState& exceptionState, bool keyOnly)
    188 {
    189     if (isDeleted()) {
    190         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::indexDeletedErrorMessage);
    191         return 0;
    192     }
    193     if (m_transaction->isFinished() || m_transaction->isFinishing()) {
    194         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
    195         return 0;
    196     }
    197     if (!m_transaction->isActive()) {
    198         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
    199         return 0;
    200     }
    201 
    202     IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), key, exceptionState);
    203     if (exceptionState.hadException())
    204         return 0;
    205     if (!keyRange) {
    206         exceptionState.throwDOMException(DataError, IDBDatabase::noKeyOrKeyRangeErrorMessage);
    207         return 0;
    208     }
    209     if (!backendDB()) {
    210         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
    211         return 0;
    212     }
    213 
    214     IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get());
    215     backendDB()->get(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, keyOnly, WebIDBCallbacksImpl::create(request).leakPtr());
    216     return request;
    217 }
    218 
    219 WebIDBDatabase* IDBIndex::backendDB() const
    220 {
    221     return m_transaction->backendDB();
    222 }
    223 
    224 bool IDBIndex::isDeleted() const
    225 {
    226     return m_deleted || m_objectStore->isDeleted();
    227 }
    228 
    229 } // namespace blink
    230