Bug 1352573 (part 1) - Convert FlashThrottleAsyncMsg from a ChildAsyncCall to a CancelableRunnable. r=bsmedberg.
authorNicholas Nethercote <nnethercote@mozilla.com>
Wed, 19 Jul 2017 17:22:05 +1000
changeset 419499 6d4b5196987ab37beb9a81b6c46ef2ecbec27609
parent 419498 3923ce220df31c0a1fb589158f1d2a3f40a93aef
child 419500 50f76943b7cef407c6a2b2da994f91354a1d1d23
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs1352573
milestone56.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 1352573 (part 1) - Convert FlashThrottleAsyncMsg from a ChildAsyncCall to a CancelableRunnable. r=bsmedberg. This requires adding mPendingFlashThrottleMsgs to PluginInstanceChild. It also requires adding FlashThrottleMsg::mInstance, and a FlashThrottleMsg::Cancel() function that nulls mInstance.
dom/plugins/ipc/PluginInstanceChild.cpp
dom/plugins/ipc/PluginInstanceChild.h
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -2334,57 +2334,67 @@ PluginInstanceChild::SetupFlashMsgThrott
     }
     else {
         // Already setup through quirks and the subclass.
         return;
     }
 }
 
 WNDPROC
-PluginInstanceChild::FlashThrottleAsyncMsg::GetProc()
+PluginInstanceChild::FlashThrottleMsg::GetProc()
 {
     if (mInstance) {
         return mWindowed ? mInstance->mPluginWndProc :
                            mInstance->mWinlessThrottleOldWndProc;
     }
     return nullptr;
 }
 
 NS_IMETHODIMP
-PluginInstanceChild::FlashThrottleAsyncMsg::Run()
+PluginInstanceChild::FlashThrottleMsg::Run()
 {
-    RemoveFromAsyncList();
+    if (!mInstance) {
+        return NS_OK;
+    }
+
+    mInstance->mPendingFlashThrottleMsgs.RemoveElement(this);
 
     // GetProc() checks mInstance, and pulls the procedure from
     // PluginInstanceChild. We don't transport sub-class procedure
-    // ptrs around in FlashThrottleAsyncMsg msgs.
+    // ptrs around in FlashThrottleMsg msgs.
     if (!GetProc())
         return NS_OK;
 
     // deliver the event to flash
     CallWindowProc(GetProc(), GetWnd(), GetMsg(), GetWParam(), GetLParam());
     return NS_OK;
 }
 
+nsresult
+PluginInstanceChild::FlashThrottleMsg::Cancel()
+{
+    MOZ_ASSERT(mInstance);
+    mInstance = nullptr;
+    return NS_OK;
+}
+
 void
 PluginInstanceChild::FlashThrottleMessage(HWND aWnd,
                                           UINT aMsg,
                                           WPARAM aWParam,
                                           LPARAM aLParam,
                                           bool isWindowed)
 {
-    // We reuse ChildAsyncCall so we get the cancelation work
-    // that's done in Destroy.
-    RefPtr<FlashThrottleAsyncMsg> task =
-        new FlashThrottleAsyncMsg(this, aWnd, aMsg, aWParam,
-                                  aLParam, isWindowed);
-    {
-        MutexAutoLock lock(mAsyncCallMutex);
-        mPendingAsyncCalls.AppendElement(task);
-    }
+    // We save a reference to the FlashThrottleMsg so we can cancel it in
+    // Destroy if it's still alive.
+    RefPtr<FlashThrottleMsg> task =
+        new FlashThrottleMsg(this, aWnd, aMsg, aWParam, aLParam, isWindowed);
+
+    mPendingFlashThrottleMsgs.AppendElement(task);
+
     MessageLoop::current()->PostDelayedTask(task.forget(),
                                             kFlashWMUSERMessageThrottleDelayMs);
 }
 
 #endif // OS_WIN
 
 mozilla::ipc::IPCResult
 PluginInstanceChild::AnswerSetPluginFocus()
