Bug 1513057 - P6: Create Background between content process and socket process r=dragana,mayhemer
authorKershaw Chang <kershaw@mozilla.com>
Fri, 11 Jan 2019 20:56:39 +0000
changeset 510644 5b73660fb915ec803544389a1c93aacdef0e5f53
parent 510643 b5904e4ffc0ca4bdab4084a92176c6a70f93f01c
child 510645 c65c63971388c25e5176afeef8528873932b19bf
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [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 - P6: Create Background between content process and socket process r=dragana,mayhemer Differential Revision: https://phabricator.services.mozilla.com/D14348
ipc/glue/BackgroundChild.h
ipc/glue/BackgroundImpl.cpp
ipc/glue/BackgroundParent.h
ipc/glue/BackgroundParentImpl.cpp
netwerk/ipc/PSocketProcessBridge.ipdl
netwerk/ipc/SocketProcessBridgeChild.cpp
netwerk/ipc/SocketProcessBridgeChild.h
netwerk/ipc/SocketProcessBridgeParent.cpp
netwerk/ipc/SocketProcessBridgeParent.h
--- a/ipc/glue/BackgroundChild.h
+++ b/ipc/glue/BackgroundChild.h
@@ -16,55 +16,70 @@ namespace mozilla {
 namespace dom {
 
 class BlobImpl;
 class ContentChild;
 class ContentParent;
 
 }  // namespace dom
 
+namespace net {
+
+class SocketProcessImpl;
+
+}  // namespace net
+
 namespace ipc {
 
 class PBackgroundChild;
 
 // This class allows access to the PBackground protocol. PBackground allows
 // communication between any thread (in the parent or a child process) and a
 // single background thread in the parent process. Each PBackgroundChild
 // instance is tied to the thread on which it is created and must not be shared
 // across threads. Each PBackgroundChild is unique and valid as long as its
 // designated thread lives.
 //
 // Creation of PBackground is synchronous. GetOrCreateForCurrentThread will
 // create the actor if it doesn't exist yet. Thereafter (assuming success)
 // GetForCurrentThread() will return the same actor every time.
 //
+// GetOrCreateSocketActorForCurrentThread, which is like
+// GetOrCreateForCurrentThread, is used to get or create PBackground actor
+// between child process and socket process.
+//
 // CloseForCurrentThread() will close the current PBackground actor.  Subsequent
 // calls to GetForCurrentThread will return null.  CloseForCurrentThread() may
 // only be called exactly once for each thread-specific actor.  Currently it is
 // illegal to call this before the PBackground actor has been created.
 //
 // The PBackgroundChild actor and all its sub-protocol actors will be
 // automatically destroyed when its designated thread completes.
 class BackgroundChild final {
   friend class mozilla::dom::ContentChild;
   friend class mozilla::dom::ContentParent;
+  friend class mozilla::net::SocketProcessImpl;
 
   typedef mozilla::ipc::Transport Transport;
 
  public:
   // See above.
   static PBackgroundChild* GetForCurrentThread();
 
   // See above.
   static PBackgroundChild* GetOrCreateForCurrentThread(
       nsIEventTarget* aMainEventTarget = nullptr);
 
   // See above.
   static void CloseForCurrentThread();
 
+  // See above.
+  static PBackgroundChild* GetOrCreateSocketActorForCurrentThread(
+      nsIEventTarget* aMainEventTarget = nullptr);
+
  private:
   // Only called by ContentChild or ContentParent.
   static void Startup();
 };
 
 }  // namespace ipc
 }  // namespace mozilla
 
--- a/ipc/glue/BackgroundImpl.cpp
+++ b/ipc/glue/BackgroundImpl.cpp
@@ -22,16 +22,17 @@
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Unused.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerRef.h"
 #include "mozilla/ipc/ProtocolTypes.h"
+#include "mozilla/net/SocketProcessBridgeChild.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsIEventTarget.h"
 #include "nsIMutable.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsIRunnable.h"
 #include "nsISupportsImpl.h"
@@ -39,16 +40,18 @@
 #include "nsITimer.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 #include "nsTraceRefcnt.h"
 #include "nsXULAppAPI.h"
 #include "nsXPCOMPrivate.h"
 #include "prthread.h"
 
+#include <functional>
+
 #ifdef RELEASE_OR_BETA
 #define THREADSAFETY_ASSERT MOZ_ASSERT
 #else
 #define THREADSAFETY_ASSERT MOZ_RELEASE_ASSERT
 #endif
 
 #define CRASH_IN_CHILD_PROCESS(_msg) \
   do {                               \
@@ -57,27 +60,32 @@
     } else {                         \
       MOZ_CRASH(_msg);               \
     }                                \
   } while (0)
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
+using namespace mozilla::net;
 
 namespace {
 
 class ChildImpl;
 
 // -----------------------------------------------------------------------------
 // Utility Functions
 // -----------------------------------------------------------------------------
 
 void AssertIsInMainProcess() { MOZ_ASSERT(XRE_IsParentProcess()); }
 
+void AssertIsInMainOrSocketProcess() {
+  MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess());
+}
+
 void AssertIsOnMainThread() { THREADSAFETY_ASSERT(NS_IsMainThread()); }
 
 void AssertIsNotOnMainThread() { THREADSAFETY_ASSERT(!NS_IsMainThread()); }
 
 // -----------------------------------------------------------------------------
 // ParentImpl Declaration
 // -----------------------------------------------------------------------------
 
@@ -96,17 +104,17 @@ class ParentImpl final : public Backgrou
   class CreateActorHelper;
 
   struct MOZ_STACK_CLASS TimerCallbackClosure {
     nsIThread* mThread;
     nsTArray<ParentImpl*>* mLiveActors;
 
     TimerCallbackClosure(nsIThread* aThread, nsTArray<ParentImpl*>* aLiveActors)
         : mThread(aThread), mLiveActors(aLiveActors) {
-      AssertIsInMainProcess();
+      AssertIsInMainOrSocketProcess();
       AssertIsOnMainThread();
       MOZ_ASSERT(aThread);
       MOZ_ASSERT(aLiveActors);
     }
   };
 
   // The length of time we will wait at shutdown for all actors to clean
   // themselves up before forcing them to be destroyed.
