Title: [121291] trunk/Source/WebCore
Revision
121291
Author
jsb...@chromium.org
Date
2012-06-26 15:04:09 -0700 (Tue, 26 Jun 2012)

Log Message

IndexedDB: Move method precondition checks to front end objects
https://bugs.webkit.org/show_bug.cgi?id=89377

Reviewed by Tony Chang.

Now that metadata exists on the front end, most of the pre-condition validation checks
done on IDB method calls from script can be moved to the front end which simplifies the
code significantly in the case of complex methods like IDBObjectStore::put().

Adds an internal "active" flag for transactions, although the behavior is not accurate
to the spec (it should only be true during event callbacks - http://webkit.org/b/89379).
The back-end methods can then be simplifed to just adding async tasks to the transaction,
and the front end methods can take care of all exception cases except for asynchronous
transaction abort which still requires plumbing back to the front end.

No functional changes - no new tests.

* Modules/indexeddb/IDBCursor.cpp:
(WebCore::IDBCursor::update): Migrate from IDBObjectStoreBackendImpl::put.
(WebCore::IDBCursor::advance): Add more explicit transaction-is-active check.
(WebCore::IDBCursor::continueFunction): Ditto.
(WebCore::IDBCursor::deleteFunction): Ditto.
(WebCore::IDBCursor::effectiveObjectStore): Convenience function (source may be store or index).
(WebCore):
* Modules/indexeddb/IDBCursor.h:
(WebCore::IDBCursor::isKeyCursor): Distinguish from IDBCursorWithValue.
(IDBCursor):
* Modules/indexeddb/IDBCursorBackendImpl.cpp:
(WebCore::IDBCursorBackendImpl::update): Remove migrated check.
* Modules/indexeddb/IDBCursorWithValue.h:
(IDBCursorWithValue):
* Modules/indexeddb/IDBDatabase.cpp: Migrate checks.
(WebCore::IDBDatabase::createObjectStore):
(WebCore::IDBDatabase::deleteObjectStore):
* Modules/indexeddb/IDBDatabaseBackendImpl.cpp: Replace checks with assertions.
(WebCore::IDBDatabaseBackendImpl::createObjectStore):
(WebCore::IDBDatabaseBackendImpl::deleteObjectStore):
* Modules/indexeddb/IDBIndex.cpp: Add transaction-is-active checks.
(WebCore::IDBIndex::openCursor):
(WebCore::IDBIndex::count):
(WebCore::IDBIndex::openKeyCursor):
(WebCore::IDBIndex::get):
(WebCore::IDBIndex::getKey):
* Modules/indexeddb/IDBObjectStore.cpp: Migrate cehcks.
(WebCore::IDBObjectStore::get):
(WebCore::IDBObjectStore::add): Delegates to put(PutMode)
(WebCore::IDBObjectStore::put): Delegates to put(PutMode)
(WebCore): Adds put(PutMode) which has the unified checks migrated from
IDBObjectStoreBackendImpl::put.
(WebCore::IDBObjectStore::deleteFunction):
(WebCore::IDBObjectStore::clear):
(WebCore::IDBObjectStore::createIndex):
(WebCore::IDBObjectStore::deleteIndex):
(WebCore::IDBObjectStore::openCursor):
(WebCore::IDBObjectStore::count):
* Modules/indexeddb/IDBObjectStore.h: Adds put(PutMode).
(IDBObjectStore):
* Modules/indexeddb/IDBObjectStoreBackendImpl.cpp:
(WebCore::IDBObjectStoreBackendImpl::getInternal): Fix trace symbol.
(WebCore::IDBObjectStoreBackendImpl::put): Remove migrated checks.
(WebCore::IDBObjectStoreBackendImpl::createIndex): Remove migrated checks.
(WebCore::IDBObjectStoreBackendImpl::deleteIndex): Remove migrated checks.
* Modules/indexeddb/IDBTransaction.cpp: Add active flag tracking.
(WebCore::IDBTransaction::IDBTransaction):
(WebCore::IDBTransaction::abort):
(WebCore::IDBTransaction::onAbort):
(WebCore::IDBTransaction::onComplete):
* Modules/indexeddb/IDBTransaction.h:
(WebCore::IDBTransaction::isActive):
(WebCore::IDBTransaction::isReadOnly): Group IDL/non-IDL methods.
(IDBTransaction):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (121290 => 121291)


--- trunk/Source/WebCore/ChangeLog	2012-06-26 21:46:34 UTC (rev 121290)
+++ trunk/Source/WebCore/ChangeLog	2012-06-26 22:04:09 UTC (rev 121291)
@@ -1,3 +1,77 @@
+2012-06-26  Joshua Bell  <jsb...@chromium.org>
+
+        IndexedDB: Move method precondition checks to front end objects
+        https://bugs.webkit.org/show_bug.cgi?id=89377
+
+        Reviewed by Tony Chang.
+
+        Now that metadata exists on the front end, most of the pre-condition validation checks
+        done on IDB method calls from script can be moved to the front end which simplifies the
+        code significantly in the case of complex methods like IDBObjectStore::put().
+
+        Adds an internal "active" flag for transactions, although the behavior is not accurate
+        to the spec (it should only be true during event callbacks - http://webkit.org/b/89379).
+        The back-end methods can then be simplifed to just adding async tasks to the transaction,
+        and the front end methods can take care of all exception cases except for asynchronous
+        transaction abort which still requires plumbing back to the front end.
+
+        No functional changes - no new tests.
+
+        * Modules/indexeddb/IDBCursor.cpp:
+        (WebCore::IDBCursor::update): Migrate from IDBObjectStoreBackendImpl::put.
+        (WebCore::IDBCursor::advance): Add more explicit transaction-is-active check.
+        (WebCore::IDBCursor::continueFunction): Ditto.
+        (WebCore::IDBCursor::deleteFunction): Ditto.
+        (WebCore::IDBCursor::effectiveObjectStore): Convenience function (source may be store or index).
+        (WebCore):
+        * Modules/indexeddb/IDBCursor.h:
+        (WebCore::IDBCursor::isKeyCursor): Distinguish from IDBCursorWithValue.
+        (IDBCursor):
+        * Modules/indexeddb/IDBCursorBackendImpl.cpp:
+        (WebCore::IDBCursorBackendImpl::update): Remove migrated check.
+        * Modules/indexeddb/IDBCursorWithValue.h:
+        (IDBCursorWithValue):
+        * Modules/indexeddb/IDBDatabase.cpp: Migrate checks.
+        (WebCore::IDBDatabase::createObjectStore):
+        (WebCore::IDBDatabase::deleteObjectStore):
+        * Modules/indexeddb/IDBDatabaseBackendImpl.cpp: Replace checks with assertions.
+        (WebCore::IDBDatabaseBackendImpl::createObjectStore):
+        (WebCore::IDBDatabaseBackendImpl::deleteObjectStore):
+        * Modules/indexeddb/IDBIndex.cpp: Add transaction-is-active checks.
+        (WebCore::IDBIndex::openCursor):
+        (WebCore::IDBIndex::count):
+        (WebCore::IDBIndex::openKeyCursor):
+        (WebCore::IDBIndex::get):
+        (WebCore::IDBIndex::getKey):
+        * Modules/indexeddb/IDBObjectStore.cpp: Migrate cehcks.
+        (WebCore::IDBObjectStore::get):
+        (WebCore::IDBObjectStore::add): Delegates to put(PutMode)
+        (WebCore::IDBObjectStore::put): Delegates to put(PutMode)
+        (WebCore): Adds put(PutMode) which has the unified checks migrated from
+        IDBObjectStoreBackendImpl::put.
+        (WebCore::IDBObjectStore::deleteFunction):
+        (WebCore::IDBObjectStore::clear):
+        (WebCore::IDBObjectStore::createIndex):
+        (WebCore::IDBObjectStore::deleteIndex):
+        (WebCore::IDBObjectStore::openCursor):
+        (WebCore::IDBObjectStore::count):
+        * Modules/indexeddb/IDBObjectStore.h: Adds put(PutMode).
+        (IDBObjectStore):
+        * Modules/indexeddb/IDBObjectStoreBackendImpl.cpp:
+        (WebCore::IDBObjectStoreBackendImpl::getInternal): Fix trace symbol.
+        (WebCore::IDBObjectStoreBackendImpl::put): Remove migrated checks.
+        (WebCore::IDBObjectStoreBackendImpl::createIndex): Remove migrated checks.
+        (WebCore::IDBObjectStoreBackendImpl::deleteIndex): Remove migrated checks.
+        * Modules/indexeddb/IDBTransaction.cpp: Add active flag tracking.
+        (WebCore::IDBTransaction::IDBTransaction):
+        (WebCore::IDBTransaction::abort):
+        (WebCore::IDBTransaction::onAbort):
+        (WebCore::IDBTransaction::onComplete):
+        * Modules/indexeddb/IDBTransaction.h:
+        (WebCore::IDBTransaction::isActive):
+        (WebCore::IDBTransaction::isReadOnly): Group IDL/non-IDL methods.
+        (IDBTransaction):
+
 2012-06-26  Sheriff Bot  <webkit.review....@gmail.com>
 
         Unreviewed, rolling out r121285.

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp (121290 => 121291)


--- trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp	2012-06-26 21:46:34 UTC (rev 121290)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp	2012-06-26 22:04:09 UTC (rev 121291)
@@ -29,9 +29,11 @@
 #if ENABLE(INDEXED_DATABASE)
 
 #include "IDBAny.h"
+#include "IDBBindingUtilities.h"
 #include "IDBCallbacks.h"
 #include "IDBCursorBackendInterface.h"
 #include "IDBKey.h"
+#include "IDBObjectStore.h"
 #include "IDBRequest.h"
 #include "IDBTracing.h"
 #include "IDBTransaction.h"
@@ -125,24 +127,37 @@
 PassRefPtr<IDBRequest> IDBCursor::update(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> prpValue, ExceptionCode& ec)
 {
     IDB_TRACE("IDBCursor::update");
+    RefPtr<SerializedScriptValue> value = prpValue;
 
-    if (!m_gotValue) {
+    if (!m_gotValue || isKeyCursor()) {
         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
         return 0;
     }
-
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return 0;
+    }
     if (m_transaction->isReadOnly()) {
         ec = IDBDatabaseException::READ_ONLY_ERR;
         return 0;
     }
-
-    RefPtr<SerializedScriptValue> value = prpValue;
     if (value->blobURLs().size() > 0) {
         // FIXME: Add Blob/File/FileList support
         ec = IDBDatabaseException::IDB_DATA_CLONE_ERR;
         return 0;
     }
 
+    RefPtr<IDBObjectStore> objectStore = effectiveObjectStore();
+    const IDBKeyPath& keyPath = objectStore->metadata().keyPath;
+    const bool usesInLineKeys = !keyPath.isNull();
+    if (usesInLineKeys) {
+        RefPtr<IDBKey> keyPathKey = createIDBKeyFromSerializedValueAndKeyPath(value, keyPath);
+        if (!keyPathKey || !keyPathKey->isEqual(m_currentPrimaryKey.get())) {
+            ec = IDBDatabaseException::DATA_ERR;
+            return 0;
+        }
+    }
+
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
     m_backend->update(value, request, ec);
     if (ec) {
@@ -160,7 +175,7 @@
         return;
     }
 
-    if (!m_request) {
+    if (!m_transaction->isActive()) {
         ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
         return;
     }
@@ -188,7 +203,7 @@
         return;
     }
 
-    if (!m_request) {
+    if (!m_transaction->isActive()) {
         ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
         return;
     }
@@ -213,6 +228,10 @@
 PassRefPtr<IDBRequest> IDBCursor::deleteFunction(ScriptExecutionContext* context, ExceptionCode& ec)
 {
     IDB_TRACE("IDBCursor::delete");
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return 0;
+    }
     if (m_transaction->isReadOnly()) {
         ec = IDBDatabaseException::READ_ONLY_ERR;
         return 0;
@@ -252,6 +271,14 @@
     m_valueIsDirty = true;
 }
 
+PassRefPtr<IDBObjectStore> IDBCursor::effectiveObjectStore()
+{
+    if (m_source->type() == IDBAny::IDBObjectStoreType)
+        return m_source->idbObjectStore();
+    RefPtr<IDBIndex> index = m_source->idbIndex();
+    return index->objectStore();
+}
+
 unsigned short IDBCursor::stringToDirection(const String& directionString, ExceptionCode& ec)
 {
     if (directionString == IDBCursor::directionNext())

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBCursor.h (121290 => 121291)


--- trunk/Source/WebCore/Modules/indexeddb/IDBCursor.h	2012-06-26 21:46:34 UTC (rev 121290)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBCursor.h	2012-06-26 22:04:09 UTC (rev 121291)
@@ -91,8 +91,11 @@
 
 protected:
     IDBCursor(PassRefPtr<IDBCursorBackendInterface>, IDBRequest*, IDBAny* source, IDBTransaction*);
+    virtual bool isKeyCursor() const { return true; }
 
 private:
+    PassRefPtr<IDBObjectStore> effectiveObjectStore();
+
     RefPtr<IDBCursorBackendInterface> m_backend;
     RefPtr<IDBRequest> m_request;
     RefPtr<IDBAny> m_source;

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBCursorBackendImpl.cpp (121290 => 121291)


--- trunk/Source/WebCore/Modules/indexeddb/IDBCursorBackendImpl.cpp	2012-06-26 21:46:34 UTC (rev 121290)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBCursorBackendImpl.cpp	2012-06-26 22:04:09 UTC (rev 121291)
@@ -93,11 +93,10 @@
 {
     IDB_TRACE("IDBCursorBackendImpl::update");
     ASSERT(m_transaction->mode() != IDBTransaction::READ_ONLY);
-    if (!m_cursor || m_cursorType == IndexKeyCursor) {
-        ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
-        return;
-    }
 
+    ASSERT(m_cursor);
+    ASSERT(m_cursorType != IndexKeyCursor);
+
     m_objectStore->put(value, m_cursor->primaryKey(), IDBObjectStoreBackendInterface::CursorUpdate, callbacks, m_transaction.get(), ec);
 }
 

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBCursorWithValue.h (121290 => 121291)


--- trunk/Source/WebCore/Modules/indexeddb/IDBCursorWithValue.h	2012-06-26 21:46:34 UTC (rev 121290)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBCursorWithValue.h	2012-06-26 22:04:09 UTC (rev 121291)
@@ -41,6 +41,9 @@
     // The value attribute defined in the IDL is simply implemented in IDBCursor (but not exposed via
     // its IDL). This is to make the implementation more simple while matching what the spec says.
 
+protected:
+    virtual bool isKeyCursor() const OVERRIDE { return false; }
+
 private:
     IDBCursorWithValue(PassRefPtr<IDBCursorBackendInterface>, IDBRequest*, IDBAny* source, IDBTransaction*);
 };

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.cpp (121290 => 121291)


--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.cpp	2012-06-26 21:46:34 UTC (rev 121290)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.cpp	2012-06-26 22:04:09 UTC (rev 121291)
@@ -117,6 +117,10 @@
         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
         return 0;
     }
+    if (!m_versionChangeTransaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return 0;
+    }
 
     IDBKeyPath keyPath;
     if (!options.isUndefinedOrNull()) {
@@ -128,6 +132,11 @@
             keyPath = IDBKeyPath(keyPathString);
     }
 
+    if (m_metadata.objectStores.contains(name)) {
+        ec = IDBDatabaseException::CONSTRAINT_ERR;
+        return 0;
+    }
+
     if (!keyPath.isNull() && !keyPath.isValid()) {
         ec = IDBDatabaseException::IDB_SYNTAX_ERR;
         return 0;
@@ -162,6 +171,14 @@
         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
         return;
     }
+    if (!m_versionChangeTransaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return;
+    }
+    if (!m_metadata.objectStores.contains(name)) {
+        ec = IDBDatabaseException::IDB_NOT_FOUND_ERR;
+        return;
+    }
 
     m_backend->deleteObjectStore(name, m_versionChangeTransaction->backend(), ec);
     if (!ec) {

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp (121290 => 121291)


--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp	2012-06-26 21:46:34 UTC (rev 121290)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp	2012-06-26 22:04:09 UTC (rev 121291)
@@ -145,10 +145,7 @@
 PassRefPtr<IDBObjectStoreBackendInterface> IDBDatabaseBackendImpl::createObjectStore(const String& name, const IDBKeyPath& keyPath, bool autoIncrement, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec)
 {
     ASSERT(transactionPtr->mode() == IDBTransaction::VERSION_CHANGE);
-    if (m_objectStores.contains(name)) {
-        ec = IDBDatabaseException::CONSTRAINT_ERR;
-        return 0;
-    }
+    ASSERT(!m_objectStores.contains(name));
 
     RefPtr<IDBObjectStoreBackendImpl> objectStore = IDBObjectStoreBackendImpl::create(this, name, keyPath, autoIncrement);
     ASSERT(objectStore->name() == name);
@@ -186,12 +183,10 @@
 void IDBDatabaseBackendImpl::deleteObjectStore(const String& name, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec)
 {
     ASSERT(transactionPtr->mode() == IDBTransaction::VERSION_CHANGE);
-    RefPtr<IDBObjectStoreBackendImpl> objectStore = m_objectStores.get(name);
-    if (!objectStore) {
-        ec = IDBDatabaseException::IDB_NOT_FOUND_ERR;
-        return;
-    }
+    ASSERT(m_objectStores.contains(name));
+
     RefPtr<IDBDatabaseBackendImpl> database = this;
+    RefPtr<IDBObjectStoreBackendImpl> objectStore = m_objectStores.get(name);
     RefPtr<IDBTransactionBackendInterface> transaction = transactionPtr;
     if (!transaction->scheduleTask(createCallbackTask(&IDBDatabaseBackendImpl::deleteObjectStoreInternal, database, objectStore, transaction),
                                    createCallbackTask(&IDBDatabaseBackendImpl::addObjectStoreToMap, database, objectStore))) {

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBIndex.cpp (121290 => 121291)


--- trunk/Source/WebCore/Modules/indexeddb/IDBIndex.cpp	2012-06-26 21:46:34 UTC (rev 121290)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBIndex.cpp	2012-06-26 22:04:09 UTC (rev 121291)
@@ -65,6 +65,10 @@
         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
         return 0;
     }
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return 0;
+    }
     unsigned short direction = IDBCursor::stringToDirection(directionString, ec);
     if (ec)
         return 0;
@@ -115,6 +119,10 @@
         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
         return 0;
     }
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return 0;
+    }
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
     m_backend->count(keyRange, request, m_transaction->backend(), ec);
     if (ec) {
@@ -140,6 +148,10 @@
         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
         return 0;
     }
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return 0;
+    }
 
     unsigned short direction = IDBCursor::stringToDirection(directionString, ec);
     if (ec)
@@ -200,6 +212,10 @@
         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
         return 0;
     }
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return 0;
+    }
     if (!keyRange) {
         ec = IDBDatabaseException::DATA_ERR;
         return 0;
@@ -231,6 +247,10 @@
         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
         return 0;
     }
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return 0;
+    }
     if (!keyRange) {
         ec = IDBDatabaseException::DATA_ERR;
         return 0;

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp (121290 => 121291)


--- trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp	2012-06-26 21:46:34 UTC (rev 121290)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp	2012-06-26 22:04:09 UTC (rev 121291)
@@ -30,6 +30,7 @@
 
 #include "DOMStringList.h"
 #include "IDBAny.h"
+#include "IDBBindingUtilities.h"
 #include "IDBDatabase.h"
 #include "IDBDatabaseException.h"
 #include "IDBIndex.h"
@@ -78,6 +79,10 @@
         ec = IDBDatabaseException::DATA_ERR;
         return 0;
     }
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return 0;
+    }
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
     m_backend->get(keyRange, request, m_transaction->backend(), ec);
     if (ec) {
@@ -96,65 +101,80 @@
     return get(context, keyRange.release(), ec);
 }
 
