2011-02-04 Jeremy Orlow <jorlow@chromium.org>
authorjorlow@chromium.org <jorlow@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Feb 2011 23:45:27 +0000 (23:45 +0000)
committerjorlow@chromium.org <jorlow@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Feb 2011 23:45:27 +0000 (23:45 +0000)
        Reviewed by Nate Chapin.

        Second IndexedDB events overhaul patch
        https://bugs.webkit.org/show_bug.cgi?id=53813

        * storage/indexeddb/request-event-propagation-expected.txt: Added.
        * storage/indexeddb/request-event-propagation.html: Added.
2011-02-04  Jeremy Orlow  <jorlow@chromium.org>

        Reviewed by Nate Chapin.

        Second IndexedDB events overhaul patch
        https://bugs.webkit.org/show_bug.cgi?id=53813

        If an IDBRequest has a IDBTransaction, it should propogate
        events through it. In order to do this, IDBRequest needs to
        hold a transaction frontend object rather than a backend one.

        Test: storage/indexeddb/request-event-propagation.html

        * storage/IDBCursor.cpp:
        (WebCore::IDBCursor::IDBCursor):
        * storage/IDBCursor.h:
        (WebCore::IDBCursor::create):
        * storage/IDBDatabase.cpp:
        (WebCore::IDBDatabase::setSetVersionTransaction):
        (WebCore::IDBDatabase::createObjectStore):
        (WebCore::IDBDatabase::deleteObjectStore):
        * storage/IDBDatabase.h:
        * storage/IDBIndex.cpp:
        (WebCore::IDBIndex::IDBIndex):
        (WebCore::IDBIndex::openCursor):
        (WebCore::IDBIndex::openKeyCursor):
        (WebCore::IDBIndex::get):
        (WebCore::IDBIndex::getKey):
        * storage/IDBIndex.h:
        (WebCore::IDBIndex::create):
        * storage/IDBObjectStore.cpp:
        (WebCore::IDBObjectStore::IDBObjectStore):
        (WebCore::IDBObjectStore::get):
        (WebCore::IDBObjectStore::add):
        (WebCore::IDBObjectStore::put):
        (WebCore::IDBObjectStore::deleteFunction):
        (WebCore::IDBObjectStore::createIndex):
        (WebCore::IDBObjectStore::deleteIndex):
        (WebCore::IDBObjectStore::openCursor):
        * storage/IDBObjectStore.h:
        (WebCore::IDBObjectStore::create):
        * storage/IDBRequest.cpp:
        (WebCore::IDBRequest::create):
        (WebCore::IDBRequest::IDBRequest):
        (WebCore::IDBRequest::resetReadyState):
        (WebCore::IDBRequest::onSuccess):
        (WebCore::IDBRequest::dispatchEvent):
        * storage/IDBRequest.h:
        * storage/IDBTransaction.cpp:
        (WebCore::IDBTransaction::IDBTransaction):
        (WebCore::IDBTransaction::objectStore):
        (WebCore::IDBTransaction::contextDestroyed):
        (WebCore::IDBTransaction::enqueueEvent):
        * storage/IDBTransaction.h:
        * storage/IDBTransaction.idl:

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

17 files changed:
LayoutTests/ChangeLog
LayoutTests/storage/indexeddb/request-event-propagation-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/request-event-propagation.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/storage/IDBCursor.cpp
Source/WebCore/storage/IDBCursor.h
Source/WebCore/storage/IDBDatabase.cpp
Source/WebCore/storage/IDBDatabase.h
Source/WebCore/storage/IDBIndex.cpp
Source/WebCore/storage/IDBIndex.h
Source/WebCore/storage/IDBObjectStore.cpp
Source/WebCore/storage/IDBObjectStore.h
Source/WebCore/storage/IDBRequest.cpp
Source/WebCore/storage/IDBRequest.h
Source/WebCore/storage/IDBTransaction.cpp
Source/WebCore/storage/IDBTransaction.h
Source/WebCore/storage/IDBTransaction.idl

index e3aaa743d210670d00f508c2c3419f8ae132844f..34803a3076dcfe700968d60610c2b30a378a2efb 100644 (file)
@@ -1,3 +1,13 @@
+2011-02-04  Jeremy Orlow  <jorlow@chromium.org>
+
+        Reviewed by Nate Chapin.
+
+        Second IndexedDB events overhaul patch
+        https://bugs.webkit.org/show_bug.cgi?id=53813
+
+        * storage/indexeddb/request-event-propagation-expected.txt: Added.
+        * storage/indexeddb/request-event-propagation.html: Added.
+
 2011-02-04  Jeremy Orlow  <jorlow@chromium.org>
 
         Reviewed by Nate Chapin.