@@ -215,31 +223,30 @@ class ParentImpl final : public Backgrou
   }
 
   // For other-process actors.
   explicit ParentImpl(ContentParent* aContent)
       : mContent(aContent),
         mLiveActorArray(nullptr),
         mIsOtherProcessActor(true),
         mActorDestroyed(false) {
-    AssertIsInMainProcess();
+    MOZ_ASSERT((XRE_IsParentProcess() && aContent) || XRE_IsSocketProcess());
     AssertIsOnMainThread();
-    MOZ_ASSERT(aContent);
   }
 
   ~ParentImpl() {
-    AssertIsInMainProcess();
+    AssertIsInMainOrSocketProcess();
     AssertIsOnMainThread();
     MOZ_ASSERT(!mContent);
   }
 
   void MainThreadActorDestroy();
 
   void SetLiveActorArray(nsTArray<ParentImpl*>* aLiveActorArray) {
-    AssertIsInMainProcess();
+    AssertIsInMainOrSocketProcess();
     AssertIsOnBackgroundThread();
     MOZ_ASSERT(aLiveActorArray);
     MOZ_ASSERT(!aLiveActorArray->Contains(this));
     MOZ_ASSERT(!mLiveActorArray);
     MOZ_ASSERT(mIsOtherProcessActor);
 
     mLiveActorArray = aLiveActorArray;
     mLiveActorArray->AppendElement(this);
@@ -265,16 +272,17 @@ class ChildImpl final : public Backgroun
 
   // A thread-local index that is not valid.
   static const unsigned int kBadThreadLocalIndex =
       static_cast<unsigned int>(-1);
 
   // This is only modified on the main thread. It is the thread-local index that
   // we use to store the BackgroundChild for each thread.
   static unsigned int sThreadLocalIndex;
+  static unsigned int sThreadLocalIndexForSocketProcess;
 
   struct ThreadLocalInfo {
     ThreadLocalInfo()
 #ifdef DEBUG
         : mClosed(false)
 #endif
     {
     }
@@ -287,32 +295,36 @@ class ChildImpl final : public Backgroun
 #endif
   };
 
   // On the main thread, we store TLS in this global instead of in
   // sThreadLocalIndex. That way, cooperative main threads all share the same
   // thread info.
   static ThreadLocalInfo* sMainThreadInfo;
 
+  static ThreadLocalInfo* sMainThreadInfoForSocketProcess;
+
   // This is only modified on the main thread. It prevents us from trying to
   // create the background thread after application shutdown has started.
   static bool sShutdownHasStarted;
 
 #if defined(DEBUG) || !defined(RELEASE_OR_BETA)
   nsISerialEventTarget* mOwningEventTarget;
 #endif
 
 #ifdef DEBUG
   bool mActorWasAlive;
   bool mActorDestroyed;
 #endif
 
  public:
   static void Shutdown();
 
+  static void ShutdownWithThreadLocalIndex(unsigned int aThreadLocalIndex);
+
   void AssertIsOnOwningThread() {
     THREADSAFETY_ASSERT(mOwningEventTarget);
 
 #ifdef RELEASE_OR_BETA
     DebugOnly<bool> current;
 #else
     bool current;
 #endif
@@ -352,23 +364,33 @@ class ChildImpl final : public Backgroun
 
  private:
   // Forwarded from BackgroundChild.
   static void Startup();
 
   // Forwarded from BackgroundChild.
   static PBackgroundChild* GetForCurrentThread();
 
+  // Helper function for getting PBackgroundChild from thread info.
+  static PBackgroundChild* GetFromThreadInfo(nsIEventTarget* aMainEventTarget,
+                                             ThreadLocalInfo* aThreadLocalInfo);
+
   // Forwarded from BackgroundChild.
   static PBackgroundChild* GetOrCreateForCurrentThread(
       nsIEventTarget* aMainEventTarget);
 
   // Forwarded from BackgroundChild.
+  static PBackgroundChild* GetOrCreateSocketActorForCurrentThread(
+      nsIEventTarget* aMainEventTarget);
+
+  // Forwarded from BackgroundChild.
   static void CloseForCurrentThread();
 
+  static void CloseThreadWithIndex(unsigned int aThreadLocalIndex);
+
   // Forwarded from BackgroundChildImpl.
   static BackgroundChildImpl::ThreadLocal* GetThreadLocalForCurrentThread();
 
   static void ThreadLocalDestructor(void* aThreadLocal);
 
   // This class is reference counted.
   ~ChildImpl() { MOZ_ASSERT_IF(mActorWasAlive, mActorDestroyed); }
 
@@ -395,32 +417,32 @@ class ParentImpl::RequestMessageLoopRunn
   nsCOMPtr<nsIThread> mTargetThread;
   MessageLoop* mMessageLoop;
 
  public:
   explicit RequestMessageLoopRunnable(nsIThread* aTargetThread)
       : Runnable("Background::ParentImpl::RequestMessageLoopRunnable"),
         mTargetThread(aTargetThread),
         mMessageLoop(nullptr) {
-    AssertIsInMainProcess();
+    AssertIsInMainOrSocketProcess();
     AssertIsOnMainThread();
     MOZ_ASSERT(aTargetThread);
   }
 
  private:
   ~RequestMessageLoopRunnable() {}
 
   NS_DECL_NSIRUNNABLE
 };
 
 class ParentImpl::ShutdownBackgroundThreadRunnable final : public Runnable {
  public:
   ShutdownBackgroundThreadRunnable()
       : Runnable("Background::ParentImpl::ShutdownBackgroundThreadRunnable") {
-    AssertIsInMainProcess();
+    AssertIsInMainOrSocketProcess();
     AssertIsOnMainThread();
   }
 
  private:
   ~ShutdownBackgroundThreadRunnable() {}
 
   NS_DECL_NSIRUNNABLE
 };
@@ -428,17 +450,17 @@ class ParentImpl::ShutdownBackgroundThre
 class ParentImpl::ForceCloseBackgroundActorsRunnable final : public Runnable {
   nsTArray<ParentImpl*>* mActorArray;
 
  public:
   explicit ForceCloseBackgroundActorsRunnable(
       nsTArray<ParentImpl*>* aActorArray)
       : Runnable("Background::ParentImpl::ForceCloseBackgroundActorsRunnable"),
         mActorArray(aActorArray) {
-    AssertIsInMainProcess();
+    AssertIsInMainOrSocketProcess();
     AssertIsOnMainThread();
     MOZ_ASSERT(aActorArray);
   }
 
  private:
   ~ForceCloseBackgroundActorsRunnable() {}
 
   NS_DECL_NSIRUNNABLE
@@ -452,24 +474,24 @@ class ParentImpl::ConnectActorRunnable f
  public:
   ConnectActorRunnable(ParentImpl* aActor,
                        Endpoint<PBackgroundParent>&& aEndpoint,
                        nsTArray<ParentImpl*>* aLiveActorArray)
       : Runnable("Background::ParentImpl::ConnectActorRunnable"),
         mActor(aActor),
         mEndpoint(std::move(aEndpoint)),
         mLiveActorArray(aLiveActorArray) {
-    AssertIsInMainProcess();
+    AssertIsInMainOrSocketProcess();
     AssertIsOnMainThread();
     MOZ_ASSERT(mEndpoint.IsValid());
     MOZ_ASSERT(aLiveActorArray);
   }
 
  private:
-  ~ConnectActorRunnable() { AssertIsInMainProcess(); }
+  ~ConnectActorRunnable() { AssertIsInMainOrSocketProcess(); }
 
   NS_DECL_NSIRUNNABLE
 };
 
 class ParentImpl::CreateActorHelper final : public Runnable {
   mozilla::Monitor mMonitor;
   RefPtr<ParentImpl> mParentActor;
   nsCOMPtr<nsIThread> mThread;
@@ -477,26 +499,26 @@ class ParentImpl::CreateActorHelper fina
   bool mWaiting;
 
  public:
   explicit CreateActorHelper()
       : Runnable("Background::ParentImpl::CreateActorHelper"),
         mMonitor("CreateActorHelper::mMonitor"),
         mMainThreadResultCode(NS_OK),
         mWaiting(true) {
-    AssertIsInMainProcess();
+    AssertIsInMainOrSocketProcess();
     AssertIsNotOnMainThread();
   }
 
   nsresult BlockAndGetResults(nsIEventTarget* aMainEventTarget,
                               RefPtr<ParentImpl>& aParentActor,
                               nsCOMPtr<nsIThread>& aThread);
 
  private:
-  ~CreateActorHelper() { AssertIsInMainProcess(); }
+  ~CreateActorHelper() { AssertIsInMainOrSocketProcess(); }
 
   nsresult RunOnMainThread();
 
   NS_DECL_NSIRUNNABLE
 };
 
 class NS_NO_VTABLE ParentImpl::CreateCallback {
  public:
@@ -527,35 +549,40 @@ class ChildImpl::ShutdownObserver final 
 };
 
 class ChildImpl::SendInitBackgroundRunnable final : public CancelableRunnable {
   nsCOMPtr<nsISerialEventTarget> mOwningEventTarget;
   RefPtr<StrongWorkerRef> mWorkerRef;
   Endpoint<PBackgroundParent> mParent;
   mozilla::Mutex mMutex;
   bool mSentInitBackground;
+  std::function<void(Endpoint<PBackgroundParent>&& aParent)> mSendInitfunc;
 
  public:
   static already_AddRefed<SendInitBackgroundRunnable> Create(
-      Endpoint<PBackgroundParent>&& aParent);
+      Endpoint<PBackgroundParent>&& aParent,
+      std::function<void(Endpoint<PBackgroundParent>&& aParent)>&& aFunc);
 
   void ClearEventTarget() {
     mWorkerRef = nullptr;
 
     mozilla::MutexAutoLock lock(mMutex);
     mOwningEventTarget = nullptr;
   }
 
  private:
-  explicit SendInitBackgroundRunnable(Endpoint<PBackgroundParent>&& aParent)
+  explicit SendInitBackgroundRunnable(
+      Endpoint<PBackgroundParent>&& aParent,
+      std::function<void(Endpoint<PBackgroundParent>&& aParent)>&& aFunc)
       : CancelableRunnable("Background::ChildImpl::SendInitBackgroundRunnable"),
         mOwningEventTarget(GetCurrentThreadSerialEventTarget()),
         mParent(std::move(aParent)),
         mMutex("SendInitBackgroundRunnable::mMutex"),
-        mSentInitBackground(false) {}
+        mSentInitBackground(false),
+        mSendInitfunc(std::move(aFunc)) {}
 
   ~SendInitBackgroundRunnable() {}
 
   NS_DECL_NSIRUNNABLE
 };
 
 }  // namespace
 
@@ -627,16 +654,22 @@ PBackgroundChild* BackgroundChild::GetFo
 
 // static
 PBackgroundChild* BackgroundChild::GetOrCreateForCurrentThread(
     nsIEventTarget* aMainEventTarget) {
   return ChildImpl::GetOrCreateForCurrentThread(aMainEventTarget);
 }
 
 // static
+PBackgroundChild* BackgroundChild::GetOrCreateSocketActorForCurrentThread(
+    nsIEventTarget* aMainEventTarget) {
+  return ChildImpl::GetOrCreateSocketActorForCurrentThread(aMainEventTarget);
+}
+
+// static
 void BackgroundChild::CloseForCurrentThread() {
   ChildImpl::CloseForCurrentThread();
 }
 
 // -----------------------------------------------------------------------------
 // BackgroundChildImpl Public Methods
 // -----------------------------------------------------------------------------
 
@@ -666,16 +699,18 @@ bool ParentImpl::sShutdownObserverRegist
 
 bool ParentImpl::sShutdownHasStarted = false;
 
 // -----------------------------------------------------------------------------
 // ChildImpl Static Members
 // -----------------------------------------------------------------------------
 
 unsigned int ChildImpl::sThreadLocalIndex = kBadThreadLocalIndex;
+unsigned int ChildImpl::sThreadLocalIndexForSocketProcess =
+    kBadThreadLocalIndex;
 
 bool ChildImpl::sShutdownHasStarted = false;
 
 // -----------------------------------------------------------------------------
 // ParentImpl Implementation
 // -----------------------------------------------------------------------------
 
 // static
@@ -771,17 +806,17 @@ bool ParentImpl::GetLiveActorArray(
   }
 
   return true;
 }
 
 // static
 bool ParentImpl::Alloc(ContentParent* aContent,
                        Endpoint<PBackgroundParent>&& aEndpoint) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnMainThread();
   MOZ_ASSERT(aEndpoint.IsValid());
 
   if (!sBackgroundThread && !CreateBackgroundThread()) {
     NS_WARNING("Failed to create background thread!");
     return false;
   }
 
