WebCore: Adding support for the optional creation callback that could be
authordumi@chromium.org <dumi@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Mar 2010 21:48:49 +0000 (21:48 +0000)
committerdumi@chromium.org <dumi@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Mar 2010 21:48:49 +0000 (21:48 +0000)
passed to openDatabase().

Reviewed by Adam Barth.

Test: storage/open-database-creation-callback.html

https://bugs.webkit.org/show_bug.cgi?id=34726

* Android.jscbindings.mk
* Android.v8bindings.mk
* GNUmakefile.am:
* WebCore.gypi:
* WebCore.pro:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::openDatabase):
* bindings/js/JSDatabaseCallback.cpp: Added.
(WebCore::JSDatabaseCallback::JSDatabaseCallback):
(WebCore::JSDatabaseCallback::~JSDatabaseCallback):
(WebCore::JSDatabaseCallback::handleEvent):
* bindings/js/JSDatabaseCallback.h: Added.
(WebCore::JSDatabaseCallback::create):
* bindings/v8/custom/V8DOMWindowCustom.cpp:
(WebCore::V8DOMWindow::openDatabaseCallback):
* bindings/v8/custom/V8DatabaseCallback.cpp: Added.
(WebCore::V8DatabaseCallback::V8DatabaseCallback):
(WebCore::V8DatabaseCallback::~V8DatabaseCallback):
(WebCore::V8DatabaseCallback::handleEvent):
* bindings/v8/custom/V8DatabaseCallback.h: Added.
(WebCore::V8DatabaseCallback::create):
* page/DOMWindow.cpp:
(WebCore::DOMWindow::openDatabase):
* page/DOMWindow.h:
* page/DOMWindow.idl:
* storage/Database.cpp:
(WebCore::DatabaseCreationCallbackTask::create):
(WebCore::DatabaseCreationCallbackTask::performTask):
(WebCore::DatabaseCreationCallbackTask::DatabaseCreationCallbackTask):
(WebCore::Database::openDatabase):
(WebCore::Database::Database):
(WebCore::Database::performOpenAndVerify):
(WebCore::Database::performCreationCallback):
* storage/Database.h:
(WebCore::Database::isNew):
* storage/DatabaseCallback.h: Added.
(WebCore::DatabaseCallback::~DatabaseCallback):
* workers/WorkerContext.cpp:
(WebCore::WorkerContext::openDatabase):
* workers/WorkerContext.h:

LayoutTests: Adding a test to test the creation callback passed to
openDatabase() and another one to make sure it is executed in the
correct world.

Reviewed by Adam Barth.

https://bugs.webkit.org/show_bug.cgi?id=34726

* storage/open-database-creation-callback-expected.txt: Added.
* storage/open-database-creation-callback.html: Added.
* storage/open-database-creation-callback-isolated-world-expected.txt: Added.
* storage/open-database-creation-callback-isolated-world.html: Added.

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

28 files changed:
LayoutTests/ChangeLog
LayoutTests/storage/open-database-creation-callback-expected.txt [new file with mode: 0644]
LayoutTests/storage/open-database-creation-callback-isolated-world-expected.txt [new file with mode: 0644]
LayoutTests/storage/open-database-creation-callback-isolated-world.html [new file with mode: 0644]
LayoutTests/storage/open-database-creation-callback.html [new file with mode: 0644]
WebCore/Android.jscbindings.mk
WebCore/Android.v8bindings.mk
WebCore/ChangeLog
WebCore/GNUmakefile.am
WebCore/WebCore.gypi
WebCore/WebCore.pro
WebCore/WebCore.vcproj/WebCore.vcproj
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/bindings/js/JSDOMWindowCustom.cpp
WebCore/bindings/js/JSDatabaseCallback.cpp [new file with mode: 0644]
WebCore/bindings/js/JSDatabaseCallback.h [new file with mode: 0644]
WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp
WebCore/bindings/v8/custom/V8DatabaseCallback.cpp [new file with mode: 0644]
WebCore/bindings/v8/custom/V8DatabaseCallback.h [new file with mode: 0644]
WebCore/dom/Document.cpp
WebCore/page/DOMWindow.cpp
WebCore/page/DOMWindow.h
WebCore/page/DOMWindow.idl
WebCore/storage/Database.cpp
WebCore/storage/Database.h
WebCore/storage/DatabaseCallback.h [new file with mode: 0644]
WebCore/workers/WorkerContext.cpp
WebCore/workers/WorkerContext.h

index bf9ac6b1905965f33314d3a0d6ea774de4b14a0e..b29883d7cdc1ad3b6f7be2b2044cdc62773e259f 100644 (file)
@@ -1,3 +1,18 @@
+2010-03-03  Dumitru Daniliuc  <dumi@chromium.org>
+
+        Reviewed by Adam Barth.
+
+        Adding a test to test the creation callback passed to
+        openDatabase() and another one to make sure it is executed in the
+        correct world.
+
+        https://bugs.webkit.org/show_bug.cgi?id=34726
+
+        * storage/open-database-creation-callback-expected.txt: Added.
+        * storage/open-database-creation-callback.html: Added.
+        * storage/open-database-creation-callback-isolated-world-expected.txt: Added.
+        * storage/open-database-creation-callback-isolated-world.html: Added.
+
 2010-03-03  Alexey Proskuryakov  <ap@apple.com>
 
         Not reviewed.
