Title: [133776] trunk
Revision
133776
Author
jsb...@chromium.org
Date
2012-11-07 10:26:18 -0800 (Wed, 07 Nov 2012)

Log Message

IndexedDB: Assertion failure with open() within upgradeneeded
https://bugs.webkit.org/show_bug.cgi?id=96947

Reviewed by Dimitri Glazkov.

Source/WebCore:

Postpone creation of the "pending second half open" until the version change
transaction has started.

Test: storage/indexeddb/unblocked-version-changes.html

* Modules/indexeddb/IDBDatabaseBackendImpl.cpp:
(WebCore::IDBDatabaseBackendImpl::setIntVersionInternal):
(WebCore::IDBDatabaseBackendImpl::runIntVersionChangeTransaction):
* Modules/indexeddb/IDBDatabaseBackendImpl.h:
(IDBDatabaseBackendImpl):
* Modules/indexeddb/IDBDatabaseCallbacks.h:

LayoutTests:

Exercise the code path leading to the assert by having a second version change transaction
unblocked by the first's connection closing. Includes a known failure due to metadata
snapshot timing.

* storage/indexeddb/resources/unblocked-version-changes.js: Added.
(test):
(openConnection):
(onUpgradeNeeded):
(onError):
(onUpgradeNeeded2):
(onSuccess):
* storage/indexeddb/unblocked-version-changes-expected.txt: Added.
* storage/indexeddb/unblocked-version-changes.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (133775 => 133776)


--- trunk/LayoutTests/ChangeLog	2012-11-07 18:20:53 UTC (rev 133775)
+++ trunk/LayoutTests/ChangeLog	2012-11-07 18:26:18 UTC (rev 133776)
@@ -1,3 +1,24 @@
+2012-11-07  Joshua Bell  <jsb...@chromium.org>
+
+        IndexedDB: Assertion failure with open() within upgradeneeded
+        https://bugs.webkit.org/show_bug.cgi?id=96947
+
+        Reviewed by Dimitri Glazkov.
+
+        Exercise the code path leading to the assert by having a second version change transaction
+        unblocked by the first's connection closing. Includes a known failure due to metadata
+        snapshot timing.
+
+        * storage/indexeddb/resources/unblocked-version-changes.js: Added.
+        (test):
+        (openConnection):
+        (onUpgradeNeeded):
+        (onError):
+        (onUpgradeNeeded2):
+        (onSuccess):
+        * storage/indexeddb/unblocked-version-changes-expected.txt: Added.
+        * storage/indexeddb/unblocked-version-changes.html: Added.
+
 2012-11-06  Simon Fraser  <simon.fra...@apple.com>
 
         Fix failing platform/mac/tiled-drawing on Lion.

Added: trunk/LayoutTests/storage/indexeddb/resources/unblocked-version-changes.js (0 => 133776)


