Bug 585173 - Process message manager. r=dougt a=blocking-fennec
authorOlli Pettay <Olli.Pettay@gmail.com>
Tue, 31 Aug 2010 11:58:35 -0700
changeset 51811 1d7e7ccda33ca670fe572b4ba63aa6ab75ac5bde
parent 51810 82ed1b11d8f1783c6dac155d2ef0e70dea9e47d1
child 51812 55f5cc760da7474ffcb87c62dda92a5b307dcc5f
push idunknown
push userunknown
push dateunknown
reviewersdougt, blocking-fennec
bugs585173
milestone2.0b6pre
Bug 585173 - Process message manager. r=dougt a=blocking-fennec
content/base/public/nsContentCID.h
content/base/public/nsIFrameMessageManager.idl
content/base/src/nsFrameMessageManager.cpp
content/base/src/nsFrameMessageManager.h
content/base/src/nsInProcessTabChildGlobal.cpp
dom/base/nsDOMClassInfo.cpp
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/ipc/TabChild.cpp
dom/ipc/remote-test.js
dom/ipc/test.xul
layout/build/nsLayoutModule.cpp
--- a/content/base/public/nsContentCID.h
+++ b/content/base/public/nsContentCID.h
@@ -310,13 +310,27 @@
 
 #define NS_GLOBALMESSAGEMANAGER_CID                   \
  { /* 130b016f-fad7-4526-bc7f-827dabf79265 */         \
     0x130b016f, 0xfad7, 0x4526,                       \
   { 0xbc, 0x7f, 0x82, 0x7d, 0xab, 0xf7, 0x92, 0x65 } }
 #define NS_GLOBALMESSAGEMANAGER_CONTRACTID \
   "@mozilla.org/globalmessagemanager;1"
 
+#define NS_PARENTPROCESSMESSAGEMANAGER_CID             \
+ { /* 2a058404-fb85-44ec-8cfd-e8cbdc988dc1 */          \
+    0x2a058404, 0xfb85, 0x44ec,                        \
+  { 0x8c, 0xfd, 0xe8, 0xcb, 0xdc, 0x98, 0x8d, 0xc1 } }
+#define NS_PARENTPROCESSMESSAGEMANAGER_CONTRACTID \
+  "@mozilla.org/parentprocessmessagemanager;1"
+
+  #define NS_CHILDPROCESSMESSAGEMANAGER_CID           \
+ { /* fe0ff7c3-8e97-448b-9a8a-86afdb9fbbb6 */         \
+    0xfe0ff7c3, 0x8e97, 0x448b,                       \
+  { 0x9a, 0x8a, 0x86, 0xaf, 0xdb, 0x9f, 0xbb, 0xb6 } }
+#define NS_CHILDPROCESSMESSAGEMANAGER_CONTRACTID \
+  "@mozilla.org/childprocessmessagemanager;1"
+  
 // {f96f5ec9-755b-447e-b1f3-717d1a84bb41}
 #define NS_PLUGINDOCUMENT_CID \
 { 0xf96f5ec9, 0x755b, 0x447e, { 0xb1, 0xf3, 0x71, 0x7d, 0x1a, 0x84, 0xbb, 0x41 } }
 
 #endif /* nsContentCID_h__ */
--- a/content/base/public/nsIFrameMessageManager.idl
+++ b/content/base/public/nsIFrameMessageManager.idl
@@ -67,26 +67,28 @@ interface nsIFrameMessageListener : nsIS
 [scriptable, uuid(6b736edb-863d-40bd-bca2-62f44da803c0)]
 interface nsIFrameMessageManager : nsISupports
 {
   void addMessageListener(in AString aMessage, in nsIFrameMessageListener aListener);
   void removeMessageListener(in AString aMessage, in nsIFrameMessageListener aListener);
   void sendAsyncMessage(/*in messageName, in JSON*/);
 };
 
-[scriptable, uuid(c56e85b8-6736-4ae2-ae90-66bcef952a82)]
-interface nsIContentFrameMessageManager : nsIFrameMessageManager
+[scriptable, uuid(cdb1a40b-9862-426c-ae8a-f5ab84e20e32)]
+interface nsISyncMessageSender : nsIFrameMessageManager
 {
   /**
-   * @note sending JS objects isn't implemented yet.
-   *
    * Returns an array of JSON objects.
    */
-  void sendSyncMessage(/*in messageName, in JSON, in an array of JS objects,*/);
+  void sendSyncMessage(/*in messageName, in JSON*/);
+};
 
