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);
/**
* 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

View File

@ -2537,6 +2537,24 @@ TabParent::RecvGetWidgetNativeData(WindowsHandle* aValue)
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
TabParent::RecvDispatchFocusToTopLevelWindow()
{

View File

@ -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,

View File

@ -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 win;
}
}
}
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
nsCOMPtr<nsIWidget> widget;
vm->GetRootWidget(getter_AddRefs(widget));
nsCOMPtr<nsIWidget> 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<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)
{
#ifdef XP_MACOSX

View File

@ -113,6 +113,11 @@ public:
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 };
@ -274,6 +279,10 @@ private:
void* mJavaView;
#endif
#if defined(XP_WIN)
nsIWidget* GetContainingWidgetIfOffset();
#endif
nsPluginNativeWindow *mPluginWindow;
nsRefPtr<nsNPAPIPluginInstance> mInstance;
nsPluginFrame *mPluginFrame;

View File

@ -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();

View File

@ -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<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;
#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

View File

@ -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;

View File

@ -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 <gdk/gdk.h>
@ -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<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.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<uint64_t>(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<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)) {
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

View File

@ -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;

View File

@ -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()
{

View File

@ -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; }

View File

@ -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, \

View File

@ -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<HWND>(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);
SetChildStyleAndParent(reinterpret_cast<HWND>(aVal), mWnd);
break;
case NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW:
SetChildStyleAndParent(reinterpret_cast<HWND>(aVal),
WinUtils::GetTopLevelHWND(mWnd));
break;
}
default:
NS_ERROR("SetNativeData called with unsupported data type.");
}