--- trunk/LayoutTests/storage/indexeddb/resources/unblocked-version-changes.js	                        (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/resources/unblocked-version-changes.js	2012-11-07 18:26:18 UTC (rev 133776)
@@ -0,0 +1,62 @@
+if (this.importScripts) {
+    importScripts('../../../fast/js/resources/js-test-pre.js');
+    importScripts('shared.js');
+}
+
+description("Ensure that metadata remains correct when an aborted version change is followed by another. ");
+
+function test() {
+    removeVendorPrefixes();
+    setDBNameFromPath();
+    request = evalAndLog("indexedDB.deleteDatabase(dbname)");
+    request._onblocked_ = unexpectedBlockedCallback;
+    request._onerror_ = unexpectedErrorCallback;
+    request._onsuccess_ = openConnection;
+}
+
+function openConnection()
+{
+    preamble();
+    evalAndLog("request = indexedDB.open(dbname, 2)");
+    request._onblocked_ = unexpectedBlockedCallback;
+    request._onsuccess_ = unexpectedSuccessCallback;
+    request._onupgradeneeded_ = onUpgradeNeeded;
+    request._onerror_ = onError;
+}
+
+function onUpgradeNeeded(evt)
+{
+    preamble(evt);
+    evalAndLog("db = request.result");
+    shouldBe("db.version", "2");
+
+    evalAndLog("request = indexedDB.open(dbname, 3)");
+    request._onerror_ = unexpectedErrorCallback;
+    request._onupgradeneeded_ = onUpgradeNeeded2;
+    request._onsuccess_ = onSuccess;
+
+    evalAndLog("db.close()");
+}
+
+function onError(evt)
+{
+    preamble(evt);
+    shouldBe("db.version", "0");
+}
+
+function onUpgradeNeeded2(evt)
+{
+    preamble(evt);
+    evalAndLog("db = request.result");
+    shouldBe("db.version", "3");
+}
+
+function onSuccess(evt)
+{
+    preamble(evt);
+    evalAndLog("db = request.result");
+    shouldBe("db.version", "3");
+    finishJSTest();
+}
+
+test();
\ No newline at end of file

Added: trunk/LayoutTests/storage/indexeddb/unblocked-version-changes-expected.txt (0 => 133776)


--- trunk/LayoutTests/storage/indexeddb/unblocked-version-changes-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/unblocked-version-changes-expected.txt	2012-11-07 18:26:18 UTC (rev 133776)
@@ -0,0 +1,33 @@
+Ensure that metadata remains correct when an aborted version change is followed by another.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+
+dbname = "unblocked-version-changes.html"
+indexedDB.deleteDatabase(dbname)
+
+openConnection():
+request = indexedDB.open(dbname, 2)
+
+onUpgradeNeeded():
+db = request.result
+PASS db.version is 2
+request = indexedDB.open(dbname, 3)
+db.close()
+
+onError():
+FAIL db.version should be 0. Was 2.
+
+onUpgradeNeeded2():
+db = request.result
+PASS db.version is 3
+
+onSuccess():
+db = request.result
+PASS db.version is 3
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/storage/indexeddb/unblocked-version-changes.html (0 => 133776)


--- trunk/LayoutTests/storage/indexeddb/unblocked-version-changes.html	                        (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/unblocked-version-changes.html	2012-11-07 18:26:18 UTC (rev 133776)
@@ -0,0 +1,10 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (133775 => 133776)


--- trunk/Source/WebCore/ChangeLog	2012-11-07 18:20:53 UTC (rev 133775)
+++ trunk/Source/WebCore/ChangeLog	2012-11-07 18:26:18 UTC (rev 133776)
@@ -1,3 +1,22 @@
+2012-11-07  Joshua Bell  <jsb...@chromium.org>
+
+        IndexedDB: Assertion failure with open() within upgradeneeded
+        https://bugs.webkit.org/show_bug.cgi?id=96947
+
+        Reviewed by Dimitri Glazkov.
+
+        Postpone creation of the "pending second half open" until the version change
+        transaction has started.
+
+        Test: storage/indexeddb/unblocked-version-changes.html
+
+        * Modules/indexeddb/IDBDatabaseBackendImpl.cpp:
+        (WebCore::IDBDatabaseBackendImpl::setIntVersionInternal):
+        (WebCore::IDBDatabaseBackendImpl::runIntVersionChangeTransaction):
+        * Modules/indexeddb/IDBDatabaseBackendImpl.h:
+        (IDBDatabaseBackendImpl):
+        * Modules/indexeddb/IDBDatabaseCallbacks.h:
+
 2012-11-07  Alexandru Chiculita  <ach...@adobe.com>
 
         [CSS Shaders] Add CustomFilterMeshBoxType to ValidatedCustomFilterOperation

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp (133775 => 133776)


--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp	2012-11-07 18:20:53 UTC (rev 133775)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp	2012-11-07 18:26:18 UTC (rev 133776)
@@ -304,8 +304,9 @@
     callbacks->onSuccess(PassRefPtr<IDBTransactionBackendInterface>(transaction));
 }
 
-void IDBDatabaseBackendImpl::setIntVersionInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, int64_t version, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendImpl> transaction)
+void IDBDatabaseBackendImpl::setIntVersionInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, int64_t version, PassRefPtr<IDBCallbacks> prpCallbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks, PassRefPtr<IDBTransactionBackendImpl> transaction)
 {
+    RefPtr<IDBCallbacks> callbacks(prpCallbacks);
     int64_t databaseId = database->id();
     int64_t oldVersion = database->m_metadata.intVersion;
     ASSERT(version > oldVersion);
@@ -316,6 +317,8 @@
         transaction->abort(error);
         return;
     }
