зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1165903: For Windows NPAPI do window re-parenting in the chrome process to allow for sandboxing. r=jimm
This commit is contained in:
Родитель
bf0d1d0f6f
Коммит
dce35c582d
|
@ -1207,6 +1207,7 @@ pref("security.sandbox.windows.log", false);
|
|||
// 3 - the strongest settings we seem to be able to use without breaking
|
||||
// everything, but will probably cause some functionality restrictions
|
||||
pref("dom.ipc.plugins.sandbox-level.default", 0);
|
||||
pref("dom.ipc.plugins.sandbox-level.flash", 0);
|
||||
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
// This controls the strength of the Windows content process sandbox for testing
|
||||
|
|
|
@ -41,6 +41,12 @@ parent:
|
|||
* native HWND of the plugin widget.
|
||||
*/
|
||||
sync GetNativePluginPort() returns (uintptr_t value);
|
||||
|
||||
/**
|
||||
* Sends an NS_NATIVE_CHILD_WINDOW to be adopted by the widget's native window
|
||||
* on the chrome side. This is only currently used on Windows.
|
||||
*/
|
||||
sync SetNativeChildWindow(uintptr_t childWindow);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult GetPluginWidget(nsIWidget **aWidget) {
|
||||
nsresult GetPluginWidget(nsIWidget **aWidget) const {
|
||||
NS_IF_ADDREF(*aWidget = mWidget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -68,7 +68,10 @@ intr protocol PPluginInstance
|
|||
child:
|
||||
intr __delete__();
|
||||
|
||||
intr NPP_SetWindow(NPRemoteWindow window);
|
||||
// Return value is only used on Windows and only when the window needs its
|
||||
// parent set to the chrome widget native window.
|
||||
intr NPP_SetWindow(NPRemoteWindow window)
|
||||
returns (NPRemoteWindow childWindowToBeAdopted);
|
||||
|
||||
intr NPP_GetValue_NPPVpluginWantsAllNetworkStreams()
|
||||
returns (bool value, NPError result);
|
||||
|
|
|
@ -1124,7 +1124,8 @@ void PluginInstanceChild::DeleteWindow()
|
|||
#endif
|
||||
|
||||
bool
|
||||
PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
|
||||
PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow,
|
||||
NPRemoteWindow* aChildWindowToBeAdopted)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG(("%s (aWindow=<window: 0x%lx, x: %d, y: %d, width: %d, height: %d>)",
|
||||
FULLFUNCTION,
|
||||
|
@ -1215,9 +1216,32 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
|
|||
if (!CreatePluginWindow())
|
||||
return false;
|
||||
|
||||
ReparentPluginWindow(reinterpret_cast<HWND>(aWindow.window));
|
||||
SizePluginWindow(aWindow.width, aWindow.height);
|
||||
|
||||
// If the window is not our parent set the return child window so that
|
||||
// it can be re-parented in the chrome process. Re-parenting now
|
||||
// happens there as we might not have sufficient permission.
|
||||
// Also, this needs to be after SizePluginWindow because SetWindowPos
|
||||
// relies on things that it sets.
|
||||
HWND parentWindow = reinterpret_cast<HWND>(aWindow.window);
|
||||
if (mPluginParentHWND != parentWindow && IsWindow(parentWindow)) {
|
||||
mPluginParentHWND = parentWindow;
|
||||
aChildWindowToBeAdopted->window =
|
||||
reinterpret_cast<uint64_t>(mPluginWindowHWND);
|
||||
} else {
|
||||
// Now we know that the window has the correct parent we can show
|
||||
// it. The actual visibility is controlled by its parent.
|
||||
// First time round, these calls are made by our caller after the
|
||||
// parent is set.
|
||||
ShowWindow(mPluginWindowHWND, SW_SHOWNA);
|
||||
|
||||
// This used to be called in SizePluginWindow, but we need to make
|
||||
// sure that mPluginWindowHWND has had it's parent set correctly,
|
||||
// otherwise it can cause a focus issue.
|
||||
SetWindowPos(mPluginWindowHWND, nullptr, 0, 0, aWindow.width,
|
||||
aWindow.height, SWP_NOZORDER | SWP_NOREPOSITION);
|
||||
}
|
||||
|
||||
mWindow.window = (void*)mPluginWindowHWND;
|
||||
mWindow.x = aWindow.x;
|
||||
mWindow.y = aWindow.y;
|
||||
|
@ -1405,25 +1429,6 @@ PluginInstanceChild::DestroyPluginWindow()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::ReparentPluginWindow(HWND hWndParent)
|
||||
{
|
||||
if (hWndParent != mPluginParentHWND && IsWindow(hWndParent)) {
|
||||
// Fix the child window's style to be a child window.
|
||||
LONG_PTR style = GetWindowLongPtr(mPluginWindowHWND, GWL_STYLE);
|
||||
style |= WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
||||
style &= ~WS_POPUP;
|
||||
SetWindowLongPtr(mPluginWindowHWND, GWL_STYLE, style);
|
||||
|
||||
// Do the reparenting.
|
||||
SetParent(mPluginWindowHWND, hWndParent);
|
||||
|
||||
// Make sure we're visible.
|
||||
ShowWindow(mPluginWindowHWND, SW_SHOWNA);
|
||||
}
|
||||
mPluginParentHWND = hWndParent;
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::SizePluginWindow(int width,
|
||||
int height)
|
||||
|
@ -1431,8 +1436,6 @@ PluginInstanceChild::SizePluginWindow(int width,
|
|||
if (mPluginWindowHWND) {
|
||||
mPluginSize.x = width;
|
||||
mPluginSize.y = height;
|
||||
SetWindowPos(mPluginWindowHWND, nullptr, 0, 0, width, height,
|
||||
SWP_NOZORDER | SWP_NOREPOSITION);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,8 @@ class PluginInstanceChild : public PPluginInstanceChild
|
|||
#endif
|
||||
|
||||
protected:
|
||||
virtual bool AnswerNPP_SetWindow(const NPRemoteWindow& window) override;
|
||||
bool AnswerNPP_SetWindow(const NPRemoteWindow& window,
|
||||
NPRemoteWindow* aChildWindowToBeAdopted) override;
|
||||
|
||||
virtual bool
|
||||
AnswerNPP_GetValue_NPPVpluginWantsAllNetworkStreams(bool* wantsAllStreams, NPError* rv) override;
|
||||
|
@ -278,7 +279,6 @@ private:
|
|||
static bool RegisterWindowClass();
|
||||
bool CreatePluginWindow();
|
||||
void DestroyPluginWindow();
|
||||
void ReparentPluginWindow(HWND hWndParent);
|
||||
void SizePluginWindow(int width, int height);
|
||||
int16_t WinlessHandleEvent(NPEvent& event);
|
||||
void CreateWinlessPopupSurrogate();
|
||||
|
|
|
@ -49,6 +49,8 @@
|
|||
#include "mozilla/plugins/PluginSurfaceParent.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsPluginNativeWindow.h"
|
||||
extern const wchar_t* kFlashFullscreenClass;
|
||||
#elif defined(MOZ_WIDGET_GTK)
|
||||
#include <gdk/gdk.h>
|
||||
|
@ -1025,8 +1027,30 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
|
|||
window.colormap = ws_info->colormap;
|
||||
#endif
|
||||
|
||||
if (!CallNPP_SetWindow(window))
|
||||
NPRemoteWindow childWindow;
|
||||
if (!CallNPP_SetWindow(window, &childWindow)) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// If a child window is returned it means that we need to re-parent it.
|
||||
if (childWindow.window) {
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
static_cast<const nsPluginNativeWindow*>(aWindow)->
|
||||
GetPluginWidget(getter_AddRefs(widget));
|
||||
if (widget) {
|
||||
widget->SetNativeData(NS_NATIVE_CHILD_WINDOW,
|
||||
static_cast<uintptr_t>(childWindow.window));
|
||||
}
|
||||
|
||||
// Now it has got the correct parent, make sure it is visible.
|
||||
// In subsequent calls to SetWindow these calls happen in the Child.
|
||||
HWND childHWND = reinterpret_cast<HWND>(childWindow.window);
|
||||
ShowWindow(childHWND, SW_SHOWNA);
|
||||
SetWindowPos(childHWND, nullptr, 0, 0, window.width, window.height,
|
||||
SWP_NOZORDER | SWP_NOREPOSITION);
|
||||
}
|
||||
#endif
|
||||
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
|
|
@ -210,5 +210,20 @@ PluginWidgetParent::RecvGetNativePluginPort(uintptr_t* value)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginWidgetParent::RecvSetNativeChildWindow(const uintptr_t& aChildWindow)
|
||||
{
|
||||
#if defined(XP_WIN)
|
||||
ENSURE_CHANNEL;
|
||||
PWLOG("PluginWidgetParent::RecvSetNativeChildWindow(%p)\n",
|
||||
static_cast<void*>(aChildWindow));
|
||||
mWidget->SetNativeData(NS_NATIVE_CHILD_WINDOW, aChildWindow);
|
||||
return true;
|
||||
#else
|
||||
NS_NOTREACHED("PluginWidgetParent::RecvSetNativeChildWindow not implemented!");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -31,6 +31,7 @@ public:
|
|||
virtual bool RecvCreate(nsresult* aResult) override;
|
||||
virtual bool RecvSetFocus(const bool& aRaise) override;
|
||||
virtual bool RecvGetNativePluginPort(uintptr_t* value) override;
|
||||
bool RecvSetNativeChildWindow(const uintptr_t& aChildWindow) override;
|
||||
|
||||
// Helper for compositor checks on the channel
|
||||
bool ActorDestroyed() { return !mWidget; }
|
||||
|
|
|
@ -141,6 +141,29 @@ PluginWidgetProxy::GetNativeData(uint32_t aDataType)
|
|||
return (void*)value;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
void
|
||||
PluginWidgetProxy::SetNativeData(uint32_t aDataType, uintptr_t aVal)
|
||||
{
|
||||
if (!mActor) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto tab = static_cast<mozilla::dom::TabChild*>(mActor->Manager());
|
||||
if (tab && tab->IsDestroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aDataType) {
|
||||
case NS_NATIVE_CHILD_WINDOW:
|
||||
mActor->SendSetNativeChildWindow(aVal);
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("SetNativeData called with unsupported data type.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginWidgetProxy::SetFocus(bool aRaise)
|
||||
{
|
||||
|
|
|
@ -43,6 +43,9 @@ public:
|
|||
|
||||
virtual nsIWidget* GetParent(void) override;
|
||||
virtual void* GetNativeData(uint32_t aDataType) override;
|
||||
#if defined(XP_WIN)
|
||||
void SetNativeData(uint32_t aDataType, uintptr_t aVal) override;
|
||||
#endif
|
||||
virtual nsTransparencyMode GetTransparencyMode() override
|
||||
{ return eTransparencyOpaque; }
|
||||
virtual void GetWindowClipRegion(nsTArray<nsIntRect>* aRects) override;
|
||||
|
|
|
@ -109,6 +109,7 @@ typedef void* nsNativeWidget;
|
|||
#define NS_NATIVE_TSF_CATEGORY_MGR 101
|
||||
#define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
|
||||
#define NS_NATIVE_ICOREWINDOW 103 // winrt specific
|
||||
#define NS_NATIVE_CHILD_WINDOW 104
|
||||
#endif
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
// set/get nsPluginNativeWindowGtk, e10s specific
|
||||
|
|
|
@ -2972,6 +2972,29 @@ void* nsWindow::GetNativeData(uint32_t aDataType)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
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);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NS_ERROR("SetNativeData called with unsupported data type.");
|
||||
}
|
||||
}
|
||||
|
||||
// Free some native data according to aDataType
|
||||
void nsWindow::FreeNativeData(void * data, uint32_t aDataType)
|
||||
{
|
||||
|
|
|
@ -133,6 +133,7 @@ public:
|
|||
bool aIncludeChildren = false);
|
||||
NS_IMETHOD Invalidate(const nsIntRect & aRect);
|
||||
virtual void* GetNativeData(uint32_t aDataType);
|
||||
void SetNativeData(uint32_t aDataType, uintptr_t aVal) override;
|
||||
virtual void FreeNativeData(void * data, uint32_t aDataType);
|
||||
NS_IMETHOD SetTitle(const nsAString& aTitle);
|
||||
NS_IMETHOD SetIcon(const nsAString& aIconSpec);
|
||||
|
|
Загрузка…
Ссылка в новой задаче