summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/storage
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-18 13:36:51 +0100
committerSteve Block <steveblock@google.com>2011-05-24 15:38:28 +0100
commit2fc2651226baac27029e38c9d6ef883fa32084db (patch)
treee396d4bf89dcce6ed02071be66212495b1df1dec /Source/WebCore/storage
parentb3725cedeb43722b3b175aaeff70552e562d2c94 (diff)
downloadexternal_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.zip
external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.gz
external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.bz2
Merge WebKit at r78450: Initial merge by git.
Change-Id: I6d3e5f1f868ec266a0aafdef66182ddc3f265dc1
Diffstat (limited to 'Source/WebCore/storage')
-rw-r--r--Source/WebCore/storage/Database.cpp4
-rw-r--r--Source/WebCore/storage/IDBAbortEvent.cpp8
-rw-r--r--Source/WebCore/storage/IDBAbortEvent.h4
-rw-r--r--Source/WebCore/storage/IDBCallbacks.h1
-rw-r--r--Source/WebCore/storage/IDBCompleteEvent.cpp8
-rw-r--r--Source/WebCore/storage/IDBCompleteEvent.h4
-rw-r--r--Source/WebCore/storage/IDBCursor.cpp6
-rw-r--r--Source/WebCore/storage/IDBCursor.h8
-rw-r--r--Source/WebCore/storage/IDBCursor.idl5
-rw-r--r--Source/WebCore/storage/IDBCursorBackendImpl.cpp59
-rw-r--r--Source/WebCore/storage/IDBCursorBackendImpl.h6
-rw-r--r--Source/WebCore/storage/IDBDatabase.cpp82
-rw-r--r--Source/WebCore/storage/IDBDatabase.h47
-rw-r--r--Source/WebCore/storage/IDBDatabase.idl21
-rw-r--r--Source/WebCore/storage/IDBDatabaseBackendImpl.cpp6
-rw-r--r--Source/WebCore/storage/IDBDatabaseBackendImpl.h2
-rw-r--r--Source/WebCore/storage/IDBDatabaseBackendInterface.h2
-rw-r--r--Source/WebCore/storage/IDBErrorEvent.cpp2
-rw-r--r--Source/WebCore/storage/IDBEvent.cpp55
-rw-r--r--Source/WebCore/storage/IDBEvent.h5
-rw-r--r--Source/WebCore/storage/IDBFactoryBackendImpl.cpp64
-rw-r--r--Source/WebCore/storage/IDBFactoryBackendInterface.cpp4
-rw-r--r--Source/WebCore/storage/IDBFactoryBackendInterface.h2
-rw-r--r--Source/WebCore/storage/IDBIndex.cpp26
-rw-r--r--Source/WebCore/storage/IDBIndex.h18
-rw-r--r--Source/WebCore/storage/IDBIndex.idl4
-rw-r--r--Source/WebCore/storage/IDBIndexBackendImpl.cpp2
-rw-r--r--Source/WebCore/storage/IDBObjectStore.cpp34
-rw-r--r--Source/WebCore/storage/IDBObjectStore.h13
-rw-r--r--Source/WebCore/storage/IDBObjectStore.idl4
-rw-r--r--Source/WebCore/storage/IDBObjectStoreBackendImpl.cpp128
-rw-r--r--Source/WebCore/storage/IDBObjectStoreBackendImpl.h8
-rw-r--r--Source/WebCore/storage/IDBObjectStoreBackendInterface.h11
-rw-r--r--Source/WebCore/storage/IDBRequest.cpp179
-rw-r--r--Source/WebCore/storage/IDBRequest.h38
-rw-r--r--Source/WebCore/storage/IDBSuccessEvent.cpp2
-rw-r--r--Source/WebCore/storage/IDBTimeoutEvent.cpp55
-rw-r--r--Source/WebCore/storage/IDBTimeoutEvent.h57
-rw-r--r--Source/WebCore/storage/IDBTransaction.cpp129
-rw-r--r--Source/WebCore/storage/IDBTransaction.h35
-rw-r--r--Source/WebCore/storage/IDBTransaction.idl2
-rw-r--r--Source/WebCore/storage/IDBTransactionBackendImpl.cpp11
-rw-r--r--Source/WebCore/storage/IDBTransactionBackendImpl.h5
-rw-r--r--Source/WebCore/storage/IDBTransactionCallbacks.h1
-rw-r--r--Source/WebCore/storage/chromium/IDBFactoryBackendInterface.cpp5
45 files changed, 618 insertions, 554 deletions
diff --git a/Source/WebCore/storage/Database.cpp b/Source/WebCore/storage/Database.cpp
index 8ef780e..75f616a 100644
--- a/Source/WebCore/storage/Database.cpp
+++ b/Source/WebCore/storage/Database.cpp
@@ -36,7 +36,7 @@
#include "DatabaseThread.h"
#include "DatabaseTracker.h"
#include "Document.h"
-#include "InspectorInstrumentation.h"
+#include "InspectorDatabaseInstrumentation.h"
#include "Logging.h"
#include "NotImplemented.h"
#include "Page.h"
@@ -107,7 +107,7 @@ PassRefPtr<Database> Database::openDatabase(ScriptExecutionContext* context, con
context->setHasOpenDatabases();
- InspectorInstrumentation::didOpenDatabase(context, database.get(), context->securityOrigin()->host(), name, expectedVersion);
+ InspectorInstrumentation::didOpenDatabase(context, database, context->securityOrigin()->host(), name, expectedVersion);
// 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
diff --git a/Source/WebCore/storage/IDBAbortEvent.cpp b/Source/WebCore/storage/IDBAbortEvent.cpp
index 21760f8..980d656 100644
--- a/Source/WebCore/storage/IDBAbortEvent.cpp
+++ b/Source/WebCore/storage/IDBAbortEvent.cpp
@@ -36,13 +36,13 @@
namespace WebCore {
-PassRefPtr<IDBAbortEvent> IDBAbortEvent::create()
+PassRefPtr<IDBAbortEvent> IDBAbortEvent::create(PassRefPtr<IDBAny> source)
{
- return adoptRef(new IDBAbortEvent());
+ return adoptRef(new IDBAbortEvent(source));
}
-IDBAbortEvent::IDBAbortEvent()
- : IDBEvent(eventNames().abortEvent, 0) // FIXME: set the source to the transaction
+IDBAbortEvent::IDBAbortEvent(PassRefPtr<IDBAny> source)
+ : IDBEvent(eventNames().abortEvent, source, true)
{
}
diff --git a/Source/WebCore/storage/IDBAbortEvent.h b/Source/WebCore/storage/IDBAbortEvent.h
index bdc2202..fc27989 100644
--- a/Source/WebCore/storage/IDBAbortEvent.h
+++ b/Source/WebCore/storage/IDBAbortEvent.h
@@ -40,14 +40,14 @@ namespace WebCore {
class IDBAbortEvent : public IDBEvent {
public:
- static PassRefPtr<IDBAbortEvent> create();
+ static PassRefPtr<IDBAbortEvent> create(PassRefPtr<IDBAny> source);
// FIXME: Need to allow creation of these events from JS.
virtual ~IDBAbortEvent();
virtual bool isIDBAbortEvent() const { return true; }
private:
- IDBAbortEvent();
+ IDBAbortEvent(PassRefPtr<IDBAny> source);
};
} // namespace WebCore
diff --git a/Source/WebCore/storage/IDBCallbacks.h b/Source/WebCore/storage/IDBCallbacks.h
index e62c085..29fb1c4 100644
--- a/Source/WebCore/storage/IDBCallbacks.h
+++ b/Source/WebCore/storage/IDBCallbacks.h
@@ -49,7 +49,6 @@ public:
virtual ~IDBCallbacks() { }
virtual void onError(PassRefPtr<IDBDatabaseError>) = 0;
- virtual void onSuccess() = 0; // For "null".
virtual void onSuccess(PassRefPtr<IDBCursorBackendInterface>) = 0;
virtual void onSuccess(PassRefPtr<IDBDatabaseBackendInterface>) = 0;
virtual void onSuccess(PassRefPtr<IDBIndexBackendInterface>) = 0;
diff --git a/Source/WebCore/storage/IDBCompleteEvent.cpp b/Source/WebCore/storage/IDBCompleteEvent.cpp
index f0ad9fc..20ee57a 100644
--- a/Source/WebCore/storage/IDBCompleteEvent.cpp
+++ b/Source/WebCore/storage/IDBCompleteEvent.cpp
@@ -36,13 +36,13 @@
namespace WebCore {
-PassRefPtr<IDBCompleteEvent> IDBCompleteEvent::create()
+PassRefPtr<IDBCompleteEvent> IDBCompleteEvent::create(PassRefPtr<IDBAny> source)
{
- return adoptRef(new IDBCompleteEvent());
+ return adoptRef(new IDBCompleteEvent(source));
}
-IDBCompleteEvent::IDBCompleteEvent()
- : IDBEvent(eventNames().completeEvent, 0) // FIXME: set the source to the transaction
+IDBCompleteEvent::IDBCompleteEvent(PassRefPtr<IDBAny> source)
+ : IDBEvent(eventNames().completeEvent, source, false)
{
}
diff --git a/Source/WebCore/storage/IDBCompleteEvent.h b/Source/WebCore/storage/IDBCompleteEvent.h
index c407096..c004a72 100644
--- a/Source/WebCore/storage/IDBCompleteEvent.h
+++ b/Source/WebCore/storage/IDBCompleteEvent.h
@@ -40,14 +40,14 @@ namespace WebCore {
class IDBCompleteEvent : public IDBEvent {
public:
- static PassRefPtr<IDBCompleteEvent> create();
+ static PassRefPtr<IDBCompleteEvent> create(PassRefPtr<IDBAny> source);
// FIXME: Need to allow creation of these events from JS.
virtual ~IDBCompleteEvent();
virtual bool isIDBCompleteEvent() const { return true; }
private:
- IDBCompleteEvent();
+ IDBCompleteEvent(PassRefPtr<IDBAny> source);
};
} // namespace WebCore
diff --git a/Source/WebCore/storage/IDBCursor.cpp b/Source/WebCore/storage/IDBCursor.cpp
index 444c109..531cae1 100644
--- a/Source/WebCore/storage/IDBCursor.cpp
+++ b/Source/WebCore/storage/IDBCursor.cpp
@@ -33,13 +33,13 @@
#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)
@@ -84,7 +84,7 @@ void IDBCursor::continueFunction(PassRefPtr<IDBKey> key, ExceptionCode& ec)
if (m_request->resetReadyState(m_transaction.get()))
m_backend->continueFunction(key, m_request, ec);
else
- ASSERT_NOT_REACHED();
+ ec = IDBDatabaseException::NOT_ALLOWED_ERR;
}
PassRefPtr<IDBRequest> IDBCursor::deleteFunction(ScriptExecutionContext* context, ExceptionCode& ec)
diff --git a/Source/WebCore/storage/IDBCursor.h b/Source/WebCore/storage/IDBCursor.h
index 54bf51a..9f5ffad 100644
--- a/Source/WebCore/storage/IDBCursor.h
+++ b/Source/WebCore/storage/IDBCursor.h
@@ -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
diff --git a/Source/WebCore/storage/IDBCursor.idl b/Source/WebCore/storage/IDBCursor.idl
index 12d0baf..2e1459f 100644
--- a/Source/WebCore/storage/IDBCursor.idl
+++ b/Source/WebCore/storage/IDBCursor.idl
@@ -37,9 +37,8 @@ module storage {
readonly attribute IDBKey key;
readonly attribute IDBAny value;
- // FIXME: Implement.
- //[CallWith=ScriptExecutionContext] IDBRequest update(in SerializedScriptValue value)
- // raises (IDBDatabaseException);
+ [CallWith=ScriptExecutionContext] IDBRequest update(in SerializedScriptValue value)
+ raises (IDBDatabaseException);
[ImplementationFunction=continueFunction] void continue(in [Optional] IDBKey key)
raises (IDBDatabaseException);
[CallWith=ScriptExecutionContext, ImplementationFunction=deleteFunction] IDBRequest delete()
diff --git a/Source/WebCore/storage/IDBCursorBackendImpl.cpp b/Source/WebCore/storage/IDBCursorBackendImpl.cpp
index d75e28d..089bb67 100644
--- a/Source/WebCore/storage/IDBCursorBackendImpl.cpp
+++ b/Source/WebCore/storage/IDBCursorBackendImpl.cpp
@@ -68,7 +68,6 @@ unsigned short IDBCursorBackendImpl::direction() const
PassRefPtr<IDBKey> IDBCursorBackendImpl::key() const
{
-
return m_currentKey;
}
@@ -79,43 +78,15 @@ PassRefPtr<IDBAny> IDBCursorBackendImpl::value() const
return IDBAny::create(m_currentIDBKeyValue.get());
}
-void IDBCursorBackendImpl::update(PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBCallbacks> prpCallbacks, ExceptionCode& ec)
+void IDBCursorBackendImpl::update(PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBCallbacks> callbacks, ExceptionCode& ec)
{
- RefPtr<IDBCursorBackendImpl> cursor = this;
- RefPtr<SerializedScriptValue> value = prpValue;
- RefPtr<IDBCallbacks> callbacks = prpCallbacks;
- // FIXME: Throw DATA_ERR and SERIAL_ERR when appropriate.
- if (!m_transaction->scheduleTask(createCallbackTask(&IDBCursorBackendImpl::updateInternal, cursor, value, callbacks)))
+ if (!m_query || m_currentId == InvalidId || !m_isSerializedScriptValueCursor) {
ec = IDBDatabaseException::NOT_ALLOWED_ERR;
-}
-
-void IDBCursorBackendImpl::updateInternal(ScriptExecutionContext*, PassRefPtr<IDBCursorBackendImpl> cursor, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBCallbacks> callbacks)
-{
- // FIXME: This method doesn't update indexes. It's dangerous to call in its current state.
- callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Not implemented."));
- return;
-
- RefPtr<SerializedScriptValue> value = prpValue;
-
- if (!cursor->m_query || cursor->m_currentId == InvalidId) {
- // FIXME: Use the proper error code when it's specced.
- callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Operation not possible."));
return;
}
- String sql = "UPDATE ObjectStoreData SET value = ? WHERE id = ?";
- SQLiteStatement updateQuery(cursor->database(), sql);
-
- bool ok = updateQuery.prepare() == SQLResultOk;
- ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
- updateQuery.bindText(1, value->toWireString());
- updateQuery.bindInt64(2, cursor->m_currentId);
- ok = updateQuery.step() == SQLResultDone;
- ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
-
- if (cursor->m_isSerializedScriptValueCursor)
- cursor->m_currentSerializedScriptValue = value.release();
- callbacks->onSuccess();
+ RefPtr<IDBKey> key = m_currentIDBKeyValue ? m_currentIDBKeyValue : m_currentKey;
+ m_objectStore->put(value, key.release(), IDBObjectStoreBackendInterface::CursorUpdate, callbacks, m_transaction.get(), ec);
}
void IDBCursorBackendImpl::continueFunction(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> prpCallbacks, ExceptionCode& ec)
@@ -127,6 +98,20 @@ void IDBCursorBackendImpl::continueFunction(PassRefPtr<IDBKey> prpKey, PassRefPt
ec = IDBDatabaseException::NOT_ALLOWED_ERR;
}
+bool IDBCursorBackendImpl::currentRowExists()
+{
+ String sql = m_currentIDBKeyValue ? "SELECT id FROM IndexData WHERE id = ?" : "SELECT id FROM ObjectStoreData WHERE id = ?";
+ SQLiteStatement statement(m_database->db(), sql);
+
+ bool ok = statement.prepare() == SQLResultOk;
+ ASSERT_UNUSED(ok, ok);
+
+ statement.bindInt64(1, m_currentId);
+ return statement.step() == SQLResultRow;
+}
+
+// IMPORTANT: If this ever 1) fires an 'error' event and 2) it's possible to fire another event afterwards,
+// IDBRequest::hasPendingActivity() will need to be modified to handle this!!!
void IDBCursorBackendImpl::continueFunctionInternal(ScriptExecutionContext*, PassRefPtr<IDBCursorBackendImpl> prpCursor, PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> callbacks)
{
RefPtr<IDBCursorBackendImpl> cursor = prpCursor;
@@ -138,13 +123,17 @@ void IDBCursorBackendImpl::continueFunctionInternal(ScriptExecutionContext*, Pas
cursor->m_currentKey = 0;
cursor->m_currentSerializedScriptValue = 0;
cursor->m_currentIDBKeyValue = 0;
- callbacks->onSuccess();
+ callbacks->onSuccess(SerializedScriptValue::nullValue());
return;
}
RefPtr<IDBKey> oldKey = cursor->m_currentKey;
cursor->loadCurrentRow();
+ // Skip if this entry has been deleted from the object store.
+ if (!cursor->currentRowExists())
+ continue;
+
// If a key was supplied, we must loop until we find that key (or hit the end).
if (key && !key->isEqual(cursor->m_currentKey.get()))
continue;
@@ -178,7 +167,7 @@ void IDBCursorBackendImpl::loadCurrentRow()
m_currentId = m_query->getColumnInt64(0);
m_currentKey = IDBKey::fromQuery(*m_query, 1);
if (m_isSerializedScriptValueCursor)
- m_currentSerializedScriptValue = SerializedScriptValue::createFromWire(m_query->getColumnText(4));
+ m_currentSerializedScriptValue = SerializedScriptValue::createFromWire(m_query->getColumnBlobAsString(4));
m_currentIDBKeyValue = IDBKey::fromQuery(*m_query, 5);
}
diff --git a/Source/WebCore/storage/IDBCursorBackendImpl.h b/Source/WebCore/storage/IDBCursorBackendImpl.h
index e3a8995..f459139 100644
--- a/Source/WebCore/storage/IDBCursorBackendImpl.h
+++ b/Source/WebCore/storage/IDBCursorBackendImpl.h
@@ -65,10 +65,10 @@ public:
private:
IDBCursorBackendImpl(IDBSQLiteDatabase*, PassRefPtr<IDBKeyRange>, IDBCursor::Direction, PassOwnPtr<SQLiteStatement> query, bool isSerializedScriptValueCursor, IDBTransactionBackendInterface*, IDBObjectStoreBackendInterface*);
+ bool currentRowExists();
void loadCurrentRow();
SQLiteDatabase& database() const;
- static void updateInternal(ScriptExecutionContext*, PassRefPtr<IDBCursorBackendImpl>, PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBCallbacks>);
static void continueFunctionInternal(ScriptExecutionContext*, PassRefPtr<IDBCursorBackendImpl>, PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>);
static const int64_t InvalidId = -1;
@@ -80,11 +80,15 @@ private:
OwnPtr<SQLiteStatement> m_query;
bool m_isSerializedScriptValueCursor;
int64_t m_currentId;
+
+ // The key in the objectStore or index that this cursor iterates over.
RefPtr<IDBKey> m_currentKey;
// m_isSerializedScriptValueCursor will only be available for object cursors.
RefPtr<SerializedScriptValue> m_currentSerializedScriptValue;
+
// FIXME: make the primary key available via script for all types of cursors.
+ // For cursors on indices, this is the key in the objectstore that corresponds to the current entry in the index.
RefPtr<IDBKey> m_currentIDBKeyValue;
RefPtr<IDBTransactionBackendInterface> m_transaction;
diff --git a/Source/WebCore/storage/IDBDatabase.cpp b/Source/WebCore/storage/IDBDatabase.cpp
index 33f004b..9a5eb6c 100644
--- a/Source/WebCore/storage/IDBDatabase.cpp
+++ b/Source/WebCore/storage/IDBDatabase.cpp
@@ -41,11 +41,16 @@
namespace WebCore {
-// FIXME: We need to spec this differently.
-const unsigned long defaultTimeout = 0; // Infinite.
+PassRefPtr<IDBDatabase> IDBDatabase::create(ScriptExecutionContext* context, PassRefPtr<IDBDatabaseBackendInterface> database)
+{
+ return adoptRef(new IDBDatabase(context, database));
+}
-IDBDatabase::IDBDatabase(PassRefPtr<IDBDatabaseBackendInterface> backend)
- : m_backend(backend)
+IDBDatabase::IDBDatabase(ScriptExecutionContext* context, PassRefPtr<IDBDatabaseBackendInterface> backend)
+ : ActiveDOMObject(context, this)
+ , m_backend(backend)
+ , m_noNewTransactions(false)
+ , m_stopped(false)
{
// We pass a reference of this object before it can be adopted.
relaxAdoptionRequirement();
@@ -53,9 +58,10 @@ IDBDatabase::IDBDatabase(PassRefPtr<IDBDatabaseBackendInterface> backend)
IDBDatabase::~IDBDatabase()
{
+ ASSERT(m_stopped);
}
-void IDBDatabase::setSetVersionTransaction(IDBTransactionBackendInterface* transaction)
+void IDBDatabase::setSetVersionTransaction(IDBTransaction* transaction)
{
m_setVersionTransaction = transaction;
}
@@ -73,7 +79,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;
@@ -88,7 +94,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)
@@ -98,38 +104,27 @@ PassRefPtr<IDBRequest> IDBDatabase::setVersion(ScriptExecutionContext* context,
return request;
}
-PassRefPtr<IDBTransaction> IDBDatabase::transaction(ScriptExecutionContext* context, const OptionsObject& options, ExceptionCode& ec)
+PassRefPtr<IDBTransaction> IDBDatabase::transaction(ScriptExecutionContext* context, PassRefPtr<DOMStringList> prpStoreNames, unsigned short mode, ExceptionCode& ec)
{
- RefPtr<DOMStringList> storeNames = options.getKeyDOMStringList("objectStoreNames");
- if (!storeNames) {
+ RefPtr<DOMStringList> storeNames = prpStoreNames;
+ if (!storeNames)
storeNames = DOMStringList::create();
- String storeName;
- if (options.getKeyString("objectStoreNames", storeName))
- storeNames->append(storeName);
- }
- // Gets cast to an unsigned short.
- int32_t mode = IDBTransaction::READ_ONLY;
- options.getKeyInt32("mode", mode);
if (mode != IDBTransaction::READ_WRITE && mode != IDBTransaction::READ_ONLY) {
// FIXME: May need to change when specced: http://www.w3.org/Bugs/Public/show_bug.cgi?id=11406
ec = IDBDatabaseException::CONSTRAINT_ERR;
return 0;
}
-
- // Gets cast to an unsigned long.
- // FIXME: The spec needs to be updated on this. It should probably take a double.
- int32_t timeout = defaultTimeout;
- options.getKeyInt32("timeout", timeout);
- int64_t unsignedLongMax = std::numeric_limits<unsigned long>::max();
- if (timeout < 0 || timeout > unsignedLongMax)
- timeout = defaultTimeout; // Ignore illegal values.
+ if (m_noNewTransactions) {
+ ec = IDBDatabaseException::NOT_ALLOWED_ERR;
+ return 0;
+ }
// We need to create a new transaction synchronously. Locks are acquired asynchronously. Operations
// can be queued against the transaction at any point. They will start executing as soon as the
// appropriate locks have been acquired.
// Also note that each backend object corresponds to exactly one IDBTransaction object.
- RefPtr<IDBTransactionBackendInterface> transactionBackend = m_backend->transaction(storeNames.get(), mode, timeout, ec);
+ RefPtr<IDBTransactionBackendInterface> transactionBackend = m_backend->transaction(storeNames.get(), mode, ec);
if (!transactionBackend) {
ASSERT(ec);
return 0;
@@ -141,7 +136,40 @@ PassRefPtr<IDBTransaction> IDBDatabase::transaction(ScriptExecutionContext* cont
void IDBDatabase::close()
{
- m_backend->close();
+ m_noNewTransactions = true;
+}
+
+bool IDBDatabase::hasPendingActivity() const
+{
+ // FIXME: Try to find some way not to just leak this object until page navigation.
+ // FIXME: In an ideal world, we should return true as long as anyone has or can
+ // get a handle to us or any derivative transaction/request object and any
+ // of those have event listeners. This is in order to handle user generated
+ // events properly.
+ return !m_stopped || ActiveDOMObject::hasPendingActivity();
+}
+
+void IDBDatabase::stop()
+{
+ // Stop fires at a deterministic time, so we need to call close in it.
+ close();
+
+ m_stopped = true;
+}
+
+ScriptExecutionContext* IDBDatabase::scriptExecutionContext() const
+{
+ return ActiveDOMObject::scriptExecutionContext();
+}
+
+EventTargetData* IDBDatabase::eventTargetData()
+{
+ return &m_eventTargetData;
+}
+
+EventTargetData* IDBDatabase::ensureEventTargetData()
+{
+ return &m_eventTargetData;
}
} // namespace WebCore
diff --git a/Source/WebCore/storage/IDBDatabase.h b/Source/WebCore/storage/IDBDatabase.h
index 9ebbf00..f90ddd3 100644
--- a/Source/WebCore/storage/IDBDatabase.h
+++ b/Source/WebCore/storage/IDBDatabase.h
@@ -26,7 +26,10 @@
#ifndef IDBDatabase_h
#define IDBDatabase_h
+#include "ActiveDOMObject.h"
#include "DOMStringList.h"
+#include "Event.h"
+#include "EventTarget.h"
#include "ExceptionCode.h"
#include "IDBDatabaseBackendInterface.h"
#include "IDBObjectStore.h"
@@ -42,17 +45,13 @@ namespace WebCore {
class IDBAny;
class IDBRequest;
-class ScriptExecutionContext;
-class IDBDatabase : public RefCounted<IDBDatabase> {
+class IDBDatabase : public RefCounted<IDBDatabase>, public EventTarget, public ActiveDOMObject {
public:
- static PassRefPtr<IDBDatabase> create(PassRefPtr<IDBDatabaseBackendInterface> database)
- {
- return adoptRef(new IDBDatabase(database));
- }
+ static PassRefPtr<IDBDatabase> create(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendInterface>);
~IDBDatabase();
- void setSetVersionTransaction(IDBTransactionBackendInterface*);
+ void setSetVersionTransaction(IDBTransaction*);
// Implement the IDL
String name() const { return m_backend->name(); }
@@ -61,19 +60,45 @@ public:
// FIXME: Try to modify the code generator so this is unneeded.
PassRefPtr<IDBObjectStore> createObjectStore(const String& name, ExceptionCode& ec) { return createObjectStore(name, OptionsObject(), ec); }
- PassRefPtr<IDBTransaction> transaction(ScriptExecutionContext* context, ExceptionCode& ec) { return transaction(context, OptionsObject(), ec); }
+ PassRefPtr<IDBTransaction> transaction(ScriptExecutionContext* context, ExceptionCode& ec) { return transaction(context, 0, ec); }
+ PassRefPtr<IDBTransaction> transaction(ScriptExecutionContext* context, PassRefPtr<DOMStringList> storeNames, ExceptionCode& ec) { return transaction(context, storeNames, IDBTransaction::READ_ONLY, ec); }
+ PassRefPtr<IDBTransaction> transaction(ScriptExecutionContext*, PassRefPtr<DOMStringList>, unsigned short mode, ExceptionCode&);
PassRefPtr<IDBObjectStore> createObjectStore(const String& name, const OptionsObject&, ExceptionCode&);
void deleteObjectStore(const String& name, ExceptionCode&);
PassRefPtr<IDBRequest> setVersion(ScriptExecutionContext*, const String& version, ExceptionCode&);
- PassRefPtr<IDBTransaction> transaction(ScriptExecutionContext*, const OptionsObject&, ExceptionCode&);
void close();
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
+
+ // ActiveDOMObject
+ virtual bool hasPendingActivity() const;
+ virtual void stop();
+
+ // EventTarget
+ virtual IDBDatabase* toIDBDatabase() { return this; }
+ virtual ScriptExecutionContext* scriptExecutionContext() const;
+
+ using RefCounted<IDBDatabase>::ref;
+ using RefCounted<IDBDatabase>::deref;
+
private:
- IDBDatabase(PassRefPtr<IDBDatabaseBackendInterface>);
+ IDBDatabase(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendInterface>);
+
+ // EventTarget
+ virtual void refEventTarget() { ref(); }
+ virtual void derefEventTarget() { deref(); }
+ virtual EventTargetData* eventTargetData();
+ virtual EventTargetData* ensureEventTargetData();
RefPtr<IDBDatabaseBackendInterface> m_backend;
- RefPtr<IDBTransactionBackendInterface> m_setVersionTransaction;
+ RefPtr<IDBTransaction> m_setVersionTransaction;
+
+ bool m_noNewTransactions;
+ bool m_stopped;
+
+ EventTargetData m_eventTargetData;
};
} // namespace WebCore
diff --git a/Source/WebCore/storage/IDBDatabase.idl b/Source/WebCore/storage/IDBDatabase.idl
index 7eb43e9..3922144 100644
--- a/Source/WebCore/storage/IDBDatabase.idl
+++ b/Source/WebCore/storage/IDBDatabase.idl
@@ -26,22 +26,35 @@
module storage {
interface [
- Conditional=INDEXED_DATABASE
+ Conditional=INDEXED_DATABASE,
+ EventTarget
] IDBDatabase {
readonly attribute DOMString name;
readonly attribute DOMString version;
readonly attribute DOMStringList objectStoreNames;
+ attribute EventListener onabort;
+ attribute EventListener onerror;
+
IDBObjectStore createObjectStore(in DOMString name, in [Optional] OptionsObject options)
raises (IDBDatabaseException);
void deleteObjectStore(in DOMString name)
raises (IDBDatabaseException);
[CallWith=ScriptExecutionContext] IDBRequest setVersion(in DOMString version)
raises (IDBDatabaseException);
- [CallWith=ScriptExecutionContext] IDBTransaction transaction(in [Optional] OptionsObject optionsObject)
+ [CallWith=ScriptExecutionContext] IDBTransaction transaction(in [Optional] DOMStringList storeNames, in [Optional] unsigned short mode)
raises (IDBDatabaseException);
- // FIXME: Implement.
- //void close();
+ void close();
+
+ // EventTarget interface
+ void addEventListener(in DOMString type,
+ in EventListener listener,
+ in boolean useCapture);
+ void removeEventListener(in DOMString type,
+ in EventListener listener,
+ in boolean useCapture);
+ boolean dispatchEvent(in Event evt)
+ raises(EventException);
};
}
diff --git a/Source/WebCore/storage/IDBDatabaseBackendImpl.cpp b/Source/WebCore/storage/IDBDatabaseBackendImpl.cpp
index fa9a336..133c5ae 100644
--- a/Source/WebCore/storage/IDBDatabaseBackendImpl.cpp
+++ b/Source/WebCore/storage/IDBDatabaseBackendImpl.cpp
@@ -214,7 +214,7 @@ void IDBDatabaseBackendImpl::setVersion(const String& version, PassRefPtr<IDBCal
RefPtr<IDBDatabaseBackendImpl> database = this;
RefPtr<IDBCallbacks> callbacks = prpCallbacks;
RefPtr<DOMStringList> objectStoreNames = DOMStringList::create();
- RefPtr<IDBTransactionBackendInterface> transaction = IDBTransactionBackendImpl::create(objectStoreNames.get(), IDBTransaction::VERSION_CHANGE, 0, this);
+ RefPtr<IDBTransactionBackendInterface> transaction = IDBTransactionBackendImpl::create(objectStoreNames.get(), IDBTransaction::VERSION_CHANGE, this);
if (!transaction->scheduleTask(createCallbackTask(&IDBDatabaseBackendImpl::setVersionInternal, database, version, callbacks, transaction),
createCallbackTask(&IDBDatabaseBackendImpl::resetVersion, database, m_version))) {
ec = IDBDatabaseException::NOT_ALLOWED_ERR;
@@ -234,7 +234,7 @@ void IDBDatabaseBackendImpl::setVersionInternal(ScriptExecutionContext*, PassRef
callbacks->onSuccess(transaction);
}
-PassRefPtr<IDBTransactionBackendInterface> IDBDatabaseBackendImpl::transaction(DOMStringList* objectStoreNames, unsigned short mode, unsigned long timeout, ExceptionCode& ec)
+PassRefPtr<IDBTransactionBackendInterface> IDBDatabaseBackendImpl::transaction(DOMStringList* objectStoreNames, unsigned short mode, ExceptionCode& ec)
{
for (size_t i = 0; i < objectStoreNames->length(); ++i) {
if (!m_objectStores.contains(objectStoreNames->item(i))) {
@@ -244,7 +244,7 @@ PassRefPtr<IDBTransactionBackendInterface> IDBDatabaseBackendImpl::transaction(D
}
// FIXME: Return not allowed err if close has been called.
- return IDBTransactionBackendImpl::create(objectStoreNames, mode, timeout, this);
+ return IDBTransactionBackendImpl::create(objectStoreNames, mode, this);
}
void IDBDatabaseBackendImpl::close()
diff --git a/Source/WebCore/storage/IDBDatabaseBackendImpl.h b/Source/WebCore/storage/IDBDatabaseBackendImpl.h
index 570f6a5..8942968 100644
--- a/Source/WebCore/storage/IDBDatabaseBackendImpl.h
+++ b/Source/WebCore/storage/IDBDatabaseBackendImpl.h
@@ -61,7 +61,7 @@ public:
virtual PassRefPtr<IDBObjectStoreBackendInterface> createObjectStore(const String& name, const String& keyPath, bool autoIncrement, IDBTransactionBackendInterface*, ExceptionCode&);
virtual void deleteObjectStore(const String& name, IDBTransactionBackendInterface*, ExceptionCode&);
virtual void setVersion(const String& version, PassRefPtr<IDBCallbacks>, ExceptionCode&);
- virtual PassRefPtr<IDBTransactionBackendInterface> transaction(DOMStringList* objectStoreNames, unsigned short mode, unsigned long timeout, ExceptionCode&);
+ virtual PassRefPtr<IDBTransactionBackendInterface> transaction(DOMStringList* objectStoreNames, unsigned short mode, ExceptionCode&);
virtual void close();
PassRefPtr<IDBObjectStoreBackendInterface> objectStore(const String& name);
diff --git a/Source/WebCore/storage/IDBDatabaseBackendInterface.h b/Source/WebCore/storage/IDBDatabaseBackendInterface.h
index 0dc59b1..9cc7230 100644
--- a/Source/WebCore/storage/IDBDatabaseBackendInterface.h
+++ b/Source/WebCore/storage/IDBDatabaseBackendInterface.h
@@ -57,7 +57,7 @@ public:
virtual PassRefPtr<IDBObjectStoreBackendInterface> createObjectStore(const String& name, const String& keyPath, bool autoIncrement, IDBTransactionBackendInterface*, ExceptionCode&) = 0;
virtual void deleteObjectStore(const String& name, IDBTransactionBackendInterface*, ExceptionCode&) = 0;
virtual void setVersion(const String& version, PassRefPtr<IDBCallbacks>, ExceptionCode&) = 0;
- virtual PassRefPtr<IDBTransactionBackendInterface> transaction(DOMStringList* storeNames, unsigned short mode, unsigned long timeout, ExceptionCode&) = 0;
+ virtual PassRefPtr<IDBTransactionBackendInterface> transaction(DOMStringList* storeNames, unsigned short mode, ExceptionCode&) = 0;
virtual void close() = 0;
};
diff --git a/Source/WebCore/storage/IDBErrorEvent.cpp b/Source/WebCore/storage/IDBErrorEvent.cpp
index cba980d..e576fa8 100644
--- a/Source/WebCore/storage/IDBErrorEvent.cpp
+++ b/Source/WebCore/storage/IDBErrorEvent.cpp
@@ -43,7 +43,7 @@ PassRefPtr<IDBErrorEvent> IDBErrorEvent::create(PassRefPtr<IDBAny> source, const
}
IDBErrorEvent::IDBErrorEvent(PassRefPtr<IDBAny> source, const IDBDatabaseError& error)
- : IDBEvent(eventNames().errorEvent, source)
+ : IDBEvent(eventNames().errorEvent, source, true)
, m_code(error.code())
, m_message(error.message())
{
diff --git a/Source/WebCore/storage/IDBEvent.cpp b/Source/WebCore/storage/IDBEvent.cpp
index f9f6060..a7f3db1 100644
--- a/Source/WebCore/storage/IDBEvent.cpp
+++ b/Source/WebCore/storage/IDBEvent.cpp
@@ -35,8 +35,8 @@
namespace WebCore {
-IDBEvent::IDBEvent(const AtomicString& type, PassRefPtr<IDBAny> source)
- : Event(type, false, false)
+IDBEvent::IDBEvent(const AtomicString& type, PassRefPtr<IDBAny> source, bool canBubble)
+ : Event(type, canBubble, true)
, m_source(source)
{
}
@@ -50,6 +50,57 @@ PassRefPtr<IDBAny> IDBEvent::source()
return m_source;
}
+bool IDBEvent::dispatch(Vector<RefPtr<EventTarget> >& eventTargets)
+{
+ size_t size = eventTargets.size();
+ ASSERT(size);
+
+ setEventPhase(Event::CAPTURING_PHASE);
+ for (size_t i = size - 1; i; --i) { // Don't do the first element.
+ setCurrentTarget(eventTargets[i].get());
+ eventTargets[i]->fireEventListeners(this);
+ if (propagationStopped())
+ goto doneDispatching;
+ }
+
+ setEventPhase(Event::AT_TARGET);
+ setCurrentTarget(eventTargets[0].get());
+ eventTargets[0]->fireEventListeners(this);
+ if (propagationStopped() || !bubbles() || cancelBubble())
+ goto doneDispatching;
+
+ setEventPhase(Event::BUBBLING_PHASE);
+ for (size_t i = 1; i < size; ++i) { // Don't do the first element.
+ setCurrentTarget(eventTargets[i].get());
+ eventTargets[i]->fireEventListeners(this);
+ if (propagationStopped() || cancelBubble())
+ goto doneDispatching;
+ }
+
+ // FIXME: "...However, we also wanted to integrate the window.onerror feature in
+ // HTML5. So after we've fired an "error" event, if .preventDefault() was
+ // never called on the event, we fire an error event on the window (can't
+ // remember if this happens before or after we abort the transaction).
+ // This is a separate event, which for example means that even if you
+ // attach a capturing "error" handler on window, you won't see any events
+ // unless an error really went unhandled. And you also can't call
+ // .preventDefault on the error event fired on the window in order to
+ // prevent the transaction from being aborted. It's purely there for
+ // error reporting and distinctly different from the event propagating to
+ // the window.
+ //
+ // This is similar to how "error" events are handled in workers.
+ //
+ // (I think that so far webkit hasn't implemented the window.onerror
+ // feature yet, so you probably don't want to fire the separate error
+ // event on the window until that has been implemented)."
+
+doneDispatching:
+ setCurrentTarget(0);
+ setEventPhase(0);
+ return !defaultPrevented();
+}
+
} // namespace WebCore
#endif
diff --git a/Source/WebCore/storage/IDBEvent.h b/Source/WebCore/storage/IDBEvent.h
index c44e449..d28885b 100644
--- a/Source/WebCore/storage/IDBEvent.h
+++ b/Source/WebCore/storage/IDBEvent.h
@@ -32,8 +32,10 @@
#if ENABLE(INDEXED_DATABASE)
#include "Event.h"
+#include "EventTarget.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
namespace WebCore {
@@ -44,9 +46,10 @@ public:
virtual ~IDBEvent();
PassRefPtr<IDBAny> source();
+ bool dispatch(Vector<RefPtr<EventTarget> >&); // The target first and then its ancestors in order of how the event bubbles.
protected:
- IDBEvent(const AtomicString& type, PassRefPtr<IDBAny> source);
+ IDBEvent(const AtomicString& type, PassRefPtr<IDBAny> source, bool canBubble);
private:
RefPtr<IDBAny> m_source;
diff --git a/Source/WebCore/storage/IDBFactoryBackendImpl.cpp b/Source/WebCore/storage/IDBFactoryBackendImpl.cpp
index 45cffeb..0e883cf 100644
--- a/Source/WebCore/storage/IDBFactoryBackendImpl.cpp
+++ b/Source/WebCore/storage/IDBFactoryBackendImpl.cpp
@@ -49,7 +49,7 @@ IDBFactoryBackendImpl::IDBFactoryBackendImpl()
: m_transactionCoordinator(IDBTransactionCoordinator::create())
{
}
-
+
IDBFactoryBackendImpl::~IDBFactoryBackendImpl()
{
}
@@ -93,11 +93,24 @@ static PassRefPtr<IDBSQLiteDatabase> openSQLiteDatabase(SecurityOrigin* security
return sqliteDatabase.release();
}
+static bool runCommands(SQLiteDatabase& sqliteDatabase, const char** commands, size_t numberOfCommands)
+{
+ SQLiteTransaction transaction(sqliteDatabase, false);
+ transaction.begin();
+ for (size_t i = 0; i < numberOfCommands; ++i) {
+ if (!sqliteDatabase.executeCommand(commands[i])) {
+ LOG_ERROR("Failed to run the following command for IndexedDB: %s", commands[i]);
+ return false;
+ }
+ }
+ transaction.commit();
+ return true;
+}
+
static bool createTables(SQLiteDatabase& sqliteDatabase)
{
if (sqliteDatabase.tableExists("Databases"))
return true;
-
static const char* commands[] = {
"CREATE TABLE Databases (id INTEGER PRIMARY KEY, name TEXT NOT NULL, description TEXT NOT NULL, version TEXT NOT NULL)",
"CREATE UNIQUE INDEX Databases_name ON Databases(name)",
@@ -117,17 +130,7 @@ static bool createTables(SQLiteDatabase& sqliteDatabase)
"CREATE INDEX IndexData_indexId ON IndexData(indexId)",
};
- SQLiteTransaction transaction(sqliteDatabase, false);
- transaction.begin();
- for (size_t i = 0; i < arraysize(commands); ++i) {
- if (!sqliteDatabase.executeCommand(commands[i])) {
- // FIXME: We should try to recover from this situation. Maybe nuke the database and start over?
- LOG_ERROR("Failed to run the following command for IndexedDB: %s", commands[i]);
- return false;
- }
- }
- transaction.commit();
- return true;
+ return runCommands(sqliteDatabase, commands, sizeof(commands) / sizeof(commands[0]));
}
static bool createMetaDataTable(SQLiteDatabase& sqliteDatabase)
@@ -137,14 +140,7 @@ static bool createMetaDataTable(SQLiteDatabase& sqliteDatabase)
"INSERT INTO MetaData VALUES ('version', 1)",
};
- SQLiteTransaction transaction(sqliteDatabase, false);
- transaction.begin();
- for (size_t i = 0; i < arraysize(commands); ++i) {
- if (!sqliteDatabase.executeCommand(commands[i]))
- return false;
- }
- transaction.commit();
- return true;
+ return runCommands(sqliteDatabase, commands, sizeof(commands) / sizeof(commands[0]));
}
static bool getDatabaseVersion(SQLiteDatabase& sqliteDatabase, int* databaseVersion)
@@ -187,19 +183,27 @@ static bool migrateDatabase(SQLiteDatabase& sqliteDatabase)
"UPDATE MetaData SET value = 2 WHERE name = 'version'",
};
- SQLiteTransaction transaction(sqliteDatabase, false);
- transaction.begin();
- for (size_t i = 0; i < arraysize(commands); ++i) {
- if (!sqliteDatabase.executeCommand(commands[i])) {
- LOG_ERROR("Failed to run the following command for IndexedDB: %s", commands[i]);
- return false;
- }
- }
- transaction.commit();
+ if (!runCommands(sqliteDatabase, commands, sizeof(commands) / sizeof(commands[0])))
+ return false;
databaseVersion = 2;
}
+ if (databaseVersion == 2) {
+ // We need to make the ObjectStoreData.value be a BLOB instead of TEXT.
+ static const char* commands[] = {
+ "DROP TABLE IF EXISTS ObjectStoreData", // This drops associated indices.
+ "CREATE TABLE ObjectStoreData (id INTEGER PRIMARY KEY, objectStoreId INTEGER NOT NULL REFERENCES ObjectStore(id), keyString TEXT, keyDate REAL, keyNumber REAL, value BLOB NOT NULL)",
+ "CREATE UNIQUE INDEX ObjectStoreData_composit ON ObjectStoreData(keyString, keyDate, keyNumber, objectStoreId)",
+ "UPDATE MetaData SET value = 3 WHERE name = 'version'",
+ };
+
+ if (!runCommands(sqliteDatabase, commands, sizeof(commands) / sizeof(commands[0])))
+ return false;
+
+ databaseVersion = 3;
+ }
+
return true;
}
diff --git a/Source/WebCore/storage/IDBFactoryBackendInterface.cpp b/Source/WebCore/storage/IDBFactoryBackendInterface.cpp
index 935ccac..ac13652 100644
--- a/Source/WebCore/storage/IDBFactoryBackendInterface.cpp
+++ b/Source/WebCore/storage/IDBFactoryBackendInterface.cpp
@@ -43,10 +43,6 @@ PassRefPtr<IDBFactoryBackendInterface> IDBFactoryBackendInterface::create()
return IDBFactoryBackendImpl::create();
}
-IDBFactoryBackendInterface::~IDBFactoryBackendInterface()
-{
-}
-
} // namespace WebCore
#endif // ENABLE(INDEXED_DATABASE)
diff --git a/Source/WebCore/storage/IDBFactoryBackendInterface.h b/Source/WebCore/storage/IDBFactoryBackendInterface.h
index 166d517..e05f316 100644
--- a/Source/WebCore/storage/IDBFactoryBackendInterface.h
+++ b/Source/WebCore/storage/IDBFactoryBackendInterface.h
@@ -49,7 +49,7 @@ class SecurityOrigin;
class IDBFactoryBackendInterface : public ThreadSafeShared<IDBFactoryBackendInterface> {
public:
static PassRefPtr<IDBFactoryBackendInterface> create();
- virtual ~IDBFactoryBackendInterface();
+ virtual ~IDBFactoryBackendInterface() { }
virtual void open(const String& name, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir, int64_t maximumSize) = 0;
};
diff --git a/Source/WebCore/storage/IDBIndex.cpp b/Source/WebCore/storage/IDBIndex.cpp
index 8a38a27..615767b 100644
--- a/Source/WebCore/storage/IDBIndex.cpp
+++ b/Source/WebCore/storage/IDBIndex.cpp
@@ -34,13 +34,13 @@
#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)
{
@@ -52,13 +52,8 @@ IDBIndex::~IDBIndex()
{
}
-PassRefPtr<IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, const OptionsObject& options, ExceptionCode& ec)
+PassRefPtr<IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, unsigned short direction, ExceptionCode& ec)
{
- RefPtr<IDBKeyRange> keyRange = options.getKeyKeyRange("range");
-
- // Converted to an unsigned short.
- int32_t direction = defaultDirection;
- options.getKeyInt32("direction", direction);
if (direction != IDBCursor::NEXT && direction != IDBCursor::NEXT_NO_DUPLICATE && direction != IDBCursor::PREV && direction != IDBCursor::PREV_NO_DUPLICATE) {
// FIXME: May need to change when specced: http://www.w3.org/Bugs/Public/show_bug.cgi?id=11406
ec = IDBDatabaseException::CONSTRAINT_ERR;
@@ -66,19 +61,14 @@ PassRefPtr<IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, con
}
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;
}
-PassRefPtr<IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext* context, const OptionsObject& options, ExceptionCode& ec)
+PassRefPtr<IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, unsigned short direction, ExceptionCode& ec)
{
- RefPtr<IDBKeyRange> keyRange = options.getKeyKeyRange("range");
-
- // Converted to an unsigned short.
- int32_t direction = defaultDirection;
- options.getKeyInt32("direction", direction);
if (direction != IDBCursor::NEXT && direction != IDBCursor::NEXT_NO_DUPLICATE && direction != IDBCursor::PREV && direction != IDBCursor::PREV_NO_DUPLICATE) {
// FIXME: May need to change when specced: http://www.w3.org/Bugs/Public/show_bug.cgi?id=11406
ec = IDBDatabaseException::CONSTRAINT_ERR;
@@ -86,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;
@@ -95,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;
@@ -104,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;
diff --git a/Source/WebCore/storage/IDBIndex.h b/Source/WebCore/storage/IDBIndex.h
index 7f1aae3..10b46f1 100644
--- a/Source/WebCore/storage/IDBIndex.h
+++ b/Source/WebCore/storage/IDBIndex.h
@@ -30,7 +30,6 @@
#include "IDBIndexBackendInterface.h"
#include "IDBKeyRange.h"
#include "IDBRequest.h"
-#include "OptionsObject.h"
#include "PlatformString.h"
#include <wtf/Forward.h>
@@ -40,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));
}
@@ -53,19 +52,22 @@ public:
bool unique() const { return m_backend->unique(); }
// FIXME: Try to modify the code generator so this is unneeded.
- PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, ExceptionCode& ec) { return openCursor(context, OptionsObject(), ec); }
- PassRefPtr<IDBRequest> openKeyCursor(ScriptExecutionContext* context, ExceptionCode& ec) { return openKeyCursor(context, OptionsObject(), ec); }
+ PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, ExceptionCode& ec) { return openCursor(context, 0, ec); }
+ PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec) { return openCursor(context, keyRange, IDBCursor::NEXT, ec); }
+ PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, PassRefPtr<IDBKeyRange>, unsigned short direction, ExceptionCode&);
+
+ PassRefPtr<IDBRequest> openKeyCursor(ScriptExecutionContext* context, ExceptionCode& ec) { return openKeyCursor(context, 0, ec); }
+ PassRefPtr<IDBRequest> openKeyCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec) { return openKeyCursor(context, keyRange, IDBCursor::NEXT, ec); }
+ PassRefPtr<IDBRequest> openKeyCursor(ScriptExecutionContext*, PassRefPtr<IDBKeyRange>, unsigned short direction, ExceptionCode&);
- PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, const OptionsObject&, ExceptionCode&);
- PassRefPtr<IDBRequest> openKeyCursor(ScriptExecutionContext*, const OptionsObject&, ExceptionCode&);
PassRefPtr<IDBRequest> get(ScriptExecutionContext*, PassRefPtr<IDBKey>, ExceptionCode&);
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
diff --git a/Source/WebCore/storage/IDBIndex.idl b/Source/WebCore/storage/IDBIndex.idl
index e6ba1e6..13089cc 100644
--- a/Source/WebCore/storage/IDBIndex.idl
+++ b/Source/WebCore/storage/IDBIndex.idl
@@ -33,9 +33,9 @@ module storage {
readonly attribute DOMString keyPath;
readonly attribute boolean unique;
- [CallWith=ScriptExecutionContext] IDBRequest openCursor(in [Optional] OptionsObject options)
+ [CallWith=ScriptExecutionContext] IDBRequest openCursor(in [Optional] IDBKeyRange range, in [Optional] unsigned short direction)
raises (IDBDatabaseException);
- [CallWith=ScriptExecutionContext] IDBRequest openKeyCursor(in [Optional] OptionsObject options)
+ [CallWith=ScriptExecutionContext] IDBRequest openKeyCursor(in [Optional] IDBKeyRange range, in [Optional] unsigned short direction))
raises (IDBDatabaseException);
[CallWith=ScriptExecutionContext] IDBRequest get(in IDBKey key)
raises (IDBDatabaseException);
diff --git a/Source/WebCore/storage/IDBIndexBackendImpl.cpp b/Source/WebCore/storage/IDBIndexBackendImpl.cpp
index df88fdb..6eba189 100644
--- a/Source/WebCore/storage/IDBIndexBackendImpl.cpp
+++ b/Source/WebCore/storage/IDBIndexBackendImpl.cpp
@@ -100,7 +100,7 @@ void IDBIndexBackendImpl::openCursorInternal(ScriptExecutionContext*, PassRefPtr
query->bindInt64(indexColumn, index->id());
if (query->step() != SQLResultRow) {
- callbacks->onSuccess();
+ callbacks->onSuccess(SerializedScriptValue::nullValue());
return;
}
diff --git a/Source/WebCore/storage/IDBObjectStore.cpp b/Source/WebCore/storage/IDBObjectStore.cpp
index ed5c96a..53ae279 100644
--- a/Source/WebCore/storage/IDBObjectStore.cpp
+++ b/Source/WebCore/storage/IDBObjectStore.cpp
@@ -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, true, 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, false, 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,16 @@ 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;
+}
+
+PassRefPtr<IDBRequest> IDBObjectStore::clear(ScriptExecutionContext* context, ExceptionCode& ec)
+{
+ RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
+ m_objectStore->clear(request, m_transaction->backend(), ec);
if (ec)
return 0;
return request;
@@ -108,7 +117,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,16 +135,11 @@ 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, const OptionsObject& options, ExceptionCode& ec)
+PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> range, unsigned short direction, ExceptionCode& ec)
{
- RefPtr<IDBKeyRange> range = options.getKeyKeyRange("range");
-
- // Converted to an unsigned short.
- int32_t direction = defaultDirection;
- options.getKeyInt32("direction", direction);
if (direction != IDBCursor::NEXT && direction != IDBCursor::NEXT_NO_DUPLICATE && direction != IDBCursor::PREV && direction != IDBCursor::PREV_NO_DUPLICATE) {
// FIXME: May need to change when specced: http://www.w3.org/Bugs/Public/show_bug.cgi?id=11406
ec = IDBDatabaseException::CONSTRAINT_ERR;
@@ -143,7 +147,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();
diff --git a/Source/WebCore/storage/IDBObjectStore.h b/Source/WebCore/storage/IDBObjectStore.h
index 0e9a4a9..f0c5ebf 100644
--- a/Source/WebCore/storage/IDBObjectStore.h
+++ b/Source/WebCore/storage/IDBObjectStore.h
@@ -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));
}
@@ -63,25 +62,27 @@ public:
PassRefPtr<IDBRequest> add(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, ExceptionCode& ec) { return add(context, value, 0, ec); }
PassRefPtr<IDBRequest> put(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, ExceptionCode& ec) { return put(context, value, 0, ec); }
PassRefPtr<IDBIndex> createIndex(const String& name, const String& keyPath, ExceptionCode& ec) { return createIndex(name, keyPath, OptionsObject(), ec); }
- PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, ExceptionCode& ec) { return openCursor(context, OptionsObject(), ec); }
+ PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, ExceptionCode& ec) { return openCursor(context, 0, ec); }
+ PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec) { return openCursor(context, keyRange, IDBCursor::NEXT, ec); }
PassRefPtr<IDBRequest> get(ScriptExecutionContext*, PassRefPtr<IDBKey>, ExceptionCode&);
PassRefPtr<IDBRequest> add(ScriptExecutionContext*, PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, ExceptionCode&);
PassRefPtr<IDBRequest> put(ScriptExecutionContext*, PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, ExceptionCode&);
PassRefPtr<IDBRequest> deleteFunction(ScriptExecutionContext*, PassRefPtr<IDBKey> key, ExceptionCode&);
+ PassRefPtr<IDBRequest> clear(ScriptExecutionContext*, ExceptionCode&);
PassRefPtr<IDBIndex> createIndex(const String& name, const String& keyPath, const OptionsObject&, ExceptionCode&);
PassRefPtr<IDBIndex> index(const String& name, ExceptionCode&);
void deleteIndex(const String& name, ExceptionCode&);
- PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, const OptionsObject&, ExceptionCode&);
+ 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
diff --git a/Source/WebCore/storage/IDBObjectStore.idl b/Source/WebCore/storage/IDBObjectStore.idl
index f023dbe..c95fb9d 100644
--- a/Source/WebCore/storage/IDBObjectStore.idl
+++ b/Source/WebCore/storage/IDBObjectStore.idl
@@ -38,9 +38,11 @@ module storage {
raises (IDBDatabaseException);
[CallWith=ScriptExecutionContext, ImplementationFunction=deleteFunction] IDBRequest delete(in IDBKey key)
raises (IDBDatabaseException);
+ [CallWith=ScriptExecutionContext] IDBRequest clear()
+ raises (IDBDatabaseException);
[CallWith=ScriptExecutionContext] IDBRequest get(in IDBKey key)
raises (IDBDatabaseException);
- [CallWith=ScriptExecutionContext] IDBRequest openCursor(in [Optional] OptionsObject options)
+ [CallWith=ScriptExecutionContext] IDBRequest openCursor(in [Optional] IDBKeyRange range, in [Optional] unsigned short direction)
raises (IDBDatabaseException);
IDBIndex createIndex(in DOMString name, in [ConvertNullToNullString] DOMString keyPath, in [Optional] OptionsObject options)
raises (IDBDatabaseException);
diff --git a/Source/WebCore/storage/IDBObjectStoreBackendImpl.cpp b/Source/WebCore/storage/IDBObjectStoreBackendImpl.cpp
index 6b162ef..921bbab 100644
--- a/Source/WebCore/storage/IDBObjectStoreBackendImpl.cpp
+++ b/Source/WebCore/storage/IDBObjectStoreBackendImpl.cpp
@@ -118,7 +118,7 @@ void IDBObjectStoreBackendImpl::getInternal(ScriptExecutionContext*, PassRefPtr<
ASSERT((key->type() == IDBKey::DateType) != query.isColumnNull(1));
ASSERT((key->type() == IDBKey::NumberType) != query.isColumnNull(2));
- callbacks->onSuccess(SerializedScriptValue::createFromWire(query.getColumnText(3)));
+ callbacks->onSuccess(SerializedScriptValue::createFromWire(query.getColumnBlobAsString(3)));
ASSERT(query.step() != SQLResultRow);
}
@@ -142,7 +142,7 @@ static bool putObjectStoreData(SQLiteDatabase& db, IDBKey* key, SerializedScript
if (query.prepare() != SQLResultOk)
return false;
key->bindWithNulls(query, 1);
- query.bindText(4, value->toWireString());
+ query.bindBlob(4, value->toWireString());
if (dataRowId != IDBDatabaseBackendImpl::InvalidId)
query.bindInt64(5, dataRowId);
else
@@ -179,7 +179,7 @@ static bool putIndexData(SQLiteDatabase& db, IDBKey* key, int64_t indexId, int64
return putQuery.step() == SQLResultDone;
}
-void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, bool addOnly, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec)
+void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, PutMode putMode, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec)
{
if (transactionPtr->mode() == IDBTransaction::READ_ONLY) {
ec = IDBDatabaseException::READ_ONLY_ERR;
@@ -193,45 +193,75 @@ void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> prpValue,
RefPtr<IDBTransactionBackendInterface> transaction = transactionPtr;
// FIXME: This should throw a SERIAL_ERR on structured clone problems.
// FIXME: This should throw a DATA_ERR when the wrong key/keyPath data is supplied.
- if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::putInternal, objectStore, value, key, addOnly, callbacks, transaction)))
+ if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::putInternal, objectStore, value, key, putMode, callbacks, transaction)))
ec = IDBDatabaseException::NOT_ALLOWED_ERR;
}
-void IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, bool addOnly, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
+PassRefPtr<IDBKey> IDBObjectStoreBackendImpl::selectKeyForPut(IDBObjectStoreBackendImpl* objectStore, SerializedScriptValue* value, IDBKey* key, PutMode putMode, IDBCallbacks* callbacks)
{
- RefPtr<SerializedScriptValue> value = prpValue;
- RefPtr<IDBKey> key = prpKey;
+ if (putMode == CursorUpdate)
+ ASSERT(key);
- if (!objectStore->m_keyPath.isNull() && key) {
+ const bool autoIncrement = objectStore->autoIncrement();
+ const bool hasKeyPath = !objectStore->m_keyPath.isNull();
+
+ if (hasKeyPath && key && putMode != CursorUpdate) {
callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "A key was supplied for an objectStore that has a keyPath."));
- return;
+ return 0;
}
- if (objectStore->autoIncrement() && key) {
- callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "A key was supplied for an objectStore that is using auto increment."));
- return;
+ if (autoIncrement && key) {
+ objectStore->resetAutoIncrementKeyCache();
+ return key;
}
- if (objectStore->autoIncrement()) {
- key = objectStore->genAutoIncrementKey();
+ if (autoIncrement) {
+ ASSERT(!key);
+ if (!hasKeyPath)
+ return objectStore->genAutoIncrementKey();
- if (!objectStore->m_keyPath.isNull()) {
- // FIXME: Inject the generated key into the object.
- callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Adding data to object stores with auto increment and in-line keys not yet supported."));
- return;
+ RefPtr<IDBKey> keyPathKey = fetchKeyFromKeyPath(value, objectStore->m_keyPath);
+ if (keyPathKey) {
+ objectStore->resetAutoIncrementKeyCache();
+ return keyPathKey;
}
- } else if (!objectStore->m_keyPath.isNull()) {
- key = fetchKeyFromKeyPath(value.get(), objectStore->m_keyPath);
- if (!key) {
+ // FIXME: Generate auto increment key, and inject it through the key path.
+ callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Adding data to object stores with auto increment and in-line keys not yet supported."));
+ return 0;
+ }
+
+ if (hasKeyPath) {
+ RefPtr<IDBKey> keyPathKey = fetchKeyFromKeyPath(value, objectStore->m_keyPath);
+
+ if (!keyPathKey) {
callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "The key could not be fetched from the keyPath."));
- return;
+ return 0;
}
- } else if (!key) {
- callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "No key supplied."));
- return;
+
+ if (putMode == CursorUpdate && !keyPathKey->isEqual(key)) {
+ callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "The key fetched from the keyPath does not match the key of the cursor."));
+ return 0;
+ }
+
+ return keyPathKey.release();
+ }
+
+ if (!key) {
+ callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "No key supplied"));
+ return 0;
}
+ return key;
+}
+
+void IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, PutMode putMode, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
+{
+ RefPtr<SerializedScriptValue> value = prpValue;
+ RefPtr<IDBKey> key = selectKeyForPut(objectStore.get(), value.get(), prpKey.get(), putMode, callbacks.get());
+ if (!key)
+ return;
+
if (key->type() == IDBKey::NullType) {
callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "NULL key is not allowed."));
return;
@@ -261,7 +291,7 @@ void IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr<
bindWhereClause(getQuery, objectStore->id(), key.get());
bool isExistingValue = getQuery.step() == SQLResultRow;
- if (addOnly && isExistingValue) {
+ if (putMode == AddOnly && isExistingValue) {
callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "Key already exists in the object store."));
return;
}
@@ -342,7 +372,39 @@ void IDBObjectStoreBackendImpl::deleteInternal(ScriptExecutionContext*, PassRefP
ok = indexQuery.step() == SQLResultDone;
ASSERT_UNUSED(ok, ok);
- callbacks->onSuccess();
+ callbacks->onSuccess(SerializedScriptValue::nullValue());
+}
+
+void IDBObjectStoreBackendImpl::clear(PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
+{
+ if (transaction->mode() == IDBTransaction::READ_ONLY) {
+ ec = IDBDatabaseException::READ_ONLY_ERR;
+ return;
+ }
+
+ RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
+ RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+
+ if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::clearInternal, objectStore, callbacks)))
+ ec = IDBDatabaseException::NOT_ALLOWED_ERR;
+}
+
+static void doDelete(SQLiteDatabase& db, const char* sql, int64_t id)
+{
+ SQLiteStatement deleteQuery(db, sql);
+ bool ok = deleteQuery.prepare() == SQLResultOk;
+ ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
+ deleteQuery.bindInt64(1, id);
+ ok = deleteQuery.step() == SQLResultDone;
+ ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
+}
+
+void IDBObjectStoreBackendImpl::clearInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBCallbacks> callbacks)
+{
+ doDelete(objectStore->sqliteDatabase(), "DELETE FROM IndexData WHERE objectStoreDataId IN (SELECT id FROM ObjectStoreData WHERE objectStoreId = ?)", objectStore->id());
+ doDelete(objectStore->sqliteDatabase(), "DELETE FROM ObjectStoreData WHERE objectStoreId = ?", objectStore->id());
+
+ callbacks->onSuccess(SerializedScriptValue::undefinedValue());
}
PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::createIndex(const String& name, const String& keyPath, bool unique, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
@@ -401,16 +463,6 @@ PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::index(const Stri
return index.release();
}
-static void doDelete(SQLiteDatabase& db, const char* sql, int64_t id)
-{
- SQLiteStatement deleteQuery(db, sql);
- bool ok = deleteQuery.prepare() == SQLResultOk;
- ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
- deleteQuery.bindInt64(1, id);
- ok = deleteQuery.step() == SQLResultDone;
- ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
-}
-
void IDBObjectStoreBackendImpl::deleteIndex(const String& name, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
{
if (transaction->mode() != IDBTransaction::VERSION_CHANGE) {
@@ -483,7 +535,7 @@ void IDBObjectStoreBackendImpl::openCursorInternal(ScriptExecutionContext*, Pass
query->bindInt64(currentColumn, objectStore->id());
if (query->step() != SQLResultRow) {
- callbacks->onSuccess();
+ callbacks->onSuccess(SerializedScriptValue::nullValue());
return;
}
diff --git a/Source/WebCore/storage/IDBObjectStoreBackendImpl.h b/Source/WebCore/storage/IDBObjectStoreBackendImpl.h
index 9fb1b7c..b54f9fd 100644
--- a/Source/WebCore/storage/IDBObjectStoreBackendImpl.h
+++ b/Source/WebCore/storage/IDBObjectStoreBackendImpl.h
@@ -67,8 +67,9 @@ public:
virtual bool autoIncrement() const { return m_autoIncrement; }
virtual void get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&);
- virtual void put(PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, bool addOnly, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&);
+ virtual void put(PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, PutMode, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&);
virtual void deleteFunction(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&);
+ virtual void clear(PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&);
virtual PassRefPtr<IDBIndexBackendInterface> createIndex(const String& name, const String& keyPath, bool unique, IDBTransactionBackendInterface*, ExceptionCode&);
virtual PassRefPtr<IDBIndexBackendInterface> index(const String& name, ExceptionCode&);
@@ -83,10 +84,13 @@ private:
void loadIndexes();
SQLiteDatabase& sqliteDatabase() const;
PassRefPtr<IDBKey> genAutoIncrementKey();
+ void resetAutoIncrementKeyCache() { m_autoIncrementNumber = -1; }
+ static PassRefPtr<IDBKey> selectKeyForPut(IDBObjectStoreBackendImpl*, SerializedScriptValue*, IDBKey*, PutMode, IDBCallbacks*);
static void getInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>);
- static void putInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, bool addOnly, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendInterface>);
+ static void putInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, PutMode, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendInterface>);
static void deleteInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>);
+ static void clearInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBCallbacks>);
static void createIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBIndexBackendImpl>, PassRefPtr<IDBTransactionBackendInterface>);
static void deleteIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBIndexBackendImpl>, PassRefPtr<IDBTransactionBackendInterface>);
static void openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKeyRange> range, unsigned short direction, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendInterface>);
diff --git a/Source/WebCore/storage/IDBObjectStoreBackendInterface.h b/Source/WebCore/storage/IDBObjectStoreBackendInterface.h
index 02ceb27..177701c 100644
--- a/Source/WebCore/storage/IDBObjectStoreBackendInterface.h
+++ b/Source/WebCore/storage/IDBObjectStoreBackendInterface.h
@@ -51,9 +51,17 @@ public:
virtual PassRefPtr<DOMStringList> indexNames() const = 0;
virtual void get(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&) = 0;
- virtual void put(PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, bool addOnly, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&) = 0;
+
+ enum PutMode {
+ AddOrUpdate,
+ AddOnly,
+ CursorUpdate
+ };
+ virtual void put(PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, PutMode, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&) = 0;
virtual void deleteFunction(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&) = 0;
+ virtual void clear(PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&) = 0;
+
virtual PassRefPtr<IDBIndexBackendInterface> createIndex(const String& name, const String& keyPath, bool unique, IDBTransactionBackendInterface*, ExceptionCode&) = 0;
virtual PassRefPtr<IDBIndexBackendInterface> index(const String& name, ExceptionCode&) = 0;
virtual void deleteIndex(const String& name, IDBTransactionBackendInterface*, ExceptionCode&) = 0;
@@ -66,4 +74,3 @@ public:
#endif
#endif // IDBObjectStoreBackendInterface_h
-
diff --git a/Source/WebCore/storage/IDBRequest.cpp b/Source/WebCore/storage/IDBRequest.cpp
index cbd635c..e7498ec 100644
--- a/Source/WebCore/storage/IDBRequest.cpp
+++ b/Source/WebCore/storage/IDBRequest.cpp
@@ -31,10 +31,11 @@
#if ENABLE(INDEXED_DATABASE)
-#include "Event.h"
+#include "Document.h"
#include "EventException.h"
#include "EventListener.h"
#include "EventNames.h"
+#include "EventQueue.h"
#include "IDBCursor.h"
#include "IDBDatabase.h"
#include "IDBIndex.h"
@@ -42,163 +43,169 @@
#include "IDBObjectStore.h"
#include "IDBPendingTransactionMonitor.h"
#include "IDBSuccessEvent.h"
-#include "ScriptExecutionContext.h"
namespace WebCore {
-IDBRequest::IDBRequest(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, IDBTransaction* transaction)
: ActiveDOMObject(context, this)
, m_source(source)
, m_transaction(transaction)
- , m_timer(this, &IDBRequest::timerFired)
, m_readyState(LOADING)
+ , m_finished(false)
{
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(m_readyState == DONE);
- m_readyState = LOADING;
- ASSERT(!m_transaction);
+ ASSERT(!m_finished);
+ ASSERT(scriptExecutionContext());
+ if (m_readyState != DONE)
+ return false;
+
m_transaction = transaction;
- IDBPendingTransactionMonitor::removePendingTransaction(m_transaction.get());
+ m_readyState = LOADING;
+
+ IDBPendingTransactionMonitor::removePendingTransaction(m_transaction->backend());
+
return true;
}
void IDBRequest::onError(PassRefPtr<IDBDatabaseError> error)
{
- scheduleEvent(0, error);
-}
-
-void IDBRequest::onSuccess()
-{
- scheduleEvent(IDBAny::createNull(), 0);
+ enqueueEvent(IDBErrorEvent::create(m_source, *error));
}
void IDBRequest::onSuccess(PassRefPtr<IDBCursorBackendInterface> backend)
{
- scheduleEvent(IDBAny::create(IDBCursor::create(backend, this, m_transaction.get())), 0);
+ enqueueEvent(IDBSuccessEvent::create(m_source, IDBAny::create(IDBCursor::create(backend, this, m_transaction.get()))));
}
void IDBRequest::onSuccess(PassRefPtr<IDBDatabaseBackendInterface> backend)
{
- scheduleEvent(IDBAny::create(IDBDatabase::create(backend)), 0);
+ enqueueEvent(IDBSuccessEvent::create(m_source, IDBAny::create(IDBDatabase::create(scriptExecutionContext(), backend))));
}
void IDBRequest::onSuccess(PassRefPtr<IDBIndexBackendInterface> backend)
{
- scheduleEvent(IDBAny::create(IDBIndex::create(backend, m_transaction.get())), 0);
+ ASSERT_NOT_REACHED(); // FIXME: This method should go away.
}
void IDBRequest::onSuccess(PassRefPtr<IDBKey> idbKey)
{
- scheduleEvent(IDBAny::create(idbKey), 0);
+ enqueueEvent(IDBSuccessEvent::create(m_source, IDBAny::create(idbKey)));
}
void IDBRequest::onSuccess(PassRefPtr<IDBObjectStoreBackendInterface> backend)
{
- // FIXME: This function should go away once createObjectStore is sync.
- scheduleEvent(IDBAny::create(IDBObjectStore::create(backend, m_transaction.get())), 0);
+ ASSERT_NOT_REACHED(); // FIXME: This method should go away.
}
void IDBRequest::onSuccess(PassRefPtr<IDBTransactionBackendInterface> prpBackend)
{
+ if (!scriptExecutionContext())
+ 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());
- scheduleEvent(IDBAny::create(frontend.release()), 0);
-}
+ m_transaction = frontend;
-void IDBRequest::onSuccess(PassRefPtr<SerializedScriptValue> serializedScriptValue)
-{
- scheduleEvent(IDBAny::create(serializedScriptValue), 0);
-}
+ ASSERT(m_source->type() == IDBAny::IDBDatabaseType);
+ m_source->idbDatabase()->setSetVersionTransaction(frontend.get());
-ScriptExecutionContext* IDBRequest::scriptExecutionContext() const
-{
- return ActiveDOMObject::scriptExecutionContext();
+ IDBPendingTransactionMonitor::removePendingTransaction(m_transaction->backend());
+ enqueueEvent(IDBSuccessEvent::create(m_source, IDBAny::create(frontend.release())));
}
-bool IDBRequest::canSuspend() const
+void IDBRequest::onSuccess(PassRefPtr<SerializedScriptValue> serializedScriptValue)
{
- // IDBTransactions cannot be suspended at the moment. We therefore
- // disallow the back/forward cache for pages that use IndexedDatabase.
- return false;
+ enqueueEvent(IDBSuccessEvent::create(m_source, IDBAny::create(serializedScriptValue)));
}
-EventTargetData* IDBRequest::eventTargetData()
+bool IDBRequest::hasPendingActivity() const
{
- return &m_eventTargetData;
+ // FIXME: In an ideal world, we should return true as long as anyone has a or can
+ // get a handle to us and we have event listeners. This is order to handle
+ // user generated events properly.
+ return !m_finished || ActiveDOMObject::hasPendingActivity();
}
-EventTargetData* IDBRequest::ensureEventTargetData()
+ScriptExecutionContext* IDBRequest::scriptExecutionContext() const
{
- return &m_eventTargetData;
+ return ActiveDOMObject::scriptExecutionContext();
}
-void IDBRequest::timerFired(Timer<IDBRequest>*)
+bool IDBRequest::dispatchEvent(PassRefPtr<Event> event)
{
- ASSERT(m_selfRef);
- ASSERT(m_pendingEvents.size());
- // FIXME: We should handle the stop event and stop any timers when we see it. We can then assert here that scriptExecutionContext is non-null.
-
- // We need to keep self-referencing ourself, otherwise it's possible we'll be deleted.
- // But in some cases, suspend() could be called while we're dispatching an event, so we
- // need to make sure that resume() doesn't re-start the timer based on m_selfRef being set.
- RefPtr<IDBRequest> selfRef = m_selfRef.release();
-
- // readyStateReset can be called synchronously while we're dispatching the event.
- RefPtr<IDBTransactionBackendInterface> transaction = m_transaction;
- m_transaction.clear();
-
- Vector<PendingEvent> pendingEvents;
- pendingEvents.swap(m_pendingEvents);
- for (size_t i = 0; i < pendingEvents.size(); ++i) {
- // It's possible we've navigated in which case we'll crash.
- if (!scriptExecutionContext())
- return;
+ ASSERT(!m_finished);
+ ASSERT(scriptExecutionContext());
+ ASSERT(event->target() == this);
+ ASSERT(m_readyState < DONE);
+ m_readyState = DONE;
- if (pendingEvents[i].m_error) {
- ASSERT(!pendingEvents[i].m_result);
- dispatchEvent(IDBErrorEvent::create(m_source, *pendingEvents[i].m_error));
- } else {
- ASSERT(pendingEvents[i].m_result->type() != IDBAny::UndefinedType);
- dispatchEvent(IDBSuccessEvent::create(m_source, pendingEvents[i].m_result));
- }
+ Vector<RefPtr<EventTarget> > targets;
+ targets.append(this);
+ if (m_transaction) {
+ targets.append(m_transaction);
+ // If there ever are events that are associated with a database but
+ // that do not have a transaction, then this will not work and we need
+ // this object to actually hold a reference to the database (to ensure
+ // it stays alive).
+ targets.append(m_transaction->db());
}
- if (transaction) {
- // Now that we processed all pending events, let the transaction monitor check if
- // it can commit the current transaction or if there's anything new pending.
- // FIXME: Handle the workers case.
- transaction->didCompleteTaskEvents();
+
+ ASSERT(event->isIDBErrorEvent() || event->isIDBSuccessEvent());
+ bool dontPreventDefault = static_cast<IDBEvent*>(event.get())->dispatch(targets);
+
+ // If the event's result was of type IDBCursor, then it's possible for us to
+ // fire again (unless the transaction completes).
+ if (event->isIDBSuccessEvent()) {
+ RefPtr<IDBAny> any = static_cast<IDBSuccessEvent*>(event.get())->result();
+ if (any->type() != IDBAny::IDBCursorType)
+ m_finished = true;
+ } else
+ m_finished = true;
+
+ if (m_transaction) {
+ if (dontPreventDefault && event->isIDBErrorEvent())
+ m_transaction->backend()->abort();
+ m_transaction->backend()->didCompleteTaskEvents();
}
+ return dontPreventDefault;
}
-void IDBRequest::scheduleEvent(PassRefPtr<IDBAny> result, PassRefPtr<IDBDatabaseError> error)
+void IDBRequest::enqueueEvent(PassRefPtr<Event> event)
{
+ ASSERT(!m_finished);
ASSERT(m_readyState < DONE);
- ASSERT(!!m_selfRef == m_timer.isActive());
+ if (!scriptExecutionContext())
+ return;
- PendingEvent pendingEvent;
- pendingEvent.m_result = result;
- pendingEvent.m_error = error;
- m_pendingEvents.append(pendingEvent);
+ ASSERT(scriptExecutionContext()->isDocument());
+ EventQueue* eventQueue = static_cast<Document*>(scriptExecutionContext())->eventQueue();
+ event->setTarget(this);
+ eventQueue->enqueueEvent(event);
+}
- m_readyState = DONE;
- if (!m_timer.isActive()) {
- m_selfRef = this;
- m_timer.startOneShot(0);
- }
+EventTargetData* IDBRequest::eventTargetData()
+{
+ return &m_eventTargetData;
+}
+
+EventTargetData* IDBRequest::ensureEventTargetData()
+{
+ return &m_eventTargetData;
}
} // namespace WebCore
diff --git a/Source/WebCore/storage/IDBRequest.h b/Source/WebCore/storage/IDBRequest.h
index fa68208..5c31318 100644
--- a/Source/WebCore/storage/IDBRequest.h
+++ b/Source/WebCore/storage/IDBRequest.h
@@ -32,21 +32,21 @@
#if ENABLE(INDEXED_DATABASE)
#include "ActiveDOMObject.h"
+#include "Event.h"
#include "EventListener.h"
#include "EventNames.h"
#include "EventTarget.h"
#include "IDBAny.h"
#include "IDBCallbacks.h"
-#include "Timer.h"
-#include <wtf/Vector.h>
namespace WebCore {
-class IDBTransactionBackendInterface;
+class IDBEvent;
+class IDBTransaction;
class IDBRequest : public IDBCallbacks, public EventTarget, public ActiveDOMObject {
public:
- static PassRefPtr<IDBRequest> create(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransactionBackendInterface* transaction) { return adoptRef(new IDBRequest(context, source, transaction)); }
+ static PassRefPtr<IDBRequest> create(ScriptExecutionContext*, PassRefPtr<IDBAny> source, IDBTransaction*);
virtual ~IDBRequest();
// Defined in the IDL
@@ -58,11 +58,10 @@ public:
DEFINE_ATTRIBUTE_EVENT_LISTENER(success);
DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
- bool resetReadyState(IDBTransactionBackendInterface*);
+ bool resetReadyState(IDBTransaction*);
// IDBCallbacks
virtual void onError(PassRefPtr<IDBDatabaseError>);
- virtual void onSuccess(); // For "null".
virtual void onSuccess(PassRefPtr<IDBDatabaseBackendInterface>);
virtual void onSuccess(PassRefPtr<IDBCursorBackendInterface>);
virtual void onSuccess(PassRefPtr<IDBIndexBackendInterface>);
@@ -71,21 +70,22 @@ public:
virtual void onSuccess(PassRefPtr<IDBTransactionBackendInterface>);
virtual void onSuccess(PassRefPtr<SerializedScriptValue>);
+ // ActiveDOMObject
+ virtual bool hasPendingActivity() const;
+
// EventTarget
virtual IDBRequest* toIDBRequest() { return this; }
-
- // ActiveDOMObject
virtual ScriptExecutionContext* scriptExecutionContext() const;
- virtual bool canSuspend() const;
+ virtual bool dispatchEvent(PassRefPtr<Event>);
+ bool dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec) { return EventTarget::dispatchEvent(event, ec); }
using ThreadSafeShared<IDBCallbacks>::ref;
using ThreadSafeShared<IDBCallbacks>::deref;
private:
- IDBRequest(ScriptExecutionContext*, PassRefPtr<IDBAny> source, IDBTransactionBackendInterface* transaction);
+ IDBRequest(ScriptExecutionContext*, PassRefPtr<IDBAny> source, IDBTransaction*);
- void timerFired(Timer<IDBRequest>*);
- void scheduleEvent(PassRefPtr<IDBAny> result, PassRefPtr<IDBDatabaseError>);
+ void enqueueEvent(PassRefPtr<Event>);
// EventTarget
virtual void refEventTarget() { ref(); }
@@ -94,19 +94,11 @@ private:
virtual EventTargetData* ensureEventTargetData();
RefPtr<IDBAny> m_source;
- RefPtr<IDBTransactionBackendInterface> m_transaction;
-
- struct PendingEvent {
- RefPtr<IDBAny> m_result;
- RefPtr<IDBDatabaseError> m_error;
- };
- Vector<PendingEvent> m_pendingEvents;
-
- // Used to fire events asynchronously.
- Timer<IDBRequest> m_timer;
- RefPtr<IDBRequest> m_selfRef; // This is set to us iff there's an event pending.
+ RefPtr<IDBTransaction> m_transaction;
ReadyState m_readyState;
+ bool m_finished; // Is it possible that we'll fire any more events? If not, we're finished.
+
EventTargetData m_eventTargetData;
};
diff --git a/Source/WebCore/storage/IDBSuccessEvent.cpp b/Source/WebCore/storage/IDBSuccessEvent.cpp
index 2dcd964..110b78b 100644
--- a/Source/WebCore/storage/IDBSuccessEvent.cpp
+++ b/Source/WebCore/storage/IDBSuccessEvent.cpp
@@ -42,7 +42,7 @@ PassRefPtr<IDBSuccessEvent> IDBSuccessEvent::create(PassRefPtr<IDBAny> source, P
}
IDBSuccessEvent::IDBSuccessEvent(PassRefPtr<IDBAny> source, PassRefPtr<IDBAny> result)
- : IDBEvent(eventNames().successEvent, source)
+ : IDBEvent(eventNames().successEvent, source, false)
, m_result(result)
{
}
diff --git a/Source/WebCore/storage/IDBTimeoutEvent.cpp b/Source/WebCore/storage/IDBTimeoutEvent.cpp
deleted file mode 100644
index b61ee47..0000000
--- a/Source/WebCore/storage/IDBTimeoutEvent.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 "IDBTimeoutEvent.h"
-
-#if ENABLE(INDEXED_DATABASE)
-
-#include "EventNames.h"
-#include "IDBAny.h"
-
-namespace WebCore {
-
-PassRefPtr<IDBTimeoutEvent> IDBTimeoutEvent::create()
-{
- return adoptRef(new IDBTimeoutEvent());
-}
-
-IDBTimeoutEvent::IDBTimeoutEvent()
- : IDBEvent(eventNames().abortEvent, 0) // FIXME: set the source to the transaction
-{
-}
-
-IDBTimeoutEvent::~IDBTimeoutEvent()
-{
-}
-
-} // namespace WebCore
-
-#endif
diff --git a/Source/WebCore/storage/IDBTimeoutEvent.h b/Source/WebCore/storage/IDBTimeoutEvent.h
deleted file mode 100644
index afc9ba4..0000000
--- a/Source/WebCore/storage/IDBTimeoutEvent.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 IDBTimeoutEvent_h
-#define IDBTimeoutEvent_h
-
-#if ENABLE(INDEXED_DATABASE)
-
-#include "IDBEvent.h"
-#include "PlatformString.h"
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefPtr.h>
-
-namespace WebCore {
-
-class IDBTimeoutEvent : public IDBEvent {
-public:
- static PassRefPtr<IDBTimeoutEvent> create();
- // FIXME: Need to allow creation of these events from JS.
- virtual ~IDBTimeoutEvent();
-
- virtual bool isIDBTimeoutEvent() const { return true; }
-
-private:
- IDBTimeoutEvent();
-};
-
-} // namespace WebCore
-
-#endif // ENABLE(INDEXED_DATABASE)
-
-#endif // IDBTimeoutEvent_h
diff --git a/Source/WebCore/storage/IDBTransaction.cpp b/Source/WebCore/storage/IDBTransaction.cpp
index e3625d4..1f696b3 100644
--- a/Source/WebCore/storage/IDBTransaction.cpp
+++ b/Source/WebCore/storage/IDBTransaction.cpp
@@ -28,8 +28,9 @@
#if ENABLE(INDEXED_DATABASE)
-#include "Event.h"
+#include "Document.h"
#include "EventException.h"
+#include "EventQueue.h"
#include "IDBAbortEvent.h"
#include "IDBCompleteEvent.h"
#include "IDBDatabase.h"
@@ -38,20 +39,22 @@
#include "IDBObjectStore.h"
#include "IDBObjectStoreBackendInterface.h"
#include "IDBPendingTransactionMonitor.h"
-#include "IDBTimeoutEvent.h"
-#include "ScriptExecutionContext.h"
namespace WebCore {
+PassRefPtr<IDBTransaction> IDBTransaction::create(ScriptExecutionContext* context, PassRefPtr<IDBTransactionBackendInterface> backend, IDBDatabase* db)
+{
+ return adoptRef(new IDBTransaction(context, backend, db));
+}
+
IDBTransaction::IDBTransaction(ScriptExecutionContext* context, PassRefPtr<IDBTransactionBackendInterface> backend, IDBDatabase* db)
: ActiveDOMObject(context, this)
, m_backend(backend)
, m_database(db)
, m_mode(m_backend->mode())
- , m_onAbortTimer(this, &IDBTransaction::onAbortTimerFired)
- , m_onCompleteTimer(this, &IDBTransaction::onCompleteTimerFired)
- , m_onTimeoutTimer(this, &IDBTransaction::onTimeoutTimerFired)
+ , m_finished(false)
{
+ ASSERT(m_backend);
IDBPendingTransactionMonitor::addPendingTransaction(m_backend.get());
}
@@ -59,19 +62,29 @@ IDBTransaction::~IDBTransaction()
{
}
+IDBTransactionBackendInterface* IDBTransaction::backend() const
+{
+ return m_backend.get();
+}
+
+bool IDBTransaction::finished() const
+{
+ return m_finished;
+}
+
unsigned short IDBTransaction::mode() const
{
return m_mode;
}
-IDBDatabase* IDBTransaction::db()
+IDBDatabase* IDBTransaction::db() const
{
return m_database.get();
}
PassRefPtr<IDBObjectStore> IDBTransaction::objectStore(const String& name, ExceptionCode& ec)
{
- if (!m_backend) {
+ if (m_finished) {
ec = IDBDatabaseException::NOT_ALLOWED_ERR;
return 0;
}
@@ -80,94 +93,96 @@ 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();
}
void IDBTransaction::abort()
{
+ RefPtr<IDBTransaction> selfRef = this;
if (m_backend)
m_backend->abort();
}
-ScriptExecutionContext* IDBTransaction::scriptExecutionContext() const
-{
- return ActiveDOMObject::scriptExecutionContext();
-}
-
void IDBTransaction::onAbort()
{
- ASSERT(!m_onAbortTimer.isActive());
- ASSERT(!m_onCompleteTimer.isActive());
- ASSERT(!m_onTimeoutTimer.isActive());
- m_selfRef = this;
- m_onAbortTimer.startOneShot(0);
- m_backend.clear(); // Release the backend as it holds a (circular) reference back to us.
+ enqueueEvent(IDBAbortEvent::create(IDBAny::create(this)));
}
void IDBTransaction::onComplete()
{
- ASSERT(!m_onAbortTimer.isActive());
- ASSERT(!m_onCompleteTimer.isActive());
- ASSERT(!m_onTimeoutTimer.isActive());
- m_selfRef = this;
- m_onCompleteTimer.startOneShot(0);
- m_backend.clear(); // Release the backend as it holds a (circular) reference back to us.
+ enqueueEvent(IDBCompleteEvent::create(IDBAny::create(this)));
}
-void IDBTransaction::onTimeout()
+bool IDBTransaction::hasPendingActivity() const
{
- ASSERT(!m_onAbortTimer.isActive());
- ASSERT(!m_onCompleteTimer.isActive());
- ASSERT(!m_onTimeoutTimer.isActive());
- m_selfRef = this;
- m_onTimeoutTimer.startOneShot(0);
- m_backend.clear(); // Release the backend as it holds a (circular) reference back to us.
+ // FIXME: In an ideal world, we should return true as long as anyone has a or can
+ // get a handle to us or any child request object and any of those have
+ // event listeners. This is in order to handle user generated events properly.
+ return !m_finished || ActiveDOMObject::hasPendingActivity();
}
-bool IDBTransaction::canSuspend() const
+ScriptExecutionContext* IDBTransaction::scriptExecutionContext() const
{
- // We may be in the middle of a transaction so we cannot suspend our object.
- // Instead, we simply don't allow the owner page to go into the back/forward cache.
- return false;
+ return ActiveDOMObject::scriptExecutionContext();
}
-void IDBTransaction::stop()
+bool IDBTransaction::dispatchEvent(PassRefPtr<Event> event)
{
- if (m_backend)
- m_backend->abort();
+ ASSERT(!m_finished);
+ ASSERT(scriptExecutionContext());
+ ASSERT(event->target() == this);
+ ASSERT(!m_finished);
+ m_finished = true;
+
+ Vector<RefPtr<EventTarget> > targets;
+ targets.append(this);
+ targets.append(db());
+
+ ASSERT(event->isIDBAbortEvent() || event->isIDBCompleteEvent());
+ return static_cast<IDBEvent*>(event.get())->dispatch(targets);
}
-EventTargetData* IDBTransaction::eventTargetData()
+bool IDBTransaction::canSuspend() const
{
- return &m_eventTargetData;
+ // FIXME: Technically we can suspend before the first request is schedule
+ // and after the complete/abort event is enqueued.
+ return m_finished;
}
-EventTargetData* IDBTransaction::ensureEventTargetData()
+void IDBTransaction::contextDestroyed()
{
- return &m_eventTargetData;
+ ActiveDOMObject::contextDestroyed();
+
+ // Must happen in contextDestroyed since it can result in ActiveDOMObjects being destructed
+ // (and contextDestroyed is the only one resilient against this).
+ RefPtr<IDBTransaction> selfRef = this;
+ if (m_backend)
+ m_backend->abort();
+
+ m_finished = true;
}
-void IDBTransaction::onAbortTimerFired(Timer<IDBTransaction>* transaction)
+void IDBTransaction::enqueueEvent(PassRefPtr<Event> event)
{
- ASSERT(m_selfRef);
- RefPtr<IDBTransaction> selfRef = m_selfRef.release();
- dispatchEvent(IDBAbortEvent::create());
+ ASSERT(!m_finished);
+ if (!scriptExecutionContext())
+ return;
+
+ ASSERT(scriptExecutionContext()->isDocument());
+ EventQueue* eventQueue = static_cast<Document*>(scriptExecutionContext())->eventQueue();
+ event->setTarget(this);
+ eventQueue->enqueueEvent(event);
}
-void IDBTransaction::onCompleteTimerFired(Timer<IDBTransaction>* transaction)
+EventTargetData* IDBTransaction::eventTargetData()
{
- ASSERT(m_selfRef);
- RefPtr<IDBTransaction> selfRef = m_selfRef.release();
- dispatchEvent(IDBCompleteEvent::create());
+ return &m_eventTargetData;
}
-
-void IDBTransaction::onTimeoutTimerFired(Timer<IDBTransaction>* transaction)
+EventTargetData* IDBTransaction::ensureEventTargetData()
{
- ASSERT(m_selfRef);
- RefPtr<IDBTransaction> selfRef = m_selfRef.release();
- dispatchEvent(IDBTimeoutEvent::create());
+ return &m_eventTargetData;
}
}
diff --git a/Source/WebCore/storage/IDBTransaction.h b/Source/WebCore/storage/IDBTransaction.h
index d0a9f0f..ff4feb6 100644
--- a/Source/WebCore/storage/IDBTransaction.h
+++ b/Source/WebCore/storage/IDBTransaction.h
@@ -30,12 +30,12 @@
#include "ActiveDOMObject.h"
#include "DOMStringList.h"
+#include "Event.h"
#include "EventListener.h"
#include "EventNames.h"
#include "EventTarget.h"
#include "IDBTransactionBackendInterface.h"
#include "IDBTransactionCallbacks.h"
-#include "Timer.h"
#include <wtf/RefCounted.h>
namespace WebCore {
@@ -45,10 +45,7 @@ class IDBObjectStore;
class IDBTransaction : public IDBTransactionCallbacks, public EventTarget, public ActiveDOMObject {
public:
- static PassRefPtr<IDBTransaction> create(ScriptExecutionContext* context, PassRefPtr<IDBTransactionBackendInterface> backend, IDBDatabase* db)
- {
- return adoptRef(new IDBTransaction(context, backend, db));
- }
+ static PassRefPtr<IDBTransaction> create(ScriptExecutionContext*, PassRefPtr<IDBTransactionBackendInterface>, IDBDatabase*);
virtual ~IDBTransaction();
enum Mode {
@@ -57,27 +54,32 @@ public:
VERSION_CHANGE = 2
};
+ IDBTransactionBackendInterface* backend() const;
+ bool finished() const;
+
unsigned short mode() const;
- IDBDatabase* db();
+ IDBDatabase* db() const;
PassRefPtr<IDBObjectStore> objectStore(const String& name, ExceptionCode&);
void abort();
DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
DEFINE_ATTRIBUTE_EVENT_LISTENER(complete);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(timeout);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
// IDBTransactionCallbacks
virtual void onAbort();
virtual void onComplete();
- virtual void onTimeout();
// EventTarget
virtual IDBTransaction* toIDBTransaction() { return this; }
+ virtual ScriptExecutionContext* scriptExecutionContext() const;
+ virtual bool dispatchEvent(PassRefPtr<Event>);
+ bool dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec) { return EventTarget::dispatchEvent(event, ec); }
// ActiveDOMObject
- virtual ScriptExecutionContext* scriptExecutionContext() const;
+ virtual bool hasPendingActivity() const;
virtual bool canSuspend() const;
- virtual void stop();
+ virtual void contextDestroyed();
using RefCounted<IDBTransactionCallbacks>::ref;
using RefCounted<IDBTransactionCallbacks>::deref;
@@ -85,25 +87,20 @@ public:
private:
IDBTransaction(ScriptExecutionContext*, PassRefPtr<IDBTransactionBackendInterface>, IDBDatabase*);
+ void enqueueEvent(PassRefPtr<Event>);
+
// EventTarget
virtual void refEventTarget() { ref(); }
virtual void derefEventTarget() { deref(); }
virtual EventTargetData* eventTargetData();
virtual EventTargetData* ensureEventTargetData();
- void onAbortTimerFired(Timer<IDBTransaction>*);
- void onCompleteTimerFired(Timer<IDBTransaction>*);
- void onTimeoutTimerFired(Timer<IDBTransaction>*);
-
- EventTargetData m_eventTargetData;
RefPtr<IDBTransactionBackendInterface> m_backend;
RefPtr<IDBDatabase> m_database;
unsigned short m_mode;
+ bool m_finished; // Is it possible that we'll fire any more events or allow any new transactions? If not, we're finished.
- Timer<IDBTransaction> m_onAbortTimer;
- Timer<IDBTransaction> m_onCompleteTimer;
- Timer<IDBTransaction> m_onTimeoutTimer;
- RefPtr<IDBTransaction> m_selfRef; // This is set to us iff there's an event pending.
+ EventTargetData m_eventTargetData;
};
} // namespace WebCore
diff --git a/Source/WebCore/storage/IDBTransaction.idl b/Source/WebCore/storage/IDBTransaction.idl
index b57ac4a..2f02195 100644
--- a/Source/WebCore/storage/IDBTransaction.idl
+++ b/Source/WebCore/storage/IDBTransaction.idl
@@ -44,7 +44,7 @@ module storage {
// Events
attribute EventListener onabort;
attribute EventListener oncomplete;
- attribute EventListener ontimeout;
+ attribute EventListener onerror;
// EventTarget interface
void addEventListener(in DOMString type,
in EventListener listener,
diff --git a/Source/WebCore/storage/IDBTransactionBackendImpl.cpp b/Source/WebCore/storage/IDBTransactionBackendImpl.cpp
index 0012231..1357838 100644
--- a/Source/WebCore/storage/IDBTransactionBackendImpl.cpp
+++ b/Source/WebCore/storage/IDBTransactionBackendImpl.cpp
@@ -35,15 +35,14 @@
namespace WebCore {
-PassRefPtr<IDBTransactionBackendImpl> IDBTransactionBackendImpl::create(DOMStringList* objectStores, unsigned short mode, unsigned long timeout, IDBDatabaseBackendImpl* database)
+PassRefPtr<IDBTransactionBackendImpl> IDBTransactionBackendImpl::create(DOMStringList* objectStores, unsigned short mode, IDBDatabaseBackendImpl* database)
{
- return adoptRef(new IDBTransactionBackendImpl(objectStores, mode, timeout, database));
+ return adoptRef(new IDBTransactionBackendImpl(objectStores, mode, database));
}
-IDBTransactionBackendImpl::IDBTransactionBackendImpl(DOMStringList* objectStores, unsigned short mode, unsigned long timeout, IDBDatabaseBackendImpl* database)
+IDBTransactionBackendImpl::IDBTransactionBackendImpl(DOMStringList* objectStores, unsigned short mode, IDBDatabaseBackendImpl* database)
: m_objectStoreNames(objectStores)
, m_mode(mode)
- , m_timeout(timeout) // FIXME: Implement timeout.
, m_state(Unused)
, m_database(database)
, m_transaction(new SQLiteTransaction(database->sqliteDatabase()))
@@ -180,12 +179,12 @@ void IDBTransactionBackendImpl::taskTimerFired(Timer<IDBTransactionBackendImpl>*
if (m_state == StartPending) {
m_transaction->begin();
m_state = Running;
- } else
- ASSERT(m_state == Running);
+ }
TaskQueue queue;
queue.swap(m_taskQueue);
while (!queue.isEmpty() && m_state != Finished) {
+ ASSERT(m_state == Running);
OwnPtr<ScriptExecutionContext::Task> task(queue.first().release());
queue.removeFirst();
m_pendingEvents++;
diff --git a/Source/WebCore/storage/IDBTransactionBackendImpl.h b/Source/WebCore/storage/IDBTransactionBackendImpl.h
index f4dfaa8..1297e74 100644
--- a/Source/WebCore/storage/IDBTransactionBackendImpl.h
+++ b/Source/WebCore/storage/IDBTransactionBackendImpl.h
@@ -42,7 +42,7 @@ class IDBDatabaseBackendImpl;
class IDBTransactionBackendImpl : public IDBTransactionBackendInterface {
public:
- static PassRefPtr<IDBTransactionBackendImpl> create(DOMStringList* objectStores, unsigned short mode, unsigned long timeout, IDBDatabaseBackendImpl*);
+ static PassRefPtr<IDBTransactionBackendImpl> create(DOMStringList* objectStores, unsigned short mode, IDBDatabaseBackendImpl*);
virtual ~IDBTransactionBackendImpl();
virtual PassRefPtr<IDBObjectStoreBackendInterface> objectStore(const String& name, ExceptionCode&);
@@ -55,7 +55,7 @@ public:
void run();
private:
- IDBTransactionBackendImpl(DOMStringList* objectStores, unsigned short mode, unsigned long timeout, IDBDatabaseBackendImpl*);
+ IDBTransactionBackendImpl(DOMStringList* objectStores, unsigned short mode, IDBDatabaseBackendImpl*);
enum State {
Unused, // Created, but no tasks yet.
@@ -72,7 +72,6 @@ private:
RefPtr<DOMStringList> m_objectStoreNames;
unsigned short m_mode;
- unsigned long m_timeout;
State m_state;
RefPtr<IDBTransactionCallbacks> m_callbacks;
diff --git a/Source/WebCore/storage/IDBTransactionCallbacks.h b/Source/WebCore/storage/IDBTransactionCallbacks.h
index 348608d..8d906a6 100644
--- a/Source/WebCore/storage/IDBTransactionCallbacks.h
+++ b/Source/WebCore/storage/IDBTransactionCallbacks.h
@@ -42,7 +42,6 @@ public:
virtual void onAbort() = 0;
virtual void onComplete() = 0;
- virtual void onTimeout() = 0;
};
} // namespace WebCore
diff --git a/Source/WebCore/storage/chromium/IDBFactoryBackendInterface.cpp b/Source/WebCore/storage/chromium/IDBFactoryBackendInterface.cpp
index 92e9a7b..81eeb3e 100644
--- a/Source/WebCore/storage/chromium/IDBFactoryBackendInterface.cpp
+++ b/Source/WebCore/storage/chromium/IDBFactoryBackendInterface.cpp
@@ -39,11 +39,6 @@ PassRefPtr<IDBFactoryBackendInterface> IDBFactoryBackendInterface::create()
return PlatformBridge::idbFactory();
}
-IDBFactoryBackendInterface::~IDBFactoryBackendInterface()
-{
- PlatformBridge::idbShutdown();
-}
-
} // namespace WebCore
#endif // ENABLE(INDEXED_DATABASE)