+    ASSERT(!database->m_pendingSecondHalfOpenWithVersion);
+    database->m_pendingSecondHalfOpenWithVersion = PendingOpenWithVersionCall::create(callbacks, databaseCallbacks, version);
     callbacks->onUpgradeNeeded(oldVersion, transaction, database);
 }
 
@@ -498,7 +501,7 @@
     ASSERT(!ec);
 
     RefPtr<IDBDatabaseBackendImpl> database = this;
-    OwnPtr<ScriptExecutionContext::Task> intVersionTask = createCallbackTask(&IDBDatabaseBackendImpl::setIntVersionInternal, database, requestedVersion, callbacks, transaction);
+    OwnPtr<ScriptExecutionContext::Task> intVersionTask = createCallbackTask(&IDBDatabaseBackendImpl::setIntVersionInternal, database, requestedVersion, callbacks, databaseCallbacks, transaction);
     OwnPtr<ScriptExecutionContext::Task> resetVersionOnAbortTask = createCallbackTask(&IDBDatabaseBackendImpl::resetVersion, database, m_metadata.version, m_metadata.intVersion);
     if (!transaction->scheduleTask(intVersionTask.release(), resetVersionOnAbortTask.release())) {
         // FIXME: Remove one of the following lines.
@@ -506,7 +509,6 @@
         ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
     }
     ASSERT(!m_pendingSecondHalfOpenWithVersion);
-    m_pendingSecondHalfOpenWithVersion = PendingOpenWithVersionCall::create(callbacks, databaseCallbacks, requestedVersion);
     m_databaseCallbacksSet.add(databaseCallbacks);
 }
 

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.h (133775 => 133776)


--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.h	2012-11-07 18:20:53 UTC (rev 133775)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.h	2012-11-07 18:26:18 UTC (rev 133776)
@@ -89,7 +89,7 @@
     static void createObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBTransactionBackendImpl>);
     static void deleteObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBTransactionBackendImpl>);
     static void setVersionInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, const String& version, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendImpl>);
-    static void setIntVersionInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, int64_t version, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendImpl>);
+    static void setIntVersionInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, int64_t version, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBDatabaseCallbacks>, PassRefPtr<IDBTransactionBackendImpl>);
 
     // These are used as setVersion transaction abort tasks.
     static void removeObjectStoreFromMap(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, PassRefPtr<IDBObjectStoreBackendImpl>);

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseCallbacks.h (133775 => 133776)


--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseCallbacks.h	2012-11-07 18:20:53 UTC (rev 133775)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseCallbacks.h	2012-11-07 18:26:18 UTC (rev 133776)
@@ -34,7 +34,9 @@
 
 namespace WebCore {
 
-class IDBDatabaseCallbacks : public RefCounted<IDBDatabaseCallbacks> {
+// FIXME: Uses ThreadSafeRefCounted for storage in ScriptExecutionContext::Task but
+// it is never actually used on multiple threads. http://webkit.org/b/101483
+class IDBDatabaseCallbacks : public ThreadSafeRefCounted<IDBDatabaseCallbacks> {
 public:
     virtual ~IDBDatabaseCallbacks() { }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to