diff --git a/LayoutTests/storage/indexeddb/request-event-propagation-expected.txt b/LayoutTests/storage/indexeddb/request-event-propagation-expected.txt
new file mode 100644 (file)
index 0000000..a1a5cd2
--- /dev/null
@@ -0,0 +1,115 @@
+Test event propogation on IDBRequest.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+webkitIndexedDB.open('name')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+Success event fired:
+PASS 'result' in event is true
+PASS 'code' in event is false
+PASS 'message' in event is false
+PASS 'source' in event is true
+PASS event.source != null is true
+PASS 'onsuccess' in event.target is true
+PASS 'onerror' in event.target is true
+PASS 'readyState' in event.target is true
+PASS event.target.readyState is event.target.DONE
+
+db = event.result
+db.setVersion('new version')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+setVersionSuccess():
+Success event fired:
+PASS 'result' in event is true
+PASS 'code' in event is false
+PASS 'message' in event is false
+PASS 'source' in event is true
+PASS event.source != null is true
+PASS 'onsuccess' in event.target is true
+PASS 'onerror' in event.target is true
+PASS 'readyState' in event.target is true
+PASS event.target.readyState is event.target.DONE
+
+trans = event.result
+PASS trans !== null is true
+trans.oncomplete = startTest
+Deleted all object stores.
+store = db.createObjectStore('storeName', null)
+store.add({x: 'value', y: 'zzz'}, 'key')
+Verify that handler fires and that not preventing default will result in an abort
+trans = db.transaction([], webkitIDBTransaction.READ_WRITE)
+trans.onabort = transactionAborted
+trans.oncomplete = unexpectedCompleteCallback
+trans.onerror = allowDefault
+store = trans.objectStore('storeName')
+store.add({x: 'value', y: 'zzz'}, 'key')
+PASS Event handler fired
+Doing nothing to prevent the default action...
+PASS handlerFired is true
+
+Verifing error
+trans = db.transaction([], webkitIDBTransaction.READ_WRITE)
+trans.onabort = transactionAborted2
+trans.oncomplete = unexpectedAbortCallback
+trans.addEventListener('error', errorCaptureCallback, true)
+trans.addEventListener('error', errorBubbleCallback, false)
+store = trans.objectStore('storeName')
+store.add({x: 'value', y: 'zzz'}, 'key')
+
+In IDBTransaction error capture
+PASS captureFired is false
+PASS requestFired is false
+PASS bubbleFired is false
+
+In IDBRequest handler
+PASS captureFired is true
+PASS requestFired is false
+PASS bubbleFired is false
+
+In IDBTransaction error bubble
+PASS captureFired is true
+PASS requestFired is true
+PASS bubbleFired is false
+
+Transaction aborted
+PASS captureFired is true
+PASS requestFired is true
+PASS bubbleFired is true
+
+Verifing success.
+trans = db.transaction([], webkitIDBTransaction.READ_WRITE)
+trans.oncomplete = transactionComplete
+trans.onabort = unexpectedAbortCallback
+trans.addEventListener('success', successCaptureCallback, true)
+trans.addEventListener('success', successBubbleCallback, false)
+store = trans.objectStore('storeName')
+store.add({x: 'value', y: 'zzz'}, 'key2')
+
+In IDBTransaction success capture
+PASS captureFired is false
+PASS requestFired is false
+PASS bubbleFired is false
+
+In IDBRequest handler
+PASS captureFired is true
+PASS requestFired is false
+PASS bubbleFired is false
+
+Transaction completed
+PASS captureFired is true
+PASS requestFired is true
+PASS bubbleFired is false
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/storage/indexeddb/request-event-propagation.html b/LayoutTests/storage/indexeddb/request-event-propagation.html
new file mode 100644 (file)
index 0000000..e1284b6
--- /dev/null
@@ -0,0 +1,194 @@
+<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 event propogation on IDBRequest.");
+if (window.layoutTestController) 
+    layoutTestController.waitUntilDone();
+
+function test()
+{
+    result = evalAndLog("webkitIndexedDB.open('name')");
+    verifyResult(result);
+    result.onsuccess = setVersion;
+    result.onerror = unexpectedErrorCallback;
+}
+
+function setVersion()
+{
+    verifySuccessEvent(event);
+    db = evalAndLog("db = event.result");
+
+    result = evalAndLog("db.setVersion('new version')");
+    verifyResult(result);
+    result.onsuccess = deleteExisting;
+    result.onerror = unexpectedErrorCallback;
+}
+
+function deleteExisting()
+{
+    debug("setVersionSuccess():");
+    verifySuccessEvent(event);
+    window.trans = evalAndLog("trans = event.result");
+    shouldBeTrue("trans !== null");
+    trans.onabort = unexpectedAbortCallback;
+    evalAndLog("trans.oncomplete = startTest");
+
+    deleteAllObjectStores(db, createObjectStore);
+}
+
+function createObjectStore()
+{
+    store = evalAndLog("store = db.createObjectStore('storeName', null)");
+    result = evalAndLog("store.add({x: 'value', y: 'zzz'}, 'key')");
+    result.onerror = unexpectedErrorCallback;
+}
+
+function startTest()
+{
+    debug("Verify that handler fires and that not preventing default will result in an abort");
+    trans = evalAndLog("trans = db.transaction([], webkitIDBTransaction.READ_WRITE)");
+    evalAndLog("trans.onabort = transactionAborted");
+    evalAndLog("trans.oncomplete = unexpectedCompleteCallback");
+    evalAndLog("trans.onerror = allowDefault");
+    store = evalAndLog("store = trans.objectStore('storeName')");
+    result = evalAndLog("store.add({x: 'value', y: 'zzz'}, 'key')");
+    result.onsuccess = unexpectedSuccessCallback;
+    handlerFired = false;
+}
+
+function allowDefault()
+{
+    testPassed("Event handler fired");
+    debug("Doing nothing to prevent the default action...");
+    handlerFired = true;
+}
+
+function transactionAborted()
+{
+    shouldBeTrue("handlerFired");
+    debug("");
+    debug("Verifing error");
+    trans = evalAndLog("trans = db.transaction([], webkitIDBTransaction.READ_WRITE)");
+    evalAndLog("trans.onabort = transactionAborted2");
+    evalAndLog("trans.oncomplete = unexpectedAbortCallback");
+    evalAndLog("trans.addEventListener('error', errorCaptureCallback, true)");
+    evalAndLog("trans.addEventListener('error', errorBubbleCallback, false)");
+    store = evalAndLog("store = trans.objectStore('storeName')");
+    result = evalAndLog("store.add({x: 'value', y: 'zzz'}, 'key')");
+    result.onsuccess = unexpectedSuccessCallback;
+    result.onerror = errorFiredCallback;
+    captureFired = false;
+    requestFired = false;
+    bubbleFired = false;
+}
+
+function errorCaptureCallback()
+{
+    debug("");
+    debug("In IDBTransaction error capture");
+    shouldBeFalse("captureFired");
+    shouldBeFalse("requestFired");
+    shouldBeFalse("bubbleFired");
+    captureFired = true;
+}
+
+function errorFiredCallback()
+{
+    debug("");
+    debug("In IDBRequest handler");
+    shouldBeTrue("captureFired");
+    shouldBeFalse("requestFired");
+    shouldBeFalse("bubbleFired");
+    requestFired = true;
+}
+
+function errorBubbleCallback()
+{
+    debug("");
+    debug("In IDBTransaction error bubble");
+    shouldBeTrue("captureFired");
+    shouldBeTrue("requestFired");
+    shouldBeFalse("bubbleFired");
+    bubbleFired = true;
+}
+
+function transactionAborted2()
+{
+    debug("");
+    debug("Transaction aborted");
+    shouldBeTrue("captureFired");
+    shouldBeTrue("requestFired");
+    shouldBeTrue("bubbleFired");
+    debug("");
+    debug("Verifing success.");
+    trans = evalAndLog("trans = db.transaction([], webkitIDBTransaction.READ_WRITE)");
+    evalAndLog("trans.oncomplete = transactionComplete");
+    evalAndLog("trans.onabort = unexpectedAbortCallback");
+    evalAndLog("trans.addEventListener('success', successCaptureCallback, true)");
+    evalAndLog("trans.addEventListener('success', successBubbleCallback, false)");
+    store = evalAndLog("store = trans.objectStore('storeName')");
+    result = evalAndLog("store.add({x: 'value', y: 'zzz'}, 'key2')");
+    result.onerror = unexpectedErrorCallback;
+    result.onsuccess = successFiredCallback;
+    captureFired = false;
+    requestFired = false;
+    bubbleFired = false;
+}
+
+function successCaptureCallback()
+{
+    debug("");
+    debug("In IDBTransaction success capture");
+    shouldBeFalse("captureFired");
+    shouldBeFalse("requestFired");
+    shouldBeFalse("bubbleFired");
+    captureFired = true;
+}
+
+function successFiredCallback()
+{
+    debug("");
+    debug("In IDBRequest handler");
+    shouldBeTrue("captureFired");
+    shouldBeFalse("requestFired");
+    shouldBeFalse("bubbleFired");
+    requestFired = true;
+}
+
+function successBubbleCallback()
+{
+    debug("");
+    debug("In IDBTransaction success bubble");
+    testFailed("Success capture callback should NOT fire");
+    bubbleFired = true;
+}
+
+function transactionComplete()
+{
+    debug("");
+    debug("Transaction completed");
+    shouldBeTrue("captureFired");
+    shouldBeTrue("requestFired");
+    shouldBeFalse("bubbleFired");
+    debug("");
+
+    done();
+    return;
+}
+
+test();
+
+var successfullyParsed = true;
+
+</script>
+</body>
+</html>
index 3a91e2d903adaaa637ab1fbafe3e6bd3c805a616..9bf5c0925e563fd061cae9a9142449e2ef5f6909 100644 (file)
@@ -1,3 +1,59 @@
+2011-02-04  Jeremy Orlow  <jorlow@chromium.org>
+
+        Reviewed by Nate Chapin.
+
+        Second IndexedDB events overhaul patch
+        https://bugs.webkit.org/show_bug.cgi?id=53813
+
+        If an IDBRequest has a IDBTransaction, it should propogate
+        events through it. In order to do this, IDBRequest needs to
+        hold a transaction frontend object rather than a backend one.
+
+        Test: storage/indexeddb/request-event-propagation.html
+
+        * storage/IDBCursor.cpp:
+        (WebCore::IDBCursor::IDBCursor):
+        * storage/IDBCursor.h:
+        (WebCore::IDBCursor::create):
+        * storage/IDBDatabase.cpp:
+        (WebCore::IDBDatabase::setSetVersionTransaction):
+        (WebCore::IDBDatabase::createObjectStore):
+        (WebCore::IDBDatabase::deleteObjectStore):
+        * storage/IDBDatabase.h:
+        * storage/IDBIndex.cpp:
+        (WebCore::IDBIndex::IDBIndex):
+        (WebCore::IDBIndex::openCursor):
+        (WebCore::IDBIndex::openKeyCursor):
+        (WebCore::IDBIndex::get):
+        (WebCore::IDBIndex::getKey):
+        * storage/IDBIndex.h:
+        (WebCore::IDBIndex::create):
+        * storage/IDBObjectStore.cpp:
+        (WebCore::IDBObjectStore::IDBObjectStore):
+        (WebCore::IDBObjectStore::get):
+        (WebCore::IDBObjectStore::add):
+        (WebCore::IDBObjectStore::put):
+        (WebCore::IDBObjectStore::deleteFunction):
+        (WebCore::IDBObjectStore::createIndex):
+        (WebCore::IDBObjectStore::deleteIndex):
+        (WebCore::IDBObjectStore::openCursor):
+        * storage/IDBObjectStore.h:
+        (WebCore::IDBObjectStore::create):
+        * storage/IDBRequest.cpp:
+        (WebCore::IDBRequest::create):
+        (WebCore::IDBRequest::IDBRequest):
+        (WebCore::IDBRequest::resetReadyState):
+        (WebCore::IDBRequest::onSuccess):
+        (WebCore::IDBRequest::dispatchEvent):
+        * storage/IDBRequest.h:
+        * storage/IDBTransaction.cpp:
+        (WebCore::IDBTransaction::IDBTransaction):
+        (WebCore::IDBTransaction::objectStore):
+        (WebCore::IDBTransaction::contextDestroyed):
+        (WebCore::IDBTransaction::enqueueEvent):
+        * storage/IDBTransaction.h:
+        * storage/IDBTransaction.idl:
+
 2011-02-04  Jeremy Orlow  <jorlow@chromium.org>
 
         Reviewed by Nate Chapin.
