Bug 1513057 - P5: Create IPC between content process and socket process r=dragana,mayhemer
☠☠ backed out by 3f76ed638d83 ☠ ☠
authorKershaw Chang <kershaw@mozilla.com>
Fri, 11 Jan 2019 13:29:33 +0000
changeset 453475 460bbf0849e11fea35612feed9d10201e1fe5213
parent 453474 86032a14d26fc5be8c6802ec915db14e1a371b6c
child 453476 f648b5f1a7c2333e10ae9f7d9a91314de4512a70
push id35357
push usernerli@mozilla.com
push dateFri, 11 Jan 2019 21:54:07 +0000
treeherdermozilla-central@0ce024c91511 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdragana, mayhemer
bugs1513057
milestone66.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
Bug 1513057 - P5: Create IPC between content process and socket process r=dragana,mayhemer Differential Revision: https://phabricator.services.mozilla.com/D14257
netwerk/ipc/NeckoParent.cpp
netwerk/ipc/NeckoParent.h
netwerk/ipc/PNecko.ipdl
netwerk/ipc/PSocketProcess.ipdl
netwerk/ipc/PSocketProcessBridge.ipdl
netwerk/ipc/SocketProcessBridgeChild.cpp
netwerk/ipc/SocketProcessBridgeChild.h
netwerk/ipc/SocketProcessBridgeParent.cpp
netwerk/ipc/SocketProcessBridgeParent.h
netwerk/ipc/SocketProcessChild.cpp
netwerk/ipc/SocketProcessChild.h
netwerk/ipc/SocketProcessParent.cpp
netwerk/ipc/SocketProcessParent.h
netwerk/ipc/moz.build
--- a/netwerk/ipc/NeckoParent.cpp
+++ b/netwerk/ipc/NeckoParent.cpp
@@ -23,16 +23,18 @@
 #include "mozilla/net/AltDataOutputStreamParent.h"
 #include "mozilla/Unused.h"
 #include "mozilla/net/FileChannelParent.h"
 #include "mozilla/net/DNSRequestParent.h"
 #include "mozilla/net/ChannelDiverterParent.h"
 #include "mozilla/net/IPCTransportProvider.h"
 #include "mozilla/net/RequestContextService.h"
 #include "mozilla/net/TrackingDummyChannelParent.h"
+#include "mozilla/net/SocketProcessParent.h"
+#include "mozilla/net/PSocketProcessBridgeParent.h"
 #ifdef MOZ_WEBRTC
 #include "mozilla/net/StunAddrsRequestParent.h"
 #include "mozilla/net/WebrtcProxyChannelParent.h"
 #endif
 #include "mozilla/dom/ChromeUtils.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/TabContext.h"
 #include "mozilla/dom/TabParent.h"
