Bug 1095754 - In the content process provide a way to track and access PluginInstanceParent objects from PluginWidgetChild. r=aklotz
authorJim Mathies <jmathies@mozilla.com>
Thu, 29 Jan 2015 13:41:53 -0600
changeset 226582 fc53ac4a756e02dfe8d5b7fc756839839e9dc466
parent 226581 c05f8b0ce6bb97b38d858ce60c23080fc34aa262
child 226583 55d0da4cbed3636454baf30667e3427877a6867e
push id28200
push userkwierso@gmail.com
push dateThu, 29 Jan 2015 23:01:46 +0000
treeherdermozilla-central@4380ed39de3a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaklotz
bugs1095754
milestone38.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 1095754 - In the content process provide a way to track and access PluginInstanceParent objects from PluginWidgetChild. r=aklotz
dom/plugins/ipc/PluginInstanceParent.cpp
dom/plugins/ipc/PluginInstanceParent.h
dom/plugins/ipc/PluginWidgetChild.cpp
dom/plugins/ipc/PluginWidgetChild.h
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -38,17 +38,18 @@
 #ifdef XP_MACOSX
 #include "MacIOSurfaceImage.h"
 #endif
 
 #if defined(OS_WIN)
 #include <windowsx.h>
 #include "gfxWindowsPlatform.h"
 #include "mozilla/plugins/PluginSurfaceParent.h"
-
+#include "nsClassHashtable.h"
+#include "nsHashKeys.h"
 // Plugin focus event for widget.
 extern const wchar_t* kOOPPPluginFocusEventId;
 UINT gOOPPPluginFocusEvent =
     RegisterWindowMessage(kOOPPPluginFocusEventId);
 extern const wchar_t* kFlashFullscreenClass;
 #elif defined(MOZ_WIDGET_GTK)
 #include <gdk/gdk.h>
 #elif defined(XP_MACOSX)
@@ -68,16 +69,39 @@ StreamNotifyParent::ActorDestroy(ActorDe
 bool
 StreamNotifyParent::RecvRedirectNotifyResponse(const bool& allow)
 {
   PluginInstanceParent* instance = static_cast<PluginInstanceParent*>(Manager());
   instance->mNPNIface->urlredirectresponse(instance->mNPP, this, static_cast<NPBool>(allow));
   return true;
 }
 
+#if defined(XP_WIN)
+namespace mozilla {
+namespace plugins {
+/**
+ * e10s specific, used in cross referencing hwnds with plugin instances so we
+ * can access methods here from PluginWidgetChild.
+ */
+static nsClassHashtable<nsVoidPtrHashKey, PluginInstanceParent>* sPluginInstanceList;
+
+// static
+PluginInstanceParent*
+PluginInstanceParent::LookupPluginInstanceByID(uintptr_t aId)
+{
+    MOZ_ASSERT(NS_IsMainThread());
+    if (sPluginInstanceList) {
+        return sPluginInstanceList->Get((void*)aId);
+    }
+    return nullptr;
+}
+}
+}
+#endif
+
 PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
                                            NPP npp,
                                            const nsCString& aMimeType,
                                            const NPNetscapeFuncs* npniface)
     : mParent(parent)
     , mSurrogate(PluginAsyncSurrogate::Cast(npp))
     , mUseSurrogate(true)
     , mNPP(npp)