@@ -862,17 +897,17 @@ already_AddRefed<ChildImpl> ParentImpl::
   // Now that Open() has succeeded transfer the ownership of the actors to IPDL.
   Unused << parentActor.forget();
 
   return childActor.forget();
 }
 
 // static
 bool ParentImpl::CreateBackgroundThread() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnMainThread();
   MOZ_ASSERT(!sBackgroundThread);
   MOZ_ASSERT(!sLiveActorsForBackgroundThread);
 
   if (sShutdownHasStarted) {
     NS_WARNING(
         "Trying to create background thread after shutdown has "
         "already begun!");
@@ -926,17 +961,17 @@ bool ParentImpl::CreateBackgroundThread(
     sShutdownTimer = newShutdownTimer;
   }
 
   return true;
 }
 
 // static
 void ParentImpl::ShutdownBackgroundThread() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnMainThread();
   MOZ_ASSERT(sShutdownHasStarted);
   MOZ_ASSERT_IF(!sBackgroundThread, !sLiveActorCount);
   MOZ_ASSERT_IF(sBackgroundThread, sShutdownTimer);
 
   nsCOMPtr<nsITimer> shutdownTimer = sShutdownTimer.get();
   sShutdownTimer = nullptr;
 
@@ -971,17 +1006,17 @@ void ParentImpl::ShutdownBackgroundThrea
     MOZ_ALWAYS_SUCCEEDS(thread->Dispatch(shutdownRunnable, NS_DISPATCH_NORMAL));
 
     MOZ_ALWAYS_SUCCEEDS(thread->Shutdown());
   }
 }
 
 // static
 void ParentImpl::ShutdownTimerCallback(nsITimer* aTimer, void* aClosure) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnMainThread();
   MOZ_ASSERT(sShutdownHasStarted);
   MOZ_ASSERT(sLiveActorCount);
 
   auto closure = static_cast<TimerCallbackClosure*>(aClosure);
   MOZ_ASSERT(closure);
 
   // Don't let the stack unwind until the ForceCloseBackgroundActorsRunnable has
@@ -992,40 +1027,40 @@ void ParentImpl::ShutdownTimerCallback(n
       new ForceCloseBackgroundActorsRunnable(closure->mLiveActors);
   MOZ_ALWAYS_SUCCEEDS(
       closure->mThread->Dispatch(forceCloseRunnable, NS_DISPATCH_NORMAL));
 }
 
 void ParentImpl::Destroy() {
   // May be called on any thread!
 
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
 
   MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(
       NewNonOwningRunnableMethod("ParentImpl::MainThreadActorDestroy", this,
                                  &ParentImpl::MainThreadActorDestroy)));
 }
 
 void ParentImpl::MainThreadActorDestroy() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnMainThread();
-  MOZ_ASSERT_IF(mIsOtherProcessActor, mContent);
+  MOZ_ASSERT_IF(mIsOtherProcessActor && XRE_IsParentProcess(), mContent);
   MOZ_ASSERT_IF(!mIsOtherProcessActor, !mContent);
 
   mContent = nullptr;
 
   MOZ_ASSERT(sLiveActorCount);
   sLiveActorCount--;
 
   // This may be the last reference!
   Release();
 }
 
 void ParentImpl::ActorDestroy(ActorDestroyReason aWhy) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(!mActorDestroyed);
   MOZ_ASSERT_IF(mIsOtherProcessActor, mLiveActorArray);
 
   BackgroundParentImpl::ActorDestroy(aWhy);
 
   mActorDestroyed = true;
 
@@ -1046,35 +1081,39 @@ void ParentImpl::ActorDestroy(ActorDestr
       "ParentImpl::Destroy", this, &ParentImpl::Destroy)));
 }
 
 NS_IMPL_ISUPPORTS(ParentImpl::ShutdownObserver, nsIObserver)
 
 NS_IMETHODIMP
 ParentImpl::ShutdownObserver::Observe(nsISupports* aSubject, const char* aTopic,
                                       const char16_t* aData) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnMainThread();
   MOZ_ASSERT(!sShutdownHasStarted);
   MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID));
 
   sShutdownHasStarted = true;
 
   // Do this first before calling (and spinning the event loop in)
   // ShutdownBackgroundThread().
-  ChildImpl::Shutdown();
+  // Since we didn't call BackgroundChild::Startup() in socket process,
+  // we can't call ChildImpl::Shutdown() here.
+  if (!XRE_IsSocketProcess()) {
+    ChildImpl::Shutdown();
+  }
 
   ShutdownBackgroundThread();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ParentImpl::RequestMessageLoopRunnable::Run() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   MOZ_ASSERT(mTargetThread);
 
   if (NS_IsMainThread()) {
     MOZ_ASSERT(mMessageLoop);
 
     if (!sBackgroundThread ||
         !SameCOMIdentity(mTargetThread.get(), sBackgroundThread.get())) {
       return NS_OK;
@@ -1110,29 +1149,29 @@ ParentImpl::RequestMessageLoopRunnable::
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ParentImpl::ShutdownBackgroundThreadRunnable::Run() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
 
   // It is possible that another background thread was created while this thread
   // was shutting down. In that case we can't assert anything about
   // sBackgroundPRThread and we should not modify it here.
   sBackgroundPRThread.compareExchange(PR_GetCurrentThread(), nullptr);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ParentImpl::ForceCloseBackgroundActorsRunnable::Run() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   MOZ_ASSERT(mActorArray);
 
   if (NS_IsMainThread()) {
     MOZ_ASSERT(sLiveActorCount);
     sLiveActorCount--;
     return NS_OK;
   }
 
@@ -1149,17 +1188,17 @@ ParentImpl::ForceCloseBackgroundActorsRu
 
   MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(this));
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ParentImpl::ConnectActorRunnable::Run() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   // Transfer ownership to this thread. If Open() fails then we will release
   // this reference in Destroy.
   ParentImpl* actor;
   mActor.forget(&actor);
 
   Endpoint<PBackgroundParent> endpoint = std::move(mEndpoint);
@@ -1241,67 +1280,92 @@ ParentImpl::CreateActorHelper::Run() {
 
 // static
 void ChildImpl::Startup() {
   // This happens on the main thread but before XPCOM has started so we can't
   // assert that we're being called on the main thread here.
 
   MOZ_ASSERT(sThreadLocalIndex == kBadThreadLocalIndex,
              "BackgroundChild::Startup() called more than once!");
+  MOZ_ASSERT(sThreadLocalIndexForSocketProcess == kBadThreadLocalIndex,
+             "BackgroundChild::Startup() called more than once!");
 
   PRStatus status =
       PR_NewThreadPrivateIndex(&sThreadLocalIndex, ThreadLocalDestructor);
   MOZ_RELEASE_ASSERT(status == PR_SUCCESS, "PR_NewThreadPrivateIndex failed!");
 
+  status = PR_NewThreadPrivateIndex(&sThreadLocalIndexForSocketProcess,
+                                    ThreadLocalDestructor);
+  MOZ_RELEASE_ASSERT(status == PR_SUCCESS, "PR_NewThreadPrivateIndex failed!");
+
   MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex);
+  MOZ_ASSERT(sThreadLocalIndexForSocketProcess != kBadThreadLocalIndex);
 
   nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
   MOZ_RELEASE_ASSERT(observerService);
 
   nsCOMPtr<nsIObserver> observer = new ShutdownObserver();
 
   nsresult rv = observerService->AddObserver(
       observer, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false);
   MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
 }
 
-// static
-void ChildImpl::Shutdown() {
-  AssertIsOnMainThread();
-
-  if (sShutdownHasStarted) {
-    MOZ_ASSERT_IF(sThreadLocalIndex != kBadThreadLocalIndex,
-                  !PR_GetThreadPrivate(sThreadLocalIndex));
-    return;
-  }
-
-  sShutdownHasStarted = true;
-
-  MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex);
+void ChildImpl::ShutdownWithThreadLocalIndex(unsigned int aThreadLocalIndex) {
+  MOZ_ASSERT(aThreadLocalIndex != kBadThreadLocalIndex);
 
   ThreadLocalInfo* threadLocalInfo;
 #ifdef DEBUG
   threadLocalInfo =
-      static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex));
+      static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(aThreadLocalIndex));
   MOZ_ASSERT(!threadLocalInfo);
 #endif
-  threadLocalInfo = sMainThreadInfo;
+  threadLocalInfo = aThreadLocalIndex == sThreadLocalIndex
+                        ? sMainThreadInfo
+                        : sMainThreadInfoForSocketProcess;
 
   if (threadLocalInfo) {
 #ifdef DEBUG
     MOZ_ASSERT(!threadLocalInfo->mClosed);
     threadLocalInfo->mClosed = true;
 #endif
 
     ThreadLocalDestructor(threadLocalInfo);
-    sMainThreadInfo = nullptr;
+    if (aThreadLocalIndex == sThreadLocalIndex) {
+      sMainThreadInfo = nullptr;
+    } else {
+      sMainThreadInfoForSocketProcess = nullptr;
+    }
+  }
+}
+
+// static
+void ChildImpl::Shutdown() {
+  AssertIsOnMainThread();
+
+  if (sShutdownHasStarted) {
+    MOZ_ASSERT_IF(sThreadLocalIndex != kBadThreadLocalIndex,
+                  !PR_GetThreadPrivate(sThreadLocalIndex));
+    MOZ_ASSERT_IF(sThreadLocalIndexForSocketProcess != kBadThreadLocalIndex,
+                  !PR_GetThreadPrivate(sThreadLocalIndexForSocketProcess));
+    return;
+  }
+
+  sShutdownHasStarted = true;
+
+  ShutdownWithThreadLocalIndex(sThreadLocalIndex);
+
+  if (sThreadLocalIndexForSocketProcess != kBadThreadLocalIndex) {
+    ShutdownWithThreadLocalIndex(sThreadLocalIndexForSocketProcess);
   }
 }
 
 ChildImpl::ThreadLocalInfo* ChildImpl::sMainThreadInfo = nullptr;
