Bug 1182411 Part 2: Change winless popup surrogate to have its parent set in the chrome process. r=jimm

The creation of the surrogate native window in the child NPAPI process was
failing when then sandbox was at low integrity, because the parent is from the
chrome process, so at medium integrity.
Instead of making an IPC call to get the parent, we now create the window upfront
and send it in an IPC message to be parented in the chrome process.
This is done with asynchronous messaging.
This commit is contained in:
Bob Owen 2015-08-12 16:00:26 +01:00
parent 4b8fd6e69b
commit 01f693c138
14 changed files with 312 additions and 98 deletions

View File

@ -144,6 +144,12 @@ parent:
*/ */
sync GetWidgetNativeData() returns (WindowsHandle value); sync GetWidgetNativeData() returns (WindowsHandle value);
/**
* Sends an NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW to be adopted by the
* widget's shareable window on the chrome side. Only used on Windows.
*/
async SetNativeChildOfShareableWindow(uintptr_t childWindow);
/** /**
* When content moves focus from a native plugin window that's a child * When content moves focus from a native plugin window that's a child
* of the native browser window we need to move native focus to the * of the native browser window we need to move native focus to the

View File

@ -2537,6 +2537,24 @@ TabParent::RecvGetWidgetNativeData(WindowsHandle* aValue)
return true; return true;
} }
bool
TabParent::RecvSetNativeChildOfShareableWindow(const uintptr_t& aChildWindow)
{
#if defined(XP_WIN)
nsCOMPtr<nsIWidget> widget = GetTopLevelWidget();
if (widget) {
// Note that this call will probably cause a sync native message to the
// process that owns the child window.
widget->SetNativeData(NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW, aChildWindow);
}
return true;
#else
NS_NOTREACHED(
"TabParent::RecvSetNativeChildOfShareableWindow not implemented!");
return false;
#endif
}
bool bool
TabParent::RecvDispatchFocusToTopLevelWindow() TabParent::RecvDispatchFocusToTopLevelWindow()
{ {

View File

@ -221,6 +221,7 @@ public:
virtual bool RecvGetDefaultScale(double* aValue) override; virtual bool RecvGetDefaultScale(double* aValue) override;
virtual bool RecvGetMaxTouchPoints(uint32_t* aTouchPoints) override; virtual bool RecvGetMaxTouchPoints(uint32_t* aTouchPoints) override;
virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue) override; virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue) override;
virtual bool RecvSetNativeChildOfShareableWindow(const uintptr_t& childWindow) override;
virtual bool RecvDispatchFocusToTopLevelWindow() override; virtual bool RecvDispatchFocusToTopLevelWindow() override;
virtual bool RecvZoomToRect(const uint32_t& aPresShellId, virtual bool RecvZoomToRect(const uint32_t& aPresShellId,
const ViewID& aViewId, const ViewID& aViewId,

View File

@ -642,23 +642,17 @@ nsPluginInstanceOwner::RedrawPlugin()
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value)
{
if (!mPluginFrame) {
NS_WARNING("plugin owner has no owner in getting doc's window handle");
return NS_ERROR_FAILURE;
}
#if defined(XP_WIN) #if defined(XP_WIN)
void** pvalue = (void**)value; nsIWidget*
nsViewManager* vm = mPluginFrame->PresContext()->GetPresShell()->GetViewManager(); nsPluginInstanceOwner::GetContainingWidgetIfOffset()
if (!vm) {
return NS_ERROR_FAILURE; MOZ_ASSERT(mPluginFrame, "Caller should have checked for null mPluginFrame.");
// This property is provided to allow a "windowless" plugin to determine the window it is drawing // This property is provided to allow a "windowless" plugin to determine the window it is drawing
// in, so it can translate mouse coordinates it receives directly from the operating system // in, so it can translate mouse coordinates it receives directly from the operating system
// to coordinates relative to itself. // to coordinates relative to itself.
// The original code (outside this #if) returns the document's window, which is OK if the window the "windowless" plugin // The original code returns the document's window, which is OK if the window the "windowless" plugin
// is drawing into has the same origin as the document's window, but this is not the case for "windowless" plugins inside of scrolling DIVs etc // is drawing into has the same origin as the document's window, but this is not the case for "windowless" plugins inside of scrolling DIVs etc
// To make sure "windowless" plugins always get the right origin for translating mouse coordinates, this code // To make sure "windowless" plugins always get the right origin for translating mouse coordinates, this code
@ -692,17 +686,53 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value)
if (offset.x || offset.y) { if (offset.x || offset.y) {
// in the case the two windows are offset from eachother, we do go ahead and return the correct enclosing window // in the case the two windows are offset from eachother, we do go ahead and return the correct enclosing window
// so that mouse co-ordinates are not messed up. // so that mouse co-ordinates are not messed up.
*pvalue = (void*)win->GetNativeData(NS_NATIVE_WINDOW); return win;
if (*pvalue)
return NS_OK;
} }
} }
} }
return nullptr;
}
static already_AddRefed<nsIWidget>
GetRootWidgetForPluginFrame(const nsPluginFrame* aPluginFrame)
{
MOZ_ASSERT(aPluginFrame);
nsViewManager* vm =
aPluginFrame->PresContext()->GetPresShell()->GetViewManager();
if (!vm) {
NS_WARNING("Could not find view manager for plugin frame.");
return nullptr;
}
nsCOMPtr<nsIWidget> rootWidget;
vm->GetRootWidget(getter_AddRefs(rootWidget));
return rootWidget.forget();
}
#endif
NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value)
{
if (!mPluginFrame) {
NS_WARNING("plugin owner has no owner in getting doc's window handle");
return NS_ERROR_FAILURE;
}
#if defined(XP_WIN)
void** pvalue = (void**)value;
nsIWidget* offsetContainingWidget = GetContainingWidgetIfOffset();
if (offsetContainingWidget) {
*pvalue = (void*)offsetContainingWidget->GetNativeData(NS_NATIVE_WINDOW);
if (*pvalue) {
return NS_OK;
}
}
// simply return the topmost document window // simply return the topmost document window
nsCOMPtr<nsIWidget> widget; nsCOMPtr<nsIWidget> widget = GetRootWidgetForPluginFrame(mPluginFrame);
vm->GetRootWidget(getter_AddRefs(widget));
if (widget) { if (widget) {
*pvalue = (void*)widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW); *pvalue = widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW);
} else { } else {
NS_ASSERTION(widget, "couldn't get doc's widget in getting doc's window handle"); NS_ASSERTION(widget, "couldn't get doc's widget in getting doc's window handle");
} }
@ -720,6 +750,48 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value)
#endif #endif
} }
#if defined(XP_WIN)
void
nsPluginInstanceOwner::SetWidgetWindowAsParent(HWND aWindowToAdopt)
{
if (!mWidget) {
NS_ERROR("mWidget should exist before this gets called.");
return;
}
mWidget->SetNativeData(NS_NATIVE_CHILD_WINDOW,
reinterpret_cast<uintptr_t>(aWindowToAdopt));
}
nsresult
nsPluginInstanceOwner::SetNetscapeWindowAsParent(HWND aWindowToAdopt)
{
if (!mPluginFrame) {
NS_WARNING("Plugin owner has no plugin frame.");
return NS_ERROR_FAILURE;
}
// If there is a containing window that is offset then ask that to adopt.
nsIWidget* offsetWidget = GetContainingWidgetIfOffset();
if (offsetWidget) {
offsetWidget->SetNativeData(NS_NATIVE_CHILD_WINDOW,
reinterpret_cast<uintptr_t>(aWindowToAdopt));
return NS_OK;
}
// Otherwise ask the topmost document window to adopt.
nsCOMPtr<nsIWidget> rootWidget = GetRootWidgetForPluginFrame(mPluginFrame);
if (!rootWidget) {
NS_ASSERTION(rootWidget, "Couldn't get topmost document's widget.");
return NS_ERROR_FAILURE;
}
rootWidget->SetNativeData(NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW,
reinterpret_cast<uintptr_t>(aWindowToAdopt));
return NS_OK;
}
#endif
NS_IMETHODIMP nsPluginInstanceOwner::SetEventModel(int32_t eventModel) NS_IMETHODIMP nsPluginInstanceOwner::SetEventModel(int32_t eventModel)
{ {
#ifdef XP_MACOSX #ifdef XP_MACOSX

View File

@ -112,6 +112,11 @@ public:
void ReleasePluginPort(void* pluginPort); void ReleasePluginPort(void* pluginPort);
nsEventStatus ProcessEvent(const mozilla::WidgetGUIEvent& anEvent); nsEventStatus ProcessEvent(const mozilla::WidgetGUIEvent& anEvent);
#if defined(XP_WIN)
void SetWidgetWindowAsParent(HWND aWindowToAdopt);
nsresult SetNetscapeWindowAsParent(HWND aWindowToAdopt);
#endif
#ifdef XP_MACOSX #ifdef XP_MACOSX
enum { ePluginPaintEnable, ePluginPaintDisable }; enum { ePluginPaintEnable, ePluginPaintDisable };
@ -273,6 +278,10 @@ private:
bool mFullScreen; bool mFullScreen;
void* mJavaView; void* mJavaView;
#endif #endif
#if defined(XP_WIN)
nsIWidget* GetContainingWidgetIfOffset();
#endif
nsPluginNativeWindow *mPluginWindow; nsPluginNativeWindow *mPluginWindow;
nsRefPtr<nsNPAPIPluginInstance> mInstance; nsRefPtr<nsNPAPIPluginInstance> mInstance;

View File

@ -70,8 +70,11 @@ child:
// This is only used on Windows and, for windowed plugins, must be called // This is only used on Windows and, for windowed plugins, must be called
// before the first call to NPP_SetWindow. // before the first call to NPP_SetWindow.
intr CreateChildPluginWindow(NPRemoteWindow window) intr CreateChildPluginWindow()
returns (NPRemoteWindow createdChild); returns (NativeWindowHandle childPluginWindow);
// This is only used on Windows and, for windowless plugins.
async CreateChildPopupSurrogate(NativeWindowHandle netscapeWindow);
intr NPP_SetWindow(NPRemoteWindow window); intr NPP_SetWindow(NPRemoteWindow window);
@ -219,6 +222,10 @@ parent:
// Notifies the parent of its NPP_New result code. // Notifies the parent of its NPP_New result code.
async AsyncNPP_NewResult(NPError aResult); async AsyncNPP_NewResult(NPError aResult);
// Sends a native window to be adopted by the native window that would be
// returned by NPN_GetValue_NPNVnetscapeWindow. Only used on Windows.
async SetNetscapeWindowAsParent(NativeWindowHandle childWindow);
both: both:
async PPluginScriptableObject(); async PPluginScriptableObject();

View File

@ -1146,25 +1146,31 @@ void PluginInstanceChild::DeleteWindow()
#endif #endif
bool bool
PluginInstanceChild::AnswerCreateChildPluginWindow(const NPRemoteWindow& aWindow, PluginInstanceChild::AnswerCreateChildPluginWindow(NativeWindowHandle* aChildPluginWindow)
NPRemoteWindow* aCreatedChild)
{ {
#if defined(XP_WIN) #if defined(XP_WIN)
MOZ_ASSERT(aWindow.type == NPWindowTypeWindow);
MOZ_ASSERT(!mPluginWindowHWND); MOZ_ASSERT(!mPluginWindowHWND);
if ((GetQuirks() & PluginModuleChild::QUIRK_QUICKTIME_AVOID_SETWINDOW) &&
aWindow.width == 0 && aWindow.height == 0) {
// Skip CreateChildPluginWindow call for hidden QuickTime plugins.
return true;
}
if (!CreatePluginWindow()) { if (!CreatePluginWindow()) {
return false; return false;
} }
aCreatedChild->window = reinterpret_cast<uint64_t>(mPluginWindowHWND); MOZ_ASSERT(mPluginWindowHWND);
*aChildPluginWindow = mPluginWindowHWND;
return true;
#else
NS_NOTREACHED("PluginInstanceChild::CreateChildPluginWindow not implemented!");
return false;
#endif
}
bool
PluginInstanceChild::RecvCreateChildPopupSurrogate(const NativeWindowHandle& aNetscapeWindow)
{
#if defined(XP_WIN)
mCachedWinlessPluginHWND = aNetscapeWindow;
CreateWinlessPopupSurrogate();
return true; return true;
#else #else
NS_NOTREACHED("PluginInstanceChild::CreateChildPluginWindow not implemented!"); NS_NOTREACHED("PluginInstanceChild::CreateChildPluginWindow not implemented!");
@ -1254,12 +1260,10 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
switch (aWindow.type) { switch (aWindow.type) {
case NPWindowTypeWindow: case NPWindowTypeWindow:
{ {
if ((GetQuirks() & QUIRK_QUICKTIME_AVOID_SETWINDOW) && // This check is now done in PluginInstanceParent before this call, so
aWindow.width == 0 && // we should never see it here.
aWindow.height == 0) { MOZ_ASSERT(!(GetQuirks() & QUIRK_QUICKTIME_AVOID_SETWINDOW) ||
// Skip SetWindow call for hidden QuickTime plugins aWindow.width != 0 || aWindow.height != 0);
return true;
}
MOZ_ASSERT(mPluginWindowHWND, MOZ_ASSERT(mPluginWindowHWND,
"Child plugin window must exist before call to SetWindow"); "Child plugin window must exist before call to SetWindow");
@ -1298,8 +1302,6 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
case NPWindowTypeDrawable: case NPWindowTypeDrawable:
mWindow.type = aWindow.type; mWindow.type = aWindow.type;
if (GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK)
CreateWinlessPopupSurrogate();
if (GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS) if (GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)
SetupFlashMsgThrottle(); SetupFlashMsgThrottle();
return SharedSurfaceSetWindow(aWindow); return SharedSurfaceSetWindow(aWindow);
@ -1968,21 +1970,15 @@ PluginInstanceChild::CreateWinlessPopupSurrogate()
if (mWinlessPopupSurrogateHWND) if (mWinlessPopupSurrogateHWND)
return; return;
HWND hwnd = nullptr;
NPError result;
if (!CallNPN_GetValue_NPNVnetscapeWindow(&hwnd, &result)) {
NS_ERROR("CallNPN_GetValue_NPNVnetscapeWindow failed.");
return;
}
mWinlessPopupSurrogateHWND = mWinlessPopupSurrogateHWND =
CreateWindowEx(WS_EX_NOPARENTNOTIFY, L"Static", nullptr, WS_CHILD, CreateWindowEx(WS_EX_NOPARENTNOTIFY, L"Static", nullptr, WS_POPUP,
0, 0, 0, 0, hwnd, 0, GetModuleHandle(nullptr), 0); 0, 0, 0, 0, nullptr, 0, GetModuleHandle(nullptr), 0);
if (!mWinlessPopupSurrogateHWND) { if (!mWinlessPopupSurrogateHWND) {
NS_ERROR("CreateWindowEx failed for winless placeholder!"); NS_ERROR("CreateWindowEx failed for winless placeholder!");
return; return;
} }
return;
SendSetNetscapeWindowAsParent(mWinlessPopupSurrogateHWND);
} }
void void
@ -2833,8 +2829,6 @@ PluginInstanceChild::DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
UpdateWindowAttributes(true); UpdateWindowAttributes(true);
#ifdef XP_WIN #ifdef XP_WIN
if (GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK)
CreateWinlessPopupSurrogate();
if (GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS) if (GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)
SetupFlashMsgThrottle(); SetupFlashMsgThrottle();
#endif #endif

View File

@ -65,10 +65,14 @@ class PluginInstanceChild : public PPluginInstanceChild
#endif #endif
protected: protected:
bool AnswerCreateChildPluginWindow(const NPRemoteWindow& window, virtual bool
NPRemoteWindow* aCreatedChild) override; AnswerCreateChildPluginWindow(NativeWindowHandle* aChildPluginWindow) override;
bool AnswerNPP_SetWindow(const NPRemoteWindow& window) override; virtual bool
RecvCreateChildPopupSurrogate(const NativeWindowHandle& aNetscapeWindow) override;
virtual bool
AnswerNPP_SetWindow(const NPRemoteWindow& window) override;
virtual bool virtual bool
AnswerNPP_GetValue_NPPVpluginWantsAllNetworkStreams(bool* wantsAllStreams, NPError* rv) override; AnswerNPP_GetValue_NPPVpluginWantsAllNetworkStreams(bool* wantsAllStreams, NPError* rv) override;

View File

@ -51,6 +51,7 @@
#include "nsHashKeys.h" #include "nsHashKeys.h"
#include "nsIWidget.h" #include "nsIWidget.h"
#include "nsPluginNativeWindow.h" #include "nsPluginNativeWindow.h"
#include "PluginQuirks.h"
extern const wchar_t* kFlashFullscreenClass; extern const wchar_t* kFlashFullscreenClass;
#elif defined(MOZ_WIDGET_GTK) #elif defined(MOZ_WIDGET_GTK)
#include <gdk/gdk.h> #include <gdk/gdk.h>
@ -679,6 +680,11 @@ PluginInstanceParent::AsyncSetWindow(NPWindow* aWindow)
mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &scaleFactor); mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &scaleFactor);
window.contentsScaleFactor = scaleFactor; window.contentsScaleFactor = scaleFactor;
#endif #endif
#if defined(OS_WIN)
MaybeCreateChildPopupSurrogate();
#endif
if (!SendAsyncSetWindow(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType(), if (!SendAsyncSetWindow(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType(),
window)) window))
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -967,16 +973,29 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
if (!SharedSurfaceSetWindow(aWindow, window)) { if (!SharedSurfaceSetWindow(aWindow, window)) {
return NPERR_OUT_OF_MEMORY_ERROR; return NPERR_OUT_OF_MEMORY_ERROR;
} }
}
else { MaybeCreateChildPopupSurrogate();
} else {
SubclassPluginWindow(reinterpret_cast<HWND>(aWindow->window)); SubclassPluginWindow(reinterpret_cast<HWND>(aWindow->window));
// Skip SetWindow call for hidden QuickTime plugins.
if ((mParent->GetQuirks() & QUIRK_QUICKTIME_AVOID_SETWINDOW) &&
aWindow->width == 0 && aWindow->height == 0) {
return NPERR_NO_ERROR;
}
window.window = reinterpret_cast<uint64_t>(aWindow->window); window.window = reinterpret_cast<uint64_t>(aWindow->window);
window.x = aWindow->x; window.x = aWindow->x;
window.y = aWindow->y; window.y = aWindow->y;
window.width = aWindow->width; window.width = aWindow->width;
window.height = aWindow->height; window.height = aWindow->height;
window.type = aWindow->type; window.type = aWindow->type;
// On Windows we need to create and set the parent before we set the
// window on the plugin, or keyboard interaction will not work.
if (!MaybeCreateAndParentChildPluginWindow()) {
return NPERR_GENERIC_ERROR;
}
} }
#else #else
window.window = reinterpret_cast<uint64_t>(aWindow->window); window.window = reinterpret_cast<uint64_t>(aWindow->window);
@ -1027,33 +1046,6 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
window.colormap = ws_info->colormap; window.colormap = ws_info->colormap;
#endif #endif
#if defined(XP_WIN)
// On Windows we need to create and set the parent before we set the window
// on the plugin, or certain things like keyboard interaction will not work.
if (!mChildPluginHWND && mWindowType == NPWindowTypeWindow) {
NPRemoteWindow childWindow;
if (!CallCreateChildPluginWindow(window, &childWindow)) {
return NPERR_GENERIC_ERROR;
}
mChildPluginHWND = reinterpret_cast<HWND>(childWindow.window);
}
// It's not clear if the parent window would ever change, but when this was
// done in the NPAPI child it used to allow for this.
if (mChildPluginHWND && mPluginHWND != mChildPluginsParentHWND) {
nsCOMPtr<nsIWidget> widget;
static_cast<const nsPluginNativeWindow*>(aWindow)->
GetPluginWidget(getter_AddRefs(widget));
if (widget) {
widget->SetNativeData(NS_NATIVE_CHILD_WINDOW,
reinterpret_cast<uintptr_t>(mChildPluginHWND));
}
mChildPluginsParentHWND = mPluginHWND;
}
#endif
if (!CallNPP_SetWindow(window)) { if (!CallNPP_SetWindow(window)) {
return NPERR_GENERIC_ERROR; return NPERR_GENERIC_ERROR;
} }
@ -1806,6 +1798,22 @@ PluginInstanceParent::RecvAsyncNPP_NewResult(const NPError& aResult)
return true; return true;
} }
bool
PluginInstanceParent::RecvSetNetscapeWindowAsParent(const NativeWindowHandle& childWindow)
{
#if defined(XP_WIN)
nsPluginInstanceOwner* owner = GetOwner();
if (!owner || NS_FAILED(owner->SetNetscapeWindowAsParent(childWindow))) {
NS_WARNING("Failed to set Netscape window as parent.");
}
return true;
#else
NS_NOTREACHED("PluginInstanceParent::RecvSetNetscapeWindowAsParent not implemented!");
return false;
#endif
}
#if defined(OS_WIN) #if defined(OS_WIN)
/* /*
@ -2050,6 +2058,65 @@ PluginInstanceParent::SharedSurfaceAfterPaint(NPEvent* npevent)
SRCCOPY); SRCCOPY);
} }
bool
PluginInstanceParent::MaybeCreateAndParentChildPluginWindow()
{
// On Windows we need to create and set the parent before we set the
// window on the plugin, or keyboard interaction will not work.
if (!mChildPluginHWND) {
if (!CallCreateChildPluginWindow(&mChildPluginHWND) ||
!mChildPluginHWND) {
return false;
}
}
// It's not clear if the parent window would ever change, but when this
// was done in the NPAPI child it used to allow for this.
if (mPluginHWND == mChildPluginsParentHWND) {
return true;
}
nsPluginInstanceOwner* owner = GetOwner();
if (!owner) {
// We can't reparent without an owner, the plugin is probably shutting
// down, just return true to allow any calls to continue.
return true;
}
// Note that this call will probably cause a sync native message to the
// process that owns the child window.
owner->SetWidgetWindowAsParent(mChildPluginHWND);
mChildPluginsParentHWND = mPluginHWND;
return true;
}
void
PluginInstanceParent::MaybeCreateChildPopupSurrogate()
{
// Already created or not required for this plugin.
if (mChildPluginHWND || mWindowType != NPWindowTypeDrawable ||
!(mParent->GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK)) {
return;
}
// We need to pass the netscape window down to be cached as part of the call
// to create the surrogate, because the reparenting of the surrogate in the
// main process can cause sync Windows messages to the plugin process, which
// then cause sync messages from the plugin child for the netscape window
// which causes a deadlock.
NativeWindowHandle netscapeWindow;
NPError result = mNPNIface->getvalue(mNPP, NPNVnetscapeWindow,
&netscapeWindow);
if (NPERR_NO_ERROR != result) {
NS_WARNING("Can't get netscape window to pass to plugin child.");
return;
}
if (!SendCreateChildPopupSurrogate(netscapeWindow)) {
NS_WARNING("Failed to create popup surrogate in child.");
}
}
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
bool bool

View File

@ -221,6 +221,9 @@ public:
virtual bool virtual bool
RecvAsyncNPP_NewResult(const NPError& aResult) override; RecvAsyncNPP_NewResult(const NPError& aResult) override;
virtual bool
RecvSetNetscapeWindowAsParent(const NativeWindowHandle& childWindow) override;
NPError NPP_SetWindow(const NPWindow* aWindow); NPError NPP_SetWindow(const NPWindow* aWindow);
NPError NPP_GetValue(NPPVariable variable, void* retval); NPError NPP_GetValue(NPPVariable variable, void* retval);
@ -361,11 +364,16 @@ private:
void SubclassPluginWindow(HWND aWnd); void SubclassPluginWindow(HWND aWnd);
void UnsubclassPluginWindow(); void UnsubclassPluginWindow();
bool MaybeCreateAndParentChildPluginWindow();
void MaybeCreateChildPopupSurrogate();
private: private:
gfx::SharedDIBWin mSharedSurfaceDib; gfx::SharedDIBWin mSharedSurfaceDib;
nsIntRect mPluginPort; nsIntRect mPluginPort;
nsIntRect mSharedSize; nsIntRect mSharedSize;
HWND mPluginHWND; HWND mPluginHWND;
// This is used for the normal child plugin HWND for windowed plugins and,
// if needed, also the child popup surrogate HWND for windowless plugins.
HWND mChildPluginHWND; HWND mChildPluginHWND;
HWND mChildPluginsParentHWND; HWND mChildPluginsParentHWND;
WNDPROC mPluginWndProc; WNDPROC mPluginWndProc;

View File

@ -1080,6 +1080,23 @@ PuppetWidget::GetNativeData(uint32_t aDataType)
return nullptr; return nullptr;
} }
#if defined(XP_WIN)
void
PuppetWidget::SetNativeData(uint32_t aDataType, uintptr_t aVal)
{
switch (aDataType) {
case NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW:
MOZ_ASSERT(mTabChild, "Need TabChild to send the message.");
if (mTabChild) {
mTabChild->SendSetNativeChildOfShareableWindow(aVal);
}
break;
default:
NS_WARNING("SetNativeData called with unsupported data type.");
}
}
#endif
nsIntPoint nsIntPoint
PuppetWidget::GetChromeDimensions() PuppetWidget::GetChromeDimensions()
{ {

View File

@ -119,6 +119,9 @@ public:
// PuppetWidgets don't have native data, as they're purely nonnative. // PuppetWidgets don't have native data, as they're purely nonnative.
virtual void* GetNativeData(uint32_t aDataType) override; virtual void* GetNativeData(uint32_t aDataType) override;
#if defined(XP_WIN)
void SetNativeData(uint32_t aDataType, uintptr_t aVal) override;
#endif
NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent) override NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent) override
{ return NS_ERROR_UNEXPECTED; } { return NS_ERROR_UNEXPECTED; }

View File

@ -102,6 +102,8 @@ typedef void* nsNativeWidget;
// HWND on Windows and XID on X11 // HWND on Windows and XID on X11
#define NS_NATIVE_SHAREABLE_WINDOW 11 #define NS_NATIVE_SHAREABLE_WINDOW 11
#define NS_NATIVE_OPENGL_CONTEXT 12 #define NS_NATIVE_OPENGL_CONTEXT 12
// See RegisterPluginWindowForRemoteUpdates
#define NS_NATIVE_PLUGIN_ID 13
#ifdef XP_MACOSX #ifdef XP_MACOSX
#define NS_NATIVE_PLUGIN_PORT_QD 100 #define NS_NATIVE_PLUGIN_PORT_QD 100
#define NS_NATIVE_PLUGIN_PORT_CG 101 #define NS_NATIVE_PLUGIN_PORT_CG 101
@ -112,13 +114,12 @@ typedef void* nsNativeWidget;
#define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102 #define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
#define NS_NATIVE_ICOREWINDOW 103 // winrt specific #define NS_NATIVE_ICOREWINDOW 103 // winrt specific
#define NS_NATIVE_CHILD_WINDOW 104 #define NS_NATIVE_CHILD_WINDOW 104
#define NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW 105
#endif #endif
#if defined(MOZ_WIDGET_GTK) #if defined(MOZ_WIDGET_GTK)
// set/get nsPluginNativeWindowGtk, e10s specific // set/get nsPluginNativeWindowGtk, e10s specific
#define NS_NATIVE_PLUGIN_OBJECT_PTR 104 #define NS_NATIVE_PLUGIN_OBJECT_PTR 104
#endif #endif
// See RegisterPluginWindowForRemoteUpdates
#define NS_NATIVE_PLUGIN_ID 105
#define NS_IWIDGET_IID \ #define NS_IWIDGET_IID \
{ 0x483BF75C, 0xF909, 0x45C3, \ { 0x483BF75C, 0xF909, 0x45C3, \

View File

@ -3153,24 +3153,31 @@ void* nsWindow::GetNativeData(uint32_t aDataType)
return nullptr; return nullptr;
} }
static void
SetChildStyleAndParent(HWND aChildWindow, HWND aParentWindow)
{
// Make sure the window is styled to be a child window.
LONG_PTR style = GetWindowLongPtr(aChildWindow, GWL_STYLE);
style |= WS_CHILD;
style &= ~WS_POPUP;
SetWindowLongPtr(aChildWindow, GWL_STYLE, style);
// Do the reparenting. Note that this call will probably cause a sync native
// message to the process that owns the child window.
::SetParent(aChildWindow, aParentWindow);
}
void void
nsWindow::SetNativeData(uint32_t aDataType, uintptr_t aVal) nsWindow::SetNativeData(uint32_t aDataType, uintptr_t aVal)
{ {
switch (aDataType) { switch (aDataType) {
case NS_NATIVE_CHILD_WINDOW: case NS_NATIVE_CHILD_WINDOW:
{ SetChildStyleAndParent(reinterpret_cast<HWND>(aVal), mWnd);
HWND childWindow = reinterpret_cast<HWND>(aVal); break;
case NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW:
// Make sure the window is styled to be a child window. SetChildStyleAndParent(reinterpret_cast<HWND>(aVal),
LONG_PTR style = GetWindowLongPtr(childWindow, GWL_STYLE); WinUtils::GetTopLevelHWND(mWnd));
style |= WS_CHILD; break;
style &= ~WS_POPUP;
SetWindowLongPtr(childWindow, GWL_STYLE, style);
// Do the reparenting.
::SetParent(childWindow, mWnd);
break;
}
default: default:
NS_ERROR("SetNativeData called with unsupported data type."); NS_ERROR("SetNativeData called with unsupported data type.");
} }