+[scriptable, uuid(c56e85b8-6736-4ae2-ae90-66bcef952a82)]
+interface nsIContentFrameMessageManager : nsISyncMessageSender
+{
   /**
    * The current top level window in the frame or null.
    */
   readonly attribute nsIDOMWindow content;
 
   /**
    * The top level docshell or null.
    */
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -30,27 +30,42 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#ifdef MOZ_IPC
+#include "ContentChild.h"
+#include "ContentParent.h"
+#endif
 #include "jscntxt.h"
 #include "nsFrameMessageManager.h"
 #include "nsContentUtils.h"
 #include "nsIXPConnect.h"
 #include "jsapi.h"
 #include "jsarray.h"
 #include "jsinterp.h"
 #include "nsJSUtils.h"
 #include "nsNetUtil.h"
 #include "nsScriptLoader.h"
 #include "nsIJSContextStack.h"
+#include "nsIXULRuntime.h"
+
+static PRBool
+IsChromeProcess()
+{
+  nsCOMPtr<nsIXULRuntime> rt = do_GetService("@mozilla.org/xre/runtime;1");
+  NS_ABORT_IF_FALSE(rt, "We must have a xre runtime");
+  PRUint32 type;
+  rt->GetProcessType(&type);
+  return type == nsIXULRuntime::PROCESS_TYPE_DEFAULT;
+}
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameMessageManager)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameMessageManager)
   PRUint32 count = tmp->mListeners.Length();
   for (PRUint32 i = 0; i < count; i++) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mListeners[i] mListener");
     cb.NoteXPCOMChild(tmp->mListeners[i].mListener.get());
@@ -71,18 +86,24 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY_AGGREGATED(nsIFrameMessageManager,
                                     (mChrome ?
                                        static_cast<nsIFrameMessageManager*>(
                                          static_cast<nsIChromeFrameMessageManager*>(this)) :
                                        static_cast<nsIFrameMessageManager*>(
                                          static_cast<nsIContentFrameMessageManager*>(this))))
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIContentFrameMessageManager, !mChrome)
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIChromeFrameMessageManager, mChrome)
+  /* nsIContentFrameMessageManager is accessible only in TabChildGlobal. */
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIContentFrameMessageManager,
+                                     !mChrome && !mIsProcessManager)
+  /* Message managers in child process support nsISyncMessageSender. */
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISyncMessageSender, !mChrome)
+  /* Process message manager doesn't support nsIChromeFrameMessageManager. */
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIChromeFrameMessageManager,
+                                     mChrome && !mIsProcessManager)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsFrameMessageManager,
                                           nsIContentFrameMessageManager)
 NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsFrameMessageManager,
                                            nsIContentFrameMessageManager)
 
 NS_IMETHODIMP
