Merge inbound to mozilla-central a=merge
authordluca <dluca@mozilla.com>
Thu, 09 Nov 2017 15:56:43 +0200
changeset 444201 2bdf6eed0f64a51dfe099e089852533595f1a896
parent 444193 05ae89bebb64438b208ce4daadadc8574b238171 (current diff)
parent 444200 176a739c66b9ebd4098131339c0ed12a192c7dc9 (diff)
child 444214 486620c2345ab558d0507c14a19e49f631b8347f
child 444215 41d667952cf2ce3f3945577c9e5d10b0be44ef60
child 444225 9aff6ae3fc566b7cb599b63b53350069801d83b5
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone58.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
Merge inbound to mozilla-central a=merge
js/src/wasm/WasmJS.cpp
new file mode 100644
--- /dev/null
+++ b/dom/clients/manager/ClientHandle.cpp
@@ -0,0 +1,99 @@
+/* -*- 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 "ClientHandle.h"
+
+#include "ClientHandleChild.h"
+#include "ClientHandleOpChild.h"
+#include "ClientManager.h"
+#include "mozilla/dom/PClientManagerChild.h"
+
+namespace mozilla {
+namespace dom {
+
+ClientHandle::~ClientHandle()
+{
+  Shutdown();
+}
+
+void
+ClientHandle::Shutdown()
+{
+  NS_ASSERT_OWNINGTHREAD(ClientSource);
+  if (IsShutdown()) {
+    return;
+  }
+
+  ShutdownThing();
+
+  mManager = nullptr;
+}
+
+already_AddRefed<ClientOpPromise>
+ClientHandle::StartOp(const ClientOpConstructorArgs& aArgs)
+{
+  RefPtr<ClientOpPromise::Private> promise =
+    new ClientOpPromise::Private(__func__);
+
+  // Hold a ref to the client until the remote operation completes.  Otherwise
+  // the ClientHandle might get de-refed and teardown the actor before we
+  // get an answer.
+  RefPtr<ClientHandle> kungFuGrip = this;
+  promise->Then(mSerialEventTarget, __func__,
+                [kungFuGrip] (const ClientOpResult &) { },
+                [kungFuGrip] (nsresult) { });
+
+  MaybeExecute([aArgs, promise] (ClientHandleChild* aActor) {
+    ClientHandleOpChild* actor = new ClientHandleOpChild(aArgs, promise);
+    if (!aActor->SendPClientHandleOpConstructor(actor, aArgs)) {
+      // Constructor failure will reject promise via ActorDestroy()
+      return;
+    }
+  });
+
+  RefPtr<ClientOpPromise> ref = promise.get();
+  return ref.forget();
+}
+
+ClientHandle::ClientHandle(ClientManager* aManager,
+                           nsISerialEventTarget* aSerialEventTarget,
+                           const ClientInfo& aClientInfo)
+  : mManager(aManager)
+  , mSerialEventTarget(aSerialEventTarget)
+  , mClientInfo(aClientInfo)
+{
+  MOZ_DIAGNOSTIC_ASSERT(mManager);
+  MOZ_DIAGNOSTIC_ASSERT(mSerialEventTarget);
+  MOZ_ASSERT(mSerialEventTarget->IsOnCurrentThread());
+}
+
+void
+ClientHandle::Activate(PClientManagerChild* aActor)
+{
+  NS_ASSERT_OWNINGTHREAD(ClientHandle);
+
+  if (IsShutdown()) {
+    return;
+  }
+
+  PClientHandleChild* actor =
+    aActor->SendPClientHandleConstructor(mClientInfo.ToIPC());
+  if (!actor) {
+    Shutdown();
+    return;
+  }
+
+  ActivateThing(static_cast<ClientHandleChild*>(actor));
+}
+
+const ClientInfo&
+ClientHandle::Info() const
+{
+  return mClientInfo;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/clients/manager/ClientHandle.h
@@ -0,0 +1,66 @@
+/* -*- 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_ClientHandle_h
+#define _mozilla_dom_ClientHandle_h
+
+#include "mozilla/dom/ClientInfo.h"
+#include "mozilla/dom/ClientOpPromise.h"
+#include "mozilla/dom/ClientThing.h"
+
+#ifdef XP_WIN
+#undef PostMessage
+#endif
+
+namespace mozilla {
+
+namespace dom {
+
+class ClientManager;
+class ClientHandleChild;
+class ClientOpConstructorArgs;
+class PClientManagerChild;
+
+// The ClientHandle allows code to take a simple ClientInfo struct and
+// convert it into a live actor-backed object attached to a particular
+// ClientSource somewhere in the browser.  If the ClientSource is
+// destroyed then the ClientHandle will simply begin to reject operations.
+// We do not currently provide a way to be notified when the ClientSource
+// is destroyed, but this could be added in the future.
+class ClientHandle final : public ClientThing<ClientHandleChild>
+{
+  friend class ClientManager;
+
+  RefPtr<ClientManager> mManager;
+  nsCOMPtr<nsISerialEventTarget> mSerialEventTarget;
+  ClientInfo mClientInfo;
+
+  ~ClientHandle();
+
+  void
+  Shutdown();
+
+  already_AddRefed<ClientOpPromise>
+  StartOp(const ClientOpConstructorArgs& aArgs);
+
+  // Private methods called by ClientManager
+  ClientHandle(ClientManager* aManager,
+               nsISerialEventTarget* aSerialEventTarget,
+               const ClientInfo& aClientInfo);
+
+  void
+  Activate(PClientManagerChild* aActor);
+
+public:
+  const ClientInfo&
+  Info() const;
+
+  NS_INLINE_DECL_REFCOUNTING(ClientHandle);
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // _mozilla_dom_ClientHandle_h
--- a/dom/clients/manager/ClientHandleParent.cpp
+++ b/dom/clients/manager/ClientHandleParent.cpp
@@ -2,16 +2,17 @@
 /* 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 "ClientHandleParent.h"
 
 #include "ClientHandleOpParent.h"
+#include "ClientManagerService.h"
 #include "ClientSourceParent.h"
 #include "mozilla/dom/ClientIPCTypes.h"
 #include "mozilla/Unused.h"
 
 namespace mozilla {
 namespace dom {
 
 using mozilla::ipc::IPCResult;
@@ -21,16 +22,20 @@ ClientHandleParent::RecvTeardown()
 {
   Unused << Send__delete__(this);
   return IPC_OK();
 }
 
 void
 ClientHandleParent::ActorDestroy(ActorDestroyReason aReason)
 {
+  if (mSource) {
+    mSource->DetachHandle(this);
+    mSource = nullptr;
+  }
 }
 
 PClientHandleOpParent*
 ClientHandleParent::AllocPClientHandleOpParent(const ClientOpConstructorArgs& aArgs)
 {
   return new ClientHandleOpParent();
 }
 
@@ -46,22 +51,38 @@ ClientHandleParent::RecvPClientHandleOpC
                                                    const ClientOpConstructorArgs& aArgs)
 {
   auto actor = static_cast<ClientHandleOpParent*>(aActor);
   actor->Init(aArgs);
   return IPC_OK();
 }
 
 ClientHandleParent::ClientHandleParent()
+  : mService(ClientManagerService::GetOrCreateInstance())
+  , mSource(nullptr)
 {
 }
 
 ClientHandleParent::~ClientHandleParent()
 {
+  MOZ_DIAGNOSTIC_ASSERT(!mSource);
 }
 
 void
 ClientHandleParent::Init(const IPCClientInfo& aClientInfo)
 {
+  mSource = mService->FindSource(aClientInfo.id(), aClientInfo.principalInfo());
+  if (!mSource) {
+    Unused << Send__delete__(this);
+    return;
+  }
+
+  mSource->AttachHandle(this);
+}
+
+ClientSourceParent*
+ClientHandleParent::GetSource() const
+{
+  return mSource;
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/clients/manager/ClientHandleParent.h
+++ b/dom/clients/manager/ClientHandleParent.h
@@ -6,18 +6,24 @@
 #ifndef _mozilla_dom_ClientHandleParent_h
 #define _mozilla_dom_ClientHandleParent_h
 
 #include "mozilla/dom/PClientHandleParent.h"
 
 namespace mozilla {
 namespace dom {
 
+class ClientManagerService;
+class ClientSourceParent;
+
 class ClientHandleParent final : public PClientHandleParent
 {
+  RefPtr<ClientManagerService> mService;
+  ClientSourceParent* mSource;
+
   // PClientHandleParent interface
   mozilla::ipc::IPCResult
   RecvTeardown() override;
 
   void
   ActorDestroy(ActorDestroyReason aReason) override;
 
   PClientHandleOpParent*
@@ -31,14 +37,17 @@ class ClientHandleParent final : public 
                                  const ClientOpConstructorArgs& aArgs) override;
 
 public:
   ClientHandleParent();
   ~ClientHandleParent();
 
   void
   Init(const IPCClientInfo& aClientInfo);
+
+  ClientSourceParent*
+  GetSource() const;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // _mozilla_dom_ClientHandleParent_h
--- a/dom/clients/manager/ClientIPCTypes.ipdlh
+++ b/dom/clients/manager/ClientIPCTypes.ipdlh
@@ -12,16 +12,20 @@ using ClientType from "mozilla/dom/Clien
 using FrameType from "mozilla/dom/ClientIPCUtils.h";
 using VisibilityState from "mozilla/dom/ClientIPCUtils.h";
 
 namespace mozilla {
 namespace dom {
 
 struct ClientSourceConstructorArgs
 {
+  nsID id;
+  ClientType type;
+  PrincipalInfo principalInfo;
+  TimeStamp creationTime;
 };
 
 struct IPCClientInfo
 {
   nsID id;
   ClientType type;
   PrincipalInfo principalInfo;
   TimeStamp creationTime;
new file mode 100644
--- /dev/null
+++ b/dom/clients/manager/ClientManager.cpp
@@ -0,0 +1,236 @@
+/* -*- 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 "ClientManager.h"
+
+#include "ClientHandle.h"
+#include "ClientManagerChild.h"
+#include "ClientManagerOpChild.h"
+#include "ClientSource.h"
+#include "mozilla/dom/WorkerPrivate.h"
+#include "mozilla/dom/workers/bindings/WorkerHolderToken.h"
+#include "mozilla/ipc/BackgroundChild.h"
+#include "mozilla/ipc/PBackgroundChild.h"
+#include "prthread.h"
+
+namespace mozilla {
+namespace dom {
+
+using mozilla::ipc::BackgroundChild;
+using mozilla::ipc::PBackgroundChild;
+using mozilla::ipc::PrincipalInfo;
+using mozilla::dom::workers::Closing;
+using mozilla::dom::workers::GetCurrentThreadWorkerPrivate;
+using mozilla::dom::workers::WorkerHolderToken;
+using mozilla::dom::workers::WorkerPrivate;
+
+namespace {
+
+uint32_t kBadThreadLocalIndex = -1;
+uint32_t sClientManagerThreadLocalIndex = kBadThreadLocalIndex;
+
+} // anonymous namespace
+
+ClientManager::ClientManager()
+{
+  PBackgroundChild* parentActor = BackgroundChild::GetOrCreateForCurrentThread();
+  if (NS_WARN_IF(!parentActor)) {
+    Shutdown();
+    return;
+  }
+
+  RefPtr<WorkerHolderToken> workerHolderToken;
+  if (!NS_IsMainThread()) {
+    WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
+    MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
+
+    workerHolderToken =
+      WorkerHolderToken::Create(workerPrivate, Closing,
+                                WorkerHolderToken::AllowIdleShutdownStart);
+    if (NS_WARN_IF(!workerHolderToken)) {
+      Shutdown();
+      return;
+    }
+  }
+
+  ClientManagerChild* actor = new ClientManagerChild(workerHolderToken);
+  PClientManagerChild *sentActor =
+    parentActor->SendPClientManagerConstructor(actor);
+  if (NS_WARN_IF(!sentActor)) {
+    Shutdown();
+    return;
+  }
+  MOZ_DIAGNOSTIC_ASSERT(sentActor == actor);
+
+  ActivateThing(actor);
+}
+
+ClientManager::~ClientManager()
+{
+  NS_ASSERT_OWNINGTHREAD(ClientManager);
+
+  Shutdown();
+
+  MOZ_DIAGNOSTIC_ASSERT(this == PR_GetThreadPrivate(sClientManagerThreadLocalIndex));
+  PRStatus status =
+    PR_SetThreadPrivate(sClientManagerThreadLocalIndex, nullptr);
+  MOZ_DIAGNOSTIC_ASSERT(status == PR_SUCCESS);
+}
+
+void
+ClientManager::Shutdown()
+{
+  NS_ASSERT_OWNINGTHREAD(ClientManager);
+
+  if (IsShutdown()) {
+    return;
+  }
+
+  ShutdownThing();
+}
+
+UniquePtr<ClientSource>
+ClientManager::CreateSourceInternal(ClientType aType,
+                                    const PrincipalInfo& aPrincipal)
+{
+  NS_ASSERT_OWNINGTHREAD(ClientManager);
+
+  if (IsShutdown()) {
+    return nullptr;
+  }
+
+  nsID id;
+  nsresult rv = nsContentUtils::GenerateUUIDInPlace(id);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return nullptr;
+  }
+
+  ClientSourceConstructorArgs args(id, aType, aPrincipal, TimeStamp::Now());
+  UniquePtr<ClientSource> source(new ClientSource(this, args));
+  source->Activate(GetActor());
+
+  return Move(source);
+}
+
+already_AddRefed<ClientHandle>
+ClientManager::CreateHandleInternal(const ClientInfo& aClientInfo,
+                                    nsISerialEventTarget* aSerialEventTarget)
+{
+  NS_ASSERT_OWNINGTHREAD(ClientManager);
+  MOZ_DIAGNOSTIC_ASSERT(aSerialEventTarget);
+
+  if (IsShutdown()) {
+    return nullptr;
+  }
+
+  RefPtr<ClientHandle> handle = new ClientHandle(this, aSerialEventTarget,
+                                                 aClientInfo);
+  handle->Activate(GetActor());
+
+  return handle.forget();
+}
+
+already_AddRefed<ClientOpPromise>
+ClientManager::StartOp(const ClientOpConstructorArgs& aArgs,
+                       nsISerialEventTarget* aSerialEventTarget)
+{
+  RefPtr<ClientOpPromise::Private> promise =
+    new ClientOpPromise::Private(__func__);
+
+  // Hold a ref to the client until the remote operation completes.  Otherwise
+  // the ClientHandle might get de-refed and teardown the actor before we
+  // get an answer.
+  RefPtr<ClientManager> kungFuGrip = this;
+  promise->Then(aSerialEventTarget, __func__,
+                [kungFuGrip] (const ClientOpResult&) { },
+                [kungFuGrip] (nsresult) { });
+
+  MaybeExecute([aArgs, promise] (ClientManagerChild* aActor) {
+    ClientManagerOpChild* actor = new ClientManagerOpChild(aArgs, promise);
+    if (!aActor->SendPClientManagerOpConstructor(actor, aArgs)) {
+      // Constructor failure will reject promise via ActorDestroy()
+      return;
+    }
+  });
+
+  RefPtr<ClientOpPromise> ref = promise.get();
+  return ref.forget();
+}
+
+// static
+already_AddRefed<ClientManager>
+ClientManager::GetOrCreateForCurrentThread()
+{
+  MOZ_DIAGNOSTIC_ASSERT(sClientManagerThreadLocalIndex != kBadThreadLocalIndex);
+  RefPtr<ClientManager> cm =
+    static_cast<ClientManager*>(PR_GetThreadPrivate(sClientManagerThreadLocalIndex));
+
+  if (!cm) {
+    cm = new ClientManager();
+
+    PRStatus status =
+      PR_SetThreadPrivate(sClientManagerThreadLocalIndex, cm.get());
+    MOZ_DIAGNOSTIC_ASSERT(status == PR_SUCCESS);
+  }
+
+  MOZ_ASSERT(cm);
+  return cm.forget();
+}
+
+WorkerPrivate*
+ClientManager::GetWorkerPrivate() const
+{
+  NS_ASSERT_OWNINGTHREAD(ClientManager);
+  MOZ_DIAGNOSTIC_ASSERT(GetActor());
+  return GetActor()->GetWorkerPrivate();
+}
+
+// static
+void
+ClientManager::Startup()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  PRStatus status =
+    PR_NewThreadPrivateIndex(&sClientManagerThreadLocalIndex, nullptr);
+  MOZ_DIAGNOSTIC_ASSERT(status == PR_SUCCESS);
+}
+
+// static
+UniquePtr<ClientSource>
+ClientManager::CreateSource(ClientType aType, nsIPrincipal* aPrincipal)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aPrincipal);
+
+  PrincipalInfo principalInfo;
+  nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return nullptr;
+  }
+
+  RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
+  return mgr->CreateSourceInternal(aType, principalInfo);
+}
+
+// static
+UniquePtr<ClientSource>
+ClientManager::CreateSource(ClientType aType, const PrincipalInfo& aPrincipal)
+{
+  RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
+  return mgr->CreateSourceInternal(aType, aPrincipal);
+}
+
+// static
+already_AddRefed<ClientHandle>
+ClientManager::CreateHandle(const ClientInfo& aClientInfo,
+                            nsISerialEventTarget* aSerialEventTarget)
+{
+  RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
+  return mgr->CreateHandleInternal(aClientInfo, aSerialEventTarget);
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/clients/manager/ClientManager.h
@@ -0,0 +1,95 @@
+/* -*- 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_ClientManager_h
+#define _mozilla_dom_ClientManager_h
+
+#include "mozilla/dom/ClientOpPromise.h"
+#include "mozilla/dom/ClientThing.h"
+
+namespace mozilla {
+namespace ipc {
+class PBackgroundChild;
+} // namespace ipc
+namespace dom {
+
+class ClientHandle;
+class ClientInfo;
+class ClientManagerChild;
+class ClientOpConstructorArgs;
+class ClientSource;
+enum class ClientType : uint8_t;
+
+namespace workers {
+class WorkerPrivate;
+} // workers namespace
+
+// The ClientManager provides a per-thread singleton interface workering
+// with the client subsystem.  It allows globals to create ClientSource
+// objects.  It allows other parts of the system to attach to this globals
+// by creating ClientHandle objects.  The ClientManager also provides
+// methods for querying the list of clients active in the system.
+class ClientManager final : public ClientThing<ClientManagerChild>
+{
+  friend class ClientManagerChild;
+
+  ClientManager();
+  ~ClientManager();
+
+  // Utility method to trigger a shutdown of the ClientManager.  This
+  // is called in various error conditions or when the last reference
+  // is dropped.
+  void
+  Shutdown();
+
+  UniquePtr<ClientSource>
+  CreateSourceInternal(ClientType aType,
+                       const mozilla::ipc::PrincipalInfo& aPrincipal);
+
+  already_AddRefed<ClientHandle>
+  CreateHandleInternal(const ClientInfo& aClientInfo,
+                       nsISerialEventTarget* aSerialEventTarget);
+
+  // Utility method to perform an IPC operation.  This will create a
+  // PClientManagerOp actor tied to a MozPromise.  The promise will
+  // resolve or reject with the result of the remote operation.
+  already_AddRefed<ClientOpPromise>
+  StartOp(const ClientOpConstructorArgs& aArgs,
+          nsISerialEventTarget* aSerialEventTarget);
+
+  // Get or create the TLS singleton.  Currently this is only used
+  // internally and external code indirectly calls it by invoking
+  // static methods.
+  static already_AddRefed<ClientManager>
+  GetOrCreateForCurrentThread();
+
+  // Private methods called by ClientSource
+  mozilla::dom::workers::WorkerPrivate*
+  GetWorkerPrivate() const;
+
+public:
+  // Initialize the ClientManager at process start.  This
+  // does book-keeping like creating a TLS identifier, etc.
+  // This should only be called by process startup code.
+  static void
+  Startup();
+
+  static UniquePtr<ClientSource>
+  CreateSource(ClientType aType, nsIPrincipal* aPrincipal);
+
+  static UniquePtr<ClientSource>
+  CreateSource(ClientType aType, const mozilla::ipc::PrincipalInfo& aPrincipal);
+
+  static already_AddRefed<ClientHandle>
+  CreateHandle(const ClientInfo& aClientInfo,
+               nsISerialEventTarget* aSerialEventTarget);
+
+  NS_INLINE_DECL_REFCOUNTING(mozilla::dom::ClientManager)
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // _mozilla_dom_ClientManager_h
--- a/dom/clients/manager/ClientManagerOpParent.cpp
+++ b/dom/clients/manager/ClientManagerOpParent.cpp
@@ -9,15 +9,21 @@
 namespace mozilla {
 namespace dom {
 
 void
 ClientManagerOpParent::ActorDestroy(ActorDestroyReason aReason)
 {
 }
 
+ClientManagerOpParent::ClientManagerOpParent(ClientManagerService* aService)
+  : mService(aService)
+{
+  MOZ_DIAGNOSTIC_ASSERT(mService);
+}
+
 void
 ClientManagerOpParent::Init(const ClientOpConstructorArgs& aArgs)
 {
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/clients/manager/ClientManagerOpParent.h
+++ b/dom/clients/manager/ClientManagerOpParent.h
@@ -10,22 +10,24 @@
 
 namespace mozilla {
 namespace dom {
 
 class ClientManagerService;
 
 class ClientManagerOpParent final : public PClientManagerOpParent
 {
+  RefPtr<ClientManagerService> mService;
+
   // PClientManagerOpParent interface
   void
   ActorDestroy(ActorDestroyReason aReason) override;
 
 public:
-  ClientManagerOpParent() = default;
+  explicit ClientManagerOpParent(ClientManagerService* aService);
   ~ClientManagerOpParent() = default;
 
   void
   Init(const ClientOpConstructorArgs& aArgs);
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/clients/manager/ClientManagerParent.cpp
+++ b/dom/clients/manager/ClientManagerParent.cpp
@@ -3,16 +3,17 @@
 /* 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 "ClientManagerParent.h"
 
 #include "ClientHandleParent.h"
 #include "ClientManagerOpParent.h"
+#include "ClientManagerService.h"
 #include "ClientSourceParent.h"
 #include "mozilla/dom/PClientNavigateOpParent.h"
 #include "mozilla/Unused.h"
 
 namespace mozilla {
 namespace dom {
 
 using mozilla::ipc::IPCResult;
@@ -49,17 +50,17 @@ ClientManagerParent::RecvPClientHandleCo
   ClientHandleParent* actor = static_cast<ClientHandleParent*>(aActor);
   actor->Init(aClientInfo);
   return IPC_OK();
 }
 
 PClientManagerOpParent*
 ClientManagerParent::AllocPClientManagerOpParent(const ClientOpConstructorArgs& aArgs)
 {
-  return new ClientManagerOpParent();
+  return new ClientManagerOpParent(mService);
 }
 
 bool
 ClientManagerParent::DeallocPClientManagerOpParent(PClientManagerOpParent* aActor)
 {
   delete aActor;
   return true;
 }
@@ -96,16 +97,17 @@ ClientManagerParent::AllocPClientSourceP
 bool
 ClientManagerParent::DeallocPClientSourceParent(PClientSourceParent* aActor)
 {
   delete aActor;
   return true;
 }
 
 ClientManagerParent::ClientManagerParent()
+  : mService(ClientManagerService::GetOrCreateInstance())
 {
 }
 
 ClientManagerParent::~ClientManagerParent()
 {
 }
 
 } // namespace dom
--- a/dom/clients/manager/ClientManagerParent.h
+++ b/dom/clients/manager/ClientManagerParent.h
@@ -6,18 +6,22 @@
 #ifndef _mozilla_dom_ClientManagerParent_h
 #define _mozilla_dom_ClientManagerParent_h
 
 #include "mozilla/dom/PClientManagerParent.h"
 
 namespace mozilla {
 namespace dom {
 
+class ClientManagerService;
+
 class ClientManagerParent final : public PClientManagerParent
 {
+  RefPtr<ClientManagerService> mService;
+
   // PClientManagerParent interface
   mozilla::ipc::IPCResult
   RecvTeardown() override;
 
   void
   ActorDestroy(ActorDestroyReason aReason) override;
 
   PClientHandleParent*
new file mode 100644
--- /dev/null
+++ b/dom/clients/manager/ClientManagerService.cpp
@@ -0,0 +1,125 @@
+/* -*- 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 "ClientManagerService.h"
+
+#include "mozilla/ipc/BackgroundParent.h"
+
+namespace mozilla {
+namespace dom {
+
+using mozilla::ipc::AssertIsOnBackgroundThread;
+using mozilla::ipc::ContentPrincipalInfo;
+
+namespace {
+
+ClientManagerService* sClientManagerServiceInstance = nullptr;
+
+bool
+MatchPrincipalInfo(const PrincipalInfo& aLeft, const PrincipalInfo& aRight)
+{
+  if (aLeft.type() != aRight.type()) {
+    return false;
+  }
+
+  switch (aLeft.type()) {
+    case PrincipalInfo::TContentPrincipalInfo:
+    {
+      const ContentPrincipalInfo& leftContent = aLeft.get_ContentPrincipalInfo();
+      const ContentPrincipalInfo& rightContent = aRight.get_ContentPrincipalInfo();
+      return leftContent.attrs() == rightContent.attrs() &&
+             leftContent.originNoSuffix() == rightContent.originNoSuffix();
+    }
+    case PrincipalInfo::TSystemPrincipalInfo:
+    {
+      // system principal always matches
+      return true;
+    }
+    case PrincipalInfo::TNullPrincipalInfo:
+    {
+      // null principal never matches
+      return false;
+    }
+    default:
+    {
+      break;
+    }
+  }
+
+  // Clients (windows/workers) should never have an expanded principal type.
+  MOZ_CRASH("unexpected principal type!");
+}
+
+} // anonymous namespace
+
+ClientManagerService::ClientManagerService()
+{
+  AssertIsOnBackgroundThread();
+}
+
+ClientManagerService::~ClientManagerService()
+{
+  AssertIsOnBackgroundThread();
+  MOZ_DIAGNOSTIC_ASSERT(mSourceTable.Count() == 0);
+
+  MOZ_DIAGNOSTIC_ASSERT(sClientManagerServiceInstance == this);
+  sClientManagerServiceInstance = nullptr;
+}
+
+// static
+already_AddRefed<ClientManagerService>
+ClientManagerService::GetOrCreateInstance()
+{
+  AssertIsOnBackgroundThread();
+
+  if (!sClientManagerServiceInstance) {
+    sClientManagerServiceInstance = new ClientManagerService();
+  }
+
+  RefPtr<ClientManagerService> ref(sClientManagerServiceInstance);
+  return ref.forget();
+}
+
+void
+ClientManagerService::AddSource(ClientSourceParent* aSource)
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(aSource);
+  auto entry = mSourceTable.LookupForAdd(aSource->Info().Id());
+  MOZ_DIAGNOSTIC_ASSERT(!entry);
+  entry.OrInsert([&] { return aSource; });
+}
+
+void
+ClientManagerService::RemoveSource(ClientSourceParent* aSource)
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(aSource);
+  auto entry = mSourceTable.Lookup(aSource->Info().Id());
+  MOZ_DIAGNOSTIC_ASSERT(entry);
+  entry.Remove();
+}
+
+ClientSourceParent*
+ClientManagerService::FindSource(const nsID& aID, const PrincipalInfo& aPrincipalInfo)
+{
+  AssertIsOnBackgroundThread();
+
+  auto entry = mSourceTable.Lookup(aID);
+  if (!entry) {
+    return nullptr;
+  }
+
+  ClientSourceParent* source = entry.Data();
+  if (!MatchPrincipalInfo(source->Info().PrincipalInfo(), aPrincipalInfo)) {
+    return nullptr;
+  }
+
+  return source;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/clients/manager/ClientManagerService.h
@@ -0,0 +1,49 @@
+/* -*- 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_ClientManagerService_h
+#define _mozilla_dom_ClientManagerService_h
+
+#include "nsDataHashtable.h"
+
+namespace mozilla {
+
+namespace dom {
+
+class ClientSourceParent;
+
+// Define a singleton service to manage client activity throughout the
+// browser.  This service runs on the PBackground thread.  To interact
+// it with it please use the ClientManager and ClientHandle classes.
+class ClientManagerService final
+{
+  // Store the ClientSourceParent objects in a hash table.  We want to
+  // optimize for insertion, removal, and lookup by UUID.
+  nsDataHashtable<nsIDHashKey, ClientSourceParent*> mSourceTable;
+
+  ClientManagerService();
+  ~ClientManagerService();
+
+public:
+  static already_AddRefed<ClientManagerService>
+  GetOrCreateInstance();
+
+  void
+  AddSource(ClientSourceParent* aSource);
+
+  void
+  RemoveSource(ClientSourceParent* aSource);
+
+  ClientSourceParent*
+  FindSource(const nsID& aID,
+             const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
+
+  NS_INLINE_DECL_REFCOUNTING(mozilla::dom::ClientManagerService)
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // _mozilla_dom_ClientManagerService_h
new file mode 100644
--- /dev/null
+++ b/dom/clients/manager/ClientSource.cpp
@@ -0,0 +1,68 @@
+/* -*- 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 "ClientSource.h"
+
+#include "ClientManager.h"
+#include "ClientManagerChild.h"
+#include "ClientSourceChild.h"
+#include "mozilla/dom/ClientIPCTypes.h"
+
+namespace mozilla {
+namespace dom {
+
+using mozilla::ipc::PrincipalInfo;
+
+void
+ClientSource::Shutdown()
+{
+  NS_ASSERT_OWNINGTHREAD(ClientSource);
+  if (IsShutdown()) {
+    return;
+  }
+
+  ShutdownThing();
+
+  mManager = nullptr;
+}
+
+ClientSource::ClientSource(ClientManager* aManager,
+                           const ClientSourceConstructorArgs& aArgs)
+  : mManager(aManager)
+  , mClientInfo(aArgs.id(), aArgs.type(), aArgs.principalInfo(), aArgs.creationTime())
+{
+  MOZ_ASSERT(mManager);
+}
+
+void
+ClientSource::Activate(PClientManagerChild* aActor)
+{
+  NS_ASSERT_OWNINGTHREAD(ClientSource);
+  MOZ_ASSERT(!GetActor());
+
+  if (IsShutdown()) {
+    return;
+  }
+
+  ClientSourceConstructorArgs args(mClientInfo.Id(), mClientInfo.Type(),
+                                   mClientInfo.PrincipalInfo(),
+                                   mClientInfo.CreationTime());
+  PClientSourceChild* actor = aActor->SendPClientSourceConstructor(args);
+  if (!actor) {
+    Shutdown();
+    return;
+  }
+
+  ActivateThing(static_cast<ClientSourceChild*>(actor));
+}
+
+ClientSource::~ClientSource()
+{
+  Shutdown();
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/clients/manager/ClientSource.h
@@ -0,0 +1,57 @@
+/* -*- 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_ClientSource_h
+#define _mozilla_dom_ClientSource_h
+
+#include "mozilla/dom/ClientInfo.h"
+#include "mozilla/dom/ClientThing.h"
+
+namespace mozilla {
+namespace dom {
+
+class ClientManager;
+class ClientSourceChild;
+class ClientSourceConstructorArgs;
+class PClientManagerChild;
+
+namespace workers {
+class WorkerPrivate;
+} // workers namespace
+
+// ClientSource is an RAII style class that is designed to be held via
+// a UniquePtr<>.  When created ClientSource will register the existence
+// of a client in the cross-process ClientManagerService.  When the
+// ClientSource is destroyed then client entry will be removed.  Code
+// that represents globals or browsing environments, such as nsGlobalWindow
+// or WorkerPrivate, should use ClientManager to create a ClientSource.
+class ClientSource final : public ClientThing<ClientSourceChild>
+{
+  friend class ClientManager;
+
+  NS_DECL_OWNINGTHREAD
+
+  RefPtr<ClientManager> mManager;
+
+  ClientInfo mClientInfo;
+
+  void
+  Shutdown();
+
+  // Private methods called by ClientManager
+  ClientSource(ClientManager* aManager,
+               const ClientSourceConstructorArgs& aArgs);
+
+  void
+  Activate(PClientManagerChild* aActor);
+
+public:
+  ~ClientSource();
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // _mozilla_dom_ClientSource_h
--- a/dom/clients/manager/ClientSourceChild.cpp
+++ b/dom/clients/manager/ClientSourceChild.cpp
@@ -2,16 +2,17 @@
 /* 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 "ClientSourceChild.h"
 
 #include "ClientSourceOpChild.h"
+#include "ClientThing.h"
 #include "mozilla/dom/ClientIPCTypes.h"
 #include "mozilla/Unused.h"
 
 namespace mozilla {
 namespace dom {
 
 using mozilla::ipc::IPCResult;
 
--- a/dom/clients/manager/ClientSourceParent.cpp
+++ b/dom/clients/manager/ClientSourceParent.cpp
@@ -2,16 +2,17 @@
 /* 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 "ClientSourceParent.h"
 
 #include "ClientHandleParent.h"
+#include "ClientManagerService.h"
 #include "ClientSourceOpParent.h"
 #include "mozilla/dom/ClientIPCTypes.h"
 #include "mozilla/Unused.h"
 
 namespace mozilla {
 namespace dom {
 
 using mozilla::ipc::IPCResult;
@@ -22,16 +23,25 @@ ClientSourceParent::RecvTeardown()
 {
   Unused << Send__delete__(this);
   return IPC_OK();
 }
 
 void
 ClientSourceParent::ActorDestroy(ActorDestroyReason aReason)
 {
+  mService->RemoveSource(this);
+
+  nsTArray<ClientHandleParent*> handleList(mHandleList);
+  for (ClientHandleParent* handle : handleList) {
+    // This should trigger DetachHandle() to be called removing
+    // the entry from the mHandleList.
+    Unused << ClientHandleParent::Send__delete__(handle);
+  }
+  MOZ_DIAGNOSTIC_ASSERT(mHandleList.IsEmpty());
 }
 
 PClientSourceOpParent*
 ClientSourceParent::AllocPClientSourceOpParent(const ClientOpConstructorArgs& aArgs)
 {
   MOZ_ASSERT_UNREACHABLE("ClientSourceOpParent should be explicitly constructed.");
   return nullptr;
 }
@@ -39,17 +49,43 @@ ClientSourceParent::AllocPClientSourceOp
 bool
 ClientSourceParent::DeallocPClientSourceOpParent(PClientSourceOpParent* aActor)
 {
   delete aActor;
   return true;
 }
 
 ClientSourceParent::ClientSourceParent(const ClientSourceConstructorArgs& aArgs)
+  : mClientInfo(aArgs.id(), aArgs.type(), aArgs.principalInfo(), aArgs.creationTime())
+  , mService(ClientManagerService::GetOrCreateInstance())
 {
+  mService->AddSource(this);
 }
 
 ClientSourceParent::~ClientSourceParent()
 {
+  MOZ_DIAGNOSTIC_ASSERT(mHandleList.IsEmpty());
+}
+
+const ClientInfo&
+ClientSourceParent::Info() const
+{
+  return mClientInfo;
+}
+
+void
+ClientSourceParent::AttachHandle(ClientHandleParent* aClientHandle)
+{
+  MOZ_DIAGNOSTIC_ASSERT(aClientHandle);
+  MOZ_ASSERT(!mHandleList.Contains(aClientHandle));
+  mHandleList.AppendElement(aClientHandle);
+}
+
+void
+ClientSourceParent::DetachHandle(ClientHandleParent* aClientHandle)
+{
+  MOZ_DIAGNOSTIC_ASSERT(aClientHandle);
+  MOZ_ASSERT(mHandleList.Contains(aClientHandle));
+  mHandleList.RemoveElement(aClientHandle);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/clients/manager/ClientSourceParent.h
+++ b/dom/clients/manager/ClientSourceParent.h
@@ -1,37 +1,54 @@
 /* -*- 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_ClientSourceParent_h
 #define _mozilla_dom_ClientSourceParent_h
 
+#include "ClientInfo.h"
 #include "mozilla/dom/PClientSourceParent.h"
 
 namespace mozilla {
 namespace dom {
 
+class ClientHandleParent;
+class ClientManagerService;
+
 class ClientSourceParent final : public PClientSourceParent
 {
+  ClientInfo mClientInfo;
+  RefPtr<ClientManagerService> mService;
+  nsTArray<ClientHandleParent*> mHandleList;
+
   // PClientSourceParent
   IPCResult
   RecvTeardown() override;
 
   void
   ActorDestroy(ActorDestroyReason aReason) override;
 
   PClientSourceOpParent*
   AllocPClientSourceOpParent(const ClientOpConstructorArgs& aArgs) override;
 
   bool
   DeallocPClientSourceOpParent(PClientSourceOpParent* aActor) override;
 
 public:
   explicit ClientSourceParent(const ClientSourceConstructorArgs& aArgs);
   ~ClientSourceParent();
+
+  const ClientInfo&
+  Info() const;
+
+  void
+  AttachHandle(ClientHandleParent* aClientSource);
+
+  void
+  DetachHandle(ClientHandleParent* aClientSource);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // _mozilla_dom_ClientSourceParent_h
--- a/dom/clients/manager/ClientThing.h
+++ b/dom/clients/manager/ClientThing.h
@@ -94,15 +94,20 @@ public:
   // Clear the weak references between the thing and its IPC actor.
   void
   RevokeActor(ActorType* aActor)
   {
     MOZ_DIAGNOSTIC_ASSERT(mActor);
     MOZ_DIAGNOSTIC_ASSERT(mActor == aActor);
     mActor->RevokeOwner(this);
     mActor = nullptr;
+
+    // Also consider the ClientThing shutdown.  We simply set the flag
+    // instead of calling ShutdownThing() to avoid calling MaybeStartTeardown()
+    // on the destroyed actor.
+    mShutdown = true;
   }
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // _mozilla_dom_ClientThing_h
--- a/dom/clients/manager/moz.build
+++ b/dom/clients/manager/moz.build
@@ -1,40 +1,47 @@
 # -*- 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 += [
+  'ClientHandle.h',
   'ClientInfo.h',
   'ClientIPCUtils.h',
+  'ClientManager.h',
   'ClientManagerActors.h',
   'ClientOpenWindowOpActors.h',
   'ClientOpPromise.h',
+  'ClientSource.h',
   'ClientState.h',
   'ClientThing.h',
 ]
 
 UNIFIED_SOURCES += [
+  'ClientHandle.cpp',
   'ClientHandleChild.cpp',
   'ClientHandleOpChild.cpp',
   'ClientHandleOpParent.cpp',
   'ClientHandleParent.cpp',
   'ClientInfo.cpp',
+  'ClientManager.cpp',
   'ClientManagerActors.cpp',
   'ClientManagerChild.cpp',
   'ClientManagerOpChild.cpp',
   'ClientManagerOpParent.cpp',
   'ClientManagerParent.cpp',
+  'ClientManagerService.cpp',
   'ClientNavigateOpChild.cpp',
   'ClientNavigateOpParent.cpp',
   'ClientOpenWindowOpActors.cpp',
   'ClientOpenWindowOpChild.cpp',
   'ClientOpenWindowOpParent.cpp',
+  'ClientSource.cpp',
   'ClientSourceChild.cpp',
   'ClientSourceOpChild.cpp',
   'ClientSourceOpParent.cpp',
   'ClientSourceParent.cpp',
   'ClientState.cpp',
 ]
 
 IPDL_SOURCES += [
@@ -47,16 +54,17 @@ IPDL_SOURCES += [
   'PClientOpenWindowOp.ipdl',
   'PClientSource.ipdl',
   'PClientSourceOp.ipdl',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
+  '/dom/workers',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 MOCHITEST_MANIFESTS += [
 ]
 
 BROWSER_CHROME_MANIFESTS += [
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -17,16 +17,17 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ProcessHangMonitorIPC.h"
 #include "mozilla/Unused.h"
 #include "mozilla/TelemetryIPC.h"
 #include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h"
 #include "mozilla/docshell/OfflineCacheUpdateChild.h"
+#include "mozilla/dom/ClientManager.h"
 #include "mozilla/dom/ClientOpenWindowOpActors.h"
 #include "mozilla/dom/ContentBridgeChild.h"
 #include "mozilla/dom/ContentBridgeParent.h"
 #include "mozilla/dom/VideoDecoderManagerChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/ExternalHelperAppChild.h"
@@ -1149,16 +1150,18 @@ ContentChild::InitXPCOM(const XPCOMInitD
   BackgroundChild::Startup();
 
   PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread();
   if (NS_WARN_IF(!actorChild)) {
     MOZ_ASSERT_UNREACHABLE("PBackground init can't fail at this point");
     return;
   }
 
+  ClientManager::Startup();
+
   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/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -29,16 +29,17 @@
 #include "mozilla/a11y/Compatibility.h"
 #endif
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/DataStorage.h"
 #include "mozilla/devtools/HeapSnapshotTempFileHelperParent.h"
 #include "mozilla/docshell/OfflineCacheUpdateParent.h"
+#include "mozilla/dom/ClientManager.h"
 #include "mozilla/dom/ClientOpenWindowOpActors.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/FileCreatorHelper.h"
 #include "mozilla/dom/FileSystemSecurity.h"
 #include "mozilla/dom/IPCBlobUtils.h"
 #include "mozilla/dom/ExternalHelperAppParent.h"
@@ -623,16 +624,17 @@ ContentParent::StartUp()
   }
 
   // Note: This reporter measures all ContentParents.
   RegisterStrongMemoryReporter(new ContentParentsMemoryReporter());
 
   mozilla::dom::time::InitializeDateCacheCleaner();
 
   BackgroundChild::Startup();
+  ClientManager::Startup();
 
   sDisableUnsafeCPOWWarnings = PR_GetEnv("DISABLE_UNSAFE_CPOW_WARNINGS");
 
 #if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
   sSandboxBrokerPolicyFactory = MakeUnique<SandboxBrokerPolicyFactory>();
 #endif
 }
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/regress/oom-wasm-streaming.js
@@ -0,0 +1,12 @@
+try {
+    WebAssembly.compileStreaming();
+} catch (err) {
+    assertEq(String(err).indexOf("not supported with --no-threads") !== -1, true);
+    quit();
+}
+if (!this.oomAfterAllocations)
+    quit();
+oomAfterAllocations(1, 2);
+var x = wasmTextToBinary('(module (func (export "run") (result i32) i32.const 42))');
+WebAssembly.compileStreaming(x);
+drainJobQueue();
--- a/js/src/vm/AsyncFunction.cpp
+++ b/js/src/vm/AsyncFunction.cpp
@@ -130,18 +130,17 @@ js::WrapAsyncFunctionWithProto(JSContext
     uint16_t length;
     if (!JSFunction::getLength(cx, unwrapped, &length))
         return nullptr;
 
     // Steps 3 (partially).
     RootedFunction wrapped(cx, NewFunctionWithProto(cx, WrappedAsyncFunction, length,
                                                     JSFunction::NATIVE_FUN, nullptr,
                                                     funName, proto,
-                                                    AllocKind::FUNCTION_EXTENDED,
-                                                    TenuredObject));
+                                                    AllocKind::FUNCTION_EXTENDED));
     if (!wrapped)
         return nullptr;
 
     if (unwrapped->hasCompileTimeName())
         wrapped->setCompileTimeName(unwrapped->compileTimeName());
 
     // Link them to each other to make GetWrappedAsyncFunction and
     // GetUnwrappedAsyncFunction work.
--- a/js/src/vm/AsyncIteration.cpp
+++ b/js/src/vm/AsyncIteration.cpp
@@ -75,18 +75,17 @@ js::WrapAsyncGeneratorWithProto(JSContex
     RootedAtom funName(cx, unwrapped->explicitName());
     uint16_t length;
     if (!JSFunction::getLength(cx, unwrapped, &length))
         return nullptr;
 
     RootedFunction wrapped(cx, NewFunctionWithProto(cx, WrappedAsyncGenerator, length,
                                                     JSFunction::NATIVE_FUN, nullptr,
                                                     funName, proto,
-                                                    AllocKind::FUNCTION_EXTENDED,
-                                                    TenuredObject));
+                                                    AllocKind::FUNCTION_EXTENDED));
     if (!wrapped)
         return nullptr;
 
     if (unwrapped->hasCompileTimeName())
         wrapped->setCompileTimeName(unwrapped->compileTimeName());
 
     // Link them to each other to make GetWrappedAsyncGenerator and
     // GetUnwrappedAsyncGenerator work.
--- a/js/src/wasm/WasmJS.cpp
+++ b/js/src/wasm/WasmJS.cpp
@@ -1847,26 +1847,34 @@ WebAssembly_toSource(JSContext* cx, unsi
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     args.rval().setString(cx->names().WebAssembly);
     return true;
 }
 #endif
 
 static bool
+RejectWithPendingException(JSContext* cx, Handle<PromiseObject*> promise)
+{
+    if (!cx->isExceptionPending())
+        return false;
+
+    RootedValue rejectionValue(cx);
+    if (!GetAndClearException(cx, &rejectionValue))
+        return false;
+
+    return PromiseObject::reject(cx, promise, rejectionValue);
+}
+
+static bool
 Reject(JSContext* cx, const CompileArgs& args, UniqueChars error, Handle<PromiseObject*> promise)
 {
     if (!error) {
         ReportOutOfMemory(cx);
-
-        RootedValue rejectionValue(cx);
-        if (!cx->getPendingException(&rejectionValue))
-            return false;
-
-        return PromiseObject::reject(cx, promise, rejectionValue);
+        return RejectWithPendingException(cx, promise);
     }
 
     RootedObject stack(cx, promise->allocationSite());
     RootedString filename(cx, JS_NewStringCopyZ(cx, args.scriptedCaller.filename.get()));
     if (!filename)
         return false;
 
     unsigned line = args.scriptedCaller.line;
@@ -1888,29 +1896,16 @@ Reject(JSContext* cx, const CompileArgs&
     if (!errorObj)
         return false;
 
     RootedValue rejectionValue(cx, ObjectValue(*errorObj));
     return PromiseObject::reject(cx, promise, rejectionValue);
 }
 
 static bool
-RejectWithPendingException(JSContext* cx, Handle<PromiseObject*> promise)
-{
-    if (!cx->isExceptionPending())
-        return false;
-
-    RootedValue rejectionValue(cx);
-    if (!GetAndClearException(cx, &rejectionValue))
-        return false;
-
-    return PromiseObject::reject(cx, promise, rejectionValue);
-}
-
-static bool
 Resolve(JSContext* cx, Module& module, const CompileArgs& compileArgs,
         Handle<PromiseObject*> promise, bool instantiate, HandleObject importObj)
 {
     RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmModule).toObject());
     RootedObject moduleObj(cx, WasmModuleObject::create(cx, module, proto));
     if (!moduleObj)
         return RejectWithPendingException(cx, promise);
 
@@ -2517,17 +2512,17 @@ ResolveResponse(JSContext* cx, CallArgs 
 
     RootedFunction onResolved(cx, NewNativeFunction(cx, ResolveResponse_OnFulfilled, 1, nullptr,
                                                     gc::AllocKind::FUNCTION_EXTENDED));
     if (!onResolved)
         return false;
 
     RootedFunction onRejected(cx, NewNativeFunction(cx, ResolveResponse_OnRejected, 1, nullptr,
                                                     gc::AllocKind::FUNCTION_EXTENDED));
-    if (!onResolved)
+    if (!onRejected)
         return false;
 
     onResolved->setExtendedSlot(0, ObjectValue(*closure));
     onRejected->setExtendedSlot(0, ObjectValue(*closure));
 
     RootedObject resolve(cx, PromiseObject::unforgeableResolve(cx, callArgs.get(0)));
     if (!resolve)
         return false;