☠☠ backed out by eb8a3fd355ba ☠ ☠ | |
author | Philipp von Weitershausen <philipp@weitershausen.de> |
Wed, 26 Sep 2012 00:41:51 -0700 | |
changeset 108118 | be95f234ff6e36bcd6b04d40668239684f7f3a70 |
parent 108117 | bea00714789ad22fd94250ea8f713a80191b0c5d |
child 108119 | 04f739fbc190ab5b9f9bb76bb865f19c59a7f8b8 |
push id | 23539 |
push user | ryanvm@gmail.com |
push date | Wed, 26 Sep 2012 22:55:55 +0000 |
treeherder | autoland@ec079fd92224 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | smaug |
bugs | 776832 |
milestone | 18.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/base/public/nsIMessageManager.idl +++ b/content/base/public/nsIMessageManager.idl @@ -330,8 +330,35 @@ interface nsIFrameScriptLoader : nsISupp */ void loadFrameScript(in AString aURL, in boolean aAllowDelayedLoad); /** * Removes aURL from the list of scripts which support delayed load. */ 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); + +};
--- a/content/base/src/nsCCUncollectableMarker.cpp +++ b/content/base/src/nsCCUncollectableMarker.cpp @@ -115,21 +115,21 @@ MarkMessageManagers() nsCOMPtr<nsIMessageListenerManager> childMM; windowMM->GetChildAt(j, getter_AddRefs(childMM)); if (!childMM) { continue; } nsCOMPtr<nsIMessageSender> tabMM = do_QueryInterface(childMM); tabMM->MarkForCC(); //XXX hack warning, but works, since we know that - // callback data is frameloader. - void* cb = static_cast<nsFrameMessageManager*>(tabMM.get())-> - GetCallbackData(); - nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb); - if (fl) { + // callback is frameloader. + mozilla::dom::ipc::MessageManagerCallback* cb = + static_cast<nsFrameMessageManager*>(tabMM.get())->GetCallback(); + if (cb) { + nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb); nsIDOMEventTarget* et = fl->GetTabChildGlobalAsEventTarget(); if (!et) { continue; } static_cast<nsInProcessTabChildGlobal*>(et)->MarkForCC(); nsEventListenerManager* elm = et->GetListenerManager(false); if (elm) { elm->UnmarkGrayJSListeners();
--- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -71,16 +71,17 @@ #include "nsThreadUtils.h" #include "nsIDOMChromeWindow.h" #include "nsInProcessTabChildGlobal.h" #include "Layers.h" +#include "AppProcessPermissions.h" #include "ContentParent.h" #include "TabParent.h" #include "mozilla/GuardObjects.h" #include "mozilla/Preferences.h" #include "mozilla/unused.h" #include "mozilla/dom/Element.h" #include "mozilla/layout/RenderFrameParent.h" #include "nsIAppsService.h" @@ -92,16 +93,17 @@ #include "mozilla/dom/StructuredCloneUtils.h" #ifdef MOZ_XUL #include "nsXULPopupManager.h" #endif using namespace mozilla; using namespace mozilla::dom; +using namespace mozilla::dom::ipc; using namespace mozilla::layers; using namespace mozilla::layout; typedef FrameMetrics::ViewID ViewID; class nsAsyncDocShellDestroyer : public nsRunnable { public: nsAsyncDocShellDestroyer(nsIDocShell* aDocShell) @@ -1252,23 +1254,23 @@ nsFrameLoader::SwapWithOtherLoader(nsFra JSContext* thisCx = mMessageManager ? mMessageManager->GetJSContext() : nullptr; JSContext* otherCx = aOther->mMessageManager ? aOther->mMessageManager->GetJSContext() : nullptr; if (mMessageManager) { 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); aFirstToSwap.swap(aSecondToSwap); // Drop any cached content viewers in the two session histories. nsCOMPtr<nsISHistoryInternal> ourInternalHistory = do_QueryInterface(ourHistory); @@ -2150,38 +2152,37 @@ nsFrameLoader::CreateStaticClone(nsIFram NS_ENSURE_STATE(doc); nsCOMPtr<nsIDocument> clonedDoc = doc->CreateStaticClone(dest->mDocShell); nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc); viewer->SetDOMDocument(clonedDOMDoc); return NS_OK; } -bool LoadScript(void* aCallbackData, const nsAString& aURL) +bool +nsFrameLoader::DoLoadFrameScript(const nsAString& aURL) { - mozilla::dom::PBrowserParent* tabParent = - static_cast<nsFrameLoader*>(aCallbackData)->GetRemoteBrowser(); + mozilla::dom::PBrowserParent* tabParent = GetRemoteBrowser(); if (tabParent) { return tabParent->SendLoadRemoteScript(nsString(aURL)); } - nsFrameLoader* fl = static_cast<nsFrameLoader*>(aCallbackData); nsRefPtr<nsInProcessTabChildGlobal> tabChild = - static_cast<nsInProcessTabChildGlobal*>(fl->GetTabChildGlobalAsEventTarget()); + static_cast<nsInProcessTabChildGlobal*>(GetTabChildGlobalAsEventTarget()); if (tabChild) { tabChild->LoadFrameScript(aURL); } return true; } 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)) { NS_RUNTIMEABORT("OOM"); } mClosure = aData.mClosure; } @@ -2204,22 +2205,21 @@ public: return NS_OK; } nsRefPtr<nsFrameLoader> mFrameLoader; nsString mMessage; JSAutoStructuredCloneBuffer mData; 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<nsFrameLoader*>(aCallbackData)->GetRemoteBrowser(); + PBrowserParent* tabParent = GetRemoteBrowser(); if (tabParent) { ClonedMessageData data; SerializedStructuredCloneBuffer& buffer = data.data(); buffer.data = aData.mData; buffer.dataLength = aData.mDataLength; const nsTArray<nsCOMPtr<nsIDOMBlob> >& blobs = aData.mClosure.mBlobs; @@ -2239,28 +2239,33 @@ bool SendAsyncMessageToChild(void* aCall blobParents.AppendElement(blobParent); } } return tabParent->SendAsyncMessage(nsString(aMessage), data); } - if (static_cast<nsFrameLoader*>(aCallbackData)->mChildMessageManager) { - nsRefPtr<nsIRunnable> ev = - new nsAsyncMessageToChild(static_cast<nsFrameLoader*>(aCallbackData), - aMessage, aData); + if (mChildMessageManager) { + nsRefPtr<nsIRunnable> ev = new nsAsyncMessageToChild(this, aMessage, aData); NS_DispatchToCurrentThread(ev); return true; } // We don't have any targets to send our asynchronous message to. return false; } +bool +nsFrameLoader::CheckPermission(const nsAString& aPermission) +{ + return AssertAppProcessPermission(GetRemoteBrowser(), + NS_ConvertUTF16toUTF8(aPermission).get()); +} + NS_IMETHODIMP nsFrameLoader::GetMessageManager(nsIMessageSender** aManager) { EnsureMessageManager(); if (mMessageManager) { CallQueryInterface(mMessageManager, aManager); } return NS_OK; @@ -2331,17 +2336,17 @@ nsFrameLoader::EnsureMessageManager() } if (!mIsTopLevelContent && !OwnerIsBrowserFrame() && !mRemoteFrame) { return NS_OK; } if (mMessageManager) { if (ShouldUseRemoteProcess()) { - mMessageManager->SetCallbackData(mRemoteBrowserShown ? this : nullptr); + mMessageManager->SetCallback(mRemoteBrowserShown ? this : nullptr); } return NS_OK; } nsIScriptContext* sctx = mOwnerContent->GetContextForEventHandlers(&rv); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_STATE(sctx); JSContext* cx = sctx->GetNativeContext(); @@ -2350,34 +2355,30 @@ nsFrameLoader::EnsureMessageManager() nsCOMPtr<nsIDOMChromeWindow> chromeWindow = do_QueryInterface(GetOwnerDoc()->GetWindow()); nsCOMPtr<nsIMessageBroadcaster> parentManager; if (chromeWindow) { chromeWindow->GetMessageManager(getter_AddRefs(parentManager)); } if (ShouldUseRemoteProcess()) { - mMessageManager = new nsFrameMessageManager(true, /* aChrome */ - nullptr, - SendAsyncMessageToChild, - LoadScript, - mRemoteBrowserShown ? this : nullptr, + mMessageManager = new nsFrameMessageManager(mRemoteBrowserShown ? this : nullptr, static_cast<nsFrameMessageManager*>(parentManager.get()), - cx); + cx, + MM_CHROME); } else { - mMessageManager = new nsFrameMessageManager(true, /* aChrome */ - nullptr, - SendAsyncMessageToChild, - LoadScript, - nullptr, + mMessageManager = new nsFrameMessageManager(nullptr, static_cast<nsFrameMessageManager*>(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; } nsIDOMEventTarget* nsFrameLoader::GetTabChildGlobalAsEventTarget() { return static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get());
--- a/content/base/src/nsFrameLoader.h +++ b/content/base/src/nsFrameLoader.h @@ -33,16 +33,17 @@ class nsITabParent; class nsIDocShellTreeItem; class nsIDocShellTreeOwner; class nsIDocShellTreeNode; namespace mozilla { namespace dom { class PBrowserParent; class TabParent; +struct StructuredCloneData; } namespace layout { class RenderFrameParent; } } #ifdef MOZ_WIDGET_GTK2 @@ -135,17 +136,18 @@ private: ViewID mScrollId; ViewConfig mConfig; }; 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; typedef mozilla::dom::TabParent TabParent; typedef mozilla::layout::RenderFrameParent RenderFrameParent; protected: nsFrameLoader(mozilla::dom::Element* aOwner, bool aNetworkCreated); @@ -175,16 +177,25 @@ public: NS_HIDDEN_(nsresult) CheckForRecursiveLoad(nsIURI* aURI); nsresult ReallyStartLoading(); void Finalize(); nsIDocShell* GetExistingDocShell() { return mDocShell; } 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. */ bool Show(int32_t marginWidth, int32_t marginHeight, int32_t scrollbarPrefX, int32_t scrollbarPrefY, nsSubDocumentFrame* frame); /**
--- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -2,26 +2,28 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "base/basictypes.h" #include "nsFrameMessageManager.h" +#include "AppProcessPermissions.h" #include "ContentChild.h" #include "ContentParent.h" #include "nsContentUtils.h" #include "nsError.h" #include "nsIXPConnect.h" #include "jsapi.h" #include "nsJSUtils.h" #include "nsJSPrincipals.h" #include "nsNetUtil.h" #include "nsScriptLoader.h" +#include "nsFrameLoader.h" #include "nsIJSContextStack.h" #include "nsIXULRuntime.h" #include "nsIScriptError.h" #include "nsIConsoleService.h" #include "nsIProtocolHandler.h" #include "nsIScriptSecurityManager.h" #include "nsIJSRuntimeService.h" #include "nsIDOMClassInfo.h" @@ -34,16 +36,18 @@ #include <android/log.h> #endif #ifdef XP_WIN #include <windows.h> #endif using namespace mozilla; using namespace mozilla::dom; +using namespace mozilla::dom::ipc; + static bool IsChromeProcess() { nsCOMPtr<nsIXULRuntime> rt = do_GetService("@mozilla.org/xre/runtime;1"); if (!rt) return true; @@ -98,16 +102,20 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION( /* nsIContentFrameMessageManager is accessible only in TabChildGlobal. */ NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIContentFrameMessageManager, !mChrome && !mIsProcessManager) /* Frame message managers (non-process message managers) support nsIFrameScriptLoader. */ 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, mChrome && !mIsBroadcaster) NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameMessageManager) NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameMessageManager) @@ -154,28 +162,28 @@ nsFrameMessageManager::RemoveMessageList NS_IMETHODIMP nsFrameMessageManager::LoadFrameScript(const nsAString& aURL, bool aAllowDelayedLoad) { if (aAllowDelayedLoad) { 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) { nsRefPtr<nsFrameMessageManager> mm = static_cast<nsFrameMessageManager*>(mChildManagers[i]); if (mm) { // Use false here, so that child managers don't cache the script, which // is already cached in the parent. @@ -237,119 +245,116 @@ nsFrameMessageManager::SendSyncMessage(c const jsval& aObject, JSContext* aCx, uint8_t aArgc, jsval* aRetval) { 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<nsString> 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<nsString> 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<const jschar*>(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<const jschar*>(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<nsFrameMessageManager*>(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; } nsresult nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName, const jsval& aObject, JSContext* aCx, - uint8_t aArgc, - ShouldBroadcast aBroadcast) + uint8_t aArgc) { 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(); - return DispatchAsyncMessageInternal(aMessageName, data, aBroadcast); + return DispatchAsyncMessageInternal(aMessageName, data); } // nsIMessageSender NS_IMETHODIMP nsFrameMessageManager::SendAsyncMessage(const nsAString& aMessageName, const jsval& aObject, JSContext* aCx, uint8_t aArgc) { - return DispatchAsyncMessage(aMessageName, aObject, aCx, aArgc, DONT_BROADCAST); + return DispatchAsyncMessage(aMessageName, aObject, aCx, aArgc); } // nsIMessageBroadcaster NS_IMETHODIMP nsFrameMessageManager::BroadcastAsyncMessage(const nsAString& aMessageName, const jsval& aObject, JSContext* aCx, uint8_t aArgc) { - return DispatchAsyncMessage(aMessageName, aObject, aCx, aArgc, BROADCAST); + return DispatchAsyncMessage(aMessageName, aObject, aCx, aArgc); } NS_IMETHODIMP nsFrameMessageManager::GetChildCount(uint32_t* aChildCount) { *aChildCount = static_cast<uint32_t>(mChildManagers.Count()); return NS_OK; } @@ -413,16 +418,33 @@ nsFrameMessageManager::Btoa(const nsAStr NS_IMETHODIMP nsFrameMessageManager::Atob(const nsAString& aAsciiString, nsAString& aBinaryData) { 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 { public: MMListenerRemover(nsFrameMessageManager* aMM) : mWasHandlingMessage(aMM->mHandlingMessage) , mMM(aMM) { @@ -605,20 +627,25 @@ nsFrameMessageManager::AddChildManager(n } for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) { aManager->LoadFrameScript(mPendingScripts[i], false); } } } 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); } if (aLoadScripts) { for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) { LoadFrameScript(mPendingScripts[i], false); } @@ -628,50 +655,45 @@ nsFrameMessageManager::SetCallbackData(v void nsFrameMessageManager::RemoveFromParent() { if (mParentManager) { mParentManager->RemoveChildManager(this); } mParentManager = nullptr; - mCallbackData = nullptr; + mCallback = nullptr; + mOwnedCallback = nullptr; mContext = nullptr; } void nsFrameMessageManager::Disconnect(bool aRemoveFromParent) { if (mParentManager && aRemoveFromParent) { mParentManager->RemoveChildManager(this); } mDisconnected = true; mParentManager = nullptr; - mCallbackData = nullptr; + mCallback = nullptr; + mOwnedCallback = nullptr; mContext = nullptr; if (!mHandlingMessage) { mListeners.Clear(); } } nsresult NS_NewGlobalMessageManager(nsIMessageBroadcaster** aResult) { NS_ENSURE_TRUE(IsChromeProcess(), NS_ERROR_NOT_AVAILABLE); - nsFrameMessageManager* mm = new nsFrameMessageManager(true /* aChrome */, - nullptr, - nullptr, - nullptr, + nsFrameMessageManager* mm = new nsFrameMessageManager(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); } void ContentScriptErrorReporter(JSContext* aCx, const char* aMessage, JSErrorReport* aReport) { @@ -996,46 +1018,16 @@ nsFrameScriptExecutor::Traverse(nsFrameS NS_IMPL_ISUPPORTS1(nsScriptCacheCleaner, nsIObserver) nsFrameMessageManager* nsFrameMessageManager::sChildProcessManager = nullptr; nsFrameMessageManager* nsFrameMessageManager::sParentProcessManager = nullptr; nsFrameMessageManager* nsFrameMessageManager::sSameProcessParentManager = nullptr; nsTArray<nsCOMPtr<nsIRunnable> >* nsFrameMessageManager::sPendingSameProcessAsyncMessages = nullptr; -bool SendAsyncMessageToChildProcess(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData) -{ - mozilla::dom::ContentParent* cp = - static_cast<mozilla::dom::ContentParent*>(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<nsCOMPtr<nsIDOMBlob> >& blobs = aData.mClosure.mBlobs; - if (!blobs.IsEmpty()) { - InfallibleTArray<PBlobParent*>& 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 { public: nsAsyncMessageToSameProcessChild(const nsAString& aMessage, const StructuredCloneData& aData) : mMessage(aMessage) { @@ -1059,34 +1051,74 @@ public: } return NS_OK; } nsString mMessage; JSAutoStructuredCloneBuffer mData; StructuredCloneClosure mClosure; }; -bool SendAsyncMessageToSameProcessChild(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData) + +/** + * Send messages to an imaginary child process in a single-process scenario. + */ +class SameParentProcessMessageManagerCallback : public MessageManagerCallback { - nsRefPtr<nsIRunnable> ev = - new nsAsyncMessageToSameProcessChild(aMessage, aData); - NS_DispatchToCurrentThread(ev); - return true; -} +public: + SameParentProcessMessageManagerCallback() + { + MOZ_COUNT_CTOR(SameParentProcessMessageManagerCallback); + } + virtual ~SameParentProcessMessageManagerCallback() + { + MOZ_COUNT_DTOR(SameParentProcessMessageManagerCallback); + } + + virtual bool DoSendAsyncMessage(const nsAString& aMessage, + const StructuredCloneData& aData) + { + nsRefPtr<nsIRunnable> 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; + } -bool SendSyncMessageToParentProcess(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData, - InfallibleTArray<nsString>* aJSONRetVal) +}; + + +/** + * Send messages to the parent process. + */ +class ChildProcessMessageManagerCallback : public MessageManagerCallback { - mozilla::dom::ContentChild* cc = - mozilla::dom::ContentChild::GetSingleton(); - if (cc) { +public: + ChildProcessMessageManagerCallback() + { + MOZ_COUNT_CTOR(ChildProcessMessageManagerCallback); + } + virtual ~ChildProcessMessageManagerCallback() + { + MOZ_COUNT_DTOR(ChildProcessMessageManagerCallback); + } + + virtual bool DoSendSyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData, + InfallibleTArray<nsString>* aJSONRetVal) + { + mozilla::dom::ContentChild* cc = + mozilla::dom::ContentChild::GetSingleton(); + if (!cc) { + return true; + } ClonedMessageData data; SerializedStructuredCloneBuffer& buffer = data.data(); buffer.data = aData.mData; buffer.dataLength = aData.mDataLength; const nsTArray<nsCOMPtr<nsIDOMBlob> >& blobs = aData.mClosure.mBlobs; if (!blobs.IsEmpty()) { InfallibleTArray<PBlobChild*>& blobChildList = data.blobsChild(); uint32_t length = blobs.Length(); @@ -1094,51 +1126,27 @@ bool SendSyncMessageToParentProcess(void for (uint32_t i = 0; i < length; ++i) { BlobChild* blobChild = cc->GetOrCreateActorForBlob(blobs[i]); if (!blobChild) { return false; } 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<nsString>* aJSONRetVal) -{ - nsTArray<nsCOMPtr<nsIRunnable> > asyncMessages; - if (nsFrameMessageManager::sPendingSameProcessAsyncMessages) { - asyncMessages.SwapElements(*nsFrameMessageManager::sPendingSameProcessAsyncMessages); - uint32_t len = asyncMessages.Length(); - for (uint32_t i = 0; i < len; ++i) { - nsCOMPtr<nsIRunnable> 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<nsFrameMessageManager> ppm = nsFrameMessageManager::sSameProcessParentManager; - ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(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; buffer.dataLength = aData.mDataLength; const nsTArray<nsCOMPtr<nsIDOMBlob> >& blobs = aData.mClosure.mBlobs; if (!blobs.IsEmpty()) { InfallibleTArray<PBlobChild*>& blobChildList = data.blobsChild(); uint32_t length = blobs.Length(); @@ -1148,24 +1156,25 @@ bool SendAsyncMessageToParentProcess(voi if (!blobChild) { return false; } blobChildList.AppendElement(blobChild); } } 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)) { NS_RUNTIMEABORT("OOM"); } mClosure = aData.mClosure; } @@ -1187,95 +1196,126 @@ public: } return NS_OK; } nsString mMessage; JSAutoStructuredCloneBuffer mData; 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<nsCOMPtr<nsIRunnable> >; +public: + SameChildProcessMessageManagerCallback() + { + MOZ_COUNT_CTOR(SameChildProcessMessageManagerCallback); + } + virtual ~SameChildProcessMessageManagerCallback() + { + MOZ_COUNT_DTOR(SameChildProcessMessageManagerCallback); } - nsCOMPtr<nsIRunnable> ev = - new nsAsyncMessageToSameProcessParent(aMessage, aData); - nsFrameMessageManager::sPendingSameProcessAsyncMessages->AppendElement(ev); - NS_DispatchToCurrentThread(ev); - return true; -} + + virtual bool DoSendSyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData, + InfallibleTArray<nsString>* aJSONRetVal) + { + nsTArray<nsCOMPtr<nsIRunnable> > asyncMessages; + if (nsFrameMessageManager::sPendingSameProcessAsyncMessages) { + asyncMessages.SwapElements(*nsFrameMessageManager::sPendingSameProcessAsyncMessages); + uint32_t len = asyncMessages.Length(); + for (uint32_t i = 0; i < len; ++i) { + nsCOMPtr<nsIRunnable> async = asyncMessages[i]; + async->Run(); + } + } + if (nsFrameMessageManager::sSameProcessParentManager) { + nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sSameProcessParentManager; + ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(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<nsIRunnable> >; + } + nsCOMPtr<nsIRunnable> ev = + new nsAsyncMessageToSameProcessParent(aMessage, aData); + nsFrameMessageManager::sPendingSameProcessAsyncMessages->AppendElement(ev); + NS_DispatchToCurrentThread(ev); + return true; + } + +}; + // This creates the global parent process message manager. nsresult NS_NewParentProcessMessageManager(nsIMessageBroadcaster** aResult) { NS_ASSERTION(!nsFrameMessageManager::sParentProcessManager, "Re-creating sParentProcessManager"); NS_ENSURE_TRUE(IsChromeProcess(), NS_ERROR_NOT_AVAILABLE); - nsRefPtr<nsFrameMessageManager> mm = new nsFrameMessageManager(true /* aChrome */, - nullptr, - nullptr, + nsRefPtr<nsFrameMessageManager> mm = new nsFrameMessageManager(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) { if (!nsFrameMessageManager::sParentProcessManager) { nsCOMPtr<nsIMessageBroadcaster> dummy; NS_NewParentProcessMessageManager(getter_AddRefs(dummy)); } - nsFrameMessageManager* mm = new nsFrameMessageManager(true /* aChrome */, - nullptr, - aProcess ? SendAsyncMessageToChildProcess - : SendAsyncMessageToSameProcessChild, - nullptr, - aProcess ? static_cast<void*>(aProcess) - : static_cast<void*>(&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; } nsresult 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); } bool nsFrameMessageManager::MarkForCC() {
--- a/content/base/src/nsFrameMessageManager.h +++ b/content/base/src/nsFrameMessageManager.h @@ -19,79 +19,112 @@ #include "nsDataHashtable.h" #include "mozilla/Services.h" #include "nsIObserverService.h" #include "nsThreadUtils.h" #include "mozilla/Attributes.h" 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<nsString>* 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; struct JSObject; struct nsMessageListenerInfo { nsCOMPtr<nsIMessageListener> mListener; nsCOMPtr<nsIAtom> mMessage; }; -typedef bool (*nsLoadScriptCallback)(void* aCallbackData, const nsAString& aURL); -typedef bool (*nsSyncMessageCallback)(void* aCallbackData, - const nsAString& aMessage, - const mozilla::dom::StructuredCloneData& aData, - InfallibleTArray<nsString>* 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() { for (int32_t i = mChildManagers.Count(); i > 0; --i) { static_cast<nsFrameMessageManager*>(mChildManagers[i - 1])-> Disconnect(false); } @@ -114,45 +147,48 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameMessageManager, nsIContentFrameMessageManager) NS_DECL_NSIMESSAGELISTENERMANAGER NS_DECL_NSIMESSAGESENDER NS_DECL_NSIMESSAGEBROADCASTER NS_DECL_NSISYNCMESSAGESENDER NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER NS_DECL_NSIFRAMESCRIPTLOADER + NS_DECL_NSIPERMISSIONCHECKER static nsFrameMessageManager* NewProcessMessageManager(mozilla::dom::ContentParent* aProcess); nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage, bool aSync, const StructuredCloneData* aCloneData, JSObject* aObjectsArray, InfallibleTArray<nsString>* aJSONRetVal, JSContext* aContext = nullptr); void AddChildManager(nsFrameMessageManager* aManager, bool aLoadScripts = true); void RemoveChildManager(nsFrameMessageManager* aManager) { mChildManagers.RemoveObject(aManager); } + void Disconnect(bool aRemoveFromParent = true); - 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(); nsFrameMessageManager* GetParentManager() { return mParentManager; } void SetParentManager(nsFrameMessageManager* aParent) { NS_ASSERTION(!mParentManager, "We have parent manager already!"); NS_ASSERTION(mChrome, "Should not set parent manager!"); @@ -169,26 +205,25 @@ public: { return sChildProcessManager; } protected: friend class MMListenerRemover; nsTArray<nsMessageListenerInfo> mListeners; nsCOMArray<nsIContentFrameMessageManager> 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<mozilla::dom::ipc::MessageManagerCallback> mOwnedCallback; nsFrameMessageManager* mParentManager; - nsSyncMessageCallback mSyncCallback; - nsAsyncMessageCallback mAsyncCallback; - nsLoadScriptCallback mLoadScriptCallback; - void* mCallbackData; JSContext* mContext; nsTArray<nsString> mPendingScripts; public: static nsFrameMessageManager* sParentProcessManager; static nsFrameMessageManager* sChildProcessManager; static nsFrameMessageManager* sSameProcessParentManager; static nsTArray<nsCOMPtr<nsIRunnable> >* sPendingSameProcessAsyncMessages; };
--- a/content/base/src/nsInProcessTabChildGlobal.cpp +++ b/content/base/src/nsInProcessTabChildGlobal.cpp @@ -20,34 +20,31 @@ #include "xpcpublic.h" #include "nsIMozBrowserFrame.h" #include "nsDOMClassInfoID.h" #include "mozilla/dom/StructuredCloneUtils.h" using mozilla::dom::StructuredCloneData; using mozilla::dom::StructuredCloneClosure; -bool SendSyncMessageToParent(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData, - InfallibleTArray<nsString>* aJSONRetVal) +bool +nsInProcessTabChildGlobal::DoSendSyncMessage(const nsAString& aMessage, + const StructuredCloneData& aData, + InfallibleTArray<nsString>* aJSONRetVal) { - nsInProcessTabChildGlobal* tabChild = - static_cast<nsInProcessTabChildGlobal*>(aCallbackData); - nsCOMPtr<nsIContent> owner = tabChild->mOwner; nsTArray<nsCOMPtr<nsIRunnable> > asyncMessages; - asyncMessages.SwapElements(tabChild->mASyncMessages); + asyncMessages.SwapElements(mASyncMessages); uint32_t len = asyncMessages.Length(); for (uint32_t i = 0; i < len; ++i) { nsCOMPtr<nsIRunnable> async = asyncMessages[i]; async->Run(); } - if (tabChild->mChromeMessageManager) { - nsRefPtr<nsFrameMessageManager> mm = tabChild->mChromeMessageManager; - mm->ReceiveMessage(owner, aMessage, true, &aData, nullptr, aJSONRetVal); + if (mChromeMessageManager) { + nsRefPtr<nsFrameMessageManager> mm = mChromeMessageManager; + mm->ReceiveMessage(mOwner, aMessage, true, &aData, nullptr, aJSONRetVal); } return true; } class nsAsyncMessageToParent : public nsRunnable { public: nsAsyncMessageToParent(nsInProcessTabChildGlobal* aTabChild, @@ -77,25 +74,23 @@ public: return NS_OK; } nsRefPtr<nsInProcessTabChildGlobal> mTabChild; nsString mMessage; JSAutoStructuredCloneBuffer mData; 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<nsInProcessTabChildGlobal*>(aCallbackData); nsCOMPtr<nsIRunnable> ev = - new nsAsyncMessageToParent(tabChild, aMessage, aData); - tabChild->mASyncMessages.AppendElement(ev); + new nsAsyncMessageToParent(this, aMessage, aData); + mASyncMessages.AppendElement(ev); NS_DispatchToCurrentThread(ev); return true; } nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell, nsIContent* aOwner, nsFrameMessageManager* aChrome) : mDocShell(aShell), mInitialized(false), mLoadingScript(false), @@ -121,23 +116,20 @@ nsresult nsInProcessTabChildGlobal::Init() { #ifdef DEBUG nsresult rv = #endif 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. JSObject *global; nsIURI* docURI = mOwner->OwnerDoc()->GetDocumentURI(); if (mGlobal && NS_SUCCEEDED(mGlobal->GetJSObject(&global)) && docURI) { xpc::SetLocationForGlobal(global, docURI); }
--- a/content/base/src/nsInProcessTabChildGlobal.h +++ b/content/base/src/nsInProcessTabChildGlobal.h @@ -19,17 +19,18 @@ #include "nsIDOMElement.h" #include "nsCOMArray.h" #include "nsThreadUtils.h" 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, nsFrameMessageManager* aChrome); virtual ~nsInProcessTabChildGlobal(); NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsInProcessTabChildGlobal, nsDOMEventTargetHelper) @@ -54,16 +55,25 @@ public: NS_IMETHOD PrivateNoteIntentionalCrash(); NS_IMETHOD Btoa(const nsAString& aBinaryData, nsAString& aAsciiBase64String); NS_IMETHOD Atob(const nsAString& aAsciiString, nsAString& aBinaryData); NS_DECL_NSIINPROCESSCONTENTFRAMEMESSAGEMANAGER + /** + * MessageManagerCallback methods that we override. + */ + virtual bool DoSendSyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData, + InfallibleTArray<nsString>* 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, bool aUseCapture) { // By default add listeners only for trusted events! return nsDOMEventTargetHelper::AddEventListener(aType, aListener, aUseCapture, false, 2);
--- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -564,16 +564,17 @@ MOCHITEST_FILES_B = \ file_XHR_anon.sjs \ test_XHR_system.html \ test_XHR_parameters.html \ test_ipc_messagemanager_blob.html \ test_mixed_content_blocker.html \ file_mixed_content_main.html \ file_mixed_content_server.sjs \ test_bug789856.html \ + test_messagemanager_assertpermission.html \ $(NULL) MOCHITEST_CHROME_FILES = \ test_bug357450.js \ $(NULL) MOCHITEST_FILES_PARTS = $(foreach s,A B,MOCHITEST_FILES_$(s))
new file mode 100644 --- /dev/null +++ b/content/base/test/test_messagemanager_assertpermission.html @@ -0,0 +1,153 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>Test for the nsIPermissionChecker part of Message Managers</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body onload="runTests();"> +<p id="display"> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="application/javascript;version=1.8"> + +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = SpecialPowers.wrap(Components); + +const APP_URL = "http://example.org"; +const APP_MANIFEST = "http://example.org/manifest.webapp"; + +let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"] + .getService(Ci.nsIMessageBroadcaster); +let cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"] + .getService(Ci.nsISyncMessageSender); +let gAppsService = Cc["@mozilla.org/AppsService;1"] + .getService(Ci.nsIAppsService); + +function setUp() { + SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true); + SpecialPowers.setBoolPref("dom.ipc.browser_frames.oop_by_default", true); + SpecialPowers.addPermission("browser", true, window.document); + + let appId = gAppsService.getAppLocalIdByManifestURL(APP_MANIFEST); + SpecialPowers.addPermission("foobar", true, { url: APP_URL, + appId: appId, + isInBrowserElement: false }); + runNextTest(); +} + +function loadApp(callback) { + let iframe = document.createElement("iframe"); + iframe.setAttribute("mozapp", APP_MANIFEST); + iframe.mozbrowser = true; + iframe.src = APP_URL; + document.getElementById("content").appendChild(iframe); + + iframe.addEventListener("mozbrowserloadend", function onloadend() { + iframe.removeEventListener("mozbrowserloadend", onloadend); + callback(iframe); + }); +} + +function testSameProcess() { + // Assert permissions on the in-process child process message manager. + // It always has all permissions, including ones that were never + // assigned to anybody. + + cpmm.sendAsyncMessage("TestPermission:InProcess"); + ppmm.addMessageListener("TestPermission:InProcess", function receiveMessage(msg) { + ppmm.removeMessageListener("TestPermission:InProcess", receiveMessage); + msg = SpecialPowers.wrap(msg); + + ok(msg.target.assertPermission("frobnaz"), "in-process cpmm always has all capabilities"); + runNextTest(); + }); +} + +function testFrameMessageManager() { + // Assert permissions on the frame message manager. + + loadApp(function (iframe) { + let frameMM = SpecialPowers.getBrowserFrameMessageManager(iframe); + ok(frameMM.assertPermission("foobar"), "Frame mm has assigned permission."); + ok(!frameMM.assertPermission("frobnaz"), "Frame mm doesn't have non-existing permission."); + + // The last permission check will result in the content process + // being killed. + iframe.addEventListener("mozbrowsererror", function onerror(event) { + iframe.removeEventListener("mozbrowsererror", onerror); + ok(event.detail.type, "fatal"); + + iframe.parentNode.removeChild(iframe); + runNextTest(); + }); + }); +} + +function testChildProcessMessageManager() { + // Assert permissions on the child process message manager. We get + // one by sending a message to a frame script in the content process + // and having it reply to us via the child process message manager. + + let frameScript = 'data:,\ + var cpmm = Components.classes["@mozilla.org/childprocessmessagemanager;1"]\ + .getService(Components.interfaces.nsISyncMessageSender);\ + addMessageListener("TestPermission:OutOfProcess", function receiveMessage(msg) {\ + cpmm.sendAsyncMessage("TestPermission:OutOfProcess");\ + });'; + + loadApp(function (iframe) { + let frameMM = SpecialPowers.getBrowserFrameMessageManager(iframe); + frameMM.loadFrameScript(frameScript, false); + + frameMM.sendAsyncMessage("TestPermission:OutOfProcess"); + ppmm.addMessageListener("TestPermission:OutOfProcess", function receiveMessage(msg) { + ppmm.removeMessageListener("TestPermission:OutOfProcess", receiveMessage); + msg = SpecialPowers.wrap(msg); + + let mm = msg.target; + ok(mm.assertPermission("foobar"), "Process mm has assigned permission."); + ok(!mm.assertPermission("frobnaz"), "Process mm doesn't have non-existing permission."); + + // The last permission check will result in the content process + // being killed. + iframe.addEventListener("mozbrowsererror", function onerror(event) { + iframe.removeEventListener("mozbrowsererror", onerror); + ok(event.detail.type, "fatal"); + + iframe.parentNode.removeChild(iframe); + runNextTest(); + }); + }); + }); +} + +function tearDown() { + SpecialPowers.clearUserPref("dom.mozBrowserFramesEnabled"); + SpecialPowers.clearUserPref("dom.ipc.browser_frames.oop_by_default"); + SimpleTest.finish(); +} + +let _tests = [ + setUp, + testSameProcess, + testFrameMessageManager, + testChildProcessMessageManager, + tearDown +] +function runNextTest() { + SimpleTest.executeSoon(_tests.shift()); +} + +function runTests() { + SimpleTest.waitForExplicitFinish(); + runNextTest(); +} + +</script> +</pre> +</body> +</html>
--- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -4345,16 +4345,17 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeMessageBroadcaster, nsISupports) DOM_CLASSINFO_MAP_ENTRY(nsIFrameScriptLoader) DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager) DOM_CLASSINFO_MAP_ENTRY(nsIMessageBroadcaster) 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) DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(FormData, nsIDOMFormData) DOM_CLASSINFO_MAP_ENTRY(nsIDOMFormData) DOM_CLASSINFO_MAP_END
--- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -230,16 +230,17 @@ #ifdef PR_LOGGING static PRLogModuleInfo* gDOMLeakPRLog; #endif 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; nsGlobalWindow::WindowByIdTable *nsGlobalWindow::sWindowsById = nullptr; bool nsGlobalWindow::sWarnedAboutWindowInternal = false; bool nsGlobalWindow::sIdleObserversAPIFuzzTimeDisabled = false; static nsIEntropyCollector *gEntropyCollector = nullptr; @@ -10984,26 +10985,20 @@ nsGlobalChromeWindow::GetMessageManager( if (!mMessageManager) { nsIScriptContext* scx = GetContextInternal(); NS_ENSURE_STATE(scx); JSContext* cx = scx->GetNativeContext(); NS_ENSURE_STATE(cx); nsCOMPtr<nsIMessageBroadcaster> globalMM = do_GetService("@mozilla.org/globalmessagemanager;1"); mMessageManager = - new nsFrameMessageManager(true, /* aChrome */ - nullptr, - nullptr, - nullptr, - nullptr, + new nsFrameMessageManager(nullptr, static_cast<nsFrameMessageManager*>(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); return NS_OK; } // nsGlobalModalWindow implementation
--- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -1878,10 +1878,42 @@ ContentParent::RecvPrivateDocShellsExist obs->NotifyObservers(nullptr, "last-pb-context-exited", nullptr); delete gPrivateContent; gPrivateContent = NULL; } } 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<nsCOMPtr<nsIDOMBlob> >& blobs = aData.mClosure.mBlobs; + if (!blobs.IsEmpty()) { + InfallibleTArray<PBlobParent*>& 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
--- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -10,28 +10,28 @@ #include "base/waitable_event_watcher.h" #include "mozilla/dom/PContentParent.h" #include "mozilla/dom/PMemoryReportRequestParent.h" #include "mozilla/ipc/GeckoChildProcessHost.h" #include "mozilla/dom/ipc/Blob.h" #include "mozilla/Attributes.h" +#include "nsFrameMessageManager.h" #include "nsIObserver.h" #include "nsIThreadInternal.h" #include "nsNetUtil.h" #include "nsIPermissionManager.h" #include "nsIDOMGeoPositionCallback.h" #include "nsIMemoryReporter.h" #include "nsCOMArray.h" #include "nsDataHashtable.h" #include "nsHashKeys.h" class mozIApplication; -class nsFrameMessageManager; class nsIDOMBlob; namespace mozilla { namespace ipc { class OptionalURIParams; class URIParams; class TestShellParent; @@ -46,16 +46,17 @@ namespace dom { class TabParent; class PStorageParent; class ClonedMessageData; 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; typedef mozilla::ipc::TestShellParent TestShellParent; typedef mozilla::ipc::URIParams URIParams; typedef mozilla::dom::ClonedMessageData ClonedMessageData; public: @@ -82,16 +83,23 @@ public: static void GetAll(nsTArray<ContentParent*>& aArray); NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER 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); TestShellParent* CreateTestShell(); bool DestroyTestShell(TestShellParent* aTestShell); TestShellParent* GetTestShellSingleton(); void ReportChildAlreadyBlocked();
--- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -70,16 +70,17 @@ #include "StructuredCloneUtils.h" #include "xpcpublic.h" #define BROWSER_ELEMENT_CHILD_SCRIPT \ NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js") using namespace mozilla; using namespace mozilla::dom; +using namespace mozilla::dom::ipc; using namespace mozilla::ipc; using namespace mozilla::layers; using namespace mozilla::layout; using namespace mozilla::docshell; using namespace mozilla::dom::indexedDB; using namespace mozilla::widget; NS_IMPL_ISUPPORTS1(ContentListener, nsIDOMEventListener) @@ -1453,24 +1454,22 @@ TabChild::AllocPIndexedDB(const nsCStrin bool TabChild::DeallocPIndexedDB(PIndexedDBChild* aActor) { delete aActor; return true; } -static bool -SendSyncMessageToParent(void* aCallbackData, - const nsAString& aMessage, - const StructuredCloneData& aData, - InfallibleTArray<nsString>* aJSONRetVal) +bool +TabChild::DoSendSyncMessage(const nsAString& aMessage, + const StructuredCloneData& aData, + InfallibleTArray<nsString>* aJSONRetVal) { - TabChild* tabChild = static_cast<TabChild*>(aCallbackData); - ContentChild* cc = static_cast<ContentChild*>(tabChild->Manager()); + ContentChild* cc = static_cast<ContentChild*>(Manager()); ClonedMessageData data; SerializedStructuredCloneBuffer& buffer = data.data(); buffer.data = aData.mData; buffer.dataLength = aData.mDataLength; const nsTArray<nsCOMPtr<nsIDOMBlob> >& blobs = aData.mClosure.mBlobs; if (!blobs.IsEmpty()) { InfallibleTArray<PBlobChild*>& blobChildList = data.blobsChild(); @@ -1479,26 +1478,24 @@ SendSyncMessageToParent(void* aCallbackD for (uint32_t i = 0; i < length; ++i) { BlobChild* blobChild = cc->GetOrCreateActorForBlob(blobs[i]); if (!blobChild) { return false; } 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<TabChild*>(aCallbackData); - ContentChild* cc = static_cast<ContentChild*>(tabChild->Manager()); + ContentChild* cc = static_cast<ContentChild*>(Manager()); ClonedMessageData data; SerializedStructuredCloneBuffer& buffer = data.data(); buffer.data = aData.mData; buffer.dataLength = aData.mDataLength; const nsTArray<nsCOMPtr<nsIDOMBlob> >& blobs = aData.mClosure.mBlobs; if (!blobs.IsEmpty()) { InfallibleTArray<PBlobChild*>& blobChildList = data.blobsChild(); @@ -1508,36 +1505,33 @@ SendAsyncMessageToParent(void* aCallback BlobChild* blobChild = cc->GetOrCreateActorForBlob(blobs[i]); if (!blobChild) { return false; } blobChildList.AppendElement(blobChild); } } - return tabChild->SendAsyncMessage(nsString(aMessage), data); + return SendAsyncMessage(nsString(aMessage), data); } TabChildGlobal::TabChildGlobal(TabChild* aTabChild) : mTabChild(aTabChild) { } 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) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TabChildGlobal, nsDOMEventTargetHelper) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mMessageManager) NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -139,17 +139,18 @@ class TabChild : public PBrowserChild, public nsIWebBrowserChrome2, public nsIEmbeddingSiteWindow, public nsIWebBrowserChromeFocus, public nsIInterfaceRequestor, public nsIWindowProvider, 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; public: /** * This is expected to be called off the critical path to content * startup. This is an opportunity to load things that are slow @@ -173,16 +174,25 @@ public: NS_DECL_NSIEMBEDDINGSITEWINDOW NS_DECL_NSIWEBBROWSERCHROMEFOCUS NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIWINDOWPROVIDER NS_DECL_NSIDIALOGCREATOR NS_DECL_NSITABCHILD NS_DECL_NSIOBSERVER + /** + * MessageManagerCallback methods that we override. + */ + virtual bool DoSendSyncMessage(const nsAString& aMessage, + const mozilla::dom::StructuredCloneData& aData, + InfallibleTArray<nsString>* 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); virtual bool RecvUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics); virtual bool RecvHandleDoubleTap(const nsIntPoint& aPoint); virtual bool RecvHandleSingleTap(const nsIntPoint& aPoint); virtual bool RecvActivate(); virtual bool RecvDeactivate();