@@ -302,16 +323,19 @@ nsresult
 nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
                                       const nsAString& aMessage,
                                       PRBool aSync, const nsAString& aJSON,
                                       JSObject* aObjectsArray,
                                       nsTArray<nsString>* aJSONRetVal,
                                       JSContext* aContext)
 {
   JSContext* ctx = mContext ? mContext : aContext;
+  if (!ctx) {
+    nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(&ctx);
+  }
   if (mListeners.Length()) {
     nsCOMPtr<nsIAtom> name = do_GetAtom(aMessage);
     nsRefPtr<nsFrameMessageManager> kungfuDeathGrip(this);
 
     for (PRUint32 i = 0; i < mListeners.Length(); ++i) {
       if (mListeners[i].mMessage == name) {
         nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS =
           do_QueryInterface(mListeners[i].mListener);
@@ -491,16 +515,17 @@ nsFrameMessageManager::Disconnect(PRBool
   mParentManager = nsnull;
   mCallbackData = nsnull;
   mContext = nsnull;
 }
 
 nsresult
 NS_NewGlobalMessageManager(nsIChromeFrameMessageManager** aResult)
 {
+  NS_ENSURE_TRUE(IsChromeProcess(), NS_ERROR_NOT_AVAILABLE);
   nsFrameMessageManager* mm = new nsFrameMessageManager(PR_TRUE,
                                                         nsnull,
                                                         nsnull,
                                                         nsnull,
                                                         nsnull,
                                                         nsnull,
                                                         nsnull,
                                                         PR_TRUE);
@@ -676,8 +701,101 @@ nsFrameScriptExecutor::LoadFrameScriptIn
     } 
     JSContext* unused;
     nsContentUtils::ThreadJSContextStack()->Pop(&unused);
   }
 }
 
 NS_IMPL_ISUPPORTS1(nsScriptCacheCleaner, nsIObserver)
 
+nsFrameMessageManager* nsFrameMessageManager::sChildProcessManager = nsnull;
+nsFrameMessageManager* nsFrameMessageManager::sParentProcessManager = nsnull;
+
+#ifdef MOZ_IPC
+bool SendAsyncMessageToChildProcess(void* aCallbackData,
+                                    const nsAString& aMessage,
+                                    const nsAString& aJSON)
+{
+  mozilla::dom::ContentParent* cp =
+    mozilla::dom::ContentParent::GetSingleton(PR_FALSE);
+  NS_WARN_IF_FALSE(cp, "No child process!");
+  if (cp) {
+    return cp->SendAsyncMessage(nsString(aMessage), nsString(aJSON));
+  }
+  return true;
+}
+
+bool SendSyncMessageToParentProcess(void* aCallbackData,
+                                    const nsAString& aMessage,
+                                    const nsAString& aJSON,
+                                    nsTArray<nsString>* aJSONRetVal)
+{
+  mozilla::dom::ContentChild* cc =
+    mozilla::dom::ContentChild::GetSingleton();
+  if (cc) {
+    return
+      cc->SendSyncMessage(nsString(aMessage), nsString(aJSON), aJSONRetVal);
+  }
+  return true;
+}
+
+bool SendAsyncMessageToParentProcess(void* aCallbackData,
+                                     const nsAString& aMessage,
+                                     const nsAString& aJSON)
+{
+  mozilla::dom::ContentChild* cc =
+    mozilla::dom::ContentChild::GetSingleton();
+  if (cc) {
+    return cc->SendAsyncMessage(nsString(aMessage), nsString(aJSON));
+  }
+  return true;
+}
+
+#endif
+
+nsresult
+NS_NewParentProcessMessageManager(nsIFrameMessageManager** aResult)
+{
+  NS_ASSERTION(!nsFrameMessageManager::sParentProcessManager,
+               "Re-creating sParentProcessManager");
+#ifdef MOZ_IPC
+  NS_ENSURE_TRUE(IsChromeProcess(), NS_ERROR_NOT_AVAILABLE);
+  nsFrameMessageManager* mm = new nsFrameMessageManager(PR_TRUE,
+                                                        nsnull,
+                                                        SendAsyncMessageToChildProcess,
+                                                        nsnull,
+                                                        &nsFrameMessageManager::sParentProcessManager,
+                                                        nsnull,
+                                                        nsnull,
+                                                        PR_FALSE,
+                                                        PR_TRUE);
+  NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY);
+  nsFrameMessageManager::sParentProcessManager = mm;
+  return CallQueryInterface(mm, aResult);
+#else
+  return NS_ERROR_NOT_AVAILABLE;
+#endif
+}
+
+
+nsresult
+NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
+{
+  NS_ASSERTION(!nsFrameMessageManager::sChildProcessManager,
+               "Re-creating sChildProcessManager");
+#ifdef MOZ_IPC
+  NS_ENSURE_TRUE(!IsChromeProcess(), NS_ERROR_NOT_AVAILABLE);
+  nsFrameMessageManager* mm = new nsFrameMessageManager(PR_FALSE,
+                                                        SendSyncMessageToParentProcess,
+                                                        SendAsyncMessageToParentProcess,
+                                                        nsnull,
+                                                        &nsFrameMessageManager::sChildProcessManager,
+                                                        nsnull,
+                                                        nsnull,
+                                                        PR_FALSE,
+                                                        PR_TRUE);
+  NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY);
+  nsFrameMessageManager::sChildProcessManager = mm;
+  return CallQueryInterface(mm, aResult);
+#else
+  return NS_ERROR_NOT_AVAILABLE;
+#endif
+}
--- a/content/base/src/nsFrameMessageManager.h
+++ b/content/base/src/nsFrameMessageManager.h
@@ -77,46 +77,57 @@ class nsFrameMessageManager : public nsI
 public:
   nsFrameMessageManager(PRBool aChrome,
                         nsSyncMessageCallback aSyncCallback,
                         nsAsyncMessageCallback aAsyncCallback,
                         nsLoadScriptCallback aLoadScriptCallback,
                         void* aCallbackData,
                         nsFrameMessageManager* aParentManager,
                         JSContext* aContext,
-                        PRBool aGlobal = PR_FALSE)
-  : mChrome(aChrome), mGlobal(aGlobal), mParentManager(aParentManager),
+                        PRBool aGlobal = PR_FALSE,
+                        PRBool aProcessManager = PR_FALSE)
+  : mChrome(aChrome), mGlobal(aGlobal), mIsProcessManager(aProcessManager),
+    mParentManager(aParentManager),
     mSyncCallback(aSyncCallback), mAsyncCallback(aAsyncCallback),
     mLoadScriptCallback(aLoadScriptCallback), mCallbackData(aCallbackData),
     mContext(aContext)
   {
-    NS_ASSERTION(mContext || (aChrome && !aParentManager),
-                 "Should have mContext in non-global manager!");
+    NS_ASSERTION(mContext || (aChrome && !aParentManager) || aProcessManager,
+                 "Should have mContext in non-global/non-process manager!");
     NS_ASSERTION(aChrome || !aParentManager, "Should not set parent manager!");
     // 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())) {
       mParentManager->AddChildManager(this);
     }
   }
 
   ~nsFrameMessageManager()
   {
     for (PRInt32 i = mChildManagers.Count(); i > 0; --i) {
       static_cast<nsFrameMessageManager*>(mChildManagers[i - 1])->
         Disconnect(PR_FALSE);
     }
+    if (mIsProcessManager) {
+      if (this == sParentProcessManager) {
+        sParentProcessManager = nsnull;
+      }
+      if (this == sChildProcessManager) {
+        sChildProcessManager = nsnull;
+      }
+    }
   }
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameMessageManager,
                                            nsIContentFrameMessageManager)
   NS_DECL_NSIFRAMEMESSAGEMANAGER
