Bug 1425975 P1 Add ClientHandle::OnDetach() which returns a MozPromise that resolves on actor destruction. r=asuth
☠☠ backed out by 2e0db1b48499 ☠ ☠
authorBen Kelly <ben@wanderview.com>
Fri, 22 Dec 2017 21:09:17 -0500
changeset 397367 b7ae11b5bce80e23a8edc94bf971608d7ff8cc24
parent 397366 9a124d96186ba2e7a431a12a44048b15c253c544
child 397368 acf4d61babab3a78c0f4d045a68bb102604d7437
push id98509
push userbkelly@mozilla.com
push dateSat, 23 Dec 2017 02:09:27 +0000
treeherdermozilla-inbound@e6f4a2d1df9a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1425975
milestone59.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 1425975 P1 Add ClientHandle::OnDetach() which returns a MozPromise that resolves on actor destruction. r=asuth
dom/clients/manager/ClientHandle.cpp
dom/clients/manager/ClientHandle.h
dom/clients/manager/ClientThing.h
--- a/dom/clients/manager/ClientHandle.cpp
+++ b/dom/clients/manager/ClientHandle.cpp
@@ -60,16 +60,26 @@ ClientHandle::StartOp(const ClientOpCons
   }, [promise] {
     promise->Reject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
   });
 
   RefPtr<ClientOpPromise> ref = promise.get();
   return ref.forget();
 }
 
+void
+ClientHandle::OnShutdownThing()
+{
+  NS_ASSERT_OWNINGTHREAD(ClientHandle);
+  if (!mDetachPromise) {
+    return;
+  }
+  mDetachPromise->Resolve(true, __func__);
+}
+
 ClientHandle::ClientHandle(ClientManager* aManager,
                            nsISerialEventTarget* aSerialEventTarget,
                            const ClientInfo& aClientInfo)
   : mManager(aManager)
   , mSerialEventTarget(aSerialEventTarget)
   , mClientInfo(aClientInfo)
 {
   MOZ_DIAGNOSTIC_ASSERT(mManager);
@@ -177,10 +187,26 @@ ClientHandle::PostMessage(StructuredClon
     }, [outerPromise](const ClientOpResult& aResult) {
       outerPromise->Reject(aResult.get_nsresult(), __func__);
     });
 
   ref = outerPromise.get();
   return ref.forget();
 }
 
+RefPtr<GenericPromise>
+ClientHandle::OnDetach()
+{
+  NS_ASSERT_OWNINGTHREAD(ClientSource);
+
+  if (!mDetachPromise) {
+    mDetachPromise = new GenericPromise::Private(__func__);
+    if (IsShutdown()) {
+      mDetachPromise->Resolve(true, __func__);
+    }
+  }
+
+  RefPtr<GenericPromise> ref(mDetachPromise);
+  return Move(ref);
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/clients/manager/ClientHandle.h
+++ b/dom/clients/manager/ClientHandle.h
@@ -37,26 +37,31 @@ class StructuredCloneData;
 // is destroyed, but this could be added in the future.
 class ClientHandle final : public ClientThing<ClientHandleChild>
 {
   friend class ClientManager;
   friend class ClientHandleChild;
 
   RefPtr<ClientManager> mManager;
   nsCOMPtr<nsISerialEventTarget> mSerialEventTarget;
+  RefPtr<GenericPromise::Private> mDetachPromise;
   ClientInfo mClientInfo;
 
   ~ClientHandle();
 
   void
   Shutdown();
 
   already_AddRefed<ClientOpPromise>
   StartOp(const ClientOpConstructorArgs& aArgs);
 
+  // ClientThing interface
+  void
+  OnShutdownThing() override;
+
   // Private methods called by ClientHandleChild
   void
   ExecutionReady(const ClientInfo& aClientInfo);
 
   // Private methods called by ClientManager
   ClientHandle(ClientManager* aManager,
                nsISerialEventTarget* aSerialEventTarget,
                const ClientInfo& aClientInfo);
@@ -85,15 +90,26 @@ public:
   // dispatched to the Client's navigator.serviceWorker event target.  The
   // returned promise will resolve if the MessageEvent is dispatched or if
   // it triggers an error handled in the Client's context.  Other errors
   // will result in the promise rejecting.
   RefPtr<GenericPromise>
   PostMessage(ipc::StructuredCloneData& aData,
               const ServiceWorkerDescriptor& aSource);
 
+  // Return a Promise that resolves when the ClientHandle object is detached
+  // from its remote actors.  This will happen if the ClientSource is destroyed
+  // and triggers the cleanup of the handle actors.  It will also naturally
+  // happen when the ClientHandle is de-referenced and tears down its own
+  // actors.
+  //
+  // Note: This method can only be called on the ClientHandle owning thread,
+  //       but the MozPromise lets you Then() to another thread.
+  RefPtr<GenericPromise>
+  OnDetach();
+
   NS_INLINE_DECL_REFCOUNTING(ClientHandle);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // _mozilla_dom_ClientHandle_h
--- a/dom/clients/manager/ClientThing.h
+++ b/dom/clients/manager/ClientThing.h
@@ -85,31 +85,42 @@ protected:
 
     // If we are shutdown before the actor, then clear the weak references
     // between the actor and the thing.
     if (mActor) {
       mActor->RevokeOwner(this);
       mActor->MaybeStartTeardown();
       mActor = nullptr;
     }
+
+    OnShutdownThing();
+  }
+
+  // Allow extending classes to take action when shutdown.
+  virtual void
+  OnShutdownThing()
+  {
+    // by default do nothing
   }
 
 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;
+
+    OnShutdownThing();
   }
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // _mozilla_dom_ClientThing_h