-PassRefPtr<IDBRequest> IDBObjectStore::add(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> key, ExceptionCode& ec)
+PassRefPtr<IDBRequest> IDBObjectStore::add(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, ExceptionCode& ec)
 {
     IDB_TRACE("IDBObjectStore::add");
+    return put(IDBObjectStoreBackendInterface::AddOnly, context, value, key, ec);
+}
+
+PassRefPtr<IDBRequest> IDBObjectStore::put(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, ExceptionCode& ec)
+{
+    IDB_TRACE("IDBObjectStore::put");
+    return put(IDBObjectStoreBackendInterface::AddOrUpdate, context, value, key, ec);
+}
+
+PassRefPtr<IDBRequest> IDBObjectStore::put(IDBObjectStoreBackendInterface::PutMode putMode, ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, ExceptionCode& ec)
+{
+    IDB_TRACE("IDBObjectStore::put");
+    RefPtr<SerializedScriptValue> value = prpValue;
+    RefPtr<IDBKey> key = prpKey;
     if (m_deleted) {
         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
         return 0;
     }
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return 0;
+    }
     if (m_transaction->isReadOnly()) {
         ec = IDBDatabaseException::READ_ONLY_ERR;
         return 0;
     }
-
-    if (key && !key->isValid()) {
-        ec = IDBDatabaseException::DATA_ERR;
-        return 0;
-    }
-
-    RefPtr<SerializedScriptValue> value = prpValue;
     if (value->blobURLs().size() > 0) {
         // FIXME: Add Blob/File/FileList support
         ec = IDBDatabaseException::IDB_DATA_CLONE_ERR;
         return 0;
     }
 
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
-    m_backend->put(value, key, IDBObjectStoreBackendInterface::AddOnly, request, m_transaction->backend(), ec);
-    if (ec) {
-        request->markEarlyDeath();
-        return 0;
-    }
-    return request.release();
-}
+    const IDBKeyPath& keyPath = m_metadata.keyPath;
+    const bool usesInLineKeys = !keyPath.isNull();
+    const bool hasKeyGenerator = autoIncrement();
 