+  NS_DECL_NSISYNCMESSAGESENDER
   NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER
   NS_DECL_NSICHROMEFRAMEMESSAGEMANAGER
 
   nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage,
                           PRBool aSync, const nsAString& aJSON,
                           JSObject* aObjectsArray,
                           nsTArray<nsString>* aJSONRetVal,
                           JSContext* aContext = nsnull);
@@ -137,28 +148,41 @@ public:
   void SetParentManager(nsFrameMessageManager* aParent)
   {
     NS_ASSERTION(!mParentManager, "We have parent manager already!");
     NS_ASSERTION(mChrome, "Should not set parent manager!");
     mParentManager = aParent;
   }
   PRBool IsGlobal() { return mGlobal; }
   PRBool IsWindowLevel() { return mParentManager && mParentManager->IsGlobal(); }
+
+  static nsFrameMessageManager* GetParentProcessManager()
+  {
+    return sParentProcessManager;
+  }
+  static nsFrameMessageManager* GetChildProcessManager()
+  {
+    return sChildProcessManager;
+  }
 protected:
   nsTArray<nsMessageListenerInfo> mListeners;
   nsCOMArray<nsIContentFrameMessageManager> mChildManagers;
   PRPackedBool mChrome;
   PRPackedBool mGlobal;
+  PRPackedBool mIsProcessManager;
   nsFrameMessageManager* mParentManager;
   nsSyncMessageCallback mSyncCallback;
   nsAsyncMessageCallback mAsyncCallback;
   nsLoadScriptCallback mLoadScriptCallback;
   void* mCallbackData;
   JSContext* mContext;
   nsTArray<nsString> mPendingScripts;
