diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index fdd5eeae0ebf..e43f61487915 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -1389,6 +1389,9 @@ nsFrameLoader::StartDestroy() if (mRemoteBrowser) { mRemoteBrowser->CacheFrameLoader(this); } + if (mChildMessageManager) { + mChildMessageManager->CacheFrameLoader(this); + } } // If the TabParent has installed any event listeners on the window, this is @@ -1532,6 +1535,9 @@ nsFrameLoader::DestroyComplete() if (mRemoteBrowser) { mRemoteBrowser->CacheFrameLoader(nullptr); } + if (mChildMessageManager) { + mChildMessageManager->CacheFrameLoader(nullptr); + } } // Call TabParent::Destroy if we haven't already (in case of a crash). @@ -2443,7 +2449,7 @@ public: static_cast(mFrameLoader->mChildMessageManager.get()); if (tabChild && tabChild->GetInnerManager()) { nsCOMPtr kungFuDeathGrip(tabChild->GetGlobal()); - ReceiveMessage(static_cast(tabChild), + ReceiveMessage(static_cast(tabChild), mFrameLoader, tabChild->GetInnerManager()); } return NS_OK; diff --git a/dom/base/nsFrameMessageManager.cpp b/dom/base/nsFrameMessageManager.cpp index 6b94a9f6ac84..b1b8b3115cc6 100644 --- a/dom/base/nsFrameMessageManager.cpp +++ b/dom/base/nsFrameMessageManager.cpp @@ -995,6 +995,7 @@ public: nsresult nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, + nsIFrameLoader* aTargetFrameLoader, const nsAString& aMessage, bool aIsSync, const StructuredCloneData* aCloneData, @@ -1002,12 +1003,13 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, nsIPrincipal* aPrincipal, InfallibleTArray* aJSONRetVal) { - return ReceiveMessage(aTarget, mClosed, aMessage, aIsSync, + return ReceiveMessage(aTarget, aTargetFrameLoader, mClosed, aMessage, aIsSync, aCloneData, aCpows, aPrincipal, aJSONRetVal); } nsresult nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, + nsIFrameLoader* aTargetFrameLoader, bool aTargetClosed, const nsAString& aMessage, bool aIsSync, @@ -1114,6 +1116,16 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, JS_DefineProperty(cx, param, "objects", cpowsv, JSPROP_ENUMERATE); NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED); + if (aTargetFrameLoader) { + JS::Rooted targetFrameLoaderv(cx); + nsresult rv = nsContentUtils::WrapNative(cx, aTargetFrameLoader, &targetFrameLoaderv); + NS_ENSURE_SUCCESS(rv, rv); + + ok = JS_DefineProperty(cx, param, "targetFrameLoader", targetFrameLoaderv, + JSPROP_ENUMERATE); + NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED); + } + // message.principal == null if (!aPrincipal) { bool ok = JS_DefineProperty(cx, param, "principal", @@ -1190,7 +1202,8 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, } } nsRefPtr kungfuDeathGrip = mParentManager; - return mParentManager ? mParentManager->ReceiveMessage(aTarget, aTargetClosed, aMessage, + return mParentManager ? mParentManager->ReceiveMessage(aTarget, aTargetFrameLoader, + aTargetClosed, aMessage, aIsSync, aCloneData, aCpows, aPrincipal, aJSONRetVal) : NS_OK; @@ -1769,7 +1782,7 @@ public: NS_IMETHOD Run() { nsFrameMessageManager* ppm = nsFrameMessageManager::GetChildProcessManager(); - ReceiveMessage(static_cast(ppm), ppm); + ReceiveMessage(static_cast(ppm), nullptr, ppm); return NS_OK; } }; @@ -1924,7 +1937,7 @@ public: virtual nsresult HandleMessage() override { nsFrameMessageManager* ppm = nsFrameMessageManager::sSameProcessParentManager; - ReceiveMessage(static_cast(ppm), ppm); + ReceiveMessage(static_cast(ppm), nullptr, ppm); return NS_OK; } }; @@ -1958,7 +1971,7 @@ public: if (nsFrameMessageManager::sSameProcessParentManager) { SameProcessCpowHolder cpows(js::GetRuntime(aCx), aCpows); nsRefPtr ppm = nsFrameMessageManager::sSameProcessParentManager; - ppm->ReceiveMessage(static_cast(ppm.get()), aMessage, + ppm->ReceiveMessage(static_cast(ppm.get()), nullptr, aMessage, true, &aData, &cpows, aPrincipal, aJSONRetVal); } return true; @@ -2089,6 +2102,7 @@ nsSameProcessAsyncMessageBase::nsSameProcessAsyncMessageBase(JSContext* aCx, void nsSameProcessAsyncMessageBase::ReceiveMessage(nsISupports* aTarget, + nsIFrameLoader* aTargetFrameLoader, nsFrameMessageManager* aManager) { if (aManager) { @@ -2100,7 +2114,7 @@ nsSameProcessAsyncMessageBase::ReceiveMessage(nsISupports* aTarget, SameProcessCpowHolder cpows(mRuntime, mCpows); nsRefPtr mm = aManager; - mm->ReceiveMessage(aTarget, mMessage, false, &data, &cpows, + mm->ReceiveMessage(aTarget, aTargetFrameLoader, mMessage, false, &data, &cpows, mPrincipal, nullptr); } } diff --git a/dom/base/nsFrameMessageManager.h b/dom/base/nsFrameMessageManager.h index 3a617f6990e1..d25a8eddbf42 100644 --- a/dom/base/nsFrameMessageManager.h +++ b/dom/base/nsFrameMessageManager.h @@ -31,6 +31,8 @@ #include "mozilla/dom/StructuredCloneUtils.h" #include "mozilla/jsipc/CpowHolder.h" +class nsIFrameLoader; + namespace mozilla { namespace dom { @@ -229,7 +231,8 @@ public: static nsFrameMessageManager* NewProcessMessageManager(bool aIsRemote); - nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage, + nsresult ReceiveMessage(nsISupports* aTarget, nsIFrameLoader* aTargetFrameLoader, + const nsAString& aMessage, bool aIsSync, const StructuredCloneData* aCloneData, mozilla::jsipc::CpowHolder* aCpows, nsIPrincipal* aPrincipal, InfallibleTArray* aJSONRetVal); @@ -293,7 +296,8 @@ private: JS::MutableHandle aRetval, bool aIsSync); - nsresult ReceiveMessage(nsISupports* aTarget, bool aTargetClosed, const nsAString& aMessage, + nsresult ReceiveMessage(nsISupports* aTarget, nsIFrameLoader* aTargetFrameLoader, + bool aTargetClosed, const nsAString& aMessage, bool aIsSync, const StructuredCloneData* aCloneData, mozilla::jsipc::CpowHolder* aCpows, nsIPrincipal* aPrincipal, InfallibleTArray* aJSONRetVal); @@ -369,7 +373,8 @@ public: JS::Handle aCpows, nsIPrincipal* aPrincipal); - void ReceiveMessage(nsISupports* aTarget, nsFrameMessageManager* aManager); + void ReceiveMessage(nsISupports* aTarget, nsIFrameLoader* aTargetFrameLoader, + nsFrameMessageManager* aManager); private: nsSameProcessAsyncMessageBase(const nsSameProcessAsyncMessageBase&); diff --git a/dom/base/nsIMessageManager.idl b/dom/base/nsIMessageManager.idl index fdb926485eed..012a3cb33e0b 100644 --- a/dom/base/nsIMessageManager.idl +++ b/dom/base/nsIMessageManager.idl @@ -8,6 +8,7 @@ interface nsIDOMWindow; interface nsIDocShell; interface nsIContent; +interface nsIFrameLoader; interface nsIPrincipal; /** @@ -383,10 +384,11 @@ interface nsIContentFrameMessageManager : nsIMessageManagerGlobal readonly attribute nsIDocShell docShell; }; -[uuid(a9e07e89-7125-48e3-bf73-2cbae7fc5b1c)] +[uuid(9c6bd4d7-88d2-46d6-8606-f2d57d46f051)] interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager { [notxpcom] nsIContent getOwnerContent(); + [notxpcom] void cacheFrameLoader(in nsIFrameLoader aFrameLoader); }; [scriptable, builtinclass, uuid(d0c799a2-d5ff-4a75-acbb-b8c8347944a6)] diff --git a/dom/base/nsInProcessTabChildGlobal.cpp b/dom/base/nsInProcessTabChildGlobal.cpp index 64e200b7879d..6717af09661d 100644 --- a/dom/base/nsInProcessTabChildGlobal.cpp +++ b/dom/base/nsInProcessTabChildGlobal.cpp @@ -42,7 +42,8 @@ nsInProcessTabChildGlobal::DoSendBlockingMessage(JSContext* aCx, if (mChromeMessageManager) { SameProcessCpowHolder cpows(js::GetRuntime(aCx), aCpows); nsRefPtr mm = mChromeMessageManager; - mm->ReceiveMessage(mOwner, aMessage, true, &aData, &cpows, aPrincipal, + nsCOMPtr fl = GetFrameLoader(); + mm->ReceiveMessage(mOwner, fl, aMessage, true, &aData, &cpows, aPrincipal, aJSONRetVal); } return true; @@ -65,7 +66,8 @@ public: virtual nsresult HandleMessage() override { - ReceiveMessage(mTabChild->mOwner, mTabChild->mChromeMessageManager); + nsCOMPtr fl = mTabChild->GetFrameLoader(); + ReceiveMessage(mTabChild->mOwner, fl, mTabChild->mChromeMessageManager); return NS_OK; } nsRefPtr mTabChild; @@ -175,6 +177,12 @@ NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) NS_IMPL_ADDREF_INHERITED(nsInProcessTabChildGlobal, DOMEventTargetHelper) NS_IMPL_RELEASE_INHERITED(nsInProcessTabChildGlobal, DOMEventTargetHelper) +void +nsInProcessTabChildGlobal::CacheFrameLoader(nsIFrameLoader* aFrameLoader) +{ + mFrameLoader = aFrameLoader; +} + NS_IMETHODIMP nsInProcessTabChildGlobal::GetContent(nsIDOMWindow** aContent) { @@ -336,3 +344,14 @@ nsInProcessTabChildGlobal::LoadFrameScript(const nsAString& aURL, bool aRunInGlo LoadScriptInternal(aURL, aRunInGlobalScope); mLoadingScript = tmp; } + +already_AddRefed +nsInProcessTabChildGlobal::GetFrameLoader() +{ + nsCOMPtr owner = do_QueryInterface(mOwner); + nsCOMPtr fl = owner ? owner->GetFrameLoader() : nullptr; + if (!fl) { + fl = mFrameLoader; + } + return fl.forget(); +} diff --git a/dom/base/nsInProcessTabChildGlobal.h b/dom/base/nsInProcessTabChildGlobal.h index c15b0f8e16a2..20c05f9637cd 100644 --- a/dom/base/nsInProcessTabChildGlobal.h +++ b/dom/base/nsInProcessTabChildGlobal.h @@ -150,6 +150,9 @@ public: { MOZ_CRASH("nsInProcessTabChildGlobal doesn't use DOM bindings!"); } + + already_AddRefed GetFrameLoader(); + protected: virtual ~nsInProcessTabChildGlobal(); @@ -165,6 +168,11 @@ protected: // PreHandleEvent. bool mIsBrowserOrAppFrame; bool mPreventEventsEscaping; + + // We keep a strong reference to the frameloader after we've started + // teardown. This allows us to dispatch message manager messages during this + // time. + nsCOMPtr mFrameLoader; public: nsIContent* mOwner; nsFrameMessageManager* mChromeMessageManager; diff --git a/dom/base/test/browser.ini b/dom/base/test/browser.ini index bb1c9c70b55d..a64380ef2741 100644 --- a/dom/base/test/browser.ini +++ b/dom/base/test/browser.ini @@ -7,6 +7,7 @@ skip-if = e10s # Bug ?????? - test directly touches content (contentWindow.ifram [browser_bug902350.js] skip-if = e10s # Bug ?????? - test e10s utils don't support load events from iframe etc, which this test relies on. [browser_messagemanager_loadprocessscript.js] +[browser_messagemanager_targetframeloader.js] [browser_pagehide_on_tab_close.js] skip-if = e10s # this tests non-e10s behavior. it's not expected to work in e10s. [browser_messagemanager_unload.js] diff --git a/dom/base/test/browser_messagemanager_targetframeloader.js b/dom/base/test/browser_messagemanager_targetframeloader.js new file mode 100644 index 000000000000..32575d0738d6 --- /dev/null +++ b/dom/base/test/browser_messagemanager_targetframeloader.js @@ -0,0 +1,31 @@ +function frameScript() +{ + sendSyncMessage("Test:Message"); + sendAsyncMessage("Test:Message"); + sendAsyncMessage("Test:Done"); +} + +function test() { + waitForExplicitFinish(); + + var newTab = gBrowser.addTab("about:blank"); + gBrowser.selectedTab = newTab; + + let browser = newTab.linkedBrowser; + let frameLoader = browser.frameLoader; + ok(frameLoader !== null, "frameLoader looks okay"); + + browser.messageManager.loadFrameScript("data:,(" + frameScript.toString() + ")()", false); + + browser.messageManager.addMessageListener("Test:Message", (msg) => { + ok(msg.target === browser, " is correct"); + ok(msg.targetFrameLoader === frameLoader, "frameLoader is correct"); + ok(browser.frameLoader === msg.targetFrameLoader, "browser frameloader is correct"); + }); + + browser.messageManager.addMessageListener("Test:Done", () => { + info("Finished"); + gBrowser.removeCurrentTab(); + finish(); + }); +} diff --git a/dom/base/test/browser_messagemanager_unload.js b/dom/base/test/browser_messagemanager_unload.js index 5490ec73cf14..413e384932d7 100644 --- a/dom/base/test/browser_messagemanager_unload.js +++ b/dom/base/test/browser_messagemanager_unload.js @@ -70,6 +70,8 @@ function test() { gBrowser.selectedTab = newTab; let browser = newTab.linkedBrowser; + let frameLoader = browser.frameLoader; + ok(frameLoader !== null, "frameLoader looks okay"); browser.messageManager.loadFrameScript("data:,(" + frameScript.toString() + ")()", false); @@ -80,6 +82,8 @@ function test() { let index = 0; browser.messageManager.addMessageListener("Test:Event", (msg) => { ok(msg.target === browser, " is correct"); + ok(msg.targetFrameLoader === frameLoader, "frameLoader is correct"); + ok(browser.frameLoader === null, "browser frameloader null during teardown"); info(JSON.stringify(msg.data)); diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 3aca9f126ca4..74b1a8b36833 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -2019,7 +2019,7 @@ ContentChild::RecvAsyncMessage(const nsString& aMsg, if (cpm) { StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForChild(aData); CrossProcessCpowHolder cpows(this, aCpows); - cpm->ReceiveMessage(static_cast(cpm.get()), + cpm->ReceiveMessage(static_cast(cpm.get()), nullptr, aMsg, false, &cloneData, &cpows, aPrincipal, nullptr); } return true; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index aba79b966c9c..0bc87b8b197f 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -1703,7 +1703,7 @@ ContentParent::ShutDownMessageManager() } mMessageManager->ReceiveMessage( - static_cast(mMessageManager.get()), + static_cast(mMessageManager.get()), nullptr, CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr, nullptr, nullptr, nullptr); diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 461a1de6a072..51402d5846a5 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -496,7 +496,7 @@ TabChildBase::DispatchMessageManagerMessage(const nsAString& aMessageName, // content manipulate the frame state. nsRefPtr mm = static_cast(mTabChildGlobal->mMessageManager.get()); - mm->ReceiveMessage(static_cast(mTabChildGlobal), + mm->ReceiveMessage(static_cast(mTabChildGlobal), nullptr, aMessageName, false, &cloneData, nullptr, nullptr, nullptr); } @@ -2689,7 +2689,7 @@ TabChild::RecvAsyncMessage(const nsString& aMessage, nsRefPtr mm = static_cast(mTabChildGlobal->mMessageManager.get()); CrossProcessCpowHolder cpows(Manager(), aCpows); - mm->ReceiveMessage(static_cast(mTabChildGlobal), + mm->ReceiveMessage(static_cast(mTabChildGlobal), nullptr, aMessage, false, &cloneData, &cpows, aPrincipal, nullptr); } return true; diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 12a57bc050ff..a0e65476f787 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -2484,6 +2484,7 @@ TabParent::ReceiveMessage(const nsString& aMessage, frameLoader->GetFrameMessageManager(); manager->ReceiveMessage(mFrameElement, + frameLoader, aMessage, aSync, aCloneData, diff --git a/dom/ipc/nsIContentChild.cpp b/dom/ipc/nsIContentChild.cpp index 929ea9490faa..c476c2ba9c62 100644 --- a/dom/ipc/nsIContentChild.cpp +++ b/dom/ipc/nsIContentChild.cpp @@ -117,7 +117,7 @@ nsIContentChild::RecvAsyncMessage(const nsString& aMsg, if (cpm) { StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForChild(aData); CrossProcessCpowHolder cpows(this, aCpows); - cpm->ReceiveMessage(static_cast(cpm.get()), + cpm->ReceiveMessage(static_cast(cpm.get()), nullptr, aMsg, false, &cloneData, &cpows, aPrincipal, nullptr); } return true; diff --git a/dom/ipc/nsIContentParent.cpp b/dom/ipc/nsIContentParent.cpp index 01a5685150ef..565fa8d86ca9 100644 --- a/dom/ipc/nsIContentParent.cpp +++ b/dom/ipc/nsIContentParent.cpp @@ -194,7 +194,7 @@ nsIContentParent::RecvSyncMessage(const nsString& aMsg, if (ppm) { StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); CrossProcessCpowHolder cpows(this, aCpows); - ppm->ReceiveMessage(static_cast(ppm.get()), + ppm->ReceiveMessage(static_cast(ppm.get()), nullptr, aMsg, true, &cloneData, &cpows, aPrincipal, aRetvals); } return true; @@ -221,7 +221,7 @@ nsIContentParent::RecvRpcMessage(const nsString& aMsg, if (ppm) { StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); CrossProcessCpowHolder cpows(this, aCpows); - ppm->ReceiveMessage(static_cast(ppm.get()), + ppm->ReceiveMessage(static_cast(ppm.get()), nullptr, aMsg, true, &cloneData, &cpows, aPrincipal, aRetvals); } return true; @@ -247,7 +247,7 @@ nsIContentParent::RecvAsyncMessage(const nsString& aMsg, if (ppm) { StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); CrossProcessCpowHolder cpows(this, aCpows); - ppm->ReceiveMessage(static_cast(ppm.get()), + ppm->ReceiveMessage(static_cast(ppm.get()), nullptr, aMsg, false, &cloneData, &cpows, aPrincipal, nullptr); } return true;