Implement IDBFactory.deleteDatabase
authorjochen@chromium.org <jochen@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 29 Oct 2011 16:18:44 +0000 (16:18 +0000)
committerjochen@chromium.org <jochen@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 29 Oct 2011 16:18:44 +0000 (16:18 +0000)
https://bugs.webkit.org/show_bug.cgi?id=62622

Reviewed by Tony Chang.

Source/WebCore:

Tests: storage/indexeddb/factory-deletedatabase-interactions.html
       storage/indexeddb/factory-deletedatabase.html

* storage/IDBBackingStore.h:
* storage/IDBDatabaseBackendImpl.cpp:
(WebCore::IDBDatabaseBackendImpl::PendingDeleteCall::create):
(WebCore::IDBDatabaseBackendImpl::PendingDeleteCall::callbacks):
(WebCore::IDBDatabaseBackendImpl::PendingDeleteCall::PendingDeleteCall):
(WebCore::IDBDatabaseBackendImpl::IDBDatabaseBackendImpl):
(WebCore::IDBDatabaseBackendImpl::openInternal):
(WebCore::IDBDatabaseBackendImpl::processPendingCalls):
(WebCore::IDBDatabaseBackendImpl::openConnection):
(WebCore::IDBDatabaseBackendImpl::deleteDatabase):
* storage/IDBDatabaseBackendImpl.h:
* storage/IDBFactory.cpp:
(WebCore::IDBFactory::deleteDatabase):
* storage/IDBFactory.h:
* storage/IDBFactory.idl:
* storage/IDBFactoryBackendImpl.cpp:
(WebCore::IDBFactoryBackendImpl::deleteDatabase):
* storage/IDBFactoryBackendImpl.h:
* storage/IDBFactoryBackendInterface.h:
* storage/IDBLevelDBBackingStore.cpp:
(WebCore::deleteRange):
(WebCore::IDBLevelDBBackingStore::deleteDatabase):
* storage/IDBLevelDBBackingStore.h:
* storage/IDBRequest.cpp:
(WebCore::IDBRequest::dispatchEvent):

Source/WebKit/chromium:

* src/IDBFactoryBackendProxy.cpp:
(WebKit::IDBFactoryBackendProxy::deleteDatabase):
* src/IDBFactoryBackendProxy.h:
* src/WebIDBFactoryImpl.cpp:
(WebKit::WebIDBFactoryImpl::getDatabaseNames):
(WebKit::WebIDBFactoryImpl::open):
(WebKit::WebIDBFactoryImpl::deleteDatabase):
* src/WebIDBFactoryImpl.h:

LayoutTests:

* storage/indexeddb/factory-basics-expected.txt: Updated.
* storage/indexeddb/factory-basics.html: Updated.
* storage/indexeddb/factory-deletedatabase-expected.txt: Added.
* storage/indexeddb/factory-deletedatabase-interactions-expected.txt: Added.
* storage/indexeddb/factory-deletedatabase-interactions.html: Added.
* storage/indexeddb/factory-deletedatabase.html: Added.
* storage/indexeddb/open-close-version-expected.txt: Updated.
* storage/indexeddb/open-close-version.html: Updated.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@98806 268f45cc-cd09-0410-ab3c-d52691b4dbfc

27 files changed:
LayoutTests/ChangeLog
LayoutTests/storage/indexeddb/factory-basics-expected.txt
LayoutTests/storage/indexeddb/factory-basics.html
LayoutTests/storage/indexeddb/factory-deletedatabase-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/factory-deletedatabase-interactions-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/factory-deletedatabase-interactions.html [new file with mode: 0644]
LayoutTests/storage/indexeddb/factory-deletedatabase.html [new file with mode: 0644]
LayoutTests/storage/indexeddb/open-close-version-expected.txt
LayoutTests/storage/indexeddb/open-close-version.html
Source/WebCore/ChangeLog
Source/WebCore/storage/IDBBackingStore.h
Source/WebCore/storage/IDBDatabaseBackendImpl.cpp
Source/WebCore/storage/IDBDatabaseBackendImpl.h
Source/WebCore/storage/IDBFactory.cpp
Source/WebCore/storage/IDBFactory.h
Source/WebCore/storage/IDBFactory.idl
Source/WebCore/storage/IDBFactoryBackendImpl.cpp
Source/WebCore/storage/IDBFactoryBackendImpl.h
Source/WebCore/storage/IDBFactoryBackendInterface.h
Source/WebCore/storage/IDBLevelDBBackingStore.cpp
Source/WebCore/storage/IDBLevelDBBackingStore.h
Source/WebCore/storage/IDBRequest.cpp
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/src/IDBFactoryBackendProxy.cpp
Source/WebKit/chromium/src/IDBFactoryBackendProxy.h
Source/WebKit/chromium/src/WebIDBFactoryImpl.cpp
Source/WebKit/chromium/src/WebIDBFactoryImpl.h

index 1c241dd..7de156d 100755 (executable)
@@ -1,3 +1,19 @@
+2011-10-29  Jochen Eisinger  <jochen@chromium.org>
+
+        Implement IDBFactory.deleteDatabase
+        https://bugs.webkit.org/show_bug.cgi?id=62622
+
+        Reviewed by Tony Chang.
+
+        * storage/indexeddb/factory-basics-expected.txt: Updated.
+        * storage/indexeddb/factory-basics.html: Updated.
+        * storage/indexeddb/factory-deletedatabase-expected.txt: Added.
+        * storage/indexeddb/factory-deletedatabase-interactions-expected.txt: Added.
+        * storage/indexeddb/factory-deletedatabase-interactions.html: Added.
+        * storage/indexeddb/factory-deletedatabase.html: Added.
+        * storage/indexeddb/open-close-version-expected.txt: Updated.
+        * storage/indexeddb/open-close-version.html: Updated.
+
 2011-10-27  Robert Hogan  <robert@webkit.org>
 
         CSS 2.1 failure: dynamic-top-change-001 to 004 fail
index e9cf7a2..cb85b76 100644 (file)
@@ -8,17 +8,23 @@ PASS indexedDB == null is false
 PASS typeof indexedDB.open === 'function' is true
 PASS typeof indexedDB.cmp === 'function' is true
 PASS typeof indexedDB.getDatabaseNames === 'function' is true
-deleteDatabase API is not yet implemented, so this will fail:
-FAIL typeof indexedDB.deleteDatabase === 'function' should be true. Was false.
+PASS typeof indexedDB.deleteDatabase === 'function' is true
 indexedDB.getDatabaseNames()
 databaseNames = event.target.result
 PASS databaseNames.contains('storage/indexeddb/factory-basics') is false
 PASS databaseNames.contains('DATABASE THAT DOES NOT EXIST') is false
 indexedDB.open(name, description)
+event.target.result.close()
 indexedDB.getDatabaseNames()
 databaseNames = event.target.result
 PASS databaseNames.contains('storage/indexeddb/factory-basics') is true
 PASS databaseNames.contains('DATABASE THAT DOES NOT EXIST') is false