+public:
+  static nsFrameMessageManager* sParentProcessManager;
+  static nsFrameMessageManager* sChildProcessManager;
 };
 
 class nsScriptCacheCleaner;
 
 struct nsFrameScriptExecutorJSObjectHolder
 {
   nsFrameScriptExecutorJSObjectHolder(JSObject* aObject) : mObject(aObject) {}
   JSObject* mObject;
--- a/content/base/src/nsInProcessTabChildGlobal.cpp
+++ b/content/base/src/nsInProcessTabChildGlobal.cpp
@@ -148,16 +148,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsInProcessTabChildGlobal,
                                                   nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMessageManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mGlobal)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsInProcessTabChildGlobal)
   NS_INTERFACE_MAP_ENTRY(nsIFrameMessageManager)
+  NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIScriptContextPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(nsInProcessTabChildGlobal, nsDOMEventTargetHelper)
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -4030,16 +4030,17 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMTransitionEvent)
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ContentFrameMessageManager, nsIContentFrameMessageManager)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIFrameMessageManager)
+    DOM_CLASSINFO_MAP_ENTRY(nsISyncMessageSender)
     DOM_CLASSINFO_MAP_ENTRY(nsIContentFrameMessageManager)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(FormData, nsIDOMFormData)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMFormData)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(WebSocket, nsIWebSocket)
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -58,16 +58,17 @@
 #include "nsDocShellCID.h"
 #include "nsNetUtil.h"
 
 #include "base/message_loop.h"
 #include "base/task.h"
 
 #include "nsChromeRegistryContent.h"
 #include "mozilla/chrome/RegistryMessageUtils.h"
+#include "nsFrameMessageManager.h"
 
 using namespace mozilla::ipc;
 using namespace mozilla::net;
 using namespace mozilla::places;
 
 namespace mozilla {
 namespace dom {
 
@@ -351,10 +352,22 @@ ContentChild::RecvNotifyRemotePrefObserv
 bool
 ContentChild::RecvNotifyVisited(const IPC::URI& aURI)
 {
     nsCOMPtr<nsIURI> newURI(aURI);
     History::GetService()->NotifyVisited(newURI);
     return true;
 }
 
+
+bool
+ContentChild::RecvAsyncMessage(const nsString& aMsg, const nsString& aJSON)
+{
+  nsRefPtr<nsFrameMessageManager> cpm = nsFrameMessageManager::sChildProcessManager;
+  if (cpm) {
+    cpm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(cpm.get()),
+                        aMsg, PR_FALSE, aJSON, nsnull, nsnull);
+  }
+  return true;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -96,18 +96,19 @@ public:
      */
     nsresult AddRemotePrefObserver(const nsCString& aDomain, 
                                    const nsCString& aPrefRoot, 
                                    nsIObserver* aObserver, PRBool aHoldWeak);
     nsresult RemoveRemotePrefObserver(const nsCString& aDomain, 
                                       const nsCString& aPrefRoot, 
                                       nsIObserver* aObserver);
 
-    virtual bool RecvNotifyRemotePrefObserver(
-            const nsCString& aDomain);
+    virtual bool RecvNotifyRemotePrefObserver(const nsCString& aDomain);
+    
+    virtual bool RecvAsyncMessage(const nsString& aMsg, const nsString& aJSON);
 
 private:
     NS_OVERRIDE
     virtual void ActorDestroy(ActorDestroyReason why);
 
     nsTArray<nsAutoPtr<PrefObserver> > mPrefObservers;
     bool mDead;
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -50,16 +50,17 @@
 #include "nsContentUtils.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "nsChromeRegistryChrome.h"
 #include "nsExternalHelperAppService.h"
 #include "nsCExternalHandlerService.h"
+#include "nsFrameMessageManager.h"
 
 #ifdef ANDROID
 #include "AndroidBridge.h"
 using namespace mozilla;
 #endif
 
 using namespace mozilla::ipc;
 using namespace mozilla::net;
@@ -551,11 +552,36 @@ ContentParent::RecvNotifyIME(const int& 
 {
 #ifdef ANDROID
     AndroidBridge::Bridge()->NotifyIME(aType, aStatus);
     return true;
 #else
     return false;
 #endif
 }
+
+
+bool
+ContentParent::RecvSyncMessage(const nsString& aMsg, const nsString& aJSON,
+                               nsTArray<nsString>* aRetvals)
+{
+  nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sParentProcessManager;
+  if (ppm) {
+    ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
+                        aMsg,PR_TRUE, aJSON, nsnull, aRetvals);
+  }
+  return true;
+}
+
+
+bool
+ContentParent::RecvAsyncMessage(const nsString& aMsg, const nsString& aJSON)
+{
+  nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sParentProcessManager;
+  if (ppm) {
+    ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
+                        aMsg, PR_FALSE, aJSON, nsnull, nsnull);
+  }
+  return true;
+}
     
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -159,16 +159,20 @@ private:
 
     virtual bool RecvNotifyIMEChange(const nsString&, const PRUint32&, const int&, 
                                const int&, const int&)
 ;
 
 
     virtual bool RecvLoadURIExternal(const IPC::URI& uri);
 
+    virtual bool RecvSyncMessage(const nsString& aMsg, const nsString& aJSON,
+                                 nsTArray<nsString>* aRetvals);
+    virtual bool RecvAsyncMessage(const nsString& aMsg, const nsString& aJSON);
+
     mozilla::Monitor mMonitor;
 
     GeckoChildProcessHost* mSubprocess;
 
     int mRunToCompletionDepth;
     bool mShouldCallUnblockChild;
     nsCOMPtr<nsIThreadObserver> mOldObserver;
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -93,12 +93,19 @@ parent:
     sync PrefIsLocked(nsCString prefName) returns (PRBool retValue, nsresult rv);
     sync GetChildList(nsCString domain) returns (nsCString[] list, nsresult rv);
 
     // PermissionsManager messages
     sync TestPermission(URI uri, nsCString type, PRBool exact) returns (PRUint32 retValue);
     NotifyIME(int aType, int aState);
     NotifyIMEChange(nsString aText, PRUint32 aTextLen,
                     int aStart, int aEnd, int aNewEnd);
+
+    sync SyncMessage(nsString aMessage, nsString aJSON)
+      returns (nsString[] retval);
+
+both:
+     AsyncMessage(nsString aMessage, nsString aJSON);
+
 };
 
 }
 }
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1188,16 +1188,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TabChildGlobal,
                                                   nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMessageManager)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChildGlobal)
   NS_INTERFACE_MAP_ENTRY(nsIFrameMessageManager)
