OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
11 * notice, this list of conditions and the following disclaimer in the | 11 * notice, this list of conditions and the following disclaimer in the |
12 * documentation and/or other materials provided with the distribution. | 12 * documentation and/or other materials provided with the distribution. |
13 * | 13 * |
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | 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 | 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 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 | 17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 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 | 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 | 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 | 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. | 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 */ | 24 */ |
25 | 25 |
26 #include "config.h" | 26 #include "config.h" |
27 #include "modules/indexeddb/IDBCursor.h" | 27 #include "modules/indexeddb/IDBCursor.h" |
28 | 28 |
29 #include "bindings/v8/ExceptionMessages.h" | |
30 #include "bindings/v8/ExceptionState.h" | 29 #include "bindings/v8/ExceptionState.h" |
31 #include "bindings/v8/IDBBindingUtilities.h" | 30 #include "bindings/v8/IDBBindingUtilities.h" |
32 #include "core/dom/ExceptionCode.h" | 31 #include "core/dom/ExceptionCode.h" |
33 #include "core/dom/ExecutionContext.h" | 32 #include "core/dom/ExecutionContext.h" |
34 #include "core/inspector/ScriptCallStack.h" | 33 #include "core/inspector/ScriptCallStack.h" |
35 #include "modules/indexeddb/IDBAny.h" | 34 #include "modules/indexeddb/IDBAny.h" |
36 #include "modules/indexeddb/IDBDatabase.h" | 35 #include "modules/indexeddb/IDBDatabase.h" |
37 #include "modules/indexeddb/IDBKey.h" | 36 #include "modules/indexeddb/IDBKey.h" |
38 #include "modules/indexeddb/IDBObjectStore.h" | 37 #include "modules/indexeddb/IDBObjectStore.h" |
39 #include "modules/indexeddb/IDBRequest.h" | 38 #include "modules/indexeddb/IDBRequest.h" |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 | 99 |
101 IDBCursor::~IDBCursor() | 100 IDBCursor::~IDBCursor() |
102 { | 101 { |
103 } | 102 } |
104 | 103 |
105 PassRefPtr<IDBRequest> IDBCursor::update(ScriptState* state, ScriptValue& value,
ExceptionState& exceptionState) | 104 PassRefPtr<IDBRequest> IDBCursor::update(ScriptState* state, ScriptValue& value,
ExceptionState& exceptionState) |
106 { | 105 { |
107 IDB_TRACE("IDBCursor::update"); | 106 IDB_TRACE("IDBCursor::update"); |
108 | 107 |
109 if (!m_gotValue) { | 108 if (!m_gotValue) { |
110 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("update", "IDBCursor", IDBDatabase::noValueErrorMessage)); | 109 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::noValue
ErrorMessage); |
111 return 0; | 110 return 0; |
112 } | 111 } |
113 if (isKeyCursor()) { | 112 if (isKeyCursor()) { |
114 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("update", "IDBCursor", IDBDatabase::isKeyCursorErrorMessage)); | 113 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::isKeyCu
rsorErrorMessage); |
115 return 0; | 114 return 0; |
116 } | 115 } |
117 if (isDeleted()) { | 116 if (isDeleted()) { |
118 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("update", "IDBCursor", IDBDatabase::sourceDeletedErrorMessage)); | 117 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::sourceD
eletedErrorMessage); |
119 return 0; | 118 return 0; |
120 } | 119 } |
121 if (m_transaction->isFinished()) { | 120 if (m_transaction->isFinished()) { |
122 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("update", "IDBCursor", IDBDatabase::transactionFinishedErr
orMessage)); | 121 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionFinishedErrorMessage); |
123 return 0; | 122 return 0; |
124 } | 123 } |
125 if (!m_transaction->isActive()) { | 124 if (!m_transaction->isActive()) { |
126 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("update", "IDBCursor", IDBDatabase::transactionInactiveErr
orMessage)); | 125 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionInactiveErrorMessage); |
127 return 0; | 126 return 0; |
128 } | 127 } |
129 if (m_transaction->isReadOnly()) { | 128 if (m_transaction->isReadOnly()) { |
130 exceptionState.throwDOMException(ReadOnlyError, ExceptionMessages::faile
dToExecute("update", "IDBCursor", "The record may not be updated inside a read-o
nly transaction.")); | 129 exceptionState.throwDOMException(ReadOnlyError, "The record may not be u
pdated inside a read-only transaction."); |
131 return 0; | 130 return 0; |
132 } | 131 } |
133 | 132 |
134 RefPtr<IDBObjectStore> objectStore = effectiveObjectStore(); | 133 RefPtr<IDBObjectStore> objectStore = effectiveObjectStore(); |
135 const IDBKeyPath& keyPath = objectStore->metadata().keyPath; | 134 const IDBKeyPath& keyPath = objectStore->metadata().keyPath; |
136 const bool usesInLineKeys = !keyPath.isNull(); | 135 const bool usesInLineKeys = !keyPath.isNull(); |
137 if (usesInLineKeys) { | 136 if (usesInLineKeys) { |
138 RefPtr<IDBKey> keyPathKey = createIDBKeyFromScriptValueAndKeyPath(m_requ
est->requestState(), value, keyPath); | 137 RefPtr<IDBKey> keyPathKey = createIDBKeyFromScriptValueAndKeyPath(m_requ
est->requestState(), value, keyPath); |
139 if (!keyPathKey || !keyPathKey->isEqual(m_primaryKey.get())) { | 138 if (!keyPathKey || !keyPathKey->isEqual(m_primaryKey.get())) { |
140 exceptionState.throwDOMException(DataError, ExceptionMessages::faile
dToExecute("update", "IDBCursor", "The effective object store of this cursor use
s in-line keys and evaluating the key path of the value parameter results in a d
ifferent value than the cursor's effective key.")); | 139 exceptionState.throwDOMException(DataError, "The effective object st
ore of this cursor uses in-line keys and evaluating the key path of the value pa
rameter results in a different value than the cursor's effective key."); |
141 return 0; | 140 return 0; |
142 } | 141 } |
143 } | 142 } |
144 | 143 |
145 return objectStore->put(WebIDBDatabase::CursorUpdate, IDBAny::create(this),
state, value, m_primaryKey, exceptionState); | 144 return objectStore->put(WebIDBDatabase::CursorUpdate, IDBAny::create(this),
state, value, m_primaryKey, exceptionState); |
146 } | 145 } |
147 | 146 |
148 void IDBCursor::advance(unsigned long count, ExceptionState& exceptionState) | 147 void IDBCursor::advance(unsigned long count, ExceptionState& exceptionState) |
149 { | 148 { |
150 IDB_TRACE("IDBCursor::advance"); | 149 IDB_TRACE("IDBCursor::advance"); |
151 if (!m_gotValue) { | 150 if (!m_gotValue) { |
152 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("advance", "IDBCursor", IDBDatabase::noValueErrorMessage)); | 151 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::noValue
ErrorMessage); |
153 return; | 152 return; |
154 } | 153 } |
155 if (isDeleted()) { | 154 if (isDeleted()) { |
156 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("advance", "IDBCursor", IDBDatabase::sourceDeletedErrorMessage)); | 155 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::sourceD
eletedErrorMessage); |
157 return; | 156 return; |
158 } | 157 } |
159 | 158 |
160 if (m_transaction->isFinished()) { | 159 if (m_transaction->isFinished()) { |
161 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("advance", "IDBCursor", IDBDatabase::transactionFinishedEr
rorMessage)); | 160 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionFinishedErrorMessage); |
162 return; | 161 return; |
163 } | 162 } |
164 if (!m_transaction->isActive()) { | 163 if (!m_transaction->isActive()) { |
165 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("advance", "IDBCursor", IDBDatabase::transactionInactiveEr
rorMessage)); | 164 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionInactiveErrorMessage); |
166 return; | 165 return; |
167 } | 166 } |
168 | 167 |
169 if (!count) { | 168 if (!count) { |
170 exceptionState.throwUninformativeAndGenericTypeError(); | 169 exceptionState.throwUninformativeAndGenericTypeError(); |
171 return; | 170 return; |
172 } | 171 } |
173 | 172 |
174 m_request->setPendingCursor(this); | 173 m_request->setPendingCursor(this); |
175 m_gotValue = false; | 174 m_gotValue = false; |
176 m_backend->advance(count, WebIDBCallbacksImpl::create(m_request).leakPtr()); | 175 m_backend->advance(count, WebIDBCallbacksImpl::create(m_request).leakPtr()); |
177 } | 176 } |
178 | 177 |
179 void IDBCursor::continueFunction(ExecutionContext* context, const ScriptValue& k
eyValue, ExceptionState& exceptionState) | 178 void IDBCursor::continueFunction(ExecutionContext* context, const ScriptValue& k
eyValue, ExceptionState& exceptionState) |
180 { | 179 { |
181 DOMRequestState requestState(context); | 180 DOMRequestState requestState(context); |
182 RefPtr<IDBKey> key = keyValue.isUndefined() ? 0 : scriptValueToIDBKey(&reque
stState, keyValue); | 181 RefPtr<IDBKey> key = keyValue.isUndefined() ? 0 : scriptValueToIDBKey(&reque
stState, keyValue); |
183 continueFunction(key.release(), exceptionState); | 182 continueFunction(key.release(), exceptionState); |
184 } | 183 } |
185 | 184 |
186 void IDBCursor::continueFunction(PassRefPtr<IDBKey> key, ExceptionState& excepti
onState) | 185 void IDBCursor::continueFunction(PassRefPtr<IDBKey> key, ExceptionState& excepti
onState) |
187 { | 186 { |
188 IDB_TRACE("IDBCursor::continue"); | 187 IDB_TRACE("IDBCursor::continue"); |
189 if (key && !key->isValid()) { | 188 if (key && !key->isValid()) { |
190 exceptionState.throwDOMException(DataError, ExceptionMessages::failedToE
xecute("continue", "IDBCursor", IDBDatabase::notValidKeyErrorMessage)); | 189 exceptionState.throwDOMException(DataError, IDBDatabase::notValidKeyErro
rMessage); |
191 return; | 190 return; |
192 } | 191 } |
193 | 192 |
194 if (m_transaction->isFinished()) { | 193 if (m_transaction->isFinished()) { |
195 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("continue", "IDBCursor", IDBDatabase::transactionFinishedE
rrorMessage)); | 194 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionFinishedErrorMessage); |
196 return; | 195 return; |
197 } | 196 } |
198 if (!m_transaction->isActive()) { | 197 if (!m_transaction->isActive()) { |
199 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("continue", "IDBCursor", IDBDatabase::transactionInactiveE
rrorMessage)); | 198 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionInactiveErrorMessage); |
200 return; | 199 return; |
201 } | 200 } |
202 | 201 |
203 if (!m_gotValue) { | 202 if (!m_gotValue) { |
204 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("continue", "IDBCursor", IDBDatabase::noValueErrorMessage)); | 203 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::noValue
ErrorMessage); |
205 return; | 204 return; |
206 } | 205 } |
207 | 206 |
208 if (isDeleted()) { | 207 if (isDeleted()) { |
209 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("continue", "IDBCursor", IDBDatabase::sourceDeletedErrorMessage))
; | 208 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::sourceD
eletedErrorMessage); |
210 return; | 209 return; |
211 } | 210 } |
212 | 211 |
213 if (key) { | 212 if (key) { |
214 ASSERT(m_key); | 213 ASSERT(m_key); |
215 if (m_direction == IndexedDB::CursorNext || m_direction == IndexedDB::Cu
rsorNextNoDuplicate) { | 214 if (m_direction == IndexedDB::CursorNext || m_direction == IndexedDB::Cu
rsorNextNoDuplicate) { |
216 if (!m_key->isLessThan(key.get())) { | 215 if (!m_key->isLessThan(key.get())) { |
217 exceptionState.throwDOMException(DataError, ExceptionMessages::f
ailedToExecute("continue", "IDBCursor", "The parameter is less than or equal to
this cursor's position.")); | 216 exceptionState.throwDOMException(DataError, "The parameter is le
ss than or equal to this cursor's position."); |
218 return; | 217 return; |
219 } | 218 } |
220 } else { | 219 } else { |
221 if (!key->isLessThan(m_key.get())) { | 220 if (!key->isLessThan(m_key.get())) { |
222 exceptionState.throwDOMException(DataError, ExceptionMessages::f
ailedToExecute("continue", "IDBCursor", "The parameter is greater than or equal
to this cursor's position.")); | 221 exceptionState.throwDOMException(DataError, "The parameter is gr
eater than or equal to this cursor's position."); |
223 return; | 222 return; |
224 } | 223 } |
225 } | 224 } |
226 } | 225 } |
227 | 226 |
228 // FIXME: We're not using the context from when continue was called, which m
eans the callback | 227 // FIXME: We're not using the context from when continue was called, which m
eans the callback |
229 // will be on the original context openCursor was called on. Is this
right? | 228 // will be on the original context openCursor was called on. Is this
right? |
230 m_request->setPendingCursor(this); | 229 m_request->setPendingCursor(this); |
231 m_gotValue = false; | 230 m_gotValue = false; |
232 m_backend->continueFunction(key, WebIDBCallbacksImpl::create(m_request).leak
Ptr()); | 231 m_backend->continueFunction(key, WebIDBCallbacksImpl::create(m_request).leak
Ptr()); |
233 } | 232 } |
234 | 233 |
235 PassRefPtr<IDBRequest> IDBCursor::deleteFunction(ExecutionContext* context, Exce
ptionState& exceptionState) | 234 PassRefPtr<IDBRequest> IDBCursor::deleteFunction(ExecutionContext* context, Exce
ptionState& exceptionState) |
236 { | 235 { |
237 IDB_TRACE("IDBCursor::delete"); | 236 IDB_TRACE("IDBCursor::delete"); |
238 if (m_transaction->isFinished()) { | 237 if (m_transaction->isFinished()) { |
239 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("delete", "IDBCursor", IDBDatabase::transactionFinishedErr
orMessage)); | 238 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionFinishedErrorMessage); |
240 return 0; | 239 return 0; |
241 } | 240 } |
242 if (!m_transaction->isActive()) { | 241 if (!m_transaction->isActive()) { |
243 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("delete", "IDBCursor", IDBDatabase::transactionInactiveErr
orMessage)); | 242 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionInactiveErrorMessage); |
244 return 0; | 243 return 0; |
245 } | 244 } |
246 if (m_transaction->isReadOnly()) { | 245 if (m_transaction->isReadOnly()) { |
247 exceptionState.throwDOMException(ReadOnlyError, ExceptionMessages::faile
dToExecute("delete", "IDBCursor", "The record may not be deleted inside a read-o
nly transaction.")); | 246 exceptionState.throwDOMException(ReadOnlyError, "The record may not be d
eleted inside a read-only transaction."); |
248 return 0; | 247 return 0; |
249 } | 248 } |
250 | 249 |
251 if (!m_gotValue) { | 250 if (!m_gotValue) { |
252 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("delete", "IDBCursor", IDBDatabase::noValueErrorMessage)); | 251 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::noValue
ErrorMessage); |
253 return 0; | 252 return 0; |
254 } | 253 } |
255 if (isKeyCursor()) { | 254 if (isKeyCursor()) { |
256 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("delete", "IDBCursor", IDBDatabase::isKeyCursorErrorMessage)); | 255 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::isKeyCu
rsorErrorMessage); |
257 return 0; | 256 return 0; |
258 } | 257 } |
259 if (isDeleted()) { | 258 if (isDeleted()) { |
260 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("delete", "IDBCursor", IDBDatabase::sourceDeletedErrorMessage)); | 259 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::sourceD
eletedErrorMessage); |
261 return 0; | 260 return 0; |
262 } | 261 } |
263 | 262 |
264 RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(m_primaryKey, exceptionStat
e); | 263 RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(m_primaryKey, exceptionStat
e); |
265 ASSERT(!exceptionState.hadException()); | 264 ASSERT(!exceptionState.hadException()); |
266 | 265 |
267 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this
), m_transaction.get()); | 266 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this
), m_transaction.get()); |
268 m_transaction->backendDB()->deleteRange(m_transaction->id(), effectiveObject
Store()->id(), keyRange.release(), WebIDBCallbacksImpl::create(request).leakPtr(
)); | 267 m_transaction->backendDB()->deleteRange(m_transaction->id(), effectiveObject
Store()->id(), keyRange.release(), WebIDBCallbacksImpl::create(request).leakPtr(
)); |
269 return request.release(); | 268 return request.release(); |
270 } | 269 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 case IndexedDB::CursorPrevNoDuplicate: | 397 case IndexedDB::CursorPrevNoDuplicate: |
399 return IDBCursor::directionPrevUnique(); | 398 return IDBCursor::directionPrevUnique(); |
400 | 399 |
401 default: | 400 default: |
402 ASSERT_NOT_REACHED(); | 401 ASSERT_NOT_REACHED(); |
403 return IDBCursor::directionNext(); | 402 return IDBCursor::directionNext(); |
404 } | 403 } |
405 } | 404 } |
406 | 405 |
407 } // namespace WebCore | 406 } // namespace WebCore |
OLD | NEW |