diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-11 19:12:36 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-11 19:12:36 +0000 |
commit | 3e076a8cc7a0f858b6ba3f563fca6716f889e1fe (patch) | |
tree | 02093584c074ae513f486683f585b82969901a3b | |
parent | e9c180b08c7464bfa37268175f9dac862c7eaac7 (diff) | |
download | chromium_src-3e076a8cc7a0f858b6ba3f563fca6716f889e1fe.zip chromium_src-3e076a8cc7a0f858b6ba3f563fca6716f889e1fe.tar.gz chromium_src-3e076a8cc7a0f858b6ba3f563fca6716f889e1fe.tar.bz2 |
Initial NPAPI plugin support in Win Aura.
Scrolling jank is noticable because the plugin moves at a different time than the content is updated. There are also a couple of other functions in RenderWidgetHostViewWin that enumerate plugin Windows that need to be shared, but I'm leaving these for a future change.
The code in render_widget_host_view_base.cc is all moved from render_widget_host_view_win.cc with the exception of the lines between the USE_AURA ifdef.
Review URL: https://codereview.chromium.org/10905122
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@156090 0039d316-1c4b-4281-b951-d872f2087c98
22 files changed, 367 insertions, 241 deletions
diff --git a/content/browser/plugin_process_host.cc b/content/browser/plugin_process_host.cc index 23cac73..ec96877 100644 --- a/content/browser/plugin_process_host.cc +++ b/content/browser/plugin_process_host.cc @@ -4,7 +4,7 @@ #include "content/browser/plugin_process_host.h" -#if defined(OS_WIN) && !defined(USE_AURA) +#if defined(OS_WIN) #include <windows.h> #elif defined(OS_POSIX) #include <utility> // for pair<> @@ -53,7 +53,7 @@ using content::ChildProcessHost; #include "ui/gfx/rect.h" #endif -#if defined(OS_WIN) && !defined(USE_AURA) +#if defined(OS_WIN) #include "base/win/windows_version.h" #include "webkit/plugins/npapi/plugin_constants_win.h" #include "webkit/plugins/npapi/webplugin_delegate_impl.h" @@ -133,7 +133,7 @@ PluginProcessHost::PluginProcessHost() } PluginProcessHost::~PluginProcessHost() { -#if defined(OS_WIN) && !defined(USE_AURA) +#if defined(OS_WIN) // We erase HWNDs from the plugin_parent_windows_set_ when we receive a // notification that the window is being destroyed. If we don't receive this // notification and the PluginProcessHost instance is being destroyed, it @@ -311,7 +311,7 @@ bool PluginProcessHost::OnMessageReceived(const IPC::Message& msg) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(PluginProcessHost, msg) IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ChannelCreated, OnChannelCreated) -#if defined(OS_WIN) && !defined(USE_AURA) +#if defined(OS_WIN) IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginWindowDestroyed, OnPluginWindowDestroyed) IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ReparentPluginWindow, diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 2cafc057..8eba358 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc @@ -1490,7 +1490,7 @@ void RenderWidgetHostImpl::DidUpdateBackingStore( // in the process could dispatch other window messages which could cause the // view to be destroyed. if (view_) - view_->MovePluginWindows(params.plugin_window_moves); + view_->MovePluginWindows(params.scroll_offset, params.plugin_window_moves); NotificationService::current()->Notify( NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index d718d1d..bb992fc 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc @@ -116,6 +116,7 @@ RenderWidgetHostViewAndroid::GetNativeViewAccessible() { } void RenderWidgetHostViewAndroid::MovePluginWindows( + const gfx::Point& scroll_offset, const std::vector<webkit::npapi::WebPluginGeometry>& moves) { // We don't have plugin windows on Android. Do nothing. Note: this is called // from RenderWidgetHost::OnMsgUpdateRect which is itself invoked while diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index 475dc03..1b14572 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h @@ -49,6 +49,7 @@ class RenderWidgetHostViewAndroid : public RenderWidgetHostViewBase { virtual gfx::NativeViewId GetNativeViewId() const OVERRIDE; virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE; virtual void MovePluginWindows( + const gfx::Point& scroll_offset, const std::vector<webkit::npapi::WebPluginGeometry>& moves) OVERRIDE; virtual void Focus() OVERRIDE; virtual void Blur() OVERRIDE; diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 271aa01..c5d4edb 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -338,7 +338,12 @@ gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const { } gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const { +#if defined(OS_WIN) + HWND window = window_->GetRootWindow()->GetAcceleratedWidget(); + return reinterpret_cast<gfx::NativeViewId>(window); +#else return static_cast<gfx::NativeViewId>(NULL); +#endif } gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() { @@ -347,8 +352,29 @@ gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() { } void RenderWidgetHostViewAura::MovePluginWindows( - const std::vector<webkit::npapi::WebPluginGeometry>& moves) { - // We don't support windowed plugins. + const gfx::Point& scroll_offset, + const std::vector<webkit::npapi::WebPluginGeometry>& plugin_window_moves) { +#if defined(OS_WIN) + HWND parent = window_->GetRootWindow()->GetAcceleratedWidget(); + gfx::Rect view_bounds = window_->GetBoundsInRootWindow(); + std::vector<webkit::npapi::WebPluginGeometry> moves = plugin_window_moves; + + gfx::Rect view_port(scroll_offset.x(), scroll_offset.y(), view_bounds.width(), + view_bounds.height()); + + for (size_t i = 0; i < moves.size(); ++i) { + gfx::Rect clip = moves[i].clip_rect; + clip.Offset(moves[i].window_rect.origin()); + clip.Offset(scroll_offset); + clip = clip.Intersect(view_port); + clip.Offset(-moves[i].window_rect.x(), -moves[i].window_rect.y()); + clip.Offset(-scroll_offset.x(), -scroll_offset.y()); + moves[i].clip_rect = clip; + + moves[i].window_rect.Offset(view_bounds.origin()); + } + MovePluginWindowsHelper(parent, moves); +#endif // defined(OS_WIN) } void RenderWidgetHostViewAura::Focus() { @@ -453,6 +479,15 @@ void RenderWidgetHostViewAura::DidUpdateBackingStore( continue; SchedulePaintIfNotInClip(rect, clip_rect); + +#if defined(OS_WIN) + // Send the invalid rect in screen coordinates. + gfx::Rect screen_rect = GetViewBounds(); + gfx::Rect invalid_screen_rect(rect); + invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y()); + HWND hwnd = window_->GetRootWindow()->GetAcceleratedWidget(); + PaintPluginWindowsHelper(hwnd, invalid_screen_rect); +#endif // defined(OS_WIN) } } diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index d0feebc..d592a64 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h @@ -77,6 +77,7 @@ class RenderWidgetHostViewAura virtual void WasShown() OVERRIDE; virtual void WasHidden() OVERRIDE; virtual void MovePluginWindows( + const gfx::Point& scroll_offset, const std::vector<webkit::npapi::WebPluginGeometry>& moves) OVERRIDE; virtual void Focus() OVERRIDE; virtual void Blur() OVERRIDE; diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc index b29bdea..4387332 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.cc +++ b/content/browser/renderer_host/render_widget_host_view_base.cc @@ -12,6 +12,21 @@ #include "ui/gfx/display.h" #include "ui/gfx/screen.h" +#if defined(OS_WIN) +#include "base/command_line.h" +#include "base/message_loop.h" +#include "base/win/wrapped_window_proc.h" +#include "content/browser/plugin_process_host.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/child_process_data.h" +#include "content/public/common/content_switches.h" +#include "ui/base/win/hwnd_util.h" +#include "ui/gfx/gdi_util.h" +#include "webkit/plugins/npapi/plugin_constants_win.h" +#include "webkit/plugins/npapi/webplugin.h" +#include "webkit/plugins/npapi/webplugin_delegate_impl.h" +#endif + #if defined(TOOLKIT_GTK) #include <gdk/gdkx.h> #include <gtk/gtk.h> @@ -39,6 +54,260 @@ RenderWidgetHostViewPort* RenderWidgetHostViewPort::CreateViewForWidget( return FromRWHV(RenderWidgetHostView::CreateViewForWidget(widget)); } +#if defined(OS_WIN) + +namespace { + +// |window| is the plugin HWND, created and destroyed in the plugin process. +// |parent| is the parent HWND, created and destroyed on the browser UI thread. +void NotifyPluginProcessHostHelper(HWND window, HWND parent, int tries) { + // How long to wait between each try. + static const int kTryDelayMs = 200; + + DWORD plugin_process_id; + bool found_starting_plugin_process = false; + GetWindowThreadProcessId(window, &plugin_process_id); + for (PluginProcessHostIterator iter; !iter.Done(); ++iter) { + if (!iter.GetData().handle) { + found_starting_plugin_process = true; + continue; + } + if (base::GetProcId(iter.GetData().handle) == plugin_process_id) { + iter->AddWindow(parent); + return; + } + } + + if (found_starting_plugin_process) { + // A plugin process has started but we don't have its handle yet. Since + // it's most likely the one for this plugin, try a few more times after a + // delay. + if (tries > 0) { + MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&NotifyPluginProcessHostHelper, window, parent, tries - 1), + base::TimeDelta::FromMilliseconds(kTryDelayMs)); + return; + } + } + + // The plugin process might have died in the time to execute the task, don't + // leak the HWND. + PostMessage(parent, WM_CLOSE, 0, 0); +} + +// The plugin wrapper window which lives in the browser process has this proc +// as its window procedure. We only handle the WM_PARENTNOTIFY message sent by +// windowed plugins for mouse input. This is forwarded off to the wrappers +// parent which is typically the RVH window which turns on user gesture. +LRESULT CALLBACK PluginWrapperWindowProc(HWND window, unsigned int message, + WPARAM wparam, LPARAM lparam) { + if (message == WM_PARENTNOTIFY) { + switch (LOWORD(wparam)) { + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: + ::SendMessage(GetParent(window), message, wparam, lparam); + return 0; + default: + break; + } + } + return ::DefWindowProc(window, message, wparam, lparam); +} + +// Create an intermediate window between the given HWND and its parent. +HWND ReparentWindow(HWND window) { + static ATOM atom = 0; + static HMODULE instance = NULL; + if (!atom) { + WNDCLASSEX window_class; + base::win::InitializeWindowClass( + webkit::npapi::kWrapperNativeWindowClassName, + &base::win::WrappedWindowProc<PluginWrapperWindowProc>, + CS_DBLCLKS, + 0, + 0, + NULL, + // xxx reinterpret_cast<HBRUSH>(COLOR_WINDOW+1), + reinterpret_cast<HBRUSH>(COLOR_GRAYTEXT+1), + NULL, + NULL, + NULL, + &window_class); + instance = window_class.hInstance; + atom = RegisterClassEx(&window_class); + } + DCHECK(atom); + + HWND orig_parent = ::GetParent(window); + HWND parent = CreateWindowEx( + WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, + MAKEINTATOM(atom), 0, + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + 0, 0, 0, 0, orig_parent, 0, instance, 0); + ui::CheckWindowCreated(parent); + // If UIPI is enabled we need to add message filters for parents with + // children that cross process boundaries. + if (::GetPropW(orig_parent, webkit::npapi::kNativeWindowClassFilterProp)) { + // Process-wide message filters required on Vista must be added to: + // chrome_content_client.cc ChromeContentClient::SandboxPlugin + ChangeWindowMessageFilterEx(parent, WM_MOUSEWHEEL, MSGFLT_ALLOW, NULL); + ChangeWindowMessageFilterEx(parent, WM_GESTURE, MSGFLT_ALLOW, NULL); + ChangeWindowMessageFilterEx(parent, WM_APPCOMMAND, MSGFLT_ALLOW, NULL); + ::RemovePropW(orig_parent, webkit::npapi::kNativeWindowClassFilterProp); + } + ::SetParent(window, parent); + // How many times we try to find a PluginProcessHost whose process matches + // the HWND. + static const int kMaxTries = 5; + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&NotifyPluginProcessHostHelper, window, parent, kMaxTries)); + return parent; +} + +BOOL CALLBACK PainEnumChildProc(HWND hwnd, LPARAM lparam) { + if (!webkit::npapi::WebPluginDelegateImpl::IsPluginDelegateWindow(hwnd)) + return TRUE; + + gfx::Rect* rect = reinterpret_cast<gfx::Rect*>(lparam); + static UINT msg = RegisterWindowMessage(webkit::npapi::kPaintMessageName); + WPARAM wparam = rect->x() << 16 | rect->y(); + lparam = rect->width() << 16 | rect->height(); + + // SendMessage gets the message across much quicker than PostMessage, since it + // doesn't get queued. When the plugin thread calls PeekMessage or other + // Win32 APIs, sent messages are dispatched automatically. + SendNotifyMessage(hwnd, msg, wparam, lparam); + + return TRUE; +} + +} // namespace + +// static +void RenderWidgetHostViewBase::MovePluginWindowsHelper( + HWND parent, + const std::vector<webkit::npapi::WebPluginGeometry>& moves) { + if (moves.empty()) + return; + + bool oop_plugins = + !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) && + !CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessPlugins); + + HDWP defer_window_pos_info = + ::BeginDeferWindowPos(static_cast<int>(moves.size())); + + if (!defer_window_pos_info) { + NOTREACHED(); + return; + } + + for (size_t i = 0; i < moves.size(); ++i) { + unsigned long flags = 0; + const webkit::npapi::WebPluginGeometry& move = moves[i]; + HWND window = move.window; + + // As the plugin parent window which lives on the browser UI thread is + // destroyed asynchronously, it is possible that we have a stale window + // sent in by the renderer for moving around. + // Note: get the parent before checking if the window is valid, to avoid a + // race condition where the window is destroyed after the check but before + // the GetParent call. + HWND cur_parent = ::GetParent(window); + if (!::IsWindow(window)) + continue; + + if (oop_plugins) { + if (cur_parent == parent) { + // The plugin window is a direct child of this window, add an + // intermediate window that lives on this thread to speed up scrolling. + // Note this only works with out of process plugins since we depend on + // PluginProcessHost to destroy the intermediate HWNDs. + cur_parent = ReparentWindow(window); + ::ShowWindow(window, SW_SHOW); // Window was created hidden. + } else if (::GetParent(cur_parent) != parent) { + // The renderer should only be trying to move windows that are children + // of its render widget window. However, this may happen as a result of + // a race condition, so we ignore it and not kill the plugin process. + continue; + } + + // We move the intermediate parent window which doesn't result in cross- + // process synchronous Windows messages. + window = cur_parent; + } + + if (move.visible) + flags |= SWP_SHOWWINDOW; + else + flags |= SWP_HIDEWINDOW; + +#if defined(USE_AURA) + // Without this flag, Windows repaints the parent area uncovered by this + // move. However it only looks at the plugin rectangle and ignores the + // clipping region. In Aura, the browser chrome could be under the plugin, + // and if Windows tries to paint it synchronously inside EndDeferWindowsPos + // then it won't have the data and it will flash white. So instead we + // manually redraw the plugin. + // Why not do this for native Windows? Not sure if there are any performance + // issues with this. + flags |= SWP_NOREDRAW; +#endif + + if (move.rects_valid) { + HRGN hrgn = ::CreateRectRgn(move.clip_rect.x(), + move.clip_rect.y(), + move.clip_rect.right(), + move.clip_rect.bottom()); + gfx::SubtractRectanglesFromRegion(hrgn, move.cutout_rects); + + // Note: System will own the hrgn after we call SetWindowRgn, + // so we don't need to call DeleteObject(hrgn) + ::SetWindowRgn(window, hrgn, !move.clip_rect.IsEmpty()); + } else { + flags |= SWP_NOMOVE; + flags |= SWP_NOSIZE; + } + + defer_window_pos_info = ::DeferWindowPos(defer_window_pos_info, + window, NULL, + move.window_rect.x(), + move.window_rect.y(), + move.window_rect.width(), + move.window_rect.height(), flags); + + if (!defer_window_pos_info) { + DCHECK(false) << "DeferWindowPos failed, so all plugin moves ignored."; + return; + } + } + + ::EndDeferWindowPos(defer_window_pos_info); + +#if defined(USE_AURA) + for (size_t i = 0; i < moves.size(); ++i) { + const webkit::npapi::WebPluginGeometry& move = moves[i]; + RECT r; + GetWindowRect(move.window, &r); + gfx::Rect gr(r); + PainEnumChildProc(move.window, reinterpret_cast<LPARAM>(&gr)); + } +#endif +} + +// static +void RenderWidgetHostViewBase::PaintPluginWindowsHelper( + HWND parent, const gfx::Rect& damaged_screen_rect) { + LPARAM lparam = reinterpret_cast<LPARAM>(&damaged_screen_rect); + EnumChildWindows(parent, PainEnumChildProc, lparam); +} + +#endif // OS_WIN + RenderWidgetHostViewBase::RenderWidgetHostViewBase() : popup_type_(WebKit::WebPopupTypeNone), mouse_locked_(false), diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h index a0a3d71..a584042 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h @@ -70,6 +70,17 @@ class CONTENT_EXPORT RenderWidgetHostViewBase // Interface class only, do not construct. RenderWidgetHostViewBase(); +#if defined(OS_WIN) + // Shared implementation of MovePluginWindows for use by win and aura/wina. + static void MovePluginWindowsHelper( + HWND parent, + const std::vector<webkit::npapi::WebPluginGeometry>& moves); + + static void PaintPluginWindowsHelper( + HWND parent, + const gfx::Rect& damaged_screen_rect); +#endif + // Whether this view is a popup and what kind of popup it is (select, // autofill...). WebKit::WebPopupType popup_type_; diff --git a/content/browser/renderer_host/render_widget_host_view_gtk.cc b/content/browser/renderer_host/render_widget_host_view_gtk.cc index 30d9fe6..4e98de1 100644 --- a/content/browser/renderer_host/render_widget_host_view_gtk.cc +++ b/content/browser/renderer_host/render_widget_host_view_gtk.cc @@ -758,6 +758,7 @@ gfx::NativeViewAccessible RenderWidgetHostViewGtk::GetNativeViewAccessible() { } void RenderWidgetHostViewGtk::MovePluginWindows( + const gfx::Point& scroll_offset, const std::vector<webkit::npapi::WebPluginGeometry>& moves) { for (size_t i = 0; i < moves.size(); ++i) { plugin_container_manager_.MovePluginContainer(moves[i]); diff --git a/content/browser/renderer_host/render_widget_host_view_gtk.h b/content/browser/renderer_host/render_widget_host_view_gtk.h index 70a5213..6e86079 100644 --- a/content/browser/renderer_host/render_widget_host_view_gtk.h +++ b/content/browser/renderer_host/render_widget_host_view_gtk.h @@ -74,6 +74,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGtk virtual void WasShown() OVERRIDE; virtual void WasHidden() OVERRIDE; virtual void MovePluginWindows( + const gfx::Point& scroll_offset, const std::vector<webkit::npapi::WebPluginGeometry>& moves) OVERRIDE; virtual void Focus() OVERRIDE; virtual void Blur() OVERRIDE; diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index e99ca40..922837a 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h @@ -227,6 +227,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase { virtual void WasShown() OVERRIDE; virtual void WasHidden() OVERRIDE; virtual void MovePluginWindows( + const gfx::Point& scroll_offset, const std::vector<webkit::npapi::WebPluginGeometry>& moves) OVERRIDE; virtual void Focus() OVERRIDE; virtual void Blur() OVERRIDE; diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 8d3854c..e33bfd6 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm @@ -479,6 +479,7 @@ gfx::NativeViewAccessible RenderWidgetHostViewMac::GetNativeViewAccessible() { } void RenderWidgetHostViewMac::MovePluginWindows( + const gfx::Point& scroll_offset, const std::vector<webkit::npapi::WebPluginGeometry>& moves) { TRACE_EVENT0("browser", "RenderWidgetHostViewMac::MovePluginWindows"); CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -1226,7 +1227,7 @@ void RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer( // plugin windows. if (params.window == gfx::kNullPluginWindow) { NOTIMPLEMENTED(); - AckPendingSwapBuffers(); + AckPendingSwapBuffers(); } else { // Deprecated accelerated plugin code path. AcceleratedPluginView* view = ViewForPluginWindowHandle(params.window); diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm index 8ae0705..80c9e02 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm @@ -115,6 +115,7 @@ class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness { geom.visible = true; geom.rects_valid = true; rwhv_mac_->MovePluginWindows( + gfx::Point(), std::vector<webkit::npapi::WebPluginGeometry>(1, geom)); return accelerated_handle; diff --git a/content/browser/renderer_host/render_widget_host_view_win.cc b/content/browser/renderer_host/render_widget_host_view_win.cc index 008aa09..3e6a217 100644 --- a/content/browser/renderer_host/render_widget_host_view_win.cc +++ b/content/browser/renderer_host/render_widget_host_view_win.cc @@ -28,7 +28,6 @@ #include "content/browser/gpu/gpu_data_manager_impl.h" #include "content/browser/gpu/gpu_process_host.h" #include "content/browser/gpu/gpu_process_host_ui_shim.h" -#include "content/browser/plugin_process_host.h" #include "content/browser/renderer_host/backing_store.h" #include "content/browser/renderer_host/backing_store_win.h" #include "content/browser/renderer_host/render_process_host_impl.h" @@ -60,7 +59,6 @@ #include "ui/base/win/hwnd_util.h" #include "ui/base/win/mouse_wheel_util.h" #include "ui/gfx/canvas.h" -#include "ui/gfx/gdi_util.h" #include "ui/gfx/rect.h" #include "ui/gfx/screen.h" #include "webkit/glue/webcursor.h" @@ -75,7 +73,6 @@ using WebKit::WebInputEvent; using WebKit::WebInputEventFactory; using WebKit::WebMouseEvent; using WebKit::WebTextDirection; -using webkit::npapi::WebPluginGeometry; namespace content { namespace { @@ -125,44 +122,6 @@ BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) { return TRUE; } -// |window| is the plugin HWND, created and destroyed in the plugin process. -// |parent| is the parent HWND, created and destroyed on the browser UI thread. -void NotifyPluginProcessHostHelper(HWND window, HWND parent, int tries) { - // How long to wait between each try. - static const int kTryDelayMs = 200; - - DWORD plugin_process_id; - bool found_starting_plugin_process = false; - GetWindowThreadProcessId(window, &plugin_process_id); - for (PluginProcessHostIterator iter; !iter.Done(); ++iter) { - if (!iter.GetData().handle) { - found_starting_plugin_process = true; - continue; - } - if (base::GetProcId(iter.GetData().handle) == plugin_process_id) { - iter->AddWindow(parent); - return; - } - } - - if (found_starting_plugin_process) { - // A plugin process has started but we don't have its handle yet. Since - // it's most likely the one for this plugin, try a few more times after a - // delay. - if (tries > 0) { - MessageLoop::current()->PostDelayedTask( - FROM_HERE, - base::Bind(&NotifyPluginProcessHostHelper, window, parent, tries - 1), - base::TimeDelta::FromMilliseconds(kTryDelayMs)); - return; - } - } - - // The plugin process might have died in the time to execute the task, don't - // leak the HWND. - PostMessage(parent, WM_CLOSE, 0, 0); -} - // Windows callback for OnDestroy to detach the plugin windows. BOOL CALLBACK DetachPluginWindowsCallback(HWND window, LPARAM param) { if (webkit::npapi::WebPluginDelegateImpl::IsPluginDelegateWindow(window) && @@ -173,26 +132,6 @@ BOOL CALLBACK DetachPluginWindowsCallback(HWND window, LPARAM param) { return TRUE; } -// The plugin wrapper window which lives in the browser process has this proc -// as its window procedure. We only handle the WM_PARENTNOTIFY message sent by -// windowed plugins for mouse input. This is forwarded off to the wrappers -// parent which is typically the RVH window which turns on user gesture. -LRESULT CALLBACK PluginWrapperWindowProc(HWND window, unsigned int message, - WPARAM wparam, LPARAM lparam) { - if (message == WM_PARENTNOTIFY) { - switch (LOWORD(wparam)) { - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: - case WM_MBUTTONDOWN: - ::SendMessage(GetParent(window), message, wparam, lparam); - return 0; - default: - break; - } - } - return ::DefWindowProc(window, message, wparam, lparam); -} - void SendToGpuProcessHost(int gpu_host_id, scoped_ptr<IPC::Message> message) { GpuProcessHost* gpu_process_host = GpuProcessHost::FromID(gpu_host_id); if (!gpu_process_host) @@ -713,140 +652,9 @@ RenderWidgetHostViewWin::GetNativeViewAccessible() { } void RenderWidgetHostViewWin::MovePluginWindows( - const std::vector<WebPluginGeometry>& plugin_window_moves) { - if (plugin_window_moves.empty()) - return; - - bool oop_plugins = - !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) && - !CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessPlugins); - - HDWP defer_window_pos_info = - ::BeginDeferWindowPos(static_cast<int>(plugin_window_moves.size())); - - if (!defer_window_pos_info) { - NOTREACHED(); - return; - } - - for (size_t i = 0; i < plugin_window_moves.size(); ++i) { - unsigned long flags = 0; - const WebPluginGeometry& move = plugin_window_moves[i]; - HWND window = move.window; - - // As the plugin parent window which lives on the browser UI thread is - // destroyed asynchronously, it is possible that we have a stale window - // sent in by the renderer for moving around. - // Note: get the parent before checking if the window is valid, to avoid a - // race condition where the window is destroyed after the check but before - // the GetParent call. - HWND parent = ::GetParent(window); - if (!::IsWindow(window)) - continue; - - if (oop_plugins) { - if (parent == m_hWnd) { - // The plugin window is a direct child of this window, add an - // intermediate window that lives on this thread to speed up scrolling. - // Note this only works with out of process plugins since we depend on - // PluginProcessHost to destroy the intermediate HWNDs. - parent = ReparentWindow(window); - ::ShowWindow(window, SW_SHOW); // Window was created hidden. - } else if (::GetParent(parent) != m_hWnd) { - // The renderer should only be trying to move windows that are children - // of its render widget window. However, this may happen as a result of - // a race condition, so we ignore it and not kill the plugin process. - continue; - } - - // We move the intermediate parent window which doesn't result in cross- - // process synchronous Windows messages. - window = parent; - } - - if (move.visible) - flags |= SWP_SHOWWINDOW; - else - flags |= SWP_HIDEWINDOW; - - if (move.rects_valid) { - HRGN hrgn = ::CreateRectRgn(move.clip_rect.x(), - move.clip_rect.y(), - move.clip_rect.right(), - move.clip_rect.bottom()); - gfx::SubtractRectanglesFromRegion(hrgn, move.cutout_rects); - - // Note: System will own the hrgn after we call SetWindowRgn, - // so we don't need to call DeleteObject(hrgn) - ::SetWindowRgn(window, hrgn, !move.clip_rect.IsEmpty()); - } else { - flags |= SWP_NOMOVE; - flags |= SWP_NOSIZE; - } - - defer_window_pos_info = ::DeferWindowPos(defer_window_pos_info, - window, NULL, - move.window_rect.x(), - move.window_rect.y(), - move.window_rect.width(), - move.window_rect.height(), flags); - if (!defer_window_pos_info) { - DCHECK(false) << "DeferWindowPos failed, so all plugin moves ignored."; - return; - } - } - - ::EndDeferWindowPos(defer_window_pos_info); -} - -HWND RenderWidgetHostViewWin::ReparentWindow(HWND window) { - static ATOM atom = 0; - static HMODULE instance = NULL; - if (!atom) { - WNDCLASSEX window_class; - base::win::InitializeWindowClass( - webkit::npapi::kWrapperNativeWindowClassName, - &base::win::WrappedWindowProc<PluginWrapperWindowProc>, - CS_DBLCLKS, - 0, - 0, - NULL, - reinterpret_cast<HBRUSH>(COLOR_WINDOW+1), - NULL, - NULL, - NULL, - &window_class); - instance = window_class.hInstance; - atom = RegisterClassEx(&window_class); - } - DCHECK(atom); - - HWND orig_parent = ::GetParent(window); - HWND parent = CreateWindowEx( - WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, - MAKEINTATOM(atom), 0, - WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, - 0, 0, 0, 0, orig_parent, 0, instance, 0); - ui::CheckWindowCreated(parent); - // If UIPI is enabled we need to add message filters for parents with - // children that cross process boundaries. - if (::GetPropW(orig_parent, webkit::npapi::kNativeWindowClassFilterProp)) { - // Process-wide message filters required on Vista must be added to: - // chrome_content_client.cc ChromeContentClient::SandboxPlugin - ChangeWindowMessageFilterEx(parent, WM_MOUSEWHEEL, MSGFLT_ALLOW, NULL); - ChangeWindowMessageFilterEx(parent, WM_GESTURE, MSGFLT_ALLOW, NULL); - ChangeWindowMessageFilterEx(parent, WM_APPCOMMAND, MSGFLT_ALLOW, NULL); - ::RemovePropW(orig_parent, webkit::npapi::kNativeWindowClassFilterProp); - } - ::SetParent(window, parent); - // How many times we try to find a PluginProcessHost whose process matches - // the HWND. - static const int kMaxTries = 5; - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(&NotifyPluginProcessHostHelper, window, parent, kMaxTries)); - return parent; + const gfx::Point& scroll_offset, + const std::vector<webkit::npapi::WebPluginGeometry>& plugin_window_moves) { + MovePluginWindowsHelper(m_hWnd, plugin_window_moves); } static BOOL CALLBACK AddChildWindowToVector(HWND hwnd, LPARAM lparam) { @@ -1002,23 +810,6 @@ void RenderWidgetHostViewWin::ImeCompositionRangeChanged( composition_character_bounds_ = character_bounds; } -BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lparam) { - if (!webkit::npapi::WebPluginDelegateImpl::IsPluginDelegateWindow(hwnd)) - return TRUE; - - gfx::Rect* rect = reinterpret_cast<gfx::Rect*>(lparam); - static UINT msg = RegisterWindowMessage(webkit::npapi::kPaintMessageName); - WPARAM wparam = rect->x() << 16 | rect->y(); - lparam = rect->width() << 16 | rect->height(); - - // SendMessage gets the message across much quicker than PostMessage, since it - // doesn't get queued. When the plugin thread calls PeekMessage or other - // Win32 APIs, sent messages are dispatched automatically. - SendNotifyMessage(hwnd, msg, wparam, lparam); - - return TRUE; -} - void RenderWidgetHostViewWin::Redraw() { RECT damage_bounds; GetUpdateRect(&damage_bounds, FALSE); @@ -1043,8 +834,7 @@ void RenderWidgetHostViewWin::Redraw() { gfx::Rect invalid_screen_rect(damage_bounds); invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y()); - LPARAM lparam = reinterpret_cast<LPARAM>(&invalid_screen_rect); - EnumChildWindows(m_hWnd, EnumChildProc, lparam); + PaintPluginWindowsHelper(m_hWnd, invalid_screen_rect); } void RenderWidgetHostViewWin::DidUpdateBackingStore( @@ -2701,7 +2491,7 @@ gfx::GLSurfaceHandle RenderWidgetHostViewWin::GetCompositingSurface() { } // On XP we need a child window that can be resized independently of the - // partent. + // parent. static ATOM atom = 0; static HMODULE instance = NULL; if (!atom) { diff --git a/content/browser/renderer_host/render_widget_host_view_win.h b/content/browser/renderer_host/render_widget_host_view_win.h index 0733372..bbd3f61a 100644 --- a/content/browser/renderer_host/render_widget_host_view_win.h +++ b/content/browser/renderer_host/render_widget_host_view_win.h @@ -170,6 +170,7 @@ class RenderWidgetHostViewWin virtual void WasShown() OVERRIDE; virtual void WasHidden() OVERRIDE; virtual void MovePluginWindows( + const gfx::Point& scroll_offset, const std::vector<webkit::npapi::WebPluginGeometry>& moves) OVERRIDE; virtual void Focus() OVERRIDE; virtual void Blur() OVERRIDE; @@ -380,9 +381,6 @@ class RenderWidgetHostViewWin // origin of |dc|. void DrawBackground(const RECT& rect, CPaintDC* dc); - // Create an intermediate window between the given HWND and its parent. - HWND ReparentWindow(HWND window); - // Clean up the compositor window, if needed. void CleanupCompositorWindow(); diff --git a/content/browser/renderer_host/test_render_view_host.h b/content/browser/renderer_host/test_render_view_host.h index 763a9ec..e805974 100644 --- a/content/browser/renderer_host/test_render_view_host.h +++ b/content/browser/renderer_host/test_render_view_host.h @@ -88,6 +88,7 @@ class TestRenderWidgetHostView : public RenderWidgetHostViewBase { virtual void WasShown() OVERRIDE {} virtual void WasHidden() OVERRIDE {} virtual void MovePluginWindows( + const gfx::Point& scroll_offset, const std::vector<webkit::npapi::WebPluginGeometry>& moves) OVERRIDE {} virtual void Focus() OVERRIDE {} virtual void Blur() OVERRIDE {} diff --git a/content/plugin/webplugin_delegate_stub.cc b/content/plugin/webplugin_delegate_stub.cc index c74f07b1..1c183e6 100644 --- a/content/plugin/webplugin_delegate_stub.cc +++ b/content/plugin/webplugin_delegate_stub.cc @@ -163,7 +163,12 @@ void WebPluginDelegateStub::OnInit(const PluginMsg_Init_Params& params, gfx::PluginWindowHandle parent = gfx::kNullPluginWindow; #if defined(USE_AURA) +#if defined(OS_WIN) + // Copy of gfx::NativeViewFromId that's defined without Aura. + parent = reinterpret_cast<HWND>(params.containing_window); +#else // Nothing. +#endif #elif defined(OS_WIN) parent = gfx::NativeViewFromId(params.containing_window); #elif defined(OS_LINUX) diff --git a/content/port/browser/render_widget_host_view_port.h b/content/port/browser/render_widget_host_view_port.h index 6d3f56b..8c60c76 100644 --- a/content/port/browser/render_widget_host_view_port.h +++ b/content/port/browser/render_widget_host_view_port.h @@ -73,7 +73,9 @@ class CONTENT_EXPORT RenderWidgetHostViewPort : public RenderWidgetHostView { virtual void WasHidden() = 0; // Moves all plugin windows as described in the given list. + // |scroll_offset| is the scroll offset of the render view. virtual void MovePluginWindows( + const gfx::Point& scroll_offset, const std::vector<webkit::npapi::WebPluginGeometry>& moves) = 0; // Take focus from the associated View component. diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index d2d7de3..6330cb2 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -4229,7 +4229,8 @@ WebKit::WebPlugin* RenderViewImpl::CreatePlugin( pepper_module.get(), params, pepper_delegate_.AsWeakPtr()); } -#if defined(USE_AURA) + +#if defined(USE_AURA) && !defined(OS_WIN) return NULL; #else return new webkit::npapi::WebPluginImpl( diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi index a0d1da9..d1fe4f6 100644 --- a/webkit/glue/webkit_glue.gypi +++ b/webkit/glue/webkit_glue.gypi @@ -420,7 +420,6 @@ ['use_aura==1', { 'sources/': [ ['exclude', '^\\.\\./plugins/npapi/webplugin_delegate_impl_mac.mm'], - ['exclude', '^\\.\\./plugins/npapi/webplugin_delegate_impl_win.cc'], ], 'sources!': [ 'webcursor_mac.mm', @@ -432,6 +431,11 @@ 'libraries': [ '-lXcursor', ], }, }], + ['use_aura==1 and OS=="win"', { + 'sources/': [ + ['exclude', '^\\.\\./plugins/npapi/webplugin_delegate_impl_aura'], + ], + }], ['OS!="mac"', { 'sources/': [['exclude', '_mac\\.(cc|mm)$']], 'sources!': [ diff --git a/webkit/plugins/npapi/webplugin_delegate_impl.h b/webkit/plugins/npapi/webplugin_delegate_impl.h index 3a35703..5a5d96b 100644 --- a/webkit/plugins/npapi/webplugin_delegate_impl.h +++ b/webkit/plugins/npapi/webplugin_delegate_impl.h @@ -10,6 +10,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner_helpers.h" #include "base/time.h" #include "base/timer.h" @@ -21,10 +22,6 @@ #include "webkit/plugins/npapi/webplugin_delegate.h" #include "webkit/plugins/webkit_plugins_export.h" -#if defined(OS_WIN) && !defined(USE_AURA) -#include "base/memory/weak_ptr.h" -#endif - #if defined(USE_X11) #include "ui/base/x/x11_util.h" @@ -53,7 +50,7 @@ class WebPluginAcceleratedSurface; class ExternalDragTracker; #endif // OS_MACOSX -#if defined(OS_WIN) && !defined(USE_AURA) +#if defined(OS_WIN) class WebPluginIMEWin; #endif // OS_WIN @@ -88,15 +85,17 @@ class WEBKIT_PLUGINS_EXPORT WebPluginDelegateImpl : public WebPluginDelegate { const std::string& mime_type, gfx::PluginWindowHandle containing_view); - static bool IsPluginDelegateWindow(gfx::NativeWindow window); - static bool GetPluginNameFromWindow(gfx::NativeWindow window, +#if defined(OS_WIN) + static bool IsPluginDelegateWindow(HWND window); + static bool GetPluginNameFromWindow(HWND window, string16* plugin_name); - static bool GetPluginVersionFromWindow(gfx::NativeWindow window, + static bool GetPluginVersionFromWindow(HWND window, string16* plugin_version); // Returns true if the window handle passed in is that of the dummy // activation window for windowless plugins. - static bool IsDummyActivationWindow(gfx::NativeWindow window); + static bool IsDummyActivationWindow(HWND window); +#endif // WebPluginDelegate implementation virtual bool Initialize(const GURL& url, @@ -148,7 +147,7 @@ class WEBKIT_PLUGINS_EXPORT WebPluginDelegateImpl : public WebPluginDelegate { // Informs the plugin that the view it is in has gained or lost focus. void SetContentAreaHasFocus(bool has_focus); -#if defined(OS_WIN) && !defined(USE_AURA) +#if defined(OS_WIN) // Informs the plug-in that an IME has changed its status. void ImeCompositionUpdated(const string16& text, const std::vector<int>& clauses, @@ -332,7 +331,7 @@ class WEBKIT_PLUGINS_EXPORT WebPluginDelegateImpl : public WebPluginDelegate { WebPlugin* plugin_; scoped_refptr<PluginInstance> instance_; -#if defined(OS_WIN) && !defined(USE_AURA) +#if defined(OS_WIN) // Original wndproc before we subclassed. WNDPROC plugin_wnd_proc_; @@ -372,7 +371,7 @@ class WEBKIT_PLUGINS_EXPORT WebPluginDelegateImpl : public WebPluginDelegate { gfx::Rect clip_rect_; int quirks_; -#if defined(OS_WIN) && !defined(USE_AURA) +#if defined(OS_WIN) // Windowless plugins don't have keyboard focus causing issues with the // plugin not receiving keyboard events if the plugin enters a modal // loop like TrackPopupMenuEx or MessageBox, etc. @@ -500,7 +499,7 @@ class WEBKIT_PLUGINS_EXPORT WebPluginDelegateImpl : public WebPluginDelegate { // The url with which the plugin was instantiated. std::string plugin_url_; -#if defined(OS_WIN) && !defined(USE_AURA) +#if defined(OS_WIN) // Indicates the end of a user gesture period. void OnUserGestureEnd(); diff --git a/webkit/plugins/npapi/webplugin_delegate_impl_win.cc b/webkit/plugins/npapi/webplugin_delegate_impl_win.cc index 594d61f..4e4273db 100644 --- a/webkit/plugins/npapi/webplugin_delegate_impl_win.cc +++ b/webkit/plugins/npapi/webplugin_delegate_impl_win.cc @@ -1515,6 +1515,8 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent( // exceptions, such as IME, where it sometimes returns true. ret = true; +// TODO(jam): do we need this for Aura? +#if !defined(USE_AURA) if (np_event.event == WM_MOUSEMOVE) { current_windowless_cursor_.InitFromExternalCursor(GetCursor()); // Snag a reference to the current cursor ASAP in case the plugin modified @@ -1522,6 +1524,7 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent( // as someone might be setting the cursor in the main process as well. current_windowless_cursor_.GetCursorInfo(cursor_info); } +#endif handle_event_depth_--; |