+  NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIScriptContextPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(TabChildGlobal, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(TabChildGlobal, nsDOMEventTargetHelper)
--- a/dom/ipc/remote-test.js
+++ b/dom/ipc/remote-test.js
@@ -1,11 +1,20 @@
 dump("Loading remote script!\n");
 dump(content + "\n");
 
+var cpm = Components.classes["@mozilla.org/childprocessmessagemanager;1"]
+                            .getService(Components.interfaces.nsISyncMessageSender);
+cpm.addMessageListener("cpm-async",
+  function(m) {
+    cpm.sendSyncMessage("ppm-sync");
+    dump(content.document.documentElement);
+    cpm.sendAsyncMessage("ppm-async");
+  });
+
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 var dshell = content.QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIWebNavigation)
                     .QueryInterface(Ci.nsIDocShellTreeItem)
                     .rootTreeItem
                     .QueryInterface(Ci.nsIDocShell);
 
--- a/dom/ipc/test.xul
+++ b/dom/ipc/test.xul
@@ -87,18 +87,44 @@
       window.open('chrome://global/content/test-ipc.xul', '_blank', 'chrome,resizable,width=800,height=800');
     }
     
     function closeWindow() {
       window.close();
     }
 
     function initRemoteFrameScript() {
-      // 1. Test that loading a script works
+      // 1. Test that loading a script works, and that accessing process level mm and
+      //     global mm works.
+      var ppm = Components.classes["@mozilla.org/parentprocessmessagemanager;1"]
+                          .getService(Components.interfaces.nsIFrameMessageManager);
+      var gm = Components.classes["@mozilla.org/globalmessagemanager;1"]
+                         .getService(Components.interfaces.nsIChromeFrameMessageManager);
+      var didThrow = false;
+      try {
+        var cpm = Components.classes["@mozilla.org/childprocessmessagemanager;1"]
+                            .getService(Components.interfaces.nsISyncMessageSender);  
+      } catch (ex) {
+        didThrow = true;
+      }
+      if (!didThrow) {
+        alert("One shouldn't be able to create content process message manager in chrome process!");
+      }
+      ppm.addMessageListener("ppm-sync",
+        function(m) {
+          document.getElementById("messageLog").value += "[SYNC PPM]"; 
+        }
+      );
+      ppm.addMessageListener("ppm-async",
+        function(m) {
+          document.getElementById("messageLog").value += "[ASYNC PPM]"; 
+        }
+      );
       messageManager.loadFrameScript("chrome://global/content/remote-test-ipc.js", true);
+      ppm.sendAsyncMessage("cpm-async");
 
       // 2. Test that adding message listener works, and that receiving a sync message works.
       messageManager.addMessageListener("linkclick",
         function(m) {
           // This checks that json sending works in sync messages. 
           document.getElementById("messageLog").value = m.name + ": " + m.json.href;
           return { message: "linkclick-received" };
         });
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -458,16 +458,18 @@ nsresult NS_NewContentDocumentLoaderFact
 nsresult NS_NewHTMLCopyTextEncoder(nsIDocumentEncoder** aResult);
 nsresult NS_NewTextEncoder(nsIDocumentEncoder** aResult);
 nsresult NS_NewXBLService(nsIXBLService** aResult);
 nsresult NS_NewContentPolicy(nsIContentPolicy** aResult);
 nsresult NS_NewDOMEventGroup(nsIDOMEventGroup** aResult);
 
 nsresult NS_NewEventListenerService(nsIEventListenerService** aResult);
 nsresult NS_NewGlobalMessageManager(nsIChromeFrameMessageManager** aResult);
+nsresult NS_NewParentProcessMessageManager(nsIFrameMessageManager** aResult);
+nsresult NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult);
 
 nsresult NS_NewXULControllers(nsISupports* aOuter, REFNSIID aIID, void** aResult);
 
 #define MAKE_CTOR(ctor_, iface_, func_)                   \
 static nsresult                                           \
 ctor_(nsISupports* aOuter, REFNSIID aIID, void** aResult) \
 {                                                         \
   *aResult = nsnull;                                      \
@@ -557,16 +559,18 @@ MAKE_CTOR(CreateXULPopupManager,      ns
 #endif
 #ifdef MOZ_XTF
 MAKE_CTOR(CreateXTFService,               nsIXTFService,               NS_NewXTFService)
 MAKE_CTOR(CreateXMLContentBuilder,        nsIXMLContentBuilder,        NS_NewXMLContentBuilder)
 #endif
 MAKE_CTOR(CreateContentDLF,               nsIDocumentLoaderFactory,    NS_NewContentDocumentLoaderFactory)
 MAKE_CTOR(CreateEventListenerService,     nsIEventListenerService,     NS_NewEventListenerService)
 MAKE_CTOR(CreateGlobalMessageManager,     nsIChromeFrameMessageManager,NS_NewGlobalMessageManager)
+MAKE_CTOR(CreateParentMessageManager,     nsIFrameMessageManager,NS_NewParentProcessMessageManager)
+MAKE_CTOR(CreateChildMessageManager,     nsISyncMessageSender,NS_NewChildProcessMessageManager)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsWyciwygProtocolHandler)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDataDocumentContentPolicy)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsNoDataProtocolContentPolicy)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSyncLoadService)
 MAKE_CTOR(CreatePluginDocument,           nsIDocument,                 NS_NewPluginDocument)
 #ifdef MOZ_MEDIA
 MAKE_CTOR(CreateVideoDocument,            nsIDocument,                 NS_NewVideoDocument)
 #endif