@@ -69,17 +71,17 @@ using mozilla::ipc::PrincipalInfo;
 using mozilla::net::PTCPServerSocketParent;
 using mozilla::net::PTCPSocketParent;
 using mozilla::net::PUDPSocketParent;
 
 namespace mozilla {
 namespace net {
 
 // C++ file contents
-NeckoParent::NeckoParent() {
+NeckoParent::NeckoParent() : mSocketProcessBridgeInited(false) {
   // Init HTTP protocol handler now since we need atomTable up and running very
   // early (IPDL argument handling for PHttpChannel constructor needs it) so
   // normal init (during 1st Http channel request) isn't early enough.
   nsCOMPtr<nsIProtocolHandler> proto =
       do_GetService("@mozilla.org/network/protocol;1?name=http");
 
   // only register once--we will have multiple NeckoParents if there are
   // multiple child processes.
@@ -949,10 +951,46 @@ mozilla::ipc::IPCResult NeckoParent::Rec
 bool NeckoParent::DeallocPTrackingDummyChannelParent(
     PTrackingDummyChannelParent* aActor) {
   RefPtr<TrackingDummyChannelParent> c =
       dont_AddRef(static_cast<TrackingDummyChannelParent*>(aActor));
   MOZ_ASSERT(c);
   return true;
 }
 
+mozilla::ipc::IPCResult NeckoParent::RecvInitSocketProcessBridge(
+    InitSocketProcessBridgeResolver&& aResolver) {
+  MOZ_ASSERT(NS_IsMainThread());
+
+  Endpoint<PSocketProcessBridgeChild> invalidEndpoint;
+  if (NS_WARN_IF(mSocketProcessBridgeInited)) {
+    aResolver(std::move(invalidEndpoint));
+    return IPC_OK();
+  }
+
+  SocketProcessParent* parent = SocketProcessParent::GetSingleton();
+  if (NS_WARN_IF(!parent)) {
+    aResolver(std::move(invalidEndpoint));
+    return IPC_OK();
+  }
+
+  Endpoint<PSocketProcessBridgeParent> parentEndpoint;
+  Endpoint<PSocketProcessBridgeChild> childEndpoint;
+  if (NS_WARN_IF(NS_FAILED(PSocketProcessBridge::CreateEndpoints(
+          parent->OtherPid(), Manager()->OtherPid(), &parentEndpoint,
+          &childEndpoint)))) {
+    aResolver(std::move(invalidEndpoint));
+    return IPC_OK();
+  }
+
+  if (NS_WARN_IF(!parent->SendInitSocketProcessBridgeParent(
+          Manager()->OtherPid(), std::move(parentEndpoint)))) {
+    aResolver(std::move(invalidEndpoint));
+    return IPC_OK();
+  }
+
+  aResolver(std::move(childEndpoint));
+  mSocketProcessBridgeInited = true;
+  return IPC_OK();
+}
+
 }  // namespace net
 }  // namespace mozilla
--- a/netwerk/ipc/NeckoParent.h
+++ b/netwerk/ipc/NeckoParent.h
@@ -82,16 +82,18 @@ class NeckoParent : public PNeckoParent 
                                nsICancelable**) override;
 
    protected:
     PNeckoParent* mNeckoParent;
     TabId mNestedFrameId;
   };
 
  protected:
+  bool mSocketProcessBridgeInited;
+
   virtual PHttpChannelParent* AllocPHttpChannelParent(
       const PBrowserOrId&, const SerializedLoadContext&,
       const HttpChannelCreationArgs& aOpenArgs) override;
   virtual mozilla::ipc::IPCResult RecvPHttpChannelConstructor(
       PHttpChannelParent* aActor, const PBrowserOrId& aBrowser,
       const SerializedLoadContext& aSerialized,
       const HttpChannelCreationArgs& aOpenArgs) override;
   virtual bool DeallocPHttpChannelParent(PHttpChannelParent*) override;
@@ -241,14 +243,17 @@ class NeckoParent : public PNeckoParent 
 
   virtual bool DeallocPTrackingDummyChannelParent(
       PTrackingDummyChannelParent* aChild) override;
 
   virtual mozilla::ipc::IPCResult RecvPTrackingDummyChannelConstructor(
       PTrackingDummyChannelParent* aActor, nsIURI* aURI, nsIURI* aTopWindowURI,
       const nsresult& aTopWindowURIResult,
       const OptionalLoadInfoArgs& aLoadInfo) override;
+
+  virtual mozilla::ipc::IPCResult RecvInitSocketProcessBridge(
+      InitSocketProcessBridgeResolver&& aResolver) override;
 };
 
 }  // namespace net
 }  // namespace mozilla
 
 #endif  // mozilla_net_NeckoParent_h
--- a/netwerk/ipc/PNecko.ipdl
+++ b/netwerk/ipc/PNecko.ipdl
@@ -23,16 +23,17 @@ include protocol PDataChannel;
 include protocol PSimpleChannel;
 include protocol PTransportProvider;
 include protocol PChildToParentStream; //FIXME: bug #792908
 include protocol PParentToChildStream; //FIXME: bug #792908
 include protocol PStunAddrsRequest;
 include protocol PFileChannel;
 include protocol PTrackingDummyChannel;
 include protocol PWebrtcProxyChannel;
