From 74b51f96961de5393203721ed997121f4a57cac9 Mon Sep 17 00:00:00 2001 From: Ben Turner Date: Fri, 9 Nov 2012 19:29:07 -0800 Subject: [PATCH] Bug 808743 - Better protection for PBrowser shutdown and database invalidation in multiprocess scenarios. r=khuey, r=cjones, a=blocking-basecamp --- dom/indexedDB/AsyncConnectionHelper.cpp | 67 +-- dom/indexedDB/AsyncConnectionHelper.h | 9 +- dom/indexedDB/IDBCursor.cpp | 8 +- dom/indexedDB/IDBCursor.h | 6 + dom/indexedDB/IDBDatabase.cpp | 20 +- dom/indexedDB/IDBDatabase.h | 14 +- dom/indexedDB/IDBIndex.cpp | 32 +- dom/indexedDB/IDBObjectStore.cpp | 27 +- dom/indexedDB/IDBRequest.cpp | 6 +- dom/indexedDB/IDBRequest.h | 5 + dom/indexedDB/IDBTransaction.cpp | 8 + dom/indexedDB/IDBTransaction.h | 7 + dom/indexedDB/IndexedDatabaseManager.cpp | 6 +- dom/indexedDB/ipc/IndexedDBChild.cpp | 105 ++++- dom/indexedDB/ipc/IndexedDBChild.h | 25 + dom/indexedDB/ipc/IndexedDBParent.cpp | 440 +++++++++++++----- dom/indexedDB/ipc/IndexedDBParent.h | 262 +++++++++-- dom/ipc/TabChild.cpp | 6 + .../src/chrome/common/ipc_channel_win.cc | 4 +- ipc/ipdl/ipdl/lower.py | 4 +- 20 files changed, 794 insertions(+), 267 deletions(-) diff --git a/dom/indexedDB/AsyncConnectionHelper.cpp b/dom/indexedDB/AsyncConnectionHelper.cpp index 5aaf2870f0ce..c0183198c263 100644 --- a/dom/indexedDB/AsyncConnectionHelper.cpp +++ b/dom/indexedDB/AsyncConnectionHelper.cpp @@ -21,6 +21,7 @@ #include "TransactionThreadPool.h" #include "ipc/IndexedDBChild.h" +#include "ipc/IndexedDBParent.h" USING_INDEXEDDB_NAMESPACE @@ -203,36 +204,47 @@ AsyncConnectionHelper::Run() MaybeSendResponseToChildProcess(mResultCode) : Success_NotSent; - NS_ASSERTION(sendResult == Success_Sent || sendResult == Success_NotSent || - sendResult == Error, - "Unknown result from MaybeSendResultsToChildProcess!"); - - if (sendResult == Success_Sent) { - if (mRequest) { - mRequest->NotifyHelperSentResultsToChildProcess(NS_OK); - } - } - else if (sendResult == Error) { - NS_WARNING("MaybeSendResultsToChildProcess failed!"); - mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; - if (mRequest) { - mRequest->NotifyHelperSentResultsToChildProcess(mResultCode); - } - } - else if (sendResult == Success_NotSent) { - if (mRequest) { - nsresult rv = mRequest->NotifyHelperCompleted(this); - if (NS_SUCCEEDED(mResultCode) && NS_FAILED(rv)) { - mResultCode = rv; + switch (sendResult) { + case Success_Sent: { + if (mRequest) { + mRequest->NotifyHelperSentResultsToChildProcess(NS_OK); } + break; } - // Call OnError if the database had an error or if the OnSuccess handler - // has an error. - if (NS_FAILED(mResultCode) || - NS_FAILED((mResultCode = OnSuccess()))) { - OnError(); + case Success_NotSent: { + if (mRequest) { + nsresult rv = mRequest->NotifyHelperCompleted(this); + if (NS_SUCCEEDED(mResultCode) && NS_FAILED(rv)) { + mResultCode = rv; + } + } + + // Call OnError if the database had an error or if the OnSuccess + // handler has an error. + if (NS_FAILED(mResultCode) || + NS_FAILED((mResultCode = OnSuccess()))) { + OnError(); + } + break; } + + case Success_ActorDisconnected: { + // Nothing needs to be done here. + break; + } + + case Error: { + NS_WARNING("MaybeSendResultsToChildProcess failed!"); + mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; + if (mRequest) { + mRequest->NotifyHelperSentResultsToChildProcess(mResultCode); + } + break; + } + + default: + MOZ_NOT_REACHED("Unknown value for ChildProcessSendResult!"); } NS_ASSERTION(gCurrentTransaction == mTransaction, "Should be unchanged!"); @@ -532,7 +544,8 @@ AsyncConnectionHelper::MaybeSendResponseToChildProcess(nsresult aResultCode) } // Are we shutting down the child? - if (trans->Database()->IsDisconnectedFromActor()) { + IndexedDBDatabaseParent* dbActor = trans->Database()->GetActorParent(); + if (dbActor && dbActor->IsDisconnected()) { return Success_ActorDisconnected; } diff --git a/dom/indexedDB/AsyncConnectionHelper.h b/dom/indexedDB/AsyncConnectionHelper.h index 496e9049f733..442e44887919 100644 --- a/dom/indexedDB/AsyncConnectionHelper.h +++ b/dom/indexedDB/AsyncConnectionHelper.h @@ -107,12 +107,17 @@ public: static IDBTransaction* GetCurrentTransaction(); - bool HasTransaction() + bool HasTransaction() const + { + return !!mTransaction; + } + + IDBTransaction* GetTransaction() const { return mTransaction; } - nsISupports* GetSource() + nsISupports* GetSource() const { return mRequest ? mRequest->Source() : nullptr; } diff --git a/dom/indexedDB/IDBCursor.cpp b/dom/indexedDB/IDBCursor.cpp index 406636f8a350..7100c5c7fe28 100644 --- a/dom/indexedDB/IDBCursor.cpp +++ b/dom/indexedDB/IDBCursor.cpp @@ -768,6 +768,12 @@ CursorHelper::Dispatch(nsIEventTarget* aDatabaseThread) return AsyncConnectionHelper::Dispatch(aDatabaseThread); } + // If we've been invalidated then there's no point sending anything to the + // parent process. + if (mCursor->Transaction()->Database()->IsInvalidated()) { + return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; + } + IndexedDBCursorChild* cursorActor = mCursor->GetActorChild(); NS_ASSERTION(cursorActor, "Must have an actor here!"); @@ -918,7 +924,7 @@ ContinueHelper::SendResponseToChildProcess(nsresult aResultCode) response = continueResponse; } - if (!actor->Send__delete__(actor, response)) { + if (!actor->SendResponse(response)) { return Error; } diff --git a/dom/indexedDB/IDBCursor.h b/dom/indexedDB/IDBCursor.h index dc2d202dcf50..e43f475e9744 100644 --- a/dom/indexedDB/IDBCursor.h +++ b/dom/indexedDB/IDBCursor.h @@ -137,6 +137,12 @@ public: return mActorChild; } + IndexedDBCursorParent* + GetActorParent() const + { + return mActorParent; + } + nsresult ContinueInternal(const Key& aKey, int32_t aCount); diff --git a/dom/indexedDB/IDBDatabase.cpp b/dom/indexedDB/IDBDatabase.cpp index f92839ca2298..a3d623e66423 100644 --- a/dom/indexedDB/IDBDatabase.cpp +++ b/dom/indexedDB/IDBDatabase.cpp @@ -10,7 +10,6 @@ #include "mozilla/Mutex.h" #include "mozilla/storage.h" -#include "mozilla/unused.h" #include "mozilla/dom/ContentParent.h" #include "nsDOMClassInfo.h" #include "nsDOMLists.h" @@ -219,7 +218,6 @@ IDBDatabase::IDBDatabase() mActorParent(nullptr), mContentParent(nullptr), mInvalidated(false), - mDisconnected(false), mRegistered(false), mClosed(false), mRunningVersionChange(false) @@ -277,21 +275,16 @@ IDBDatabase::Invalidate() // And let the child process know as well. if (mActorParent) { NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!"); - mozilla::unused << mActorParent->SendInvalidate(); + mActorParent->Invalidate(); } } void -IDBDatabase::DisconnectFromActor() +IDBDatabase::DisconnectFromActorParent() { + NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!"); NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - if (IsDisconnectedFromActor()) { - return; - } - - mDisconnected = true; - // Make sure we're closed too. Close(); @@ -302,13 +295,6 @@ IDBDatabase::DisconnectFromActor() } } -bool -IDBDatabase::IsDisconnectedFromActor() const -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - return mDisconnected; -} - void IDBDatabase::CloseInternal(bool aIsDead) { diff --git a/dom/indexedDB/IDBDatabase.h b/dom/indexedDB/IDBDatabase.h index 286d2a67682c..5df1fb2a5647 100644 --- a/dom/indexedDB/IDBDatabase.h +++ b/dom/indexedDB/IDBDatabase.h @@ -110,12 +110,7 @@ public: return mInvalidated; } - void DisconnectFromActor(); - - // Whether or not the database has been disconnected from its actor. If true - // it is not safe to send any IPC messages to the actor representing this db - // or any of its subactors. - bool IsDisconnectedFromActor() const; + void DisconnectFromActorParent(); void CloseInternal(bool aIsDead); @@ -155,6 +150,12 @@ public: return mActorChild; } + IndexedDBDatabaseParent* + GetActorParent() const + { + return mActorParent; + } + mozilla::dom::ContentParent* GetContentParent() const { @@ -195,7 +196,6 @@ private: mozilla::dom::ContentParent* mContentParent; bool mInvalidated; - bool mDisconnected; bool mRegistered; bool mClosed; bool mRunningVersionChange; diff --git a/dom/indexedDB/IDBIndex.cpp b/dom/indexedDB/IDBIndex.cpp index 794177639b47..d115a4d334ee 100644 --- a/dom/indexedDB/IDBIndex.cpp +++ b/dom/indexedDB/IDBIndex.cpp @@ -1017,6 +1017,12 @@ IndexHelper::Dispatch(nsIEventTarget* aDatabaseThread) return AsyncConnectionHelper::Dispatch(aDatabaseThread); } + // If we've been invalidated then there's no point sending anything to the + // parent process. + if (mIndex->ObjectStore()->Transaction()->Database()->IsInvalidated()) { + return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; + } + IndexedDBIndexChild* indexActor = mIndex->GetActorChild(); NS_ASSERTION(indexActor, "Must have an actor here!"); @@ -1128,7 +1134,7 @@ GetKeyHelper::SendResponseToChildProcess(nsresult aResultCode) response = getKeyResponse; } - if (!actor->Send__delete__(actor, response)) { + if (!actor->SendResponse(response)) { return Error; } @@ -1271,7 +1277,7 @@ GetHelper::SendResponseToChildProcess(nsresult aResultCode) response = getResponse; } - if (!actor->Send__delete__(actor, response)) { + if (!actor->SendResponse(response)) { return Error; } @@ -1448,7 +1454,7 @@ GetAllKeysHelper::SendResponseToChildProcess(nsresult aResultCode) response = getAllKeysResponse; } - if (!actor->Send__delete__(actor, response)) { + if (!actor->SendResponse(response)) { return Error; } @@ -1638,7 +1644,7 @@ GetAllHelper::SendResponseToChildProcess(nsresult aResultCode) response = getAllResponse; } - if (!actor->Send__delete__(actor, response)) { + if (!actor->SendResponse(response)) { return Error; } @@ -1943,19 +1949,15 @@ OpenKeyCursorHelper::SendResponseToChildProcess(nsresult aResultCode) params.objectKey() = mObjectKey; params.optionalCloneInfo() = mozilla::void_t(); - IndexedDBCursorParent* cursorActor = new IndexedDBCursorParent(mCursor); - - if (!indexActor->SendPIndexedDBCursorConstructor(cursorActor, params)) { + if (!indexActor->OpenCursor(mCursor, params, openCursorResponse)) { return Error; } - - openCursorResponse = cursorActor; } response = openCursorResponse; } - if (!actor->Send__delete__(actor, response)) { + if (!actor->SendResponse(response)) { return Error; } @@ -2303,19 +2305,15 @@ OpenCursorHelper::SendResponseToChildProcess(nsresult aResultCode) params.optionalCloneInfo() = mSerializedCloneReadInfo; params.blobsParent().SwapElements(blobsParent); - IndexedDBCursorParent* cursorActor = new IndexedDBCursorParent(mCursor); - - if (!indexActor->SendPIndexedDBCursorConstructor(cursorActor, params)) { + if (!indexActor->OpenCursor(mCursor, params, openCursorResponse)) { return Error; } - - openCursorResponse = cursorActor; } response = openCursorResponse; } - if (!actor->Send__delete__(actor, response)) { + if (!actor->SendResponse(response)) { return Error; } @@ -2432,7 +2430,7 @@ CountHelper::SendResponseToChildProcess(nsresult aResultCode) response = countResponse; } - if (!actor->Send__delete__(actor, response)) { + if (!actor->SendResponse(response)) { return Error; } diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp index 4e9d23df88ce..9fc889a4d87b 100644 --- a/dom/indexedDB/IDBObjectStore.cpp +++ b/dom/indexedDB/IDBObjectStore.cpp @@ -2560,6 +2560,12 @@ ObjectStoreHelper::Dispatch(nsIEventTarget* aDatabaseThread) return AsyncConnectionHelper::Dispatch(aDatabaseThread); } + // If we've been invalidated then there's no point sending anything to the + // parent process. + if (mObjectStore->Transaction()->Database()->IsInvalidated()) { + return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; + } + IndexedDBObjectStoreChild* objectStoreActor = mObjectStore->GetActorChild(); NS_ASSERTION(objectStoreActor, "Must have an actor here!"); @@ -2878,7 +2884,7 @@ AddHelper::SendResponseToChildProcess(nsresult aResultCode) response = addResponse; } - if (!actor->Send__delete__(actor, response)) { + if (!actor->SendResponse(response)) { return Error; } @@ -3013,7 +3019,7 @@ GetHelper::SendResponseToChildProcess(nsresult aResultCode) response = getResponse; } - if (!actor->Send__delete__(actor, response)) { + if (!actor->SendResponse(response)) { return Error; } @@ -3113,7 +3119,7 @@ DeleteHelper::SendResponseToChildProcess(nsresult aResultCode) response = DeleteResponse(); } - if (!actor->Send__delete__(actor, response)) { + if (!actor->SendResponse(response)) { return Error; } @@ -3177,7 +3183,7 @@ ClearHelper::SendResponseToChildProcess(nsresult aResultCode) response = ClearResponse(); } - if (!actor->Send__delete__(actor, response)) { + if (!actor->SendResponse(response)) { return Error; } @@ -3462,20 +3468,15 @@ OpenCursorHelper::SendResponseToChildProcess(nsresult aResultCode) params.cloneInfo() = mSerializedCloneReadInfo; params.blobsParent().SwapElements(blobsParent); - IndexedDBCursorParent* cursorActor = new IndexedDBCursorParent(mCursor); - - if (!objectStoreActor->SendPIndexedDBCursorConstructor(cursorActor, - params)) { + if (!objectStoreActor->OpenCursor(mCursor, params, openCursorResponse)) { return Error; } - - openCursorResponse = cursorActor; } response = openCursorResponse; } - if (!actor->Send__delete__(actor, response)) { + if (!actor->SendResponse(response)) { return Error; } @@ -3893,7 +3894,7 @@ GetAllHelper::SendResponseToChildProcess(nsresult aResultCode) response = getAllResponse; } - if (!actor->Send__delete__(actor, response)) { + if (!actor->SendResponse(response)) { return Error; } @@ -4045,7 +4046,7 @@ CountHelper::SendResponseToChildProcess(nsresult aResultCode) response = countResponse; } - if (!actor->Send__delete__(actor, response)) { + if (!actor->SendResponse(response)) { return Error; } diff --git a/dom/indexedDB/IDBRequest.cpp b/dom/indexedDB/IDBRequest.cpp index 5807b2981326..f7ea3ede1b06 100644 --- a/dom/indexedDB/IDBRequest.cpp +++ b/dom/indexedDB/IDBRequest.cpp @@ -232,11 +232,11 @@ IDBRequest::GetReadyState(nsAString& aReadyState) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - if (mHaveResultOrErrorCode) { - aReadyState.AssignLiteral("done"); + if (IsPending()) { + aReadyState.AssignLiteral("pending"); } else { - aReadyState.AssignLiteral("pending"); + aReadyState.AssignLiteral("done"); } return NS_OK; diff --git a/dom/indexedDB/IDBRequest.h b/dom/indexedDB/IDBRequest.h index 6fc5f1dbd742..42b3f861036c 100644 --- a/dom/indexedDB/IDBRequest.h +++ b/dom/indexedDB/IDBRequest.h @@ -84,6 +84,11 @@ public: void FillScriptErrorEvent(nsScriptErrorEvent* aEvent) const; + bool IsPending() const + { + return !mHaveResultOrErrorCode; + } + protected: IDBRequest(); ~IDBRequest(); diff --git a/dom/indexedDB/IDBTransaction.cpp b/dom/indexedDB/IDBTransaction.cpp index 7f758215fd25..5bfe2aa0816f 100644 --- a/dom/indexedDB/IDBTransaction.cpp +++ b/dom/indexedDB/IDBTransaction.cpp @@ -219,6 +219,14 @@ IDBTransaction::OnRequestFinished() } } +void +IDBTransaction::OnRequestDisconnected() +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(mPendingRequests, "Mismatched calls!"); + --mPendingRequests; +} + void IDBTransaction::RemoveObjectStore(const nsAString& aName) { diff --git a/dom/indexedDB/IDBTransaction.h b/dom/indexedDB/IDBTransaction.h index cac2ce62aaaf..147f597303d1 100644 --- a/dom/indexedDB/IDBTransaction.h +++ b/dom/indexedDB/IDBTransaction.h @@ -101,6 +101,7 @@ public: void OnNewRequest(); void OnRequestFinished(); + void OnRequestDisconnected(); void RemoveObjectStore(const nsAString& aName); @@ -188,6 +189,12 @@ public: return mActorChild; } + IndexedDBTransactionParent* + GetActorParent() const + { + return mActorParent; + } + nsresult ObjectStoreInternal(const nsAString& aName, IDBObjectStore** _retval); diff --git a/dom/indexedDB/IndexedDatabaseManager.cpp b/dom/indexedDB/IndexedDatabaseManager.cpp index dde8a65f812d..21b03a2c8174 100644 --- a/dom/indexedDB/IndexedDatabaseManager.cpp +++ b/dom/indexedDB/IndexedDatabaseManager.cpp @@ -1769,10 +1769,8 @@ OriginClearRunnable::DeleteFiles(IndexedDatabaseManager* aManager) NS_ENSURE_SUCCESS_VOID(rv); nsCOMPtr entries; - rv = directory->GetDirectoryEntries(getter_AddRefs(entries)); - NS_ENSURE_SUCCESS_VOID(rv); - - if (!entries) { + if (NS_FAILED(directory->GetDirectoryEntries(getter_AddRefs(entries))) || + !entries) { return; } diff --git a/dom/indexedDB/ipc/IndexedDBChild.cpp b/dom/indexedDB/ipc/IndexedDBChild.cpp index 6bd8a8f4d24b..aea57eb17764 100644 --- a/dom/indexedDB/ipc/IndexedDBChild.cpp +++ b/dom/indexedDB/ipc/IndexedDBChild.cpp @@ -159,6 +159,9 @@ public: IndexedDBChild::IndexedDBChild(const nsCString& aASCIIOrigin) : mFactory(nullptr), mASCIIOrigin(aASCIIOrigin) +#ifdef DEBUG + , mDisconnected(false) +#endif { MOZ_COUNT_CTOR(IndexedDBChild); } @@ -179,6 +182,21 @@ IndexedDBChild::SetFactory(IDBFactory* aFactory) mFactory = aFactory; } +void +IndexedDBChild::Disconnect() +{ +#ifdef DEBUG + MOZ_ASSERT(!mDisconnected); + mDisconnected = true; +#endif + + const InfallibleTArray& databases = + ManagedPIndexedDBDatabaseChild(); + for (uint32_t i = 0; i < databases.Length(); ++i) { + static_cast(databases[i])->Disconnect(); + } +} + void IndexedDBChild::ActorDestroy(ActorDestroyReason aWhy) { @@ -246,6 +264,16 @@ IndexedDBDatabaseChild::SetRequest(IDBOpenDBRequest* aRequest) mRequest = aRequest; } +void +IndexedDBDatabaseChild::Disconnect() +{ + const InfallibleTArray& transactions = + ManagedPIndexedDBTransactionChild(); + for (uint32_t i = 0; i < transactions.Length(); ++i) { + static_cast(transactions[i])->Disconnect(); + } +} + bool IndexedDBDatabaseChild::EnsureDatabase( IDBOpenDBRequest* aRequest, @@ -552,6 +580,16 @@ IndexedDBTransactionChild::SetTransaction(IDBTransaction* aTransaction) mStrongTransaction = aTransaction; } +void +IndexedDBTransactionChild::Disconnect() +{ + const InfallibleTArray& objectStores = + ManagedPIndexedDBObjectStoreChild(); + for (uint32_t i = 0; i < objectStores.Length(); ++i) { + static_cast(objectStores[i])->Disconnect(); + } +} + void IndexedDBTransactionChild::FireCompleteEvent(nsresult aRv) { @@ -654,6 +692,28 @@ IndexedDBObjectStoreChild::~IndexedDBObjectStoreChild() MOZ_ASSERT(!mObjectStore); } +void +IndexedDBObjectStoreChild::Disconnect() +{ + const InfallibleTArray& requests = + ManagedPIndexedDBRequestChild(); + for (uint32_t i = 0; i < requests.Length(); ++i) { + static_cast(requests[i])->Disconnect(); + } + + const InfallibleTArray& indexes = + ManagedPIndexedDBIndexChild(); + for (uint32_t i = 0; i < indexes.Length(); ++i) { + static_cast(indexes[i])->Disconnect(); + } + + const InfallibleTArray& cursors = + ManagedPIndexedDBCursorChild(); + for (uint32_t i = 0; i < cursors.Length(); ++i) { + static_cast(cursors[i])->Disconnect(); + } +} + void IndexedDBObjectStoreChild::ActorDestroy(ActorDestroyReason aWhy) { @@ -760,6 +820,22 @@ IndexedDBIndexChild::~IndexedDBIndexChild() MOZ_ASSERT(!mIndex); } +void +IndexedDBIndexChild::Disconnect() +{ + const InfallibleTArray& requests = + ManagedPIndexedDBRequestChild(); + for (uint32_t i = 0; i < requests.Length(); ++i) { + static_cast(requests[i])->Disconnect(); + } + + const InfallibleTArray& cursors = + ManagedPIndexedDBCursorChild(); + for (uint32_t i = 0; i < cursors.Length(); ++i) { + static_cast(cursors[i])->Disconnect(); + } +} + void IndexedDBIndexChild::ActorDestroy(ActorDestroyReason aWhy) { @@ -882,6 +958,16 @@ IndexedDBCursorChild::SetCursor(IDBCursor* aCursor) mStrongCursor = aCursor; } +void +IndexedDBCursorChild::Disconnect() +{ + const InfallibleTArray& requests = + ManagedPIndexedDBRequestChild(); + for (uint32_t i = 0; i < requests.Length(); ++i) { + static_cast(requests[i])->Disconnect(); + } +} + void IndexedDBCursorChild::ActorDestroy(ActorDestroyReason aWhy) { @@ -926,7 +1012,24 @@ IndexedDBRequestChildBase::~IndexedDBRequestChildBase() IDBRequest* IndexedDBRequestChildBase::GetRequest() const { - return mHelper ? mHelper->GetRequest() : NULL; + return mHelper ? mHelper->GetRequest() : nullptr; +} + +void +IndexedDBRequestChildBase::Disconnect() +{ + if (mHelper) { + IDBRequest* request = mHelper->GetRequest(); + + if (request->IsPending()) { + request->SetError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + + IDBTransaction* transaction = mHelper->GetTransaction(); + if (transaction) { + transaction->OnRequestDisconnected(); + } + } + } } bool diff --git a/dom/indexedDB/ipc/IndexedDBChild.h b/dom/indexedDB/ipc/IndexedDBChild.h index 38fd1ce4db19..fbde91046fd1 100644 --- a/dom/indexedDB/ipc/IndexedDBChild.h +++ b/dom/indexedDB/ipc/IndexedDBChild.h @@ -39,6 +39,10 @@ class IndexedDBChild : public PIndexedDBChild IDBFactory* mFactory; nsCString mASCIIOrigin; +#ifdef DEBUG + bool mDisconnected; +#endif + public: IndexedDBChild(const nsCString& aASCIIOrigin); virtual ~IndexedDBChild(); @@ -52,6 +56,9 @@ public: void SetFactory(IDBFactory* aFactory); + void + Disconnect(); + protected: virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; @@ -95,6 +102,9 @@ public: void SetRequest(IDBOpenDBRequest* aRequest); + void + Disconnect(); + protected: bool EnsureDatabase(IDBOpenDBRequest* aRequest, @@ -158,6 +168,9 @@ public: return mTransaction; } + void + Disconnect(); + protected: void FireCompleteEvent(nsresult aRv); @@ -188,6 +201,9 @@ public: IndexedDBObjectStoreChild(IDBObjectStore* aObjectStore); virtual ~IndexedDBObjectStoreChild(); + void + Disconnect(); + protected: virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; @@ -230,6 +246,9 @@ public: IndexedDBIndexChild(IDBIndex* aIndex); virtual ~IndexedDBIndexChild(); + void + Disconnect(); + protected: virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; @@ -276,6 +295,9 @@ public: return mStrongCursor.forget(); } + void + Disconnect(); + protected: virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; @@ -300,6 +322,9 @@ public: IDBRequest* GetRequest() const; + void + Disconnect(); + protected: IndexedDBRequestChildBase(AsyncConnectionHelper* aHelper); virtual ~IndexedDBRequestChildBase(); diff --git a/dom/indexedDB/ipc/IndexedDBParent.cpp b/dom/indexedDB/ipc/IndexedDBParent.cpp index 69b131abe6d0..963c9797b9d7 100644 --- a/dom/indexedDB/ipc/IndexedDBParent.cpp +++ b/dom/indexedDB/ipc/IndexedDBParent.cpp @@ -14,6 +14,7 @@ #include "mozilla/AppProcessPermissions.h" #include "mozilla/Assertions.h" +#include "mozilla/unused.h" #include "mozilla/Util.h" #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/TabParent.h" @@ -82,13 +83,14 @@ IndexedDBParent::~IndexedDBParent() void IndexedDBParent::Disconnect() { + MOZ_ASSERT(!mDisconnected); + mDisconnected = true; - const InfallibleTArray& dbs = + const InfallibleTArray& databases = ManagedPIndexedDBDatabaseParent(); - - for (uint32_t i = 0; i < dbs.Length(); ++i) { - static_cast(dbs[i])->Disconnect(); + for (uint32_t i = 0; i < databases.Length(); ++i) { + static_cast(databases[i])->Disconnect(); } } @@ -145,12 +147,19 @@ IndexedDBParent::RecvPIndexedDBDatabaseConstructor( const nsString& aName, const uint64_t& aVersion) { - MOZ_ASSERT(mFactory); - if (!CheckReadPermission(aName)) { return false; } + if (IsDisconnected()) { + // We're shutting down, ignore this request. + return true; + } + + if (!mFactory) { + return true; + } + nsRefPtr request; nsresult rv = mFactory->OpenCommon(aName, aVersion, false, nullptr, @@ -171,12 +180,19 @@ IndexedDBParent::RecvPIndexedDBDeleteDatabaseRequestConstructor( PIndexedDBDeleteDatabaseRequestParent* aActor, const nsString& aName) { - MOZ_ASSERT(mFactory); - if (!CheckWritePermission(aName)) { return false; } + if (IsDisconnected()) { + // We're shutting down, ignore this request. + return true; + } + + if (!mFactory) { + return true; + } + IndexedDBDeleteDatabaseRequestParent* actor = static_cast(aActor); @@ -196,11 +212,6 @@ PIndexedDBDatabaseParent* IndexedDBParent::AllocPIndexedDBDatabase(const nsString& aName, const uint64_t& aVersion) { - if (!mFactory) { - // This can happen if the child process dies before we set the factory. - return nullptr; - } - return new IndexedDBDatabaseParent(); } @@ -214,11 +225,6 @@ IndexedDBParent::DeallocPIndexedDBDatabase(PIndexedDBDatabaseParent* aActor) PIndexedDBDeleteDatabaseRequestParent* IndexedDBParent::AllocPIndexedDBDeleteDatabaseRequest(const nsString& aName) { - if (!mFactory) { - // This can happen if the child process dies before we set the factory. - return nullptr; - } - return new IndexedDBDeleteDatabaseRequestParent(mFactory); } @@ -278,8 +284,8 @@ IndexedDBDatabaseParent::HandleEvent(nsIDOMEvent* aEvent) { MOZ_ASSERT(aEvent); - if (Manager() && - static_cast(Manager())->IsDisconnected()) { + if (IsDisconnected()) { + // We're shutting down, ignore this event. return NS_OK; } @@ -317,7 +323,7 @@ void IndexedDBDatabaseParent::Disconnect() { if (mDatabase) { - mDatabase->DisconnectFromActor(); + mDatabase->DisconnectFromActorParent(); } } @@ -330,11 +336,22 @@ IndexedDBDatabaseParent::CheckWritePermission(const nsAString& aDatabaseName) return manager->CheckWritePermission(aDatabaseName); } +void +IndexedDBDatabaseParent::Invalidate() +{ + MOZ_ASSERT(mDatabase); + + if (!IsDisconnected()) { + mozilla::unused << SendInvalidate(); + } +} + nsresult IndexedDBDatabaseParent::HandleRequestEvent(nsIDOMEvent* aEvent, const nsAString& aType) { MOZ_ASSERT(mOpenRequest); + MOZ_ASSERT(!IsDisconnected()); nsresult rv; @@ -510,6 +527,7 @@ IndexedDBDatabaseParent::HandleDatabaseEvent(nsIDOMEvent* aEvent, MOZ_ASSERT(mDatabase); MOZ_ASSERT(!aType.EqualsLiteral(ERROR_EVT_STR), "Should never get error events in the parent process!"); + MOZ_ASSERT(!IsDisconnected()); nsresult rv; @@ -562,6 +580,11 @@ IndexedDBDatabaseParent::RecvClose(const bool& aUnlinked) { MOZ_ASSERT(mDatabase); + if (IsDisconnected()) { + // We're shutting down, ignore this request. + return true; + } + mDatabase->CloseInternal(aUnlinked); return true; } @@ -574,7 +597,15 @@ IndexedDBDatabaseParent::RecvPIndexedDBTransactionConstructor( MOZ_ASSERT(aParams.type() == TransactionParams::TNormalTransactionParams); MOZ_ASSERT(!mOpenRequest); - MOZ_ASSERT(mDatabase); + + if (IsDisconnected()) { + // We're shutting down, ignore this request. + return true; + } + + if (!mDatabase) { + return true; + } IndexedDBTransactionParent* actor = static_cast(aActor); @@ -586,6 +617,11 @@ IndexedDBDatabaseParent::RecvPIndexedDBTransactionConstructor( return false; } + if (mDatabase->IsClosed()) { + // If the window was navigated then we won't be able to do anything here. + return true; + } + nsTArray storesToOpen; storesToOpen.AppendElements(params.names()); @@ -603,11 +639,6 @@ PIndexedDBTransactionParent* IndexedDBDatabaseParent::AllocPIndexedDBTransaction( const TransactionParams& aParams) { - if (!mDatabase) { - // This can happen if the child process dies before we set the database. - return nullptr; - } - MOZ_ASSERT(aParams.type() == TransactionParams::TNormalTransactionParams); return new IndexedDBTransactionParent(); @@ -665,6 +696,13 @@ IndexedDBTransactionParent::SetTransaction(IDBTransaction* aTransaction) nsresult IndexedDBTransactionParent::HandleEvent(nsIDOMEvent* aEvent) { + MOZ_ASSERT(aEvent); + + if (IsDisconnected()) { + // We're shutting down, ignore this event. + return NS_OK; + } + nsString type; nsresult rv = aEvent->GetType(type); NS_ENSURE_SUCCESS(rv, rv); @@ -723,6 +761,12 @@ bool IndexedDBTransactionParent::RecvAbort(const nsresult& aAbortCode) { MOZ_ASSERT(mTransaction); + + if (IsDisconnected()) { + // We're shutting down, ignore this request. + return true; + } + mTransaction->Abort(aAbortCode); return true; } @@ -733,6 +777,11 @@ IndexedDBTransactionParent::RecvAllRequestsFinished() MOZ_ASSERT(mTransaction); MOZ_ASSERT(mArtificialRequestCount); + if (IsDisconnected()) { + // We're shutting down, ignore this request. + return true; + } + mTransaction->OnRequestFinished(); mArtificialRequestCount = false; @@ -751,7 +800,14 @@ IndexedDBTransactionParent::RecvPIndexedDBObjectStoreConstructor( PIndexedDBObjectStoreParent* aActor, const ObjectStoreConstructorParams& aParams) { - MOZ_ASSERT(mTransaction); + if (IsDisconnected()) { + // We're shutting down, ignore this request. + return true; + } + + if (!mTransaction) { + return true; + } IndexedDBObjectStoreParent* actor = static_cast(aActor); @@ -791,11 +847,6 @@ PIndexedDBObjectStoreParent* IndexedDBTransactionParent::AllocPIndexedDBObjectStore( const ObjectStoreConstructorParams& aParams) { - if (!mTransaction) { - // This can happen if the child process dies before we set the transaction. - return nullptr; - } - return new IndexedDBObjectStoreParent(); } @@ -827,7 +878,23 @@ bool IndexedDBVersionChangeTransactionParent::RecvDeleteObjectStore( const nsString& aName) { - MOZ_ASSERT(mTransaction->GetMode() == IDBTransaction::VERSION_CHANGE); + MOZ_ASSERT(!mTransaction || + mTransaction->GetMode() == IDBTransaction::VERSION_CHANGE); + + if (IsDisconnected()) { + // We're shutting down, ignore this request. + return true; + } + + if (!mTransaction) { + return true; + } + + if (mTransaction->Database()->IsInvalidated()) { + // If we've invalidated this database in the parent then we should bail out + // now to avoid logic problems that could force-kill the child. + return true; + } IDBDatabase* db = mTransaction->Database(); MOZ_ASSERT(db); @@ -850,7 +917,20 @@ IndexedDBVersionChangeTransactionParent::RecvPIndexedDBObjectStoreConstructor( PIndexedDBObjectStoreParent* aActor, const ObjectStoreConstructorParams& aParams) { - MOZ_ASSERT(mTransaction); + if (IsDisconnected()) { + // We're shutting down, ignore this request. + return true; + } + + if (!mTransaction) { + return true; + } + + if (mTransaction->Database()->IsInvalidated()) { + // If we've invalidated this database in the parent then we should bail out + // now to avoid logic problems that could force-kill the child. + return true; + } IndexedDBObjectStoreParent* actor = static_cast(aActor); @@ -894,11 +974,6 @@ PIndexedDBObjectStoreParent* IndexedDBVersionChangeTransactionParent::AllocPIndexedDBObjectStore( const ObjectStoreConstructorParams& aParams) { - if (!mTransaction) { - // This can happen if the child process dies before we set the transaction. - return nullptr; - } - if (aParams.type() == ObjectStoreConstructorParams::TCreateObjectStoreParams || mTransaction->GetMode() == IDBTransaction::VERSION_CHANGE) { @@ -908,6 +983,86 @@ IndexedDBVersionChangeTransactionParent::AllocPIndexedDBObjectStore( return IndexedDBTransactionParent::AllocPIndexedDBObjectStore(aParams); } +/******************************************************************************* + * IndexedDBCursorParent + ******************************************************************************/ + +IndexedDBCursorParent::IndexedDBCursorParent(IDBCursor* aCursor) +: mCursor(aCursor) +{ + MOZ_COUNT_CTOR(IndexedDBCursorParent); + MOZ_ASSERT(aCursor); + aCursor->SetActor(this); +} + +IndexedDBCursorParent::~IndexedDBCursorParent() +{ + MOZ_COUNT_DTOR(IndexedDBCursorParent); +} + +bool +IndexedDBCursorParent::IsDisconnected() const +{ + MOZ_ASSERT(mCursor); + return mCursor->Transaction()->GetActorParent()->IsDisconnected(); +} + +void +IndexedDBCursorParent::ActorDestroy(ActorDestroyReason aWhy) +{ + MOZ_ASSERT(mCursor); + mCursor->SetActor(static_cast(NULL)); +} + +bool +IndexedDBCursorParent::RecvPIndexedDBRequestConstructor( + PIndexedDBRequestParent* aActor, + const CursorRequestParams& aParams) +{ + MOZ_ASSERT(mCursor); + + if (IsDisconnected()) { + // We're shutting down, ignore this request. + return true; + } + + IndexedDBCursorRequestParent* actor = + static_cast(aActor); + + if (mCursor->Transaction()->Database()->IsInvalidated()) { + // If we've invalidated this database in the parent then we should bail out + // now to avoid logic problems that could force-kill the child. + return actor->Send__delete__(actor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + } + + switch (aParams.type()) { + case CursorRequestParams::TContinueParams: + return actor->Continue(aParams.get_ContinueParams()); + + default: + MOZ_NOT_REACHED("Unknown type!"); + return false; + } + + MOZ_NOT_REACHED("Should never get here!"); + return false; +} + +PIndexedDBRequestParent* +IndexedDBCursorParent::AllocPIndexedDBRequest( + const CursorRequestParams& aParams) +{ + MOZ_ASSERT(mCursor); + return new IndexedDBCursorRequestParent(mCursor, aParams.type()); +} + +bool +IndexedDBCursorParent::DeallocPIndexedDBRequest(PIndexedDBRequestParent* aActor) +{ + delete aActor; + return true; +} + /******************************************************************************* * IndexedDBObjectStoreParent ******************************************************************************/ @@ -925,7 +1080,7 @@ IndexedDBObjectStoreParent::~IndexedDBObjectStoreParent() void IndexedDBObjectStoreParent::SetObjectStore(IDBObjectStore* aObjectStore) { - MOZ_ASSERT(aObjectStore); + // Sadly can't assert aObjectStore here... MOZ_ASSERT(!mObjectStore); mObjectStore = aObjectStore; @@ -951,11 +1106,24 @@ IndexedDBObjectStoreParent::RecvPIndexedDBRequestConstructor( PIndexedDBRequestParent* aActor, const ObjectStoreRequestParams& aParams) { - MOZ_ASSERT(mObjectStore); + if (IsDisconnected()) { + // We're shutting down, ignore this request. + return true; + } + + if (!mObjectStore) { + return true; + } IndexedDBObjectStoreRequestParent* actor = static_cast(aActor); + if (mObjectStore->Transaction()->Database()->IsInvalidated()) { + // If we've invalidated this database in the parent then we should bail out + // now to avoid logic problems that could force-kill the child. + return actor->Send__delete__(actor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + } + switch (aParams.type()) { case ObjectStoreRequestParams::TGetParams: return actor->Get(aParams.get_GetParams()); @@ -995,7 +1163,14 @@ IndexedDBObjectStoreParent::RecvPIndexedDBIndexConstructor( PIndexedDBIndexParent* aActor, const IndexConstructorParams& aParams) { - MOZ_ASSERT(mObjectStore); + if (IsDisconnected()) { + // We're shutting down, ignore this request. + return true; + } + + if (!mObjectStore) { + return true; + } IndexedDBIndexParent* actor = static_cast(aActor); @@ -1031,11 +1206,6 @@ PIndexedDBRequestParent* IndexedDBObjectStoreParent::AllocPIndexedDBRequest( const ObjectStoreRequestParams& aParams) { - if (!mObjectStore) { - // This can happen if the child process dies before we set the objectStore. - return nullptr; - } - return new IndexedDBObjectStoreRequestParent(mObjectStore, aParams.type()); } @@ -1051,11 +1221,6 @@ PIndexedDBIndexParent* IndexedDBObjectStoreParent::AllocPIndexedDBIndex( const IndexConstructorParams& aParams) { - if (!mObjectStore) { - // This can happen if the child process dies before we set the objectStore. - return nullptr; - } - return new IndexedDBIndexParent(); } @@ -1102,9 +1267,25 @@ IndexedDBVersionChangeObjectStoreParent:: bool IndexedDBVersionChangeObjectStoreParent::RecvDeleteIndex(const nsString& aName) { - MOZ_ASSERT(mObjectStore->Transaction()->GetMode() == + MOZ_ASSERT(!mObjectStore || + mObjectStore->Transaction()->GetMode() == IDBTransaction::VERSION_CHANGE); + if (IsDisconnected()) { + // We're shutting down, ignore this request. + return true; + } + + if (!mObjectStore) { + return true; + } + + if (mObjectStore->Transaction()->Database()->IsInvalidated()) { + // If we've invalidated this database in the parent then we should bail out + // now to avoid logic problems that could force-kill the child. + return true; + } + nsresult rv; { @@ -1123,7 +1304,20 @@ IndexedDBVersionChangeObjectStoreParent::RecvPIndexedDBIndexConstructor( PIndexedDBIndexParent* aActor, const IndexConstructorParams& aParams) { - MOZ_ASSERT(mObjectStore); + if (IsDisconnected()) { + // We're shutting down, ignore this request. + return true; + } + + if (!mObjectStore) { + return true; + } + + if (mObjectStore->Transaction()->Database()->IsInvalidated()) { + // If we've invalidated this database in the parent then we should bail out + // now to avoid logic problems that could force-kill the child. + return true; + } IndexedDBIndexParent* actor = static_cast(aActor); @@ -1191,11 +1385,24 @@ IndexedDBIndexParent::RecvPIndexedDBRequestConstructor( PIndexedDBRequestParent* aActor, const IndexRequestParams& aParams) { - MOZ_ASSERT(mIndex); + if (IsDisconnected()) { + // We're shutting down, ignore this request. + return true; + } + + if (!mIndex) { + return true; + } IndexedDBIndexRequestParent* actor = static_cast(aActor); + if (mIndex->ObjectStore()->Transaction()->Database()->IsInvalidated()) { + // If we've invalidated this database in the parent then we should bail out + // now to avoid logic problems that could force-kill the child. + return actor->Send__delete__(actor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + } + switch (aParams.type()) { case IndexRequestParams::TGetParams: return actor->Get(aParams.get_GetParams()); @@ -1230,11 +1437,6 @@ IndexedDBIndexParent::RecvPIndexedDBRequestConstructor( PIndexedDBRequestParent* IndexedDBIndexParent::AllocPIndexedDBRequest(const IndexRequestParams& aParams) { - if (!mIndex) { - // This can happen if the child process dies before we set the index. - return nullptr; - } - return new IndexedDBIndexRequestParent(mIndex, aParams.type()); } @@ -1260,68 +1462,6 @@ IndexedDBIndexParent::DeallocPIndexedDBCursor(PIndexedDBCursorParent* aActor) return true; } -/******************************************************************************* - * IndexedDBCursorParent - ******************************************************************************/ - -IndexedDBCursorParent::IndexedDBCursorParent(IDBCursor* aCursor) -: mCursor(aCursor) -{ - MOZ_COUNT_CTOR(IndexedDBCursorParent); - MOZ_ASSERT(aCursor); - aCursor->SetActor(this); -} - -IndexedDBCursorParent::~IndexedDBCursorParent() -{ - MOZ_COUNT_DTOR(IndexedDBCursorParent); -} - -void -IndexedDBCursorParent::ActorDestroy(ActorDestroyReason aWhy) -{ - MOZ_ASSERT(mCursor); - mCursor->SetActor(static_cast(NULL)); -} - -bool -IndexedDBCursorParent::RecvPIndexedDBRequestConstructor( - PIndexedDBRequestParent* aActor, - const CursorRequestParams& aParams) -{ - MOZ_ASSERT(mCursor); - - IndexedDBCursorRequestParent* actor = - static_cast(aActor); - - switch (aParams.type()) { - case CursorRequestParams::TContinueParams: - return actor->Continue(aParams.get_ContinueParams()); - - default: - MOZ_NOT_REACHED("Unknown type!"); - return false; - } - - MOZ_NOT_REACHED("Should never get here!"); - return false; -} - -PIndexedDBRequestParent* -IndexedDBCursorParent::AllocPIndexedDBRequest( - const CursorRequestParams& aParams) -{ - MOZ_ASSERT(mCursor); - return new IndexedDBCursorRequestParent(mCursor, aParams.type()); -} - -bool -IndexedDBCursorParent::DeallocPIndexedDBRequest(PIndexedDBRequestParent* aActor) -{ - delete aActor; - return true; -} - /******************************************************************************* * IndexedDBRequestParentBase ******************************************************************************/ @@ -1354,7 +1494,7 @@ IndexedDBObjectStoreRequestParent::IndexedDBObjectStoreRequestParent( : mObjectStore(aObjectStore), mRequestType(aRequestType) { MOZ_COUNT_CTOR(IndexedDBObjectStoreRequestParent); - MOZ_ASSERT(aObjectStore); + // Sadly can't assert aObjectStore here... MOZ_ASSERT(aRequestType > ParamsUnionType::T__None && aRequestType <= ParamsUnionType::T__Last); } @@ -1370,6 +1510,7 @@ IndexedDBObjectStoreRequestParent::ConvertBlobActors( nsTArray >& aBlobs) { MOZ_ASSERT(aBlobs.IsEmpty()); + MOZ_ASSERT(mObjectStore); if (!aActors.IsEmpty()) { // Walk the chain to get to ContentParent. @@ -1385,10 +1526,19 @@ IndexedDBObjectStoreRequestParent::ConvertBlobActors( } } +bool +IndexedDBObjectStoreRequestParent::IsDisconnected() +{ + MOZ_ASSERT(mObjectStore); + MOZ_ASSERT(mObjectStore->GetActorParent()); + return mObjectStore->GetActorParent()->IsDisconnected(); +} + bool IndexedDBObjectStoreRequestParent::Get(const GetParams& aParams) { MOZ_ASSERT(mRequestType == ParamsUnionType::TGetParams); + MOZ_ASSERT(mObjectStore); nsRefPtr request; @@ -1406,6 +1556,7 @@ IndexedDBObjectStoreRequestParent::Get(const GetParams& aParams) request->SetActor(this); mRequest.swap(request); + return true; } @@ -1413,6 +1564,7 @@ bool IndexedDBObjectStoreRequestParent::GetAll(const GetAllParams& aParams) { MOZ_ASSERT(mRequestType == ParamsUnionType::TGetAllParams); + MOZ_ASSERT(mObjectStore); nsRefPtr request; @@ -1453,6 +1605,7 @@ bool IndexedDBObjectStoreRequestParent::Add(const AddParams& aParams) { MOZ_ASSERT(mRequestType == ParamsUnionType::TAddParams); + MOZ_ASSERT(mObjectStore); ipc::AddPutParams params = aParams.commonParams(); @@ -1480,6 +1633,7 @@ bool IndexedDBObjectStoreRequestParent::Put(const PutParams& aParams) { MOZ_ASSERT(mRequestType == ParamsUnionType::TPutParams); + MOZ_ASSERT(mObjectStore); ipc::AddPutParams params = aParams.commonParams(); @@ -1507,6 +1661,7 @@ bool IndexedDBObjectStoreRequestParent::Delete(const DeleteParams& aParams) { MOZ_ASSERT(mRequestType == ParamsUnionType::TDeleteParams); + MOZ_ASSERT(mObjectStore); nsRefPtr request; @@ -1531,6 +1686,7 @@ bool IndexedDBObjectStoreRequestParent::Clear(const ClearParams& aParams) { MOZ_ASSERT(mRequestType == ParamsUnionType::TClearParams); + MOZ_ASSERT(mObjectStore); nsRefPtr request; @@ -1550,6 +1706,7 @@ bool IndexedDBObjectStoreRequestParent::Count(const CountParams& aParams) { MOZ_ASSERT(mRequestType == ParamsUnionType::TCountParams); + MOZ_ASSERT(mObjectStore); const ipc::FIXME_Bug_521898_objectstore::OptionalKeyRange keyRangeUnion = aParams.optionalKeyRange(); @@ -1589,6 +1746,7 @@ bool IndexedDBObjectStoreRequestParent::OpenCursor(const OpenCursorParams& aParams) { MOZ_ASSERT(mRequestType == ParamsUnionType::TOpenCursorParams); + MOZ_ASSERT(mObjectStore); const ipc::FIXME_Bug_521898_objectstore::OptionalKeyRange keyRangeUnion = aParams.optionalKeyRange(); @@ -1637,7 +1795,7 @@ IndexedDBIndexRequestParent::IndexedDBIndexRequestParent( : mIndex(aIndex), mRequestType(aRequestType) { MOZ_COUNT_CTOR(IndexedDBIndexRequestParent); - MOZ_ASSERT(aIndex); + // Sadly can't assert aIndex here... MOZ_ASSERT(aRequestType > ParamsUnionType::T__None && aRequestType <= ParamsUnionType::T__Last); } @@ -1647,10 +1805,19 @@ IndexedDBIndexRequestParent::~IndexedDBIndexRequestParent() MOZ_COUNT_DTOR(IndexedDBIndexRequestParent); } +bool +IndexedDBIndexRequestParent::IsDisconnected() +{ + MOZ_ASSERT(mIndex); + MOZ_ASSERT(mIndex->GetActorParent()); + return mIndex->GetActorParent()->IsDisconnected(); +} + bool IndexedDBIndexRequestParent::Get(const GetParams& aParams) { MOZ_ASSERT(mRequestType == ParamsUnionType::TGetParams); + MOZ_ASSERT(mIndex); nsRefPtr request; @@ -1675,6 +1842,7 @@ bool IndexedDBIndexRequestParent::GetKey(const GetKeyParams& aParams) { MOZ_ASSERT(mRequestType == ParamsUnionType::TGetKeyParams); + MOZ_ASSERT(mIndex); nsRefPtr request; @@ -1699,6 +1867,7 @@ bool IndexedDBIndexRequestParent::GetAll(const GetAllParams& aParams) { MOZ_ASSERT(mRequestType == ParamsUnionType::TGetAllParams); + MOZ_ASSERT(mIndex); nsRefPtr request; @@ -1738,6 +1907,7 @@ bool IndexedDBIndexRequestParent::GetAllKeys(const GetAllKeysParams& aParams) { MOZ_ASSERT(mRequestType == ParamsUnionType::TGetAllKeysParams); + MOZ_ASSERT(mIndex); nsRefPtr request; @@ -1777,6 +1947,7 @@ bool IndexedDBIndexRequestParent::Count(const CountParams& aParams) { MOZ_ASSERT(mRequestType == ParamsUnionType::TCountParams); + MOZ_ASSERT(mIndex); const ipc::FIXME_Bug_521898_index::OptionalKeyRange keyRangeUnion = aParams.optionalKeyRange(); @@ -1816,6 +1987,7 @@ bool IndexedDBIndexRequestParent::OpenCursor(const OpenCursorParams& aParams) { MOZ_ASSERT(mRequestType == ParamsUnionType::TOpenCursorParams); + MOZ_ASSERT(mIndex); const ipc::FIXME_Bug_521898_index::OptionalKeyRange keyRangeUnion = aParams.optionalKeyRange(); @@ -1858,6 +2030,7 @@ bool IndexedDBIndexRequestParent::OpenKeyCursor(const OpenKeyCursorParams& aParams) { MOZ_ASSERT(mRequestType == ParamsUnionType::TOpenKeyCursorParams); + MOZ_ASSERT(mIndex); const ipc::FIXME_Bug_521898_index::OptionalKeyRange keyRangeUnion = aParams.optionalKeyRange(); @@ -1916,9 +2089,18 @@ IndexedDBCursorRequestParent::~IndexedDBCursorRequestParent() MOZ_COUNT_DTOR(IndexedDBCursorRequestParent); } +bool +IndexedDBCursorRequestParent::IsDisconnected() +{ + MOZ_ASSERT(mCursor); + MOZ_ASSERT(mCursor->GetActorParent()); + return mCursor->GetActorParent()->IsDisconnected(); +} + bool IndexedDBCursorRequestParent::Continue(const ContinueParams& aParams) { + MOZ_ASSERT(mCursor); MOZ_ASSERT(mRequestType == ParamsUnionType::TContinueParams); { @@ -1955,13 +2137,13 @@ IndexedDBDeleteDatabaseRequestParent::~IndexedDBDeleteDatabaseRequestParent() nsresult IndexedDBDeleteDatabaseRequestParent::HandleEvent(nsIDOMEvent* aEvent) { - if (Manager() && - static_cast(Manager())->IsDisconnected()) { + MOZ_ASSERT(aEvent); + + if (IsDisconnected()) { + // We're shutting down, ignore this event. return NS_OK; } - MOZ_ASSERT(aEvent); - nsString type; nsresult rv = aEvent->GetType(type); NS_ENSURE_SUCCESS(rv, rv); diff --git a/dom/indexedDB/ipc/IndexedDBParent.h b/dom/indexedDB/ipc/IndexedDBParent.h index a6d1fb2c36d0..a3f81c8fcbb4 100644 --- a/dom/indexedDB/ipc/IndexedDBParent.h +++ b/dom/indexedDB/ipc/IndexedDBParent.h @@ -41,6 +41,15 @@ class IDBObjectStore; class IDBOpenDBRequest; class IDBTransaction; +class IndexedDBCursorParent; +class IndexedDBDatabaseParent; +class IndexedDBDeleteDatabaseRequestParent; +class IndexedDBIndexParent; +class IndexedDBObjectStoreParent; +class IndexedDBTransactionParent; +class IndexedDBVersionChangeTransactionParent; +class IndexedDBVersionChangeObjectStoreParent; + /******************************************************************************* * AutoSetCurrentTransaction ******************************************************************************/ @@ -130,10 +139,12 @@ public: * IndexedDBParent ******************************************************************************/ -class IndexedDBParent : public PIndexedDBParent +class IndexedDBParent : private PIndexedDBParent { friend class mozilla::dom::ContentParent; friend class mozilla::dom::TabParent; + friend class IndexedDBDatabaseParent; + friend class IndexedDBDeleteDatabaseRequestParent; nsRefPtr mFactory; nsCString mASCIIOrigin; @@ -220,8 +231,12 @@ protected: * IndexedDBDatabaseParent ******************************************************************************/ -class IndexedDBDatabaseParent : public PIndexedDBDatabaseParent +class IndexedDBDatabaseParent : private PIndexedDBDatabaseParent { + friend class IndexedDBParent; + friend class IndexedDBTransactionParent; + friend class IndexedDBVersionChangeTransactionParent; + AutoWeakEventListener mEventListener; nsRefPtr mOpenRequest; @@ -240,9 +255,18 @@ public: void Disconnect(); + bool + IsDisconnected() const + { + return static_cast(Manager())->IsDisconnected(); + } + bool CheckWritePermission(const nsAString& aDatabaseName); + void + Invalidate(); + protected: nsresult HandleRequestEvent(nsIDOMEvent* aEvent, const nsAString& aType); @@ -273,8 +297,12 @@ protected: * IndexedDBTransactionParent ******************************************************************************/ -class IndexedDBTransactionParent : public PIndexedDBTransactionParent +class IndexedDBTransactionParent : protected PIndexedDBTransactionParent { + friend class IndexedDBCursorParent; + friend class IndexedDBDatabaseParent; + friend class IndexedDBObjectStoreParent; + protected: AutoWeakEventListener mEventListener; @@ -286,6 +314,12 @@ public: IndexedDBTransactionParent(); virtual ~IndexedDBTransactionParent(); + bool + IsDisconnected() const + { + return static_cast(Manager())->IsDisconnected(); + } + nsresult SetTransaction(IDBTransaction* aTransaction); @@ -333,10 +367,18 @@ protected: class IndexedDBVersionChangeTransactionParent : public IndexedDBTransactionParent { + friend class IndexedDBVersionChangeObjectStoreParent; + public: IndexedDBVersionChangeTransactionParent(); virtual ~IndexedDBVersionChangeTransactionParent(); + bool + IsDisconnected() const + { + return static_cast(Manager())->IsDisconnected(); + } + protected: virtual bool RecvDeleteObjectStore(const nsString& aName) MOZ_OVERRIDE; @@ -352,12 +394,58 @@ protected: MOZ_OVERRIDE; }; +/******************************************************************************* + * IndexedDBCursorParent + ******************************************************************************/ + +class IndexedDBCursorParent : private PIndexedDBCursorParent +{ + friend class IndexedDBIndexParent; + friend class IndexedDBObjectStoreParent; + + nsRefPtr mCursor; + +public: + IDBCursor* + GetCursor() const + { + return mCursor; + } + + bool + IsDisconnected() const; + +protected: + IndexedDBCursorParent(IDBCursor* aCursor); + virtual ~IndexedDBCursorParent(); + + virtual void + ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; + + virtual bool + RecvPIndexedDBRequestConstructor(PIndexedDBRequestParent* aActor, + const CursorRequestParams& aParams) + MOZ_OVERRIDE; + + virtual PIndexedDBRequestParent* + AllocPIndexedDBRequest(const CursorRequestParams& aParams) MOZ_OVERRIDE; + + virtual bool + DeallocPIndexedDBRequest(PIndexedDBRequestParent* aActor) MOZ_OVERRIDE; +}; + /******************************************************************************* * IndexedDBObjectStoreParent ******************************************************************************/ -class IndexedDBObjectStoreParent : public PIndexedDBObjectStoreParent +class IndexedDBObjectStoreParent : protected PIndexedDBObjectStoreParent { + friend class IndexedDBIndexParent; + friend class IndexedDBTransactionParent; + friend class IndexedDBVersionChangeTransactionParent; + + typedef mozilla::dom::indexedDB::ipc::OpenCursorResponse OpenCursorResponse; + protected: nsRefPtr mObjectStore; @@ -374,6 +462,38 @@ public: return mObjectStore; } + bool + IsDisconnected() const + { + IndexedDBTransactionParent* manager = + static_cast(Manager()); + return manager->IsDisconnected(); + } + + // Ordinarily callers could just do this manually using + // PIndexedDBObjectStoreParent::SendPIndexedDBCursorConstructor but we're + // inheriting the abstract protocol class privately to prevent outside code + // from sending messages without checking the disconnected state. Therefore + // we need a helper method. + bool + OpenCursor(IDBCursor* aCursor, + const ObjectStoreCursorConstructorParams& aParams, + OpenCursorResponse& aResponse) NS_WARN_UNUSED_RESULT + { + if (IsDisconnected()) { + return true; + } + + IndexedDBCursorParent* cursorActor = new IndexedDBCursorParent(aCursor); + + if (!SendPIndexedDBCursorConstructor(cursorActor, aParams)) { + return false; + } + + aResponse = cursorActor; + return true; + } + protected: virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; @@ -418,11 +538,21 @@ protected: class IndexedDBVersionChangeObjectStoreParent : public IndexedDBObjectStoreParent { + friend class IndexedDBVersionChangeTransactionParent; + public: IndexedDBVersionChangeObjectStoreParent(); virtual ~IndexedDBVersionChangeObjectStoreParent(); protected: + bool + IsDisconnected() const + { + IndexedDBVersionChangeTransactionParent* manager = + static_cast(Manager()); + return manager->IsDisconnected(); + } + virtual bool RecvDeleteIndex(const nsString& aName) MOZ_OVERRIDE; @@ -436,8 +566,13 @@ protected: * IndexedDBIndexParent ******************************************************************************/ -class IndexedDBIndexParent : public PIndexedDBIndexParent +class IndexedDBIndexParent : private PIndexedDBIndexParent { + friend class IndexedDBObjectStoreParent; + friend class IndexedDBVersionChangeObjectStoreParent; + + typedef mozilla::dom::indexedDB::ipc::OpenCursorResponse OpenCursorResponse; + nsRefPtr mIndex; public: @@ -453,6 +588,37 @@ public: return mIndex; } + // Ordinarily callers could just do this manually using + // PIndexedDBIndexParent::SendPIndexedDBCursorConstructor but we're + // inheriting the abstract protocol class privately to prevent outside code + // from sending messages without checking the disconnected state. Therefore + // we need a helper method. + bool + OpenCursor(IDBCursor* aCursor, const IndexCursorConstructorParams& aParams, + OpenCursorResponse& aResponse) NS_WARN_UNUSED_RESULT + { + if (IsDisconnected()) { + return true; + } + + IndexedDBCursorParent* cursorActor = new IndexedDBCursorParent(aCursor); + + if (!SendPIndexedDBCursorConstructor(cursorActor, aParams)) { + return false; + } + + aResponse = cursorActor; + return true; + } + + bool + IsDisconnected() const + { + IndexedDBObjectStoreParent* manager = + static_cast(Manager()); + return manager->IsDisconnected(); + } + protected: virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; @@ -476,48 +642,29 @@ protected: DeallocPIndexedDBCursor(PIndexedDBCursorParent* aActor) MOZ_OVERRIDE; }; -/******************************************************************************* - * IndexedDBCursorParent - ******************************************************************************/ - -class IndexedDBCursorParent : public PIndexedDBCursorParent -{ - nsRefPtr mCursor; - -public: - IndexedDBCursorParent(IDBCursor* aCursor); - virtual ~IndexedDBCursorParent(); - - IDBCursor* - GetCursor() const - { - return mCursor; - } - -protected: - virtual void - ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; - - virtual bool - RecvPIndexedDBRequestConstructor(PIndexedDBRequestParent* aActor, - const CursorRequestParams& aParams) - MOZ_OVERRIDE; - - virtual PIndexedDBRequestParent* - AllocPIndexedDBRequest(const CursorRequestParams& aParams) MOZ_OVERRIDE; - - virtual bool - DeallocPIndexedDBRequest(PIndexedDBRequestParent* aActor) MOZ_OVERRIDE; -}; - /******************************************************************************* * IndexedDBRequestParentBase ******************************************************************************/ class IndexedDBRequestParentBase : public PIndexedDBRequestParent { +public: + bool + SendResponse(const ResponseValue& aResponse) NS_WARN_UNUSED_RESULT + { + if (IsDisconnected()) { + return true; + } + + return Send__delete__(this, aResponse); + } + protected: + // Don't let anyone call this directly, instead go through SendResponse. + using PIndexedDBRequestParent::Send__delete__; + typedef ipc::ResponseValue ResponseValue; + typedef PIndexedDBRequestParent::PBlobParent PBlobParent; nsRefPtr mRequest; @@ -526,6 +673,9 @@ protected: virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; + + virtual bool + IsDisconnected() = 0; }; /******************************************************************************* @@ -534,6 +684,8 @@ protected: class IndexedDBObjectStoreRequestParent : public IndexedDBRequestParentBase { + friend class IndexedDBObjectStoreParent; + nsRefPtr mObjectStore; typedef ipc::ObjectStoreRequestParams ParamsUnionType; @@ -582,6 +734,10 @@ protected: void ConvertBlobActors(const InfallibleTArray& aActors, nsTArray >& aBlobs); + +private: + virtual bool + IsDisconnected() MOZ_OVERRIDE; }; /******************************************************************************* @@ -590,6 +746,8 @@ protected: class IndexedDBIndexRequestParent : public IndexedDBRequestParentBase { + friend class IndexedDBIndexParent; + nsRefPtr mIndex; typedef ipc::IndexRequestParams ParamsUnionType; @@ -628,6 +786,10 @@ public: bool OpenKeyCursor(const OpenKeyCursorParams& aParams); + +private: + virtual bool + IsDisconnected() MOZ_OVERRIDE; }; /******************************************************************************* @@ -636,6 +798,8 @@ public: class IndexedDBCursorRequestParent : public IndexedDBRequestParentBase { + friend class IndexedDBCursorParent; + nsRefPtr mCursor; typedef ipc::CursorRequestParams ParamsUnionType; @@ -650,6 +814,10 @@ public: bool Continue(const ContinueParams& aParams); + +private: + virtual bool + IsDisconnected() MOZ_OVERRIDE; }; /******************************************************************************* @@ -657,25 +825,33 @@ public: ******************************************************************************/ class IndexedDBDeleteDatabaseRequestParent : - public PIndexedDBDeleteDatabaseRequestParent + private PIndexedDBDeleteDatabaseRequestParent { + friend class IndexedDBParent; + AutoWeakEventListener mEventListener; nsRefPtr mFactory; nsRefPtr mOpenRequest; public: + nsresult + HandleEvent(nsIDOMEvent* aEvent); + +protected: IndexedDBDeleteDatabaseRequestParent(IDBFactory* aFactory); virtual ~IndexedDBDeleteDatabaseRequestParent(); nsresult SetOpenRequest(IDBOpenDBRequest* aOpenRequest); - nsresult - HandleEvent(nsIDOMEvent* aEvent); + bool + IsDisconnected() const + { + return static_cast(Manager())->IsDisconnected(); + } }; - END_INDEXEDDB_NAMESPACE #endif // mozilla_dom_indexeddb_ipc_indexeddbparent_h__ diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index e18ba03e7cda..e4c0abc770d6 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -1648,6 +1648,12 @@ TabChild::RecvDestroy() observerService->RemoveObserver(this, BROWSER_ZOOM_TO_RECT); observerService->RemoveObserver(this, BEFORE_FIRST_PAINT); + const InfallibleTArray& idbActors = + ManagedPIndexedDBChild(); + for (uint32_t i = 0; i < idbActors.Length(); ++i) { + static_cast(idbActors[i])->Disconnect(); + } + // XXX what other code in ~TabChild() should we be running here? DestroyWindow(); diff --git a/ipc/chromium/src/chrome/common/ipc_channel_win.cc b/ipc/chromium/src/chrome/common/ipc_channel_win.cc index 85ad6b42db3c..746eef129497 100644 --- a/ipc/chromium/src/chrome/common/ipc_channel_win.cc +++ b/ipc/chromium/src/chrome/common/ipc_channel_win.cc @@ -107,7 +107,9 @@ void Channel::ChannelImpl::Close() { } bool Channel::ChannelImpl::Send(Message* message) { - DCHECK(thread_check_->CalledOnValidThread()); + if (thread_check_.get()) { + DCHECK(thread_check_->CalledOnValidThread()); + } chrome::Counters::ipc_send_counter().Increment(); #ifdef IPC_MESSAGE_DEBUG_EXTRA DLOG(INFO) << "sending message @" << message << " on channel @" << this diff --git a/ipc/ipdl/ipdl/lower.py b/ipc/ipdl/ipdl/lower.py index eab964b8d16e..dd62fad0a654 100644 --- a/ipc/ipdl/ipdl/lower.py +++ b/ipc/ipdl/ipdl/lower.py @@ -2855,10 +2855,10 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor): if not ptype.isToplevel(): if 1 == len(p.managers): - ## manager() + ## manager() const managertype = p.managerActorType(self.side, ptr=1) managermeth = MethodDefn(MethodDecl( - p.managerMethod().name, ret=managertype)) + p.managerMethod().name, ret=managertype, const=1)) managermeth.addstmt(StmtReturn( ExprCast(p.managerVar(), managertype, static=1)))