index 4be6f4a552485954683b9168577a242b31292ce0..531cae140effd0ffd467449b75c36dfcd0cfeab7 100644 (file)
 #include "IDBCursorBackendInterface.h"
 #include "IDBKey.h"
 #include "IDBRequest.h"
-#include "IDBTransactionBackendInterface.h"
+#include "IDBTransaction.h"
 #include "ScriptExecutionContext.h"
 #include "SerializedScriptValue.h"
 
 namespace WebCore {
 
-IDBCursor::IDBCursor(PassRefPtr<IDBCursorBackendInterface> backend, IDBRequest* request, IDBTransactionBackendInterface* transaction)
+IDBCursor::IDBCursor(PassRefPtr<IDBCursorBackendInterface> backend, IDBRequest* request, IDBTransaction* transaction)
     : m_backend(backend)
     , m_request(request)
     , m_transaction(transaction)
index 54bf51aa3465655241676efc3409158cb7bd5a8d..9f5ffad534fb255284cec5b142745abae5f5e302 100644 (file)
@@ -40,9 +40,9 @@ class IDBCallbacks;
 class IDBCursorBackendInterface;
 class IDBKey;
 class IDBRequest;
+class IDBTransaction;
 class ScriptExecutionContext;
 class SerializedScriptValue;
-class IDBTransactionBackendInterface;
 
 class IDBCursor : public RefCounted<IDBCursor> {
 public:
@@ -52,7 +52,7 @@ public:
         PREV = 2,
         PREV_NO_DUPLICATE = 3,
     };
-    static PassRefPtr<IDBCursor> create(PassRefPtr<IDBCursorBackendInterface> backend, IDBRequest* request, IDBTransactionBackendInterface* transaction)
+    static PassRefPtr<IDBCursor> create(PassRefPtr<IDBCursorBackendInterface> backend, IDBRequest* request, IDBTransaction* transaction)
     {
         return adoptRef(new IDBCursor(backend, request, transaction));
     }
@@ -70,11 +70,11 @@ public:
     PassRefPtr<IDBRequest> deleteFunction(ScriptExecutionContext*, ExceptionCode&);
 
 private:
-    explicit IDBCursor(PassRefPtr<IDBCursorBackendInterface>, IDBRequest*, IDBTransactionBackendInterface*);
+    explicit IDBCursor(PassRefPtr<IDBCursorBackendInterface>, IDBRequest*, IDBTransaction*);
 
     RefPtr<IDBCursorBackendInterface> m_backend;
     RefPtr<IDBRequest> m_request;
-    RefPtr<IDBTransactionBackendInterface> m_transaction;
+    RefPtr<IDBTransaction> m_transaction;
 };
 
 } // namespace WebCore
