Bug 1333917 - Make ContentBridge use endpoints, not bridges. r=kanru
authorAndrew McCreight <continuation@gmail.com>
Thu, 26 Jan 2017 14:40:17 -0800
changeset 469901 fc0e726a478fcfa49512bb7551f29e1b2c3039b8
parent 469900 e96ce1680238b4e607fafb5c6072f40a8183d434
child 469902 0afe5ed6c1b47584a5f90bfc10060567dc9eb6a9
push id43881
push userbmo:gps@mozilla.com
push dateThu, 02 Feb 2017 23:49:03 +0000
reviewerskanru
bugs1333917
milestone54.0a1
Bug 1333917 - Make ContentBridge use endpoints, not bridges. r=kanru MozReview-Commit-ID: IPFX2pVblD7
dom/ipc/ContentBridgeChild.cpp
dom/ipc/ContentBridgeChild.h
dom/ipc/ContentBridgeParent.cpp
dom/ipc/ContentBridgeParent.h
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/ipc/PContentBridge.ipdl
--- a/dom/ipc/ContentBridgeChild.cpp
+++ b/dom/ipc/ContentBridgeChild.cpp
@@ -30,26 +30,24 @@ ContentBridgeChild::~ContentBridgeChild(
 }
 
 void
 ContentBridgeChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   MessageLoop::current()->PostTask(NewRunnableMethod(this, &ContentBridgeChild::DeferredDestroy));
 }
 
-/*static*/ ContentBridgeChild*
-ContentBridgeChild::Create(Transport* aTransport, ProcessId aOtherPid)
+/*static*/ void
+ContentBridgeChild::Create(Endpoint<PContentBridgeChild>&& aEndpoint)
 {
   RefPtr<ContentBridgeChild> bridge = new ContentBridgeChild();
   bridge->mSelfRef = bridge;
 
-  DebugOnly<bool> ok = bridge->Open(aTransport, aOtherPid, XRE_GetIOMessageLoop());
+  DebugOnly<bool> ok = aEndpoint.Bind(bridge);
   MOZ_ASSERT(ok);
-
-  return bridge;
 }
 
 void
 ContentBridgeChild::DeferredDestroy()
 {
   mSelfRef = nullptr;
   // |this| was just destroyed, hands off
 }