+include protocol PSocketProcessBridge;
 
 include IPCStream;
 include URIParams;
 include NeckoChannelParams;
 include PBrowserOrId;
 include protocol PAltDataOutputStream;
 
 using class IPC::SerializedLoadContext from "SerializedLoadContext.h";
@@ -138,16 +139,19 @@ parent:
   async PWebrtcProxyChannel(PBrowserOrId browser);
 
   /**
    * WebExtension-specific remote resource loading
    */
   async GetExtensionStream(URIParams uri) returns (nsIInputStream stream);
   async GetExtensionFD(URIParams uri) returns (FileDescriptor fd);
 
+  async InitSocketProcessBridge()
+    returns (Endpoint<PSocketProcessBridgeChild> endpoint);
+
 child:
   /*
    * Bring up the http auth prompt for a nested remote mozbrowser.
    * NestedFrameId is the id corresponding to the PBrowser.  It is the same id
    * that was passed to the PBrowserOrId param in to the PHttpChannel constructor
    */
   async AsyncAuthPromptForNestedFrame(TabId nestedFrameId, nsCString uri,
                                       nsString realm, uint64_t callbackId);
--- a/netwerk/ipc/PSocketProcess.ipdl
+++ b/netwerk/ipc/PSocketProcess.ipdl
@@ -1,17 +1,19 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 MemoryReportTypes;
+include protocol PSocketProcessBridge;
 include PrefsTypes;
 
 using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