index c9d96feca82356ee5d0221acc551ed8cb0455c24..6ca2f42fbc9c5286def4bf1ccb0c8136dcfc01bc 100644 (file)
@@ -53,7 +53,7 @@ IDBDatabase::~IDBDatabase()
 {
 }
 
-void IDBDatabase::setSetVersionTransaction(IDBTransactionBackendInterface* transaction)
+void IDBDatabase::setSetVersionTransaction(IDBTransaction* transaction)
 {
     m_setVersionTransaction = transaction;
 }
@@ -71,7 +71,7 @@ PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, co
     options.getKeyBool("autoIncrement", autoIncrement);
     // FIXME: Look up evictable and pass that on as well.
 
-    RefPtr<IDBObjectStoreBackendInterface> objectStore = m_backend->createObjectStore(name, keyPath, autoIncrement, m_setVersionTransaction.get(), ec);
+    RefPtr<IDBObjectStoreBackendInterface> objectStore = m_backend->createObjectStore(name, keyPath, autoIncrement, m_setVersionTransaction->backend(), ec);
     if (!objectStore) {
         ASSERT(ec);
         return 0;
@@ -86,7 +86,7 @@ void IDBDatabase::deleteObjectStore(const String& name, ExceptionCode& ec)
         return;
     }
 
