Bug 1438945 - Part 8: RemoteWorker IPC. r=asuth
authorAndrea Marchesini <amarchesini@mozilla.com>
Mon, 19 Nov 2018 15:18:32 -0800
changeset 503570 6059af9c85adc62a51d9b38b9cdcba3904d4d824
parent 503569 a38f567faf3faedcc609ced953aefa09d73e0fd6
child 503571 b3d9a379c852669a1fa005148bee537b99c91c6f
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1438945
milestone65.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 1438945 - Part 8: RemoteWorker IPC. r=asuth
dom/ipc/ContentChild.cpp
dom/workers/moz.build
dom/workers/remoteworkers/PRemoteWorker.ipdl
dom/workers/remoteworkers/PRemoteWorkerService.ipdl
dom/workers/remoteworkers/RemoteWorkerChild.cpp
dom/workers/remoteworkers/RemoteWorkerChild.h
dom/workers/remoteworkers/RemoteWorkerController.cpp
dom/workers/remoteworkers/RemoteWorkerController.h
dom/workers/remoteworkers/RemoteWorkerManager.cpp
dom/workers/remoteworkers/RemoteWorkerManager.h
dom/workers/remoteworkers/RemoteWorkerParent.cpp
dom/workers/remoteworkers/RemoteWorkerParent.h
dom/workers/remoteworkers/RemoteWorkerService.cpp
dom/workers/remoteworkers/RemoteWorkerService.h
dom/workers/remoteworkers/RemoteWorkerServiceChild.cpp
dom/workers/remoteworkers/RemoteWorkerServiceChild.h
dom/workers/remoteworkers/RemoteWorkerServiceParent.cpp
dom/workers/remoteworkers/RemoteWorkerServiceParent.h
dom/workers/remoteworkers/RemoteWorkerTypes.ipdlh
dom/workers/remoteworkers/moz.build
ipc/glue/BackgroundChildImpl.cpp
ipc/glue/BackgroundChildImpl.h
ipc/glue/BackgroundParentImpl.cpp
ipc/glue/BackgroundParentImpl.h
ipc/glue/PBackground.ipdl
layout/build/nsLayoutStatics.cpp
layout/ipc/PVsync.ipdl
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -39,16 +39,17 @@
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/ExternalHelperAppChild.h"
 #include "mozilla/dom/FileCreatorHelper.h"
 #include "mozilla/dom/GetFilesHelper.h"
 #include "mozilla/dom/IPCBlobUtils.h"
 #include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/dom/PLoginReputationChild.h"
 #include "mozilla/dom/PushNotifier.h"
+#include "mozilla/dom/RemoteWorkerService.h"
 #include "mozilla/dom/ServiceWorkerManager.h"
 #include "mozilla/dom/TabGroup.h"
 #include "mozilla/dom/nsIContentChild.h"
 #include "mozilla/dom/URLClassifierChild.h"
 #include "mozilla/dom/WorkerDebugger.h"
 #include "mozilla/dom/WorkerDebuggerManager.h"
 #include "mozilla/dom/ipc/SharedMap.h"
 #include "mozilla/gfx/gfxVars.h"
@@ -1220,16 +1221,18 @@ ContentChild::InitXPCOM(const XPCOMInitD
   PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread();
   if (NS_WARN_IF(!actorChild)) {
     MOZ_ASSERT_UNREACHABLE("PBackground init can't fail at this point");
     return;
   }
 
   ClientManager::Startup();
 
+  RemoteWorkerService::Initialize();
+
   nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
   if (!svc) {
     NS_WARNING("Couldn't acquire console service");
     return;
   }
 
   mConsoleListener = new ConsoleListener(this);
   if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
--- a/dom/workers/moz.build
+++ b/dom/workers/moz.build
@@ -2,17 +2,17 @@
 # vim: set filetype=python:
 # 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/.
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "DOM: Workers")
 