+using base::ProcessId from "base/process.h";
 
 namespace mozilla {
 namespace net {
 
 protocol PSocketProcess
 {
 parent:
   async InitCrashReporter(Shmem shmem, NativeThreadId threadId);
@@ -20,12 +22,13 @@ parent:
 
 child:
   async PreferenceUpdate(Pref pref);
   async RequestMemoryReport(uint32_t generation,
                             bool anonymize,
                             bool minimizeMemoryUsage,
                             MaybeFileDesc DMDFile);
   async SetOffline(bool offline);
+  async InitSocketProcessBridgeParent(ProcessId processId, Endpoint<PSocketProcessBridgeParent> endpoint);
 };
 
 } // namespace net
 } // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/netwerk/ipc/PSocketProcessBridge.ipdl
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+namespace mozilla {
+namespace net {
+
+/**
+  * PSocketProcessBridge is the IPC protocol between content process and
+  * socket process. This protocol allows socket process to send data to
+  * content process bypassing parent process.
+  * Once created, PSocketProcessBridgeChild is the actor that lives in
+  * content process and PSocketProcessBridgeParent lives in
+  * socket process.
+  */
+nested(upto inside_cpow) sync protocol PSocketProcessBridge
+{
+both:
+  async Test();
+};
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/netwerk/ipc/SocketProcessBridgeChild.cpp
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "SocketProcessBridgeChild.h"
+#include "SocketProcessLogging.h"
+
+#include "mozilla/net/NeckoChild.h"
+#include "nsIObserverService.h"
+#include "nsThreadUtils.h"
+
+namespace mozilla {
+namespace net {
+
+StaticRefPtr<SocketProcessBridgeChild>
+    SocketProcessBridgeChild::sSocketProcessBridgeChild;
+
+NS_IMPL_ISUPPORTS(SocketProcessBridgeChild, nsIObserver)
+
+// static
+bool SocketProcessBridgeChild::Create(
+    Endpoint<PSocketProcessBridgeChild>&& aEndpoint) {
+  MOZ_ASSERT(NS_IsMainThread());
+
+  sSocketProcessBridgeChild =
+      new SocketProcessBridgeChild(std::move(aEndpoint));
+  if (sSocketProcessBridgeChild->Inited()) {
+    return true;
+  }
+
+  sSocketProcessBridgeChild = nullptr;
+  return false;
+}
+
+// static
+already_AddRefed<SocketProcessBridgeChild>
+SocketProcessBridgeChild::GetSinglton() {
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!sSocketProcessBridgeChild) {
+    return nullptr;
+  }
+
+  RefPtr<SocketProcessBridgeChild> child = sSocketProcessBridgeChild.get();
+  return child.forget();
+}
+
+// static
+void SocketProcessBridgeChild::EnsureSocketProcessBridge(
+    std::function<void()>&& aOnSuccess, std::function<void()>&& aOnFailure) {
+  MOZ_ASSERT(IsNeckoChild() && gNeckoChild);
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!gNeckoChild) {
+    aOnFailure();
+    return;
+  }
+
+  if (sSocketProcessBridgeChild) {
+    aOnSuccess();
+    return;
+  }
+
+  gNeckoChild->SendInitSocketProcessBridge()->Then(
+      GetMainThreadSerialEventTarget(), __func__,
+      [onSuccess = std::move(aOnSuccess), onFailure = std::move(aOnFailure)](
+          Endpoint<PSocketProcessBridgeChild>&& aEndpoint) {
+        if (aEndpoint.IsValid()) {
+          if (SocketProcessBridgeChild::Create(std::move(aEndpoint))) {
+            onSuccess();
+            return;
+          }
+        }
+        onFailure();
+      },
+      [onFailure = std::move(aOnFailure)](
+          const mozilla::ipc::ResponseRejectReason) { onFailure(); });
+}
+
+SocketProcessBridgeChild::SocketProcessBridgeChild(
+    Endpoint<PSocketProcessBridgeChild>&& aEndpoint) {
+  LOG(("CONSTRUCT SocketProcessBridgeChild::SocketProcessBridgeChild\n"));
+
+  mInited = aEndpoint.Bind(this);
+  if (!mInited) {
+    MOZ_ASSERT(false, "Bind failed!");
+    return;
+  }
+
+  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+  if (os) {
+    os->AddObserver(this, "content-child-shutdown", false);
+  }
+}
+
+SocketProcessBridgeChild::~SocketProcessBridgeChild() {
+  LOG(("DESTRUCT SocketProcessBridgeChild::SocketProcessBridgeChild\n"));
+}
+
+mozilla::ipc::IPCResult SocketProcessBridgeChild::RecvTest() {
+  LOG(("SocketProcessBridgeChild::RecvTest\n"));
+  return IPC_OK();
+}
+
+void SocketProcessBridgeChild::ActorDestroy(ActorDestroyReason aWhy) {
+  LOG(("SocketProcessBridgeChild::ActorDestroy\n"));
+  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+  if (os) {
+    os->RemoveObserver(this, "content-child-shutdown");
+  }
+  MessageLoop::current()->PostTask(
+      NewRunnableMethod("net::SocketProcessBridgeChild::DeferredDestroy", this,
+                        &SocketProcessBridgeChild::DeferredDestroy));
+}
+
+NS_IMETHODIMP
+SocketProcessBridgeChild::Observe(nsISupports* aSubject, const char* aTopic,
+                                  const char16_t* aData) {
+  if (!strcmp(aTopic, "content-child-shutdown")) {
+    PSocketProcessBridgeChild::Close();
+  }
+  return NS_OK;
+}
+
+void SocketProcessBridgeChild::DeferredDestroy() {
+  MOZ_ASSERT(NS_IsMainThread());
+
+  sSocketProcessBridgeChild = nullptr;
+}
+
+}  // namespace net
+}  // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/netwerk/ipc/SocketProcessBridgeChild.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef mozilla_net_SocketProcessBridgeChild_h
+#define mozilla_net_SocketProcessBridgeChild_h
+
+#include <functional>
+#include "mozilla/net/PSocketProcessBridgeChild.h"
+#include "nsIObserver.h"
+
+namespace mozilla {
+namespace net {
+
+// The IPC actor implements PSocketProcessBridgeChild in content process.
+// This is allocated and kept alive by NeckoChild. When "content-child-shutdown"
+// topic is observed, this actor will be destroyed.
+class SocketProcessBridgeChild final : public PSocketProcessBridgeChild,
+                                       public nsIObserver {
+ public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+
+  static bool Create(Endpoint<PSocketProcessBridgeChild>&& aEndpoint);
+  static already_AddRefed<SocketProcessBridgeChild> GetSinglton();
+  static void EnsureSocketProcessBridge(std::function<void()>&& aOnSuccess,
+                                        std::function<void()>&& aOnFailure);
+
+  mozilla::ipc::IPCResult RecvTest() override;
+  void ActorDestroy(ActorDestroyReason aWhy) override;
+  void DeferredDestroy();
+  bool Inited() const { return mInited; };
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SocketProcessBridgeChild);
+  explicit SocketProcessBridgeChild(
+      Endpoint<PSocketProcessBridgeChild>&& aEndpoint);
+  virtual ~SocketProcessBridgeChild();
+
+  static StaticRefPtr<SocketProcessBridgeChild> sSocketProcessBridgeChild;
+  bool mInited = false;
+};
+
+}  // namespace net
+}  // namespace mozilla
+
+#endif  // mozilla_net_SocketProcessBridgeChild_h
new file mode 100644
--- /dev/null
+++ b/netwerk/ipc/SocketProcessBridgeParent.cpp
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "SocketProcessBridgeParent.h"
+#include "SocketProcessLogging.h"
+
+#include "SocketProcessChild.h"
+
+namespace mozilla {
+namespace net {
+
+SocketProcessBridgeParent::SocketProcessBridgeParent(
+    ProcessId aId, Endpoint<PSocketProcessBridgeParent>&& aEndpoint)
+    : mId(aId) {
+  LOG((
+      "CONSTRUCT SocketProcessBridgeParent::SocketProcessBridgeParent mId=%d\n",
+      mId));
+  MOZ_COUNT_CTOR(SocketProcessBridgeParent);
+  DebugOnly<bool> ok = aEndpoint.Bind(this);
+  MOZ_ASSERT(ok);
+}
+
+SocketProcessBridgeParent::~SocketProcessBridgeParent() {
+  LOG(("DESTRUCT SocketProcessBridgeParent::SocketProcessBridgeParent\n"));
+  MOZ_COUNT_DTOR(SocketProcessBridgeParent);
+}
+
+mozilla::ipc::IPCResult SocketProcessBridgeParent::RecvTest() {
+  LOG(("SocketProcessBridgeParent::RecvTest\n"));
+  Unused << SendTest();
+  return IPC_OK();
+}
+
+void SocketProcessBridgeParent::ActorDestroy(ActorDestroyReason aWhy) {
+  LOG(("SocketProcessBridgeParent::ActorDestroy mId=%d\n", mId));
+
+  MessageLoop::current()->PostTask(
+      NewRunnableMethod("net::SocketProcessBridgeParent::DeferredDestroy", this,
+                        &SocketProcessBridgeParent::DeferredDestroy));
+}
+
+void SocketProcessBridgeParent::DeferredDestroy() {
+  SocketProcessChild::GetSingleton()->DestroySocketProcessBridgeParent(mId);
+}
+
+}  // namespace net
+}  // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/netwerk/ipc/SocketProcessBridgeParent.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef mozilla_net_SocketProcessBridgeParent_h
+#define mozilla_net_SocketProcessBridgeParent_h
+
+#include "mozilla/net/PSocketProcessBridgeParent.h"
+
+namespace mozilla {
+namespace net {
+
+// The IPC actor implements PSocketProcessBridgeParent in socket process.
+// This is allocated and kept alive by SocketProcessChild. When |ActorDestroy|
+// is called, |SocketProcessChild::DestroySocketProcessBridgeParent| will be
+// called to destroy this actor.
+class SocketProcessBridgeParent final : public PSocketProcessBridgeParent {
+ public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SocketProcessBridgeParent)
+
+  explicit SocketProcessBridgeParent(
+      ProcessId aId, Endpoint<PSocketProcessBridgeParent>&& aEndpoint);
+
+  mozilla::ipc::IPCResult RecvTest() override;
+  void ActorDestroy(ActorDestroyReason aWhy) override;
+  void DeferredDestroy();
+
+ private:
+  ~SocketProcessBridgeParent();
+
+  ProcessId mId;
+};
+
+}  // namespace net
+}  // namespace mozilla
+
+#endif  // mozilla_net_SocketProcessBridgeParent_h
--- a/netwerk/ipc/SocketProcessChild.cpp
+++ b/netwerk/ipc/SocketProcessChild.cpp
@@ -10,16 +10,17 @@
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/ipc/CrashReporterClient.h"
 #include "mozilla/ipc/ProcessChild.h"
 #include "mozilla/Preferences.h"
 #include "nsDebugImpl.h"
 #include "nsThreadManager.h"
 #include "ProcessUtils.h"
