Bug 758401 - Add a way to get message manager from docshell, r=jst
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Mon, 28 May 2012 12:27:25 +0300
changeset 95085 43fb1c7ae6e7dc201eaf2dff7e5d503c38b66bfc
parent 95084 823f773dd7ebf51c6da4405b32a2679ac981f7c0
child 95113 79262a88881d66b474921d6944e7ca9f45facf6a
push idunknown
push userunknown
push dateunknown
reviewersjst
bugs758401
milestone15.0a1
Bug 758401 - Add a way to get message manager from docshell, r=jst
content/base/test/chrome/file_bug549682.xul
docshell/base/nsDocShell.cpp
dom/interfaces/base/nsITabChild.idl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/remote-test.js
--- a/content/base/test/chrome/file_bug549682.xul
+++ b/content/base/test/chrome/file_bug549682.xul
@@ -86,16 +86,32 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   function loadScript() {
     // Async should be processed first!
     messageManager.loadFrameScript("data:,sendAsyncMessage('async', { data: 1234 }); sendSyncMessage('sync', { data: 1234 });", false);
   }
 
   function run() {
     var localmm = document.getElementById('ifr').messageManager;
+
+    var wn = document.getElementById('ifr').contentWindow
+      .getInterface(Components.interfaces.nsIWebNavigation);
+    opener.wrappedJSObject.ok(wn, "Should have webnavigation");
+    var cfmm = wn.getInterface(Components.interfaces.nsIContentFrameMessageManager);
+    opener.wrappedJSObject.ok(cfmm, "Should have content messageManager");
+
+    var didGetSyncMessage = false;
+    function syncContinueTestFn() {
+      didGetSyncMessage = true;
+    }
+    localmm.addMessageListener("syncContinueTest", syncContinueTestFn);
+    cfmm.sendSyncMessage("syncContinueTest", {});
+    localmm.removeMessageListener("syncContinueTest", syncContinueTestFn);
+    opener.wrappedJSObject.ok(didGetSyncMessage, "Should have got sync message!");
+    
     localmm.addMessageListener("lasync", localL);
     localmm.loadFrameScript("data:,sendAsyncMessage('lasync', { data: 2345 })", false);
 
     messageManager.addMessageListener("async", asyncL);
     messageManager.addMessageListener("sync", syncL);
     global.addMessageListener("async", globalListener);
     global.addMessageListener("sync", globalListener);
     global.addMessageListener("global-sync", globalListener);
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -185,16 +185,17 @@
 #include "nsIChannelPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 
 #include "nsXULAppAPI.h"
 
 #include "nsDOMNavigationTiming.h"
 #include "nsITimedChannel.h"
 #include "mozilla/StartupTimeline.h"
+#include "nsIFrameMessageManager.h"
 
 static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
                      NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 #if defined(DEBUG_bryner) || defined(DEBUG_chb)
 //#define DEBUG_DOCSHELL_FOCUS
 #define DEBUG_PAGE_CACHE
@@ -1052,16 +1053,32 @@ NS_IMETHODIMP nsDocShell::GetInterface(c
       nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
       nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner));
       if (NS_SUCCEEDED(rv) && treeOwner) {
         nsCOMPtr<nsIInterfaceRequestor> ir = do_QueryInterface(treeOwner);
         if (ir)
           return ir->GetInterface(aIID, aSink);
       }
     }
+    else if (aIID.Equals(NS_GET_IID(nsIContentFrameMessageManager))) {
+      nsCOMPtr<nsITabChild> tabChild =
+        do_GetInterface(static_cast<nsIDocShell*>(this));
+      nsCOMPtr<nsIContentFrameMessageManager> mm;
+      if (tabChild) {
+        tabChild->
+          GetMessageManager(getter_AddRefs(mm));
+      } else {
+        nsCOMPtr<nsPIDOMWindow> win =
+          do_GetInterface(static_cast<nsIDocShell*>(this));
+        if (win) {
+          mm = do_QueryInterface(win->GetParentTarget());
+        }
+      }
+      *aSink = mm.get();
+    }
     else {
       return nsDocLoader::GetInterface(aIID, aSink);
     }
 
     NS_IF_ADDREF(((nsISupports *) * aSink));
     return *aSink ? NS_OK : NS_NOINTERFACE;
 }
 