-PassRefPtr<IDBRequest> IDBObjectStore::put(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> key, ExceptionCode& ec)
-{
-    IDB_TRACE("IDBObjectStore::put");
-    if (m_deleted) {
-        ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
+    if (usesInLineKeys && key) {
+        ec = IDBDatabaseException::DATA_ERR;
         return 0;
     }
-    if (m_transaction->isReadOnly()) {
-        ec = IDBDatabaseException::READ_ONLY_ERR;
+    if (!usesInLineKeys && !hasKeyGenerator && !key) {
+        ec = IDBDatabaseException::DATA_ERR;
         return 0;
     }
-
+    if (usesInLineKeys) {
+        RefPtr<IDBKey> keyPathKey = createIDBKeyFromSerializedValueAndKeyPath(value, keyPath);
+        if (keyPathKey && !keyPathKey->isValid()) {
+            ec = IDBDatabaseException::DATA_ERR;
+            return 0;
+        }
+        if (!hasKeyGenerator && !keyPathKey) {
+            ec = IDBDatabaseException::DATA_ERR;
+            return 0;
+        }
+        if (hasKeyGenerator && !keyPathKey) {
+            RefPtr<IDBKey> dummyKey = IDBKey::createNumber(-1);
+            RefPtr<SerializedScriptValue> valueAfterInjection = injectIDBKeyIntoSerializedValue(dummyKey, value, keyPath);
+            if (!valueAfterInjection) {
+                ec = IDBDatabaseException::DATA_ERR;
+                return 0;
+            }
+        }
+    }
     if (key && !key->isValid()) {
         ec = IDBDatabaseException::DATA_ERR;
         return 0;
     }
 
-    RefPtr<SerializedScriptValue> value = prpValue;
-    if (value->blobURLs().size() > 0) {
-        // FIXME: Add Blob/File/FileList support
-        ec = IDBDatabaseException::IDB_DATA_CLONE_ERR;
-        return 0;
-    }
-
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
-    m_backend->put(value, key, IDBObjectStoreBackendInterface::AddOrUpdate, request, m_transaction->backend(), ec);
+    // FIXME: Pass through keyPathKey as key to simplify back end implementation.
+    m_backend->put(value.release(), key.release(), putMode, request, m_transaction->backend(), ec);
     if (ec) {
         request->markEarlyDeath();
         return 0;
@@ -169,11 +189,14 @@
         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
         return 0;
     }
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return 0;
+    }
     if (m_transaction->isReadOnly()) {
         ec = IDBDatabaseException::READ_ONLY_ERR;
         return 0;
     }
-
     if (!keyRange) {
         ec = IDBDatabaseException::DATA_ERR;
         return 0;
@@ -204,6 +227,10 @@
         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
         return 0;
     }
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return 0;
+    }
     if (m_transaction->isReadOnly()) {
         ec = IDBDatabaseException::READ_ONLY_ERR;
         return 0;
@@ -239,11 +266,22 @@
         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
         return 0;
     }
-
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return 0;
+    }
     if (!keyPath.isValid()) {
         ec = IDBDatabaseException::IDB_SYNTAX_ERR;
         return 0;
     }
