Bug 1425975 P1 Add ClientHandle::OnDetach() which returns a MozPromise that resolves on actor destruction. r=asuth
authorBen Kelly <ben@wanderview.com>
Fri, 05 Jan 2018 12:10:20 -0500
changeset 449765 21042078d8070e0e704ebacfc7abd20968d42fda
parent 449764 9cd8ce4f59dd2e9ffbffb74107227e10d0fa0910
child 449766 ef7cf1394d0fd6fbd9e97bed3cc705cc439107a5
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [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