+indexedDB.deleteDatabase('storage/indexeddb/factory-basics')
+indexedDB.getDatabaseNames()
+databaseNames = event.target.result
+PASS databaseNames.contains('storage/indexeddb/factory-basics') is false
+PASS databaseNames.contains('DATABASE THAT DOES NOT EXIST') is false
+indexedDB.deleteDatabase('DATABASE THAT DOES NOT EXIST')
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 89051fd..07ad47b 100644 (file)
@@ -22,7 +22,6 @@ function test()
     shouldBeTrue("typeof indexedDB.cmp === 'function'");
     shouldBeTrue("typeof indexedDB.getDatabaseNames === 'function'");
 
-    debug("deleteDatabase API is not yet implemented, so this will fail:");
     shouldBeTrue("typeof indexedDB.deleteDatabase === 'function'");
 
     name = 'storage/indexeddb/factory-basics';
@@ -47,6 +46,7 @@ function getDatabaseNamesSuccess1()
 
 function openSuccess()
 {
+    evalAndLog("event.target.result.close()");
     request = evalAndLog("indexedDB.getDatabaseNames()");
     request.onsuccess = getDatabaseNamesSuccess2;
     request.onerror = unexpectedErrorCallback;
@@ -59,8 +59,32 @@ function getDatabaseNamesSuccess2()
     shouldBeTrue("databaseNames.contains('" + name + "')");
     shouldBeFalse("databaseNames.contains('DATABASE THAT DOES NOT EXIST')");
 
-    // FIXME: test indexedDB.deleteDatabase(databaseName)
+    request = evalAndLog("indexedDB.deleteDatabase('" + name + "')");
+    request.onsuccess = deleteDatabaseSuccess;
+    request.onerror = unexpectedErrorCallback;
+}
 
+function deleteDatabaseSuccess()
+{
+    request = evalAndLog("indexedDB.getDatabaseNames()");
+    request.onsuccess = getDatabaseNamesSuccess3;
+    request.onerror = unexpectedErrorCallback;
+}
+
+function getDatabaseNamesSuccess3()
+{
+    var databaseNames;
+    evalAndLog("databaseNames = event.target.result");
+    shouldBeFalse("databaseNames.contains('" + name + "')");
+    shouldBeFalse("databaseNames.contains('DATABASE THAT DOES NOT EXIST')");
+
+    request = evalAndLog("indexedDB.deleteDatabase('DATABASE THAT DOES NOT EXIST')");
+    request.onsuccess = deleteDatabaseSuccess2;
+    request.onerror = unexpectedErrorCallback;
+}
+
+function deleteDatabaseSuccess2()
+{
     done();
 }
 