--- a/dom/ipc/ContentBridgeChild.h
+++ b/dom/ipc/ContentBridgeChild.h
@@ -16,18 +16,18 @@ namespace dom {
 class ContentBridgeChild final : public PContentBridgeChild
                                , public nsIContentChild
 {
 public:
   explicit ContentBridgeChild();
 
   NS_DECL_ISUPPORTS
 
-  static ContentBridgeChild*
-  Create(Transport* aTransport, ProcessId aOtherProcess);
+  static void
+  Create(Endpoint<PContentBridgeChild>&& aEndpoint);
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
   void DeferredDestroy();
 
   virtual mozilla::ipc::IPCResult RecvAsyncMessage(const nsString& aMsg,
                                                    InfallibleTArray<jsipc::CpowEntry>&& aCpows,
                                                    const IPC::Principal& aPrincipal,
                                                    const ClonedMessageData& aData) override;
--- a/dom/ipc/ContentBridgeParent.cpp
+++ b/dom/ipc/ContentBridgeParent.cpp
@@ -34,23 +34,22 @@ ContentBridgeParent::ActorDestroy(ActorD
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (os) {
     os->RemoveObserver(this, "content-child-shutdown");
   }
   MessageLoop::current()->PostTask(NewRunnableMethod(this, &ContentBridgeParent::DeferredDestroy));
 }
 
 /*static*/ ContentBridgeParent*
-ContentBridgeParent::Create(Transport* aTransport, ProcessId aOtherPid)
+ContentBridgeParent::Create(Endpoint<PContentBridgeParent>&& aEndpoint)
 {
   RefPtr<ContentBridgeParent> bridge = new ContentBridgeParent();
   bridge->mSelfRef = bridge;
 
-  DebugOnly<bool> ok = bridge->Open(aTransport, aOtherPid,
-                                    XRE_GetIOMessageLoop());
+  DebugOnly<bool> ok = aEndpoint.Bind(bridge);
   MOZ_ASSERT(ok);
 
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (os) {
     os->AddObserver(bridge, "content-child-shutdown", false);
   }
 
   // Initialize the message manager (and load delayed scripts) now that we
--- a/dom/ipc/ContentBridgeParent.h
+++ b/dom/ipc/ContentBridgeParent.h
@@ -26,17 +26,17 @@ public:
   NS_DECL_NSIOBSERVER
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
   void DeferredDestroy();
   virtual bool IsContentBridgeParent() const override { return true; }
   void NotifyTabDestroyed();
 
   static ContentBridgeParent*
-  Create(Transport* aTransport, ProcessId aOtherProcess);
+  Create(Endpoint<PContentBridgeParent>&& aEndpoint);
 
   virtual PBlobParent*
   SendPBlobConstructor(PBlobParent* actor,
                        const BlobConstructorParams& params) override;
 
   virtual PBrowserParent*
   SendPBrowserConstructor(PBrowserParent* aActor,
                           const TabId& aTabId,
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -1065,31 +1065,21 @@ ContentChild::DeallocPCycleCollectWithLo
 {
   // ...so when we get here, there's nothing for us to do.
   //
   // Also, we're already in ~CycleCollectWithLogsChild (q.v.) at
   // this point, so we shouldn't touch the actor in any case.
   return true;
 }
 
-PContentBridgeChild*
-ContentChild::AllocPContentBridgeChild(mozilla::ipc::Transport* aTransport,
-                                       base::ProcessId aOtherProcess)
+mozilla::ipc::IPCResult
+ContentChild::RecvInitContentBridgeChild(Endpoint<PContentBridgeChild>&& aEndpoint)
 {
-  return ContentBridgeChild::Create(aTransport, aOtherProcess);
-}
-
-PContentBridgeParent*
-ContentChild::AllocPContentBridgeParent(mozilla::ipc::Transport* aTransport,
-                                        base::ProcessId aOtherProcess)
-{
-  MOZ_ASSERT(!mLastBridge);
-  mLastBridge = static_cast<ContentBridgeParent*>(
-    ContentBridgeParent::Create(aTransport, aOtherProcess));
-  return mLastBridge;
+  ContentBridgeChild::Create(Move(aEndpoint));
+  return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 ContentChild::RecvInitGMPService(Endpoint<PGMPServiceChild>&& aGMPService)
 {
   if (!GMPServiceChild::Create(Move(aGMPService))) {
     return IPC_FAIL_NO_REASON(this);
   }
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -132,32 +132,18 @@ public:
 #endif
 
   bool IsAlive() const;
 
   bool IsShuttingDown() const;
 
   static void AppendProcessId(nsACString& aName);
 
-  ContentBridgeParent* GetLastBridge()
-  {
-    MOZ_ASSERT(mLastBridge);
-    ContentBridgeParent* parent = mLastBridge;
-    mLastBridge = nullptr;
-    return parent;
-  }
-
-  RefPtr<ContentBridgeParent> mLastBridge;
-
-  PContentBridgeParent*
-  AllocPContentBridgeParent(mozilla::ipc::Transport* transport,
-                            base::ProcessId otherProcess) override;
-  PContentBridgeChild*
-  AllocPContentBridgeChild(mozilla::ipc::Transport* transport,
-                           base::ProcessId otherProcess) override;
+  mozilla::ipc::IPCResult
+  RecvInitContentBridgeChild(Endpoint<PContentBridgeChild>&& aEndpoint) override;
 
   mozilla::ipc::IPCResult
   RecvInitGMPService(Endpoint<PGMPServiceChild>&& aGMPService) override;
 
   mozilla::ipc::IPCResult
   RecvGMPsChanged(nsTArray<GMPCapabilityData>&& capabilities) override;
 
   mozilla::ipc::IPCResult
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -802,28 +802,41 @@ ContentParent::RecvCreateChildProcess(co
     }
     return IPC_OK();
   }
 
   return IPC_FAIL_NO_REASON(this);
 }
 
 mozilla::ipc::IPCResult
-ContentParent::RecvBridgeToChildProcess(const ContentParentId& aCpId)
+ContentParent::RecvBridgeToChildProcess(const ContentParentId& aCpId,
+                                        Endpoint<PContentBridgeParent>* aEndpoint)
 {
   ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
   ContentParent* cp = cpm->GetContentProcessById(aCpId);
 
   if (cp) {
     ContentParentId parentId;
     if (cpm->GetParentProcessId(cp->ChildID(), &parentId) &&
       parentId == this->ChildID()) {
-      if (NS_FAILED(PContentBridge::Bridge(this, cp))) {
-        return IPC_FAIL_NO_REASON(this);
+
+      Endpoint<PContentBridgeParent> parent;
+      Endpoint<PContentBridgeChild> child;
+
+      if (NS_FAILED(PContentBridge::CreateEndpoints(OtherPid(), cp->OtherPid(),
+                                                    &parent, &child))) {
+        return IPC_FAIL(this, "CreateEndpoints failed");
       }
+
+      *aEndpoint = Move(parent);
+
+      if (!cp->SendInitContentBridgeChild(Move(child))) {
+        return IPC_FAIL(this, "SendInitContentBridgeChild failed");
+      }
+
       return IPC_OK();
     }
   }
 
   // You can't bridge to a process you didn't open!
   KillHard("BridgeToChildProcess");
   return IPC_FAIL_NO_REASON(this);
 }
@@ -1086,20 +1099,21 @@ ContentParent::CreateContentBridgeParent
                                      &cpId,
                                      &isForBrowser,
                                      aTabId)) {
     return nullptr;
   }
   if (cpId == 0) {
     return nullptr;
   }
-  if (!child->SendBridgeToChildProcess(cpId)) {
+  Endpoint<PContentBridgeParent> endpoint;
+  if (!child->SendBridgeToChildProcess(cpId, &endpoint)) {
     return nullptr;
   }
-  ContentBridgeParent* parent = child->GetLastBridge();
+  ContentBridgeParent* parent = ContentBridgeParent::Create(Move(endpoint));
   parent->SetChildID(cpId);
   parent->SetIsForBrowser(isForBrowser);
   return parent;
 }
 
 void
 ContentParent::GetAll(nsTArray<ContentParent*>& aArray)
 {
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -273,17 +273,18 @@ public:
 
   virtual mozilla::ipc::IPCResult RecvCreateChildProcess(const IPCTabContext& aContext,
                                                          const hal::ProcessPriority& aPriority,
                                                          const TabId& aOpenerTabId,
                                                          ContentParentId* aCpId,
                                                          bool* aIsForBrowser,
                                                          TabId* aTabId) override;
 
-  virtual mozilla::ipc::IPCResult RecvBridgeToChildProcess(const ContentParentId& aCpId) override;
+  virtual mozilla::ipc::IPCResult RecvBridgeToChildProcess(const ContentParentId& aCpId,
+                                                           Endpoint<PContentBridgeParent>* aEndpoint) override;
 
   virtual mozilla::ipc::IPCResult RecvCreateGMPService() override;
 
   virtual mozilla::ipc::IPCResult RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv,
                                                  uint32_t* aRunID,
                                                  Endpoint<PPluginModuleParent>* aEndpoint) override;
 
   virtual mozilla::ipc::IPCResult RecvConnectPluginBridge(const uint32_t& aPluginId,
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -408,16 +408,17 @@ both:
     // to persist a subdocument.  For child->parent, arguments are
     // ignored and should be null/zero.
     async PWebBrowserPersistDocument(nullable PBrowser aBrowser,
                                      uint64_t aOuterWindowID);
 
 child:
     async InitGMPService(Endpoint<PGMPServiceChild> service);
     async InitProcessHangMonitor(Endpoint<PProcessHangMonitorChild> hangMonitor);
+    async InitContentBridgeChild(Endpoint<PContentBridgeChild> endpoint);
 
     // Give the content process its endpoints to the compositor.
     async InitRendering(
       Endpoint<PCompositorBridgeChild> compositor,
       Endpoint<PImageBridgeChild> imageBridge,
       Endpoint<PVRManagerChild> vr,
       Endpoint<PVideoDecoderManagerChild> video);
 
@@ -678,17 +679,18 @@ parent:
                  FontFamilyListEntry[] fontFamilies /* used on MacOSX only */,
                  OptionalURIParams userContentSheetURL,
                  LookAndFeelInt[] lookAndFeelIntCache);
 
     sync CreateChildProcess(IPCTabContext context,
                             ProcessPriority priority,
                             TabId openerTabId)
         returns (ContentParentId cpId, bool isForBrowser, TabId tabId);
-    sync BridgeToChildProcess(ContentParentId cpId);
+    sync BridgeToChildProcess(ContentParentId cpId)
+        returns (Endpoint<PContentBridgeParent> endpoint);
 
     async CreateGMPService();
 
     /**
      * This call connects the content process to a plugin process. This call
      * returns an endpoint for a new PluginModuleParent. The corresponding
      * PluginModuleChild will be started up in the plugin process.
      */
--- a/dom/ipc/PContentBridge.ipdl
+++ b/dom/ipc/PContentBridge.ipdl
@@ -29,18 +29,16 @@ namespace dom {
  * child processes.  When a child process wants to open its own child, it asks
  * the root process to create a new process and then bridge them.  The first
  * child will allocate the PContentBridgeParent, and the newly opened child will
  * allocate the PContentBridgeChild.  This protocol allows these processes to
  * share PBrowsers and send messages to each other.
  */
 nested(upto inside_cpow) sync protocol PContentBridge
 {
-    bridges PContent, PContent;
-
     manages PBlob;
     manages PBrowser;
     manages PFileDescriptorSet;
     manages PJavaScript;
     manages PSendStream;
 
 parent:
     sync SyncMessage(nsString aMessage, ClonedMessageData aData,