@@ -863,16 +867,18 @@ NS_DEFINE_NAMED_CID(NS_TEXTSERVICESDOCUM
 #endif
 NS_DEFINE_NAMED_CID(NS_GEOLOCATION_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_GEOLOCATION_CID);
 NS_DEFINE_NAMED_CID(NS_FOCUSMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_ICONTENTUTILS_CID);
 NS_DEFINE_NAMED_CID(CSPSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_EVENTLISTENERSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_GLOBALMESSAGEMANAGER_CID);
+NS_DEFINE_NAMED_CID(NS_PARENTPROCESSMESSAGEMANAGER_CID);
+NS_DEFINE_NAMED_CID(NS_CHILDPROCESSMESSAGEMANAGER_CID);
 NS_DEFINE_NAMED_CID(NSCHANNELPOLICY_CID);
 NS_DEFINE_NAMED_CID(NS_SCRIPTSECURITYMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_PRINCIPAL_CID);
 NS_DEFINE_NAMED_CID(NS_SYSTEMPRINCIPAL_CID);
 NS_DEFINE_NAMED_CID(NS_NULLPRINCIPAL_CID);
 NS_DEFINE_NAMED_CID(NS_SECURITYNAMESET_CID);
 
 #if defined(XP_UNIX)    || \
@@ -1011,16 +1017,18 @@ static const mozilla::Module::CIDEntry k
 #endif
   { &kNS_GEOLOCATION_SERVICE_CID, false, NULL, nsGeolocationServiceConstructor },
   { &kNS_GEOLOCATION_CID, false, NULL, nsGeolocationConstructor },
   { &kNS_FOCUSMANAGER_CID, false, NULL, CreateFocusManager },
   { &kNS_ICONTENTUTILS_CID, false, NULL, nsIContentUtilsConstructor },
   { &kCSPSERVICE_CID, false, NULL, CSPServiceConstructor },
   { &kNS_EVENTLISTENERSERVICE_CID, false, NULL, CreateEventListenerService },
   { &kNS_GLOBALMESSAGEMANAGER_CID, false, NULL, CreateGlobalMessageManager },
+  { &kNS_PARENTPROCESSMESSAGEMANAGER_CID, false, NULL, CreateParentMessageManager },
+  { &kNS_CHILDPROCESSMESSAGEMANAGER_CID, false, NULL, CreateChildMessageManager },
   { &kNSCHANNELPOLICY_CID, false, NULL, nsChannelPolicyConstructor },
   { &kNS_SCRIPTSECURITYMANAGER_CID, false, NULL, Construct_nsIScriptSecurityManager },
   { &kNS_PRINCIPAL_CID, false, NULL, nsPrincipalConstructor },
   { &kNS_SYSTEMPRINCIPAL_CID, false, NULL, nsSystemPrincipalConstructor },
   { &kNS_NULLPRINCIPAL_CID, false, NULL, nsNullPrincipalConstructor },
   { &kNS_SECURITYNAMESET_CID, false, NULL, nsSecurityNameSetConstructor },
 #if defined(XP_UNIX)    || \
     defined(_WINDOWS)   || \
@@ -1153,16 +1161,18 @@ static const mozilla::Module::ContractID
 #endif
   { "@mozilla.org/geolocation/service;1", &kNS_GEOLOCATION_SERVICE_CID },
   { "@mozilla.org/geolocation;1", &kNS_GEOLOCATION_CID },
   { "@mozilla.org/focus-manager;1", &kNS_FOCUSMANAGER_CID },
   { "@mozilla.org/content/contentutils;1", &kNS_ICONTENTUTILS_CID },
   { CSPSERVICE_CONTRACTID, &kCSPSERVICE_CID },
   { NS_EVENTLISTENERSERVICE_CONTRACTID, &kNS_EVENTLISTENERSERVICE_CID },
   { NS_GLOBALMESSAGEMANAGER_CONTRACTID, &kNS_GLOBALMESSAGEMANAGER_CID },
+  { NS_PARENTPROCESSMESSAGEMANAGER_CONTRACTID, &kNS_PARENTPROCESSMESSAGEMANAGER_CID },
+  { NS_CHILDPROCESSMESSAGEMANAGER_CONTRACTID, &kNS_CHILDPROCESSMESSAGEMANAGER_CID },
   { NSCHANNELPOLICY_CONTRACTID, &kNSCHANNELPOLICY_CID },
   { NS_SCRIPTSECURITYMANAGER_CONTRACTID, &kNS_SCRIPTSECURITYMANAGER_CID },
   { NS_GLOBAL_CHANNELEVENTSINK_CONTRACTID, &kNS_SCRIPTSECURITYMANAGER_CID },
   { NS_PRINCIPAL_CONTRACTID, &kNS_PRINCIPAL_CID },
   { NS_SYSTEMPRINCIPAL_CONTRACTID, &kNS_SYSTEMPRINCIPAL_CID },
   { NS_NULLPRINCIPAL_CONTRACTID, &kNS_NULLPRINCIPAL_CID },
   { NS_SECURITYNAMESET_CONTRACTID, &kNS_SECURITYNAMESET_CID },
 #if defined(XP_UNIX)    || \