diff --git a/LayoutTests/storage/indexeddb/factory-deletedatabase-expected.txt b/LayoutTests/storage/indexeddb/factory-deletedatabase-expected.txt
new file mode 100644 (file)
index 0000000..46217f7
--- /dev/null
@@ -0,0 +1,28 @@
+Test IndexedDB's webkitIndexedDB.deleteDatabase().
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+webkitIndexedDB.open('database-to-delete')
+db = event.target.result
+db.setVersion('new version')
+trans = event.target.result
+PASS trans !== null is true
+store = db.createObjectStore('storeName', null)
+store.createIndex('indexName', '')
+PASS store.indexNames.contains('indexName') is true
+store.add('value', 'key')
+db.transaction('storeName', webkitIDBTransaction.READ_WRITE)
+store = transaction.objectStore('storeName')
+store.get('key')
+PASS event.target.result is "value"
+db.setVersion('new version')
+request = webkitIndexedDB.deleteDatabase('database-to-delete')
+webkitIndexedDB.open('database-to-delete')
+db = event.target.result
+db.setVersion('new version')
+PASS db.objectStoreNames.length is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/storage/indexeddb/factory-deletedatabase-interactions-expected.txt b/LayoutTests/storage/indexeddb/factory-deletedatabase-interactions-expected.txt
new file mode 100644 (file)
index 0000000..bfb81eb
--- /dev/null
@@ -0,0 +1,70 @@
+Test the deleteDatabase call and its interaction with open/setVersion
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;
+PASS indexedDB == null is false
+
+TEST: deleteDatabase blocked on open handles
+window.dbname = 'test1'; window.ver = 1; window.steps = []
+'h.open'
+'h.open.onsuccess'
+'deleteDatabase()'
+'h.onversionchange'
+    h closing, but not immediately
+'deleteDatabase().onblocked'
+'h.close'
+'deleteDatabase().onsuccess'
+PASS window.steps.toString() is "h.open,h.open.onsuccess,deleteDatabase(),h.onversionchange,deleteDatabase().onblocked,h.close,deleteDatabase().onsuccess"
+
+TEST: deleteDatabase not blocked when handles close immediately
+window.dbname = 'test2'; window.ver = 1; window.steps = []
+'h.open'
+'h.open.onsuccess'
+'deleteDatabase()'
+'h.onversionchange'
+    h closing immediately
+'h.close'
+'deleteDatabase().onblocked'
+'deleteDatabase().onsuccess'
+NOTE: Will FAIL with extra bogus deleteDatabase().onblocked step; https://bugs.webkit.org/show_bug.cgi?id=71130
+FAIL window.steps.toString() should be h.open,h.open.onsuccess,deleteDatabase(),h.onversionchange,h.close,deleteDatabase().onsuccess. Was h.open,h.open.onsuccess,deleteDatabase(),h.onversionchange,h.close,deleteDatabase().onblocked,deleteDatabase().onsuccess.
+
+TEST: deleteDatabase is delayed if a VERSION_CHANGE transaction is running
+window.dbname = 'test3'; window.ver = 1; window.steps = []
+'h.open'
+'h.open.onsuccess'
+'h.setVersion'
+'deleteDatabase()'
+'h.setVersion.onsuccess'
+'h.setVersion.transaction-complete'
+'h.onversionchange'
+    h closing, but not immediately
+'deleteDatabase().onblocked'
+'h.close'
+'deleteDatabase().onsuccess'
+PASS window.steps.toString() is "h.open,h.open.onsuccess,h.setVersion,deleteDatabase(),h.setVersion.onsuccess,h.setVersion.transaction-complete,h.onversionchange,deleteDatabase().onblocked,h.close,deleteDatabase().onsuccess"
+
+TEST: multiple deleteDatabase calls
+window.dbname = 'test4'; window.ver = 1; window.steps = []
+'h.open'
+'h.open.onsuccess'
+'deleteDatabase(1)'
+'deleteDatabase(2)'
+'h.onversionchange'
+    h closing, but not immediately
+'deleteDatabase(1).onblocked'
+'h.onversionchange'
+    h closing, but not immediately
+'deleteDatabase(2).onblocked'
+'h.close'
+'h.close'
+'deleteDatabase(1).onsuccess'
+'deleteDatabase(2).onsuccess'
+NOTE: Will FAIL with extra bogus h.onversionchange/h.close steps; https://bugs.webkit.org/show_bug.cgi?id=71129
+FAIL window.steps.toString() should be h.open,h.open.onsuccess,deleteDatabase(1),deleteDatabase(2),h.onversionchange,deleteDatabase(1).onblocked,deleteDatabase(2).onblocked,h.close,deleteDatabase(1).onsuccess,deleteDatabase(2).onsuccess. Was h.open,h.open.onsuccess,deleteDatabase(1),deleteDatabase(2),h.onversionchange,deleteDatabase(1).onblocked,h.onversionchange,deleteDatabase(2).onblocked,h.close,h.close,deleteDatabase(1).onsuccess,deleteDatabase(2).onsuccess.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/storage/indexeddb/factory-deletedatabase-interactions.html b/LayoutTests/storage/indexeddb/factory-deletedatabase-interactions.html
new file mode 100644 (file)
index 0000000..237b713
--- /dev/null
@@ -0,0 +1,232 @@
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+<script src="../../fast/js/resources/js-test-post-function.js"></script>
+<script src="resources/shared.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+
+description("Test the deleteDatabase call and its interaction with open/setVersion");
+if (window.layoutTestController)
+    layoutTestController.waitUntilDone();
+
+function Connection(id) {
+    id = String(id);
+    var self = this;
+    this.open = function(opts) {
+        window.steps.push(evalAndLog("'" + id + ".open'"));
+        var req = indexedDB.open(window.dbname);
+        req.onerror = unexpectedErrorCallback;
+        req.onsuccess = function (e) {
+            self.handle = e.target.result;
+            window.steps.push(evalAndLog("'" + id + ".open.onsuccess'"));
+            self.handle.onversionchange = function(e) {
+                window.steps.push(evalAndLog("'" + id + ".onversionchange'"));
+                if (opts && opts.onversion) { opts.onversion.call(self); }
+            };
+            if (opts && opts.onsuccess) { opts.onsuccess.call(self); }
+        };
+    };
+
+    this.close = function() {
+        window.steps.push(evalAndLog("'" + id + ".close'"));
+        this.handle.close();
+    };
+
+    this.setVersion = function(opts) {
+        window.steps.push(evalAndLog("'" + id + ".setVersion'"));
+        var req = this.handle.setVersion(String(window.ver++));
+        req.onabort = function (e) {
+            window.steps.push(evalAndLog("'" + id + ".setVersion.onabort'"));
+            if (opts && opts.onabort) { opts.onabort.call(self); }
+        };
+        req.onblocked = function (e) {
+            window.steps.push(evalAndLog("'" + id + ".setVersion.onblocked'"));
+            if (opts && opts.onblocked) { opts.onblocked.call(self); }
+        };
+        req.onsuccess = function (e) {
+            window.steps.push(evalAndLog("'" + id + ".setVersion.onsuccess'"));
+            if (self.handle.objectStoreNames.contains("test-store" + window.ver)) {
+                self.handle.deleteObjectStore("test-store" + window.ver);
+            }
+            var store = self.handle.createObjectStore("test-store" + window.ver);
+            var count = 0;
+            do_async_puts(); // Keep this transaction running for a while
+            function do_async_puts() {
+                var req = store.put(count, count);
+                req.onerror = unexpectedErrorCallback;
+                req.onsuccess = function (e) {
+                    if (++count < 10) {
+                        do_async_puts();
+                    } else {
+                        window.steps.push(evalAndLog("'" + id + ".setVersion.transaction-complete'"));
+                        if (opts && opts.onsuccess) { opts.onsuccess.call(self); }
+                    }
+                };
+            }
+        };
+        req.onerror = function (e) {
+            window.steps.push(evalAndLog("'" + id + ".setVersion.onerror'"));
+            if (opts && opts.onerror) { opts.onerror.call(self); }
+        };
+    };
+}
+
+function deleteDatabase(id, name, opts) {
+    window.steps.push(evalAndLog("'deleteDatabase(" + id + ")'"));
+    var req = indexedDB.deleteDatabase(name);
+    req.onsuccess = function (e) {
+        window.steps.push(evalAndLog("'deleteDatabase(" + id + ").onsuccess'"));
+        if (opts && opts.onsuccess) { opts.onsuccess.call(null); }
+    };
+    req.onerror = function (e) {
+        window.steps.push(evalAndLog("'deleteDatabase(" + id + ").onerror'"));
+        if (opts && opts.onerror) { opts.onerror.call(null); }
+    };
+    req.onblocked = function (e) {
+        window.steps.push(evalAndLog("'deleteDatabase(" + id + ").onblocked'"));
+        if (opts && opts.onblocked) { opts.onblocked.call(null); }
+    };
+}
+
+// run a series of steps that take a continuation function
+function runSteps(commands) {
+    if (commands.length) {
+        var command = commands.shift();
+        command(function() { runSteps(commands); });
+    }
+}
+
+function test() {
+    indexedDB = evalAndLog("indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;");
+    shouldBeFalse("indexedDB == null");
+    test1();
+}
+
+function test1() {
+    debug("");
+    debug("TEST: deleteDatabase blocked on open handles");
+    evalAndLog("window.dbname = 'test1'; window.ver = 1; window.steps = []");
+    var h = new Connection("h");
+    runSteps([function(doNext) { h.open({onsuccess: doNext,
+                                onversion: function() {
+                                    debug("    h closing, but not immediately");
+                                    setTimeout(function() { h.close(); }, 0);
+                                }}); },
+        function(doNext) { deleteDatabase("", window.dbname, {
+                           onsuccess: finishTest}); },
+        ]);
+    function finishTest() {
+        shouldBeEqualToString("window.steps.toString()",
+                              ["h.open",
+                               "h.open.onsuccess",
+                               "deleteDatabase()",
+                               "h.onversionchange",
+                               "deleteDatabase().onblocked",
+                               "h.close",
+                               "deleteDatabase().onsuccess"
+                               ].toString());
+        test2();
+    }
+}
+
+function test2() {
+    debug("");
+    debug("TEST: deleteDatabase not blocked when handles close immediately");
+    evalAndLog("window.dbname = 'test2'; window.ver = 1; window.steps = []");
+    var h = new Connection("h");
+    runSteps([function(doNext) { h.open({onsuccess: doNext,
+                                          onversion: function() {
+                                              debug("    h closing immediately");
+                                              h.close();
+                                          }}); },
+        function(doNext) { deleteDatabase("", window.dbname, {
+                           onsuccess: finishTest}); },
+        ]);
+    function finishTest() {
+        debug("NOTE: Will FAIL with extra bogus deleteDatabase().onblocked step; https://bugs.webkit.org/show_bug.cgi?id=71130");
+        shouldBeEqualToString("window.steps.toString()",
+                              ["h.open",
+                               "h.open.onsuccess",
+                               "deleteDatabase()",
+                               "h.onversionchange",
+                               "h.close",
+                               "deleteDatabase().onsuccess"
+                               ].toString());
+        test3();
+    }
+}
+
+function test3() {
+    debug("");
+    debug("TEST: deleteDatabase is delayed if a VERSION_CHANGE transaction is running");
+    evalAndLog("window.dbname = 'test3'; window.ver = 1; window.steps = []");
+    var h = new Connection("h");
+    runSteps([function(doNext) { h.open({onsuccess: doNext,
+                                onversion: function() {
+                                    debug("    h closing, but not immediately");
+                                    setTimeout(function() { h.close(); }, 0);
+                                }}); },
+              function(doNext) { h.setVersion(); doNext(); },
+              function(doNext) { deleteDatabase("", window.dbname,
+                                {onsuccess: finishTest}); },
+              ]);
+
+    function finishTest() {
+        shouldBeEqualToString("window.steps.toString()",
+                              ["h.open",
+                               "h.open.onsuccess",
+                               "h.setVersion",
+                               "deleteDatabase()",
+                               "h.setVersion.onsuccess",
+                               "h.setVersion.transaction-complete",
+                               "h.onversionchange",
+                               "deleteDatabase().onblocked",
+                               "h.close",
+                               "deleteDatabase().onsuccess"
+                               ].toString());
+        test4();
+    }
+}
+
+function test4() {
+    debug("");
+    debug("TEST: multiple deleteDatabase calls");
+    evalAndLog("window.dbname = 'test4'; window.ver = 1; window.steps = []");
+    var h = new Connection("h");
+    runSteps([function(doNext) { h.open({onsuccess: doNext,
+                                onversion: function() {
+                                    debug("    h closing, but not immediately");
+                                    setTimeout(function() { h.close(); }, 0);
+                                }}); },
+        function(doNext) { deleteDatabase("1", window.dbname); doNext(); },
+        function(doNext) { deleteDatabase("2", window.dbname, {
+                           onsuccess: finishTest}); },
+        ]);
+    function finishTest() {
+        debug("NOTE: Will FAIL with extra bogus h.onversionchange/h.close steps; https://bugs.webkit.org/show_bug.cgi?id=71129");
+        shouldBeEqualToString("window.steps.toString()",
+                              ["h.open",
+                               "h.open.onsuccess",
+                               "deleteDatabase(1)",
+                               "deleteDatabase(2)",
+                               "h.onversionchange",
+                               "deleteDatabase(1).onblocked",
+                               "deleteDatabase(2).onblocked",
+                               "h.close",
+                               "deleteDatabase(1).onsuccess",
+                               "deleteDatabase(2).onsuccess"
+                               ].toString());
+        done();
+    }
+}
+
+test();
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/storage/indexeddb/factory-deletedatabase.html b/LayoutTests/storage/indexeddb/factory-deletedatabase.html
new file mode 100644 (file)
index 0000000..413a2ff
--- /dev/null
@@ -0,0 +1,102 @@
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+<script src="../../fast/js/resources/js-test-post-function.js"></script>
+<script src="resources/shared.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+
+description("Test IndexedDB's webkitIndexedDB.deleteDatabase().");
+if (window.layoutTestController)
+    layoutTestController.waitUntilDone();
+
+function test()
+{
+    request = evalAndLog("webkitIndexedDB.open('database-to-delete')");
+    request.onsuccess = startSetVersion;
+    request.onerror = unexpectedErrorCallback;
+}
+
+function startSetVersion()
+{
+    db = evalAndLog("db = event.target.result");
+
+    request = evalAndLog("db.setVersion('new version')");
+    request.onsuccess = deleteExisting;
+    request.onerror = unexpectedErrorCallback;
+}
+
+function deleteExisting()
+{
+    window.trans = evalAndLog("trans = event.target.result");
+    shouldBeTrue("trans !== null");
+
+    store = evalAndLog("store = db.createObjectStore('storeName', null)");
+
+    window.index = evalAndLog("store.createIndex('indexName', '')");
+    shouldBeTrue("store.indexNames.contains('indexName')");
+
+    request = evalAndLog("store.add('value', 'key')");
+    request.onsuccess = getValue;
+    request.onerror = unexpectedErrorCallback;
+}
+
+function getValue()
+{
+    transaction = evalAndLog("db.transaction('storeName', webkitIDBTransaction.READ_WRITE)");
+    transaction.onabort = unexpectedErrorCallback;
+    var store = evalAndLog("store = transaction.objectStore('storeName')");
+
+    request = evalAndLog("store.get('key')");
+    request.onsuccess = addIndex;
+    request.onerror = unexpectedErrorCallback;
+}
+
+function addIndex()
+{
+    shouldBeEqualToString("event.target.result", "value");
+
+    request = evalAndLog("db.setVersion('new version')");
+    request.onsuccess = deleteDatabase;
+    request.onerror = unexpectedErrorCallback;
+}
+
+function deleteDatabase()
+{
+    db.onversionchange = function() { db.close(); }
+    request = evalAndLog("request = webkitIndexedDB.deleteDatabase('database-to-delete')");
+    request.onsuccess = reopenDatabase;
+    request.onerror = unexpectedErrorCallback;
+}
+
+function reopenDatabase()
+{
+    request = evalAndLog("webkitIndexedDB.open('database-to-delete')");
+    request.onsuccess = startSetVersionAgain;
+    request.onerror = unexpectedErrorCallback;
+}
+
+function startSetVersionAgain()
+{
+    rdb = evalAndLog("db = event.target.result");
+
+    request = evalAndLog("db.setVersion('new version')");
+    request.onsuccess = verifyNotFound;
+    request.onerror = unexpectedErrorCallback;
+}
+
+function verifyNotFound()
+{
+    shouldBe("db.objectStoreNames.length", "0");
+
+    done();
+}
+
+test();
+</script>
+</body>
+</html>
index 2728a29..96b0468 100644 (file)
@@ -34,7 +34,7 @@ window.dbname = 'test2'; window.ver = 1; window.steps = []
 'h1.setVersion.onblocked'
 'h1.setVersion.onsuccess'
 'h1.setVersion.transaction-complete'