+#include "SocketProcessBridgeParent.h"
 
 namespace mozilla {
 namespace net {
 
 using namespace ipc;
 
 static SocketProcessChild* sSocketProcessChild;
 
@@ -113,10 +114,28 @@ mozilla::ipc::IPCResult SocketProcessChi
   nsCOMPtr<nsIIOService> io(do_GetIOService());
   NS_ASSERTION(io, "IO Service can not be null");
 
   io->SetOffline(aOffline);
 
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult SocketProcessChild::RecvInitSocketProcessBridgeParent(
+    const ProcessId& aContentProcessId,
+    Endpoint<mozilla::net::PSocketProcessBridgeParent>&& aEndpoint) {
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(!mSocketProcessBridgeParentMap.Get(aContentProcessId, nullptr));
+
+  mSocketProcessBridgeParentMap.Put(
+      aContentProcessId,
+      new SocketProcessBridgeParent(aContentProcessId, std::move(aEndpoint)));
+  return IPC_OK();
+}
+
+void SocketProcessChild::DestroySocketProcessBridgeParent(ProcessId aId) {
+  MOZ_ASSERT(NS_IsMainThread());
+
+  mSocketProcessBridgeParentMap.Remove(aId);
+}
+
 }  // namespace net
 }  // namespace mozilla