+    if (name.isNull()) {
+        ec = IDBDatabaseException::IDB_TYPE_ERR;
+        return 0;
+    }
+    if (m_metadata.indexes.contains(name)) {
+        ec = IDBDatabaseException::CONSTRAINT_ERR;
+        return 0;
+    }
 
     bool unique = false;
     options.get("unique", unique);
@@ -304,6 +342,14 @@
         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
         return;
     }
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return;
+    }
+    if (!m_metadata.indexes.contains(name)) {
+        ec = IDBDatabaseException::IDB_NOT_FOUND_ERR;
+        return;
+    }
 
     m_backend->deleteIndex(name, m_transaction->backend(), ec);
     if (!ec) {
@@ -325,6 +371,10 @@
         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
         return 0;
     }
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return 0;
+    }
     unsigned short direction = IDBCursor::stringToDirection(directionString, ec);
     if (ec)
         return 0;
@@ -375,6 +425,10 @@
         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
         return 0;
     }
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+        return 0;
+    }
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
     m_backend->count(range, request, m_transaction->backend(), ec);
     if (ec) {

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.h (121290 => 121291)


--- trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.h	2012-06-26 21:46:34 UTC (rev 121290)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.h	2012-06-26 22:04:09 UTC (rev 121291)
@@ -95,6 +95,7 @@
     PassRefPtr<IDBRequest> count(ScriptExecutionContext*, PassRefPtr<IDBKeyRange>, ExceptionCode&);
     PassRefPtr<IDBRequest> count(ScriptExecutionContext*, PassRefPtr<IDBKey>, ExceptionCode&);
 
+    PassRefPtr<IDBRequest> put(IDBObjectStoreBackendInterface::PutMode, ScriptExecutionContext*, PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, ExceptionCode&);
     void markDeleted() { m_deleted = true; }
     void transactionFinished();
 
@@ -103,7 +104,6 @@
 
 private:
     IDBObjectStore(const IDBObjectStoreMetadata&, PassRefPtr<IDBObjectStoreBackendInterface>, IDBTransaction*);
-    void removeTransactionFromPendingList();
 
     IDBObjectStoreMetadata m_metadata;
     RefPtr<IDBObjectStoreBackendInterface> m_backend;

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.cpp (121290 => 121291)


--- trunk/Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.cpp	2012-06-26 21:46:34 UTC (rev 121290)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.cpp	2012-06-26 22:04:09 UTC (rev 121291)
@@ -42,7 +42,7 @@
 #include "IDBKeyPathBackendImpl.h"
 #include "IDBKeyRange.h"
 #include "IDBTracing.h"
-#include "IDBTransactionBackendInterface.h"
+#include "IDBTransactionBackendImpl.h"
 #include "ScriptExecutionContext.h"
 
 namespace WebCore {
@@ -92,7 +92,7 @@
 
 void IDBObjectStoreBackendImpl::getInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKeyRange> keyRange, PassRefPtr<IDBCallbacks> callbacks)
 {
-    IDB_TRACE("IDBObjectStoreBackendImpl::getByRangeInternal");
+    IDB_TRACE("IDBObjectStoreBackendImpl::getInternal");
     RefPtr<IDBKey> key;
     if (keyRange->isOnlyKey())
         key = keyRange->lower();
@@ -148,53 +148,6 @@
     RefPtr<IDBCallbacks> callbacks = prpCallbacks;
     RefPtr<IDBTransactionBackendInterface> transaction = transactionPtr;
 
-    if (putMode != CursorUpdate) {
-        const bool autoIncrement = objectStore->autoIncrement();
-        const bool hasKeyPath = !objectStore->m_keyPath.isNull();
-
-        if (hasKeyPath && key) {
-            ec = IDBDatabaseException::DATA_ERR;
-            return;
-        }
-        if (!hasKeyPath && !autoIncrement && !key) {
-            ec = IDBDatabaseException::DATA_ERR;
-            return;
-        }
-        if (hasKeyPath) {
-            RefPtr<IDBKey> keyPathKey = fetchKeyFromKeyPath(value.get(), objectStore->m_keyPath);
-            if (keyPathKey && !keyPathKey->isValid()) {
-                ec = IDBDatabaseException::DATA_ERR;
-                return;
-            }
-            if (!autoIncrement && !keyPathKey) {
-                ec = IDBDatabaseException::DATA_ERR;
-                return;
-            }
-            if (autoIncrement && !keyPathKey) {
-                RefPtr<IDBKey> dummyKey = IDBKey::createNumber(-1);
-                RefPtr<SerializedScriptValue> valueAfterInjection = injectKeyIntoKeyPath(dummyKey, value, objectStore->m_keyPath);
-                if (!valueAfterInjection) {
-                    ec = IDBDatabaseException::DATA_ERR;
-                    return;
-                }
-            }
-        }
-        if (key && !key->isValid()) {
-            ec = IDBDatabaseException::DATA_ERR;
-            return;
-        }
-    } else {
-        ASSERT(key);
-        const bool hasKeyPath = !objectStore->m_keyPath.isNull();
-        if (hasKeyPath) {
-            RefPtr<IDBKey> keyPathKey = fetchKeyFromKeyPath(value.get(), objectStore->m_keyPath);
-            if (!keyPathKey || !keyPathKey->isEqual(key.get())) {
-                ec = IDBDatabaseException::DATA_ERR;
-                return;
-            }
-        }
-    }
-
     if (!transaction->scheduleTask(
             createCallbackTask(&IDBObjectStoreBackendImpl::putInternal, objectStore, value, key, putMode, callbacks, transaction),
             // FIXME: One of these per put() is overkill, since it's simply a cache invalidation.
@@ -459,18 +412,8 @@
 
 PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::createIndex(const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
 {
-    if (name.isNull()) {
-        ec = IDBDatabaseException::IDB_TYPE_ERR;
-        return 0;
-    }
-    if (m_indexes.contains(name)) {
-        ec = IDBDatabaseException::CONSTRAINT_ERR;
-        return 0;
-    }
-    if (transaction->mode() != IDBTransaction::VERSION_CHANGE) {
-        ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
-        return 0;
-    }
+    ASSERT(transaction->mode() == IDBTransaction::VERSION_CHANGE);
+    ASSERT(!m_indexes.contains(name));
 
     RefPtr<IDBIndexBackendImpl> index = IDBIndexBackendImpl::create(m_database, this, name, keyPath, unique, multiEntry);
     ASSERT(index->name() == name);
@@ -520,18 +463,11 @@
 
 void IDBObjectStoreBackendImpl::deleteIndex(const String& name, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
 {
-    if (transaction->mode() != IDBTransaction::VERSION_CHANGE) {
-        ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
-        return;
-    }
+    ASSERT(transaction->mode() == IDBTransaction::VERSION_CHANGE);
+    ASSERT(m_indexes.contains(name));
 
-    RefPtr<IDBIndexBackendImpl> index = m_indexes.get(name);
-    if (!index) {
-        ec = IDBDatabaseException::IDB_NOT_FOUND_ERR;
-        return;
-    }
-
     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
+    RefPtr<IDBIndexBackendImpl> index = m_indexes.get(name);
     RefPtr<IDBTransactionBackendInterface> transactionPtr = transaction;
     if (!transaction->scheduleTask(
               createCallbackTask(&IDBObjectStoreBackendImpl::deleteIndexInternal,

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp (121290 => 121291)


--- trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp	2012-06-26 21:46:34 UTC (rev 121290)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp	2012-06-26 22:04:09 UTC (rev 121291)
@@ -84,6 +84,7 @@
     , m_backend(backend)
     , m_database(db)
     , m_mode(mode)
+    , m_active(true)
     , m_transactionFinished(false)
     , m_contextStopped(false)
 {
@@ -193,6 +194,7 @@
 {
     if (m_transactionFinished)
         return;
+    m_active = false;
     RefPtr<IDBTransaction> selfRef = this;
     if (m_backend)
         m_backend->abort();
@@ -242,6 +244,7 @@
 void IDBTransaction::onAbort()
 {
     ASSERT(!m_transactionFinished);
+    m_active = false;
     while (!m_childRequests.isEmpty()) {
         IDBRequest* request = *m_childRequests.begin();
         m_childRequests.remove(request);
@@ -265,6 +268,7 @@
 void IDBTransaction::onComplete()
 {
     ASSERT(!m_transactionFinished);
+    m_active = false;
     m_objectStoreCleanupMap.clear();
     closeOpenCursors();
     m_database->transactionFinished(this);

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.h (121290 => 121291)


--- trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.h	2012-06-26 21:46:34 UTC (rev 121290)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.h	2012-06-26 22:04:09 UTC (rev 121291)
@@ -68,12 +68,13 @@
     static const AtomicString& modeToString(Mode, ExceptionCode&);
 
     IDBTransactionBackendInterface* backend() const;
+    bool isActive() const { return m_active; }
     bool isFinished() const;
+    bool isReadOnly() const { return m_mode == READ_ONLY; }
     bool isVersionChange() const { return m_mode == VERSION_CHANGE; }
 
     // Implement the IDBTransaction IDL
     const String& mode() const;
-    bool isReadOnly() const { return m_mode == READ_ONLY; }
     IDBDatabase* db() const;
     PassRefPtr<DOMError> error(ExceptionCode&) const;
     void setError(PassRefPtr<DOMError>);
@@ -135,6 +136,7 @@
     RefPtr<IDBTransactionBackendInterface> m_backend;
     RefPtr<IDBDatabase> m_database;
     const Mode m_mode;
+    bool m_active;
     bool m_transactionFinished; // Is it possible that we'll fire any more events or allow any new requests? If not, we're finished.
     bool m_contextStopped;
     RefPtr<DOMError> m_error;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to