From 88d8d1f2b077e8b0d8a7494ec24de30d10111b55 Mon Sep 17 00:00:00 2001 From: Jim Mathies Date: Thu, 29 Jan 2015 13:41:53 -0600 Subject: [PATCH] Bug 1095754 - In the content process provide a way to track and access PluginInstanceParent objects from PluginWidgetChild. r=aklotz --- dom/plugins/ipc/PluginInstanceParent.cpp | 95 +++++++++++++++++++----- dom/plugins/ipc/PluginInstanceParent.h | 9 +++ dom/plugins/ipc/PluginWidgetChild.cpp | 27 +++++++ dom/plugins/ipc/PluginWidgetChild.h | 1 + 4 files changed, 114 insertions(+), 18 deletions(-) diff --git a/dom/plugins/ipc/PluginInstanceParent.cpp b/dom/plugins/ipc/PluginInstanceParent.cpp index 438a037a652..6f83bdf70e1 100644 --- a/dom/plugins/ipc/PluginInstanceParent.cpp +++ b/dom/plugins/ipc/PluginInstanceParent.cpp @@ -43,7 +43,8 @@ #include #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 = @@ -73,6 +74,29 @@ StreamNotifyParent::RecvRedirectNotifyResponse(const bool& 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* 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, @@ -95,6 +119,11 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent, , mShColorSpace(nullptr) #endif { +#if defined(OS_WIN) + if (!sPluginInstanceList) { + sPluginInstanceList = new nsClassHashtable(); + } +#endif } PluginInstanceParent::~PluginInstanceParent() @@ -1756,30 +1785,60 @@ PluginInstanceParent::PluginWindowHookProc(HWND hWnd, 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(PluginWindowHookProc)); - DebugOnly 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(PluginWindowHookProc)); + DebugOnly 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 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(mPluginWndProc)); diff --git a/dom/plugins/ipc/PluginInstanceParent.h b/dom/plugins/ipc/PluginInstanceParent.h index 784e656a741..d5423e2e486 100644 --- a/dom/plugins/ipc/PluginInstanceParent.h +++ b/dom/plugins/ipc/PluginInstanceParent.h @@ -51,6 +51,15 @@ class PluginInstanceParent : public PPluginInstanceParent 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, diff --git a/dom/plugins/ipc/PluginWidgetChild.cpp b/dom/plugins/ipc/PluginWidgetChild.cpp index d689da81e33..e2859619b0d 100644 --- a/dom/plugins/ipc/PluginWidgetChild.cpp +++ b/dom/plugins/ipc/PluginWidgetChild.cpp @@ -4,6 +4,13 @@ #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 { @@ -28,6 +35,26 @@ PluginWidgetChild::ActorDestroy(ActorDestroyReason aWhy) 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 diff --git a/dom/plugins/ipc/PluginWidgetChild.h b/dom/plugins/ipc/PluginWidgetChild.h index 22aa9c171cd..1a53ab05361 100644 --- a/dom/plugins/ipc/PluginWidgetChild.h +++ b/dom/plugins/ipc/PluginWidgetChild.h @@ -19,6 +19,7 @@ public: PluginWidgetChild(); virtual ~PluginWidgetChild(); + virtual bool RecvUpdateWindow(const uintptr_t& aChildId) MOZ_OVERRIDE; virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; mozilla::widget::PluginWidgetProxy* mWidget;