-DIRS += ['sharedworkers']
+DIRS += ['remoteworkers', 'sharedworkers']
 
 # Public stuff.
 EXPORTS.mozilla.dom += [
     'ChromeWorker.h',
     'Worker.h',
     'WorkerCommon.h',
     'WorkerDebugger.h',
     'WorkerDebuggerManager.h',
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/PRemoteWorker.ipdl
@@ -0,0 +1,24 @@
+/* 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 dom {
+
+// This protocol is used to make a remote worker controllable from the parent
+// process. The parent process will receive operations from the
+// PRemoteWorkerController protocol.
+protocol PRemoteWorker
+{
+  manager PBackground;
+
+parent:
+  async __delete__();
+
+  async Created(bool aStatus);
+};
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/PRemoteWorkerService.ipdl
@@ -0,0 +1,24 @@
+/* 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;
+
+include ProtocolTypes;
+include RemoteWorkerTypes;
+
+namespace mozilla {
+namespace dom {
+
+// Simple protocol to register any active RemoteWorkerService running on any
+// process.
+protocol PRemoteWorkerService
+{
+  manager PBackground;
+
+parent:
+  async __delete__();
+};
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/RemoteWorkerChild.cpp
@@ -0,0 +1,18 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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 "RemoteWorkerChild.h"
+
+namespace mozilla {
+namespace dom {
+
+RemoteWorkerChild::RemoteWorkerChild()
+{}
+
+RemoteWorkerChild::~RemoteWorkerChild() = default;
+
+} // dom namespace
+} // mozilla namespace
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/RemoteWorkerChild.h
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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/. */
+
+#ifndef mozilla_dom_RemoteWorkerChild_h
+#define mozilla_dom_RemoteWorkerChild_h
+
+#include "mozilla/dom/PRemoteWorkerChild.h"
+
+namespace mozilla {
+namespace dom {
+
+class RemoteWorkerChild final : public PRemoteWorkerChild
+{
+public:
+  RemoteWorkerChild();
+  ~RemoteWorkerChild();
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_RemoteWorkerChild_h
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/RemoteWorkerController.cpp
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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 "mozilla/ipc/BackgroundParent.h"
+#include "RemoteWorkerController.h"
+#include "RemoteWorkerManager.h"
+
+namespace mozilla {
+
+using namespace ipc;
+
+namespace dom {
+
+/* static */ already_AddRefed<RemoteWorkerController>
+RemoteWorkerController::Create()
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+
+  RefPtr<RemoteWorkerController> controller = new RemoteWorkerController();
+
+  // This will be populated, eventually.
+  RemoteWorkerData data;
+
+  RefPtr<RemoteWorkerManager> manager = RemoteWorkerManager::GetOrCreate();
+  MOZ_ASSERT(manager);
+
+  manager->Launch(controller, data);
+
+  return controller.forget();
+}
+
+RemoteWorkerController::RemoteWorkerController()
+  : mState(ePending)
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+}
+
+RemoteWorkerController::~RemoteWorkerController()
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+}
+
+void
+RemoteWorkerController::SetWorkerActor(RemoteWorkerParent* aActor)
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(!mActor);
+  MOZ_ASSERT(aActor);
+
+  mActor = aActor;
+}
+
+void
+RemoteWorkerController::CreationFailed()
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(mActor);
+
+  mState = eTerminated;
+  mActor = nullptr;
+}
+
+void
+RemoteWorkerController::CreationSucceeded()
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(mActor);
+
+  mState = eReady;
+
+  // TODO: flush the pending op queue.
+}
+
+} // dom namespace
+} // mozilla namespace
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/RemoteWorkerController.h
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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/. */
+
+#ifndef mozilla_dom_RemoteWorkerController_h
+#define mozilla_dom_RemoteWorkerController_h
+
+#include "nsISupportsImpl.h"
+
+namespace mozilla {
+namespace dom {
+
+/* Here a graph about this remote workers are spawn.
+ *
+ *  _________________________________    |   ________________________________
+ * |                                 |   |  |                                |
+ * |              Parent process     |  IPC |           Creation ofProcess X |
+ * |              PBackground thread |   |  |                                |
+ * |                                 |   |  | [RemoteWorkerService::Init()]  |
+ * |                                 |   |  |               |                |
+ * |                                 |   |  |               | (1)            |
+ * | [RemoteWorkerManager::  (2)     |   |  |               V                |
+ * |                RegisterActor()]<-------- [new RemoteWorkerServiceChild] |
+ * |                                 |   |  |                                |
+ * |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~   |   |  |________________________________|
+ * |                                 |   |
+ * |  new SharedWorker/ServiceWorker |   |
+ * |      |     ^                    |  IPC
+ * |  (3) |  (4)|                    |
+ * |      V     |                    |   |
+ * | [RemoteWorkerController::       |   |
+ * |         |         Create(data)] |   |
+ * |         | (5)                   |   |
+ * |         V                       |   |
+ * | [RemoteWorkerManager::Launch()] |   |
+ * |         |                       |  IPC   _____________________________
+ * |         | (6)                   |   |   |                             |
+ * |         |                       |       | Selected content process    |
+ * |         V                       |  (7)  |                             |
+ * | [SendPRemoteWorkerConstructor()]--------->[new RemoteWorkerChild()]   |
+ * |         |                       |   |   |             |               |
+ * |         | (8)                   |   |   |             |               |
+ * |         V                       |   |   |             V               |
+ * | [RemoteWorkerController->       |   |   | RemoteWorkerChild->Exec()   |
+ * |         | SetControllerActor()] |   |   |_____________________________|
+ * |     (9) |                       |  IPC
+ * |         V                       |   |
+ * | [RemoteWorkerObserver->         |   |
+ * |           CreationCompleted()]  |   |
+ * |_________________________________|   |
+ *                                       |
+ *
+ * 1. When a new process starts, it creates a RemoteWorkerService singleton.
+ *    This service creates a new thread (Worker Launcher) and from there, it
+ *    starts a PBackground RemoteWorkerServiceChild actor.
+ * 2. On the parent process, PBackground thread, RemoteWorkerServiceParent
+ *    actors are registered into the RemoteWorkerManager service.
+ *
+ * 3. At some point, a SharedWorker or a ServiceWorker must be executed.
+ *    RemoteWorkerController::Create() is used to start the launching. This
+ *    method must be called on the parent process, on the PBackground thread.
+ * 4. RemoteWorkerController object is immediately returned to the caller. Any
+ *    operation done with this controller object will be stored in a queue,
+ *    until the launching is correctly executed.
+ * 5. RemoteWorkerManager has the list of active RemoteWorkerServiceParent
+ *    actors. From them, it picks one.
+ *    In case we don't have any content process to select, a new one is
+ *    spawn. If this happen, the operation is suspended until a new
+ *    RemoteWorkerServiceParent is registered.
+ * 6. RemoteWorkerServiceParent is used to create a RemoteWorkerParent.
+ * 7. RemoteWorkerChild is created on a selected process and it executes the
+ *    WorkerPrivate.
+ * 8. The RemoteWorkerParent actor is passed to the RemoteWorkerController.
+ * 9. RemoteWorkerController now is ready to continue and it called
+ *    RemoteWorkerObserver to inform that the operation is completed.
+ *    In case there were pending operations, they are now executed.
+ */
+
+class RemoteWorkerManager;
+class RemoteWorkerParent;
+
+class RemoteWorkerController final
+{
+  friend class RemoteWorkerManager;
+  friend class RemoteWorkerParent;
+
+public:
+  NS_INLINE_DECL_REFCOUNTING(RemoteWorkerController)
+
+  static already_AddRefed<RemoteWorkerController>
+  Create(); // TODO parameters?
+
+private:
+  RemoteWorkerController();
+  ~RemoteWorkerController();
+
+  void
+  SetWorkerActor(RemoteWorkerParent* aActor);
+
+  void
+  CreationFailed();
+
+  void
+  CreationSucceeded();
+
+  enum {
+    ePending,
+    eReady,
+    eTerminated,
+  } mState;
+
+  RefPtr<RemoteWorkerParent> mActor;
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_RemoteWorkerController_h
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/RemoteWorkerManager.cpp
@@ -0,0 +1,179 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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 "RemoteWorkerManager.h"
+
+#include "mozilla/dom/RemoteWorkerParent.h"
+#include "mozilla/ipc/BackgroundParent.h"
+#include "mozilla/ipc/PBackgroundParent.h"
+#include "RemoteWorkerServiceParent.h"
+
+namespace mozilla {
+
+using namespace ipc;
+
+namespace dom {
+
+namespace {
+
+// Raw pointer because this object is kept alive by RemoteWorkerServiceParent
+// actors.
+RemoteWorkerManager* sRemoteWorkerManager;
+
+} // anonymous
+
+/* static */ already_AddRefed<RemoteWorkerManager>
+RemoteWorkerManager::GetOrCreate()
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+
+  if (!sRemoteWorkerManager) {
+    sRemoteWorkerManager = new RemoteWorkerManager();
+  }
+
+  RefPtr<RemoteWorkerManager> rwm = sRemoteWorkerManager;
+  return rwm.forget();
+}
+
+RemoteWorkerManager::RemoteWorkerManager()
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(!sRemoteWorkerManager);
+}
+
+RemoteWorkerManager::~RemoteWorkerManager()
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(sRemoteWorkerManager == this);
+  sRemoteWorkerManager = nullptr;
+}
+
+void
+RemoteWorkerManager::RegisterActor(RemoteWorkerServiceParent* aActor)
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(aActor);
+  MOZ_ASSERT(!mActors.Contains(aActor));
+
+  mActors.AppendElement(aActor);
+
+  if (!mPendings.IsEmpty()) {
+    // Flush pending launching.
+    for (const Pending& p : mPendings) {
+      LaunchInternal(p.mController, aActor, p.mData);
+    }
+
+    mPendings.Clear();
+
+    // We don't need to keep this manager alive manually. The Actor is doing it
+    // for us.
+    Release();
+  }
+}
+
+void
+RemoteWorkerManager::UnregisterActor(RemoteWorkerServiceParent* aActor)
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(aActor);
+  MOZ_ASSERT(mActors.Contains(aActor));
+
+  mActors.RemoveElement(aActor);
+}
+
+void
+RemoteWorkerManager::Launch(RemoteWorkerController* aController,
+                            const RemoteWorkerData& aData)
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+
+  RemoteWorkerServiceParent* targetActor = SelectTargetActor();
+
+  // If there is not an available actor, let's store the data, and let's spawn a
+  // new process.
+  if (!targetActor) {
+    // If this is the first time we have a pending launching, we must keep alive
+    // the manager.
+    if (mPendings.IsEmpty()) {
+      AddRef();
+    }
+
+    Pending* pending = mPendings.AppendElement();
+    pending->mController = aController;
+    pending->mData = aData;
+
+    LaunchNewContentProcess();
+    return;
+  }
+
+  LaunchInternal(aController, targetActor, aData);
+}
+
+void
+RemoteWorkerManager::LaunchInternal(RemoteWorkerController* aController,
+                                    RemoteWorkerServiceParent* aTargetActor,
+                                    const RemoteWorkerData& aData)
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(aController);
+  MOZ_ASSERT(aTargetActor);
+  MOZ_ASSERT(mActors.Contains(aTargetActor));
+
+  RemoteWorkerParent* workerActor =
+    static_cast<RemoteWorkerParent*>(
+      aTargetActor->Manager()->SendPRemoteWorkerConstructor(aData));
+  if (NS_WARN_IF(!workerActor)) {
+    AsyncCreationFailed(aController);
+    return;
+  }
+
+  // This makes the link better the 2 actors.
+  aController->SetWorkerActor(workerActor);
+  workerActor->SetController(aController);
+}
+
+void
+RemoteWorkerManager::AsyncCreationFailed(RemoteWorkerController* aController)
+{
+  RefPtr<RemoteWorkerController> controller = aController;
+  nsCOMPtr<nsIRunnable> r =
+    NS_NewRunnableFunction("RemoteWorkerManager::AsyncCreationFailed",
+                           [controller]() {
+      controller->CreationFailed();
+  });
+
+  NS_DispatchToCurrentThread(r.forget());
+}
+
+RemoteWorkerServiceParent*
+RemoteWorkerManager::SelectTargetActor()
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+
+  // TODO
+
+  return nullptr;
+}
+
+void
+RemoteWorkerManager::LaunchNewContentProcess()
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+
+  // TODO: exec a new process
+}
+
+} // dom namespace
+} // mozilla namespace
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/RemoteWorkerManager.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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/. */
+
+#ifndef mozilla_dom_RemoteWorkerManager_h
+#define mozilla_dom_RemoteWorkerManager_h
+
+#include "mozilla/dom/RemoteWorkerTypes.h"
+#include "nsISupportsImpl.h"
+#include "nsTArray.h"
+
+namespace mozilla {
+namespace dom {
+
+class RemoteWorkerController;
+class RemoteWorkerServiceParent;
+
+// This class is used on PBackground thread, on the parent process only.
+class RemoteWorkerManager final
+{
+public:
+  NS_INLINE_DECL_REFCOUNTING(RemoteWorkerManager)
+
+  static already_AddRefed<RemoteWorkerManager>
+  GetOrCreate();
+
+  void
+  RegisterActor(RemoteWorkerServiceParent* aActor);
+
+  void
+  UnregisterActor(RemoteWorkerServiceParent* aActor);
+
+  void
+  Launch(RemoteWorkerController* aController,
+         const RemoteWorkerData& aData);
+
+private:
+  RemoteWorkerManager();
+  ~RemoteWorkerManager();
+
+  RemoteWorkerServiceParent*
+  SelectTargetActor();
+
+  void
+  LaunchInternal(RemoteWorkerController* aController,
+                 RemoteWorkerServiceParent* aTargetActor,
+                 const RemoteWorkerData& aData);
+
+  void
+  LaunchNewContentProcess();
+
+  void
+  AsyncCreationFailed(RemoteWorkerController* aController);
+
+  // Raw pointers because RemoteWorkerServiceParent actors unregister themselves
+  // when destroyed.
+  nsTArray<RemoteWorkerServiceParent*> mActors;
+
+  struct Pending {
+    RefPtr<RemoteWorkerController> mController;
+    RemoteWorkerData mData;
+  };
+
+  nsTArray<Pending> mPendings;
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_RemoteWorkerManager_h
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/RemoteWorkerParent.cpp
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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 "RemoteWorkerParent.h"
+#include "RemoteWorkerController.h"
+#include "mozilla/ipc/BackgroundParent.h"
+
+namespace mozilla {
+
+using namespace ipc;
+
+namespace dom {
+
+RemoteWorkerParent::RemoteWorkerParent()
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+}
+
+RemoteWorkerParent::~RemoteWorkerParent()
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+}
+
+void
+RemoteWorkerParent::ActorDestroy(IProtocol::ActorDestroyReason)
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+
+  mController = nullptr;
+}
+
+IPCResult
+RemoteWorkerParent::RecvCreated(const bool& aStatus)
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+
+  if (!mController) {
+    return IPC_OK();
+  }
+
+  if (aStatus) {
+    mController->CreationSucceeded();
+  } else {
+    mController->CreationFailed();
+  }
+
+  return IPC_OK();
+}
+
+void
+RemoteWorkerParent::SetController(RemoteWorkerController* aController)
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(XRE_IsParentProcess());
+
+  mController = aController;
+}
+
+} // dom namespace
+} // mozilla namespace
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/RemoteWorkerParent.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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/. */
+
+#ifndef mozilla_dom_RemoteWorkerParent_h
+#define mozilla_dom_RemoteWorkerParent_h
+
+#include "mozilla/dom/PRemoteWorkerParent.h"
+
+namespace mozilla {
+namespace dom {
+
+class RemoteWorkerController;
+
+class RemoteWorkerParent final : public PRemoteWorkerParent
+{
+public:
+  NS_INLINE_DECL_REFCOUNTING(RemoteWorkerParent)
+
+  RemoteWorkerParent();
+
+  void
+  SetController(RemoteWorkerController* aController);
+
+private:
+  ~RemoteWorkerParent();
+
+  void
+  ActorDestroy(mozilla::ipc::IProtocol::ActorDestroyReason) override;
+
+  mozilla::ipc::IPCResult
+  RecvCreated(const bool& aStatus) override;
+
+  RefPtr<RemoteWorkerController> mController;
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_RemoteWorkerParent_h
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/RemoteWorkerService.cpp
@@ -0,0 +1,203 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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 "RemoteWorkerService.h"
+
+#include "mozilla/dom/PRemoteWorkerParent.h"
+#include "mozilla/ipc/BackgroundChild.h"
+#include "mozilla/ipc/BackgroundParent.h"
+#include "mozilla/ipc/PBackgroundChild.h"
+#include "mozilla/ipc/PBackgroundParent.h"
+#include "mozilla/Services.h"
+#include "mozilla/StaticMutex.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/SystemGroup.h"
+#include "nsIObserverService.h"
+#include "nsIThread.h"
+#include "nsThreadUtils.h"
+#include "nsXPCOMPrivate.h"
+#include "RemoteWorkerController.h"
+#include "RemoteWorkerServiceChild.h"
+#include "RemoteWorkerServiceParent.h"
+
+namespace mozilla {
+
+using namespace ipc;
+
+namespace dom {
+
+namespace {
+
+StaticMutex sRemoteWorkerServiceMutex;
+StaticRefPtr<RemoteWorkerService> sRemoteWorkerService;
+
+} // anonymous
+
+/* static */ void
+RemoteWorkerService::Initialize()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  StaticMutexAutoLock lock(sRemoteWorkerServiceMutex);
+  MOZ_ASSERT(!sRemoteWorkerService);
+
+  RefPtr<RemoteWorkerService> service = new RemoteWorkerService();
+
+  if (!XRE_IsParentProcess()) {
+    nsresult rv = service->InitializeOnMainThread();
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return;
+    }
+
+    sRemoteWorkerService = service;
+    return;
+  }
+
+  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+  if (NS_WARN_IF(!obs)) {
+    return;
+  }
+
+  nsresult rv = obs->AddObserver(service, "profile-after-change", false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return;
+  }
+
+  sRemoteWorkerService = service;
+}
+
+nsresult
+RemoteWorkerService::InitializeOnMainThread()
+{
+  // I would like to call this thread "DOM Remote Worker Launcher", but the max
+  // length is 16 chars.
+  nsresult rv = NS_NewNamedThread("Worker Launcher",
+                                  getter_AddRefs(mThread));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+  if (NS_WARN_IF(!obs)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  rv = obs->AddObserver(this,
+                        NS_XPCOM_SHUTDOWN_OBSERVER_ID,
+                        false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  RefPtr<RemoteWorkerService> self = this;
+  nsCOMPtr<nsIRunnable> r =
+    NS_NewRunnableFunction("InitializeThread", [self] () {
+    self->InitializeOnTargetThread();
+  });
+
+  rv = mThread->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+RemoteWorkerService::RemoteWorkerService()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
+RemoteWorkerService::~RemoteWorkerService() = default;
+
+void
+RemoteWorkerService::InitializeOnTargetThread()
+{
+  MOZ_ASSERT(mThread);
+  MOZ_ASSERT(mThread->IsOnCurrentThread());
+
+  PBackgroundChild* actorChild =
+  BackgroundChild::GetOrCreateForCurrentThread();
+  if (NS_WARN_IF(!actorChild)) {
+    return;
+  }
+
+  RemoteWorkerServiceChild* actor =
+    static_cast<RemoteWorkerServiceChild*>(
+      actorChild->SendPRemoteWorkerServiceConstructor());
+  if (NS_WARN_IF(!actor)) {
+    return;
+  }
+
+  // Now we are ready!
+  mActor = actor;
+}
+
+void
+RemoteWorkerService::ShutdownOnTargetThread()
+{
+  MOZ_ASSERT(mThread);
+  MOZ_ASSERT(mThread->IsOnCurrentThread());
+  MOZ_ASSERT(mActor);
+
+  // Here we need to shutdown the IPC protocol.
+  mActor->Send__delete__(mActor);
+  mActor = nullptr;
+
+  // Then we can terminate the thread on the main-thread.
+  RefPtr<RemoteWorkerService> self = this;
+  nsCOMPtr<nsIRunnable> r =
+    NS_NewRunnableFunction("ShutdownOnMainThread", [self] () {
+    self->mThread->Shutdown();
+    self->mThread = nullptr;
+  });
+
+  nsCOMPtr<nsIEventTarget> target =
+    SystemGroup::EventTargetFor(TaskCategory::Other);
+  target->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
+}
+
+NS_IMETHODIMP
+RemoteWorkerService::Observe(nsISupports* aSubject,
+                             const char* aTopic,
+                             const char16_t* aData)
+{
+  if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
+    MOZ_ASSERT(mThread);
+
+    nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+    if (obs) {
+      obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
+    }
+
+    RefPtr<RemoteWorkerService> self = this;
+    nsCOMPtr<nsIRunnable> r =
+      NS_NewRunnableFunction("ShutdownThread", [self] () {
+      self->ShutdownOnTargetThread();
+    });
+
+    mThread->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
+
+    StaticMutexAutoLock lock(sRemoteWorkerServiceMutex);
+    sRemoteWorkerService = nullptr;
+    return NS_OK;
+  }
+
+  MOZ_ASSERT(!strcmp(aTopic, "profile-after-change"));
+  MOZ_ASSERT(XRE_IsParentProcess());
+
+  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+  if (obs) {
+    obs->RemoveObserver(this, "profile-after-change");
+  }
+
+  return InitializeOnMainThread();
+}
+
+NS_IMPL_ISUPPORTS(RemoteWorkerService, nsIObserver)
+
+} // dom namespace
+} // mozilla namespace
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/RemoteWorkerService.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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/. */
+
+#ifndef mozilla_dom_RemoteWorkerService_h
+#define mozilla_dom_RemoteWorkerService_h
+
+#include "nsCOMPtr.h"
+#include "nsIObserver.h"
+
+class nsIThread;
+
+namespace mozilla {
+namespace dom {
+
+class RemoteWorkerServiceChild;
+
+class RemoteWorkerService final : public nsIObserver
+{
+public:
+  NS_DECL_THREADSAFE_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+
+  // To be called when a process is initialized on main-thread.
+  static void
+  Initialize();
+
+private:
+  RemoteWorkerService();
+  ~RemoteWorkerService();
+
+  nsresult
+  InitializeOnMainThread();
+
+  void
+  InitializeOnTargetThread();
+
+  void
+  ShutdownOnTargetThread();
+
+  nsCOMPtr<nsIThread> mThread;
+  RefPtr<RemoteWorkerServiceChild> mActor;
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_RemoteWorkerService_h
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/RemoteWorkerServiceChild.cpp
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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 "RemoteWorkerServiceChild.h"
+#include "RemoteWorkerController.h"
+
+namespace mozilla {
+namespace dom {
+
+RemoteWorkerServiceChild::RemoteWorkerServiceChild()
+{}
+
+RemoteWorkerServiceChild::~RemoteWorkerServiceChild() = default;
+
+} // dom namespace
+} // mozilla namespace
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/RemoteWorkerServiceChild.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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/. */
+
+#ifndef mozilla_dom_RemoteWorkerServiceChild_h
+#define mozilla_dom_RemoteWorkerServiceChild_h
+
+#include "mozilla/dom/PRemoteWorkerServiceChild.h"
+#include "nsISupportsImpl.h"
+
+namespace mozilla {
+namespace dom {
+
+class RemoteWorkerController;
+class RemoteWorkerData;
+
+class RemoteWorkerServiceChild final : public PRemoteWorkerServiceChild
+{
+public:
+  NS_INLINE_DECL_REFCOUNTING(RemoteWorkerServiceChild)
+
+  RemoteWorkerServiceChild();
+
+private:
+  ~RemoteWorkerServiceChild();
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_RemoteWorkerServiceChild_h
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/RemoteWorkerServiceParent.cpp
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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 "RemoteWorkerServiceParent.h"
+#include "RemoteWorkerManager.h"
+
+namespace mozilla {
+
+using namespace ipc;
+
+namespace dom {
+
+RemoteWorkerServiceParent::RemoteWorkerServiceParent()
+  : mManager(RemoteWorkerManager::GetOrCreate())
+{}
+
+RemoteWorkerServiceParent::~RemoteWorkerServiceParent()
+{}
+
+void
+RemoteWorkerServiceParent::Initialize()
+{
+  AssertIsOnBackgroundThread();
+  mManager->RegisterActor(this);
+}
+
+void
+RemoteWorkerServiceParent::ActorDestroy(IProtocol::ActorDestroyReason)
+{
+  AssertIsOnBackgroundThread();
+  mManager->UnregisterActor(this);
+}
+
+} // dom namespace
+} // mozilla namespace
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/RemoteWorkerServiceParent.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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/. */
+
+#ifndef mozilla_dom_RemoteWorkerServiceParent_h
+#define mozilla_dom_RemoteWorkerServiceParent_h
+
+#include "mozilla/dom/PRemoteWorkerServiceParent.h"
+
+namespace mozilla {
+namespace dom {
+
+class RemoteWorkerManager;
+
+class RemoteWorkerServiceParent final : public PRemoteWorkerServiceParent
+{
+public:
+  RemoteWorkerServiceParent();
+  ~RemoteWorkerServiceParent();
+
+  void
+  ActorDestroy(mozilla::ipc::IProtocol::ActorDestroyReason) override;
+
+  void
+  Initialize();
+
+private:
+  RefPtr<RemoteWorkerManager> mManager;
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_RemoteWorkerServiceParent_h
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/RemoteWorkerTypes.ipdlh
@@ -0,0 +1,13 @@
+/* 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 dom {
+
+struct RemoteWorkerData
+{
+};
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/workers/remoteworkers/moz.build
@@ -0,0 +1,38 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+EXPORTS.mozilla.dom += [
+    'RemoteWorkerChild.h',
+    'RemoteWorkerController.h',
+    'RemoteWorkerParent.h',
+    'RemoteWorkerService.h',
+    'RemoteWorkerServiceChild.h',
+    'RemoteWorkerServiceParent.h',
+]
+
+UNIFIED_SOURCES += [
+    'RemoteWorkerChild.cpp',
+    'RemoteWorkerController.cpp',
+    'RemoteWorkerManager.cpp',
+    'RemoteWorkerParent.cpp',
+    'RemoteWorkerService.cpp',
+    'RemoteWorkerServiceChild.cpp',
+    'RemoteWorkerServiceParent.cpp',
+]
+
+LOCAL_INCLUDES += [
+    '/xpcom/build',
+]
+
+IPDL_SOURCES += [
+    'PRemoteWorker.ipdl',
+    'PRemoteWorkerService.ipdl',
+    'RemoteWorkerTypes.ipdlh',
+]
+
+include('/ipc/chromium/chromium-config.mozbuild')
+
+FINAL_LIBRARY = 'xul'
--- a/ipc/glue/BackgroundChildImpl.cpp
+++ b/ipc/glue/BackgroundChildImpl.cpp
@@ -22,16 +22,18 @@
 #include "mozilla/dom/asmjscache/AsmJSCache.h"
 #include "mozilla/dom/cache/ActorUtils.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h"
 #include "mozilla/dom/indexedDB/PBackgroundIndexedDBUtilsChild.h"
 #include "mozilla/dom/ipc/IPCBlobInputStreamChild.h"
 #include "mozilla/dom/ipc/PendingIPCBlobChild.h"
 #include "mozilla/dom/ipc/TemporaryIPCBlobChild.h"
 #include "mozilla/dom/quota/PQuotaChild.h"
+#include "mozilla/dom/RemoteWorkerChild.h"
+#include "mozilla/dom/RemoteWorkerServiceChild.h"
 #include "mozilla/dom/SharedWorkerChild.h"
 #include "mozilla/dom/StorageIPC.h"
 #include "mozilla/dom/GamepadEventChannelChild.h"
 #include "mozilla/dom/GamepadTestChannelChild.h"
 #include "mozilla/dom/LocalStorage.h"
 #include "mozilla/dom/MessagePortChild.h"
 #include "mozilla/dom/ServiceWorkerActors.h"
 #include "mozilla/dom/ServiceWorkerManagerChild.h"
@@ -284,16 +286,45 @@ BackgroundChildImpl::AllocPPendingIPCBlo
 
 bool
 BackgroundChildImpl::DeallocPPendingIPCBlobChild(PPendingIPCBlobChild* aActor)
 {
   delete aActor;
   return true;
 }
 
+dom::PRemoteWorkerChild*
+BackgroundChildImpl::AllocPRemoteWorkerChild(const RemoteWorkerData& aData)
+{
+  return new dom::RemoteWorkerChild();
+}
+
+bool
+BackgroundChildImpl::DeallocPRemoteWorkerChild(dom::PRemoteWorkerChild* aActor)
+{
+  delete aActor;
+  return true;
+}
+
+dom::PRemoteWorkerServiceChild*
+BackgroundChildImpl::AllocPRemoteWorkerServiceChild()
+{
+  RefPtr<dom::RemoteWorkerServiceChild> agent =
+    new dom::RemoteWorkerServiceChild();
+  return agent.forget().take();
+}
+
+bool
+BackgroundChildImpl::DeallocPRemoteWorkerServiceChild(dom::PRemoteWorkerServiceChild* aActor)
+{
+  RefPtr<dom::RemoteWorkerServiceChild> actor =
+    dont_AddRef(static_cast<dom::RemoteWorkerServiceChild*>(aActor));
+  return true;
+}
+
 dom::PSharedWorkerChild*
 BackgroundChildImpl::AllocPSharedWorkerChild(const dom::SharedWorkerLoadInfo& aInfo)
 {
   RefPtr<dom::SharedWorkerChild> agent = new dom::SharedWorkerChild();
   return agent.forget().take();
 }
 
 bool
--- a/ipc/glue/BackgroundChildImpl.h
+++ b/ipc/glue/BackgroundChildImpl.h
@@ -109,16 +109,28 @@ protected:
   DeallocPIPCBlobInputStreamChild(PIPCBlobInputStreamChild* aActor) override;
 
   virtual PTemporaryIPCBlobChild*
   AllocPTemporaryIPCBlobChild() override;
 
   virtual bool
   DeallocPTemporaryIPCBlobChild(PTemporaryIPCBlobChild* aActor) override;
 
+  virtual mozilla::dom::PRemoteWorkerChild*
+  AllocPRemoteWorkerChild(const RemoteWorkerData& aData) override;
+
+  virtual bool
+  DeallocPRemoteWorkerChild(mozilla::dom::PRemoteWorkerChild* aActor) override;
+
+  virtual mozilla::dom::PRemoteWorkerServiceChild*
+  AllocPRemoteWorkerServiceChild() override;
+
+  virtual bool
+  DeallocPRemoteWorkerServiceChild(mozilla::dom::PRemoteWorkerServiceChild* aActor) override;
+
   virtual mozilla::dom::PSharedWorkerChild*
   AllocPSharedWorkerChild(const mozilla::dom::SharedWorkerLoadInfo& aInfo) override;
 
   virtual bool
   DeallocPSharedWorkerChild(mozilla::dom::PSharedWorkerChild* aActor) override;
 
   virtual PFileDescriptorSetChild*
   AllocPFileDescriptorSetChild(const FileDescriptor& aFileDescriptor)
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -30,16 +30,18 @@
 #include "mozilla/dom/asmjscache/AsmJSCache.h"
 #include "mozilla/dom/cache/ActorUtils.h"
 #include "mozilla/dom/indexedDB/ActorsParent.h"
 #include "mozilla/dom/ipc/IPCBlobInputStreamParent.h"
 #include "mozilla/dom/ipc/PendingIPCBlobParent.h"
 #include "mozilla/dom/ipc/TemporaryIPCBlobParent.h"
 #include "mozilla/dom/quota/ActorsParent.h"
 #include "mozilla/dom/simpledb/ActorsParent.h"
+#include "mozilla/dom/RemoteWorkerParent.h"
+#include "mozilla/dom/RemoteWorkerServiceParent.h"
 #include "mozilla/dom/SharedWorkerParent.h"
 #include "mozilla/dom/StorageIPC.h"
 #include "mozilla/dom/MIDIManagerParent.h"
 #include "mozilla/dom/MIDIPortParent.h"
 #include "mozilla/dom/MIDIPlatformService.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/IPCStreamAlloc.h"
@@ -382,16 +384,53 @@ BackgroundParentImpl::DeallocPPendingIPC
   AssertIsInMainProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   delete aActor;
   return true;
 }
 
+mozilla::dom::PRemoteWorkerParent*
+BackgroundParentImpl::AllocPRemoteWorkerParent(const RemoteWorkerData& aData)
+{
+  RefPtr<dom::RemoteWorkerParent> agent = new dom::RemoteWorkerParent();
+  return agent.forget().take();
+}
+
+bool
+BackgroundParentImpl::DeallocPRemoteWorkerParent(mozilla::dom::PRemoteWorkerParent* aActor)
+{
+  RefPtr<mozilla::dom::RemoteWorkerParent> actor =
+    dont_AddRef(static_cast<mozilla::dom::RemoteWorkerParent*>(aActor));
+  return true;
+}
+
+mozilla::dom::PRemoteWorkerServiceParent*
+BackgroundParentImpl::AllocPRemoteWorkerServiceParent()
+{
+  return new mozilla::dom::RemoteWorkerServiceParent();
+}
+
+IPCResult
+BackgroundParentImpl::RecvPRemoteWorkerServiceConstructor(PRemoteWorkerServiceParent* aActor)
+{
+  mozilla::dom::RemoteWorkerServiceParent* actor =
+    static_cast<mozilla::dom::RemoteWorkerServiceParent*>(aActor);
+  actor->Initialize();
+  return IPC_OK();
+}
+
+bool
+BackgroundParentImpl::DeallocPRemoteWorkerServiceParent(mozilla::dom::PRemoteWorkerServiceParent* aActor)
+{
+  delete aActor;
+  return true;
+}
+
 mozilla::dom::PSharedWorkerParent*
 BackgroundParentImpl::AllocPSharedWorkerParent(const mozilla::dom::SharedWorkerLoadInfo& aInfo)
 {
   RefPtr<dom::SharedWorkerParent> agent =
     new mozilla::dom::SharedWorkerParent();
   return agent.forget().take();
 }
 
--- a/ipc/glue/BackgroundParentImpl.h
+++ b/ipc/glue/BackgroundParentImpl.h
@@ -128,16 +128,31 @@ protected:
   AllocPTemporaryIPCBlobParent() override;
 
   virtual mozilla::ipc::IPCResult
   RecvPTemporaryIPCBlobConstructor(PTemporaryIPCBlobParent* actor) override;
 
   virtual bool
   DeallocPTemporaryIPCBlobParent(PTemporaryIPCBlobParent* aActor) override;
 
+  virtual mozilla::dom::PRemoteWorkerParent*
+  AllocPRemoteWorkerParent(const RemoteWorkerData& aData) override;
+
+  virtual bool
+  DeallocPRemoteWorkerParent(PRemoteWorkerParent* aActor) override;
+
+  virtual mozilla::dom::PRemoteWorkerServiceParent*
+  AllocPRemoteWorkerServiceParent() override;
+
+  virtual mozilla::ipc::IPCResult
+  RecvPRemoteWorkerServiceConstructor(PRemoteWorkerServiceParent* aActor) override;
+
+  virtual bool
+  DeallocPRemoteWorkerServiceParent(PRemoteWorkerServiceParent* aActor) override;
+
   virtual mozilla::dom::PSharedWorkerParent*
   AllocPSharedWorkerParent(const mozilla::dom::SharedWorkerLoadInfo& aInfo) override;
 
   virtual mozilla::ipc::IPCResult
   RecvPSharedWorkerConstructor(PSharedWorkerParent* aActor,
                                const mozilla::dom::SharedWorkerLoadInfo& aInfo) override;
 
   virtual bool
--- a/ipc/glue/PBackground.ipdl
+++ b/ipc/glue/PBackground.ipdl
@@ -16,16 +16,18 @@ include protocol PCacheStreamControl;
 include protocol PClientManager;
 include protocol PFileDescriptorSet;
 include protocol PFileSystemRequest;
 include protocol PGamepadEventChannel;
 include protocol PGamepadTestChannel;
 include protocol PHttpBackgroundChannel;
 include protocol PIPCBlobInputStream;
 include protocol PPendingIPCBlob;
+include protocol PRemoteWorker;
+include protocol PRemoteWorkerService;
 include protocol PSharedWorker;
 include protocol PTemporaryIPCBlob;
 include protocol PMessagePort;
 include protocol PCameras;
 include protocol PMIDIManager;
 include protocol PMIDIPort;
 include protocol PQuota;
 include protocol PChildToParentStream;
@@ -41,16 +43,17 @@ include protocol PVsync;
 include DOMTypes;
 include IPCBlob;
 include IPCServiceWorkerDescriptor;
 include IPCServiceWorkerRegistrationDescriptor;
 include PBackgroundSharedTypes;
 include PBackgroundIDBSharedTypes;
 include PFileSystemParams;
 include ProtocolTypes;
+include RemoteWorkerTypes;
 include SharedWorkerTypes;
 include MIDITypes;
 
 include "mozilla/dom/cache/IPCUtils.h";
 include "mozilla/layers/LayersMessageUtils.h";
 
 using mozilla::dom::cache::Namespace
   from "mozilla/dom/cache/Types.h";
@@ -80,16 +83,18 @@ sync protocol PBackground
   manages PClientManager;
   manages PFileDescriptorSet;
   manages PFileSystemRequest;
   manages PGamepadEventChannel;
   manages PGamepadTestChannel;
   manages PHttpBackgroundChannel;
   manages PIPCBlobInputStream;
   manages PPendingIPCBlob;
+  manages PRemoteWorker;
+  manages PRemoteWorkerService;
   manages PSharedWorker;
   manages PTemporaryIPCBlob;
   manages PMessagePort;
   manages PCameras;
   manages PMIDIManager;
   manages PMIDIPort;
   manages PQuota;
   manages PChildToParentStream;
@@ -166,28 +171,31 @@ parent:
   async PMIDIPort(MIDIPortInfo portInfo, bool sysexEnabled);
 
   // This method is used to propagate storage activities from the child actor
   // to the parent actor. See StorageActivityService.
   async StorageActivity(PrincipalInfo principalInfo);
 
   async PServiceWorker(IPCServiceWorkerDescriptor aDescriptor);
 
+  async PRemoteWorkerService();
+
   async PServiceWorkerContainer();
 
   async PServiceWorkerRegistration(IPCServiceWorkerRegistrationDescriptor aDescriptor);
 
 child:
   async PCache();
   async PCacheStreamControl();
 
   async PParentToChildStream();
 
   async PPendingIPCBlob(IPCBlob blob);
 
+  async PRemoteWorker(RemoteWorkerData data);
 both:
   // PIPCBlobInputStream is created on the parent side only if the child starts
   // a migration.
   async PIPCBlobInputStream(nsID aID, uint64_t aSize);
 
   async PFileDescriptorSet(FileDescriptor fd);
 };
 
--- a/layout/build/nsLayoutStatics.cpp
+++ b/layout/build/nsLayoutStatics.cpp
@@ -104,16 +104,17 @@
 #include "mozilla/ClearSiteData.h"
 #include "mozilla/Fuzzyfox.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/StaticPresData.h"
 #include "mozilla/dom/WebIDLGlobalNameHash.h"
 #include "mozilla/dom/ipc/IPCBlobInputStreamStorage.h"
 #include "mozilla/dom/U2FTokenManager.h"
 #include "mozilla/dom/PointerEventHandler.h"
+#include "mozilla/dom/RemoteWorkerService.h"
 #include "mozilla/dom/BlobURLProtocolHandler.h"
 #include "nsThreadManager.h"
 #include "mozilla/css/ImageLoader.h"
 
 using namespace mozilla;
 using namespace mozilla::net;
 using namespace mozilla::dom;
 using namespace mozilla::dom::ipc;
@@ -269,19 +270,20 @@ nsLayoutStatics::Initialize()
   }
 
   // This must be initialized on the main-thread.
   mozilla::dom::IPCBlobInputStreamStorage::Initialize();
 
   mozilla::dom::U2FTokenManager::Initialize();
 
   if (XRE_IsParentProcess()) {
-    // On content process we initialize DOMPrefs when PContentChild is fully
-    // initialized.
+    // On content process we initialize these components when PContentChild is
+    // fully initialized.
     mozilla::dom::DOMPrefs::Initialize();
+    mozilla::dom::RemoteWorkerService::Initialize();
   }
 
   nsThreadManager::InitializeShutdownObserver();
 
   mozilla::Fuzzyfox::Start();
 
   ClearSiteData::Initialize();
 
--- a/layout/ipc/PVsync.ipdl
+++ b/layout/ipc/PVsync.ipdl
@@ -1,14 +1,15 @@
 /* -*- 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 protocol PBackground;
+include "mozilla/layers/LayersMessageUtils.h";
 
 using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
 
 namespace mozilla {
 namespace layout {
 
 /*
  * The PVsync is a sub-protocol in PBackground and it is used to notify