+ChildImpl::ThreadLocalInfo* ChildImpl::sMainThreadInfoForSocketProcess =
+    nullptr;
 
 // static
 PBackgroundChild* ChildImpl::GetForCurrentThread() {
   MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex);
 
   auto threadLocalInfo = NS_IsMainThread()
                              ? sMainThreadInfo
                              : static_cast<ThreadLocalInfo*>(
@@ -1310,16 +1374,51 @@ PBackgroundChild* ChildImpl::GetForCurre
   if (!threadLocalInfo) {
     return nullptr;
   }
 
   return threadLocalInfo->mActor;
 }
 
 /* static */
+PBackgroundChild* ChildImpl::GetFromThreadInfo(
+    nsIEventTarget* aMainEventTarget, ThreadLocalInfo* aThreadLocalInfo) {
+  MOZ_ASSERT(aThreadLocalInfo);
+
+  if (aThreadLocalInfo->mActor) {
+    RefPtr<SendInitBackgroundRunnable>& runnable =
+        aThreadLocalInfo->mSendInitBackgroundRunnable;
+
+    if (aMainEventTarget && runnable) {
+      // The SendInitBackgroundRunnable was already dispatched to the main
+      // thread to finish initialization of a new background child actor.
+      // However, the caller passed a custom main event target which indicates
+      // that synchronous blocking of the main thread is happening (done by
+      // creating a nested event target and spinning the event loop).
+      // It can happen that the SendInitBackgroundRunnable didn't have a chance
+      // to run before the synchronous blocking has occured. Unblocking of the
+      // main thread can depend on an IPC message received on this thread, so
+      // we have to dispatch the SendInitBackgroundRunnable to the custom main
+      // event target too, otherwise IPC will be only queueing messages on this
+      // thread. The runnable will run twice in the end, but that's a harmless
+      // race between the main and nested event queue of the main thread.
+      // There's a guard in the runnable implementation for calling
+      // SendInitBackground only once.
+
+      MOZ_ALWAYS_SUCCEEDS(
+          aMainEventTarget->Dispatch(runnable, NS_DISPATCH_NORMAL));
+    }
+
+    return aThreadLocalInfo->mActor;
+  }
+
+  return nullptr;
+}
+
+/* static */
 PBackgroundChild* ChildImpl::GetOrCreateForCurrentThread(
     nsIEventTarget* aMainEventTarget) {
   MOZ_ASSERT_IF(NS_IsMainThread(), !aMainEventTarget);
 
   MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex,
              "BackgroundChild::Startup() was never called!");
 
   if (NS_IsMainThread() && sShutdownHasStarted) {
@@ -1341,41 +1440,20 @@ PBackgroundChild* ChildImpl::GetOrCreate
         CRASH_IN_CHILD_PROCESS("PR_SetThreadPrivate failed!");
         return nullptr;
       }
     }
 
     threadLocalInfo = newInfo.forget();
   }
 
-  if (threadLocalInfo->mActor) {
-    RefPtr<SendInitBackgroundRunnable>& runnable =
-        threadLocalInfo->mSendInitBackgroundRunnable;
-
-    if (aMainEventTarget && runnable) {
-      // The SendInitBackgroundRunnable was already dispatched to the main
-      // thread to finish initialization of a new background child actor.
-      // However, the caller passed a custom main event target which indicates
-      // that synchronous blocking of the main thread is happening (done by
-      // creating a nested event target and spinning the event loop).
-      // It can happen that the SendInitBackgroundRunnable didn't have a chance
-      // to run before the synchronous blocking has occured. Unblocking of the
-      // main thread can depend on an IPC message received on this thread, so
-      // we have to dispatch the SendInitBackgroundRunnable to the custom main
-      // event target too, otherwise IPC will be only queueing messages on this
-      // thread. The runnable will run twice in the end, but that's a harmless
-      // race between the main and nested event queue of the main thread.
-      // There's a guard in the runnable implementation for calling
-      // SendInitBackground only once.
-
-      MOZ_ALWAYS_SUCCEEDS(
-          aMainEventTarget->Dispatch(runnable, NS_DISPATCH_NORMAL));
-    }
-
-    return threadLocalInfo->mActor;
+  PBackgroundChild* bgChild =
+      GetFromThreadInfo(aMainEventTarget, threadLocalInfo);
+  if (bgChild) {
+    return bgChild;
   }
 
   if (XRE_IsParentProcess()) {
     RefPtr<ChildImpl> strongActor =
         ParentImpl::CreateActorForSameProcess(aMainEventTarget);
     if (NS_WARN_IF(!strongActor)) {
       return nullptr;
     }
@@ -1402,17 +1480,25 @@ PBackgroundChild* ChildImpl::GetOrCreate
                                     base::GetCurrentProcId(), &parent, &child);
   if (NS_FAILED(rv)) {
     NS_WARNING("Failed to create top level actor!");
     return nullptr;
   }
 
   RefPtr<SendInitBackgroundRunnable> runnable;
   if (!NS_IsMainThread()) {
-    runnable = SendInitBackgroundRunnable::Create(std::move(parent));
+    runnable = SendInitBackgroundRunnable::Create(
+        std::move(parent), [](Endpoint<PBackgroundParent>&& aParent) {
+          RefPtr<ContentChild> content = ContentChild::GetSingleton();
+          MOZ_ASSERT(content);
+
+          if (!content->SendInitBackground(std::move(aParent))) {
+            MOZ_CRASH("Failed to create top level actor!");
+          }
+        });
     if (!runnable) {
       return nullptr;
     }
   }
 
   RefPtr<ChildImpl> strongActor = new ChildImpl();
 
   if (!child.Bind(strongActor)) {
@@ -1440,44 +1526,156 @@ PBackgroundChild* ChildImpl::GetOrCreate
   }
 
   RefPtr<ChildImpl>& actor = threadLocalInfo->mActor;
   strongActor.swap(actor);
 
   return actor;
 }
 
-// static
-void ChildImpl::CloseForCurrentThread() {
-  MOZ_ASSERT(!NS_IsMainThread(),
-             "PBackground for the main thread should be shut down via "
-             "ChildImpl::Shutdown().");
+/* static */
+PBackgroundChild* ChildImpl::GetOrCreateSocketActorForCurrentThread(
+    nsIEventTarget* aMainEventTarget) {
+  MOZ_ASSERT_IF(NS_IsMainThread(), !aMainEventTarget);
 
-  if (sThreadLocalIndex == kBadThreadLocalIndex) {
-    return;
+  MOZ_ASSERT(sThreadLocalIndexForSocketProcess != kBadThreadLocalIndex,
+             "BackgroundChild::Startup() was never called!");
+
+  if (NS_IsMainThread() && sShutdownHasStarted) {
+    return nullptr;
   }
 
   auto threadLocalInfo =
-      static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex));
+      NS_IsMainThread() ? sMainThreadInfoForSocketProcess
+                        : static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(
+                              sThreadLocalIndexForSocketProcess));
+
+  if (!threadLocalInfo) {
+    nsAutoPtr<ThreadLocalInfo> newInfo(new ThreadLocalInfo());
+
+    if (NS_IsMainThread()) {
+      sMainThreadInfoForSocketProcess = newInfo;
+    } else {
+      if (PR_SetThreadPrivate(sThreadLocalIndexForSocketProcess, newInfo) !=
+          PR_SUCCESS) {
+        CRASH_IN_CHILD_PROCESS("PR_SetThreadPrivate failed!");
+        return nullptr;
+      }
+    }
+
+    threadLocalInfo = newInfo.forget();
+  }
+
+  PBackgroundChild* bgChild =
+      GetFromThreadInfo(aMainEventTarget, threadLocalInfo);
+  if (bgChild) {
+    return bgChild;
+  }
+
+  RefPtr<SocketProcessBridgeChild> bridgeChild =
+      SocketProcessBridgeChild::GetSingleton();
+
+  if (!bridgeChild || bridgeChild->IsShuttingDown()) {
+    // The transport for SocketProcessBridgeChild is shut down
+    // and can't be used to open PBackground.
+    return nullptr;
+  }
+
+  Endpoint<PBackgroundParent> parent;
+  Endpoint<PBackgroundChild> child;
+  nsresult rv;
+  rv = PBackground::CreateEndpoints(bridgeChild->SocketProcessPid(),
+                                    base::GetCurrentProcId(), &parent, &child);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to create top level actor!");
+    return nullptr;
+  }
+
+  RefPtr<SendInitBackgroundRunnable> runnable;
+  if (!NS_IsMainThread()) {
+    runnable = SendInitBackgroundRunnable::Create(
+        std::move(parent), [](Endpoint<PBackgroundParent>&& aParent) {
+          RefPtr<SocketProcessBridgeChild> bridgeChild =
+              SocketProcessBridgeChild::GetSingleton();
+
+          if (!bridgeChild->SendInitBackground(std::move(aParent))) {
+            MOZ_CRASH("Failed to create top level actor!");
+          }
+        });
+    if (!runnable) {
+      return nullptr;
+    }
+  }
+
+  RefPtr<ChildImpl> strongActor = new ChildImpl();
+
+  if (!child.Bind(strongActor)) {
+    CRASH_IN_CHILD_PROCESS("Failed to bind ChildImpl!");
+
+    return nullptr;
+  }
+
+  strongActor->SetActorAlive();
+
+  if (NS_IsMainThread()) {
+    if (!bridgeChild->SendInitBackground(std::move(parent))) {
+      NS_WARNING("Failed to create top level actor!");
+      return nullptr;
+    }
+  } else {
+    if (aMainEventTarget) {
+      MOZ_ALWAYS_SUCCEEDS(
+          aMainEventTarget->Dispatch(runnable, NS_DISPATCH_NORMAL));
+    } else {
+      MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
+    }
+
+    threadLocalInfo->mSendInitBackgroundRunnable = runnable;
+  }
+
+  RefPtr<ChildImpl>& actor = threadLocalInfo->mActor;
+  strongActor.swap(actor);
+
+  return actor;
+}
+
+// static
+void ChildImpl::CloseThreadWithIndex(unsigned int aThreadLocalIndex) {
+  auto threadLocalInfo =
+      static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(aThreadLocalIndex));
 
   if (!threadLocalInfo) {
     return;
   }
 
 #ifdef DEBUG
   MOZ_ASSERT(!threadLocalInfo->mClosed);
   threadLocalInfo->mClosed = true;
 #endif
 
   // Clearing the thread local will synchronously close the actor.