--- a/dom/interfaces/base/nsITabChild.idl
+++ b/dom/interfaces/base/nsITabChild.idl
@@ -1,13 +1,15 @@
 /* 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 "domstubs.idl"
+interface nsIContentFrameMessageManager;
 
 // Sole purpose is to be able to identify the concrete class nsTabChild
-[uuid(a89f8ab5-ff71-492a-8ed5-71185446fa66)]
+[uuid(bf1eddf9-731b-4a4b-bd65-9a712a892832)]
 interface nsITabChild : nsISupports
 {
+  readonly attribute nsIContentFrameMessageManager messageManager;
 };
 
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -934,16 +934,27 @@ void
 TabChild::SetBackgroundColor(const nscolor& aColor)
 {
   if (mLastBackgroundColor != aColor) {
     mLastBackgroundColor = aColor;
     SendSetBackgroundColor(mLastBackgroundColor);
   }
 }
 
+NS_IMETHODIMP
+TabChild::GetMessageManager(nsIContentFrameMessageManager** aResult)
+{
+  if (mTabChildGlobal) {
+    NS_ADDREF(*aResult = mTabChildGlobal);
+    return NS_OK;
+  }
+  *aResult = nsnull;
+  return NS_ERROR_FAILURE;
+}
+
 static bool
 SendSyncMessageToParent(void* aCallbackData,
                         const nsAString& aMessage,
                         const nsAString& aJSON,
                         InfallibleTArray<nsString>* aJSONRetVal)
 {
   return static_cast<TabChild*>(aCallbackData)->
     SendSyncMessage(nsString(aMessage), nsString(aJSON),
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -147,16 +147,17 @@ public:
     NS_DECL_NSIWEBBROWSERCHROME
     NS_DECL_NSIWEBBROWSERCHROME2
     NS_DECL_NSIEMBEDDINGSITEWINDOW
     NS_DECL_NSIEMBEDDINGSITEWINDOW2
     NS_DECL_NSIWEBBROWSERCHROMEFOCUS
     NS_DECL_NSIINTERFACEREQUESTOR
     NS_DECL_NSIWINDOWPROVIDER
     NS_DECL_NSIDIALOGCREATOR
+    NS_DECL_NSITABCHILD
 
     virtual bool RecvLoadURL(const nsCString& uri);
     virtual bool RecvShow(const nsIntSize& size);
     virtual bool RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size);
     virtual bool RecvActivate();
     virtual bool RecvDeactivate();
     virtual bool RecvMouseEvent(const nsString& aType,
                                 const float&    aX,
--- a/dom/ipc/remote-test.js
+++ b/dom/ipc/remote-test.js
@@ -23,17 +23,19 @@ var dshell = content.QueryInterface(Ci.n
                     .QueryInterface(Ci.nsIDocShell);
 
 
 addEventListener("click",
   function(e) {
     dump(e.target + "\n");
     if (e.target instanceof Components.interfaces.nsIDOMHTMLAnchorElement &&
         dshell == docShell) {
-      var retval = sendSyncMessage("linkclick", { href: e.target.href });
+      var retval = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+                            getInterface(Components.interfaces.nsIContentFrameMessageManager).
+                            sendSyncMessage("linkclick", { href: e.target.href });
       dump(uneval(retval[0]) + "\n");
       // Test here also that both retvals are the same
       sendAsyncMessage("linkclick-reply-object", uneval(retval[0]) == uneval(retval[1]) ? retval[0] : "");
     }
   },
   true);
 
 addMessageListener("chrome-message",