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