From 324273b63bbb543d83f639d08ba5b82e852d32b7 Mon Sep 17 00:00:00 2001 From: Ben Turner Date: Thu, 26 Aug 2010 13:57:25 -0700 Subject: [PATCH 1/3] Bug 579882 - 'IndexedDB: Investigate/review IndexedDB event handling'. r=smaug+sicking. --- dom/indexedDB/IDBCursor.cpp | 11 +++---- dom/indexedDB/IDBDatabase.cpp | 35 +++++++++++++------- dom/indexedDB/IDBFactory.cpp | 19 ++++++++++- dom/indexedDB/IDBIndex.cpp | 55 +++++++++++++++++++++----------- dom/indexedDB/IDBObjectStore.cpp | 28 ++++++++++------ dom/indexedDB/IDBRequest.cpp | 33 ++++++++++++++----- dom/indexedDB/IDBRequest.h | 42 ++++++++++++++---------- dom/indexedDB/IDBTransaction.cpp | 21 +++++++++++- dom/indexedDB/IDBTransaction.h | 15 ++++++++- dom/indexedDB/IndexedDatabase.h | 1 + dom/indexedDB/nsIIDBDatabase.idl | 11 +++++-- dom/indexedDB/nsIIDBFactory.idl | 5 +++ 12 files changed, 200 insertions(+), 76 deletions(-) diff --git a/dom/indexedDB/IDBCursor.cpp b/dom/indexedDB/IDBCursor.cpp index 902bbe7e2c2..b8cddbebd45 100644 --- a/dom/indexedDB/IDBCursor.cpp +++ b/dom/indexedDB/IDBCursor.cpp @@ -37,15 +37,12 @@ * * ***** END LICENSE BLOCK ***** */ -// XXX remove once we can get jsvals out of XPIDL -#include "jscntxt.h" -#include "jsapi.h" - #include "IDBCursor.h" #include "nsIIDBDatabaseException.h" #include "nsIVariant.h" +#include "jscntxt.h" #include "mozilla/storage.h" #include "nsComponentManagerUtils.h" #include "nsContentUtils.h" @@ -484,7 +481,8 @@ IDBCursor::Update(const jsval &aValue, rv = json->EncodeFromJSVal(clone.jsval_addr(), aCx, jsonValue); NS_ENSURE_SUCCESS(rv, rv); - nsRefPtr request = GenerateWriteRequest(); + nsRefPtr request = + GenerateWriteRequest(mTransaction->ScriptContext(), mTransaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = @@ -518,7 +516,8 @@ IDBCursor::Remove(nsIIDBRequest** _retval) const Key& key = mData[mDataIndex].key; NS_ASSERTION(!key.IsUnset() && !key.IsNull(), "Bad key!"); - nsRefPtr request = GenerateWriteRequest(); + nsRefPtr request = + GenerateWriteRequest(mTransaction->ScriptContext(), mTransaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = diff --git a/dom/indexedDB/IDBDatabase.cpp b/dom/indexedDB/IDBDatabase.cpp index 39f84e26b67..5453cab4e11 100644 --- a/dom/indexedDB/IDBDatabase.cpp +++ b/dom/indexedDB/IDBDatabase.cpp @@ -364,6 +364,7 @@ NS_IMETHODIMP IDBDatabase::CreateObjectStore(const nsAString& aName, const nsAString& aKeyPath, PRBool aAutoIncrement, + JSContext* aCx, nsIIDBRequest** _retval) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); @@ -388,9 +389,6 @@ IDBDatabase::CreateObjectStore(const nsAString& aName, return NS_ERROR_ALREADY_INITIALIZED; } - nsRefPtr request = GenerateWriteRequest(); - NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); - nsTArray objectStores; nsString* name = objectStores.AppendElement(aName); if (!name) { @@ -399,9 +397,14 @@ IDBDatabase::CreateObjectStore(const nsAString& aName, } nsRefPtr transaction = - IDBTransaction::Create(this, objectStores, nsIIDBTransaction::READ_WRITE, + IDBTransaction::Create(aCx, this, objectStores, + nsIIDBTransaction::READ_WRITE, kDefaultDatabaseTimeoutSeconds); + nsRefPtr request = + GenerateWriteRequest(transaction->ScriptContext(), transaction->Owner()); + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); + nsRefPtr helper = new CreateObjectStoreHelper(transaction, request, aName, keyPath, !!aAutoIncrement); @@ -414,6 +417,7 @@ IDBDatabase::CreateObjectStore(const nsAString& aName, NS_IMETHODIMP IDBDatabase::RemoveObjectStore(const nsAString& aName, + JSContext* aCx, nsIIDBRequest** _retval) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); @@ -439,12 +443,14 @@ IDBDatabase::RemoveObjectStore(const nsAString& aName, } nsRefPtr transaction = - IDBTransaction::Create(this, storesToOpen, nsIIDBTransaction::READ_WRITE, + IDBTransaction::Create(aCx, this, storesToOpen, + nsIIDBTransaction::READ_WRITE, kDefaultDatabaseTimeoutSeconds); NS_ENSURE_TRUE(transaction, NS_ERROR_FAILURE); - - nsRefPtr request = GenerateWriteRequest(); + nsRefPtr request = + GenerateWriteRequest(transaction->ScriptContext(), transaction->Owner()); + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = new RemoveObjectStoreHelper(transaction, request, aName); @@ -457,6 +463,7 @@ IDBDatabase::RemoveObjectStore(const nsAString& aName, NS_IMETHODIMP IDBDatabase::SetVersion(const nsAString& aVersion, + JSContext* aCx, nsIIDBRequest** _retval) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); @@ -467,15 +474,17 @@ IDBDatabase::SetVersion(const nsAString& aVersion, return NS_ERROR_UNEXPECTED; } - nsRefPtr request = GenerateWriteRequest(); - // Lock the whole database nsTArray storesToOpen; nsRefPtr transaction = - IDBTransaction::Create(this, storesToOpen, IDBTransaction::FULL_LOCK, + IDBTransaction::Create(aCx, this, storesToOpen, IDBTransaction::FULL_LOCK, kDefaultDatabaseTimeoutSeconds); NS_ENSURE_TRUE(transaction, NS_ERROR_FAILURE); + nsRefPtr request = + GenerateWriteRequest(transaction->ScriptContext(), transaction->Owner()); + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); + nsRefPtr helper = new SetVersionHelper(transaction, request, aVersion); nsresult rv = helper->DispatchToTransactionPool(); @@ -489,6 +498,7 @@ NS_IMETHODIMP IDBDatabase::Transaction(nsIVariant* aStoreNames, PRUint16 aMode, PRUint32 aTimeout, + JSContext* aCx, PRUint8 aOptionalArgCount, nsIIDBTransaction** _retval) { @@ -613,7 +623,7 @@ IDBDatabase::Transaction(nsIVariant* aStoreNames, } nsRefPtr transaction = - IDBTransaction::Create(this, storesToOpen, aMode, + IDBTransaction::Create(aCx, this, storesToOpen, aMode, kDefaultDatabaseTimeoutSeconds); NS_ENSURE_TRUE(transaction, NS_ERROR_FAILURE); @@ -624,6 +634,7 @@ IDBDatabase::Transaction(nsIVariant* aStoreNames, NS_IMETHODIMP IDBDatabase::ObjectStore(const nsAString& aName, PRUint16 aMode, + JSContext* aCx, PRUint8 aOptionalArgCount, nsIIDBObjectStore** _retval) { @@ -661,7 +672,7 @@ IDBDatabase::ObjectStore(const nsAString& aName, } nsRefPtr transaction = - IDBTransaction::Create(this, storesToOpen, aMode, + IDBTransaction::Create(aCx, this, storesToOpen, aMode, kDefaultDatabaseTimeoutSeconds); NS_ENSURE_TRUE(transaction, NS_ERROR_FAILURE); diff --git a/dom/indexedDB/IDBFactory.cpp b/dom/indexedDB/IDBFactory.cpp index 667b5cddc3b..f1c3010423e 100644 --- a/dom/indexedDB/IDBFactory.cpp +++ b/dom/indexedDB/IDBFactory.cpp @@ -41,6 +41,7 @@ #include "nsIIDBDatabaseException.h" #include "nsILocalFile.h" +#include "nsIScriptContext.h" #include "mozilla/storage.h" #include "nsAppDirectoryServiceDefs.h" @@ -49,6 +50,7 @@ #include "nsDirectoryServiceUtils.h" #include "nsDOMClassInfo.h" #include "nsHashKeys.h" +#include "nsPIDOMWindow.h" #include "nsServiceManagerUtils.h" #include "nsThreadUtils.h" #include "nsXPCOMCID.h" @@ -518,6 +520,7 @@ DOMCI_DATA(IDBFactory, IDBFactory) NS_IMETHODIMP IDBFactory::Open(const nsAString& aName, const nsAString& aDescription, + JSContext* aCx, nsIIDBRequest** _retval) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); @@ -540,7 +543,21 @@ IDBFactory::Open(const nsAString& aName, NS_ENSURE_SUCCESS(rv, nsnull); } - nsRefPtr request = GenerateRequest(); + nsIScriptContext* context = GetScriptContextFromJSContext(aCx); + NS_ENSURE_STATE(context); + + nsCOMPtr innerWindow; + + nsCOMPtr window = + do_QueryInterface(context->GetGlobalObject()); + if (window) { + innerWindow = window->GetCurrentInnerWindow(); + } + NS_ENSURE_STATE(innerWindow); + + nsRefPtr request = GenerateRequest(context, innerWindow); + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); + nsRefPtr thread(new LazyIdleThread(kDefaultThreadTimeoutMS, nsnull)); diff --git a/dom/indexedDB/IDBIndex.cpp b/dom/indexedDB/IDBIndex.cpp index 8cd57d91add..955de567035 100644 --- a/dom/indexedDB/IDBIndex.cpp +++ b/dom/indexedDB/IDBIndex.cpp @@ -319,12 +319,14 @@ IDBIndex::Get(nsIVariant* aKey, return NS_ERROR_INVALID_ARG; } - nsRefPtr request = GenerateRequest(); + IDBTransaction* transaction = mObjectStore->Transaction(); + + nsRefPtr request = + GenerateRequest(transaction->ScriptContext(), transaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = - new GetHelper(mObjectStore->Transaction(), request, key, mId, mUnique, - mAutoIncrement); + new GetHelper(transaction, request, key, mId, mUnique, mAutoIncrement); rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, rv); @@ -346,11 +348,14 @@ IDBIndex::GetObject(nsIVariant* aKey, return NS_ERROR_INVALID_ARG; } - nsRefPtr request = GenerateRequest(); + IDBTransaction* transaction = mObjectStore->Transaction(); + + nsRefPtr request = + GenerateRequest(transaction->ScriptContext(), transaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = - new GetObjectHelper(mObjectStore->Transaction(), request, key, mId, mUnique, + new GetObjectHelper(transaction, request, key, mId, mUnique, mAutoIncrement); rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, rv); @@ -379,12 +384,15 @@ IDBIndex::GetAll(nsIVariant* aKey, aLimit = PR_UINT32_MAX; } - nsRefPtr request = GenerateRequest(); + IDBTransaction* transaction = mObjectStore->Transaction(); + + nsRefPtr request = + GenerateRequest(transaction->ScriptContext(), transaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = - new GetAllHelper(mObjectStore->Transaction(), request, key, mId, mUnique, - mAutoIncrement, aLimit); + new GetAllHelper(transaction, request, key, mId, mUnique, mAutoIncrement, + aLimit); rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, rv); @@ -412,12 +420,15 @@ IDBIndex::GetAllObjects(nsIVariant* aKey, aLimit = PR_UINT32_MAX; } - nsRefPtr request = GenerateRequest(); + IDBTransaction* transaction = mObjectStore->Transaction(); + + nsRefPtr request = + GenerateRequest(transaction->ScriptContext(), transaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = - new GetAllObjectsHelper(mObjectStore->Transaction(), request, key, mId, - mUnique, mAutoIncrement, aLimit); + new GetAllObjectsHelper(transaction, request, key, mId, mUnique, + mAutoIncrement, aLimit); rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, rv); @@ -477,13 +488,16 @@ IDBIndex::OpenCursor(nsIIDBKeyRange* aKeyRange, return NS_ERROR_NOT_IMPLEMENTED; } - nsRefPtr request = GenerateRequest(); + IDBTransaction* transaction = mObjectStore->Transaction(); + + nsRefPtr request = + GenerateRequest(transaction->ScriptContext(), transaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = - new OpenCursorHelper(mObjectStore->Transaction(), request, this, mId, - mUnique, mAutoIncrement, leftKey, rightKey, - keyRangeFlags, aDirection, aPreload); + new OpenCursorHelper(transaction, request, this, mId, mUnique, + mAutoIncrement, leftKey, rightKey, keyRangeFlags, + aDirection, aPreload); rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, rv); @@ -544,13 +558,16 @@ IDBIndex::OpenObjectCursor(nsIIDBKeyRange* aKeyRange, return NS_ERROR_NOT_IMPLEMENTED; } - nsRefPtr request = GenerateRequest(); + IDBTransaction* transaction = mObjectStore->Transaction(); + + nsRefPtr request = + GenerateRequest(transaction->ScriptContext(), transaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = - new OpenObjectCursorHelper(mObjectStore->Transaction(), request, this, mId, - mUnique, mAutoIncrement, leftKey, rightKey, - keyRangeFlags, aDirection, aPreload); + new OpenObjectCursorHelper(transaction, request, this, mId, mUnique, + mAutoIncrement, leftKey, rightKey, keyRangeFlags, + aDirection, aPreload); rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, rv); diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp index 7ebb79aeaa8..1c10fa03893 100644 --- a/dom/indexedDB/IDBObjectStore.cpp +++ b/dom/indexedDB/IDBObjectStore.cpp @@ -839,7 +839,8 @@ IDBObjectStore::Get(nsIVariant* aKey, return NS_ERROR_ILLEGAL_VALUE; } - nsRefPtr request = GenerateRequest(); + nsRefPtr request = + GenerateRequest(mTransaction->ScriptContext(), mTransaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = @@ -889,7 +890,8 @@ IDBObjectStore::GetAll(nsIIDBKeyRange* aKeyRange, NS_ENSURE_SUCCESS(rv, rv); } - nsRefPtr request = GenerateRequest(); + nsRefPtr request = + GenerateRequest(mTransaction->ScriptContext(), mTransaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = @@ -935,7 +937,8 @@ IDBObjectStore::Add(const jsval &aValue, return NS_ERROR_ILLEGAL_VALUE; } - nsRefPtr request = GenerateWriteRequest(); + nsRefPtr request = + GenerateWriteRequest(mTransaction->ScriptContext(), mTransaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = @@ -980,7 +983,8 @@ IDBObjectStore::Modify(const jsval &aValue, return NS_ERROR_ILLEGAL_VALUE; } - nsRefPtr request = GenerateWriteRequest(); + nsRefPtr request = + GenerateWriteRequest(mTransaction->ScriptContext(), mTransaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = @@ -1025,7 +1029,8 @@ IDBObjectStore::AddOrModify(const jsval &aValue, return NS_ERROR_ILLEGAL_VALUE; } - nsRefPtr request = GenerateWriteRequest(); + nsRefPtr request = + GenerateWriteRequest(mTransaction->ScriptContext(), mTransaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = @@ -1062,7 +1067,8 @@ IDBObjectStore::Remove(nsIVariant* aKey, return NS_ERROR_ILLEGAL_VALUE; } - nsRefPtr request = GenerateWriteRequest(); + nsRefPtr request = + GenerateWriteRequest(mTransaction->ScriptContext(), mTransaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = @@ -1127,7 +1133,8 @@ IDBObjectStore::OpenCursor(nsIIDBKeyRange* aKeyRange, return NS_ERROR_NOT_IMPLEMENTED; } - nsRefPtr request = GenerateRequest(); + nsRefPtr request = + GenerateRequest(mTransaction->ScriptContext(), mTransaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = @@ -1178,7 +1185,8 @@ IDBObjectStore::CreateIndex(const nsAString& aName, return NS_ERROR_UNEXPECTED; } - nsRefPtr request = GenerateWriteRequest(); + nsRefPtr request = + GenerateWriteRequest(mTransaction->ScriptContext(), mTransaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = @@ -1257,7 +1265,9 @@ IDBObjectStore::RemoveIndex(const nsAString& aName, return NS_ERROR_NOT_AVAILABLE; } - nsRefPtr request = GenerateWriteRequest(); + nsRefPtr request = + GenerateWriteRequest(mTransaction->ScriptContext(), mTransaction->Owner()); + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr helper = new RemoveIndexHelper(mTransaction, request, aName, this); diff --git a/dom/indexedDB/IDBRequest.cpp b/dom/indexedDB/IDBRequest.cpp index 415f681a371..197d3a49885 100644 --- a/dom/indexedDB/IDBRequest.cpp +++ b/dom/indexedDB/IDBRequest.cpp @@ -45,6 +45,8 @@ #include "nsComponentManagerUtils.h" #include "nsDOMClassInfo.h" +#include "nsDOMJSUtils.h" +#include "nsPIDOMWindow.h" #include "nsStringGlue.h" #include "nsThreadUtils.h" @@ -52,14 +54,29 @@ USING_INDEXEDDB_NAMESPACE -IDBRequest::IDBRequest(Generator* aGenerator, - bool aWriteRequest) -: mGenerator(aGenerator), - mReadyState(nsIIDBRequest::INITIAL), - mAborted(false), - mWriteRequest(aWriteRequest) +already_AddRefed +IDBRequest::Generator::GenerateRequestInternal(nsIScriptContext* aScriptContext, + nsPIDOMWindow* aOwner, + PRBool aWriteRequest) { - NS_ASSERTION(aGenerator, "Null generator!"); + if (!aScriptContext || !aOwner) { + NS_ERROR("Null context and owner!"); + return nsnull; + } + + nsRefPtr request(new IDBRequest()); + + request->mGenerator = this; + request->mWriteRequest = aWriteRequest; + request->mScriptContext = aScriptContext; + request->mOwner = aOwner; + + if (!mLiveRequests.AppendElement(request)) { + NS_ERROR("Append failed!"); + return nsnull; + } + + return request.forget(); } IDBRequest::~IDBRequest() @@ -84,7 +101,7 @@ IDBRequest::Abort() return NS_ERROR_NOT_AVAILABLE; } - mAborted = true; + mAborted = PR_TRUE; mReadyState = nsIIDBRequest::DONE; return NS_OK; } diff --git a/dom/indexedDB/IDBRequest.h b/dom/indexedDB/IDBRequest.h index 91f7d8ac062..04e3f61cfd0 100644 --- a/dom/indexedDB/IDBRequest.h +++ b/dom/indexedDB/IDBRequest.h @@ -49,6 +49,9 @@ #include "nsDOMEventTargetHelper.h" #include "nsCycleCollectionParticipant.h" +class nsIScriptContext; +class nsPIDOMWindow; + BEGIN_INDEXEDDB_NAMESPACE class AsyncConnectionHelper; @@ -72,20 +75,16 @@ public: NS_ASSERTION(mLiveRequests.IsEmpty(), "Huh?!"); } - IDBRequest* GenerateRequest() { - IDBRequest* request = new IDBRequest(this, false); - if (!mLiveRequests.AppendElement(request)) { - NS_ERROR("Append failed!"); - } - return request; + already_AddRefed + GenerateRequest(nsIScriptContext* aScriptContext, + nsPIDOMWindow* aOwner) { + return GenerateRequestInternal(aScriptContext, aOwner, PR_FALSE); } - IDBRequest* GenerateWriteRequest() { - IDBRequest* request = new IDBRequest(this, true); - if (!mLiveRequests.AppendElement(request)) { - NS_ERROR("Append failed!"); - } - return request; + already_AddRefed + GenerateWriteRequest(nsIScriptContext* aScriptContext, + nsPIDOMWindow* aOwner) { + return GenerateRequestInternal(aScriptContext, aOwner, PR_TRUE); } void NoteDyingRequest(IDBRequest* aRequest) { @@ -94,6 +93,11 @@ public: } private: + already_AddRefed + GenerateRequestInternal(nsIScriptContext* aScriptContext, + nsPIDOMWindow* aOwner, + PRBool aWriteRequest); + // XXXbent Assuming infallible nsTArray here, make sure it lands! nsAutoTArray mLiveRequests; }; @@ -113,8 +117,11 @@ public: private: // Only called by IDBRequestGenerator::Generate(). - IDBRequest(Generator* aGenerator, - bool aWriteRequest); + IDBRequest() + : mReadyState(nsIIDBRequest::INITIAL), + mAborted(PR_FALSE), + mWriteRequest(PR_FALSE) + { } nsRefPtr mGenerator; @@ -122,11 +129,12 @@ protected: // Called by Release(). ~IDBRequest(); - PRUint16 mReadyState; - PRBool mAborted; - PRBool mWriteRequest; nsRefPtr mOnSuccessListener; nsRefPtr mOnErrorListener; + + PRUint16 mReadyState; + PRPackedBool mAborted; + PRPackedBool mWriteRequest; }; END_INDEXEDDB_NAMESPACE diff --git a/dom/indexedDB/IDBTransaction.cpp b/dom/indexedDB/IDBTransaction.cpp index ac75299ac81..d78de9f7b86 100644 --- a/dom/indexedDB/IDBTransaction.cpp +++ b/dom/indexedDB/IDBTransaction.cpp @@ -39,8 +39,11 @@ #include "IDBTransaction.h" +#include "nsIScriptContext.h" + #include "mozilla/storage.h" #include "nsDOMClassInfo.h" +#include "nsPIDOMWindow.h" #include "nsProxyRelease.h" #include "nsThreadUtils.h" @@ -72,7 +75,8 @@ DoomCachedStatements(const nsACString& aQuery, // static already_AddRefed -IDBTransaction::Create(IDBDatabase* aDatabase, +IDBTransaction::Create(JSContext* aCx, + IDBDatabase* aDatabase, nsTArray& aObjectStoreNames, PRUint16 aMode, PRUint32 aTimeout) @@ -95,6 +99,21 @@ IDBTransaction::Create(IDBDatabase* aDatabase, return nsnull; } + nsIScriptContext* context = GetScriptContextFromJSContext(aCx); + if (context) { + transaction->mScriptContext = context; + nsCOMPtr window = + do_QueryInterface(context->GetGlobalObject()); + if (window) { + transaction->mOwner = window->GetCurrentInnerWindow(); + } + } + + if (!transaction->mOwner) { + NS_ERROR("Couldn't get script context and owner!"); + return nsnull; + } + return transaction.forget(); } diff --git a/dom/indexedDB/IDBTransaction.h b/dom/indexedDB/IDBTransaction.h index bd1221418dd..f3bd4fb26d7 100644 --- a/dom/indexedDB/IDBTransaction.h +++ b/dom/indexedDB/IDBTransaction.h @@ -53,7 +53,9 @@ #include "nsHashKeys.h" #include "nsInterfaceHashtable.h" +class nsIScriptContext; class nsIThread; +class nsPIDOMWindow; BEGIN_INDEXEDDB_NAMESPACE @@ -78,7 +80,8 @@ public: nsDOMEventTargetHelper) static already_AddRefed - Create(IDBDatabase* aDatabase, + Create(JSContext* aCx, + IDBDatabase* aDatabase, nsTArray& aObjectStoreNames, PRUint16 aMode, PRUint32 aTimeout); @@ -144,6 +147,16 @@ public: enum { FULL_LOCK = nsIIDBTransaction::SNAPSHOT_READ + 1 }; + nsIScriptContext* ScriptContext() + { + return mScriptContext; + } + + nsPIDOMWindow* Owner() + { + return mOwner; + } + private: IDBTransaction(); ~IDBTransaction(); diff --git a/dom/indexedDB/IndexedDatabase.h b/dom/indexedDB/IndexedDatabase.h index 327a3ff9b69..25fe71d568f 100644 --- a/dom/indexedDB/IndexedDatabase.h +++ b/dom/indexedDB/IndexedDatabase.h @@ -43,6 +43,7 @@ #include "nsIProgrammingLanguage.h" +#include "jsapi.h" #include "nsAutoPtr.h" #include "nsCOMPtr.h" #include "nsDebug.h" diff --git a/dom/indexedDB/nsIIDBDatabase.idl b/dom/indexedDB/nsIIDBDatabase.idl index 61aaf93975b..17f831f8512 100644 --- a/dom/indexedDB/nsIIDBDatabase.idl +++ b/dom/indexedDB/nsIIDBDatabase.idl @@ -45,6 +45,10 @@ interface nsIIDBRequest; interface nsIIDBTransaction; interface nsIDOMDOMStringList; +%{C++ +#include "jsapi.h" +%} + /** * IDBDatabase interface. See * http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBDatabase @@ -61,24 +65,27 @@ interface nsIIDBDatabase : nsISupports readonly attribute nsIDOMDOMStringList objectStoreNames; + [implicit_jscontext] nsIIDBRequest createObjectStore(in AString name, in AString keyPath, [optional /* false */] in boolean autoIncrement); + [implicit_jscontext] nsIIDBRequest removeObjectStore(in AString name); + [implicit_jscontext] nsIIDBRequest setVersion(in AString version); - [optional_argc] + [optional_argc, implicit_jscontext] nsIIDBTransaction transaction(in nsIVariant storeNames, // js array of strings [optional /* READ_ONLY */] in unsigned short mode, [optional /* 5000ms */] in unsigned long timeout); - [optional_argc] + [optional_argc, implicit_jscontext] nsIIDBObjectStore objectStore(in AString name, [optional /* READ_ONLY */] in unsigned short mode); diff --git a/dom/indexedDB/nsIIDBFactory.idl b/dom/indexedDB/nsIIDBFactory.idl index 09d8dc6f172..3f82dc489c9 100644 --- a/dom/indexedDB/nsIIDBFactory.idl +++ b/dom/indexedDB/nsIIDBFactory.idl @@ -44,6 +44,10 @@ interface nsIIDBKeyRange; interface nsIIDBRequest; interface nsIVariant; +%{C++ +#include "jsapi.h" +%} + /** * Interface that defines the indexedDB property on a window. See * http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBFactory @@ -52,6 +56,7 @@ interface nsIVariant; [scriptable, uuid(a1e1dbd1-53a7-490a-ab6f-aa55809dd867)] interface nsIIDBFactory : nsISupports { + [implicit_jscontext] nsIIDBRequest open(in AString name, in AString description); From 248eae0489dbfb7b3e5a2a4b42785d6d63e7420b Mon Sep 17 00:00:00 2001 From: Ben Turner Date: Thu, 26 Aug 2010 13:57:28 -0700 Subject: [PATCH 2/3] Bug 589334 - 'IndexedDB: Get rid of IDBObjectStore::Modify, rename IDBObjectStore::AddOrModify to Put'. r=sicking --- dom/indexedDB/IDBObjectStore.cpp | 70 +++------------ dom/indexedDB/nsIIDBObjectStore.idl | 10 +-- dom/indexedDB/test/test_cursors.html | 2 +- dom/indexedDB/test/test_key_requirements.html | 86 +++++++++---------- .../test/test_readonly_transactions.html | 16 ++-- .../test/test_transaction_abort.html | 8 +- 6 files changed, 69 insertions(+), 123 deletions(-) diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp index 1c10fa03893..1cb007a360c 100644 --- a/dom/indexedDB/IDBObjectStore.cpp +++ b/dom/indexedDB/IDBObjectStore.cpp @@ -76,12 +76,11 @@ public: const nsAString& aValue, const Key& aKey, bool aAutoIncrement, - bool aCreate, bool aOverwrite, nsTArray& aIndexUpdateInfo) : AsyncConnectionHelper(aTransaction, aRequest), mOSID(aObjectStoreID), mKeyPath(aKeyPath), mValue(aValue), mKey(aKey), - mAutoIncrement(aAutoIncrement), mCreate(aCreate), mOverwrite(aOverwrite) + mAutoIncrement(aAutoIncrement), mOverwrite(aOverwrite) { mIndexUpdateInfo.SwapElements(aIndexUpdateInfo); } @@ -101,7 +100,6 @@ private: nsString mValue; Key mKey; const bool mAutoIncrement; - const bool mCreate; const bool mOverwrite; nsTArray mIndexUpdateInfo; }; @@ -943,7 +941,7 @@ IDBObjectStore::Add(const jsval &aValue, nsRefPtr helper = new AddHelper(mTransaction, request, mId, mKeyPath, jsonValue, key, - !!mAutoIncrement, true, false, updateInfo); + !!mAutoIncrement, false, updateInfo); rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, rv); @@ -952,11 +950,11 @@ IDBObjectStore::Add(const jsval &aValue, } NS_IMETHODIMP -IDBObjectStore::Modify(const jsval &aValue, - const jsval &aKey, - JSContext* aCx, - PRUint8 aOptionalArgCount, - nsIIDBRequest** _retval) +IDBObjectStore::Put(const jsval &aValue, + const jsval &aKey, + JSContext* aCx, + PRUint8 aOptionalArgCount, + nsIIDBRequest** _retval) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); @@ -989,53 +987,7 @@ IDBObjectStore::Modify(const jsval &aValue, nsRefPtr helper = new AddHelper(mTransaction, request, mId, mKeyPath, jsonValue, key, - !!mAutoIncrement, false, true, updateInfo); - rv = helper->DispatchToTransactionPool(); - NS_ENSURE_SUCCESS(rv, rv); - - request.forget(_retval); - return NS_OK; -} - -NS_IMETHODIMP -IDBObjectStore::AddOrModify(const jsval &aValue, - const jsval &aKey, - JSContext* aCx, - PRUint8 aOptionalArgCount, - nsIIDBRequest** _retval) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - if (!mTransaction->TransactionIsOpen()) { - return NS_ERROR_UNEXPECTED; - } - - if (mMode != nsIIDBTransaction::READ_WRITE) { - return NS_ERROR_OBJECT_IS_IMMUTABLE; - } - - jsval keyval = (aOptionalArgCount >= 1) ? aKey : JSVAL_VOID; - - nsString jsonValue; - Key key; - nsTArray updateInfo; - - nsresult rv = GetAddInfo(aCx, aValue, keyval, jsonValue, key, updateInfo); - if (NS_FAILED(rv)) { - return rv; - } - - if (key.IsUnset() || key.IsNull()) { - return NS_ERROR_ILLEGAL_VALUE; - } - - nsRefPtr request = - GenerateWriteRequest(mTransaction->ScriptContext(), mTransaction->Owner()); - NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); - - nsRefPtr helper = - new AddHelper(mTransaction, request, mId, mKeyPath, jsonValue, key, - !!mAutoIncrement, true, true, updateInfo); + !!mAutoIncrement, true, updateInfo); rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, rv); @@ -1351,7 +1303,7 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection) } // Now we add it to the database (or update, depending on our variables). - stmt = mTransaction->AddStatement(mCreate, mayOverwrite, mAutoIncrement); + stmt = mTransaction->AddStatement(true, mayOverwrite, mAutoIncrement); NS_ENSURE_TRUE(stmt, nsIIDBDatabaseException::UNKNOWN_ERR); mozStorageStatementScoper scoper(stmt); @@ -1381,7 +1333,7 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection) rv = stmt->Execute(); if (NS_FAILED(rv)) { - if (mCreate && mayOverwrite && rv == NS_ERROR_STORAGE_CONSTRAINT) { + if (mayOverwrite && rv == NS_ERROR_STORAGE_CONSTRAINT) { scoper.Abandon(); stmt = mTransaction->AddStatement(false, true, mAutoIncrement); @@ -1419,7 +1371,7 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection) } // If we are supposed to generate a key, get the new id. - if (mAutoIncrement && mCreate && !mOverwrite) { + if (mAutoIncrement && !mOverwrite) { #ifdef DEBUG PRInt64 oldKey = unsetKey ? 0 : mKey.IntValue(); #endif diff --git a/dom/indexedDB/nsIIDBObjectStore.idl b/dom/indexedDB/nsIIDBObjectStore.idl index e089f6c0ca7..ecae8341c01 100644 --- a/dom/indexedDB/nsIIDBObjectStore.idl +++ b/dom/indexedDB/nsIIDBObjectStore.idl @@ -82,14 +82,8 @@ interface nsIIDBObjectStore : nsISupports // Success fires IDBTransactionEvent, result == key [implicit_jscontext, optional_argc] nsIIDBRequest - modify(in jsval value, - [optional /* undefined */] in jsval key); - - // Success fires IDBTransactionEvent, result == key - [implicit_jscontext, optional_argc] - nsIIDBRequest - addOrModify(in jsval value, - [optional /* undefined */] in jsval key); + put(in jsval value, + [optional /* undefined */] in jsval key); // Success fires IDBTransactionEvent, result == null nsIIDBRequest diff --git a/dom/indexedDB/test/test_cursors.html b/dom/indexedDB/test/test_cursors.html index 51140b4e239..20005e299e1 100644 --- a/dom/indexedDB/test/test_cursors.html +++ b/dom/indexedDB/test/test_cursors.html @@ -282,7 +282,7 @@ is(event.result, "bar", "Update succeeded"); - request = objectStore.modify("foo", sortedKeys[4]); + request = objectStore.put("foo", sortedKeys[4]); request.onerror = errorHandler; request.onsuccess = grabEventAndContinueHandler; event = yield; diff --git a/dom/indexedDB/test/test_key_requirements.html b/dom/indexedDB/test/test_key_requirements.html index 652e0db516c..7d58f9a22ef 100644 --- a/dom/indexedDB/test/test_key_requirements.html +++ b/dom/indexedDB/test/test_key_requirements.html @@ -37,21 +37,21 @@ let key1 = event.result; - request = objectStore.modify({}, key1); + request = objectStore.put({}, key1); request.onerror = errorHandler; request.onsuccess = grabEventAndContinueHandler; event = yield; - is(event.result, key1, "modify gave the same key back"); + is(event.result, key1, "put gave the same key back"); let key2 = 10; - request = objectStore.addOrModify({}, key2); + request = objectStore.put({}, key2); request.onerror = errorHandler; request.onsuccess = grabEventAndContinueHandler; event = yield; - is(event.result, key2, "modify gave the same key back"); + is(event.result, key2, "put gave the same key back"); key2 = 100; @@ -60,22 +60,22 @@ request.onsuccess = grabEventAndContinueHandler; event = yield; - is(event.result, key2, "modify gave the same key back"); + is(event.result, key2, "put gave the same key back"); try { - objectStore.addOrModify({}); - ok(false, "addOrModify with no key should throw!"); + objectStore.put({}); + ok(false, "put with no key should throw!"); } catch (e) { - ok(true, "addOrModify with no key threw"); + ok(true, "put with no key threw"); } try { - objectStore.modify({}); - ok(false, "modify with no key should throw!"); + objectStore.put({}); + ok(false, "put with no key should throw!"); } catch (e) { - ok(true, "modify with no key threw"); + ok(true, "put with no key threw"); } try { @@ -102,19 +102,19 @@ } try { - objectStore.addOrModify({}); - ok(false, "addOrModify with no key should throw!"); + objectStore.put({}); + ok(false, "put with no key should throw!"); } catch (e) { - ok(true, "addOrModify with no key threw"); + ok(true, "put with no key threw"); } try { - objectStore.modify({}); - ok(false, "modify with no key should throw!"); + objectStore.put({}); + ok(false, "put with no key should throw!"); } catch (e) { - ok(true, "modify with no key threw"); + ok(true, "put with no key threw"); } try { @@ -141,19 +141,19 @@ } try { - objectStore.addOrModify({}); - ok(false, "addOrModify with no key should throw!"); + objectStore.put({}); + ok(false, "put with no key should throw!"); } catch (e) { - ok(true, "addOrModify with no key threw"); + ok(true, "put with no key threw"); } try { - objectStore.modify({}); - ok(false, "modify with no key should throw!"); + objectStore.put({}); + ok(false, "put with no key should throw!"); } catch (e) { - ok(true, "modify with no key threw"); + ok(true, "put with no key threw"); } try { @@ -173,19 +173,19 @@ is(event.result, key1, "add gave back the same key"); - request = objectStore.modify({id:10}); + request = objectStore.put({id:10}); request.onerror = errorHandler; request.onsuccess = grabEventAndContinueHandler; event = yield; - is(event.result, key1, "modify gave back the same key"); + is(event.result, key1, "put gave back the same key"); - request = objectStore.addOrModify({id:10}); + request = objectStore.put({id:10}); request.onerror = errorHandler; request.onsuccess = grabEventAndContinueHandler; event = yield; - is(event.result, key1, "addOrModify gave back the same key"); + is(event.result, key1, "put gave back the same key"); request = objectStore.add({id:10}); request.onerror = grabEventAndContinueHandler; @@ -200,19 +200,19 @@ is(typeof(event.result), "string", "Good generated key"); try { - objectStore.modify({}, null); - ok(false, "modify with null key should throw!"); + objectStore.put({}, null); + ok(false, "put with null key should throw!"); } catch (e) { - ok(true, "modify with null key threw"); + ok(true, "put with null key threw"); } try { - objectStore.addOrModify({}, null); - ok(false, "addOrModify with null key should throw!"); + objectStore.put({}, null); + ok(false, "put with null key should throw!"); } catch (e) { - ok(true, "addOrModify with null key threw"); + ok(true, "put with null key threw"); } try { @@ -237,36 +237,36 @@ key1 = event.result; - request = objectStore.modify({id:key1}); + request = objectStore.put({id:key1}); request.onerror = errorHandler; request.onsuccess = grabEventAndContinueHandler; event = yield; - is(event.result, key1, "modify gave the same key back"); + is(event.result, key1, "put gave the same key back"); key2 = 10; - request = objectStore.addOrModify({id:key2}); + request = objectStore.put({id:key2}); request.onerror = errorHandler; request.onsuccess = grabEventAndContinueHandler; event = yield; - is(event.result, key2, "modify gave the same key back"); + is(event.result, key2, "put gave the same key back"); try { - objectStore.addOrModify({}); - ok(false, "addOrModify with no key should throw!"); + objectStore.put({}); + ok(false, "put with no key should throw!"); } catch (e) { - ok(true, "addOrModify with no key threw"); + ok(true, "put with no key threw"); } try { - objectStore.modify({}); - ok(false, "modify with no key should throw!"); + objectStore.put({}); + ok(false, "put with no key should throw!"); } catch (e) { - ok(true, "modify with no key threw"); + ok(true, "put with no key threw"); } try { diff --git a/dom/indexedDB/test/test_readonly_transactions.html b/dom/indexedDB/test/test_readonly_transactions.html index 118d22af830..5440b685d6e 100644 --- a/dom/indexedDB/test/test_readonly_transactions.html +++ b/dom/indexedDB/test/test_readonly_transactions.html @@ -60,7 +60,7 @@ request = db.transaction([osName], READ_WRITE) .objectStore(osName) - .addOrModify({}, key1); + .put({}, key1); request.onerror = errorHandler; request.onsuccess = function(event) { is(event.transaction.mode, READ_WRITE, "Correct mode"); @@ -68,7 +68,7 @@ } yield; - request = db.objectStore(osName, READ_WRITE).addOrModify({}, key2); + request = db.objectStore(osName, READ_WRITE).put({}, key2); request.onerror = errorHandler; request.onsuccess = function(event) { is(event.transaction.mode, READ_WRITE, "Correct mode"); @@ -78,7 +78,7 @@ request = db.transaction([osName], READ_WRITE) .objectStore(osName) - .modify({}, key1); + .put({}, key1); request.onerror = errorHandler; request.onsuccess = function(event) { is(event.transaction.mode, READ_WRITE, "Correct mode"); @@ -86,7 +86,7 @@ } yield; - request = db.objectStore(osName, READ_WRITE).modify({}, key1); + request = db.objectStore(osName, READ_WRITE).put({}, key1); request.onerror = errorHandler; request.onsuccess = function(event) { is(event.transaction.mode, READ_WRITE, "Correct mode"); @@ -129,7 +129,7 @@ } try { - request = db.transaction([osName]).objectStore(osName).addOrModify({}); + request = db.transaction([osName]).objectStore(osName).put({}); ok(false, "Adding or modifying a readonly transaction should fail!"); } catch (e) { @@ -137,7 +137,7 @@ } try { - request = db.objectStore(osName).addOrModify({}); + request = db.objectStore(osName).put({}); ok(false, "Adding or modifying a readonly transaction should fail!"); } catch (e) { @@ -145,7 +145,7 @@ } try { - request = db.transaction([osName]).objectStore(osName).modify({}, key1); + request = db.transaction([osName]).objectStore(osName).put({}, key1); ok(false, "Modifying a readonly transaction should fail!"); } catch (e) { @@ -153,7 +153,7 @@ } try { - request = db.objectStore(osName).modify({}, key1); + request = db.objectStore(osName).put({}, key1); ok(false, "Modifying a readonly transaction should fail!"); } catch (e) { diff --git a/dom/indexedDB/test/test_transaction_abort.html b/dom/indexedDB/test/test_transaction_abort.html index 64520015c30..93cb7c39a3d 100644 --- a/dom/indexedDB/test/test_transaction_abort.html +++ b/dom/indexedDB/test/test_transaction_abort.html @@ -91,19 +91,19 @@ } try { - objectStore.modify({}, 1); + objectStore.put({}, 1); ok(false, "Should have thrown"); } catch (e) { - ok(true, "Modify threw"); + ok(true, "Put threw"); } try { - objectStore.addOrModify({}, 1); + objectStore.put({}, 1); ok(false, "Should have thrown"); } catch (e) { - ok(true, "AddOrModify threw"); + ok(true, "Put threw"); } try { From cc122a0efcdbfe42c57e736856137394cf7fc86d Mon Sep 17 00:00:00 2001 From: Ben Turner Date: Thu, 26 Aug 2010 13:57:30 -0700 Subject: [PATCH 3/3] Bug 589355 - 'IndexedDB: Add IDBObjectStore::Clear'. r=sicking --- dom/indexedDB/IDBFactory.cpp | 5 +- dom/indexedDB/IDBObjectStore.cpp | 86 ++++++++++++++++++++- dom/indexedDB/nsIIDBObjectStore.idl | 4 + dom/indexedDB/test/Makefile.in | 1 + dom/indexedDB/test/helpers.js | 7 ++ dom/indexedDB/test/test_clear.html | 113 ++++++++++++++++++++++++++++ 6 files changed, 212 insertions(+), 4 deletions(-) create mode 100644 dom/indexedDB/test/test_clear.html diff --git a/dom/indexedDB/IDBFactory.cpp b/dom/indexedDB/IDBFactory.cpp index f1c3010423e..43b39176c50 100644 --- a/dom/indexedDB/IDBFactory.cpp +++ b/dom/indexedDB/IDBFactory.cpp @@ -61,7 +61,7 @@ #include "IDBKeyRange.h" #include "LazyIdleThread.h" -#define DB_SCHEMA_VERSION 2 +#define DB_SCHEMA_VERSION 3 USING_INDEXEDDB_NAMESPACE @@ -165,10 +165,9 @@ CreateTables(mozIStorageConnection* aDBConn) // Table `ai_object_data` rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( "CREATE TABLE ai_object_data (" - "id INTEGER, " + "id INTEGER PRIMARY KEY AUTOINCREMENT, " "object_store_id INTEGER NOT NULL, " "data TEXT NOT NULL, " - "PRIMARY KEY (id), " "FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE " "CASCADE" ");" diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp index 1cb007a360c..6ddab0afc6c 100644 --- a/dom/indexedDB/IDBObjectStore.cpp +++ b/dom/indexedDB/IDBObjectStore.cpp @@ -146,6 +146,25 @@ public: PRUint16 GetSuccessResult(nsIWritableVariant* aResult); }; +class ClearHelper : public AsyncConnectionHelper +{ +public: + ClearHelper(IDBTransaction* aTransaction, + IDBRequest* aRequest, + PRInt64 aObjectStoreID, + bool aAutoIncrement) + : AsyncConnectionHelper(aTransaction, aRequest), mOSID(aObjectStoreID), + mAutoIncrement(aAutoIncrement) + { } + + PRUint16 DoDatabaseWork(mozIStorageConnection* aConnection); + +protected: + // In-params. + const PRInt64 mOSID; + const bool mAutoIncrement; +}; + class OpenCursorHelper : public AsyncConnectionHelper { public: @@ -920,7 +939,16 @@ IDBObjectStore::Add(const jsval &aValue, return NS_ERROR_OBJECT_IS_IMMUTABLE; } - jsval keyval = (aOptionalArgCount >= 1) ? aKey : JSVAL_VOID; + jsval keyval; + if (aOptionalArgCount >= 1) { + keyval = aKey; + if (mAutoIncrement && JSVAL_IS_NULL(keyval)) { + return NS_ERROR_ILLEGAL_VALUE; + } + } + else { + keyval = JSVAL_VOID; + } nsString jsonValue; Key key; @@ -1032,6 +1060,32 @@ IDBObjectStore::Remove(nsIVariant* aKey, return NS_OK; } +NS_IMETHODIMP +IDBObjectStore::Clear(nsIIDBRequest** _retval) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + if (!mTransaction->TransactionIsOpen()) { + return NS_ERROR_UNEXPECTED; + } + + if (mMode != nsIIDBTransaction::READ_WRITE) { + return NS_ERROR_OBJECT_IS_IMMUTABLE; + } + + nsRefPtr request = + GenerateWriteRequest(mTransaction->ScriptContext(), mTransaction->Owner()); + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); + + nsRefPtr helper = + new ClearHelper(mTransaction, request, mId, !!mAutoIncrement); + nsresult rv = helper->DispatchToTransactionPool(); + NS_ENSURE_SUCCESS(rv, rv); + + request.forget(_retval); + return NS_OK; +} + NS_IMETHODIMP IDBObjectStore::OpenCursor(nsIIDBKeyRange* aKeyRange, PRUint16 aDirection, @@ -1607,6 +1661,36 @@ RemoveHelper::GetSuccessResult(nsIWritableVariant* aResult) return OK; } +PRUint16 +ClearHelper::DoDatabaseWork(mozIStorageConnection* aConnection) +{ + NS_PRECONDITION(aConnection, "Passed a null connection!"); + + nsCString table; + if (mAutoIncrement) { + table.AssignLiteral("ai_object_data"); + } + else { + table.AssignLiteral("object_data"); + } + + nsCString query = NS_LITERAL_CSTRING("DELETE FROM ") + table + + NS_LITERAL_CSTRING(" WHERE object_store_id = :osid"); + + nsCOMPtr stmt = mTransaction->GetCachedStatement(query); + NS_ENSURE_TRUE(stmt, nsIIDBDatabaseException::UNKNOWN_ERR); + + mozStorageStatementScoper scoper(stmt); + + nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), mOSID); + NS_ENSURE_SUCCESS(rv, nsIIDBDatabaseException::UNKNOWN_ERR); + + rv = stmt->Execute(); + NS_ENSURE_SUCCESS(rv, nsIIDBDatabaseException::UNKNOWN_ERR); + + return OK; +} + PRUint16 OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection) { diff --git a/dom/indexedDB/nsIIDBObjectStore.idl b/dom/indexedDB/nsIIDBObjectStore.idl index ecae8341c01..4b4fd9d65e7 100644 --- a/dom/indexedDB/nsIIDBObjectStore.idl +++ b/dom/indexedDB/nsIIDBObjectStore.idl @@ -89,6 +89,10 @@ interface nsIIDBObjectStore : nsISupports nsIIDBRequest remove(in nsIVariant key); + // Success fires IDBTransactionEvent, result == null + nsIIDBRequest + clear(); + // Success fires IDBTransactionEvent, result == IDBCursor or // IDBCursorPreloadedRequest if preload == true. result == null if no match. [optional_argc] diff --git a/dom/indexedDB/test/Makefile.in b/dom/indexedDB/test/Makefile.in index 41686e88b01..491802726ec 100644 --- a/dom/indexedDB/test/Makefile.in +++ b/dom/indexedDB/test/Makefile.in @@ -48,6 +48,7 @@ _TEST_FILES = \ helpers.js \ test_add_twice_failure.html \ test_bad_keypath.html \ + test_clear.html \ test_create_index.html \ test_create_objectStore.html \ test_cursors.html \ diff --git a/dom/indexedDB/test/helpers.js b/dom/indexedDB/test/helpers.js index 1b6f0e847fe..0c892d30133 100644 --- a/dom/indexedDB/test/helpers.js +++ b/dom/indexedDB/test/helpers.js @@ -23,6 +23,13 @@ function grabEventAndContinueHandler(event) testGenerator.send(event); } +function continueToNextStep() +{ + SimpleTest.executeSoon(function() { + testGenerator.next(); + }); +} + function errorHandler(event) { ok(false, "indexedDB error (" + event.code + "): " + event.message); diff --git a/dom/indexedDB/test/test_clear.html b/dom/indexedDB/test/test_clear.html new file mode 100644 index 00000000000..f5a1e393024 --- /dev/null +++ b/dom/indexedDB/test/test_clear.html @@ -0,0 +1,113 @@ + + + + Indexed Database Property Test + + + + + + + + + + + + +