diff --git a/content/base/public/nsIMessageManager.idl b/content/base/public/nsIMessageManager.idl index eae400a1b5e7..766f8aacedf7 100644 --- a/content/base/public/nsIMessageManager.idl +++ b/content/base/public/nsIMessageManager.idl @@ -335,3 +335,30 @@ interface nsIFrameScriptLoader : nsISupports */ void removeDelayedFrameScript(in AString aURL); }; + +[scriptable, builtinclass, uuid(5f552699-01a2-4f17-833b-ddb3fa0d98b2)] +interface nsIPermissionChecker : nsISupports +{ + + /** + * Return true iff the "remote" process has |aPermission|. This is + * intended to be used by JS implementations of cross-process DOM + * APIs, like so + * + * recvFooRequest: function(message) { + * if (!message.target.assertPermission("foo")) { + * return false; + * } + * // service foo request + * + * This interface only returns meaningful data when our content is + * in a separate process. If it shares the same OS process as us, + * then applying this permission check doesn't add any security, + * though it doesn't hurt anything either. + * + * Note: If the remote content process does *not* have |aPermission|, + * it will be killed as a precaution. + */ + boolean assertPermission(in DOMString aPermission); + +}; diff --git a/content/base/src/nsCCUncollectableMarker.cpp b/content/base/src/nsCCUncollectableMarker.cpp index b7a9b6234acb..3eb1c7268815 100644 --- a/content/base/src/nsCCUncollectableMarker.cpp +++ b/content/base/src/nsCCUncollectableMarker.cpp @@ -120,11 +120,11 @@ MarkMessageManagers() nsCOMPtr tabMM = do_QueryInterface(childMM); tabMM->MarkForCC(); //XXX hack warning, but works, since we know that - // callback data is frameloader. - void* cb = static_cast(tabMM.get())-> - GetCallbackData(); - nsFrameLoader* fl = static_cast(cb); - if (fl) { + // callback is frameloader. + mozilla::dom::ipc::MessageManagerCallback* cb = + static_cast(tabMM.get())->GetCallback(); + if (cb) { + nsFrameLoader* fl = static_cast(cb); nsIDOMEventTarget* et = fl->GetTabChildGlobalAsEventTarget(); if (!et) { continue; diff --git a/content/base/src/nsFrameLoader.cpp b/content/base/src/nsFrameLoader.cpp index 781da57574eb..9e3d12c9d25e 100644 --- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -76,6 +76,7 @@ #include "Layers.h" +#include "AppProcessPermissions.h" #include "ContentParent.h" #include "TabParent.h" #include "mozilla/GuardObjects.h" @@ -97,6 +98,7 @@ using namespace mozilla; using namespace mozilla::dom; +using namespace mozilla::dom::ipc; using namespace mozilla::layers; using namespace mozilla::layout; typedef FrameMetrics::ViewID ViewID; @@ -1242,13 +1244,13 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther, mMessageManager->RemoveFromParent(); mMessageManager->SetJSContext(otherCx); mMessageManager->SetParentManager(otherParentManager); - mMessageManager->SetCallbackData(aOther, false); + mMessageManager->SetCallback(aOther, false); } if (aOther->mMessageManager) { aOther->mMessageManager->RemoveFromParent(); aOther->mMessageManager->SetJSContext(thisCx); aOther->mMessageManager->SetParentManager(ourParentManager); - aOther->mMessageManager->SetCallbackData(this, false); + aOther->mMessageManager->SetCallback(this, false); } mMessageManager.swap(aOther->mMessageManager); @@ -2135,16 +2137,15 @@ nsFrameLoader::CreateStaticClone(nsIFrameLoader* aDest) return NS_OK; } -bool LoadScript(void* aCallbackData, const nsAString& aURL) +bool +nsFrameLoader::DoLoadFrameScript(const nsAString& aURL) { - mozilla::dom::PBrowserParent* tabParent = - static_cast(aCallbackData)->GetRemoteBrowser(); + mozilla::dom::PBrowserParent* tabParent = GetRemoteBrowser(); if (tabParent) { return tabParent->SendLoadRemoteScript(nsString(aURL)); } - nsFrameLoader* fl = static_cast(aCallbackData); nsRefPtr tabChild = - static_cast(fl->GetTabChildGlobalAsEventTarget()); + static_cast(GetTabChildGlobalAsEventTarget()); if (tabChild) { tabChild->LoadFrameScript(aURL); } @@ -2155,8 +2156,8 @@ class nsAsyncMessageToChild : public nsRunnable { public: nsAsyncMessageToChild(nsFrameLoader* aFrameLoader, - const nsAString& aMessage, - const StructuredCloneData& aData) + const nsAString& aMessage, + const StructuredCloneData& aData) : mFrameLoader(aFrameLoader), mMessage(aMessage) { if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) { @@ -2189,12 +2190,11 @@ public: StructuredCloneClosure mClosure; }; -bool SendAsyncMessageToChild(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData) +bool +nsFrameLoader::DoSendAsyncMessage(const nsAString& aMessage, + const StructuredCloneData& aData) { - PBrowserParent* tabParent = - static_cast(aCallbackData)->GetRemoteBrowser(); + PBrowserParent* tabParent = GetRemoteBrowser(); if (tabParent) { ClonedMessageData data; @@ -2224,10 +2224,8 @@ bool SendAsyncMessageToChild(void* aCallbackData, return tabParent->SendAsyncMessage(nsString(aMessage), data); } - if (static_cast(aCallbackData)->mChildMessageManager) { - nsRefPtr ev = - new nsAsyncMessageToChild(static_cast(aCallbackData), - aMessage, aData); + if (mChildMessageManager) { + nsRefPtr ev = new nsAsyncMessageToChild(this, aMessage, aData); NS_DispatchToCurrentThread(ev); return true; } @@ -2236,6 +2234,13 @@ bool SendAsyncMessageToChild(void* aCallbackData, return false; } +bool +nsFrameLoader::CheckPermission(const nsAString& aPermission) +{ + return AssertAppProcessPermission(GetRemoteBrowser(), + NS_ConvertUTF16toUTF8(aPermission).get()); +} + NS_IMETHODIMP nsFrameLoader::GetMessageManager(nsIMessageSender** aManager) { @@ -2316,7 +2321,7 @@ nsFrameLoader::EnsureMessageManager() if (mMessageManager) { if (ShouldUseRemoteProcess()) { - mMessageManager->SetCallbackData(mRemoteBrowserShown ? this : nullptr); + mMessageManager->SetCallback(mRemoteBrowserShown ? this : nullptr); } return NS_OK; } @@ -2335,24 +2340,20 @@ nsFrameLoader::EnsureMessageManager() } if (ShouldUseRemoteProcess()) { - mMessageManager = new nsFrameMessageManager(true, /* aChrome */ - nullptr, - SendAsyncMessageToChild, - LoadScript, - mRemoteBrowserShown ? this : nullptr, + mMessageManager = new nsFrameMessageManager(mRemoteBrowserShown ? this : nullptr, static_cast(parentManager.get()), - cx); + cx, + MM_CHROME); } else { - mMessageManager = new nsFrameMessageManager(true, /* aChrome */ - nullptr, - SendAsyncMessageToChild, - LoadScript, - nullptr, + mMessageManager = new nsFrameMessageManager(nullptr, static_cast(parentManager.get()), - cx); + cx, + MM_CHROME); + mChildMessageManager = new nsInProcessTabChildGlobal(mDocShell, mOwnerContent, mMessageManager); - mMessageManager->SetCallbackData(this); + // Force pending frame scripts to be loaded. + mMessageManager->SetCallback(this); } return NS_OK; } diff --git a/content/base/src/nsFrameLoader.h b/content/base/src/nsFrameLoader.h index 32cd360ce7fd..017477598804 100644 --- a/content/base/src/nsFrameLoader.h +++ b/content/base/src/nsFrameLoader.h @@ -38,6 +38,7 @@ namespace mozilla { namespace dom { class PBrowserParent; class TabParent; +struct StructuredCloneData; } namespace layout { @@ -140,7 +141,8 @@ private: class nsFrameLoader MOZ_FINAL : public nsIFrameLoader, public nsIContentViewManager, - public nsStubMutationObserver + public nsStubMutationObserver, + public mozilla::dom::ipc::MessageManagerCallback { friend class AutoResetInShow; typedef mozilla::dom::PBrowserParent PBrowserParent; @@ -179,6 +181,15 @@ public: nsIDOMEventTarget* GetTabChildGlobalAsEventTarget(); nsresult CreateStaticClone(nsIFrameLoader* aDest); + /** + * MessageManagerCallback methods that we override. + */ + virtual bool DoLoadFrameScript(const nsAString& aURL); + virtual bool DoSendAsyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData); + virtual bool CheckPermission(const nsAString& aPermission); + + /** * Called from the layout frame associated with this frame loader; * this notifies us to hook up with the widget and view. diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index ad2d075b9624..cc56ed889044 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -7,6 +7,7 @@ #include "nsFrameMessageManager.h" +#include "AppProcessPermissions.h" #include "ContentChild.h" #include "ContentParent.h" #include "nsContentUtils.h" @@ -17,6 +18,7 @@ #include "nsJSPrincipals.h" #include "nsNetUtil.h" #include "nsScriptLoader.h" +#include "nsFrameLoader.h" #include "nsIJSContextStack.h" #include "nsIXULRuntime.h" #include "nsIScriptError.h" @@ -39,6 +41,8 @@ using namespace mozilla; using namespace mozilla::dom; +using namespace mozilla::dom::ipc; + static bool IsChromeProcess() @@ -103,6 +107,10 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameMessageManager) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIFrameScriptLoader, mChrome && !mIsProcessManager) + /* Message senders in the chrome process support nsIPermissionChecker. */ + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIPermissionChecker, + mChrome && !mIsBroadcaster) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(ChromeMessageBroadcaster, mChrome && mIsBroadcaster) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(ChromeMessageSender, @@ -159,18 +167,18 @@ nsFrameMessageManager::LoadFrameScript(const nsAString& aURL, if (IsGlobal() || IsWindowLevel()) { // Cache for future windows or frames mPendingScripts.AppendElement(aURL); - } else if (!mCallbackData) { + } else if (!mCallback) { // We're frame message manager, which isn't connected yet. mPendingScripts.AppendElement(aURL); return NS_OK; } } - if (mCallbackData) { + if (mCallback) { #ifdef DEBUG_smaug printf("Will load %s \n", NS_ConvertUTF16toUTF8(aURL).get()); #endif - NS_ENSURE_TRUE(mLoadScriptCallback(mCallbackData, aURL), NS_ERROR_FAILURE); + NS_ENSURE_TRUE(mCallback->DoLoadFrameScript(aURL), NS_ERROR_FAILURE); } for (int32_t i = 0; i < mChildManagers.Count(); ++i) { @@ -242,62 +250,60 @@ nsFrameMessageManager::SendSyncMessage(const nsAString& aMessageName, NS_ASSERTION(!IsGlobal(), "Should not call SendSyncMessage in chrome"); NS_ASSERTION(!IsWindowLevel(), "Should not call SendSyncMessage in chrome"); NS_ASSERTION(!mParentManager, "Should not have parent manager in content!"); + *aRetval = JSVAL_VOID; - if (mSyncCallback) { - NS_ENSURE_TRUE(mCallbackData, NS_ERROR_NOT_INITIALIZED); - StructuredCloneData data; - JSAutoStructuredCloneBuffer buffer; - if (aArgc >= 2 && - !GetParamsForMessage(aCx, aObject, buffer, data.mClosure)) { - return NS_ERROR_DOM_DATA_CLONE_ERR; - } - data.mData = buffer.data(); - data.mDataLength = buffer.nbytes(); + NS_ENSURE_TRUE(mCallback, NS_ERROR_NOT_INITIALIZED); - InfallibleTArray retval; - if (mSyncCallback(mCallbackData, aMessageName, data, &retval)) { - JSAutoRequest ar(aCx); - uint32_t len = retval.Length(); - JSObject* dataArray = JS_NewArrayObject(aCx, len, NULL); - NS_ENSURE_TRUE(dataArray, NS_ERROR_OUT_OF_MEMORY); + StructuredCloneData data; + JSAutoStructuredCloneBuffer buffer; + if (aArgc >= 2 && + !GetParamsForMessage(aCx, aObject, buffer, data.mClosure)) { + return NS_ERROR_DOM_DATA_CLONE_ERR; + } + data.mData = buffer.data(); + data.mDataLength = buffer.nbytes(); - for (uint32_t i = 0; i < len; ++i) { - if (retval[i].IsEmpty()) { - continue; - } + InfallibleTArray retval; + if (mCallback->DoSendSyncMessage(aMessageName, data, &retval)) { + JSAutoRequest ar(aCx); + uint32_t len = retval.Length(); + JSObject* dataArray = JS_NewArrayObject(aCx, len, NULL); + NS_ENSURE_TRUE(dataArray, NS_ERROR_OUT_OF_MEMORY); - jsval ret = JSVAL_VOID; - if (!JS_ParseJSON(aCx, static_cast(retval[i].get()), - retval[i].Length(), &ret)) { - return NS_ERROR_UNEXPECTED; - } - NS_ENSURE_TRUE(JS_SetElement(aCx, dataArray, i, &ret), NS_ERROR_OUT_OF_MEMORY); + for (uint32_t i = 0; i < len; ++i) { + if (retval[i].IsEmpty()) { + continue; } - *aRetval = OBJECT_TO_JSVAL(dataArray); + jsval ret = JSVAL_VOID; + if (!JS_ParseJSON(aCx, static_cast(retval[i].get()), + retval[i].Length(), &ret)) { + return NS_ERROR_UNEXPECTED; + } + NS_ENSURE_TRUE(JS_SetElement(aCx, dataArray, i, &ret), NS_ERROR_OUT_OF_MEMORY); } + + *aRetval = OBJECT_TO_JSVAL(dataArray); } return NS_OK; } nsresult nsFrameMessageManager::DispatchAsyncMessageInternal(const nsAString& aMessage, - const StructuredCloneData& aData, - ShouldBroadcast aBroadcast) + const StructuredCloneData& aData) { - if (mAsyncCallback) { - NS_ENSURE_TRUE(mCallbackData, NS_ERROR_NOT_INITIALIZED); - - if (!mAsyncCallback(mCallbackData, aMessage, aData)) { - return NS_ERROR_FAILURE; - } - } - if (aBroadcast == BROADCAST) { + if (mIsBroadcaster) { int32_t len = mChildManagers.Count(); for (int32_t i = 0; i < len; ++i) { static_cast(mChildManagers[i])-> - DispatchAsyncMessageInternal(aMessage, aData, aBroadcast); + DispatchAsyncMessageInternal(aMessage, aData); } + return NS_OK; + } + + NS_ENSURE_TRUE(mCallback, NS_ERROR_NOT_INITIALIZED); + if (!mCallback->DoSendAsyncMessage(aMessage, aData)) { + return NS_ERROR_FAILURE; } return NS_OK; } @@ -306,8 +312,7 @@ nsresult nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName, const jsval& aObject, JSContext* aCx, - uint8_t aArgc, - ShouldBroadcast aBroadcast) + uint8_t aArgc) { StructuredCloneData data; JSAutoStructuredCloneBuffer buffer; @@ -320,7 +325,7 @@ nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName, data.mData = buffer.data(); data.mDataLength = buffer.nbytes(); - return DispatchAsyncMessageInternal(aMessageName, data, aBroadcast); + return DispatchAsyncMessageInternal(aMessageName, data); } @@ -332,7 +337,7 @@ nsFrameMessageManager::SendAsyncMessage(const nsAString& aMessageName, JSContext* aCx, uint8_t aArgc) { - return DispatchAsyncMessage(aMessageName, aObject, aCx, aArgc, DONT_BROADCAST); + return DispatchAsyncMessage(aMessageName, aObject, aCx, aArgc); } @@ -344,7 +349,7 @@ nsFrameMessageManager::BroadcastAsyncMessage(const nsAString& aMessageName, JSContext* aCx, uint8_t aArgc) { - return DispatchAsyncMessage(aMessageName, aObject, aCx, aArgc, BROADCAST); + return DispatchAsyncMessage(aMessageName, aObject, aCx, aArgc); } NS_IMETHODIMP @@ -418,6 +423,23 @@ nsFrameMessageManager::Atob(const nsAString& aAsciiString, return NS_OK; } +// nsIPermissionChecker + +NS_IMETHODIMP +nsFrameMessageManager::AssertPermission(const nsAString& aPermission, bool* aHasPermission) +{ + *aHasPermission = false; + + // This API is only supported for message senders in the chrome process. + if (!mChrome || mIsBroadcaster) { + return NS_ERROR_NOT_IMPLEMENTED; + } + if (!mCallback) { + return NS_ERROR_NOT_AVAILABLE; + } + *aHasPermission = mCallback->CheckPermission(aPermission); + return NS_OK; +} class MMListenerRemover { @@ -610,10 +632,15 @@ nsFrameMessageManager::AddChildManager(nsFrameMessageManager* aManager, } void -nsFrameMessageManager::SetCallbackData(void* aData, bool aLoadScripts) +nsFrameMessageManager::SetCallback(MessageManagerCallback* aCallback, bool aLoadScripts) { - if (aData && mCallbackData != aData) { - mCallbackData = aData; + NS_ASSERTION(!mIsBroadcaster || !mCallback, + "Broadcasters cannot have callbacks!"); + if (aCallback && mCallback != aCallback) { + mCallback = aCallback; + if (mOwnsCallback) { + mOwnedCallback = aCallback; + } // First load global scripts by adding this to parent manager. if (mParentManager) { mParentManager->AddChildManager(this, aLoadScripts); @@ -633,7 +660,8 @@ nsFrameMessageManager::RemoveFromParent() mParentManager->RemoveChildManager(this); } mParentManager = nullptr; - mCallbackData = nullptr; + mCallback = nullptr; + mOwnedCallback = nullptr; mContext = nullptr; } @@ -645,7 +673,8 @@ nsFrameMessageManager::Disconnect(bool aRemoveFromParent) } mDisconnected = true; mParentManager = nullptr; - mCallbackData = nullptr; + mCallback = nullptr; + mOwnedCallback = nullptr; mContext = nullptr; if (!mHandlingMessage) { mListeners.Clear(); @@ -656,17 +685,10 @@ nsresult NS_NewGlobalMessageManager(nsIMessageBroadcaster** aResult) { NS_ENSURE_TRUE(IsChromeProcess(), NS_ERROR_NOT_AVAILABLE); - nsFrameMessageManager* mm = new nsFrameMessageManager(true /* aChrome */, + nsFrameMessageManager* mm = new nsFrameMessageManager(nullptr, nullptr, nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - true /* aGlobal */, - false /* aProcessManager */, - true /* aBroadcaster */); - NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY); + MM_CHROME | MM_GLOBAL | MM_BROADCASTER); return CallQueryInterface(mm, aResult); } @@ -1001,36 +1023,6 @@ nsFrameMessageManager* nsFrameMessageManager::sParentProcessManager = nullptr; nsFrameMessageManager* nsFrameMessageManager::sSameProcessParentManager = nullptr; nsTArray >* nsFrameMessageManager::sPendingSameProcessAsyncMessages = nullptr; -bool SendAsyncMessageToChildProcess(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData) -{ - mozilla::dom::ContentParent* cp = - static_cast(aCallbackData); - NS_WARN_IF_FALSE(cp, "No child process!"); - if (cp) { - ClonedMessageData data; - SerializedStructuredCloneBuffer& buffer = data.data(); - buffer.data = aData.mData; - buffer.dataLength = aData.mDataLength; - const nsTArray >& blobs = aData.mClosure.mBlobs; - if (!blobs.IsEmpty()) { - InfallibleTArray& blobParents = data.blobsParent(); - uint32_t length = blobs.Length(); - blobParents.SetCapacity(length); - for (uint32_t i = 0; i < length; ++i) { - BlobParent* blobParent = cp->GetOrCreateActorForBlob(blobs[i]); - if (!blobParent) { - return false; - } - blobParents.AppendElement(blobParent); - } - } - - return cp->SendAsyncMessage(nsString(aMessage), data); - } - return true; -} class nsAsyncMessageToSameProcessChild : public nsRunnable { @@ -1064,24 +1056,64 @@ public: StructuredCloneClosure mClosure; }; -bool SendAsyncMessageToSameProcessChild(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData) -{ - nsRefPtr ev = - new nsAsyncMessageToSameProcessChild(aMessage, aData); - NS_DispatchToCurrentThread(ev); - return true; -} -bool SendSyncMessageToParentProcess(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData, - InfallibleTArray* aJSONRetVal) +/** + * Send messages to an imaginary child process in a single-process scenario. + */ +class SameParentProcessMessageManagerCallback : public MessageManagerCallback { - mozilla::dom::ContentChild* cc = - mozilla::dom::ContentChild::GetSingleton(); - if (cc) { +public: + SameParentProcessMessageManagerCallback() + { + MOZ_COUNT_CTOR(SameParentProcessMessageManagerCallback); + } + virtual ~SameParentProcessMessageManagerCallback() + { + MOZ_COUNT_DTOR(SameParentProcessMessageManagerCallback); + } + + virtual bool DoSendAsyncMessage(const nsAString& aMessage, + const StructuredCloneData& aData) + { + nsRefPtr ev = + new nsAsyncMessageToSameProcessChild(aMessage, aData); + NS_DispatchToCurrentThread(ev); + return true; + } + + bool CheckPermission(const nsAString& aPermission) + { + // In a single-process scenario, the child always has all capabilities. + return true; + } + +}; + + +/** + * Send messages to the parent process. + */ +class ChildProcessMessageManagerCallback : public MessageManagerCallback +{ +public: + ChildProcessMessageManagerCallback() + { + MOZ_COUNT_CTOR(ChildProcessMessageManagerCallback); + } + virtual ~ChildProcessMessageManagerCallback() + { + MOZ_COUNT_DTOR(ChildProcessMessageManagerCallback); + } + + virtual bool DoSendSyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData, + InfallibleTArray* aJSONRetVal) + { + mozilla::dom::ContentChild* cc = + mozilla::dom::ContentChild::GetSingleton(); + if (!cc) { + return true; + } ClonedMessageData data; SerializedStructuredCloneBuffer& buffer = data.data(); buffer.data = aData.mData; @@ -1099,41 +1131,17 @@ bool SendSyncMessageToParentProcess(void* aCallbackData, blobChildList.AppendElement(blobChild); } } - return - cc->SendSyncMessage(nsString(aMessage), data, aJSONRetVal); + return cc->SendSyncMessage(nsString(aMessage), data, aJSONRetVal); } - return true; -} -bool SendSyncMessageToSameProcessParent(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData, - InfallibleTArray* aJSONRetVal) -{ - nsTArray > asyncMessages; - if (nsFrameMessageManager::sPendingSameProcessAsyncMessages) { - asyncMessages.SwapElements(*nsFrameMessageManager::sPendingSameProcessAsyncMessages); - uint32_t len = asyncMessages.Length(); - for (uint32_t i = 0; i < len; ++i) { - nsCOMPtr async = asyncMessages[i]; - async->Run(); + virtual bool DoSendAsyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData) + { + mozilla::dom::ContentChild* cc = + mozilla::dom::ContentChild::GetSingleton(); + if (!cc) { + return true; } - } - if (nsFrameMessageManager::sSameProcessParentManager) { - nsRefPtr ppm = nsFrameMessageManager::sSameProcessParentManager; - ppm->ReceiveMessage(static_cast(ppm.get()), aMessage, - true, &aData, nullptr, aJSONRetVal); - } - return true; -} - -bool SendAsyncMessageToParentProcess(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData) -{ - mozilla::dom::ContentChild* cc = - mozilla::dom::ContentChild::GetSingleton(); - if (cc) { ClonedMessageData data; SerializedStructuredCloneBuffer& buffer = data.data(); buffer.data = aData.mData; @@ -1153,14 +1161,15 @@ bool SendAsyncMessageToParentProcess(void* aCallbackData, } return cc->SendAsyncMessage(nsString(aMessage), data); } - return true; -} + +}; + class nsAsyncMessageToSameProcessParent : public nsRunnable { public: nsAsyncMessageToSameProcessParent(const nsAString& aMessage, - const StructuredCloneData& aData) + const StructuredCloneData& aData) : mMessage(aMessage) { if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) { @@ -1192,19 +1201,57 @@ public: StructuredCloneClosure mClosure; }; -bool SendAsyncMessageToSameProcessParent(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData) +/** + * Send messages to the imaginary parent process in a single-process scenario. + */ +class SameChildProcessMessageManagerCallback : public MessageManagerCallback { - if (!nsFrameMessageManager::sPendingSameProcessAsyncMessages) { - nsFrameMessageManager::sPendingSameProcessAsyncMessages = new nsTArray >; +public: + SameChildProcessMessageManagerCallback() + { + MOZ_COUNT_CTOR(SameChildProcessMessageManagerCallback); } - nsCOMPtr ev = - new nsAsyncMessageToSameProcessParent(aMessage, aData); - nsFrameMessageManager::sPendingSameProcessAsyncMessages->AppendElement(ev); - NS_DispatchToCurrentThread(ev); - return true; -} + virtual ~SameChildProcessMessageManagerCallback() + { + MOZ_COUNT_DTOR(SameChildProcessMessageManagerCallback); + } + + virtual bool DoSendSyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData, + InfallibleTArray* aJSONRetVal) + { + nsTArray > asyncMessages; + if (nsFrameMessageManager::sPendingSameProcessAsyncMessages) { + asyncMessages.SwapElements(*nsFrameMessageManager::sPendingSameProcessAsyncMessages); + uint32_t len = asyncMessages.Length(); + for (uint32_t i = 0; i < len; ++i) { + nsCOMPtr async = asyncMessages[i]; + async->Run(); + } + } + if (nsFrameMessageManager::sSameProcessParentManager) { + nsRefPtr ppm = nsFrameMessageManager::sSameProcessParentManager; + ppm->ReceiveMessage(static_cast(ppm.get()), aMessage, + true, &aData, nullptr, aJSONRetVal); + } + return true; + } + + virtual bool DoSendAsyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData) + { + if (!nsFrameMessageManager::sPendingSameProcessAsyncMessages) { + nsFrameMessageManager::sPendingSameProcessAsyncMessages = new nsTArray >; + } + nsCOMPtr ev = + new nsAsyncMessageToSameProcessParent(aMessage, aData); + nsFrameMessageManager::sPendingSameProcessAsyncMessages->AppendElement(ev); + NS_DispatchToCurrentThread(ev); + return true; + } + +}; + // This creates the global parent process message manager. nsresult @@ -1213,22 +1260,17 @@ NS_NewParentProcessMessageManager(nsIMessageBroadcaster** aResult) NS_ASSERTION(!nsFrameMessageManager::sParentProcessManager, "Re-creating sParentProcessManager"); NS_ENSURE_TRUE(IsChromeProcess(), NS_ERROR_NOT_AVAILABLE); - nsRefPtr mm = new nsFrameMessageManager(true /* aChrome */, + nsRefPtr mm = new nsFrameMessageManager(nullptr, nullptr, nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - false, /* aGlobal */ - true /* aProcessManager */, - true /* aBroadcaster */); + MM_CHROME | MM_PROCESSMANAGER | MM_BROADCASTER); NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY); nsFrameMessageManager::sParentProcessManager = mm; nsFrameMessageManager::NewProcessMessageManager(nullptr); // Create same process message manager. return CallQueryInterface(mm, aResult); } + nsFrameMessageManager* nsFrameMessageManager::NewProcessMessageManager(mozilla::dom::ContentParent* aProcess) { @@ -1237,18 +1279,17 @@ nsFrameMessageManager::NewProcessMessageManager(mozilla::dom::ContentParent* aPr NS_NewParentProcessMessageManager(getter_AddRefs(dummy)); } - nsFrameMessageManager* mm = new nsFrameMessageManager(true /* aChrome */, - nullptr, - aProcess ? SendAsyncMessageToChildProcess - : SendAsyncMessageToSameProcessChild, - nullptr, - aProcess ? static_cast(aProcess) - : static_cast(&nsFrameMessageManager::sChildProcessManager), - nsFrameMessageManager::sParentProcessManager, - nullptr, - false, /* aGlobal */ - true /* aProcessManager */); - if (!aProcess) { + nsFrameMessageManager* mm; + if (aProcess) { + mm = new nsFrameMessageManager(aProcess, + nsFrameMessageManager::sParentProcessManager, + nullptr, + MM_CHROME | MM_PROCESSMANAGER); + } else { + mm = new nsFrameMessageManager(new SameParentProcessMessageManagerCallback(), + nsFrameMessageManager::sParentProcessManager, + nullptr, + MM_CHROME | MM_PROCESSMANAGER | MM_OWNSCALLBACK); sSameProcessParentManager = mm; } return mm; @@ -1259,18 +1300,17 @@ NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult) { NS_ASSERTION(!nsFrameMessageManager::sChildProcessManager, "Re-creating sChildProcessManager"); - bool isChrome = IsChromeProcess(); - nsFrameMessageManager* mm = new nsFrameMessageManager(false /* aChrome */, - isChrome ? SendSyncMessageToSameProcessParent - : SendSyncMessageToParentProcess, - isChrome ? SendAsyncMessageToSameProcessParent - : SendAsyncMessageToParentProcess, - nullptr, - &nsFrameMessageManager::sChildProcessManager, + + MessageManagerCallback* cb; + if (IsChromeProcess()) { + cb = new SameChildProcessMessageManagerCallback(); + } else { + cb = new ChildProcessMessageManagerCallback(); + } + nsFrameMessageManager* mm = new nsFrameMessageManager(cb, nullptr, nullptr, - false /* aGlobal */, - true /* aProcessManager */); + MM_PROCESSMANAGER | MM_OWNSCALLBACK); NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY); nsFrameMessageManager::sChildProcessManager = mm; return CallQueryInterface(mm, aResult); diff --git a/content/base/src/nsFrameMessageManager.h b/content/base/src/nsFrameMessageManager.h index 8285ab00f9a6..fb41fac3a886 100644 --- a/content/base/src/nsFrameMessageManager.h +++ b/content/base/src/nsFrameMessageManager.h @@ -24,10 +24,53 @@ namespace mozilla { namespace dom { + class ContentParent; struct StructuredCloneData; -} -} + +namespace ipc { + +enum MessageManagerFlags { + MM_CHILD = 0, + MM_CHROME = 1, + MM_GLOBAL = 2, + MM_PROCESSMANAGER = 4, + MM_BROADCASTER = 8, + MM_OWNSCALLBACK = 16 +}; + +class MessageManagerCallback +{ +public: + virtual ~MessageManagerCallback() {} + + virtual bool DoLoadFrameScript(const nsAString& aURL) + { + return true; + } + + virtual bool DoSendSyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData, + InfallibleTArray* aJSONRetVal) + { + return true; + } + + virtual bool DoSendAsyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData) + { + return true; + } + + virtual bool CheckPermission(const nsAString& aPermission) + { + return false; + } +}; + +} // namespace ipc +} // namespace dom +} // namespace mozilla class nsAXPCNativeCallContext; struct JSContext; @@ -39,54 +82,44 @@ struct nsMessageListenerInfo nsCOMPtr mMessage; }; -typedef bool (*nsLoadScriptCallback)(void* aCallbackData, const nsAString& aURL); -typedef bool (*nsSyncMessageCallback)(void* aCallbackData, - const nsAString& aMessage, - const mozilla::dom::StructuredCloneData& aData, - InfallibleTArray* aJSONRetVal); -typedef bool (*nsAsyncMessageCallback)(void* aCallbackData, - const nsAString& aMessage, - const mozilla::dom::StructuredCloneData& aData); class nsFrameMessageManager MOZ_FINAL : public nsIContentFrameMessageManager, public nsIMessageBroadcaster, - public nsIFrameScriptLoader + public nsIFrameScriptLoader, + public nsIPermissionChecker { typedef mozilla::dom::StructuredCloneData StructuredCloneData; public: - nsFrameMessageManager(bool aChrome, - nsSyncMessageCallback aSyncCallback, - nsAsyncMessageCallback aAsyncCallback, - nsLoadScriptCallback aLoadScriptCallback, - void* aCallbackData, + nsFrameMessageManager(mozilla::dom::ipc::MessageManagerCallback* aCallback, nsFrameMessageManager* aParentManager, JSContext* aContext, - bool aGlobal = false, - bool aProcessManager = false, - bool aBroadcaster = false) - : mChrome(aChrome), - mGlobal(aGlobal), - mIsProcessManager(aProcessManager), - mIsBroadcaster(aBroadcaster), + /* mozilla::dom::ipc::MessageManagerFlags */ uint32_t aFlags) + : mChrome(!!(aFlags & mozilla::dom::ipc::MM_CHROME)), + mGlobal(!!(aFlags & mozilla::dom::ipc::MM_GLOBAL)), + mIsProcessManager(!!(aFlags & mozilla::dom::ipc::MM_PROCESSMANAGER)), + mIsBroadcaster(!!(aFlags & mozilla::dom::ipc::MM_BROADCASTER)), + mOwnsCallback(!!(aFlags & mozilla::dom::ipc::MM_OWNSCALLBACK)), mHandlingMessage(false), mDisconnected(false), + mCallback(aCallback), mParentManager(aParentManager), - mSyncCallback(aSyncCallback), - mAsyncCallback(aAsyncCallback), - mLoadScriptCallback(aLoadScriptCallback), - mCallbackData(aCallbackData), mContext(aContext) { - NS_ASSERTION(mContext || (aChrome && !aParentManager) || aProcessManager, + NS_ASSERTION(mContext || (mChrome && !mParentManager) || mIsProcessManager, "Should have mContext in non-global/non-process manager!"); - NS_ASSERTION(aChrome || !aParentManager, "Should not set parent manager!"); + NS_ASSERTION(mChrome || !aParentManager, "Should not set parent manager!"); + NS_ASSERTION(!mIsBroadcaster || !mCallback, + "Broadcasters cannot have callbacks!"); // This is a bit hackish. When parent manager is global, we want // to attach the window message manager to it immediately. // Is it just the frame message manager which waits until the // content process is running. - if (mParentManager && (mCallbackData || IsWindowLevel())) { + if (mParentManager && (mCallback || IsWindowLevel())) { mParentManager->AddChildManager(this); } + if (mOwnsCallback) { + mOwnedCallback = aCallback; + } } ~nsFrameMessageManager() @@ -119,6 +152,7 @@ public: NS_DECL_NSISYNCMESSAGESENDER NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER NS_DECL_NSIFRAMESCRIPTLOADER + NS_DECL_NSIPERMISSIONCHECKER static nsFrameMessageManager* NewProcessMessageManager(mozilla::dom::ContentParent* aProcess); @@ -135,19 +169,21 @@ public: { mChildManagers.RemoveObject(aManager); } - void Disconnect(bool aRemoveFromParent = true); - void SetCallbackData(void* aData, bool aLoadScripts = true); - void* GetCallbackData() { return mCallbackData; } - enum ShouldBroadcast { BROADCAST, DONT_BROADCAST }; + + void SetCallback(mozilla::dom::ipc::MessageManagerCallback* aCallback, + bool aLoadScripts = true); + mozilla::dom::ipc::MessageManagerCallback* GetCallback() + { + return mCallback; + } + nsresult DispatchAsyncMessage(const nsAString& aMessageName, const jsval& aObject, JSContext* aCx, - uint8_t aArgc, - ShouldBroadcast aBroadcast); + uint8_t aArgc); nsresult DispatchAsyncMessageInternal(const nsAString& aMessage, - const StructuredCloneData& aData, - ShouldBroadcast aBroadcast); + const StructuredCloneData& aData); JSContext* GetJSContext() { return mContext; } void SetJSContext(JSContext* aCx) { mContext = aCx; } void RemoveFromParent(); @@ -174,16 +210,15 @@ protected: nsTArray mListeners; nsCOMArray mChildManagers; bool mChrome; // true if we're in the chrome process - bool mGlobal; // true if + bool mGlobal; // true if we're the global frame message manager bool mIsProcessManager; // true if the message manager belongs to the process realm bool mIsBroadcaster; // true if the message manager is a broadcaster + bool mOwnsCallback; bool mHandlingMessage; bool mDisconnected; + mozilla::dom::ipc::MessageManagerCallback* mCallback; + nsAutoPtr mOwnedCallback; nsFrameMessageManager* mParentManager; - nsSyncMessageCallback mSyncCallback; - nsAsyncMessageCallback mAsyncCallback; - nsLoadScriptCallback mLoadScriptCallback; - void* mCallbackData; JSContext* mContext; nsTArray mPendingScripts; public: diff --git a/content/base/src/nsInProcessTabChildGlobal.cpp b/content/base/src/nsInProcessTabChildGlobal.cpp index b1439490d873..6270f8e232d9 100644 --- a/content/base/src/nsInProcessTabChildGlobal.cpp +++ b/content/base/src/nsInProcessTabChildGlobal.cpp @@ -25,24 +25,21 @@ using mozilla::dom::StructuredCloneData; using mozilla::dom::StructuredCloneClosure; -bool SendSyncMessageToParent(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData, - InfallibleTArray* aJSONRetVal) +bool +nsInProcessTabChildGlobal::DoSendSyncMessage(const nsAString& aMessage, + const StructuredCloneData& aData, + InfallibleTArray* aJSONRetVal) { - nsInProcessTabChildGlobal* tabChild = - static_cast(aCallbackData); - nsCOMPtr owner = tabChild->mOwner; nsTArray > asyncMessages; - asyncMessages.SwapElements(tabChild->mASyncMessages); + asyncMessages.SwapElements(mASyncMessages); uint32_t len = asyncMessages.Length(); for (uint32_t i = 0; i < len; ++i) { nsCOMPtr async = asyncMessages[i]; async->Run(); } - if (tabChild->mChromeMessageManager) { - nsRefPtr mm = tabChild->mChromeMessageManager; - mm->ReceiveMessage(owner, aMessage, true, &aData, nullptr, aJSONRetVal); + if (mChromeMessageManager) { + nsRefPtr mm = mChromeMessageManager; + mm->ReceiveMessage(mOwner, aMessage, true, &aData, nullptr, aJSONRetVal); } return true; } @@ -82,15 +79,13 @@ public: StructuredCloneClosure mClosure; }; -bool SendAsyncMessageToParent(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData) +bool +nsInProcessTabChildGlobal::DoSendAsyncMessage(const nsAString& aMessage, + const StructuredCloneData& aData) { - nsInProcessTabChildGlobal* tabChild = - static_cast(aCallbackData); nsCOMPtr ev = - new nsAsyncMessageToParent(tabChild, aMessage, aData); - tabChild->mASyncMessages.AppendElement(ev); + new nsAsyncMessageToParent(this, aMessage, aData); + mASyncMessages.AppendElement(ev); NS_DispatchToCurrentThread(ev); return true; } @@ -135,13 +130,10 @@ nsInProcessTabChildGlobal::Init() InitTabChildGlobal(); NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Couldn't initialize nsInProcessTabChildGlobal"); - mMessageManager = new nsFrameMessageManager(false, /* aChrome */ - SendSyncMessageToParent, - SendAsyncMessageToParent, + mMessageManager = new nsFrameMessageManager(this, nullptr, - this, - nullptr, - mCx); + mCx, + mozilla::dom::ipc::MM_CHILD); // Set the location information for the new global, so that tools like // about:memory may use that information. diff --git a/content/base/src/nsInProcessTabChildGlobal.h b/content/base/src/nsInProcessTabChildGlobal.h index 53540458c57b..0c8783520c69 100644 --- a/content/base/src/nsInProcessTabChildGlobal.h +++ b/content/base/src/nsInProcessTabChildGlobal.h @@ -24,7 +24,8 @@ class nsInProcessTabChildGlobal : public nsDOMEventTargetHelper, public nsFrameScriptExecutor, public nsIInProcessContentFrameMessageManager, public nsIScriptObjectPrincipal, - public nsIScriptContextPrincipal + public nsIScriptContextPrincipal, + public mozilla::dom::ipc::MessageManagerCallback { public: nsInProcessTabChildGlobal(nsIDocShell* aShell, nsIContent* aOwner, @@ -59,6 +60,15 @@ public: NS_DECL_NSIINPROCESSCONTENTFRAMEMESSAGEMANAGER + /** + * MessageManagerCallback methods that we override. + */ + virtual bool DoSendSyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData, + InfallibleTArray* aJSONRetVal); + virtual bool DoSendAsyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData); + virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor); NS_IMETHOD AddEventListener(const nsAString& aType, nsIDOMEventListener* aListener, diff --git a/content/base/test/Makefile.in b/content/base/test/Makefile.in index c930ac84878e..094727682ff4 100644 --- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -571,6 +571,16 @@ MOCHITEST_FILES_B = \ test_bug789856.html \ $(NULL) +# OOP tests don't work on Windows (bug 763081) or native-fennec +# (see Bug 774939) +ifneq ($(OS_ARCH),WINNT) +ifndef MOZ_JAVA_COMPOSITOR +MOCHITEST_FILES_B += \ + test_messagemanager_assertpermission.html \ + $(NULL) +endif +endif + MOCHITEST_CHROME_FILES = \ test_bug357450.js \ $(NULL) diff --git a/content/base/test/test_messagemanager_assertpermission.html b/content/base/test/test_messagemanager_assertpermission.html new file mode 100644 index 000000000000..1b497b62e067 --- /dev/null +++ b/content/base/test/test_messagemanager_assertpermission.html @@ -0,0 +1,172 @@ + + + + + Test for the nsIPermissionChecker part of Message Managers + + + + +