-  DebugOnly<PRStatus> status = PR_SetThreadPrivate(sThreadLocalIndex, nullptr);
+  DebugOnly<PRStatus> status = PR_SetThreadPrivate(aThreadLocalIndex, nullptr);
   MOZ_ASSERT(status == PR_SUCCESS);
 }
 
 // static
+void ChildImpl::CloseForCurrentThread() {
+  MOZ_ASSERT(!NS_IsMainThread(),
+             "PBackground for the main thread should be shut down via "
+             "ChildImpl::Shutdown().");
+
+  if (sThreadLocalIndex != kBadThreadLocalIndex) {
+    CloseThreadWithIndex(sThreadLocalIndex);
+  }
+  if (sThreadLocalIndexForSocketProcess != kBadThreadLocalIndex) {
+    CloseThreadWithIndex(sThreadLocalIndexForSocketProcess);
+  }
+}
+
+// static
 BackgroundChildImpl::ThreadLocal* ChildImpl::GetThreadLocalForCurrentThread() {
   MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex,
              "BackgroundChild::Startup() was never called!");
 
   auto threadLocalInfo = NS_IsMainThread()
                              ? sMainThreadInfo
                              : static_cast<ThreadLocalInfo*>(
                                    PR_GetThreadPrivate(sThreadLocalIndex));