-    m_backend->deleteObjectStore(name, m_setVersionTransaction.get(), ec);
+    m_backend->deleteObjectStore(name, m_setVersionTransaction->backend(), ec);
 }
 
 PassRefPtr<IDBRequest> IDBDatabase::setVersion(ScriptExecutionContext* context, const String& version, ExceptionCode& ec)
index 7c35b09bf0ae32e84a55746273eb149c412cace9..d82ead3e43912e9a943dd177792c1c08343d3c0e 100644 (file)
@@ -52,7 +52,7 @@ public:
     }
     ~IDBDatabase();
 
-    void setSetVersionTransaction(IDBTransactionBackendInterface*);
+    void setSetVersionTransaction(IDBTransaction*);
 
     // Implement the IDL
     String name() const { return m_backend->name(); }
@@ -74,7 +74,7 @@ private:
     IDBDatabase(PassRefPtr<IDBDatabaseBackendInterface>);
 
     RefPtr<IDBDatabaseBackendInterface> m_backend;
-    RefPtr<IDBTransactionBackendInterface> m_setVersionTransaction;
+    RefPtr<IDBTransaction> m_setVersionTransaction;
 
     bool m_noNewTransactions;
 };
index 0cc4726911965bb1e26496ea2e2bf33deaf58f6b..615767b7c3dcab3a866526fbead26ce59aad8105 100644 (file)
 #include "IDBKey.h"
 #include "IDBKeyRange.h"
 #include "IDBRequest.h"
-#include "IDBTransactionBackendInterface.h"
+#include "IDBTransaction.h"
 
 namespace WebCore {
 
 static const unsigned short defaultDirection = IDBCursor::NEXT;
 
-IDBIndex::IDBIndex(PassRefPtr<IDBIndexBackendInterface> backend, IDBTransactionBackendInterface* transaction)
+IDBIndex::IDBIndex(PassRefPtr<IDBIndexBackendInterface> backend, IDBTransaction* transaction)
     : m_backend(backend)
     , m_transaction(transaction)
 {
@@ -61,7 +61,7 @@ PassRefPtr<IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, Pas
     }
 
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
-    m_backend->openCursor(keyRange, direction, request, m_transaction.get(), ec);
+    m_backend->openCursor(keyRange, direction, request, m_transaction->backend(), ec);
     if (ec)
         return 0;
     return request;
@@ -76,7 +76,7 @@ PassRefPtr<IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext* context,
     }
 
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
-    m_backend->openKeyCursor(keyRange, direction, request, m_transaction.get(), ec);
+    m_backend->openKeyCursor(keyRange, direction, request, m_transaction->backend(), ec);
     if (ec)
         return 0;
     return request;