+

+ +
+
+
+ + diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 306864fef88a..f9d2222c5d5a 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -4350,6 +4350,7 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeMessageSender, nsISupports) + DOM_CLASSINFO_MAP_ENTRY(nsIPermissionChecker) DOM_CLASSINFO_MAP_ENTRY(nsIFrameScriptLoader) DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager) DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index caccf6d10a85..187b93cd7a3b 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -235,6 +235,7 @@ static const char kStorageEnabled[] = "dom.storage.enabled"; using namespace mozilla; using namespace mozilla::dom; +using namespace mozilla::dom::ipc; using mozilla::TimeStamp; using mozilla::TimeDuration; @@ -11004,16 +11005,10 @@ nsGlobalChromeWindow::GetMessageManager(nsIMessageBroadcaster** aManager) nsCOMPtr globalMM = do_GetService("@mozilla.org/globalmessagemanager;1"); mMessageManager = - new nsFrameMessageManager(true, /* aChrome */ - nullptr, - nullptr, - nullptr, - nullptr, + new nsFrameMessageManager(nullptr, static_cast(globalMM.get()), cx, - false, /* aGlobal */ - false, /* aProcessManager */ - true /* aBroadcaster */); + MM_CHROME | MM_BROADCASTER); NS_ENSURE_TRUE(mMessageManager, NS_ERROR_OUT_OF_MEMORY); } CallQueryInterface(mMessageManager, aManager); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 854ce5547756..ded1545bf557 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -1883,5 +1883,37 @@ ContentParent::RecvPrivateDocShellsExist(const bool& aExist) return true; } +bool +ContentParent::DoSendAsyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData) +{ + ClonedMessageData data; + SerializedStructuredCloneBuffer& buffer = data.data(); + buffer.data = aData.mData; + buffer.dataLength = aData.mDataLength; + const nsTArray >& blobs = aData.mClosure.mBlobs; + if (!blobs.IsEmpty()) { + InfallibleTArray& blobParents = data.blobsParent(); + uint32_t length = blobs.Length(); + blobParents.SetCapacity(length); + for (uint32_t i = 0; i < length; ++i) { + BlobParent* blobParent = GetOrCreateActorForBlob(blobs[i]); + if (!blobParent) { + return false; + } + blobParents.AppendElement(blobParent); + } + } + + return SendAsyncMessage(nsString(aMessage), data); +} + +bool +ContentParent::CheckPermission(const nsAString& aPermission) +{ + return AssertAppProcessPermission(this, NS_ConvertUTF16toUTF8(aPermission).get()); +} + + } // namespace dom } // namespace mozilla diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index a24380882acd..b4ba0b5925ae 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -15,6 +15,7 @@ #include "mozilla/dom/ipc/Blob.h" #include "mozilla/Attributes.h" +#include "nsFrameMessageManager.h" #include "nsIObserver.h" #include "nsIThreadInternal.h" #include "nsNetUtil.h" @@ -26,7 +27,6 @@ #include "nsHashKeys.h" class mozIApplication; -class nsFrameMessageManager; class nsIDOMBlob; namespace mozilla { @@ -51,6 +51,7 @@ class ContentParent : public PContentParent , public nsIObserver , public nsIThreadObserver , public nsIDOMGeoPositionCallback + , public mozilla::dom::ipc::MessageManagerCallback { typedef mozilla::ipc::GeckoChildProcessHost GeckoChildProcessHost; typedef mozilla::ipc::OptionalURIParams OptionalURIParams; @@ -87,6 +88,13 @@ public: NS_DECL_NSITHREADOBSERVER NS_DECL_NSIDOMGEOPOSITIONCALLBACK + /** + * MessageManagerCallback methods that we override. + */ + virtual bool DoSendAsyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData); + virtual bool CheckPermission(const nsAString& aPermission); + /** Notify that a tab was destroyed during normal operation. */ void NotifyTabDestroyed(PBrowserParent* aTab); diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index ac0250c0fb83..df0d4fa0ca0e 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -75,6 +75,7 @@ using namespace mozilla; using namespace mozilla::dom; +using namespace mozilla::dom::ipc; using namespace mozilla::ipc; using namespace mozilla::layers; using namespace mozilla::layout; @@ -1458,14 +1459,12 @@ TabChild::DeallocPIndexedDB(PIndexedDBChild* aActor) return true; } -static bool -SendSyncMessageToParent(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData, - InfallibleTArray* aJSONRetVal) +bool +TabChild::DoSendSyncMessage(const nsAString& aMessage, + const StructuredCloneData& aData, + InfallibleTArray* aJSONRetVal) { - TabChild* tabChild = static_cast(aCallbackData); - ContentChild* cc = static_cast(tabChild->Manager()); + ContentChild* cc = static_cast(Manager()); ClonedMessageData data; SerializedStructuredCloneBuffer& buffer = data.data(); buffer.data = aData.mData; @@ -1484,16 +1483,14 @@ SendSyncMessageToParent(void* aCallbackData, blobChildList.AppendElement(blobChild); } } - return tabChild->SendSyncMessage(nsString(aMessage), data, aJSONRetVal); + return SendSyncMessage(nsString(aMessage), data, aJSONRetVal); } -static bool -SendAsyncMessageToParent(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData) +bool +TabChild::DoSendAsyncMessage(const nsAString& aMessage, + const StructuredCloneData& aData) { - TabChild* tabChild = static_cast(aCallbackData); - ContentChild* cc = static_cast(tabChild->Manager()); + ContentChild* cc = static_cast(Manager()); ClonedMessageData data; SerializedStructuredCloneBuffer& buffer = data.data(); buffer.data = aData.mData; @@ -1513,7 +1510,7 @@ SendAsyncMessageToParent(void* aCallbackData, } } - return tabChild->SendAsyncMessage(nsString(aMessage), data); + return SendAsyncMessage(nsString(aMessage), data); } @@ -1526,13 +1523,10 @@ void TabChildGlobal::Init() { NS_ASSERTION(!mMessageManager, "Re-initializing?!?"); - mMessageManager = new nsFrameMessageManager(false, /* aChrome */ - SendSyncMessageToParent, - SendAsyncMessageToParent, + mMessageManager = new nsFrameMessageManager(mTabChild, nullptr, - mTabChild, - nullptr, - mTabChild->GetJSContext()); + mTabChild->GetJSContext(), + MM_CHILD); } NS_IMPL_CYCLE_COLLECTION_CLASS(TabChildGlobal) diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 475b78e89f6c..1e6a0b232abb 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -144,7 +144,8 @@ class TabChild : public PBrowserChild, public nsSupportsWeakReference, public nsIDialogCreator, public nsITabChild, - public nsIObserver + public nsIObserver, + public mozilla::dom::ipc::MessageManagerCallback { typedef mozilla::layout::RenderFrameChild RenderFrameChild; typedef mozilla::dom::ClonedMessageData ClonedMessageData; @@ -178,6 +179,15 @@ public: NS_DECL_NSITABCHILD NS_DECL_NSIOBSERVER + /** + * MessageManagerCallback methods that we override. + */ + virtual bool DoSendSyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData, + InfallibleTArray* aJSONRetVal); + virtual bool DoSendAsyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData); + virtual bool RecvLoadURL(const nsCString& uri); virtual bool RecvShow(const nsIntSize& size); virtual bool RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size);