-NOTE: Will FAIL with extra bogus h1.setVersion.onblocked step; crbug.com/100123
+NOTE: Will FAIL with extra bogus h1.setVersion.onblocked step; https://bugs.webkit.org/show_bug.cgi?id=71130
 FAIL window.steps.toString() should be h1.open,h1.open.onsuccess,h2.open,h2.open.onsuccess,h1.setVersion,h2.onversionchange,h2.close,h1.setVersion.onsuccess,h1.setVersion.transaction-complete. Was h1.open,h1.open.onsuccess,h2.open,h2.open.onsuccess,h1.setVersion,h2.onversionchange,h2.close,h1.setVersion.onblocked,h1.setVersion.onsuccess,h1.setVersion.transaction-complete.
 
 TEST: open and setVersion blocked if a VERSION_CHANGE transaction is running - close when blocked
@@ -71,7 +71,7 @@ window.dbname = 'test4'; window.ver = 1; window.steps = []
 'h1.setVersion.onsuccess'
 'h1.setVersion.transaction-complete'
 'h3.open.onsuccess'
-NOTE: Will FAIL with extra bogus h1.setVersion.onblocked step; crbug.com/100123
+NOTE: Will FAIL with extra bogus h1.setVersion.onblocked step; https://bugs.webkit.org/show_bug.cgi?id=71130
 FAIL window.steps.toString() should be h1.open,h1.open.onsuccess,h2.open,h2.open.onsuccess,h1.setVersion,h3.open,h2.close,h1.setVersion.onsuccess,h1.setVersion.transaction-complete,h3.open.onsuccess. Was h1.open,h1.open.onsuccess,h2.open,h2.open.onsuccess,h1.setVersion,h3.open,h2.close,h1.setVersion.onblocked,h1.setVersion.onsuccess,h1.setVersion.transaction-complete,h3.open.onsuccess.
 
 TEST: open blocked if a VERSION_CHANGE transaction is running