--- a/netwerk/ipc/SocketProcessChild.h
+++ b/netwerk/ipc/SocketProcessChild.h
@@ -2,20 +2,23 @@
 /* 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/. */
 
 #ifndef mozilla_net_SocketProcessChild_h
 #define mozilla_net_SocketProcessChild_h
 
 #include "mozilla/net/PSocketProcessChild.h"
+#include "nsRefPtrHashtable.h"
 
 namespace mozilla {
 namespace net {
 
+class SocketProcessBridgeParent;
+
 // The IPC actor implements PSocketProcessChild in child process.
 // This is allocated and kept alive by SocketProcessImpl.
 class SocketProcessChild final : public PSocketProcessChild {
  public:
   SocketProcessChild();
   ~SocketProcessChild();
 
   static SocketProcessChild* GetSingleton();
@@ -25,18 +28,26 @@ class SocketProcessChild final : public 
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   mozilla::ipc::IPCResult RecvPreferenceUpdate(const Pref& aPref) override;
   mozilla::ipc::IPCResult RecvRequestMemoryReport(
       const uint32_t& generation, const bool& anonymize,
       const bool& minimizeMemoryUsage, const MaybeFileDesc& DMDFile) override;
   mozilla::ipc::IPCResult RecvSetOffline(const bool& aOffline) override;
+  mozilla::ipc::IPCResult RecvInitSocketProcessBridgeParent(
+      const ProcessId& aContentProcessId,
+      Endpoint<mozilla::net::PSocketProcessBridgeParent>&& aEndpoint) override;
 
   void CleanUp();
+  void DestroySocketProcessBridgeParent(ProcessId aId);
 
  private:
+  // Mapping of content process id and the SocketProcessBridgeParent.
+  // This table keeps SocketProcessBridgeParent alive in socket process.
+  nsRefPtrHashtable<nsUint32HashKey, SocketProcessBridgeParent>
+      mSocketProcessBridgeParentMap;
 };
 
 }  // namespace net
 }  // namespace mozilla
 
 #endif  // mozilla_net_SocketProcessChild_h