@@ -4257,16 +4267,21 @@ PluginInstanceChild::Destroy()
     // PluginInstanceDestroyed call above.
     mCachedWindowActor = nullptr;
     mCachedElementActor = nullptr;
 
 #if defined(OS_WIN)
     DestroyWinlessPopupSurrogate();
     UnhookWinlessFlashThrottle();
     DestroyPluginWindow();
+
+    for (uint32_t i = 0; i < mPendingFlashThrottleMsgs.Length(); ++i) {
+        mPendingFlashThrottleMsgs[i]->Cancel();
+    }
+    mPendingFlashThrottleMsgs.Clear();
 #endif
 
     // Pending async calls are discarded, not delivered. This matches the
     // in-process behavior.
     for (uint32_t i = 0; i < mPendingAsyncCalls.Length(); ++i)
         mPendingAsyncCalls[i]->Cancel();
 
     mPendingAsyncCalls.Clear();
--- a/dom/plugins/ipc/PluginInstanceChild.h
+++ b/dom/plugins/ipc/PluginInstanceChild.h
@@ -343,41 +343,41 @@ private:
     static BOOL WINAPI ImmReleaseContextProc(HWND aWND, HIMC aIMC);
     static LONG WINAPI ImmGetCompositionStringProc(HIMC aIMC, DWORD aIndex,
                                                    LPVOID aBuf, DWORD aLen);
     static BOOL WINAPI ImmSetCandidateWindowProc(HIMC hIMC,
                                                  LPCANDIDATEFORM plCandidate);
     static BOOL WINAPI ImmNotifyIME(HIMC aIMC, DWORD aAction, DWORD aIndex,
                                     DWORD aValue);
 
-    class FlashThrottleAsyncMsg : public ChildAsyncCall
+    class FlashThrottleMsg : public CancelableRunnable
     {
       public:
-        FlashThrottleAsyncMsg();
-        FlashThrottleAsyncMsg(PluginInstanceChild* aInst,
-                              HWND aWnd, UINT aMsg,
-                              WPARAM aWParam, LPARAM aLParam,
-                              bool isWindowed)
-          : ChildAsyncCall(aInst, nullptr, nullptr),
+        FlashThrottleMsg(PluginInstanceChild* aInstance, HWND aWnd, UINT aMsg,
+                         WPARAM aWParam, LPARAM aLParam, bool isWindowed)
+          : CancelableRunnable("FlashThrottleMsg"),
+          mInstance(aInstance),
           mWnd(aWnd),
           mMsg(aMsg),
           mWParam(aWParam),
           mLParam(aLParam),
           mWindowed(isWindowed)
         {}
 
         NS_IMETHOD Run() override;
+        nsresult Cancel() override;
 
         WNDPROC GetProc();
         HWND GetWnd() { return mWnd; }
         UINT GetMsg() { return mMsg; }
         WPARAM GetWParam() { return mWParam; }
         LPARAM GetLParam() { return mLParam; }
 
       private:
+        PluginInstanceChild* mInstance;
         HWND                 mWnd;
         UINT                 mMsg;
         WPARAM               mWParam;
         LPARAM               mLParam;
         bool                 mWindowed;
     };
 
     bool ShouldPostKeyMessage(UINT message, WPARAM wParam, LPARAM lParam);
@@ -445,16 +445,19 @@ private:
     HWND mWinlessPopupSurrogateHWND;
     nsIntPoint mPluginSize;
     WNDPROC mWinlessThrottleOldWndProc;
     HWND mWinlessHiddenMsgHWND;
 #endif
 
     friend class ChildAsyncCall;
 
+#if defined(OS_WIN)
+    nsTArray<FlashThrottleMsg*> mPendingFlashThrottleMsgs;
+#endif
     Mutex mAsyncCallMutex;
     nsTArray<ChildAsyncCall*> mPendingAsyncCalls;
     nsTArray<nsAutoPtr<ChildTimer> > mTimers;
 
     /**
      * During destruction we enumerate all remaining scriptable objects and
      * invalidate/delete them. Enumeration can re-enter, so maintain a
      * hash separate from PluginModuleChild.mObjectMap.