index 022d44b..2c890a9 100644 (file)
@@ -137,7 +137,7 @@ function test2() {
               ]);
 
     function finishTest() {
-        debug("NOTE: Will FAIL with extra bogus h1.setVersion.onblocked step; crbug.com/100123");
+        debug("NOTE: Will FAIL with extra bogus h1.setVersion.onblocked step; https://bugs.webkit.org/show_bug.cgi?id=71130");
         shouldBeEqualToString("window.steps.toString()",
                               ["h1.open",
                                "h1.open.onsuccess",
@@ -210,7 +210,7 @@ function test4() {
               ]);
 
     function finishTest() {
-        debug("NOTE: Will FAIL with extra bogus h1.setVersion.onblocked step; crbug.com/100123");
+        debug("NOTE: Will FAIL with extra bogus h1.setVersion.onblocked step; https://bugs.webkit.org/show_bug.cgi?id=71130");
         shouldBeEqualToString("window.steps.toString()",
                               ["h1.open",
                                "h1.open.onsuccess",
@@ -290,8 +290,6 @@ function test6() {
     }
 }
 
-var successfullyParsed = true;
-
 test();
 
 </script>
index 27092a6..2833f7f 100755 (executable)
@@ -1,3 +1,39 @@
+2011-10-29  Jochen Eisinger  <jochen@chromium.org>
+
+        Implement IDBFactory.deleteDatabase
+        https://bugs.webkit.org/show_bug.cgi?id=62622
+
+        Reviewed by Tony Chang.
+
+        Tests: storage/indexeddb/factory-deletedatabase-interactions.html
+               storage/indexeddb/factory-deletedatabase.html
+
+        * storage/IDBBackingStore.h:
+        * storage/IDBDatabaseBackendImpl.cpp:
+        (WebCore::IDBDatabaseBackendImpl::PendingDeleteCall::create):
+        (WebCore::IDBDatabaseBackendImpl::PendingDeleteCall::callbacks):
+        (WebCore::IDBDatabaseBackendImpl::PendingDeleteCall::PendingDeleteCall):
+        (WebCore::IDBDatabaseBackendImpl::IDBDatabaseBackendImpl):
+        (WebCore::IDBDatabaseBackendImpl::openInternal):
+        (WebCore::IDBDatabaseBackendImpl::processPendingCalls):
+        (WebCore::IDBDatabaseBackendImpl::openConnection):
+        (WebCore::IDBDatabaseBackendImpl::deleteDatabase):
+        * storage/IDBDatabaseBackendImpl.h:
+        * storage/IDBFactory.cpp:
+        (WebCore::IDBFactory::deleteDatabase):
+        * storage/IDBFactory.h:
+        * storage/IDBFactory.idl:
+        * storage/IDBFactoryBackendImpl.cpp:
+        (WebCore::IDBFactoryBackendImpl::deleteDatabase):
+        * storage/IDBFactoryBackendImpl.h:
+        * storage/IDBFactoryBackendInterface.h:
+        * storage/IDBLevelDBBackingStore.cpp:
+        (WebCore::deleteRange):
+        (WebCore::IDBLevelDBBackingStore::deleteDatabase):
+        * storage/IDBLevelDBBackingStore.h:
+        * storage/IDBRequest.cpp:
+        (WebCore::IDBRequest::dispatchEvent):
+
 2011-10-28  Robert Hogan  <robert@webkit.org>
 
         CSS 2.1 failure: dynamic-top-change-001 to 004 fail
index 6d881a5..6b0a040 100644 (file)
@@ -50,6 +50,7 @@ public:
     virtual bool getIDBDatabaseMetaData(const String& name, String& foundVersion, int64_t& foundId) = 0;
     virtual bool createIDBDatabaseMetaData(const String& name, const String& version, int64_t& rowId) = 0;
     virtual bool updateIDBDatabaseMetaData(int64_t rowId, const String& version) = 0;
+    virtual bool deleteDatabase(const String& name) = 0;
 
     virtual void getObjectStores(int64_t databaseId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundAutoIncrementFlags) = 0;
     virtual bool createObjectStore(int64_t databaseId, const String& name, const String& keyPath, bool autoIncrement, int64_t& assignedObjectStoreId) = 0;
index 9af22e4..59ff14a 100644 (file)
@@ -55,6 +55,22 @@ private:
     RefPtr<IDBCallbacks> m_callbacks;
 };
 
+class IDBDatabaseBackendImpl::PendingDeleteCall : public RefCounted<PendingDeleteCall> {
+public:
+    static PassRefPtr<PendingDeleteCall> create(PassRefPtr<IDBCallbacks> callbacks)
+    {
+        return adoptRef(new PendingDeleteCall(callbacks));
+    }
+    PassRefPtr<IDBCallbacks> callbacks() { return m_callbacks; }
+
+private:
+    PendingDeleteCall(PassRefPtr<IDBCallbacks> callbacks)
+        : m_callbacks(callbacks)
+    {
+    }
+    RefPtr<IDBCallbacks> m_callbacks;
+};
+
 class IDBDatabaseBackendImpl::PendingSetVersionCall : public RefCounted<PendingSetVersionCall> {
 public:
     static PassRefPtr<PendingSetVersionCall> create(const String& version, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks)
@@ -90,7 +106,13 @@ IDBDatabaseBackendImpl::IDBDatabaseBackendImpl(const String& name, IDBBackingSto
 
     bool success = m_backingStore->getIDBDatabaseMetaData(m_name, m_version, m_id);
     ASSERT(success == (m_id != InvalidId));
-    if (!success && !m_backingStore->createIDBDatabaseMetaData(m_name, m_version, m_id))
+    if (!success)
+        openInternal();
+}
+
+void IDBDatabaseBackendImpl::openInternal()
+{
+    if (!m_backingStore->createIDBDatabaseMetaData(m_name, m_version, m_id))
         ASSERT_NOT_REACHED(); // FIXME: Need better error handling.
     loadObjectStores();
 }
@@ -192,7 +214,7 @@ void IDBDatabaseBackendImpl::setVersion(const String& version, PassRefPtr<IDBCal
     }
     // FIXME: Only fire onBlocked if there are open connections after the
     // VersionChangeEvents are received, not just set up to fire.
-    // http://crbug.com/100123
+    // https://bugs.webkit.org/show_bug.cgi?id=71130
     if (m_databaseCallbacksSet.size() > 1) {
         callbacks->onBlocked();
         RefPtr<PendingSetVersionCall> pendingSetVersionCall = PendingSetVersionCall::create(version, callbacks, databaseCallbacks);
@@ -258,7 +280,21 @@ void IDBDatabaseBackendImpl::processPendingCalls()
         ASSERT(!ec);
     }
 
-    while (!m_runningVersionChangeTransaction && m_pendingSetVersionCalls.isEmpty() && !m_pendingOpenCalls.isEmpty()) {
+    if (m_runningVersionChangeTransaction || !m_pendingSetVersionCalls.isEmpty())
+        return;
+
+    // Pending calls may be requeued.
+    Deque<RefPtr<PendingDeleteCall> > pendingDeleteCalls;
+    m_pendingDeleteCalls.swap(pendingDeleteCalls);
+    while (!pendingDeleteCalls.isEmpty()) {
+        RefPtr<PendingDeleteCall> pendingDeleteCall = pendingDeleteCalls.takeFirst();
+        deleteDatabase(pendingDeleteCall->callbacks());
+    }
+
+    if (m_runningVersionChangeTransaction || !m_pendingSetVersionCalls.isEmpty() || !m_pendingDeleteCalls.isEmpty())
+        return;
+
+    while (!m_pendingOpenCalls.isEmpty()) {
         RefPtr<PendingOpenCall> pendingOpenCall = m_pendingOpenCalls.takeFirst();
         openConnection(pendingOpenCall->callbacks());
     }
@@ -284,10 +320,43 @@ void IDBDatabaseBackendImpl::open(PassRefPtr<IDBDatabaseCallbacks> callbacks)
 
 void IDBDatabaseBackendImpl::openConnection(PassRefPtr<IDBCallbacks> callbacks)
 {
-    if (m_runningVersionChangeTransaction || !m_pendingSetVersionCalls.isEmpty())
+    if (!m_pendingDeleteCalls.isEmpty() || m_runningVersionChangeTransaction || !m_pendingSetVersionCalls.isEmpty())
         m_pendingOpenCalls.append(PendingOpenCall::create(callbacks));
-    else
+    else {
+        if (m_id == InvalidId)
+            openInternal();
         callbacks->onSuccess(this);
+    }
+}
+
+void IDBDatabaseBackendImpl::deleteDatabase(PassRefPtr<IDBCallbacks> prpCallbacks)
+{
+    if (m_runningVersionChangeTransaction || !m_pendingSetVersionCalls.isEmpty()) {
+        m_pendingDeleteCalls.append(PendingDeleteCall::create(prpCallbacks));
+        return;
+    }
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    // FIXME: Only fire onVersionChange if there the connection isn't in
+    // the process of closing.
+    // https://bugs.webkit.org/show_bug.cgi?id=71129
+    for (DatabaseCallbacksSet::const_iterator it = m_databaseCallbacksSet.begin(); it != m_databaseCallbacksSet.end(); ++it)
+        (*it)->onVersionChange("");
+    // FIXME: Only fire onBlocked if there are open connections after the
+    // VersionChangeEvents are received, not just set up to fire.
+    // https://bugs.webkit.org/show_bug.cgi?id=71130
+    if (!m_databaseCallbacksSet.isEmpty()) {
+        m_pendingDeleteCalls.append(PendingDeleteCall::create(callbacks));
+        callbacks->onBlocked();
+        return;
+    }
+    if (!m_backingStore->deleteDatabase(m_name)) {
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
+        return;
+    }
+    m_version = "";
+    m_id = InvalidId;
+    m_objectStores.clear();
+    callbacks->onSuccess(SerializedScriptValue::nullValue());
 }
 
 void IDBDatabaseBackendImpl::close(PassRefPtr<IDBDatabaseCallbacks> prpCallbacks)
index e8b1084..7a5ce1d 100644 (file)
@@ -58,6 +58,7 @@ public:
     // FIXME: Rename "open" to something more descriptive, like registerFrontEndCallbacks.
     void open(PassRefPtr<IDBDatabaseCallbacks>);
     void openConnection(PassRefPtr<IDBCallbacks>);
+    void deleteDatabase(PassRefPtr<IDBCallbacks>);
 
     virtual String name() const { return m_name; }
     virtual String version() const { return m_version; }
@@ -77,6 +78,7 @@ public:
 private:
     IDBDatabaseBackendImpl(const String& name, IDBBackingStore* database, IDBTransactionCoordinator*, IDBFactoryBackendImpl*, const String& uniqueIdentifier);
 
+    void openInternal();
     void loadObjectStores();
     void processPendingCalls();
 
@@ -110,6 +112,9 @@ private:
     class PendingOpenCall;
     Deque<RefPtr<PendingOpenCall> > m_pendingOpenCalls;
 
+    class PendingDeleteCall;
+    Deque<RefPtr<PendingDeleteCall> > m_pendingDeleteCalls;
+
     typedef ListHashSet<RefPtr<IDBDatabaseCallbacks> > DatabaseCallbacksSet;
     DatabaseCallbacksSet m_databaseCallbacksSet;
 };
index ab16b7d..058c4d3 100644 (file)
@@ -42,6 +42,7 @@
 #include "IDBKey.h"
 #include "IDBKeyRange.h"
 #include "IDBRequest.h"
+#include "IDBVersionChangeRequest.h"
 #include "Page.h"
 #include "PageGroup.h"
 #include "SecurityOrigin.h"
@@ -98,6 +99,28 @@ PassRefPtr<IDBRequest> IDBFactory::open(ScriptExecutionContext* context, const S
     return request;
 }
 
+PassRefPtr<IDBVersionChangeRequest> IDBFactory::deleteDatabase(ScriptExecutionContext* context, const String& name, ExceptionCode& ec)
+{
+    if (!context->isDocument()) {
+        // FIXME: make this work with workers.
+        return 0;
+    }
+
+    Document* document = static_cast<Document*>(context);
+    if (!document->frame() || !document->page())
+        return 0;
+
+    if (name.isNull()) {
+        ec = IDBDatabaseException::NON_TRANSIENT_ERR;
+        return 0;
+    }
+
+    RefPtr<IDBVersionChangeRequest> request = IDBVersionChangeRequest::create(document, IDBAny::createNull(), "");
+    GroupSettings* groupSettings = document->page()->group().groupSettings();
+    m_factoryBackend->deleteDatabase(name, request, document->securityOrigin(), document->frame(), groupSettings->indexedDBDatabasePath());
+    return request;
+}
+
 short IDBFactory::cmp(PassRefPtr<IDBKey> first, PassRefPtr<IDBKey> second, ExceptionCode& ec)
 {
     ASSERT(first);
index 893421d..17bff1d 100644 (file)
@@ -44,6 +44,7 @@ namespace WebCore {
 class IDBKey;
 class IDBKeyRange;
 class IDBFactoryBackendInterface;
+class IDBVersionChangeRequest;
 class ScriptExecutionContext;
 
 class IDBFactory : public RefCounted<IDBFactory> {
@@ -57,6 +58,7 @@ public:
     PassRefPtr<IDBRequest> getDatabaseNames(ScriptExecutionContext*);
 
     PassRefPtr<IDBRequest> open(ScriptExecutionContext*, const String& name, ExceptionCode&);
+    PassRefPtr<IDBVersionChangeRequest> deleteDatabase(ScriptExecutionContext*, const String& name, ExceptionCode&);
 
     short cmp(PassRefPtr<IDBKey> first, PassRefPtr<IDBKey> second, ExceptionCode&);
 
index 23fa871..c44996b 100644 (file)
@@ -32,6 +32,8 @@ module storage {
 
         [CallWith=ScriptExecutionContext] IDBRequest open(in DOMString name)
             raises (IDBDatabaseException);
+        [CallWith=ScriptExecutionContext] IDBVersionChangeRequest deleteDatabase(in DOMString name)
+            raises (IDBDatabaseException);
 
         short cmp(in IDBKey first, in IDBKey second)
             raises (IDBDatabaseException);
index 444d6ac..d12481d 100644 (file)
@@ -122,6 +122,30 @@ void IDBFactoryBackendImpl::open(const String& name, PassRefPtr<IDBCallbacks> ca
     m_databaseBackendMap.set(uniqueIdentifier, databaseBackend.get());
 }
 
+void IDBFactoryBackendImpl::deleteDatabase(const String& name, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<SecurityOrigin> securityOrigin, Frame*, const String& dataDir)
+{
+    const String uniqueIdentifier = computeUniqueIdentifier(name, securityOrigin.get());
+
+    IDBDatabaseBackendMap::iterator it = m_databaseBackendMap.find(uniqueIdentifier);
+    if (it != m_databaseBackendMap.end()) {
+        // If there are any connections to the database, directly delete the
+        // database.
+        it->second->deleteDatabase(callbacks);
+        return;
+    }
+
+    // FIXME: Everything from now on should be done on another thread.
+    RefPtr<IDBBackingStore> backingStore = openBackingStore(securityOrigin, dataDir);
+    if (!backingStore) {
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
+        return;
+    }
+
+    RefPtr<IDBDatabaseBackendImpl> databaseBackend = IDBDatabaseBackendImpl::create(name, backingStore.get(), m_transactionCoordinator.get(), this, uniqueIdentifier);
+    m_databaseBackendMap.set(uniqueIdentifier, databaseBackend.get());
+    databaseBackend->deleteDatabase(callbacks);
+}
+
 PassRefPtr<IDBBackingStore> IDBFactoryBackendImpl::openBackingStore(PassRefPtr<SecurityOrigin> securityOrigin, const String& dataDir)
 {
     const String fileIdentifier = computeFileIdentifier(securityOrigin.get());
index 6ee9bb2..9c2f07f 100644 (file)
@@ -57,6 +57,7 @@ public:
 
     virtual void getDatabaseNames(PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir);
     virtual void open(const String& name, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir);
+    virtual void deleteDatabase(const String& name, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir);
 
 private:
     IDBFactoryBackendImpl();
index c4018ef..e92545d 100644 (file)
@@ -53,6 +53,7 @@ public:
 
     virtual void getDatabaseNames(PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir) = 0;
     virtual void open(const String& name, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir) = 0;
+    virtual void deleteDatabase(const String& name, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir) = 0;
 };
 
 } // namespace WebCore
index c5d6fb4..8cff91b 100644 (file)
@@ -239,6 +239,47 @@ bool IDBLevelDBBackingStore::updateIDBDatabaseMetaData(int64_t rowId, const Stri
     return true;
 }
 
+static bool deleteRange(LevelDBTransaction* transaction, const Vector<char>& begin, const Vector<char>& end)
+{
+    OwnPtr<LevelDBIterator> it = transaction->createIterator();
+    for (it->seek(begin); it->isValid() && compareKeys(it->key(), end) < 0; it->next()) {
+        if (!transaction->remove(it->key()))
+            return false;
+    }
+
+    return true;
+}
+
+
+bool IDBLevelDBBackingStore::deleteDatabase(const String& name)
+{
+    if (m_currentTransaction)
+        return false;
+
+    RefPtr<IDBLevelDBBackingStore::Transaction> transaction = IDBLevelDBBackingStore::Transaction::create(this);
+    transaction->begin();
+
+    int64_t databaseId;
+    String version;
+    if (!getIDBDatabaseMetaData(name, version, databaseId)) {
+        transaction->rollback();
+        return true;
+    }
+
+    const Vector<char> startKey = DatabaseMetaDataKey::encode(databaseId, DatabaseMetaDataKey::kOriginName);
+    const Vector<char> stopKey = DatabaseMetaDataKey::encode(databaseId + 1, DatabaseMetaDataKey::kOriginName);
+    if (!deleteRange(m_currentTransaction.get(), startKey, stopKey)) {
+        transaction->rollback();
+        return false;
+    }
+
+    const Vector<char> key = DatabaseNameKey::encode(m_identifier, name);
+    m_currentTransaction->remove(key);
+
+    transaction->commit();
+    return true;
+}
+
 static bool checkObjectStoreAndMetaDataType(const LevelDBIterator* it, const Vector<char>& stopKey, int64_t objectStoreId, int64_t metaDataType)
 {
     if (!it->isValid() || compareKeys(it->key(), stopKey) >= 0)
@@ -418,17 +459,6 @@ bool IDBLevelDBBackingStore::createObjectStore(int64_t databaseId, const String&
     return true;
 }
 
-static bool deleteRange(LevelDBTransaction* transaction, const Vector<char>& begin, const Vector<char>& end)
-{
-    OwnPtr<LevelDBIterator> it = transaction->createIterator();
-    for (it->seek(begin); it->isValid() && compareKeys(it->key(), end) < 0; it->next()) {
-        if (!transaction->remove(it->key()))
-            return false;
-    }
-
-    return true;
-}
-
 void IDBLevelDBBackingStore::deleteObjectStore(int64_t databaseId, int64_t objectStoreId)
 {
     ASSERT(m_currentTransaction);
@@ -1382,8 +1412,6 @@ bool IDBLevelDBBackingStore::backingStoreExists(SecurityOrigin* securityOrigin,
     return fileExists(path+"/CURRENT");
 }
 
-// FIXME: deleteDatabase should be part of IDBBackingStore.
-
 } // namespace WebCore
 
 #endif // USE(LEVELDB)
index 9a37c0d..db24e51 100644 (file)
@@ -48,6 +48,7 @@ public:
     virtual bool getIDBDatabaseMetaData(const String& name, String& foundVersion, int64_t& foundId);
     virtual bool createIDBDatabaseMetaData(const String& name, const String& version, int64_t& rowId);
     virtual bool updateIDBDatabaseMetaData(int64_t rowId, const String& version);
+    virtual bool deleteDatabase(const String& name);
 
     virtual void getObjectStores(int64_t databaseId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundAutoIncrementFlags);
     virtual bool createObjectStore(int64_t databaseId, const String& name, const String& keyPath, bool autoIncrement, int64_t& assignedObjectStoreId);
index f8fcce8..d1256f3 100644 (file)
@@ -301,8 +301,8 @@ bool IDBRequest::dispatchEvent(PassRefPtr<Event> event)
     ASSERT(event->type() == eventNames().successEvent || event->type() == eventNames().errorEvent || event->type() == eventNames().blockedEvent);
     bool dontPreventDefault = IDBEventDispatcher::dispatch(event.get(), targets);
 
-    // If the result was of type IDBCursor, then we'll fire again.
-    if (m_result && m_result->type() != IDBAny::IDBCursorType && m_result->type() != IDBAny::IDBCursorWithValueType)
+    // If the result was of type IDBCursor, or a onBlocked event, then we'll fire again.
+    if (event->type() != eventNames().blockedEvent && m_result && m_result->type() != IDBAny::IDBCursorType && m_result->type() != IDBAny::IDBCursorWithValueType)
         m_finished = true;
 
     if (m_transaction) {
index 3fa7cc9..215d6fc 100644 (file)
@@ -1,3 +1,19 @@
+2011-10-29  Jochen Eisinger  <jochen@chromium.org>
+
+        Implement IDBFactory.deleteDatabase
+        https://bugs.webkit.org/show_bug.cgi?id=62622
+
+        Reviewed by Tony Chang.
+
+        * src/IDBFactoryBackendProxy.cpp:
+        (WebKit::IDBFactoryBackendProxy::deleteDatabase):
+        * src/IDBFactoryBackendProxy.h:
+        * src/WebIDBFactoryImpl.cpp:
+        (WebKit::WebIDBFactoryImpl::getDatabaseNames):
+        (WebKit::WebIDBFactoryImpl::open):
+        (WebKit::WebIDBFactoryImpl::deleteDatabase):
+        * src/WebIDBFactoryImpl.h:
+
 2011-10-28  Sadrul Habib Chowdhury  <sadrul@chromium.org>
  
         Add support for sending scroll-update events from EventSender.
index 7a62e50..7b6038b 100755 (executable)
@@ -91,6 +91,19 @@ void IDBFactoryBackendProxy::open(const String& name, PassRefPtr<IDBCallbacks> c
     m_webIDBFactory->open(name, new WebIDBCallbacksImpl(callbacks), origin, webFrame, dataDir);
 }
 
+void IDBFactoryBackendProxy::deleteDatabase(const String& name, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<SecurityOrigin> prpOrigin, Frame* frame, const String& dataDir)
+{
+    WebSecurityOrigin origin(prpOrigin);
+    WebFrameImpl* webFrame = WebFrameImpl::fromFrame(frame);
+    WebViewImpl* webView = webFrame->viewImpl();
+    if (webView->permissionClient() && !webView->permissionClient()->allowIndexedDB(webFrame, name, origin)) {
+        callbacks->onError(WebIDBDatabaseError(0, "The user denied permission to access the database."));
+        return;
+    }
+
+    m_webIDBFactory->deleteDatabase(name, new WebIDBCallbacksImpl(callbacks), origin, webFrame, dataDir);
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(INDEXED_DATABASE)
index baf1e05..e14b8ce 100755 (executable)
@@ -46,6 +46,7 @@ public:
 
     virtual void getDatabaseNames(PassRefPtr<WebCore::IDBCallbacks>, PassRefPtr<WebCore::SecurityOrigin>, WebCore::Frame*, const String& dataDir);
     virtual void open(const String& name, PassRefPtr<WebCore::IDBCallbacks>, PassRefPtr<WebCore::SecurityOrigin>, WebCore::Frame*, const String& dataDir);
+    virtual void deleteDatabase(const String& name, PassRefPtr<WebCore::IDBCallbacks>, PassRefPtr<WebCore::SecurityOrigin>, WebCore::Frame*, const String& dataDir);
 
 private:
     IDBFactoryBackendProxy();
index 1c0968a..84c1a3d 100755 (executable)
@@ -60,17 +60,18 @@ WebIDBFactoryImpl::~WebIDBFactoryImpl()
 
 void WebIDBFactoryImpl::getDatabaseNames(WebIDBCallbacks* callbacks, const WebSecurityOrigin& origin, WebFrame*, const WebString& dataDir)
 {
-    WebString path = dataDir;
-
-    m_idbFactoryBackend->getDatabaseNames(IDBCallbacksProxy::create(adoptPtr(callbacks)), origin, 0, path);
+    m_idbFactoryBackend->getDatabaseNames(IDBCallbacksProxy::create(adoptPtr(callbacks)), origin, 0, dataDir);
 }
 
 
 void WebIDBFactoryImpl::open(const WebString& name, WebIDBCallbacks* callbacks, const WebSecurityOrigin& origin, WebFrame*, const WebString& dataDir)
 {
-    WebString path = dataDir;
+    m_idbFactoryBackend->open(name, IDBCallbacksProxy::create(adoptPtr(callbacks)), origin, 0, dataDir);
+}
 
-    m_idbFactoryBackend->open(name, IDBCallbacksProxy::create(adoptPtr(callbacks)), origin, 0, path);
+void WebIDBFactoryImpl::deleteDatabase(const WebString& name, WebIDBCallbacks* callbacks, const WebSecurityOrigin& origin, WebFrame*, const WebString& dataDir)
+{
+    m_idbFactoryBackend->deleteDatabase(name, IDBCallbacksProxy::create(adoptPtr(callbacks)), origin, 0, dataDir);
 }
 
 } // namespace WebKit
index 3e01d1a..b3e474d 100755 (executable)
@@ -46,6 +46,7 @@ public:
 
     virtual void getDatabaseNames(WebIDBCallbacks*, const WebSecurityOrigin&, WebFrame*, const WebString& dataDir);
     virtual void open(const WebString& name, WebIDBCallbacks*, const WebSecurityOrigin&, WebFrame*, const WebString& dataDir);
+    virtual void deleteDatabase(const WebString& name, WebIDBCallbacks*, const WebSecurityOrigin&, WebFrame*, const WebString& dataDir);
 
 private:
     WTF::RefPtr<WebCore::IDBFactoryBackendInterface> m_idbFactoryBackend;