--- a/netwerk/ipc/SocketProcessParent.cpp
+++ b/netwerk/ipc/SocketProcessParent.cpp
@@ -6,25 +6,38 @@
 #include "SocketProcessParent.h"
 
 #include "SocketProcessHost.h"
 #include "mozilla/ipc/CrashReporterHost.h"
 
 namespace mozilla {
 namespace net {
 
+static SocketProcessParent* sSocketProcessParent;
+
 SocketProcessParent::SocketProcessParent(SocketProcessHost* aHost)
     : mHost(aHost) {
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mHost);
 
   MOZ_COUNT_CTOR(SocketProcessParent);
+  sSocketProcessParent = this;
 }
 
 SocketProcessParent::~SocketProcessParent() {
+  MOZ_ASSERT(NS_IsMainThread());
+
   MOZ_COUNT_DTOR(SocketProcessParent);
+  sSocketProcessParent = nullptr;
+}
+
+/* static */ SocketProcessParent* SocketProcessParent::GetSingleton() {
+  MOZ_ASSERT(NS_IsMainThread());
+
+  return sSocketProcessParent;
 }
 
 mozilla::ipc::IPCResult SocketProcessParent::RecvInitCrashReporter(
     Shmem&& aShmem, const NativeThreadId& aThreadId) {
   mCrashReporter = MakeUnique<CrashReporterHost>(GeckoProcessType_Content,
                                                  aShmem, aThreadId);
 
   return IPC_OK();
--- a/netwerk/ipc/SocketProcessParent.h
+++ b/netwerk/ipc/SocketProcessParent.h
@@ -28,16 +28,18 @@ class SocketProcessHost;
 // by SocketProcessHost.
 class SocketProcessParent final : public PSocketProcessParent {
  public:
   friend class SocketProcessHost;
 
   explicit SocketProcessParent(SocketProcessHost* aHost);
   ~SocketProcessParent();
 
+  static SocketProcessParent* GetSingleton();
+
   mozilla::ipc::IPCResult RecvInitCrashReporter(
       Shmem&& aShmem, const NativeThreadId& aThreadId) override;
   mozilla::ipc::IPCResult RecvAddMemoryReport(
       const MemoryReport& aReport) override;
   mozilla::ipc::IPCResult RecvFinishMemoryReport(
       const uint32_t& aGeneration) override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
--- a/netwerk/ipc/moz.build
+++ b/netwerk/ipc/moz.build
@@ -6,42 +6,47 @@
 
 EXPORTS.mozilla.net += [
     'ChannelEventQueue.h',
     'NeckoChild.h',
     'NeckoCommon.h',
     'NeckoMessageUtils.h',
     'NeckoParent.h',
     'NeckoTargetHolder.h',
+    'SocketProcessBridgeChild.h',
+    'SocketProcessBridgeParent.h',
     'SocketProcessChild.h',
     'SocketProcessHost.h',
     'SocketProcessImpl.h',
     'SocketProcessParent.h',
 ]
 
 UNIFIED_SOURCES += [
     'ChannelEventQueue.cpp',
     'NeckoChild.cpp',
     'NeckoCommon.cpp',
     'NeckoParent.cpp',
     'NeckoTargetHolder.cpp',
+    'SocketProcessBridgeChild.cpp',
+    'SocketProcessBridgeParent.cpp',
     'SocketProcessChild.cpp',
     'SocketProcessHost.cpp',
     'SocketProcessImpl.cpp',
     'SocketProcessParent.cpp',
 ]
 
 IPDL_SOURCES = [
     'NeckoChannelParams.ipdlh',
     'PChannelDiverter.ipdl',
     'PDataChannel.ipdl',
     'PFileChannel.ipdl',
     'PNecko.ipdl',
     'PSimpleChannel.ipdl',
-    'PSocketProcess.ipdl'
+    'PSocketProcess.ipdl',
+    'PSocketProcessBridge.ipdl'
 ]
 
 # needed so --disable-webrtc builds work (yes, a bit messy)
 if not CONFIG['MOZ_WEBRTC']:
   IPDL_SOURCES += [
       '../../media/mtransport/ipc/PStunAddrsRequest.ipdl',
       '../../media/mtransport/ipc/PWebrtcProxyChannel.ipdl',
   ]