diff --git a/LayoutTests/storage/open-database-creation-callback-expected.txt b/LayoutTests/storage/open-database-creation-callback-expected.txt
new file mode 100644 (file)
index 0000000..d86ab72
--- /dev/null
@@ -0,0 +1,2 @@
+This test tests openDatabase()'s creation callback.
+
diff --git a/LayoutTests/storage/open-database-creation-callback-isolated-world-expected.txt b/LayoutTests/storage/open-database-creation-callback-isolated-world-expected.txt
new file mode 100644 (file)
index 0000000..567af33
--- /dev/null
@@ -0,0 +1,3 @@
+ALERT: undefined
+This test tests that the openDatabase() creation callback is called in the right world.
+
diff --git a/LayoutTests/storage/open-database-creation-callback-isolated-world.html b/LayoutTests/storage/open-database-creation-callback-isolated-world.html
new file mode 100644 (file)
index 0000000..15bf45d
--- /dev/null
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<body>
+This test tests that the openDatabase() creation callback is called in the right world.
+<div id="console"></div>
+<script>
+function done()
+{
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+
+function creationCallback(db)
+{
+    alert("FAIL: Visible in isolated world.");
+    done();
+}
+
+document.body.foo = "FAIL: document.body.foo visible in isolated world.";
+
+if (window.layoutTestController) {
+    layoutTestController.clearAllDatabases();
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+    layoutTestController.evaluateScriptInIsolatedWorld(
+        0,
+        "function creationCallback(db)\n" +
+        "{\n" +
+        "    alert(document.body.foo);\n" +
+        "    window.location='javascript:done()';\n" +
+        "}\n" +
+        "var db = openDatabase('OpenDatabaseCreationCallbackIsolatedWorld', '1.0', '', 1, creationCallback);");
+}
+</script>
+</body>
+</html>
diff --git a/LayoutTests/storage/open-database-creation-callback.html b/LayoutTests/storage/open-database-creation-callback.html
new file mode 100644 (file)
index 0000000..ac24942
--- /dev/null
@@ -0,0 +1,90 @@
+<html>
+<head>
+<script>
+function log(message)
+{
+    document.getElementById("console").innerHTML += message + "<br>";
+}
+
+function finishTest()
+{
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+
+function runTest()
+{
+    if (window.layoutTestController) {
+        layoutTestController.clearAllDatabases();
+        layoutTestController.setDatabaseQuota(32768);
+        layoutTestController.dumpDatabaseCallbacks();
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+
+    var transactionsRun = 0;
+
+    // Open a new database with a creation callback, and make sure the creation callback is queued
+    var creationCallbackCalled1 = false;
+    var db1 = openDatabase("OpenDatabaseCreationCallback1", "1.0", "", 1,
+                           function(db) {
+                               creationCallbackCalled1 = true;
+                               if (db.version != "") {
+                                   log("Creation callback was called with a database with version " +
+                                       db.version + "; empty string expected.");
+                                   finishTest();
+                               }
+                           });
+
+    // Putting this code inside a transaction on 'db1' makes sure that it is executed after
+    // the creation callback is.
+    db1.transaction(function(tx) {
+        if (!creationCallbackCalled1) {
+            log("Creation callback for db1 was not called.");
+            finishTest();
+        }
+        if (++transactionsRun == 2)
+            finishTest();
+    });
+
+    // Try to open another handle to the same database.
+    // Since the version of this database is "" (empty string), openDatabase() should return
+    // a null handle and throw a INVALID_STATE_ERR exception.
+    var db1Fail = null;
+    try {
+        db1Fail = openDatabase("OpenDatabaseCreationCallback1", "1.0", "", 1);
+        log("This statement should not have been executed; an INVALID_STATE_ERR exception should've been thrown.");
+        finishTest();
+    } catch(err) {
+        if (db1Fail) {
+            log("db1Fail should have been null.");
+            finishTest();
+        }
+    }
+
+    // Open a handle to another database, first without a creation callback, then with one.
+    // Make sure the creation callback is not called.
+    var creationCallbackCalled2 = false;
+    var db2 = openDatabase("OpenDatabaseCreationCallback2", "1.0", "", 1);
+    db2 = openDatabase("OpenDatabaseCreationCallback2", "1.0", "", 1,
+                       function(db) { creationCallbackCalled2 = true; });
+    db2.transaction(function(tx) {
+        if (creationCallbackCalled2) {
+            log("Creation callback for db2 should not have been called.");
+            finishTest();
+        }
+        if (++transactionsRun == 2)
+            finishTest();
+    });
+}
+
+</script>
+</head>
+
+<body onload="runTest()">
+This test tests openDatabase()'s creation callback.
+<pre id="console">
+</pre>
+</body>
+
+</html>
index b330b11091e539c12d2cb424f29d7f2a934d8733..f07ba6840aae94345474caed4b6e76872ce29d5a 100644 (file)
@@ -80,6 +80,7 @@ LOCAL_SRC_FILES += \
        bindings/js/JSCustomSQLTransactionCallback.cpp \
        bindings/js/JSCustomSQLTransactionErrorCallback.cpp \
        bindings/js/JSCustomVoidCallback.cpp \
+       bindings/js/JSDatabaseCallback.cpp \
        bindings/js/JSDesktopNotificationsCustom.cpp \
        bindings/js/JSDOMApplicationCacheCustom.cpp \
        bindings/js/JSDOMBinding.cpp \
index fecf531c164d8554af6b6c8c0a357d3f7d955604..c829659aaebca835f21ca4e2948ecc4c3f066a9b 100644 (file)
@@ -108,6 +108,7 @@ LOCAL_SRC_FILES += \
        bindings/v8/custom/V8DOMSelectionCustom.cpp \
        bindings/v8/custom/V8DOMWindowCustom.cpp \
        bindings/v8/custom/V8DataGridColumnListCustom.cpp \
+       bindings/v8/custom/V8DatabaseCallback.cpp \
        bindings/v8/custom/V8DatabaseCustom.cpp \
        bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp \
        bindings/v8/custom/V8DocumentCustom.cpp \
index e63384558d1e9d876ec6e5c3d1058268c4e5e08c..6581f2d0b4caebf153e7f5280169b5c999559cb3 100644 (file)
@@ -1,3 +1,57 @@
+2010-03-03  Dumitru Daniliuc  <dumi@chromium.org>
+
+        Reviewed by Adam Barth.
+
+        Adding support for the optional creation callback that could be
+        passed to openDatabase().
+
+        Test: storage/open-database-creation-callback.html
+
+        https://bugs.webkit.org/show_bug.cgi?id=34726
+
+        * Android.jscbindings.mk
+        * Android.v8bindings.mk
+        * GNUmakefile.am:
+        * WebCore.gypi:
+        * WebCore.pro:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/JSDOMWindowCustom.cpp:
+        (WebCore::JSDOMWindow::openDatabase):
+        * bindings/js/JSDatabaseCallback.cpp: Added.
+        (WebCore::JSDatabaseCallback::JSDatabaseCallback):
+        (WebCore::JSDatabaseCallback::~JSDatabaseCallback):
+        (WebCore::JSDatabaseCallback::handleEvent):
+        * bindings/js/JSDatabaseCallback.h: Added.
+        (WebCore::JSDatabaseCallback::create):
+        * bindings/v8/custom/V8DOMWindowCustom.cpp:
+        (WebCore::V8DOMWindow::openDatabaseCallback):
+        * bindings/v8/custom/V8DatabaseCallback.cpp: Added.
+        (WebCore::V8DatabaseCallback::V8DatabaseCallback):
+        (WebCore::V8DatabaseCallback::~V8DatabaseCallback):
+        (WebCore::V8DatabaseCallback::handleEvent):
+        * bindings/v8/custom/V8DatabaseCallback.h: Added.
+        (WebCore::V8DatabaseCallback::create):
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::openDatabase):
+        * page/DOMWindow.h:
+        * page/DOMWindow.idl:
+        * storage/Database.cpp:
+        (WebCore::DatabaseCreationCallbackTask::create):
+        (WebCore::DatabaseCreationCallbackTask::performTask):
+        (WebCore::DatabaseCreationCallbackTask::DatabaseCreationCallbackTask):
+        (WebCore::Database::openDatabase):
+        (WebCore::Database::Database):
+        (WebCore::Database::performOpenAndVerify):
+        (WebCore::Database::performCreationCallback):
+        * storage/Database.h:
+        (WebCore::Database::isNew):
+        * storage/DatabaseCallback.h: Added.
+        (WebCore::DatabaseCallback::~DatabaseCallback):
+        * workers/WorkerContext.cpp:
+        (WebCore::WorkerContext::openDatabase):
+        * workers/WorkerContext.h:
+
 2010-03-03  Alexander Pavlov  <apavlov@chromium.org>
 
         Reviewed by Pavel Feldman.
index 15b13ba3f4399c1cab330aea577b22e6db8a9919..a0ace5c9b88440ecdcb11988ef9ee63d6b3e08da 100644 (file)
@@ -2228,6 +2228,8 @@ webcore_sources += \
        WebCore/bindings/js/JSCustomSQLTransactionCallback.h \
        WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp \
        WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.h \
+       WebCore/bindings/js/JSDatabaseCallback.cpp \
+       WebCore/bindings/js/JSDatabaseCallback.h \
        WebCore/bindings/js/JSDatabaseCustom.cpp \
        WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp \
        WebCore/bindings/js/JSSQLTransactionCustom.cpp \
@@ -2248,6 +2250,7 @@ webcore_sources += \
        WebCore/storage/Database.h \
        WebCore/storage/DatabaseAuthorizer.cpp \
        WebCore/storage/DatabaseAuthorizer.h \
+       WebCore/storage/DatabaseCallback.h \
        WebCore/storage/DatabaseDetails.h \
        WebCore/storage/DatabaseTask.cpp \
        WebCore/storage/DatabaseTask.h \
index 182e209ce9109d4fbd86492942667bb6dca1290f..9dd525934ffaee195b9c46c78056171d2053be9a 100644 (file)
             'bindings/v8/custom/V8CustomVoidCallback.h',
             'bindings/v8/custom/V8CustomXPathNSResolver.cpp',
             'bindings/v8/custom/V8CustomXPathNSResolver.h',
+            'bindings/v8/custom/V8DatabaseCallback.cpp',
+            'bindings/v8/custom/V8DatabaseCallback.h',
             'bindings/v8/custom/V8DatabaseCustom.cpp',
             'bindings/v8/custom/V8DataGridColumnListCustom.cpp',
             'bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp',
             'storage/Database.h',
             'storage/DatabaseAuthorizer.cpp',
             'storage/DatabaseAuthorizer.h',
+            'storage/DatabaseCallback.h',
             'storage/DatabaseDetails.h',
             'storage/DatabaseTask.cpp',
             'storage/DatabaseTask.h',
index 84e5c863135022e290ebb0d8f8071d07c90067f2..4f23242ff49e07c221a4c5f01b55de5d60a36203 100644 (file)
@@ -1012,6 +1012,7 @@ HEADERS += \
     bindings/js/JSCustomSQLTransactionErrorCallback.h \
     bindings/js/JSCustomVoidCallback.h \
     bindings/js/JSCustomXPathNSResolver.h \
+    bindings/js/JSDatabaseCallback.h \
     bindings/js/JSDataGridDataSource.h \
     bindings/js/JSDOMBinding.h \
     bindings/js/JSDOMGlobalObject.h \
@@ -2220,6 +2221,7 @@ contains(DEFINES, ENABLE_DATABASE=1) {
         bindings/js/JSCustomSQLStatementErrorCallback.cpp \
         bindings/js/JSCustomSQLTransactionCallback.cpp \
         bindings/js/JSCustomSQLTransactionErrorCallback.cpp \
+        bindings/js/JSDatabaseCallback.cpp \
         bindings/js/JSDatabaseCustom.cpp \
         bindings/js/JSSQLResultSetRowListCustom.cpp \
         bindings/js/JSSQLTransactionCustom.cpp
@@ -2230,6 +2232,7 @@ contains(DEFINES, ENABLE_DOM_STORAGE=1) {
         storage/ChangeVersionWrapper.h \
         storage/DatabaseAuthorizer.h \
         storage/Database.h \
+        storage/DatabaseCallback.h \
         storage/DatabaseTask.h \
         storage/DatabaseThread.h \
         storage/DatabaseTracker.h \
index 09aba61325fe5648398eb2d08d7fc607582aa2f2..53abc32c7cc39e779f6fc15a73cee5b11b8f5c76 100644 (file)
                                        RelativePath="..\bindings\js\JSCustomXPathNSResolver.h"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath="..\bindings\js\JSDatabaseCallback.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath="..\bindings\js\JSDatabaseCallback.h"\r
+                                       >\r
+                               </File>\r
                                <File\r
                                        RelativePath="..\bindings\js\JSDatabaseCustom.cpp"\r
                                        >\r
                                RelativePath="..\storage\DatabaseAuthorizer.h"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\storage\DatabaseCallback.h"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\storage\DatabaseTask.cpp"\r
                                >\r
index c579da5ab14156460ee9183724428d1a0e16b854..e61f7c94ee77b820f7217de68cbc011e3a36fbce 100644 (file)
                B5A684240FFABEAA00D24689 /* SQLiteFileSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5A684230FFABEAA00D24689 /* SQLiteFileSystem.cpp */; };
                B5C1123B102B6C4600096578 /* SQLTransactionCoordinator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5C11239102B6C4600096578 /* SQLTransactionCoordinator.cpp */; };
                B5C1123C102B6C4600096578 /* SQLTransactionCoordinator.h in Headers */ = {isa = PBXBuildFile; fileRef = B5C1123A102B6C4600096578 /* SQLTransactionCoordinator.h */; };
+               B5D3601A112F8B560048DEA8 /* DatabaseCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = B5D36019112F8B560048DEA8 /* DatabaseCallback.h */; };
+               B5D3601D112F8BA00048DEA8 /* JSDatabaseCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = B5D3601C112F8BA00048DEA8 /* JSDatabaseCallback.h */; };
+               B5D3601F112F8BA80048DEA8 /* JSDatabaseCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5D3601E112F8BA80048DEA8 /* JSDatabaseCallback.cpp */; };
                B71FE6DF11091CB300DAEF77 /* PrintContext.h in Headers */ = {isa = PBXBuildFile; fileRef = B776D43A1104525D00BEB0EC /* PrintContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
                B776D43D1104527500BEB0EC /* PrintContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B776D43C1104527500BEB0EC /* PrintContext.cpp */; };
                BC00F0040E0A185500FD04E3 /* DOMFile.h in Headers */ = {isa = PBXBuildFile; fileRef = BC00EFFE0E0A185500FD04E3 /* DOMFile.h */; };
                B5A684230FFABEAA00D24689 /* SQLiteFileSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SQLiteFileSystem.cpp; path = sql/SQLiteFileSystem.cpp; sourceTree = "<group>"; };
                B5C11239102B6C4600096578 /* SQLTransactionCoordinator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SQLTransactionCoordinator.cpp; sourceTree = "<group>"; };
                B5C1123A102B6C4600096578 /* SQLTransactionCoordinator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLTransactionCoordinator.h; sourceTree = "<group>"; };
+               B5D36019112F8B560048DEA8 /* DatabaseCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseCallback.h; sourceTree = "<group>"; };
+               B5D3601C112F8BA00048DEA8 /* JSDatabaseCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDatabaseCallback.h; sourceTree = "<group>"; };
+               B5D3601E112F8BA80048DEA8 /* JSDatabaseCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDatabaseCallback.cpp; sourceTree = "<group>"; };
                B776D43A1104525D00BEB0EC /* PrintContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrintContext.h; sourceTree = "<group>"; };
                B776D43C1104527500BEB0EC /* PrintContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrintContext.cpp; sourceTree = "<group>"; };
                BC00EFFE0E0A185500FD04E3 /* DOMFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMFile.h; sourceTree = "<group>"; };
                                519611600CAC56570010A80C /* Database.idl */,
                                51A45B550CAD7FD7000D2BE9 /* DatabaseAuthorizer.cpp */,
                                51A45B540CAD7FD7000D2BE9 /* DatabaseAuthorizer.h */,
