diff --git a/content/base/public/nsIMessageManager.idl b/content/base/public/nsIMessageManager.idl index ce9c32f8178..eae400a1b5e 100644 --- a/content/base/public/nsIMessageManager.idl +++ b/content/base/public/nsIMessageManager.idl @@ -222,6 +222,13 @@ interface nsIMessageSender : nsIMessageListenerManager * * See nsIMessageListener::receiveMessage() for the format of the * data delivered to listeners. + * @throws NS_ERROR_NOT_INITIALIZED if the sender is not initialized. For + * example, we will throw NS_ERROR_NOT_INITIALIZED if we try to send + * a message to a cross-process frame but the other process has not + * yet been set up. + * @throws NS_ERROR_FAILURE when the message receiver cannot be found. For + * example, we will throw NS_ERROR_FAILURE if we try to send a message + * to a cross-process frame whose process has crashed. */ [implicit_jscontext, optional_argc] void sendAsyncMessage([optional] in AString messageName, diff --git a/content/base/src/nsFrameLoader.cpp b/content/base/src/nsFrameLoader.cpp index 5ddf530f549..d950ba2fb5e 100644 --- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -2244,11 +2244,16 @@ bool SendAsyncMessageToChild(void* aCallbackData, return tabParent->SendAsyncMessage(nsString(aMessage), data); } - nsRefPtr ev = - new nsAsyncMessageToChild(static_cast(aCallbackData), - aMessage, aData); - NS_DispatchToCurrentThread(ev); - return true; + if (static_cast(aCallbackData)->mChildMessageManager) { + nsRefPtr ev = + new nsAsyncMessageToChild(static_cast(aCallbackData), + aMessage, aData); + NS_DispatchToCurrentThread(ev); + return true; + } + + // We don't have any targets to send our asynchronous message to. + return false; } NS_IMETHODIMP diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index 5e914112269..0e79e76c5e0 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -287,7 +287,10 @@ nsFrameMessageManager::DispatchAsyncMessageInternal(const nsAString& aMessage, { if (mAsyncCallback) { NS_ENSURE_TRUE(mCallbackData, NS_ERROR_NOT_INITIALIZED); - mAsyncCallback(mCallbackData, aMessage, aData); + + if (!mAsyncCallback(mCallbackData, aMessage, aData)) { + return NS_ERROR_FAILURE; + } } if (aBroadcast == BROADCAST) { int32_t len = mChildManagers.Count(); diff --git a/dom/browser-element/BrowserElementParent.js b/dom/browser-element/BrowserElementParent.js index a13128d496e..e9c1c59ae2e 100644 --- a/dom/browser-element/BrowserElementParent.js +++ b/dom/browser-element/BrowserElementParent.js @@ -322,15 +322,9 @@ BrowserElementParent.prototype = { try { this._mm.sendAsyncMessage('browser-element-api:' + msg, data); } catch (e) { - // Ignore NS_ERROR_NOT_INITIALIZED. This exception is thrown when - // we call _sendAsyncMsg if our frame is not in the DOM, in which case - // we don't have child to receive the message. - if (e.result == Cr.NS_ERROR_NOT_INITIALIZED) { - debug("Handle NS_ERROR_NOT_INITIALIZED"); - return; - } - throw e; + return false; } + return true; }, _recvHello: function(data) { @@ -462,8 +456,11 @@ BrowserElementParent.prototype = { _sendDOMRequest: function(msgName) { let id = 'req_' + this._domRequestCounter++; let req = Services.DOMRequest.createRequest(this._window); - this._pendingDOMRequests[id] = req; - this._sendAsyncMsg(msgName, {id: id}); + if (this._sendAsyncMsg(msgName, {id: id})) { + this._pendingDOMRequests[id] = req; + } else { + Services.DOMRequest.fireErrorAsync(req, "fail"); + } return req; },