Title: [113502] branches/chromium/1084
Revision
113502
Author
jsb...@chromium.org
Date
2012-04-06 14:49:13 -0700 (Fri, 06 Apr 2012)

Log Message

Merge 112740 - IndexedDB: Race condition causes version change transaction to commit after onblocked
https://bugs.webkit.org/show_bug.cgi?id=82678

Source/WebCore:

For a version change event, the blocked and success events could both be queued
before either is dispatched. The transaction would erroneously be allowed to commit
after the blocked event was dispatched; it should not be, as the request was not
finished.

Reviewed by Tony Chang.

Test: storage/indexeddb/dont-commit-on-blocked.html

* Modules/indexeddb/IDBRequest.cpp:
(WebCore::IDBRequest::dispatchEvent):

LayoutTests:

Landing test marked PASS FAIL as WK82776 prevents it from running in DRT; will
run it as a Chromium browser test for now.

Reviewed by Tony Chang.

* platform/chromium/test_expectations.txt:
* storage/indexeddb/dont-commit-on-blocked.html: Added.
* storage/indexeddb/resources/dont-commit-on-blocked-worker.js: Added.
(request.onsuccess):
(onSetVersionBlocked):
(onSetVersionSuccess):
(onTransactionComplete):


TBR=jsb...@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10007047

Modified Paths

Added Paths

Diff

Modified: branches/chromium/1084/LayoutTests/platform/chromium/test_expectations.txt (113501 => 113502)


--- branches/chromium/1084/LayoutTests/platform/chromium/test_expectations.txt	2012-04-06 21:49:11 UTC (rev 113501)
+++ branches/chromium/1084/LayoutTests/platform/chromium/test_expectations.txt	2012-04-06 21:49:13 UTC (rev 113502)
@@ -4327,3 +4327,6 @@
 BUGWK82372 LINUX X86 RELEASE : css3/filters/custom/effect-custom-parameters.html = IMAGE
 
 BUGWK82269 DEBUG: media/track/track-delete-during-setup.html = CRASH
+
+// This test depends on Worker behavior that is broken in DRT
+BUGWK82776 : storage/indexeddb/dont-commit-on-blocked.html = PASS FAIL

Copied: branches/chromium/1084/LayoutTests/storage/indexeddb/dont-commit-on-blocked-expected.txt (from rev 112740, trunk/LayoutTests/storage/indexeddb/dont-commit-on-blocked-expected.txt) (0 => 113502)


--- branches/chromium/1084/LayoutTests/storage/indexeddb/dont-commit-on-blocked-expected.txt	                        (rev 0)
+++ branches/chromium/1084/LayoutTests/storage/indexeddb/dont-commit-on-blocked-expected.txt	2012-04-06 21:49:13 UTC (rev 113502)
@@ -0,0 +1,51 @@
+Regression test for WK82678 - don't commit after a blocked event
+
+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;
+PASS Boolean(indexedDB && IDBCursor && IDBDatabase && IDBDatabaseError && IDBDatabaseException && IDBFactory && IDBIndex && IDBKeyRange && IDBObjectStore && IDBRequest && IDBTransaction) is true
+
+Prepare Database
+request = indexedDB.deleteDatabase('dont-commit-on-blocked')
+request = indexedDB.open('dont-commit-on-blocked')
+db = request.result
+db._onversionchange_ = onVersionChange
+PASS db.version is ""
+db.setVersion('1')
+store = db.createObjectStore('store1')
+
+holdConnection():
+holding connection until versionchange event
+
+Starting worker: resources/dont-commit-on-blocked-worker.js
+[Worker] indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+PASS [Worker] Boolean(indexedDB && IDBCursor && IDBDatabase && IDBDatabaseError && IDBDatabaseException && IDBFactory && IDBIndex && IDBKeyRange && IDBObjectStore && IDBRequest && IDBTransaction) is true
+[Worker] 
+[Worker] opening database connection
+[Worker] request = indexedDB.open('dont-commit-on-blocked')
+[Worker] db = request.result
+[Worker] state = 'setversion'
+[Worker] request = db.setVersion(2)
+[Worker] request._onblocked_ = onSetVersionBlocked
+[Worker] request._onsuccess_ = onSetVersionSuccess
+[Worker] spinning for 100ms to let events be queued but prevent dispatch
+[Worker] done spinning
+[Worker] 
+[Worker] onSetVersionSuccess():
+FAIL [Worker] state should be blocked. Was setversion.
+[Worker] state = 'success'
+[Worker] creating object store - will fail if transaction commited after blocked event
+[Worker] db.createObjectStore('store2')
+[Worker] transaction = request.result
+[Worker] transaction._oncomplete_ = onTransactionComplete
+[Worker] 
+[Worker] onTransactionComplete
+PASS [Worker] state is "success"
+PASS [Worker] Number(db.version) is 2
+FAIL [Worker] db.objectStoreNames.contains('store1') should be true. Was false.
+PASS [Worker] db.objectStoreNames.contains('store2') is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Copied: branches/chromium/1084/LayoutTests/storage/indexeddb/dont-commit-on-blocked.html (from rev 112740, trunk/LayoutTests/storage/indexeddb/dont-commit-on-blocked.html) (0 => 113502)