+                               B5D36019112F8B560048DEA8 /* DatabaseCallback.h */,
                                5116D9750CF177BD00C2B84D /* DatabaseDetails.h */,
                                519611E90CAC749C0010A80C /* DatabaseTask.cpp */,
                                519611E80CAC749C0010A80C /* DatabaseTask.h */,
                                A8EDB03C1016849400FE8113 /* DOMObjectWithSVGContext.h */,
                                1432E8480C51493F00B1500F /* GCController.cpp */,
                                1432E8460C51493800B1500F /* GCController.h */,
+                               B5D3601E112F8BA80048DEA8 /* JSDatabaseCallback.cpp */,
+                               B5D3601C112F8BA00048DEA8 /* JSDatabaseCallback.h */,
                                93B70D4709EB0C7C009D8468 /* JSDOMBinding.cpp */,
                                93B70D4809EB0C7C009D8468 /* JSDOMBinding.h */,
                                E1C36CBC0EB08062007410BC /* JSDOMGlobalObject.cpp */,
                                0BC2C7781134A8FC000B2F61 /* CanvasSurface.h in Headers */,
                                E462A4A1113E71BE004A4220 /* IntPointHash.h in Headers */,
                                CE172E011136E8CE0062A533 /* ZoomMode.h in Headers */,