@@ -1536,21 +1734,22 @@ ChildImpl::ShutdownObserver::Observe(nsI
   ChildImpl::Shutdown();
 
   return NS_OK;
 }
 
 // static
 already_AddRefed<ChildImpl::SendInitBackgroundRunnable>
 ChildImpl::SendInitBackgroundRunnable::Create(
-    Endpoint<PBackgroundParent>&& aParent) {
+    Endpoint<PBackgroundParent>&& aParent,
+    std::function<void(Endpoint<PBackgroundParent>&& aParent)>&& aFunc) {
   MOZ_ASSERT(!NS_IsMainThread());
 
   RefPtr<SendInitBackgroundRunnable> runnable =
-      new SendInitBackgroundRunnable(std::move(aParent));
+      new SendInitBackgroundRunnable(std::move(aParent), std::move(aFunc));
 
   WorkerPrivate* workerPrivate = mozilla::dom::GetCurrentThreadWorkerPrivate();
   if (!workerPrivate) {
     return runnable.forget();
   }
 
   workerPrivate->AssertIsOnWorkerThread();
 
@@ -1567,22 +1766,17 @@ NS_IMETHODIMP
 ChildImpl::SendInitBackgroundRunnable::Run() {
   if (NS_IsMainThread()) {
     if (mSentInitBackground) {
       return NS_OK;
     }
 
     mSentInitBackground = true;
 
-    RefPtr<ContentChild> content = ContentChild::GetSingleton();
-    MOZ_ASSERT(content);
-
-    if (!content->SendInitBackground(std::move(mParent))) {
-      MOZ_CRASH("Failed to create top level actor!");
-    }
+    mSendInitfunc(std::move(mParent));
 
     nsCOMPtr<nsISerialEventTarget> owningEventTarget;
     {
       mozilla::MutexAutoLock lock(mMutex);
       owningEventTarget = mOwningEventTarget;
     }
 
     if (!owningEventTarget) {
--- a/ipc/glue/BackgroundParent.h
+++ b/ipc/glue/BackgroundParent.h
@@ -10,16 +10,23 @@
 #include "base/process.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/ipc/Transport.h"
 
 template <class>
 struct already_AddRefed;
 
 namespace mozilla {
+
+namespace net {
+
+class SocketProcessBridgeParent;
+
+}  // namespace net
+
 namespace dom {
 
 class BlobImpl;
 class ContentParent;
 
 }  // namespace dom
 
 namespace ipc {
@@ -33,16 +40,17 @@ class Endpoint;
 // member functions.
 class BackgroundParent final {
   friend class mozilla::dom::ContentParent;
 
   typedef base::ProcessId ProcessId;
   typedef mozilla::dom::BlobImpl BlobImpl;
   typedef mozilla::dom::ContentParent ContentParent;
   typedef mozilla::ipc::Transport Transport;
+  friend class mozilla::net::SocketProcessBridgeParent;
 
  public:
   // This function allows the caller to determine if the given parent actor
   // corresponds to a child actor from another process or a child actor from a
   // different thread in the same process.
   // This function may only be called on the background thread.
   static bool IsOtherProcessActor(PBackgroundParent* aBackgroundActor);
 
@@ -68,16 +76,19 @@ class BackgroundParent final {
 
   static bool GetLiveActorArray(PBackgroundParent* aBackgroundActor,
                                 nsTArray<PBackgroundParent*>& aLiveActorArray);
 
  private:
   // Only called by ContentParent for cross-process actors.
   static bool Alloc(ContentParent* aContent,
                     Endpoint<PBackgroundParent>&& aEndpoint);
+
+  // Only called by SocketProcessBridgeParent for cross-process actors.
+  static bool Alloc(Endpoint<PBackgroundParent>&& aEndpoint);
 };
 
 // Implemented in BackgroundImpl.cpp.
 bool IsOnBackgroundThread();
 
 #ifdef DEBUG
 
 // Implemented in BackgroundImpl.cpp.
@@ -86,12 +97,16 @@ void AssertIsOnBackgroundThread();
 #else
 
 inline void AssertIsOnBackgroundThread() {}
 
 #endif  // DEBUG
 
 inline void AssertIsInMainProcess() { MOZ_ASSERT(XRE_IsParentProcess()); }
 
+inline void AssertIsInMainOrSocketProcess() {
+  MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess());
+}
+
 }  // namespace ipc
 }  // namespace mozilla
 
 #endif  // mozilla_ipc_backgroundparent_h__
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -113,359 +113,359 @@ class TestParent final : public mozilla:
 namespace mozilla {
 namespace ipc {
 
 using mozilla::dom::BroadcastChannelParent;
 using mozilla::dom::ContentParent;
 using mozilla::dom::ServiceWorkerRegistrationData;
 
 BackgroundParentImpl::BackgroundParentImpl() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnMainThread();
 
   MOZ_COUNT_CTOR(mozilla::ipc::BackgroundParentImpl);
 }
 
 BackgroundParentImpl::~BackgroundParentImpl() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnMainThread();
 
   MOZ_COUNT_DTOR(mozilla::ipc::BackgroundParentImpl);
 }
 
 void BackgroundParentImpl::ActorDestroy(ActorDestroyReason aWhy) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 }
 
 BackgroundParentImpl::PBackgroundTestParent*
 BackgroundParentImpl::AllocPBackgroundTestParent(const nsCString& aTestArg) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   return new TestParent();
 }
 
 mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBackgroundTestConstructor(
     PBackgroundTestParent* aActor, const nsCString& aTestArg) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   if (!PBackgroundTestParent::Send__delete__(aActor, aTestArg)) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
 bool BackgroundParentImpl::DeallocPBackgroundTestParent(
     PBackgroundTestParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   delete static_cast<TestParent*>(aActor);
   return true;
 }
 
 auto BackgroundParentImpl::AllocPBackgroundIDBFactoryParent(
     const LoggingInfo& aLoggingInfo) -> PBackgroundIDBFactoryParent* {
   using mozilla::dom::indexedDB::AllocPBackgroundIDBFactoryParent;
 
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   return AllocPBackgroundIDBFactoryParent(aLoggingInfo);
 }
 
 mozilla::ipc::IPCResult
 BackgroundParentImpl::RecvPBackgroundIDBFactoryConstructor(
     PBackgroundIDBFactoryParent* aActor, const LoggingInfo& aLoggingInfo) {
   using mozilla::dom::indexedDB::RecvPBackgroundIDBFactoryConstructor;
 
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   if (!RecvPBackgroundIDBFactoryConstructor(aActor, aLoggingInfo)) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
 bool BackgroundParentImpl::DeallocPBackgroundIDBFactoryParent(
     PBackgroundIDBFactoryParent* aActor) {
   using mozilla::dom::indexedDB::DeallocPBackgroundIDBFactoryParent;
 
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   return DeallocPBackgroundIDBFactoryParent(aActor);
 }
 
 auto BackgroundParentImpl::AllocPBackgroundIndexedDBUtilsParent()
     -> PBackgroundIndexedDBUtilsParent* {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   return mozilla::dom::indexedDB::AllocPBackgroundIndexedDBUtilsParent();
 }
 
 bool BackgroundParentImpl::DeallocPBackgroundIndexedDBUtilsParent(
     PBackgroundIndexedDBUtilsParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   return mozilla::dom::indexedDB::DeallocPBackgroundIndexedDBUtilsParent(
       aActor);
 }
 
 mozilla::ipc::IPCResult BackgroundParentImpl::RecvFlushPendingFileDeletions() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   if (!mozilla::dom::indexedDB::RecvFlushPendingFileDeletions()) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
 BackgroundParentImpl::PBackgroundSDBConnectionParent*
 BackgroundParentImpl::AllocPBackgroundSDBConnectionParent(
     const PrincipalInfo& aPrincipalInfo) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   return mozilla::dom::AllocPBackgroundSDBConnectionParent(aPrincipalInfo);
 }
 
 mozilla::ipc::IPCResult
 BackgroundParentImpl::RecvPBackgroundSDBConnectionConstructor(
     PBackgroundSDBConnectionParent* aActor,
     const PrincipalInfo& aPrincipalInfo) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   if (!mozilla::dom::RecvPBackgroundSDBConnectionConstructor(aActor,
                                                              aPrincipalInfo)) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
 bool BackgroundParentImpl::DeallocPBackgroundSDBConnectionParent(
     PBackgroundSDBConnectionParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   return mozilla::dom::DeallocPBackgroundSDBConnectionParent(aActor);
 }
 
 BackgroundParentImpl::PBackgroundLSDatabaseParent*
 BackgroundParentImpl::AllocPBackgroundLSDatabaseParent(
     const PrincipalInfo& aPrincipalInfo, const uint32_t& aPrivateBrowsingId,
     const uint64_t& aDatastoreId) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   return mozilla::dom::AllocPBackgroundLSDatabaseParent(
       aPrincipalInfo, aPrivateBrowsingId, aDatastoreId);
 }
 
 mozilla::ipc::IPCResult
 BackgroundParentImpl::RecvPBackgroundLSDatabaseConstructor(
     PBackgroundLSDatabaseParent* aActor, const PrincipalInfo& aPrincipalInfo,
     const uint32_t& aPrivateBrowsingId, const uint64_t& aDatastoreId) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   if (!mozilla::dom::RecvPBackgroundLSDatabaseConstructor(
           aActor, aPrincipalInfo, aPrivateBrowsingId, aDatastoreId)) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
 bool BackgroundParentImpl::DeallocPBackgroundLSDatabaseParent(
     PBackgroundLSDatabaseParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   return mozilla::dom::DeallocPBackgroundLSDatabaseParent(aActor);
 }
 
 BackgroundParentImpl::PBackgroundLSObserverParent*
 BackgroundParentImpl::AllocPBackgroundLSObserverParent(
     const uint64_t& aObserverId) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   return mozilla::dom::AllocPBackgroundLSObserverParent(aObserverId);
 }
 
 mozilla::ipc::IPCResult
 BackgroundParentImpl::RecvPBackgroundLSObserverConstructor(
     PBackgroundLSObserverParent* aActor, const uint64_t& aObserverId) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   if (!mozilla::dom::RecvPBackgroundLSObserverConstructor(aActor,
                                                           aObserverId)) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
 bool BackgroundParentImpl::DeallocPBackgroundLSObserverParent(
     PBackgroundLSObserverParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   return mozilla::dom::DeallocPBackgroundLSObserverParent(aActor);
 }
 
 BackgroundParentImpl::PBackgroundLSRequestParent*
 BackgroundParentImpl::AllocPBackgroundLSRequestParent(
     const LSRequestParams& aParams) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   return mozilla::dom::AllocPBackgroundLSRequestParent(this, aParams);
 }
 
 mozilla::ipc::IPCResult
 BackgroundParentImpl::RecvPBackgroundLSRequestConstructor(
     PBackgroundLSRequestParent* aActor, const LSRequestParams& aParams) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   if (!mozilla::dom::RecvPBackgroundLSRequestConstructor(aActor, aParams)) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
 bool BackgroundParentImpl::DeallocPBackgroundLSRequestParent(
     PBackgroundLSRequestParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   return mozilla::dom::DeallocPBackgroundLSRequestParent(aActor);
 }
 
 BackgroundParentImpl::PBackgroundLSSimpleRequestParent*
 BackgroundParentImpl::AllocPBackgroundLSSimpleRequestParent(
     const LSSimpleRequestParams& aParams) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   return mozilla::dom::AllocPBackgroundLSSimpleRequestParent(aParams);
 }
 
 mozilla::ipc::IPCResult
 BackgroundParentImpl::RecvPBackgroundLSSimpleRequestConstructor(
     PBackgroundLSSimpleRequestParent* aActor,
     const LSSimpleRequestParams& aParams) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   if (!mozilla::dom::RecvPBackgroundLSSimpleRequestConstructor(aActor,
                                                                aParams)) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
 bool BackgroundParentImpl::DeallocPBackgroundLSSimpleRequestParent(
     PBackgroundLSSimpleRequestParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   return mozilla::dom::DeallocPBackgroundLSSimpleRequestParent(aActor);
 }
 
 BackgroundParentImpl::PBackgroundLocalStorageCacheParent*
 BackgroundParentImpl::AllocPBackgroundLocalStorageCacheParent(
     const PrincipalInfo& aPrincipalInfo, const nsCString& aOriginKey,
     const uint32_t& aPrivateBrowsingId) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   return mozilla::dom::AllocPBackgroundLocalStorageCacheParent(
       aPrincipalInfo, aOriginKey, aPrivateBrowsingId);
 }
 
 mozilla::ipc::IPCResult
 BackgroundParentImpl::RecvPBackgroundLocalStorageCacheConstructor(
     PBackgroundLocalStorageCacheParent* aActor,
     const PrincipalInfo& aPrincipalInfo, const nsCString& aOriginKey,
     const uint32_t& aPrivateBrowsingId) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   return mozilla::dom::RecvPBackgroundLocalStorageCacheConstructor(
       this, aActor, aPrincipalInfo, aOriginKey, aPrivateBrowsingId);
 }
 
 bool BackgroundParentImpl::DeallocPBackgroundLocalStorageCacheParent(
     PBackgroundLocalStorageCacheParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   return mozilla::dom::DeallocPBackgroundLocalStorageCacheParent(aActor);
 }
 
 auto BackgroundParentImpl::AllocPBackgroundStorageParent(
     const nsString& aProfilePath) -> PBackgroundStorageParent* {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   return mozilla::dom::AllocPBackgroundStorageParent(aProfilePath);
 }
 
 mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBackgroundStorageConstructor(
     PBackgroundStorageParent* aActor, const nsString& aProfilePath) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   return mozilla::dom::RecvPBackgroundStorageConstructor(aActor, aProfilePath);
 }
 
 bool BackgroundParentImpl::DeallocPBackgroundStorageParent(
     PBackgroundStorageParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   return mozilla::dom::DeallocPBackgroundStorageParent(aActor);
 }
 
 PPendingIPCBlobParent* BackgroundParentImpl::AllocPPendingIPCBlobParent(
     const IPCBlob& aBlob) {
   MOZ_CRASH("PPendingIPCBlobParent actors should be manually constructed!");
 }
 
 bool BackgroundParentImpl::DeallocPPendingIPCBlobParent(
     PPendingIPCBlobParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   delete aActor;
   return true;
 }
 
 mozilla::dom::PRemoteWorkerParent*
@@ -540,17 +540,17 @@ mozilla::ipc::IPCResult BackgroundParent
 bool BackgroundParentImpl::DeallocPTemporaryIPCBlobParent(
     PTemporaryIPCBlobParent* aActor) {
   delete aActor;
   return true;
 }
 
 PIPCBlobInputStreamParent* BackgroundParentImpl::AllocPIPCBlobInputStreamParent(
     const nsID& aID, const uint64_t& aSize) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   RefPtr<mozilla::dom::IPCBlobInputStreamParent> actor =
       mozilla::dom::IPCBlobInputStreamParent::Create(aID, aSize, this);
   return actor.forget().take();
 }
 
 mozilla::ipc::IPCResult
@@ -561,36 +561,36 @@ BackgroundParentImpl::RecvPIPCBlobInputS
     return IPC_FAIL_NO_REASON(this);
   }
 
   return IPC_OK();
 }
 
 bool BackgroundParentImpl::DeallocPIPCBlobInputStreamParent(
     PIPCBlobInputStreamParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   RefPtr<mozilla::dom::IPCBlobInputStreamParent> actor =
       dont_AddRef(static_cast<mozilla::dom::IPCBlobInputStreamParent*>(aActor));
   return true;
 }
 
 PFileDescriptorSetParent* BackgroundParentImpl::AllocPFileDescriptorSetParent(
     const FileDescriptor& aFileDescriptor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   return new FileDescriptorSetParent(aFileDescriptor);
 }
 
 bool BackgroundParentImpl::DeallocPFileDescriptorSetParent(
     PFileDescriptorSetParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   delete static_cast<FileDescriptorSetParent*>(aActor);
   return true;
 }
 
 PChildToParentStreamParent*
