+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.
--- /dev/null
+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
+
--- /dev/null
+<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>
+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.
#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)
class IDBCursorBackendInterface;
class IDBKey;
class IDBRequest;
+class IDBTransaction;
class ScriptExecutionContext;
class SerializedScriptValue;
-class IDBTransactionBackendInterface;
class IDBCursor : public RefCounted<IDBCursor> {
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));
}
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
{
}
-void IDBDatabase::setSetVersionTransaction(IDBTransactionBackendInterface* transaction)
+void IDBDatabase::setSetVersionTransaction(IDBTransaction* transaction)
{
m_setVersionTransaction = transaction;
}
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;
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)
}
~IDBDatabase();
- void setSetVersionTransaction(IDBTransactionBackendInterface*);
+ void setSetVersionTransaction(IDBTransaction*);
// Implement the IDL
String name() const { return m_backend->name(); }
IDBDatabase(PassRefPtr<IDBDatabaseBackendInterface>);
RefPtr<IDBDatabaseBackendInterface> m_backend;
- RefPtr<IDBTransactionBackendInterface> m_setVersionTransaction;
+ RefPtr<IDBTransaction> m_setVersionTransaction;
bool m_noNewTransactions;
};
#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)
{
}
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;
}
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;
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;
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;
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));
}
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
#include "IDBIndex.h"
#include "IDBKey.h"
#include "IDBKeyRange.h"
-#include "IDBTransactionBackendInterface.h"
+#include "IDBTransaction.h"
#include "SerializedScriptValue.h"
#include <wtf/UnusedParam.h>
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)
{
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();
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;
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;
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;
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;
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)
}
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();
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));
}
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
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)
m_transaction = transaction;
m_readyState = LOADING;
- IDBPendingTransactionMonitor::removePendingTransaction(m_transaction.get());
+ IDBPendingTransactionMonitor::removePendingTransaction(m_transaction->backend());
return true;
}
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())));
}
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;
}
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
DEFINE_ATTRIBUTE_EVENT_LISTENER(success);
DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
- bool resetReadyState(IDBTransactionBackendInterface*);
+ bool resetReadyState(IDBTransaction*);
// IDBCallbacks
virtual void onError(PassRefPtr<IDBDatabaseError>);
using ThreadSafeShared<IDBCallbacks>::deref;
private:
- IDBRequest(ScriptExecutionContext*, PassRefPtr<IDBAny> source, IDBTransactionBackendInterface* transaction);
+ IDBRequest(ScriptExecutionContext*, PassRefPtr<IDBAny> source, IDBTransaction*);
void enqueueEvent(PassRefPtr<Event>);
virtual EventTargetData* ensureEventTargetData();
RefPtr<IDBAny> m_source;
- RefPtr<IDBTransactionBackendInterface> m_transaction;
+ RefPtr<IDBTransaction> m_transaction;
ReadyState m_readyState;
, m_backend(backend)
, m_database(db)
, m_mode(m_backend->mode())
+ , m_finished(false)
{
+ ASSERT(m_backend);
IDBPendingTransactionMonitor::addPendingTransaction(m_backend.get());
}
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;
}
ASSERT(ec);
return 0;
}
- RefPtr<IDBObjectStore> objectStore = IDBObjectStore::create(objectStoreBackend, m_backend.get());
+ RefPtr<IDBObjectStore> objectStore = IDBObjectStore::create(objectStoreBackend, this);
return objectStore.release();
}
RefPtr<IDBTransaction> selfRef = this;
if (m_backend)
m_backend->abort();
- m_backend.clear();
+
+ m_finished = true;
}
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);
DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
DEFINE_ATTRIBUTE_EVENT_LISTENER(complete);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
// IDBTransactionCallbacks
virtual void onAbort();
RefPtr<IDBTransactionBackendInterface> m_backend;
RefPtr<IDBDatabase> m_database;
unsigned short m_mode;
+ bool m_finished;
EventTargetData m_eventTargetData;
};
// Events
attribute EventListener onabort;
attribute EventListener oncomplete;
+ attribute EventListener onerror;
// EventTarget interface
void addEventListener(in DOMString type,
in EventListener listener,