@@ -85,7 +85,7 @@ PassRefPtr<IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext* context,
 PassRefPtr<IDBRequest> IDBIndex::get(ScriptExecutionContext* context, PassRefPtr<IDBKey> key, ExceptionCode& ec)
 {
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
-    m_backend->get(key, request, m_transaction.get(), ec);
+    m_backend->get(key, request, m_transaction->backend(), ec);
     if (ec)
         return 0;
     return request;
@@ -94,7 +94,7 @@ PassRefPtr<IDBRequest> IDBIndex::get(ScriptExecutionContext* context, PassRefPtr
 PassRefPtr<IDBRequest> IDBIndex::getKey(ScriptExecutionContext* context, PassRefPtr<IDBKey> key, ExceptionCode& ec)
 {
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
-    m_backend->getKey(key, request, m_transaction.get(), ec);
+    m_backend->getKey(key, request, m_transaction->backend(), ec);
     if (ec)
         return 0;
     return request;
index aaeb348618ab5399fad7415b140f624c380e5343..10b46f1f045462cccb91fd4bcfab4c181964563b 100644 (file)
@@ -39,7 +39,7 @@ namespace WebCore {
 
 class IDBIndex : public RefCounted<IDBIndex> {
 public:
-    static PassRefPtr<IDBIndex> create(PassRefPtr<IDBIndexBackendInterface> backend, IDBTransactionBackendInterface* transaction)
+    static PassRefPtr<IDBIndex> create(PassRefPtr<IDBIndexBackendInterface> backend, IDBTransaction* transaction)
     {
         return adoptRef(new IDBIndex(backend, transaction));
     }
@@ -64,10 +64,10 @@ public:
     PassRefPtr<IDBRequest> getKey(ScriptExecutionContext*, PassRefPtr<IDBKey>, ExceptionCode&);
 
 private:
-    IDBIndex(PassRefPtr<IDBIndexBackendInterface>, IDBTransactionBackendInterface* transaction);
+    IDBIndex(PassRefPtr<IDBIndexBackendInterface>, IDBTransaction*);
 
     RefPtr<IDBIndexBackendInterface> m_backend;
-    RefPtr<IDBTransactionBackendInterface> m_transaction;
+    RefPtr<IDBTransaction> m_transaction;
 };
 
 } // namespace WebCore
index ac860a2558b4e329fad9d90bdb48a10e925d1dc4..1ba8733390cb1c4d1260ff8f786afec8067391e1 100644 (file)
@@ -34,7 +34,7 @@
 #include "IDBIndex.h"
 #include "IDBKey.h"
 #include "IDBKeyRange.h"
-#include "IDBTransactionBackendInterface.h"
+#include "IDBTransaction.h"
 #include "SerializedScriptValue.h"
 #include <wtf/UnusedParam.h>
 
@@ -42,7 +42,7 @@ namespace WebCore {
 
 static const unsigned short defaultDirection = IDBCursor::NEXT;
 
-IDBObjectStore::IDBObjectStore(PassRefPtr<IDBObjectStoreBackendInterface> idbObjectStore, IDBTransactionBackendInterface* transaction)
+IDBObjectStore::IDBObjectStore(PassRefPtr<IDBObjectStoreBackendInterface> idbObjectStore, IDBTransaction* transaction)
     : m_objectStore(idbObjectStore)
     , m_transaction(transaction)
 {
@@ -70,7 +70,7 @@ PassRefPtr<DOMStringList> IDBObjectStore::indexNames() const
 PassRefPtr<IDBRequest> IDBObjectStore::get(ScriptExecutionContext* context, PassRefPtr<IDBKey> key, ExceptionCode& ec)
 {
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
-    m_objectStore->get(key, request, m_transaction.get(), ec);
+    m_objectStore->get(key, request, m_transaction->backend(), ec);
     if (ec)
         return 0;
     return request.release();
@@ -79,7 +79,7 @@ PassRefPtr<IDBRequest> IDBObjectStore::get(ScriptExecutionContext* context, Pass
 PassRefPtr<IDBRequest> IDBObjectStore::add(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, ExceptionCode& ec)
 {
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
-    m_objectStore->put(value, key, IDBObjectStoreBackendInterface::AddOnly, request, m_transaction.get(), ec);
+    m_objectStore->put(value, key, IDBObjectStoreBackendInterface::AddOnly, request, m_transaction->backend(), ec);
     if (ec)
         return 0;
     return request;
@@ -88,7 +88,7 @@ PassRefPtr<IDBRequest> IDBObjectStore::add(ScriptExecutionContext* context, Pass
 PassRefPtr<IDBRequest> IDBObjectStore::put(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, ExceptionCode& ec)
 {
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
-    m_objectStore->put(value, key, IDBObjectStoreBackendInterface::AddOrUpdate, request, m_transaction.get(), ec);
+    m_objectStore->put(value, key, IDBObjectStoreBackendInterface::AddOrUpdate, request, m_transaction->backend(), ec);
     if (ec)
         return 0;
     return request;
@@ -97,7 +97,7 @@ PassRefPtr<IDBRequest> IDBObjectStore::put(ScriptExecutionContext* context, Pass
 PassRefPtr<IDBRequest> IDBObjectStore::deleteFunction(ScriptExecutionContext* context, PassRefPtr<IDBKey> key, ExceptionCode& ec)
 {
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
-    m_objectStore->deleteFunction(key, request, m_transaction.get(), ec);
+    m_objectStore->deleteFunction(key, request, m_transaction->backend(), ec);
     if (ec)
         return 0;
     return request;
@@ -108,7 +108,7 @@ PassRefPtr<IDBIndex> IDBObjectStore::createIndex(const String& name, const Strin
     bool unique = false;
     options.getKeyBool("unique", unique);
 
-    RefPtr<IDBIndexBackendInterface> index = m_objectStore->createIndex(name, keyPath, unique, m_transaction.get(), ec);
+    RefPtr<IDBIndexBackendInterface> index = m_objectStore->createIndex(name, keyPath, unique, m_transaction->backend(), ec);
     ASSERT(!index != !ec); // If we didn't get an index, we should have gotten an exception code. And vice versa.
     if (!index)
         return 0;
@@ -126,7 +126,7 @@ PassRefPtr<IDBIndex> IDBObjectStore::index(const String& name, ExceptionCode& ec
 
 void IDBObjectStore::deleteIndex(const String& name, ExceptionCode& ec)
 {
-    m_objectStore->deleteIndex(name, m_transaction.get(), ec);
+    m_objectStore->deleteIndex(name, m_transaction->backend(), ec);
 }
 
 PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> range, unsigned short direction, ExceptionCode& ec)
@@ -138,7 +138,7 @@ PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* contex
     }
 
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
-    m_objectStore->openCursor(range, direction, request, m_transaction.get(), ec);
+    m_objectStore->openCursor(range, direction, request, m_transaction->backend(), ec);
     if (ec)
         return 0;
     return request.release();
index 8c076c7b131c99835c81e8e76c2a00de460d4684..432cf190c8600fed0f277cf59adca399031a8e7d 100644 (file)
@@ -45,11 +45,10 @@ namespace WebCore {
 
 class DOMStringList;
 class IDBAny;
-class IDBTransactionBackendInterface;
 
 class IDBObjectStore : public RefCounted<IDBObjectStore> {
 public:
-    static PassRefPtr<IDBObjectStore> create(PassRefPtr<IDBObjectStoreBackendInterface> idbObjectStore, IDBTransactionBackendInterface* transaction)
+    static PassRefPtr<IDBObjectStore> create(PassRefPtr<IDBObjectStoreBackendInterface> idbObjectStore, IDBTransaction* transaction)
     {
         return adoptRef(new IDBObjectStore(idbObjectStore, transaction));
     }
@@ -78,11 +77,11 @@ public:
     PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, PassRefPtr<IDBKeyRange>, unsigned short direction, ExceptionCode&); 
 
 private:
-    IDBObjectStore(PassRefPtr<IDBObjectStoreBackendInterface>, IDBTransactionBackendInterface* transaction);
+    IDBObjectStore(PassRefPtr<IDBObjectStoreBackendInterface>, IDBTransaction*);
     void removeTransactionFromPendingList();
 
     RefPtr<IDBObjectStoreBackendInterface> m_objectStore;
-    RefPtr<IDBTransactionBackendInterface> m_transaction;
+    RefPtr<IDBTransaction> m_transaction;
 };
 
 } // namespace WebCore
index f45c43734022d9adeacbe2155bd077de8b377fbb..c9f9aefa97a153f161f0f5549121e48e1db35812 100644 (file)
 
 namespace WebCore {
 
-PassRefPtr<IDBRequest> IDBRequest::create(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransactionBackendInterface* transaction)
+PassRefPtr<IDBRequest> IDBRequest::create(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransaction* transaction)
 {
     return adoptRef(new IDBRequest(context, source, transaction));
 }
 
-IDBRequest::IDBRequest(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransactionBackendInterface* transaction)
+IDBRequest::IDBRequest(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransaction* transaction)
     : ActiveDOMObject(context, this)
     , m_source(source)
     , m_transaction(transaction)
     , m_readyState(LOADING)
 {
     if (m_transaction)
-        IDBPendingTransactionMonitor::removePendingTransaction(m_transaction.get());
+        IDBPendingTransactionMonitor::removePendingTransaction(m_transaction->backend());
 }
 
 IDBRequest::~IDBRequest()
 {
 }
 
-bool IDBRequest::resetReadyState(IDBTransactionBackendInterface* transaction)
+bool IDBRequest::resetReadyState(IDBTransaction* transaction)
 {
     ASSERT(scriptExecutionContext());
     if (m_readyState != DONE)
@@ -74,7 +74,7 @@ bool IDBRequest::resetReadyState(IDBTransactionBackendInterface* transaction)
     m_transaction = transaction;
     m_readyState = LOADING;
 
-    IDBPendingTransactionMonitor::removePendingTransaction(m_transaction.get());
+    IDBPendingTransactionMonitor::removePendingTransaction(m_transaction->backend());
 
     return true;
 }
@@ -115,12 +115,14 @@ void IDBRequest::onSuccess(PassRefPtr<IDBTransactionBackendInterface> prpBackend
         return;
 
     RefPtr<IDBTransactionBackendInterface> backend = prpBackend;
-    // This is only used by setVersion which will always have a source that's an IDBDatabase.
-    m_source->idbDatabase()->setSetVersionTransaction(backend.get());
     RefPtr<IDBTransaction> frontend = IDBTransaction::create(scriptExecutionContext(), backend, m_source->idbDatabase().get());
     backend->setCallbacks(frontend.get());
-    m_transaction = backend;
-    IDBPendingTransactionMonitor::removePendingTransaction(m_transaction.get());
+    m_transaction = frontend;
+
+    ASSERT(m_source->type() == IDBAny::IDBDatabaseType);
+    m_source->idbDatabase()->setSetVersionTransaction(frontend.get());
+
+    IDBPendingTransactionMonitor::removePendingTransaction(m_transaction->backend());
     enqueueEvent(IDBSuccessEvent::create(m_source, IDBAny::create(frontend.release())));
 }
 
@@ -142,15 +144,17 @@ bool IDBRequest::dispatchEvent(PassRefPtr<Event> event)
     Vector<RefPtr<EventTarget> > targets;
     targets.append(this);
     ASSERT(event->target() == this);
+    if (m_transaction)
+        targets.append(m_transaction);
+
     ASSERT(event->isIDBErrorEvent() || event->isIDBSuccessEvent());
     bool dontPreventDefault = static_cast<IDBEvent*>(event.get())->dispatch(targets);
 
     if (m_transaction) {
         if (dontPreventDefault && event->isIDBErrorEvent())
-            m_transaction->abort();
-        m_transaction->didCompleteTaskEvents();
+            m_transaction->backend()->abort();
+        m_transaction->backend()->didCompleteTaskEvents();
     }
-
     return dontPreventDefault;
 }
 
index 849eb9ad1e4ceafb3df1c7984b0038bced5f51c3..2c5f4545a38cc1a3e42269865690d39b48d2dcd5 100644 (file)
 namespace WebCore {
 
 class IDBEvent;
-class IDBTransactionBackendInterface;
+class IDBTransaction;
 
 class IDBRequest : public IDBCallbacks, public EventTarget, public ActiveDOMObject {
 public:
-    static PassRefPtr<IDBRequest> create(ScriptExecutionContext*, PassRefPtr<IDBAny> source, IDBTransactionBackendInterface*);
+    static PassRefPtr<IDBRequest> create(ScriptExecutionContext*, PassRefPtr<IDBAny> source, IDBTransaction*);
     virtual ~IDBRequest();
 
     // Defined in the IDL
@@ -58,7 +58,7 @@ public:
     DEFINE_ATTRIBUTE_EVENT_LISTENER(success);
     DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
 
-    bool resetReadyState(IDBTransactionBackendInterface*);
+    bool resetReadyState(IDBTransaction*);
 
     // IDBCallbacks
     virtual void onError(PassRefPtr<IDBDatabaseError>);
@@ -80,7 +80,7 @@ public:
     using ThreadSafeShared<IDBCallbacks>::deref;
 
 private:
-    IDBRequest(ScriptExecutionContext*, PassRefPtr<IDBAny> source, IDBTransactionBackendInterface* transaction);
+    IDBRequest(ScriptExecutionContext*, PassRefPtr<IDBAny> source, IDBTransaction*);
 
     void enqueueEvent(PassRefPtr<Event>);
 
@@ -91,7 +91,7 @@ private:
     virtual EventTargetData* ensureEventTargetData();
 
     RefPtr<IDBAny> m_source;
-    RefPtr<IDBTransactionBackendInterface> m_transaction;
+    RefPtr<IDBTransaction> m_transaction;
 
     ReadyState m_readyState;
 
index b9e015503233a1cd6b920199fd9ca396fb05f57b..9e89aabda215b1426d92653e10c4c018d645c1d0 100644 (file)
@@ -52,7 +52,9 @@ IDBTransaction::IDBTransaction(ScriptExecutionContext* context, PassRefPtr<IDBTr
     , m_backend(backend)
     , m_database(db)
     , m_mode(m_backend->mode())
+    , m_finished(false)
 {
+    ASSERT(m_backend);
     IDBPendingTransactionMonitor::addPendingTransaction(m_backend.get());
 }
 
@@ -73,7 +75,7 @@ IDBDatabase* IDBTransaction::db()
 PassRefPtr<IDBObjectStore> IDBTransaction::objectStore(const String& name, ExceptionCode& ec)
 {
     // FIXME: It'd be better (because it's more deterministic) if we didn't start throwing this until the complete or abort event fires.
-    if (!m_backend) {
+    if (m_finished) {
         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
         return 0;
     }
@@ -82,7 +84,7 @@ PassRefPtr<IDBObjectStore> IDBTransaction::objectStore(const String& name, Excep
         ASSERT(ec);
         return 0;
     }
-    RefPtr<IDBObjectStore> objectStore = IDBObjectStore::create(objectStoreBackend, m_backend.get());
+    RefPtr<IDBObjectStore> objectStore = IDBObjectStore::create(objectStoreBackend, this);
     return objectStore.release();
 }
 
@@ -120,7 +122,8 @@ void IDBTransaction::contextDestroyed()
     RefPtr<IDBTransaction> selfRef = this;
     if (m_backend)
         m_backend->abort();
-    m_backend.clear();
+
+    m_finished = true;
 }
 
 void IDBTransaction::enqueueEvent(PassRefPtr<Event> event)
@@ -128,9 +131,9 @@ void IDBTransaction::enqueueEvent(PassRefPtr<Event> event)
     if (!scriptExecutionContext())
         return;
 
-    ASSERT(m_backend);
-    m_backend.clear();
-    
+    ASSERT(!m_finished);
+    m_finished = true;
+
     ASSERT(scriptExecutionContext()->isDocument());
     EventQueue* eventQueue = static_cast<Document*>(scriptExecutionContext())->eventQueue();
     event->setTarget(this);
index 3fdb9e52000c6c0d705119e551340e5711b7564c..38db3b6ed0d74071a58c0c87cdd9a8989f46a807 100644 (file)
@@ -62,6 +62,7 @@ public:
 
     DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
     DEFINE_ATTRIBUTE_EVENT_LISTENER(complete);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
 
     // IDBTransactionCallbacks
     virtual void onAbort();
@@ -92,6 +93,7 @@ private:
     RefPtr<IDBTransactionBackendInterface> m_backend;
     RefPtr<IDBDatabase> m_database;
     unsigned short m_mode;
+    bool m_finished;
 
     EventTargetData m_eventTargetData;
 };
index cf3b1ce8365d1f0615829c66dd92d52c670dbbba..2f0219544ff53fa00a60ee6c057c785b46c10e8a 100644 (file)
@@ -44,6 +44,7 @@ module storage {
         // Events
         attribute EventListener onabort;
         attribute EventListener oncomplete;
+        attribute EventListener onerror;
         // EventTarget interface
         void addEventListener(in DOMString type,
                               in EventListener listener,