--- branches/chromium/1084/LayoutTests/storage/indexeddb/dont-commit-on-blocked.html	                        (rev 0)
+++ branches/chromium/1084/LayoutTests/storage/indexeddb/dont-commit-on-blocked.html	2012-04-06 21:49:13 UTC (rev 113502)
@@ -0,0 +1,65 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+
+description("Regression test for WK82678 - don't commit after a blocked event");
+
+function test()
+{
+    removeVendorPrefixes();
+    prepareDatabase();
+}
+
+function prepareDatabase()
+{
+    debug("Prepare Database");
+    evalAndLog("request = indexedDB.deleteDatabase('dont-commit-on-blocked')");
+    request._onerror_ = unexpectedErrorCallback;
+    request._onsuccess_ = function(e) {
+        evalAndLog("request = indexedDB.open('dont-commit-on-blocked')");
+        request._onerror_ = unexpectedErrorCallback;
+        request._onsuccess_ = function(e) {
+            evalAndLog("db = request.result");
+            db._onerror_ = unexpectedErrorCallback;
+            evalAndLog("db._onversionchange_ = onVersionChange");
+            shouldBeEqualToString("db.version", "");
+            request = evalAndLog("db.setVersion('1')");
+            request._onerror_ = unexpectedErrorCallback;
+            request._onsuccess_ = function(e) {
+                var trans = request.result;
+                evalAndLog("store = db.createObjectStore('store1')");
+                trans._onerror_ = unexpectedErrorCallback;
+                trans._onabort_ = unexpectedAbortCallback;
+                trans._oncomplete_ = holdConnection;
+            };
+        };
+    };
+}
+
+function holdConnection()
+{
+    debug("");
+    debug("holdConnection():");
+    debug("holding connection until versionchange event");
+    debug("");
+    startWorker("resources/dont-commit-on-blocked-worker.js");
+}
+
+function onVersionChange(e)
+{
+    debug("");
+    debug("onVersionChange():");
+    debug("closing connection");
+    evalAndLog("db.close()");
+}
+
+test();
+
+</script>
+<script src=""
+</body>
+</html>

Copied: branches/chromium/1084/LayoutTests/storage/indexeddb/resources/dont-commit-on-blocked-worker.js (from rev 112740, trunk/LayoutTests/storage/indexeddb/resources/dont-commit-on-blocked-worker.js) (0 => 113502)


--- branches/chromium/1084/LayoutTests/storage/indexeddb/resources/dont-commit-on-blocked-worker.js	                        (rev 0)
+++ branches/chromium/1084/LayoutTests/storage/indexeddb/resources/dont-commit-on-blocked-worker.js	2012-04-06 21:49:13 UTC (rev 113502)
@@ -0,0 +1,57 @@
+importScripts('../../../fast/js/resources/js-test-pre.js');
+importScripts('shared.js');
+
+removeVendorPrefixes();
+
+debug("opening database connection");
+evalAndLog("request = indexedDB.open('dont-commit-on-blocked')");
+request._onerror_ = unexpectedErrorCallback;
+request._onsuccess_ = function(e) {
+  evalAndLog("db = request.result");
+  db._onerror_ = unexpectedErrorCallback;
+
+  evalAndLog("state = 'setversion'");
+  evalAndLog("request = db.setVersion(2)");
+  evalAndLog("request._onblocked_ = onSetVersionBlocked");
+  evalAndLog("request._onsuccess_ = onSetVersionSuccess");
+  debug("spinning for 100ms to let events be queued but prevent dispatch");
+  var t = Date.now();
+  while ((Date.now() - t) < 100) {
+  }
+  debug("done spinning");
+};
+
+function onSetVersionBlocked(e)
+{
+  debug("");
+  debug("onSetVersionBlocked():");
+  shouldBeEqualToString("state", "setversion");
+  evalAndLog("state = 'blocked'");
+}
+
+function onSetVersionSuccess(e)
+{
+  debug("");
+  debug("onSetVersionSuccess():");
+  shouldBeEqualToString("state", "blocked");
+  evalAndLog("state = 'success'");
+
+  debug("creating object store - will fail if transaction commited after blocked event");
+  evalAndLog("db.createObjectStore('store2')");
+
+  evalAndLog("transaction = request.result");
+  evalAndLog("transaction._oncomplete_ = onTransactionComplete");
+}
+
+function onTransactionComplete(e)
+{
+  debug("");
+  debug("onTransactionComplete");
+
+  shouldBeEqualToString("state", "success");
+
+  shouldBe("Number(db.version)", "2");
+  shouldBeTrue("db.objectStoreNames.contains('store1')");
+  shouldBeTrue("db.objectStoreNames.contains('store2')");
+  finishJSTest();
+}

Modified: branches/chromium/1084/Source/WebCore/Modules/indexeddb/IDBRequest.cpp (113501 => 113502)


--- branches/chromium/1084/Source/WebCore/Modules/indexeddb/IDBRequest.cpp	2012-04-06 21:49:11 UTC (rev 113501)
+++ branches/chromium/1084/Source/WebCore/Modules/indexeddb/IDBRequest.cpp	2012-04-06 21:49:13 UTC (rev 113502)
@@ -378,7 +378,7 @@
     if (cursorToNotify)
         cursorToNotify->postSuccessHandlerCallback();
 
-    if (m_transaction) {
+    if (m_transaction && event->type() != eventNames().blockedEvent) {
         // If an error event and the default wasn't prevented...
         if (dontPreventDefault && event->type() == eventNames().errorEvent)
             m_transaction->backend()->abort();
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to