summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsbell@chromium.org <jsbell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-07 01:27:11 +0000
committerjsbell@chromium.org <jsbell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-07 01:27:11 +0000
commit8c2acc21b17cdcc88edc0bea2623a637c97fdeab (patch)
tree26feec0cc3d6a3cfea9314dd8c38bae230ae7825
parentdfa1818b45e80b628bc8dbd62d7adc046d9dccd4 (diff)
downloadchromium_src-8c2acc21b17cdcc88edc0bea2623a637c97fdeab.zip
chromium_src-8c2acc21b17cdcc88edc0bea2623a637c97fdeab.tar.gz
chromium_src-8c2acc21b17cdcc88edc0bea2623a637c97fdeab.tar.bz2
IndexedDB: Ensure transactions from terminated renderers are aborted
The previous logic for this was lost when the TransactionDispatcherHost was removed (in the palindromic r179971). The test for this scenario had been broken and disabled so it was not caught during the refactor. BUG=167483,180685 Review URL: https://chromiumcodereview.appspot.com/12546006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@186577 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/in_process_webkit/indexed_db_browsertest.cc4
-rw-r--r--content/browser/in_process_webkit/indexed_db_dispatcher_host.cc26
-rw-r--r--content/browser/in_process_webkit/indexed_db_dispatcher_host.h2
-rw-r--r--content/test/data/indexeddb/common.js7
-rw-r--r--content/test/data/indexeddb/transaction_not_blocked.html10
-rw-r--r--content/test/data/indexeddb/transaction_not_blocked.js35
-rw-r--r--content/test/data/indexeddb/transaction_run_forever.js85
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);
}