@@ -612,53 +612,53 @@ BackgroundParentImpl::AllocPParentToChil
 
 bool BackgroundParentImpl::DeallocPParentToChildStreamParent(
     PParentToChildStreamParent* aActor) {
   delete aActor;
   return true;
 }
 
 BackgroundParentImpl::PVsyncParent* BackgroundParentImpl::AllocPVsyncParent() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   RefPtr<mozilla::layout::VsyncParent> actor =
       mozilla::layout::VsyncParent::Create();
   // There still has one ref-count after return, and it will be released in
   // DeallocPVsyncParent().
   return actor.forget().take();
 }
 
 bool BackgroundParentImpl::DeallocPVsyncParent(PVsyncParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   // This actor already has one ref-count. Please check AllocPVsyncParent().
   RefPtr<mozilla::layout::VsyncParent> actor =
       dont_AddRef(static_cast<mozilla::layout::VsyncParent*>(aActor));
   return true;
 }
 
 camera::PCamerasParent* BackgroundParentImpl::AllocPCamerasParent() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
 #ifdef MOZ_WEBRTC
   RefPtr<mozilla::camera::CamerasParent> actor =
       mozilla::camera::CamerasParent::Create();
   return actor.forget().take();
 #else
   return nullptr;
 #endif
 }
 
 bool BackgroundParentImpl::DeallocPCamerasParent(
     camera::PCamerasParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
 #ifdef MOZ_WEBRTC
   RefPtr<mozilla::camera::CamerasParent> actor =
       dont_AddRef(static_cast<mozilla::camera::CamerasParent*>(aActor));
 #endif
   return true;
@@ -670,17 +670,17 @@ auto BackgroundParentImpl::AllocPUDPSock
   RefPtr<UDPSocketParent> p = new UDPSocketParent(this);
 
   return p.forget().take();
 }
 
 mozilla::ipc::IPCResult BackgroundParentImpl::RecvPUDPSocketConstructor(
     PUDPSocketParent* aActor, const OptionalPrincipalInfo& aOptionalPrincipal,
     const nsCString& aFilter) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   if (aOptionalPrincipal.type() == OptionalPrincipalInfo::TPrincipalInfo) {
     // Support for checking principals (for non-mtransport use) will be handled
     // in bug 1167039
     return IPC_FAIL_NO_REASON(this);
   }
   // No principal - This must be from mtransport (WebRTC/ICE) - We'd want
@@ -708,17 +708,17 @@ bool BackgroundParentImpl::DeallocPUDPSo
   p->Release();
   return true;
 }
 
 mozilla::dom::PBroadcastChannelParent*
 BackgroundParentImpl::AllocPBroadcastChannelParent(
     const PrincipalInfo& aPrincipalInfo, const nsCString& aOrigin,
     const nsString& aChannel) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   nsString originChannelKey;
 
   // The format of originChannelKey is:
   //  <channelName>|<origin+OriginAttributes>
 
   originChannelKey.Assign(aChannel);
@@ -745,17 +745,17 @@ class CheckPrincipalRunnable final : pub
  public:
   CheckPrincipalRunnable(already_AddRefed<ContentParent> aParent,
                          const PrincipalInfo& aPrincipalInfo,
                          const nsCString& aOrigin)
       : Runnable("ipc::CheckPrincipalRunnable"),
         mContentParent(aParent),
         mPrincipalInfo(aPrincipalInfo),
         mOrigin(aOrigin) {
-    AssertIsInMainProcess();
+    AssertIsInMainOrSocketProcess();
     AssertIsOnBackgroundThread();
 
     MOZ_ASSERT(mContentParent);
   }
 
   NS_IMETHOD Run() override {
     MOZ_ASSERT(NS_IsMainThread());
 
@@ -786,17 +786,17 @@ class CheckPrincipalRunnable final : pub
   nsCString mOrigin;
 };
 
 }  // namespace
 
 mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBroadcastChannelConstructor(
     PBroadcastChannelParent* actor, const PrincipalInfo& aPrincipalInfo,
     const nsCString& aOrigin, const nsString& aChannel) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   RefPtr<ContentParent> parent = BackgroundParent::GetContentParent(this);
 
   // If the ContentParent is null we are dealing with a same-process actor.
   if (!parent) {
     return IPC_OK();
   }
@@ -805,49 +805,49 @@ mozilla::ipc::IPCResult BackgroundParent
       new CheckPrincipalRunnable(parent.forget(), aPrincipalInfo, aOrigin);
   MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
 
   return IPC_OK();
 }
 
 bool BackgroundParentImpl::DeallocPBroadcastChannelParent(
     PBroadcastChannelParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   delete static_cast<BroadcastChannelParent*>(aActor);
   return true;
 }
 
 mozilla::dom::PServiceWorkerManagerParent*
 BackgroundParentImpl::AllocPServiceWorkerManagerParent() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   RefPtr<dom::ServiceWorkerManagerParent> agent =
       new dom::ServiceWorkerManagerParent();
   return agent.forget().take();
 }
 
 bool BackgroundParentImpl::DeallocPServiceWorkerManagerParent(
     PServiceWorkerManagerParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   RefPtr<dom::ServiceWorkerManagerParent> parent =
       dont_AddRef(static_cast<dom::ServiceWorkerManagerParent*>(aActor));
   MOZ_ASSERT(parent);
   return true;
 }
 
 mozilla::ipc::IPCResult
 BackgroundParentImpl::RecvShutdownServiceWorkerRegistrar() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   if (BackgroundParent::IsOtherProcessActor(this)) {
     return IPC_FAIL_NO_REASON(this);
   }
 
   RefPtr<dom::ServiceWorkerRegistrar> service =
       dom::ServiceWorkerRegistrar::Get();
@@ -889,96 +889,96 @@ bool BackgroundParentImpl::DeallocPCache
     PCacheStreamControlParent* aActor) {
   dom::cache::DeallocPCacheStreamControlParent(aActor);
   return true;
 }
 
 PMessagePortParent* BackgroundParentImpl::AllocPMessagePortParent(
     const nsID& aUUID, const nsID& aDestinationUUID,
     const uint32_t& aSequenceID) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   return new MessagePortParent(aUUID);
 }
 
 mozilla::ipc::IPCResult BackgroundParentImpl::RecvPMessagePortConstructor(
     PMessagePortParent* aActor, const nsID& aUUID, const nsID& aDestinationUUID,
     const uint32_t& aSequenceID) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   MessagePortParent* mp = static_cast<MessagePortParent*>(aActor);
   if (!mp->Entangle(aDestinationUUID, aSequenceID)) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
 bool BackgroundParentImpl::DeallocPMessagePortParent(
     PMessagePortParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   delete static_cast<MessagePortParent*>(aActor);
   return true;
 }
 
 mozilla::ipc::IPCResult BackgroundParentImpl::RecvMessagePortForceClose(
     const nsID& aUUID, const nsID& aDestinationUUID,
     const uint32_t& aSequenceID) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   if (!MessagePortParent::ForceClose(aUUID, aDestinationUUID, aSequenceID)) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
 PAsmJSCacheEntryParent* BackgroundParentImpl::AllocPAsmJSCacheEntryParent(
     const dom::asmjscache::OpenMode& aOpenMode,
     const dom::asmjscache::WriteParams& aWriteParams,
     const PrincipalInfo& aPrincipalInfo) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   return dom::asmjscache::AllocEntryParent(aOpenMode, aWriteParams,
                                            aPrincipalInfo);
 }
 
 bool BackgroundParentImpl::DeallocPAsmJSCacheEntryParent(
     PAsmJSCacheEntryParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   dom::asmjscache::DeallocEntryParent(aActor);
   return true;
 }
 
 BackgroundParentImpl::PQuotaParent* BackgroundParentImpl::AllocPQuotaParent() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   return mozilla::dom::quota::AllocPQuotaParent();
 }
 
 bool BackgroundParentImpl::DeallocPQuotaParent(PQuotaParent* aActor) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   return mozilla::dom::quota::DeallocPQuotaParent(aActor);
 }
 
 dom::PFileSystemRequestParent*
 BackgroundParentImpl::AllocPFileSystemRequestParent(
     const FileSystemParams& aParams) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   RefPtr<FileSystemRequestParent> result = new FileSystemRequestParent();
 
   if (NS_WARN_IF(!result->Initialize(aParams))) {
     return nullptr;
   }
 
@@ -988,17 +988,17 @@ BackgroundParentImpl::AllocPFileSystemRe
 mozilla::ipc::IPCResult BackgroundParentImpl::RecvPFileSystemRequestConstructor(
     PFileSystemRequestParent* aActor, const FileSystemParams& params) {
   static_cast<FileSystemRequestParent*>(aActor)->Start();
   return IPC_OK();
 }
 
 bool BackgroundParentImpl::DeallocPFileSystemRequestParent(
     PFileSystemRequestParent* aDoomed) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   RefPtr<FileSystemRequestParent> parent =
       dont_AddRef(static_cast<FileSystemRequestParent*>(aDoomed));
   return true;
 }
 
 // Gamepad API Background IPC
