Bug 1095754 - In the content process provide a way to track and access PluginInstanceParent objects from PluginWidgetChild. r=aklotz

This commit is contained in:
Jim Mathies 2015-01-29 13:41:53 -06:00
parent ef2806c191
commit 88d8d1f2b0
4 changed files with 114 additions and 18 deletions

View File

@ -43,7 +43,8 @@
#include <windowsx.h> #include <windowsx.h>
#include "gfxWindowsPlatform.h" #include "gfxWindowsPlatform.h"
#include "mozilla/plugins/PluginSurfaceParent.h" #include "mozilla/plugins/PluginSurfaceParent.h"
#include "nsClassHashtable.h"
#include "nsHashKeys.h"
// Plugin focus event for widget. // Plugin focus event for widget.
extern const wchar_t* kOOPPPluginFocusEventId; extern const wchar_t* kOOPPPluginFocusEventId;
UINT gOOPPPluginFocusEvent = UINT gOOPPPluginFocusEvent =
@ -73,6 +74,29 @@ StreamNotifyParent::RecvRedirectNotifyResponse(const bool& allow)
return true; 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, PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
NPP npp, NPP npp,
const nsCString& aMimeType, const nsCString& aMimeType,
@ -95,6 +119,11 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
, mShColorSpace(nullptr) , mShColorSpace(nullptr)
#endif #endif
{ {
#if defined(OS_WIN)
if (!sPluginInstanceList) {
sPluginInstanceList = new nsClassHashtable<nsVoidPtrHashKey, PluginInstanceParent>();
}
#endif
} }
PluginInstanceParent::~PluginInstanceParent() PluginInstanceParent::~PluginInstanceParent()
@ -1756,30 +1785,60 @@ PluginInstanceParent::PluginWindowHookProc(HWND hWnd,
void void
PluginInstanceParent::SubclassPluginWindow(HWND aWnd) PluginInstanceParent::SubclassPluginWindow(HWND aWnd)
{ {
if (XRE_GetProcessType() == GeckoProcessType_Content) { if ((aWnd && mPluginHWND == aWnd) || (!aWnd && mPluginHWND)) {
mPluginHWND = aWnd; // now a remote window, we can't subclass this return;
mPluginWndProc = nullptr;
return;
} }
NS_ASSERTION(!(mPluginHWND && aWnd != mPluginHWND),
"PluginInstanceParent::SubclassPluginWindow hwnd is not our window!");
if (!mPluginHWND) { #if defined(XP_WIN)
mPluginHWND = aWnd; if (XRE_GetProcessType() == GeckoProcessType_Content) {
mPluginWndProc = if (!aWnd) {
(WNDPROC)::SetWindowLongPtrA(mPluginHWND, GWLP_WNDPROC, NS_WARNING("PluginInstanceParent::SubclassPluginWindow unexpected null window");
reinterpret_cast<LONG_PTR>(PluginWindowHookProc)); return;
DebugOnly<bool> bRes = ::SetPropW(mPluginHWND, kPluginInstanceParentProperty, this); }
NS_ASSERTION(mPluginWndProc, mPluginHWND = aWnd; // now a remote window, we can't subclass this
"PluginInstanceParent::SubclassPluginWindow failed to set subclass!"); mPluginWndProc = nullptr;
NS_ASSERTION(bRes, // Note sPluginInstanceList wil delete 'this' if we do not remove
"PluginInstanceParent::SubclassPluginWindow failed to set prop!"); // 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 void
PluginInstanceParent::UnsubclassPluginWindow() 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) { if (mPluginHWND && mPluginWndProc) {
::SetWindowLongPtrA(mPluginHWND, GWLP_WNDPROC, ::SetWindowLongPtrA(mPluginHWND, GWLP_WNDPROC,
reinterpret_cast<LONG_PTR>(mPluginWndProc)); reinterpret_cast<LONG_PTR>(mPluginWndProc));

View File

@ -51,6 +51,15 @@ class PluginInstanceParent : public PPluginInstanceParent
friend class PluginStreamParent; friend class PluginStreamParent;
friend class StreamNotifyParent; 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: public:
PluginInstanceParent(PluginModuleParent* parent, PluginInstanceParent(PluginModuleParent* parent,
NPP npp, NPP npp,

View File

@ -4,6 +4,13 @@
#include "mozilla/plugins/PluginWidgetChild.h" #include "mozilla/plugins/PluginWidgetChild.h"
#include "PluginWidgetProxy.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 mozilla {
namespace plugins { namespace plugins {
@ -28,6 +35,26 @@ PluginWidgetChild::ActorDestroy(ActorDestroyReason aWhy)
mWidget = nullptr; 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 plugins
} // namespace mozilla } // namespace mozilla

View File

@ -19,6 +19,7 @@ public:
PluginWidgetChild(); PluginWidgetChild();
virtual ~PluginWidgetChild(); virtual ~PluginWidgetChild();
virtual bool RecvUpdateWindow(const uintptr_t& aChildId) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
mozilla::widget::PluginWidgetProxy* mWidget; mozilla::widget::PluginWidgetProxy* mWidget;