Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / modules / indexeddb / IDBIndex.cpp
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 "bindings/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 WebCore {
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     ScriptWrappable::init(this);
57 }
58
59 IDBIndex::~IDBIndex()
60 {
61 }
62
63 void IDBIndex::trace(Visitor* visitor)
64 {
65     visitor->trace(m_objectStore);
66     visitor->trace(m_transaction);
67 }
68
69 ScriptValue IDBIndex::keyPath(ScriptState* scriptState) const
70 {
71     return idbAnyToScriptValue(scriptState, IDBAny::create(m_metadata.keyPath));
72 }
73
74 IDBRequest* IDBIndex::openCursor(ScriptState* scriptState, const ScriptValue& range, const String& directionString, ExceptionState& exceptionState)
75 {
76     IDB_TRACE("IDBIndex::openCursor");
77     if (isDeleted()) {
78         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::indexDeletedErrorMessage);
79         return 0;
80     }
81     if (m_transaction->isFinished() || m_transaction->isFinishing()) {
82         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
83         return 0;
84     }
85     if (!m_transaction->isActive()) {
86         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
87         return 0;
88     }
89     blink::WebIDBCursorDirection direction = IDBCursor::stringToDirection(directionString, exceptionState);
90     if (exceptionState.hadException())
91         return 0;
92
93     IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), range, exceptionState);
94     if (exceptionState.hadException())
95         return 0;
96
97     if (!backendDB()) {
98         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
99         return 0;
100     }
101
102     return openCursor(scriptState, keyRange, direction);
103 }
104
105 IDBRequest* IDBIndex::openCursor(ScriptState* scriptState, IDBKeyRange* keyRange, blink::WebIDBCursorDirection direction)
106 {
107     IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get());
108     request->setCursorDetails(IndexedDB::CursorKeyAndValue, direction);
109     backendDB()->openCursor(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, direction, false, blink::WebIDBTaskTypeNormal, WebIDBCallbacksImpl::create(request).leakPtr());
110     return request;
111 }
112
113 IDBRequest* IDBIndex::count(ScriptState* scriptState, const ScriptValue& range, ExceptionState& exceptionState)
114 {
115     IDB_TRACE("IDBIndex::count");
116     if (isDeleted()) {
117         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::indexDeletedErrorMessage);
118         return 0;
119     }
120     if (m_transaction->isFinished() || m_transaction->isFinishing()) {
121         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
122         return 0;
123     }
124     if (!m_transaction->isActive()) {
125         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
126         return 0;
127     }
128
129     IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), range, exceptionState);
130     if (exceptionState.hadException())
131         return 0;
132
133     if (!backendDB()) {
134         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
135         return 0;
136     }
137
138     IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get());
139     backendDB()->count(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, WebIDBCallbacksImpl::create(request).leakPtr());
140     return request;
141 }
142
143 IDBRequest* IDBIndex::openKeyCursor(ScriptState* scriptState, const ScriptValue& range, const String& directionString, ExceptionState& exceptionState)
144 {
145     IDB_TRACE("IDBIndex::openKeyCursor");
146     if (isDeleted()) {
147         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::indexDeletedErrorMessage);
148         return 0;
149     }
150     if (m_transaction->isFinished() || m_transaction->isFinishing()) {
151         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
152         return 0;
153     }
154     if (!m_transaction->isActive()) {
155         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
156         return 0;
157     }
158     blink::WebIDBCursorDirection direction = IDBCursor::stringToDirection(directionString, exceptionState);
159     if (exceptionState.hadException())
160         return 0;
161
162     IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), range, exceptionState);
163     if (exceptionState.hadException())
164         return 0;
165     if (!backendDB()) {
166         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
167         return 0;
168     }
169
170     IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get());
171     request->setCursorDetails(IndexedDB::CursorKeyOnly, direction);
172     backendDB()->openCursor(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, direction, true, blink::WebIDBTaskTypeNormal, WebIDBCallbacksImpl::create(request).leakPtr());
173     return request;
174 }
175
176 IDBRequest* IDBIndex::get(ScriptState* scriptState, const ScriptValue& key, ExceptionState& exceptionState)
177 {
178     IDB_TRACE("IDBIndex::get");
179     return getInternal(scriptState, key, exceptionState, false);
180 }
181
182 IDBRequest* IDBIndex::getKey(ScriptState* scriptState, const ScriptValue& key, ExceptionState& exceptionState)
183 {
184     IDB_TRACE("IDBIndex::getKey");
185     return getInternal(scriptState, key, exceptionState, true);
186 }
187
188 IDBRequest* IDBIndex::getInternal(ScriptState* scriptState, const ScriptValue& key, ExceptionState& exceptionState, bool keyOnly)
189 {
190     if (isDeleted()) {
191         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::indexDeletedErrorMessage);
192         return 0;
193     }
194     if (m_transaction->isFinished() || m_transaction->isFinishing()) {
195         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
196         return 0;
197     }
198     if (!m_transaction->isActive()) {
199         exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
200         return 0;
201     }
202
203     IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), key, exceptionState);
204     if (exceptionState.hadException())
205         return 0;
206     if (!keyRange) {
207         exceptionState.throwDOMException(DataError, IDBDatabase::noKeyOrKeyRangeErrorMessage);
208         return 0;
209     }
210     if (!backendDB()) {
211         exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
212         return 0;
213     }
214
215     IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get());
216     backendDB()->get(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, keyOnly, WebIDBCallbacksImpl::create(request).leakPtr());
217     return request;
218 }
219
220 WebIDBDatabase* IDBIndex::backendDB() const
221 {
222     return m_transaction->backendDB();
223 }
224
225 bool IDBIndex::isDeleted() const
226 {
227     return m_deleted || m_objectStore->isDeleted();
228 }
229
230 } // namespace WebCore