+                               B5D3601A112F8B560048DEA8 /* DatabaseCallback.h in Headers */,
+                               B5D3601D112F8BA00048DEA8 /* JSDatabaseCallback.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                E1698264113467F300894115 /* JavaRuntimeObject.cpp in Sources */,
                                596229781133EFD700DC4CBB /* GeolocationPositionCache.cpp in Sources */,
                                0BC2C7771134A8FC000B2F61 /* CanvasSurface.cpp in Sources */,
+                               B5D3601F112F8BA80048DEA8 /* JSDatabaseCallback.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index c71761cdf109d833eeeff2904ad0f0f99a8ca80f..0af6821b6ab4df662ce31183536f5ed17e3a47ea 100644 (file)
@@ -23,6 +23,7 @@
 #include "AtomicString.h"
 #include "Base64.h"
 #include "Chrome.h"
+#include "Database.h"
 #include "DOMWindow.h"
 #include "Document.h"
 #include "ExceptionCode.h"
@@ -36,6 +37,8 @@
 #include "HTMLDocument.h"
 #include "History.h"
 #include "JSAudioConstructor.h"
+#include "JSDatabase.h"
+#include "JSDatabaseCallback.h"
 #include "JSDOMWindowShell.h"
 #include "JSEvent.h"
 #include "JSEventListener.h"
@@ -1017,6 +1020,24 @@ JSValue JSDOMWindow::removeEventListener(ExecState* exec, const ArgList& args)
     return jsUndefined();
 }
 
+JSValue JSDOMWindow::openDatabase(ExecState* exec, const ArgList& args)
+{
+    if (!allowsAccessFrom(exec) || (args.size() < 4))
+        return jsUndefined();
+    ExceptionCode ec = 0;
+    const UString& name = args.at(0).toString(exec);
+    const UString& version = args.at(1).toString(exec);
+    const UString& displayName = args.at(2).toString(exec);
+    unsigned long estimatedSize = args.at(3).toInt32(exec);
+    RefPtr<DatabaseCallback> creationCallback;
+    if ((args.size() >= 5) && args.at(4).isObject())
+        creationCallback = JSDatabaseCallback::create(asObject(args.at(4)), globalObject());
+
+    JSValue result = toJS(exec, globalObject(), WTF::getPtr(impl()->openDatabase(name, version, displayName, estimatedSize, creationCallback.release(), ec)));
+    setDOMException(exec, ec);
+    return result;
+}
+
 DOMWindow* toDOMWindow(JSValue value)
 {
     if (!value.isObject())
diff --git a/WebCore/bindings/js/JSDatabaseCallback.cpp b/WebCore/bindings/js/JSDatabaseCallback.cpp
new file mode 100644 (file)
index 0000000..c75a6e5
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSDatabaseCallback.h"
+
+#if ENABLE(DATABASE)
+
+#include "Frame.h"
+#include "JSDatabase.h"
+#include "ScriptController.h"
+#include "ScriptExecutionContext.h"
+#include <runtime/JSLock.h>
+#include <wtf/MainThread.h>
+
+namespace WebCore {
+
+using namespace JSC;
+
+JSDatabaseCallback::JSDatabaseCallback(JSObject* callback, JSDOMGlobalObject* globalObject)
+    : m_data(new JSCallbackData(callback, globalObject))
+    , m_isolatedWorld(DOMWrapperWorld::create(globalObject->globalData(), true))
+{
+}
+
+JSDatabaseCallback::~JSDatabaseCallback()
+{
+    callOnMainThread(JSCallbackData::deleteData, m_data);
+#ifndef NDEBUG
+    m_data = 0;
+#endif
+}
+
+void JSDatabaseCallback::handleEvent(ScriptExecutionContext* context, Database* database)
+{
+    ASSERT(m_data);
+    ASSERT(context);
+
+    RefPtr<JSDatabaseCallback> protect(this);
+
+    JSC::JSLock lock(SilenceAssertionsOnly);
+
+    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get());
+    if (!globalObject)
+        return;
+
+    ExecState* exec = globalObject->globalExec();
+    MarkedArgumentBuffer args;
+    args.append(toJS(exec, database));
+
+    bool ignored;
+    m_data->invokeCallback(args, &ignored);
+}
+
+}
+
+#endif // ENABLE(DATABASE)
diff --git a/WebCore/bindings/js/JSDatabaseCallback.h b/WebCore/bindings/js/JSDatabaseCallback.h
new file mode 100644 (file)
index 0000000..2f9234e
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSDatabaseCallback_h
+#define JSDatabaseCallback_h
+
+#if ENABLE(DATABASE)
+
+#include "DatabaseCallback.h"
+#include "JSCallbackData.h"
+
+namespace WebCore {
+
+class ScriptExecutionContext;
+
+class JSDatabaseCallback : public DatabaseCallback {
+public:
+    static PassRefPtr<JSDatabaseCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
+    {
+        return adoptRef(new JSDatabaseCallback(callback, globalObject));
+    }
+
+    virtual ~JSDatabaseCallback();
+
+    virtual void handleEvent(ScriptExecutionContext*, Database*);
+
+private:
+    JSDatabaseCallback(JSC::JSObject* callback, JSDOMGlobalObject*);
+
+    JSCallbackData* m_data;
+    RefPtr<DOMWrapperWorld> m_isolatedWorld;
+};
+
+}
+
+#endif // ENABLE(DATABASE)
+
+#endif // JSDatabaseCallback_h
index e9f7ca844a3db76ba55a0154981c092e072a23f1..1f73f76eb363d90e93afb53d525574fbcf092b4e 100644 (file)
@@ -55,6 +55,8 @@
 #include "V8BindingDOMWindow.h"
 #include "V8BindingState.h"
 #include "V8CustomEventListener.h"
+#include "V8Database.h"
+#include "V8DatabaseCallback.h"
 #include "V8GCForContextDispose.h"
 #include "V8HTMLCollection.h"
 #include "V8MessagePortCustom.h"
@@ -806,6 +808,30 @@ v8::Handle<v8::Value> V8DOMWindow::clearIntervalCallback(const v8::Arguments& ar
     return v8::Undefined();
 }
 
+v8::Handle<v8::Value> V8DOMWindow::openDatabaseCallback(const v8::Arguments& args)
+{
+    INC_STATS("DOM.DOMWindow.openDatabase");
+    if (args.Length() < 4)
+        return v8::Undefined();
+
+    DOMWindow* imp = V8DOMWindow::toNative(args.Holder());
+    if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
+        return v8::Undefined();
+
+    ExceptionCode ec = 0;
+    String name = toWebCoreString(args[0]);
+    String version = toWebCoreString(args[1]);
+    String displayName = toWebCoreString(args[2]);
+    unsigned long estimatedSize = args[3]->IntegerValue();
+    RefPtr<DatabaseCallback> creationCallback;
+    if ((args.Length() >= 5) && args[4]->IsObject())
+        creationCallback = V8DatabaseCallback::create(args[4], imp->frame());
+
+    v8::Handle<v8::Value> result = toV8(imp->openDatabase(name, version, displayName, estimatedSize, creationCallback.release(), ec));
+    V8Proxy::setDOMException(ec);
+    return result;
+}
+
 bool V8DOMWindow::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value> data)
 {
     ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW);
diff --git a/WebCore/bindings/v8/custom/V8DatabaseCallback.cpp b/WebCore/bindings/v8/custom/V8DatabaseCallback.cpp
new file mode 100644 (file)
index 0000000..088d89f
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(DATABASE)
+
+#include "V8DatabaseCallback.h"
+
+#include "Frame.h"
+#include "ScriptExecutionContext.h"
+#include "V8CustomVoidCallback.h"
+#include "V8Database.h"
+
+namespace WebCore {
+
+V8DatabaseCallback::V8DatabaseCallback(v8::Local<v8::Object> callback, Frame* frame)
+    : m_callback(v8::Persistent<v8::Object>::New(callback))
+    , m_frame(frame)
+    , m_worldContext(UseCurrentWorld)
+{
+}
+
+V8DatabaseCallback::~V8DatabaseCallback()
+{
+    m_callback.Dispose();
+}
+
+void V8DatabaseCallback::handleEvent(ScriptExecutionContext* context, Database* database)
+{
+    v8::HandleScope handleScope;
+
+    v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext);
+    if (v8Context.IsEmpty())
+        return;
+
+    v8::Context::Scope scope(v8Context);
+
+    v8::Handle<v8::Value> argv[] = {
+        toV8(database)
+    };
+
+    // Protect the frame until the callback returns.
+    RefPtr<Frame> protector(m_frame);
+
+    bool callbackReturnValue = false;
+    invokeCallback(m_callback, 1, argv, callbackReturnValue);
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/bindings/v8/custom/V8DatabaseCallback.h b/WebCore/bindings/v8/custom/V8DatabaseCallback.h
new file mode 100644 (file)
index 0000000..fd411b4
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef V8DatabaseCallback_h
+#define V8DatabaseCallback_h
+
+#if ENABLE(DATABASE)
+
+#include "DatabaseCallback.h"
+#include "WorldContextHandle.h"
+#include <v8.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Frame;
+
+class V8DatabaseCallback : public DatabaseCallback {
+public:
+    static PassRefPtr<V8DatabaseCallback> create(v8::Local<v8::Value> value, Frame* frame)
+    {
+        ASSERT(value->IsObject());
+        return adoptRef(new V8DatabaseCallback(value->ToObject(), frame));
+    }
+    virtual ~V8DatabaseCallback();
+
+    virtual void handleEvent(ScriptExecutionContext*, Database*);
+
+private:
+    V8DatabaseCallback(v8::Local<v8::Object>, Frame*);
+
+    v8::Persistent<v8::Object> m_callback;
+    RefPtr<Frame> m_frame;
+    WorldContextHandle m_worldContext;
+};
+
+} // namespace WebCore
+
+#endif
+
+#endif // V8DatabaseCallback_h
index d0fe75f71344e07ff19181cf5b47066b0187852c..5925fad52edb6051aba02cc0ac2a92ddea5a468e 100644 (file)
@@ -4730,12 +4730,7 @@ static void performTask(void* ctx)
 
 void Document::postTask(PassOwnPtr<Task> task)
 {
-    if (isMainThread()) {
-        ScriptExecutionContextTaskTimer* timer = new ScriptExecutionContextTaskTimer(static_cast<Document*>(this), task);
-        timer->startOneShot(0);
-    } else {
-        callOnMainThread(performTask, new PerformTaskContext(m_weakReference, task));
-    }
+    callOnMainThread(performTask, new PerformTaskContext(m_weakReference, task));
 }
 
 Element* Document::findAnchor(const String& name)
index 7e0ad2349b063d24aa7a5eda50b7cecafe1905fc..8e1574c6b036a0df18ba577f63954bd86808db62 100644 (file)
@@ -35,6 +35,7 @@
 #include "Chrome.h"
 #include "Console.h"
 #include "Database.h"
+#include "DatabaseCallback.h"
 #include "DOMApplicationCache.h"
 #include "DOMSelection.h"
 #include "DOMTimer.h"
@@ -1125,7 +1126,7 @@ double DOMWindow::devicePixelRatio() const
 }
 
 #if ENABLE(DATABASE)
-PassRefPtr<Database> DOMWindow::openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, ExceptionCode& ec)
+PassRefPtr<Database> DOMWindow::openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback, ExceptionCode& ec)
 {
     if (!m_frame)
         return 0;
@@ -1137,7 +1138,7 @@ PassRefPtr<Database> DOMWindow::openDatabase(const String& name, const String& v
     if (!document->securityOrigin()->canAccessDatabase())
         return 0;
 
-    return Database::openDatabase(document, name, version, displayName, estimatedSize, ec);
+    return Database::openDatabase(document, name, version, displayName, estimatedSize, creationCallback, ec);
 }
 #endif
 
index 4452dbbaae93c3c7def0397783c449aa1152c290..fb5585590bc2258d1ae28257a1637d49a047c805 100644 (file)
@@ -45,6 +45,7 @@ namespace WebCore {
     class Console;
     class DOMSelection;
     class Database;
+    class DatabaseCallback;
     class Document;
     class Element;
     class Event;
@@ -198,7 +199,7 @@ namespace WebCore {
 
 #if ENABLE(DATABASE)
         // HTML 5 client-side database
-        PassRefPtr<Database> openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, ExceptionCode&);
+        PassRefPtr<Database> openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback, ExceptionCode&);
 #endif
 
 #if ENABLE(DOM_STORAGE)
index c757146c8a95110899600aeb450167787cc27e5d..124888e06fcb5f7628619cc76475d7a8e6a14b9e 100644 (file)
@@ -160,7 +160,7 @@ module window {
         readonly attribute [EnabledAtRuntime] DOMApplicationCache applicationCache;
 #endif    
 #if defined(ENABLE_DATABASE) && ENABLE_DATABASE
-        [EnabledAtRuntime] Database openDatabase(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize)
+        [EnabledAtRuntime, Custom] Database openDatabase(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in DatabaseCallback creationCallback)
             raises(DOMException);
 #endif
 #if defined(ENABLE_DOM_STORAGE) && ENABLE_DOM_STORAGE
index 2130631f186b34c57be2f93f03ca998c1d88a1fc..42eeb11a4fa96863bccf52b2fd61986ce4f9507c 100644 (file)
@@ -132,7 +132,31 @@ static const String& databaseVersionKey()
 
 static int guidForOriginAndName(const String& origin, const String& name);
 
-PassRefPtr<Database> Database::openDatabase(ScriptExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, ExceptionCode& e)
+class DatabaseCreationCallbackTask : public ScriptExecutionContext::Task {
+public:
+    static PassOwnPtr<DatabaseCreationCallbackTask> create(PassRefPtr<Database> database)
+    {
+        return new DatabaseCreationCallbackTask(database);
+    }
+
+    virtual void performTask(ScriptExecutionContext*)
+    {
+        m_database->performCreationCallback();
+    }
+
+private:
+    DatabaseCreationCallbackTask(PassRefPtr<Database> database)
+        : m_database(database)
+    {
+    }
+
+    RefPtr<Database> m_database;
+};
+
+PassRefPtr<Database> Database::openDatabase(ScriptExecutionContext* context, const String& name,
+                                            const String& expectedVersion, const String& displayName,
+                                            unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback,
+                                            ExceptionCode& e)
 {
     if (!DatabaseTracker::tracker().canEstablishDatabase(context, name, displayName, estimatedSize)) {
         // FIXME: There should be an exception raised here in addition to returning a null Database object.  The question has been raised with the WHATWG.
@@ -140,7 +164,7 @@ PassRefPtr<Database> Database::openDatabase(ScriptExecutionContext* context, con
         return 0;
     }
 
-    RefPtr<Database> database = adoptRef(new Database(context, name, expectedVersion, displayName, estimatedSize));
+    RefPtr<Database> database = adoptRef(new Database(context, name, expectedVersion, displayName, estimatedSize, creationCallback));
 
     if (!database->openAndVerifyVersion(e)) {
         LOG(StorageAPI, "Failed to open and verify version (expected %s) of database %s", expectedVersion.ascii().data(), database->databaseDebugName().ascii().data());
@@ -160,10 +184,20 @@ PassRefPtr<Database> Database::openDatabase(ScriptExecutionContext* context, con
     }
 #endif
 
+    // If it's a new database and a creation callback was provided, reset the expected
+    // version to "" and schedule the creation callback. Because of some subtle String
+    // implementation issues, we have to reset m_expectedVersion here instead of doing
+    // it inside performOpenAndVerify() which is run on the DB thread.
+    if (database->isNew() && database->m_creationCallback.get()) {
+        database->m_expectedVersion = "";
+        LOG(StorageAPI, "Scheduling DatabaseCreationCallbackTask for database %p\n", database.get());
+        database->m_scriptExecutionContext->postTask(DatabaseCreationCallbackTask::create(database));
+    }
+
     return database;
 }
 
-Database::Database(ScriptExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize)
+Database::Database(ScriptExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback)
     : m_transactionInProgress(false)
     , m_isTransactionQueueEnabled(true)
     , m_scriptExecutionContext(context)
@@ -175,6 +209,8 @@ Database::Database(ScriptExecutionContext* context, const String& name, const St
     , m_deleted(false)
     , m_stopped(false)
     , m_opened(false)
+    , m_new(false)
+    , m_creationCallback(creationCallback)
 {
     ASSERT(m_scriptExecutionContext.get());
     m_mainThreadSecurityOrigin = m_scriptExecutionContext->securityOrigin();
@@ -520,6 +556,8 @@ bool Database::performOpenAndVerify(ExceptionCode& e)
             LOG(StorageAPI, "No cached version for guid %i", m_guid);
 
             if (!m_sqliteDatabase.tableExists(databaseInfoTableName())) {
+                m_new = true;
+
                 if (!m_sqliteDatabase.executeCommand("CREATE TABLE " + databaseInfoTableName() + " (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,value TEXT NOT NULL ON CONFLICT FAIL);")) {
                     LOG_ERROR("Unable to create table %s in database %s", databaseInfoTableName().ascii().data(), databaseDebugName().ascii().data());
                     e = INVALID_STATE_ERR;
@@ -538,7 +576,7 @@ bool Database::performOpenAndVerify(ExceptionCode& e)
             }
             if (currentVersion.length()) {
                 LOG(StorageAPI, "Retrieved current version %s from database %s", currentVersion.ascii().data(), databaseDebugName().ascii().data());
-            } else {
+            } else if (!m_new || !m_creationCallback) {
                 LOG(StorageAPI, "Setting version %s in database %s that was just created", m_expectedVersion.ascii().data(), databaseDebugName().ascii().data());
                 if (!setVersionInDatabase(m_expectedVersion)) {
                     LOG_ERROR("Failed to set version %s in database %s", m_expectedVersion.ascii().data(), databaseDebugName().ascii().data());
@@ -561,7 +599,7 @@ bool Database::performOpenAndVerify(ExceptionCode& e)
 
     // If the expected version isn't the empty string, ensure that the current database version we have matches that version. Otherwise, set an exception.
     // If the expected version is the empty string, then we always return with whatever version of the database we have.
-    if (m_expectedVersion.length() && m_expectedVersion != currentVersion) {
+    if ((!m_new || !m_creationCallback) && m_expectedVersion.length() && m_expectedVersion != currentVersion) {
         LOG(StorageAPI, "page expects version %s from database %s, which actually has version name %s - openDatabase() call will fail", m_expectedVersion.ascii().data(),
             databaseDebugName().ascii().data(), currentVersion.ascii().data());
         e = INVALID_STATE_ERR;
@@ -685,6 +723,11 @@ Vector<String> Database::performGetTableNames()
     return tableNames;
 }
 
+void Database::performCreationCallback()
+{
+    m_creationCallback->handleEvent(m_scriptExecutionContext.get(), this);
+}
+
 SQLTransactionClient* Database::transactionClient() const
 {
     return m_scriptExecutionContext->databaseThread()->transactionClient();
index 0d7f33cc974242f03e4b4810b06ee2e3f8d1875d..0fd0511211441a41183d58eca3c4f4c305bc62a6 100644 (file)
@@ -30,6 +30,7 @@
 #define Database_h
 
 #if ENABLE(DATABASE)
+#include "DatabaseCallback.h"
 #include "PlatformString.h"
 #include "SecurityOrigin.h"
 #include "SQLiteDatabase.h"
@@ -51,6 +52,7 @@
 namespace WebCore {
 
 class DatabaseAuthorizer;
+class DatabaseCallback;
 class DatabaseThread;
 class ScriptExecutionContext;
 class SQLResultSet;
@@ -73,7 +75,10 @@ public:
     ~Database();
 
 // Direct support for the DOM API
-    static PassRefPtr<Database> openDatabase(ScriptExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, ExceptionCode&);
+    static PassRefPtr<Database> openDatabase(ScriptExecutionContext* context, const String& name,
+                                             const String& expectedVersion, const String& displayName,
+                                             unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback,
+                                             ExceptionCode&);
     String version() const;
     void changeVersion(const String& oldVersion, const String& newVersion,
                        PassRefPtr<SQLTransactionCallback> callback, PassRefPtr<SQLTransactionErrorCallback> errorCallback,
@@ -111,6 +116,8 @@ public:
     void stop();
     bool stopped() const { return m_stopped; }
 
+    bool isNew() const { return m_new; }
+
     unsigned long long databaseSize() const;
     unsigned long long maximumSize() const;
 
@@ -121,6 +128,7 @@ public:
     bool performOpenAndVerify(ExceptionCode&);
 
     Vector<String> performGetTableNames();
+    void performCreationCallback();
 
     SQLTransactionClient* transactionClient() const;
     SQLTransactionCoordinator* transactionCoordinator() const;
@@ -128,7 +136,7 @@ public:
 private:
     Database(ScriptExecutionContext* context, const String& name,
              const String& expectedVersion, const String& displayName,
-             unsigned long estimatedSize);
+             unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback);
 
     bool openAndVerifyVersion(ExceptionCode&);
 
@@ -159,9 +167,13 @@ private:
 
     bool m_opened;
 
+    bool m_new;
+
     SQLiteDatabase m_sqliteDatabase;
     RefPtr<DatabaseAuthorizer> m_databaseAuthorizer;
 
+    RefPtr<DatabaseCallback> m_creationCallback;
+
 #ifndef NDEBUG
     String databaseDebugName() const { return m_mainThreadSecurityOrigin->toString() + "::" + m_name; }
 #endif
diff --git a/WebCore/storage/DatabaseCallback.h b/WebCore/storage/DatabaseCallback.h
new file mode 100644 (file)
index 0000000..2115a21
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DatabaseCallback_h
+#define DatabaseCallback_h
+
+#if ENABLE(DATABASE)
+
+#include <wtf/Threading.h>
+
+namespace WebCore {
+
+class Database;
+class ScriptExecutionContext;
+
+class DatabaseCallback : public ThreadSafeShared<DatabaseCallback> {
+public:
+    virtual ~DatabaseCallback() { }
+    virtual void handleEvent(ScriptExecutionContext*, Database*) = 0;
+};
+
+}
+
+#endif
+
+#endif // DatabaseCallback_h
index 0ec24e696ac68c233b2a18c8c241edab3d929a5c..7b4f2934680ca0c5f7fd4b106da83cb4194655ef 100644 (file)
@@ -256,7 +256,7 @@ NotificationCenter* WorkerContext::webkitNotifications() const
 #endif
 
 #if ENABLE(DATABASE)
-PassRefPtr<Database> WorkerContext::openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, ExceptionCode& ec)
+PassRefPtr<Database> WorkerContext::openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback, ExceptionCode& ec)
 {
     if (!securityOrigin()->canAccessDatabase()) {
         ec = SECURITY_ERR;
@@ -267,7 +267,7 @@ PassRefPtr<Database> WorkerContext::openDatabase(const String& name, const Strin
     if (!Database::isAvailable())
         return 0;
 
-    return Database::openDatabase(this, name, version, displayName, estimatedSize, ec);
+    return Database::openDatabase(this, name, version, displayName, estimatedSize, creationCallback, ec);
 }
 #endif
 
index a795947071dfd878aae0b8093c69b9e7ae79e04d..fb4a26dcaa25177acd9e3309a20f3160a70381ca 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "AtomicStringHash.h"
 #include "Database.h"
+#include "DatabaseCallback.h"
 #include "EventListener.h"
 #include "EventNames.h"
 #include "EventTarget.h"
@@ -106,7 +107,7 @@ namespace WebCore {
 
 #if ENABLE(DATABASE)
         // HTML 5 client-side database
-        PassRefPtr<Database> openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, ExceptionCode&);
+        PassRefPtr<Database> openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback, ExceptionCode&);
         // Not implemented yet.
         virtual bool isDatabaseReadOnly() const { return false; }
         // Not implemented yet.