@@ -90,16 +114,21 @@ PluginInstanceParent::PluginInstancePare
     , mNestedEventState(false)
 #endif // defined(XP_WIN)
 #if defined(XP_MACOSX)
     , mShWidth(0)
     , mShHeight(0)
     , mShColorSpace(nullptr)
 #endif
 {
+#if defined(OS_WIN)
+    if (!sPluginInstanceList) {
+        sPluginInstanceList = new nsClassHashtable<nsVoidPtrHashKey, PluginInstanceParent>();
+    }
+#endif
 }
 
 PluginInstanceParent::~PluginInstanceParent()
 {
     if (mNPP)
         mNPP->pdata = nullptr;
 
 #if defined(OS_WIN)
@@ -1751,40 +1780,70 @@ PluginInstanceParent::PluginWindowHookPr
     }
     return ::CallWindowProc(self->mPluginWndProc, hWnd, message, wParam,
                             lParam);
 }
 
 void
 PluginInstanceParent::SubclassPluginWindow(HWND aWnd)
 {
-    if (XRE_GetProcessType() == GeckoProcessType_Content) {
-      mPluginHWND = aWnd; // now a remote window, we can't subclass this
-      mPluginWndProc = nullptr;
-      return;
+    if ((aWnd && mPluginHWND == aWnd) || (!aWnd && mPluginHWND)) {
+        return;
     }
-    NS_ASSERTION(!(mPluginHWND && aWnd != mPluginHWND),
-      "PluginInstanceParent::SubclassPluginWindow hwnd is not our window!");
 
-    if (!mPluginHWND) {
-        mPluginHWND = aWnd;
-        mPluginWndProc =
-            (WNDPROC)::SetWindowLongPtrA(mPluginHWND, GWLP_WNDPROC,
-                         reinterpret_cast<LONG_PTR>(PluginWindowHookProc));
-        DebugOnly<bool> bRes = ::SetPropW(mPluginHWND, kPluginInstanceParentProperty, this);
-        NS_ASSERTION(mPluginWndProc,
-          "PluginInstanceParent::SubclassPluginWindow failed to set subclass!");
-        NS_ASSERTION(bRes,
-          "PluginInstanceParent::SubclassPluginWindow failed to set prop!");
-   }
+#if defined(XP_WIN)
+    if (XRE_GetProcessType() == GeckoProcessType_Content) {
+        if (!aWnd) {
+            NS_WARNING("PluginInstanceParent::SubclassPluginWindow unexpected null window");
+            return;
+        }
+        mPluginHWND = aWnd; // now a remote window, we can't subclass this
+        mPluginWndProc = nullptr;
+        // Note sPluginInstanceList wil delete 'this' if we do not remove
+        // it on shutdown.
+        sPluginInstanceList->Put((void*)mPluginHWND, this);
+        return;
+    }
+#endif
+
+    NS_ASSERTION(!(mPluginHWND && aWnd != mPluginHWND),
+        "PluginInstanceParent::SubclassPluginWindow hwnd is not our window!");
+
+    mPluginHWND = aWnd;
+    mPluginWndProc =
+        (WNDPROC)::SetWindowLongPtrA(mPluginHWND, GWLP_WNDPROC,
+            reinterpret_cast<LONG_PTR>(PluginWindowHookProc));
+    DebugOnly<bool> bRes = ::SetPropW(mPluginHWND, kPluginInstanceParentProperty, this);
+    NS_ASSERTION(mPluginWndProc,
+        "PluginInstanceParent::SubclassPluginWindow failed to set subclass!");
+    NS_ASSERTION(bRes,
+        "PluginInstanceParent::SubclassPluginWindow failed to set prop!");
 }
 
 void
 PluginInstanceParent::UnsubclassPluginWindow()
 {
+#if defined(XP_WIN)
+    if (XRE_GetProcessType() == GeckoProcessType_Content) {
+        if (mPluginHWND) {
+            // Remove 'this' from the plugin list safely
+            nsAutoPtr<PluginInstanceParent> tmp;
+            MOZ_ASSERT(sPluginInstanceList);
+            sPluginInstanceList->RemoveAndForget((void*)mPluginHWND, tmp);
+            tmp.forget();
+            if (!sPluginInstanceList->Count()) {
+                delete sPluginInstanceList;
+                sPluginInstanceList = nullptr;
+            }
+        }
+        mPluginHWND = nullptr;
+        return;
+    }
+#endif
+
     if (mPluginHWND && mPluginWndProc) {
         ::SetWindowLongPtrA(mPluginHWND, GWLP_WNDPROC,
                             reinterpret_cast<LONG_PTR>(mPluginWndProc));
 
         ::RemovePropW(mPluginHWND, kPluginInstanceParentProperty);
 
         mPluginWndProc = nullptr;
         mPluginHWND = nullptr;
--- a/dom/plugins/ipc/PluginInstanceParent.h
+++ b/dom/plugins/ipc/PluginInstanceParent.h
@@ -46,16 +46,25 @@ class PluginModuleParent;
 class PluginInstanceParent : public PPluginInstanceParent
                            , public PluginDataResolver
 {
     friend class PluginModuleParent;
     friend class BrowserStreamParent;
     friend class PluginStreamParent;
     friend class StreamNotifyParent;
 
+#if defined(XP_WIN)
+public:
+    /**
+     * Helper method for looking up instances based on a supplied id.
+     */
+    static PluginInstanceParent*
+    LookupPluginInstanceByID(uintptr_t aId);
+#endif // defined(XP_WIN)
+
 public:
     PluginInstanceParent(PluginModuleParent* parent,
                          NPP npp,
                          const nsCString& mimeType,
                          const NPNetscapeFuncs* npniface);
 
     virtual ~PluginInstanceParent();
 
--- a/dom/plugins/ipc/PluginWidgetChild.cpp
+++ b/dom/plugins/ipc/PluginWidgetChild.cpp
@@ -1,14 +1,21 @@
 /* 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/plugins/PluginWidgetChild.h"
 #include "PluginWidgetProxy.h"
+#include "mozilla/DebugOnly.h"
+#include "nsDebug.h"
+
+#if defined(XP_WIN)
+#include "mozilla/plugins/PluginInstanceParent.h"
+using mozilla::plugins::PluginInstanceParent;
+#endif
 
 namespace mozilla {
 namespace plugins {
 
 PluginWidgetChild::PluginWidgetChild() :
   mWidget(nullptr)
 {
   MOZ_COUNT_CTOR(PluginWidgetChild);
@@ -23,13 +30,33 @@ void
 PluginWidgetChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   if (mWidget) {
     mWidget->ChannelDestroyed();
   }
   mWidget = nullptr;
 }
 
+bool
+PluginWidgetChild::RecvUpdateWindow(const uintptr_t& aChildId)
+{
+#if defined(XP_WIN)
+  NS_ASSERTION(aChildId, "Expected child hwnd value for remote plugin instance.");
+  PluginInstanceParent* parentInstance =
+    PluginInstanceParent::LookupPluginInstanceByID(aChildId);
+  NS_ASSERTION(parentInstance, "Expected matching plugin instance");
+  if (parentInstance) {
+    // sync! update call to the plugin instance that forces the
+    // plugin to paint its child window.
+    parentInstance->CallUpdateWindow();
+  }
+  return true;
+#else
+  NS_NOTREACHED("PluginWidgetChild::RecvUpdateWindow calls unexpected on this platform.");
+  return false;
+#endif
+}
+
 } // namespace plugins
 } // namespace mozilla
 
 
 
--- a/dom/plugins/ipc/PluginWidgetChild.h
+++ b/dom/plugins/ipc/PluginWidgetChild.h
@@ -14,16 +14,17 @@ class PluginWidgetProxy;
 namespace plugins {
 
 class PluginWidgetChild : public PPluginWidgetChild
 {
 public:
   PluginWidgetChild();
   virtual ~PluginWidgetChild();
 
+  virtual bool RecvUpdateWindow(const uintptr_t& aChildId) MOZ_OVERRIDE;
   virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
   mozilla::widget::PluginWidgetProxy* mWidget;
 };
 
 } // namespace plugins
 } // namespace mozilla