@@ -1044,89 +1044,89 @@ bool BackgroundParentImpl::DeallocPWebAu
   MOZ_ASSERT(aActor);
   delete aActor;
   return true;
 }
 
 net::PHttpBackgroundChannelParent*
 BackgroundParentImpl::AllocPHttpBackgroundChannelParent(
     const uint64_t& aChannelId) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   RefPtr<net::HttpBackgroundChannelParent> actor =
       new net::HttpBackgroundChannelParent();
 
   // hold extra refcount for IPDL
   return actor.forget().take();
 }
 
 mozilla::ipc::IPCResult
 BackgroundParentImpl::RecvPHttpBackgroundChannelConstructor(
     net::PHttpBackgroundChannelParent* aActor, const uint64_t& aChannelId) {
   MOZ_ASSERT(aActor);
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   net::HttpBackgroundChannelParent* aParent =
       static_cast<net::HttpBackgroundChannelParent*>(aActor);
 
   if (NS_WARN_IF(NS_FAILED(aParent->Init(aChannelId)))) {
     return IPC_FAIL_NO_REASON(this);
   }
 
   return IPC_OK();
 }
 
 bool BackgroundParentImpl::DeallocPHttpBackgroundChannelParent(
     net::PHttpBackgroundChannelParent* aActor) {
   MOZ_ASSERT(aActor);
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   // release extra refcount hold by AllocPHttpBackgroundChannelParent
   RefPtr<net::HttpBackgroundChannelParent> actor =
       dont_AddRef(static_cast<net::HttpBackgroundChannelParent*>(aActor));
 
   return true;
 }
 
 PMIDIPortParent* BackgroundParentImpl::AllocPMIDIPortParent(
     const MIDIPortInfo& aPortInfo, const bool& aSysexEnabled) {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   RefPtr<MIDIPortParent> result = new MIDIPortParent(aPortInfo, aSysexEnabled);
   return result.forget().take();
 }
 
 bool BackgroundParentImpl::DeallocPMIDIPortParent(PMIDIPortParent* aActor) {
   MOZ_ASSERT(aActor);
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   RefPtr<MIDIPortParent> parent =
       dont_AddRef(static_cast<MIDIPortParent*>(aActor));
   parent->Teardown();
   return true;
 }
 
 PMIDIManagerParent* BackgroundParentImpl::AllocPMIDIManagerParent() {
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   RefPtr<MIDIManagerParent> result = new MIDIManagerParent();
   MIDIPlatformService::Get()->AddManager(result);
   return result.forget().take();
 }
 
 bool BackgroundParentImpl::DeallocPMIDIManagerParent(
     PMIDIManagerParent* aActor) {
   MOZ_ASSERT(aActor);
-  AssertIsInMainProcess();
+  AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 
   RefPtr<MIDIManagerParent> parent =
       dont_AddRef(static_cast<MIDIManagerParent*>(aActor));
   parent->Teardown();
   return true;
 }
 
@@ -1240,11 +1240,11 @@ mozilla::ipc::IPCResult BackgroundParent
 
   return IPC_OK();
 }
 
 }  // namespace ipc
 }  // namespace mozilla
 
 void TestParent::ActorDestroy(ActorDestroyReason aWhy) {
-  mozilla::ipc::AssertIsInMainProcess();
+  mozilla::ipc::AssertIsInMainOrSocketProcess();
   AssertIsOnBackgroundThread();
 }
--- a/netwerk/ipc/PSocketProcessBridge.ipdl
+++ b/netwerk/ipc/PSocketProcessBridge.ipdl
@@ -1,25 +1,30 @@
 /* -*- 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/. */
 
+include protocol PBackground;
+
 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
 {
+parent:
+  async InitBackground(Endpoint<PBackgroundParent> aEndpoint);
+
 both:
   async Test();
 };
 
 }
 }
--- a/netwerk/ipc/SocketProcessBridgeChild.cpp
+++ b/netwerk/ipc/SocketProcessBridgeChild.cpp
@@ -30,17 +30,17 @@ bool SocketProcessBridgeChild::Create(
   }
 
   sSocketProcessBridgeChild = nullptr;
   return false;
 }
 
 // static
 already_AddRefed<SocketProcessBridgeChild>
-SocketProcessBridgeChild::GetSinglton() {
+SocketProcessBridgeChild::GetSingleton() {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!sSocketProcessBridgeChild) {
     return nullptr;
   }
 
   RefPtr<SocketProcessBridgeChild> child = sSocketProcessBridgeChild.get();
   return child.forget();
@@ -74,29 +74,32 @@ void SocketProcessBridgeChild::EnsureSoc
         }
         onFailure();
       },
       [onFailure = std::move(aOnFailure)](
           const mozilla::ipc::ResponseRejectReason) { onFailure(); });
 }
 
 SocketProcessBridgeChild::SocketProcessBridgeChild(
-    Endpoint<PSocketProcessBridgeChild>&& aEndpoint) {
+    Endpoint<PSocketProcessBridgeChild>&& aEndpoint)
+    : mShuttingDown(false) {
   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);
   }
+
+  mSocketProcessPid = aEndpoint.OtherPid();
 }
 
 SocketProcessBridgeChild::~SocketProcessBridgeChild() {
   LOG(("DESTRUCT SocketProcessBridgeChild::SocketProcessBridgeChild\n"));
 }
 
 mozilla::ipc::IPCResult SocketProcessBridgeChild::RecvTest() {
   LOG(("SocketProcessBridgeChild::RecvTest\n"));
@@ -107,16 +110,17 @@ void SocketProcessBridgeChild::ActorDest
   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));
+  mShuttingDown = true;
 }
 
 NS_IMETHODIMP
 SocketProcessBridgeChild::Observe(nsISupports* aSubject, const char* aTopic,
                                   const char16_t* aData) {
   if (!strcmp(aTopic, "content-child-shutdown")) {
     PSocketProcessBridgeChild::Close();
   }
--- a/netwerk/ipc/SocketProcessBridgeChild.h
+++ b/netwerk/ipc/SocketProcessBridgeChild.h
@@ -18,31 +18,35 @@ namespace net {
 // 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 already_AddRefed<SocketProcessBridgeChild> GetSingleton();
   static void EnsureSocketProcessBridge(std::function<void()>&& aOnSuccess,
                                         std::function<void()>&& aOnFailure);
 
   mozilla::ipc::IPCResult RecvTest() override;
   void ActorDestroy(ActorDestroyReason aWhy) override;
   void DeferredDestroy();
+  bool IsShuttingDown() const { return mShuttingDown; };
   bool Inited() const { return mInited; };
+  ProcessId SocketProcessPid() const { return mSocketProcessPid; };
 
  private:
   DISALLOW_COPY_AND_ASSIGN(SocketProcessBridgeChild);
   explicit SocketProcessBridgeChild(
       Endpoint<PSocketProcessBridgeChild>&& aEndpoint);
   virtual ~SocketProcessBridgeChild();
 
   static StaticRefPtr<SocketProcessBridgeChild> sSocketProcessBridgeChild;
+  bool mShuttingDown;
   bool mInited = false;
+  ProcessId mSocketProcessPid;
 };
 
 }  // namespace net
 }  // namespace mozilla
 
 #endif  // mozilla_net_SocketProcessBridgeChild_h
--- a/netwerk/ipc/SocketProcessBridgeParent.cpp
+++ b/netwerk/ipc/SocketProcessBridgeParent.cpp
@@ -1,16 +1,17 @@
 /* -*- 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 "mozilla/ipc/BackgroundParent.h"
 #include "SocketProcessChild.h"
 
 namespace mozilla {
 namespace net {
 
 SocketProcessBridgeParent::SocketProcessBridgeParent(
     ProcessId aId, Endpoint<PSocketProcessBridgeParent>&& aEndpoint)
     : mId(aId) {
@@ -28,16 +29,26 @@ SocketProcessBridgeParent::~SocketProces
 }
 
 mozilla::ipc::IPCResult SocketProcessBridgeParent::RecvTest() {
   LOG(("SocketProcessBridgeParent::RecvTest\n"));
   Unused << SendTest();
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult SocketProcessBridgeParent::RecvInitBackground(
+    Endpoint<PBackgroundParent>&& aEndpoint) {
+  LOG(("SocketProcessBridgeParent::RecvInitBackground mId=%d\n", mId));
+  if (!ipc::BackgroundParent::Alloc(nullptr, std::move(aEndpoint))) {
+    return IPC_FAIL(this, "BackgroundParent::Alloc failed");
+  }
+
+  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));
 }
 
--- a/netwerk/ipc/SocketProcessBridgeParent.h
+++ b/netwerk/ipc/SocketProcessBridgeParent.h
@@ -18,16 +18,19 @@ namespace net {
 class SocketProcessBridgeParent final : public PSocketProcessBridgeParent {
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SocketProcessBridgeParent)
 
   explicit SocketProcessBridgeParent(
       ProcessId aId, Endpoint<PSocketProcessBridgeParent>&& aEndpoint);
 
   mozilla::ipc::IPCResult RecvTest() override;
+  mozilla::ipc::IPCResult RecvInitBackground(
+      Endpoint<PBackgroundParent>&& aEndpoint) override;
+
   void ActorDestroy(ActorDestroyReason aWhy) override;
   void DeferredDestroy();
 
  private:
   ~SocketProcessBridgeParent();
 
   ProcessId mId;
 };