From 01f693c13856e34d0c979a691aea466f3cfe88b9 Mon Sep 17 00:00:00 2001 From: Bob Owen Date: Wed, 12 Aug 2015 16:00:26 +0100 Subject: [PATCH] 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. --- dom/ipc/PBrowser.ipdl | 6 + dom/ipc/TabParent.cpp | 18 +++ dom/ipc/TabParent.h | 1 + dom/plugins/base/nsPluginInstanceOwner.cpp | 108 +++++++++++++++--- dom/plugins/base/nsPluginInstanceOwner.h | 9 ++ dom/plugins/ipc/PPluginInstance.ipdl | 11 +- dom/plugins/ipc/PluginInstanceChild.cpp | 56 +++++---- dom/plugins/ipc/PluginInstanceChild.h | 10 +- dom/plugins/ipc/PluginInstanceParent.cpp | 125 ++++++++++++++++----- dom/plugins/ipc/PluginInstanceParent.h | 8 ++ widget/PuppetWidget.cpp | 17 +++ widget/PuppetWidget.h | 3 + widget/nsIWidget.h | 5 +- widget/windows/nsWindow.cpp | 33 +++--- 14 files changed, 312 insertions(+), 98 deletions(-) diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 9d80048c6fd..8c53a01efae 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -144,6 +144,12 @@ parent: */ 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 * of the native browser window we need to move native focus to the diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 5d2219f2cad..da23c11d018 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -2537,6 +2537,24 @@ TabParent::RecvGetWidgetNativeData(WindowsHandle* aValue) return true; } +bool +TabParent::RecvSetNativeChildOfShareableWindow(const uintptr_t& aChildWindow) +{ +#if defined(XP_WIN) + nsCOMPtr 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 TabParent::RecvDispatchFocusToTopLevelWindow() { diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index 5417d60aa06..4791e899dda 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -221,6 +221,7 @@ public: virtual bool RecvGetDefaultScale(double* aValue) override; virtual bool RecvGetMaxTouchPoints(uint32_t* aTouchPoints) override; virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue) override; + virtual bool RecvSetNativeChildOfShareableWindow(const uintptr_t& childWindow) override; virtual bool RecvDispatchFocusToTopLevelWindow() override; virtual bool RecvZoomToRect(const uint32_t& aPresShellId, const ViewID& aViewId, diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index 97b2eaf9aae..c872c3f2ff6 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -642,23 +642,17 @@ nsPluginInstanceOwner::RedrawPlugin() 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) - void** pvalue = (void**)value; - nsViewManager* vm = mPluginFrame->PresContext()->GetPresShell()->GetViewManager(); - if (!vm) - return NS_ERROR_FAILURE; +nsIWidget* +nsPluginInstanceOwner::GetContainingWidgetIfOffset() +{ + 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 // in, so it can translate mouse coordinates it receives directly from the operating system // 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 // 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) { // 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. - *pvalue = (void*)win->GetNativeData(NS_NATIVE_WINDOW); - if (*pvalue) - return NS_OK; + return win; } } } + + return nullptr; +} + +static already_AddRefed +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 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 - nsCOMPtr widget; - vm->GetRootWidget(getter_AddRefs(widget)); + nsCOMPtr widget = GetRootWidgetForPluginFrame(mPluginFrame); if (widget) { - *pvalue = (void*)widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW); + *pvalue = widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW); } else { 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 } +#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(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(aWindowToAdopt)); + return NS_OK; + } + + // Otherwise ask the topmost document window to adopt. + nsCOMPtr 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(aWindowToAdopt)); + return NS_OK; +} +#endif + NS_IMETHODIMP nsPluginInstanceOwner::SetEventModel(int32_t eventModel) { #ifdef XP_MACOSX diff --git a/dom/plugins/base/nsPluginInstanceOwner.h b/dom/plugins/base/nsPluginInstanceOwner.h index 29af2be7ab2..885ba0cd5a3 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.h +++ b/dom/plugins/base/nsPluginInstanceOwner.h @@ -112,6 +112,11 @@ public: void ReleasePluginPort(void* pluginPort); nsEventStatus ProcessEvent(const mozilla::WidgetGUIEvent& anEvent); + +#if defined(XP_WIN) + void SetWidgetWindowAsParent(HWND aWindowToAdopt); + nsresult SetNetscapeWindowAsParent(HWND aWindowToAdopt); +#endif #ifdef XP_MACOSX enum { ePluginPaintEnable, ePluginPaintDisable }; @@ -273,6 +278,10 @@ private: bool mFullScreen; void* mJavaView; #endif + +#if defined(XP_WIN) + nsIWidget* GetContainingWidgetIfOffset(); +#endif nsPluginNativeWindow *mPluginWindow; nsRefPtr mInstance; diff --git a/dom/plugins/ipc/PPluginInstance.ipdl b/dom/plugins/ipc/PPluginInstance.ipdl index b86ce11b48e..a162d3639e4 100644 --- a/dom/plugins/ipc/PPluginInstance.ipdl +++ b/dom/plugins/ipc/PPluginInstance.ipdl @@ -70,8 +70,11 @@ child: // This is only used on Windows and, for windowed plugins, must be called // before the first call to NPP_SetWindow. - intr CreateChildPluginWindow(NPRemoteWindow window) - returns (NPRemoteWindow createdChild); + intr CreateChildPluginWindow() + returns (NativeWindowHandle childPluginWindow); + + // This is only used on Windows and, for windowless plugins. + async CreateChildPopupSurrogate(NativeWindowHandle netscapeWindow); intr NPP_SetWindow(NPRemoteWindow window); @@ -219,6 +222,10 @@ parent: // Notifies the parent of its NPP_New result code. 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: async PPluginScriptableObject(); diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginInstanceChild.cpp index 35d67db8137..64d1745912e 100644 --- a/dom/plugins/ipc/PluginInstanceChild.cpp +++ b/dom/plugins/ipc/PluginInstanceChild.cpp @@ -1146,25 +1146,31 @@ void PluginInstanceChild::DeleteWindow() #endif bool -PluginInstanceChild::AnswerCreateChildPluginWindow(const NPRemoteWindow& aWindow, - NPRemoteWindow* aCreatedChild) +PluginInstanceChild::AnswerCreateChildPluginWindow(NativeWindowHandle* aChildPluginWindow) { #if defined(XP_WIN) - MOZ_ASSERT(aWindow.type == NPWindowTypeWindow); 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()) { return false; } - aCreatedChild->window = reinterpret_cast(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; #else NS_NOTREACHED("PluginInstanceChild::CreateChildPluginWindow not implemented!"); @@ -1254,12 +1260,10 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow) switch (aWindow.type) { case NPWindowTypeWindow: { - if ((GetQuirks() & QUIRK_QUICKTIME_AVOID_SETWINDOW) && - aWindow.width == 0 && - aWindow.height == 0) { - // Skip SetWindow call for hidden QuickTime plugins - return true; - } + // This check is now done in PluginInstanceParent before this call, so + // we should never see it here. + MOZ_ASSERT(!(GetQuirks() & QUIRK_QUICKTIME_AVOID_SETWINDOW) || + aWindow.width != 0 || aWindow.height != 0); MOZ_ASSERT(mPluginWindowHWND, "Child plugin window must exist before call to SetWindow"); @@ -1298,8 +1302,6 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow) case NPWindowTypeDrawable: mWindow.type = aWindow.type; - if (GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK) - CreateWinlessPopupSurrogate(); if (GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS) SetupFlashMsgThrottle(); return SharedSurfaceSetWindow(aWindow); @@ -1968,21 +1970,15 @@ PluginInstanceChild::CreateWinlessPopupSurrogate() if (mWinlessPopupSurrogateHWND) return; - HWND hwnd = nullptr; - NPError result; - if (!CallNPN_GetValue_NPNVnetscapeWindow(&hwnd, &result)) { - NS_ERROR("CallNPN_GetValue_NPNVnetscapeWindow failed."); - return; - } - mWinlessPopupSurrogateHWND = - CreateWindowEx(WS_EX_NOPARENTNOTIFY, L"Static", nullptr, WS_CHILD, - 0, 0, 0, 0, hwnd, 0, GetModuleHandle(nullptr), 0); + CreateWindowEx(WS_EX_NOPARENTNOTIFY, L"Static", nullptr, WS_POPUP, + 0, 0, 0, 0, nullptr, 0, GetModuleHandle(nullptr), 0); if (!mWinlessPopupSurrogateHWND) { NS_ERROR("CreateWindowEx failed for winless placeholder!"); return; } - return; + + SendSetNetscapeWindowAsParent(mWinlessPopupSurrogateHWND); } void @@ -2833,8 +2829,6 @@ PluginInstanceChild::DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType, UpdateWindowAttributes(true); #ifdef XP_WIN - if (GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK) - CreateWinlessPopupSurrogate(); if (GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS) SetupFlashMsgThrottle(); #endif diff --git a/dom/plugins/ipc/PluginInstanceChild.h b/dom/plugins/ipc/PluginInstanceChild.h index 0d03bb3aee9..e7bab586f17 100644 --- a/dom/plugins/ipc/PluginInstanceChild.h +++ b/dom/plugins/ipc/PluginInstanceChild.h @@ -65,10 +65,14 @@ class PluginInstanceChild : public PPluginInstanceChild #endif protected: - bool AnswerCreateChildPluginWindow(const NPRemoteWindow& window, - NPRemoteWindow* aCreatedChild) override; + virtual bool + 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 AnswerNPP_GetValue_NPPVpluginWantsAllNetworkStreams(bool* wantsAllStreams, NPError* rv) override; diff --git a/dom/plugins/ipc/PluginInstanceParent.cpp b/dom/plugins/ipc/PluginInstanceParent.cpp index 255edba382a..afb2c3535e9 100644 --- a/dom/plugins/ipc/PluginInstanceParent.cpp +++ b/dom/plugins/ipc/PluginInstanceParent.cpp @@ -51,6 +51,7 @@ #include "nsHashKeys.h" #include "nsIWidget.h" #include "nsPluginNativeWindow.h" +#include "PluginQuirks.h" extern const wchar_t* kFlashFullscreenClass; #elif defined(MOZ_WIDGET_GTK) #include @@ -679,6 +680,11 @@ PluginInstanceParent::AsyncSetWindow(NPWindow* aWindow) mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &scaleFactor); window.contentsScaleFactor = scaleFactor; #endif + +#if defined(OS_WIN) + MaybeCreateChildPopupSurrogate(); +#endif + if (!SendAsyncSetWindow(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType(), window)) return NS_ERROR_FAILURE; @@ -967,16 +973,29 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow) if (!SharedSurfaceSetWindow(aWindow, window)) { return NPERR_OUT_OF_MEMORY_ERROR; } - } - else { + + MaybeCreateChildPopupSurrogate(); + } else { SubclassPluginWindow(reinterpret_cast(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(aWindow->window); window.x = aWindow->x; window.y = aWindow->y; window.width = aWindow->width; window.height = aWindow->height; 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 window.window = reinterpret_cast(aWindow->window); @@ -1027,33 +1046,6 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow) window.colormap = ws_info->colormap; #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(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 widget; - static_cast(aWindow)-> - GetPluginWidget(getter_AddRefs(widget)); - if (widget) { - widget->SetNativeData(NS_NATIVE_CHILD_WINDOW, - reinterpret_cast(mChildPluginHWND)); - } - - mChildPluginsParentHWND = mPluginHWND; - } -#endif - if (!CallNPP_SetWindow(window)) { return NPERR_GENERIC_ERROR; } @@ -1806,6 +1798,22 @@ PluginInstanceParent::RecvAsyncNPP_NewResult(const NPError& aResult) 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) /* @@ -2050,6 +2058,65 @@ PluginInstanceParent::SharedSurfaceAfterPaint(NPEvent* npevent) 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) bool diff --git a/dom/plugins/ipc/PluginInstanceParent.h b/dom/plugins/ipc/PluginInstanceParent.h index 6a2f0f0bdbf..84c467da21f 100644 --- a/dom/plugins/ipc/PluginInstanceParent.h +++ b/dom/plugins/ipc/PluginInstanceParent.h @@ -221,6 +221,9 @@ public: virtual bool RecvAsyncNPP_NewResult(const NPError& aResult) override; + virtual bool + RecvSetNetscapeWindowAsParent(const NativeWindowHandle& childWindow) override; + NPError NPP_SetWindow(const NPWindow* aWindow); NPError NPP_GetValue(NPPVariable variable, void* retval); @@ -361,11 +364,16 @@ private: void SubclassPluginWindow(HWND aWnd); void UnsubclassPluginWindow(); + bool MaybeCreateAndParentChildPluginWindow(); + void MaybeCreateChildPopupSurrogate(); + private: gfx::SharedDIBWin mSharedSurfaceDib; nsIntRect mPluginPort; nsIntRect mSharedSize; 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 mChildPluginsParentHWND; WNDPROC mPluginWndProc; diff --git a/widget/PuppetWidget.cpp b/widget/PuppetWidget.cpp index e6368fb36da..8b009139e03 100644 --- a/widget/PuppetWidget.cpp +++ b/widget/PuppetWidget.cpp @@ -1080,6 +1080,23 @@ PuppetWidget::GetNativeData(uint32_t aDataType) 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 PuppetWidget::GetChromeDimensions() { diff --git a/widget/PuppetWidget.h b/widget/PuppetWidget.h index 75ffe0d362f..38690eadcc1 100644 --- a/widget/PuppetWidget.h +++ b/widget/PuppetWidget.h @@ -119,6 +119,9 @@ public: // PuppetWidgets don't have native data, as they're purely nonnative. 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 { return NS_ERROR_UNEXPECTED; } diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index 86c21fa4698..e8ceb927bb7 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -102,6 +102,8 @@ typedef void* nsNativeWidget; // HWND on Windows and XID on X11 #define NS_NATIVE_SHAREABLE_WINDOW 11 #define NS_NATIVE_OPENGL_CONTEXT 12 +// See RegisterPluginWindowForRemoteUpdates +#define NS_NATIVE_PLUGIN_ID 13 #ifdef XP_MACOSX #define NS_NATIVE_PLUGIN_PORT_QD 100 #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_ICOREWINDOW 103 // winrt specific #define NS_NATIVE_CHILD_WINDOW 104 +#define NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW 105 #endif #if defined(MOZ_WIDGET_GTK) // set/get nsPluginNativeWindowGtk, e10s specific #define NS_NATIVE_PLUGIN_OBJECT_PTR 104 #endif -// See RegisterPluginWindowForRemoteUpdates -#define NS_NATIVE_PLUGIN_ID 105 #define NS_IWIDGET_IID \ { 0x483BF75C, 0xF909, 0x45C3, \ diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index b615161080e..6441c84e4d9 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -3153,24 +3153,31 @@ void* nsWindow::GetNativeData(uint32_t aDataType) 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 nsWindow::SetNativeData(uint32_t aDataType, uintptr_t aVal) { switch (aDataType) { case NS_NATIVE_CHILD_WINDOW: - { - HWND childWindow = reinterpret_cast(aVal); - - // Make sure the window is styled to be a child window. - LONG_PTR style = GetWindowLongPtr(childWindow, GWL_STYLE); - style |= WS_CHILD; - style &= ~WS_POPUP; - SetWindowLongPtr(childWindow, GWL_STYLE, style); - - // Do the reparenting. - ::SetParent(childWindow, mWnd); - break; - } + SetChildStyleAndParent(reinterpret_cast(aVal), mWnd); + break; + case NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW: + SetChildStyleAndParent(reinterpret_cast(aVal), + WinUtils::GetTopLevelHWND(mWnd)); + break; default: NS_ERROR("SetNativeData called with unsupported data type."); }