2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "modules/indexeddb/IDBObjectStore.h"
29 #include "bindings/v8/ExceptionState.h"
30 #include "bindings/v8/ExceptionStatePlaceholder.h"
31 #include "bindings/v8/IDBBindingUtilities.h"
32 #include "bindings/v8/ScriptState.h"
33 #include "core/dom/DOMStringList.h"
34 #include "core/dom/ExceptionCode.h"
35 #include "core/dom/ExecutionContext.h"
36 #include "modules/indexeddb/IDBAny.h"
37 #include "modules/indexeddb/IDBCursorWithValue.h"
38 #include "modules/indexeddb/IDBDatabase.h"
39 #include "modules/indexeddb/IDBKeyPath.h"
40 #include "modules/indexeddb/IDBTracing.h"
41 #include "modules/indexeddb/WebIDBCallbacksImpl.h"
42 #include "platform/SharedBuffer.h"
43 #include "public/platform/WebBlobInfo.h"
44 #include "public/platform/WebData.h"
45 #include "public/platform/WebIDBKey.h"
46 #include "public/platform/WebIDBKeyRange.h"
47 #include "public/platform/WebVector.h"
49 using blink::WebBlobInfo;
50 using blink::WebIDBCallbacks;
51 using blink::WebIDBCursor;
52 using blink::WebIDBDatabase;
53 using blink::WebVector;
57 IDBObjectStore::IDBObjectStore(const IDBObjectStoreMetadata& metadata, IDBTransaction* transaction)
58 : m_metadata(metadata)
59 , m_transaction(transaction)
62 ASSERT(m_transaction);
64 // We pass a reference to this object before it can be adopted.
65 relaxAdoptionRequirement();
67 ScriptWrappable::init(this);
70 void IDBObjectStore::trace(Visitor* visitor)
72 visitor->trace(m_transaction);
73 visitor->trace(m_indexMap);
76 ScriptValue IDBObjectStore::keyPath(ScriptState* scriptState) const
78 return idbAnyToScriptValue(scriptState, IDBAny::create(m_metadata.keyPath));
81 PassRefPtrWillBeRawPtr<DOMStringList> IDBObjectStore::indexNames() const
83 IDB_TRACE("IDBObjectStore::indexNames");
84 RefPtrWillBeRawPtr<DOMStringList> indexNames = DOMStringList::create();
85 for (IDBObjectStoreMetadata::IndexMap::const_iterator it = m_metadata.indexes.begin(); it != m_metadata.indexes.end(); ++it)
86 indexNames->append(it->value.name);
88 return indexNames.release();
91 PassRefPtrWillBeRawPtr<IDBRequest> IDBObjectStore::get(ExecutionContext* context, const ScriptValue& key, ExceptionState& exceptionState)
93 IDB_TRACE("IDBObjectStore::get");
95 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage);
98 if (m_transaction->isFinished() || m_transaction->isFinishing()) {
99 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
102 if (!m_transaction->isActive()) {
103 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
106 RefPtrWillBeRawPtr<IDBKeyRange> keyRange = IDBKeyRange::fromScriptValue(context, key, exceptionState);
107 if (exceptionState.hadException())
110 exceptionState.throwDOMException(DataError, IDBDatabase::noKeyOrKeyRangeErrorMessage);
114 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
118 RefPtrWillBeRawPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
119 backendDB()->get(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, keyRange.release(), false, WebIDBCallbacksImpl::create(request).leakPtr());
120 return request.release();
123 static void generateIndexKeysForValue(v8::Isolate* isolate, const IDBIndexMetadata& indexMetadata, const ScriptValue& objectValue, IDBObjectStore::IndexKeys* indexKeys)
126 RefPtrWillBeRawPtr<IDBKey> indexKey = createIDBKeyFromScriptValueAndKeyPath(isolate, objectValue, indexMetadata.keyPath);
131 if (!indexMetadata.multiEntry || indexKey->type() != IDBKey::ArrayType) {
132 if (!indexKey->isValid())
135 indexKeys->append(indexKey);
137 ASSERT(indexMetadata.multiEntry);
138 ASSERT(indexKey->type() == IDBKey::ArrayType);
139 indexKey = IDBKey::createMultiEntryArray(indexKey->array());
141 for (size_t i = 0; i < indexKey->array().size(); ++i)
142 indexKeys->append(indexKey->array()[i]);
146 PassRefPtrWillBeRawPtr<IDBRequest> IDBObjectStore::add(ExecutionContext* executionContext, ScriptValue& value, const ScriptValue& key, ExceptionState& exceptionState)
148 IDB_TRACE("IDBObjectStore::add");
149 return put(executionContext, WebIDBDatabase::AddOnly, IDBAny::create(this), value, key, exceptionState);
152 PassRefPtrWillBeRawPtr<IDBRequest> IDBObjectStore::put(ExecutionContext* executionContext, ScriptValue& value, const ScriptValue& key, ExceptionState& exceptionState)
154 IDB_TRACE("IDBObjectStore::put");
155 return put(executionContext, WebIDBDatabase::AddOrUpdate, IDBAny::create(this), value, key, exceptionState);
158 PassRefPtrWillBeRawPtr<IDBRequest> IDBObjectStore::put(ExecutionContext* executionContext, WebIDBDatabase::PutMode putMode, PassRefPtrWillBeRawPtr<IDBAny> source, ScriptValue& value, const ScriptValue& keyValue, ExceptionState& exceptionState)
160 RefPtrWillBeRawPtr<IDBKey> key = keyValue.isUndefined() ? nullptr : scriptValueToIDBKey(toIsolate(executionContext), keyValue);
161 return put(executionContext, putMode, source, value, key.release(), exceptionState);
164 PassRefPtrWillBeRawPtr<IDBRequest> IDBObjectStore::put(ExecutionContext* executionContext, WebIDBDatabase::PutMode putMode, PassRefPtrWillBeRawPtr<IDBAny> source, ScriptValue& value, PassRefPtrWillBeRawPtr<IDBKey> prpKey, ExceptionState& exceptionState)
166 RefPtrWillBeRawPtr<IDBKey> key = prpKey;
168 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage);
171 if (m_transaction->isFinished() || m_transaction->isFinishing()) {
172 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
175 if (!m_transaction->isActive()) {
176 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
179 if (m_transaction->isReadOnly()) {
180 exceptionState.throwDOMException(ReadOnlyError, IDBDatabase::transactionReadOnlyErrorMessage);
184 Vector<WebBlobInfo> blobInfo;
186 RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(value, &blobInfo, exceptionState, toIsolate(executionContext));
187 if (exceptionState.hadException())
190 if (serializedValue->containsBlobs()) {
191 // FIXME: Add Blob/File/FileList support
192 exceptionState.throwDOMException(DataCloneError, "The object store currently does not support blob values.");
195 ASSERT(blobInfo.isEmpty());
197 const IDBKeyPath& keyPath = m_metadata.keyPath;
198 const bool usesInLineKeys = !keyPath.isNull();
199 const bool hasKeyGenerator = autoIncrement();
201 if (putMode != WebIDBDatabase::CursorUpdate && usesInLineKeys && key) {
202 exceptionState.throwDOMException(DataError, "The object store uses in-line keys and the key parameter was provided.");
205 if (!usesInLineKeys && !hasKeyGenerator && !key) {
206 exceptionState.throwDOMException(DataError, "The object store uses out-of-line keys and has no key generator and the key parameter was not provided.");
209 if (usesInLineKeys) {
210 RefPtrWillBeRawPtr<IDBKey> keyPathKey = createIDBKeyFromScriptValueAndKeyPath(toIsolate(executionContext), value, keyPath);
211 if (keyPathKey && !keyPathKey->isValid()) {
212 exceptionState.throwDOMException(DataError, "Evaluating the object store's key path yielded a value that is not a valid key.");
215 if (!hasKeyGenerator && !keyPathKey) {
216 exceptionState.throwDOMException(DataError, "Evaluating the object store's key path did not yield a value.");
219 if (hasKeyGenerator && !keyPathKey) {
220 if (!canInjectIDBKeyIntoScriptValue(toIsolate(executionContext), value, keyPath)) {
221 exceptionState.throwDOMException(DataError, "A generated key could not be inserted into the value.");
228 if (key && !key->isValid()) {
229 exceptionState.throwDOMException(DataError, IDBDatabase::notValidKeyErrorMessage);
234 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
238 Vector<int64_t> indexIds;
239 WillBeHeapVector<IndexKeys> indexKeys;
240 for (IDBObjectStoreMetadata::IndexMap::const_iterator it = m_metadata.indexes.begin(); it != m_metadata.indexes.end(); ++it) {
242 generateIndexKeysForValue(toIsolate(executionContext), it->value, value, &keys);
243 indexIds.append(it->key);
244 indexKeys.append(keys);
247 RefPtrWillBeRawPtr<IDBRequest> request = IDBRequest::create(executionContext, source, m_transaction.get());
248 Vector<char> wireBytes;
249 serializedValue->toWireBytes(wireBytes);
250 RefPtr<SharedBuffer> valueBuffer = SharedBuffer::adoptVector(wireBytes);
252 backendDB()->put(m_transaction->id(), id(), blink::WebData(valueBuffer), blobInfo, key.release(), static_cast<WebIDBDatabase::PutMode>(putMode), WebIDBCallbacksImpl::create(request).leakPtr(), indexIds, indexKeys);
253 return request.release();
256 PassRefPtrWillBeRawPtr<IDBRequest> IDBObjectStore::deleteFunction(ExecutionContext* context, const ScriptValue& key, ExceptionState& exceptionState)
258 IDB_TRACE("IDBObjectStore::delete");
260 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage);
263 if (m_transaction->isFinished() || m_transaction->isFinishing()) {
264 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
267 if (!m_transaction->isActive()) {
268 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
271 if (m_transaction->isReadOnly()) {
272 exceptionState.throwDOMException(ReadOnlyError, IDBDatabase::transactionReadOnlyErrorMessage);
276 RefPtrWillBeRawPtr<IDBKeyRange> keyRange = IDBKeyRange::fromScriptValue(context, key, exceptionState);
277 if (exceptionState.hadException())
280 exceptionState.throwDOMException(DataError, IDBDatabase::noKeyOrKeyRangeErrorMessage);
284 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
288 RefPtrWillBeRawPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
289 backendDB()->deleteRange(m_transaction->id(), id(), keyRange.release(), WebIDBCallbacksImpl::create(request).leakPtr());
290 return request.release();
293 PassRefPtrWillBeRawPtr<IDBRequest> IDBObjectStore::clear(ExecutionContext* context, ExceptionState& exceptionState)
295 IDB_TRACE("IDBObjectStore::clear");
297 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage);
300 if (m_transaction->isFinished() || m_transaction->isFinishing()) {
301 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
304 if (!m_transaction->isActive()) {
305 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
308 if (m_transaction->isReadOnly()) {
309 exceptionState.throwDOMException(ReadOnlyError, IDBDatabase::transactionReadOnlyErrorMessage);
313 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
317 RefPtrWillBeRawPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
318 backendDB()->clear(m_transaction->id(), id(), WebIDBCallbacksImpl::create(request).leakPtr());
319 return request.release();
323 // This class creates the index keys for a given index by extracting
324 // them from the SerializedScriptValue, for all the existing values in
325 // the objectStore. It only needs to be kept alive by virtue of being
326 // a listener on an IDBRequest object, in the same way that JavaScript
327 // cursor success handlers are kept alive.
328 class IndexPopulator FINAL : public EventListener {
330 static PassRefPtr<IndexPopulator> create(ScriptState* scriptState, PassRefPtrWillBeRawPtr<IDBDatabase> database, int64_t transactionId, int64_t objectStoreId, const IDBIndexMetadata& indexMetadata)
332 return adoptRef(new IndexPopulator(scriptState, database, transactionId, objectStoreId, indexMetadata));
335 virtual bool operator==(const EventListener& other) OVERRIDE
337 return this == &other;
341 IndexPopulator(ScriptState* scriptState, PassRefPtrWillBeRawPtr<IDBDatabase> database, int64_t transactionId, int64_t objectStoreId, const IDBIndexMetadata& indexMetadata)
342 : EventListener(CPPEventListenerType)
343 , m_scriptState(scriptState)
344 , m_database(database)
345 , m_transactionId(transactionId)
346 , m_objectStoreId(objectStoreId)
347 , m_indexMetadata(indexMetadata)
351 virtual void handleEvent(ExecutionContext* context, Event* event) OVERRIDE
353 ASSERT(event->type() == EventTypeNames::success);
354 EventTarget* target = event->target();
355 IDBRequest* request = static_cast<IDBRequest*>(target);
357 if (!m_database->backend()) // If database is stopped?
360 RefPtrWillBeRawPtr<IDBAny> cursorAny = request->resultAsAny();
361 RefPtrWillBeRawPtr<IDBCursorWithValue> cursor = nullptr;
362 if (cursorAny->type() == IDBAny::IDBCursorWithValueType)
363 cursor = cursorAny->idbCursorWithValue();
365 Vector<int64_t> indexIds;
366 indexIds.append(m_indexMetadata.id);
367 if (cursor && !cursor->isDeleted()) {
368 cursor->continueFunction(static_cast<IDBKey*>(0), static_cast<IDBKey*>(0), ASSERT_NO_EXCEPTION);
370 RefPtrWillBeRawPtr<IDBKey> primaryKey = cursor->idbPrimaryKey();
371 ScriptValue value = cursor->value(m_scriptState.get());
373 IDBObjectStore::IndexKeys indexKeys;
374 generateIndexKeysForValue(toIsolate(context), m_indexMetadata, value, &indexKeys);
376 WillBeHeapVector<IDBObjectStore::IndexKeys> indexKeysList;
377 indexKeysList.append(indexKeys);
379 m_database->backend()->setIndexKeys(m_transactionId, m_objectStoreId, primaryKey.release(), indexIds, indexKeysList);
381 // Now that we are done indexing, tell the backend to go
382 // back to processing tasks of type NormalTask.
383 m_database->backend()->setIndexesReady(m_transactionId, m_objectStoreId, indexIds);
389 RefPtr<ScriptState> m_scriptState;
390 RefPtrWillBePersistent<IDBDatabase> m_database;
391 const int64_t m_transactionId;
392 const int64_t m_objectStoreId;
393 const IDBIndexMetadata m_indexMetadata;
397 PassRefPtrWillBeRawPtr<IDBIndex> IDBObjectStore::createIndex(ScriptState* scriptState, const String& name, const IDBKeyPath& keyPath, const Dictionary& options, ExceptionState& exceptionState)
400 options.get("unique", unique);
402 bool multiEntry = false;
403 options.get("multiEntry", multiEntry);
405 return createIndex(scriptState, name, keyPath, unique, multiEntry, exceptionState);
408 PassRefPtrWillBeRawPtr<IDBIndex> IDBObjectStore::createIndex(ScriptState* scriptState, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry, ExceptionState& exceptionState)
410 IDB_TRACE("IDBObjectStore::createIndex");
411 if (!m_transaction->isVersionChange()) {
412 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVersionChangeTransactionErrorMessage);
416 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage);
419 if (m_transaction->isFinished() || m_transaction->isFinishing()) {
420 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
423 if (!m_transaction->isActive()) {
424 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
427 if (!keyPath.isValid()) {
428 exceptionState.throwDOMException(SyntaxError, "The keyPath argument contains an invalid key path.");
432 exceptionState.throwTypeError("The name provided is null.");
435 if (containsIndex(name)) {
436 exceptionState.throwDOMException(ConstraintError, "An index with the specified name already exists.");
440 if (keyPath.type() == IDBKeyPath::ArrayType && multiEntry) {
441 exceptionState.throwDOMException(InvalidAccessError, "The keyPath argument was an array and the multiEntry option is true.");
445 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
449 int64_t indexId = m_metadata.maxIndexId + 1;
450 backendDB()->createIndex(m_transaction->id(), id(), indexId, name, keyPath, unique, multiEntry);
452 ++m_metadata.maxIndexId;
454 IDBIndexMetadata metadata(name, indexId, keyPath, unique, multiEntry);
455 RefPtrWillBeRawPtr<IDBIndex> index = IDBIndex::create(metadata, this, m_transaction.get());
456 m_indexMap.set(name, index);
457 m_metadata.indexes.set(indexId, metadata);
458 m_transaction->db()->indexCreated(id(), metadata);
460 ASSERT(!exceptionState.hadException());
461 if (exceptionState.hadException())
464 RefPtrWillBeRawPtr<IDBRequest> indexRequest = openCursor(scriptState->executionContext(), static_cast<IDBKeyRange*>(0), blink::WebIDBCursor::Next, WebIDBDatabase::PreemptiveTask);
465 indexRequest->preventPropagation();
467 // This is kept alive by being the success handler of the request, which is in turn kept alive by the owning transaction.
468 RefPtr<IndexPopulator> indexPopulator = IndexPopulator::create(scriptState, transaction()->db(), m_transaction->id(), id(), metadata);
469 indexRequest->setOnsuccess(indexPopulator);
470 return index.release();
473 PassRefPtrWillBeRawPtr<IDBIndex> IDBObjectStore::index(const String& name, ExceptionState& exceptionState)
475 IDB_TRACE("IDBObjectStore::index");
477 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage);
480 if (m_transaction->isFinished() || m_transaction->isFinishing()) {
481 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::transactionFinishedErrorMessage);
485 IDBIndexMap::iterator it = m_indexMap.find(name);
486 if (it != m_indexMap.end())
489 int64_t indexId = findIndexId(name);
490 if (indexId == IDBIndexMetadata::InvalidId) {
491 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchIndexErrorMessage);
495 const IDBIndexMetadata* indexMetadata(0);
496 for (IDBObjectStoreMetadata::IndexMap::const_iterator it = m_metadata.indexes.begin(); it != m_metadata.indexes.end(); ++it) {
497 if (it->value.name == name) {
498 indexMetadata = &it->value;
502 ASSERT(indexMetadata);
503 ASSERT(indexMetadata->id != IDBIndexMetadata::InvalidId);
505 RefPtrWillBeRawPtr<IDBIndex> index = IDBIndex::create(*indexMetadata, this, m_transaction.get());
506 m_indexMap.set(name, index);
507 return index.release();
510 void IDBObjectStore::deleteIndex(const String& name, ExceptionState& exceptionState)
512 IDB_TRACE("IDBObjectStore::deleteIndex");
513 if (!m_transaction->isVersionChange()) {
514 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVersionChangeTransactionErrorMessage);
518 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage);
521 if (m_transaction->isFinished() || m_transaction->isFinishing()) {
522 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
525 if (!m_transaction->isActive()) {
526 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
529 int64_t indexId = findIndexId(name);
530 if (indexId == IDBIndexMetadata::InvalidId) {
531 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchIndexErrorMessage);
535 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
539 backendDB()->deleteIndex(m_transaction->id(), id(), indexId);
541 m_metadata.indexes.remove(indexId);
542 m_transaction->db()->indexDeleted(id(), indexId);
543 IDBIndexMap::iterator it = m_indexMap.find(name);
544 if (it != m_indexMap.end()) {
545 it->value->markDeleted();
546 m_indexMap.remove(name);
550 PassRefPtrWillBeRawPtr<IDBRequest> IDBObjectStore::openCursor(ExecutionContext* context, const ScriptValue& range, const String& directionString, ExceptionState& exceptionState)
552 IDB_TRACE("IDBObjectStore::openCursor");
554 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage);
557 if (m_transaction->isFinished() || m_transaction->isFinishing()) {
558 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
561 if (!m_transaction->isActive()) {
562 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
566 WebIDBCursor::Direction direction = IDBCursor::stringToDirection(directionString, exceptionState);
567 if (exceptionState.hadException())
570 RefPtrWillBeRawPtr<IDBKeyRange> keyRange = IDBKeyRange::fromScriptValue(context, range, exceptionState);
571 if (exceptionState.hadException())
575 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
579 return openCursor(context, keyRange, direction, WebIDBDatabase::NormalTask);
582 PassRefPtrWillBeRawPtr<IDBRequest> IDBObjectStore::openCursor(ExecutionContext* context, PassRefPtrWillBeRawPtr<IDBKeyRange> range, WebIDBCursor::Direction direction, WebIDBDatabase::TaskType taskType)
584 RefPtrWillBeRawPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
585 request->setCursorDetails(IndexedDB::CursorKeyAndValue, direction);
587 backendDB()->openCursor(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, range, direction, false, taskType, WebIDBCallbacksImpl::create(request).leakPtr());
588 return request.release();
591 PassRefPtrWillBeRawPtr<IDBRequest> IDBObjectStore::openKeyCursor(ExecutionContext* context, const ScriptValue& range, const String& directionString, ExceptionState& exceptionState)
593 IDB_TRACE("IDBObjectStore::openKeyCursor");
595 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage);
598 if (m_transaction->isFinished() || m_transaction->isFinishing()) {
599 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
602 if (!m_transaction->isActive()) {
603 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
607 WebIDBCursor::Direction direction = IDBCursor::stringToDirection(directionString, exceptionState);
608 if (exceptionState.hadException())
611 RefPtrWillBeRawPtr<IDBKeyRange> keyRange = IDBKeyRange::fromScriptValue(context, range, exceptionState);
612 if (exceptionState.hadException())
616 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
620 RefPtrWillBeRawPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
621 request->setCursorDetails(IndexedDB::CursorKeyOnly, direction);
623 backendDB()->openCursor(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, keyRange.release(), direction, true, WebIDBDatabase::NormalTask, WebIDBCallbacksImpl::create(request).leakPtr());
624 return request.release();
627 PassRefPtrWillBeRawPtr<IDBRequest> IDBObjectStore::count(ExecutionContext* context, const ScriptValue& range, ExceptionState& exceptionState)
629 IDB_TRACE("IDBObjectStore::count");
631 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage);
634 if (m_transaction->isFinished() || m_transaction->isFinishing()) {
635 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
638 if (!m_transaction->isActive()) {
639 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
643 RefPtrWillBeRawPtr<IDBKeyRange> keyRange = IDBKeyRange::fromScriptValue(context, range, exceptionState);
644 if (exceptionState.hadException())
648 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
652 RefPtrWillBeRawPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
653 backendDB()->count(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, keyRange.release(), WebIDBCallbacksImpl::create(request).leakPtr());
654 return request.release();
657 void IDBObjectStore::transactionFinished()
659 ASSERT(m_transaction->isFinished());
661 // Break reference cycles.
665 int64_t IDBObjectStore::findIndexId(const String& name) const
667 for (IDBObjectStoreMetadata::IndexMap::const_iterator it = m_metadata.indexes.begin(); it != m_metadata.indexes.end(); ++it) {
668 if (it->value.name == name) {
669 ASSERT(it->key != IDBIndexMetadata::InvalidId);
673 return IDBIndexMetadata::InvalidId;
676 WebIDBDatabase* IDBObjectStore::backendDB() const
678 return m_transaction->backendDB();
681 } // namespace WebCore