diff options
7 files changed, 121 insertions, 48 deletions
diff --git a/content/browser/in_process_webkit/indexed_db_browsertest.cc b/content/browser/in_process_webkit/indexed_db_browsertest.cc index 0c968aa..b2d779a 100644 --- a/content/browser/in_process_webkit/indexed_db_browsertest.cc +++ b/content/browser/in_process_webkit/indexed_db_browsertest.cc @@ -124,10 +124,10 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ValueSizeTest) { SimpleTest(GetTestUrl("indexeddb", "value_size_test.html")); } -IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_DoesntHangTest) { +IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DoesntHangTest) { SimpleTest(GetTestUrl("indexeddb", "transaction_run_forever.html")); CrashTab(shell()->web_contents()); - SimpleTest(GetTestUrl("indexeddb", "transaction_test.html")); + SimpleTest(GetTestUrl("indexeddb", "transaction_not_blocked.html")); } IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, Bug84933Test) { diff --git a/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc b/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc index 068c79b..5bfbbaf 100644 --- a/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc +++ b/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc @@ -287,14 +287,22 @@ void IndexedDBDispatcherHost::FinishTransaction( database_dispatcher_host_->transaction_url_map_; TransactionIDToSizeMap& transaction_size_map = database_dispatcher_host_->transaction_size_map_; + TransactionIDToDatabaseIDMap& transaction_database_map = + database_dispatcher_host_->transaction_database_map_; if (committed) Context()->TransactionComplete(transaction_url_map[host_transaction_id]); + // It's unclear if std::map::erase(key) has defined behavior if the + // key is not found. + // TODO(alecflett): Remove if it is proven that it is safe. if (transaction_url_map.find(host_transaction_id) != transaction_url_map.end()) transaction_url_map.erase(host_transaction_id); if (transaction_size_map.find(host_transaction_id) != transaction_size_map.end()) transaction_size_map.erase(host_transaction_id); + if (transaction_database_map.find(host_transaction_id) != + transaction_database_map.end()) + transaction_database_map.erase(host_transaction_id); } ////////////////////////////////////////////////////////////////////// @@ -340,6 +348,23 @@ IndexedDBDispatcherHost::DatabaseDispatcherHost::~DatabaseDispatcherHost() { } void IndexedDBDispatcherHost::DatabaseDispatcherHost::CloseAll() { + // Abort outstanding transactions started by connections in the associated + // front-end to unblock later transactions. This should only occur on unclean + // (crash) or abrupt (process-kill) shutdowns. + for (TransactionIDToDatabaseIDMap::iterator iter = + transaction_database_map_.begin(); + iter != transaction_database_map_.end();) { + int64 transaction_id = iter->first; + int32 ipc_database_id = iter->second; + ++iter; + WebIDBDatabase* database = map_.Lookup(ipc_database_id); + if (database) { + database->abort(transaction_id, WebIDBDatabaseError( + WebKit::WebIDBDatabaseExceptionUnknownError)); + } + } + DCHECK(transaction_database_map_.empty()); + for (WebIDBObjectIDToURLMap::iterator iter = database_url_map_.begin(); iter != database_url_map_.end(); iter++) { WebIDBDatabase* database = map_.Lookup(iter->first); @@ -443,6 +468,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateTransaction( new IndexedDBDatabaseCallbacks(parent_, params.ipc_thread_id, params.ipc_database_response_id), object_stores, params.mode); + transaction_database_map_[host_transaction_id] = params.ipc_database_id; parent_->RegisterTransactionId(host_transaction_id, database_url_map_[params.ipc_database_id]); } diff --git a/content/browser/in_process_webkit/indexed_db_dispatcher_host.h b/content/browser/in_process_webkit/indexed_db_dispatcher_host.h index 3c152f7..e45ca4f 100644 --- a/content/browser/in_process_webkit/indexed_db_dispatcher_host.h +++ b/content/browser/in_process_webkit/indexed_db_dispatcher_host.h @@ -106,6 +106,7 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter { typedef std::map<int64, GURL> TransactionIDToURLMap; typedef std::map<int64, uint64> TransactionIDToSizeMap; + typedef std::map<int64, int64> TransactionIDToDatabaseIDMap; class DatabaseDispatcherHost { public: @@ -161,6 +162,7 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter { WebIDBObjectIDToURLMap database_url_map_; TransactionIDToSizeMap transaction_size_map_; TransactionIDToURLMap transaction_url_map_; + TransactionIDToDatabaseIDMap transaction_database_map_; }; class CursorDispatcherHost { diff --git a/content/test/data/indexeddb/common.js b/content/test/data/indexeddb/common.js index befa4ba..795877b 100644 --- a/content/test/data/indexeddb/common.js +++ b/content/test/data/indexeddb/common.js @@ -57,6 +57,11 @@ function unexpectedBlockedCallback() fail('unexpectedBlockedCallback'); } +function unexpectedUpgradeNeededCallback() +{ + fail('unexpectedUpgradeNeededCallback'); +} + function deleteAllObjectStores(db) { objectStoreNames = db.objectStoreNames; @@ -124,7 +129,7 @@ function shouldBeEqualToString(a, b) function indexedDBTest(upgradeCallback, optionalOpenCallback) { dbname = self.location.pathname.substring( - 1 + self.location.pathname.lastIndexOf("/")); + 1 + self.location.pathname.lastIndexOf("/")); var deleteRequest = indexedDB.deleteDatabase(dbname); deleteRequest.onerror = unexpectedErrorCallback; deleteRequest.onblocked = unexpectedBlockedCallback; diff --git a/content/test/data/indexeddb/transaction_not_blocked.html b/content/test/data/indexeddb/transaction_not_blocked.html new file mode 100644 index 0000000..1a2e528 --- /dev/null +++ b/content/test/data/indexeddb/transaction_not_blocked.html @@ -0,0 +1,10 @@ +<html> + <head> + <title>IndexedDB transaction test</title> + <script type="text/javascript" src="common.js"></script> + <script type="text/javascript" src="transaction_not_blocked.js"></script> + </head> + <body onLoad="test()"> + <div id="status">Starting...</div> + </body> +</html> diff --git a/content/test/data/indexeddb/transaction_not_blocked.js b/content/test/data/indexeddb/transaction_not_blocked.js new file mode 100644 index 0000000..3a22ba6 --- /dev/null +++ b/content/test/data/indexeddb/transaction_not_blocked.js @@ -0,0 +1,35 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function test() +{ + // Do not use indexedDBTest() - need to re-use previous database. + var dbname = "doesnt-hang-test"; + var request = indexedDB.open(dbname); + request.onerror = unexpectedErrorCallback; + request.onblocked = unexpectedBlockedCallback; + request.onupgradeneeded = unexpectedUpgradeNeededCallback; + request.onsuccess = onOpenSuccess; +} + +function onOpenSuccess() +{ + var db = event.target.result; + + debug('Creating new transaction.'); + var transaction = db.transaction('store', 'readwrite'); + transaction.onabort = unexpectedAbortCallback; + var objectStore = transaction.objectStore('store'); + + var request = objectStore.get(0); + request.onerror = unexpectedErrorCallback; + request.onsuccess = function() { + debug("request completed successfully"); + }; + + transaction.oncomplete = function() { + debug("transaction completed"); + done(); + }; +} diff --git a/content/test/data/indexeddb/transaction_run_forever.js b/content/test/data/indexeddb/transaction_run_forever.js index 3a79340..f6c65c0 100644 --- a/content/test/data/indexeddb/transaction_run_forever.js +++ b/content/test/data/indexeddb/transaction_run_forever.js @@ -2,64 +2,59 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -loopCount = 0; -function endlessLoop() +function test() { - var request = objectStore.get(0); - request.onsuccess = endlessLoop; - request.onerror = unexpectedErrorCallback; + // Do not use indexedDBTest() - need to specify the database name + var dbname = "doesnt-hang-test"; - loopCount += 1; - if (loopCount == 7) { - // If we've already looped 7 times, it's pretty safe to assume - // we'll continue looping for some time... - debug("Looping infinitely within a transaction."); - done(); - } + var request = indexedDB.deleteDatabase(dbname); + request.onerror = unexpectedErrorCallback; + request.onblocked = unexpectedBlockedCallback; + request.onsuccess = function() { + var request = indexedDB.open(dbname, 1); + request.onerror = unexpectedErrorCallback; + request.onblocked = unexpectedBlockedCallback; + request.onupgradeneeded = onUpgradeNeeded; + request.onsuccess = onOpenSuccess; + }; } -function newTransactionComplete() +function onUpgradeNeeded() { - debug('The transaction completed.'); - - var finalTransaction = db.transaction(['employees'], - 'readonly'); - finalTransaction.oncomplete = unexpectedCompleteCallback; - finalTransaction.onabort = unexpectedErrorCallback; - - objectStore = finalTransaction.objectStore('employees'); - endlessLoop(); - endlessLoop(); // Make sure at least one is in flight at any time. + // We are now in a set version transaction. + debug('Creating object store.'); + var db = event.target.result; + db.createObjectStore('store'); } -function onSetVersionComplete() + +var objectStore; +function onOpenSuccess() { + var db = event.target.result; + debug('Creating new transaction.'); - var newTransaction = db.transaction(['employees'], 'readwrite'); - newTransaction.oncomplete = newTransactionComplete; - newTransaction.onabort = unexpectedAbortCallback; + var transaction = db.transaction('store', 'readwrite'); + transaction.oncomplete = unexpectedCompleteCallback; + transaction.onabort = unexpectedAbortCallback; + objectStore = transaction.objectStore('store'); - var request = newTransaction.objectStore('employees').put( - {id: 0, name: 'John Doe', desk: 'LON-BEL-123'}); - request.onerror = unexpectedErrorCallback; + debug('Starting endless loop...'); + endlessLoop(); } -function onSetVersion() +var loopCount = 0; +function endlessLoop() { - // We are now in a set version transaction. - debug('Creating object store.'); - db = event.target.result; - deleteAllObjectStores(db); - var objectStore = db.createObjectStore('employees', {keyPath: 'id'}); -} + var request = objectStore.get(0); + request.onsuccess = endlessLoop; + request.onerror = unexpectedErrorCallback; -function test() -{ - if ('webkitIndexedDB' in window) { - indexedDB = webkitIndexedDB; - IDBCursor = webkitIDBCursor; - IDBKeyRange = webkitIDBKeyRange; - IDBTransaction = webkitIDBTransaction; + loopCount += 1; + if (loopCount == 7) { + // If we've already looped 7 times, it's pretty safe to assume + // we'll continue looping for some time... + debug("Looping infinitely within a transaction."); + done(); } - indexedDBTest(onSetVersion, onSetVersionComplete); } |