Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(409)

Side by Side Diff: content/browser/renderer_host/render_widget_host_view_base.cc

Issue 10905122: Initial NPAPI plugin support in Win Aura. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: sync Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/render_widget_host_view_base.h" 5 #include "content/browser/renderer_host/render_widget_host_view_base.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "content/browser/accessibility/browser_accessibility_manager.h" 8 #include "content/browser/accessibility/browser_accessibility_manager.h"
9 #include "content/browser/renderer_host/render_widget_host_impl.h" 9 #include "content/browser/renderer_host/render_widget_host_impl.h"
10 #include "content/port/browser/smooth_scroll_gesture.h" 10 #include "content/port/browser/smooth_scroll_gesture.h"
11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h" 11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h"
12 #include "ui/gfx/display.h" 12 #include "ui/gfx/display.h"
13 #include "ui/gfx/screen.h" 13 #include "ui/gfx/screen.h"
14 14
15 #if defined(OS_WIN)
16 #include "base/command_line.h"
17 #include "base/message_loop.h"
18 #include "base/win/wrapped_window_proc.h"
19 #include "content/browser/plugin_process_host.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/child_process_data.h"
22 #include "content/public/common/content_switches.h"
23 #include "ui/base/win/hwnd_util.h"
24 #include "ui/gfx/gdi_util.h"
25 #include "webkit/plugins/npapi/plugin_constants_win.h"
26 #include "webkit/plugins/npapi/webplugin.h"
27 #include "webkit/plugins/npapi/webplugin_delegate_impl.h"
28 #endif
29
15 #if defined(TOOLKIT_GTK) 30 #if defined(TOOLKIT_GTK)
16 #include <gdk/gdkx.h> 31 #include <gdk/gdkx.h>
17 #include <gtk/gtk.h> 32 #include <gtk/gtk.h>
18 33
19 #include "content/browser/renderer_host/gtk_window_utils.h" 34 #include "content/browser/renderer_host/gtk_window_utils.h"
20 #endif 35 #endif
21 36
22 namespace content { 37 namespace content {
23 38
24 // How long a smooth scroll gesture should run when it is a near scroll. 39 // How long a smooth scroll gesture should run when it is a near scroll.
25 static const int64 kDurationOfNearScrollGestureMs = 150; 40 static const int64 kDurationOfNearScrollGestureMs = 150;
26 41
27 // How long a smooth scroll gesture should run when it is a far scroll. 42 // How long a smooth scroll gesture should run when it is a far scroll.
28 static const int64 kDurationOfFarScrollGestureMs = 500; 43 static const int64 kDurationOfFarScrollGestureMs = 500;
29 44
30 // static 45 // static
31 RenderWidgetHostViewPort* RenderWidgetHostViewPort::FromRWHV( 46 RenderWidgetHostViewPort* RenderWidgetHostViewPort::FromRWHV(
32 RenderWidgetHostView* rwhv) { 47 RenderWidgetHostView* rwhv) {
33 return static_cast<RenderWidgetHostViewPort*>(rwhv); 48 return static_cast<RenderWidgetHostViewPort*>(rwhv);
34 } 49 }
35 50
36 // static 51 // static
37 RenderWidgetHostViewPort* RenderWidgetHostViewPort::CreateViewForWidget( 52 RenderWidgetHostViewPort* RenderWidgetHostViewPort::CreateViewForWidget(
38 content::RenderWidgetHost* widget) { 53 content::RenderWidgetHost* widget) {
39 return FromRWHV(RenderWidgetHostView::CreateViewForWidget(widget)); 54 return FromRWHV(RenderWidgetHostView::CreateViewForWidget(widget));
40 } 55 }
41 56
57 #if defined(OS_WIN)
58
59 namespace {
60
61 // |window| is the plugin HWND, created and destroyed in the plugin process.
62 // |parent| is the parent HWND, created and destroyed on the browser UI thread.
63 void NotifyPluginProcessHostHelper(HWND window, HWND parent, int tries) {
64 // How long to wait between each try.
65 static const int kTryDelayMs = 200;
66
67 DWORD plugin_process_id;
68 bool found_starting_plugin_process = false;
69 GetWindowThreadProcessId(window, &plugin_process_id);
70 for (PluginProcessHostIterator iter; !iter.Done(); ++iter) {
71 if (!iter.GetData().handle) {
72 found_starting_plugin_process = true;
73 continue;
74 }
75 if (base::GetProcId(iter.GetData().handle) == plugin_process_id) {
76 iter->AddWindow(parent);
77 return;
78 }
79 }
80
81 if (found_starting_plugin_process) {
82 // A plugin process has started but we don't have its handle yet. Since
83 // it's most likely the one for this plugin, try a few more times after a
84 // delay.
85 if (tries > 0) {
86 MessageLoop::current()->PostDelayedTask(
87 FROM_HERE,
88 base::Bind(&NotifyPluginProcessHostHelper, window, parent, tries - 1),
89 base::TimeDelta::FromMilliseconds(kTryDelayMs));
90 return;
91 }
92 }
93
94 // The plugin process might have died in the time to execute the task, don't
95 // leak the HWND.
96 PostMessage(parent, WM_CLOSE, 0, 0);
97 }
98
99 // The plugin wrapper window which lives in the browser process has this proc
100 // as its window procedure. We only handle the WM_PARENTNOTIFY message sent by
101 // windowed plugins for mouse input. This is forwarded off to the wrappers
102 // parent which is typically the RVH window which turns on user gesture.
103 LRESULT CALLBACK PluginWrapperWindowProc(HWND window, unsigned int message,
104 WPARAM wparam, LPARAM lparam) {
105 if (message == WM_PARENTNOTIFY) {
106 switch (LOWORD(wparam)) {
107 case WM_LBUTTONDOWN:
108 case WM_RBUTTONDOWN:
109 case WM_MBUTTONDOWN:
110 ::SendMessage(GetParent(window), message, wparam, lparam);
111 return 0;
112 default:
113 break;
114 }
115 }
116 return ::DefWindowProc(window, message, wparam, lparam);
117 }
118
119 // Create an intermediate window between the given HWND and its parent.
120 HWND ReparentWindow(HWND window) {
121 static ATOM atom = 0;
122 static HMODULE instance = NULL;
123 if (!atom) {
124 WNDCLASSEX window_class;
125 base::win::InitializeWindowClass(
126 webkit::npapi::kWrapperNativeWindowClassName,
127 &base::win::WrappedWindowProc<PluginWrapperWindowProc>,
128 CS_DBLCLKS,
129 0,
130 0,
131 NULL,
132 // xxx reinterpret_cast<HBRUSH>(COLOR_WINDOW+1),
133 reinterpret_cast<HBRUSH>(COLOR_GRAYTEXT+1),
134 NULL,
135 NULL,
136 NULL,
137 &window_class);
138 instance = window_class.hInstance;
139 atom = RegisterClassEx(&window_class);
140 }
141 DCHECK(atom);
142
143 HWND orig_parent = ::GetParent(window);
144 HWND parent = CreateWindowEx(
145 WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
146 MAKEINTATOM(atom), 0,
147 WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
148 0, 0, 0, 0, orig_parent, 0, instance, 0);
149 ui::CheckWindowCreated(parent);
150 // If UIPI is enabled we need to add message filters for parents with
151 // children that cross process boundaries.
152 if (::GetPropW(orig_parent, webkit::npapi::kNativeWindowClassFilterProp)) {
153 // Process-wide message filters required on Vista must be added to:
154 // chrome_content_client.cc ChromeContentClient::SandboxPlugin
155 ChangeWindowMessageFilterEx(parent, WM_MOUSEWHEEL, MSGFLT_ALLOW, NULL);
156 ChangeWindowMessageFilterEx(parent, WM_GESTURE, MSGFLT_ALLOW, NULL);
157 ChangeWindowMessageFilterEx(parent, WM_APPCOMMAND, MSGFLT_ALLOW, NULL);
158 ::RemovePropW(orig_parent, webkit::npapi::kNativeWindowClassFilterProp);
159 }
160 ::SetParent(window, parent);
161 // How many times we try to find a PluginProcessHost whose process matches
162 // the HWND.
163 static const int kMaxTries = 5;
164 BrowserThread::PostTask(
165 BrowserThread::IO,
166 FROM_HERE,
167 base::Bind(&NotifyPluginProcessHostHelper, window, parent, kMaxTries));
168 return parent;
169 }
170
171 BOOL CALLBACK PainEnumChildProc(HWND hwnd, LPARAM lparam) {
172 if (!webkit::npapi::WebPluginDelegateImpl::IsPluginDelegateWindow(hwnd))
173 return TRUE;
174
175 gfx::Rect* rect = reinterpret_cast<gfx::Rect*>(lparam);
176 static UINT msg = RegisterWindowMessage(webkit::npapi::kPaintMessageName);
177 WPARAM wparam = rect->x() << 16 | rect->y();
178 lparam = rect->width() << 16 | rect->height();
179
180 // SendMessage gets the message across much quicker than PostMessage, since it
181 // doesn't get queued. When the plugin thread calls PeekMessage or other
182 // Win32 APIs, sent messages are dispatched automatically.
183 SendNotifyMessage(hwnd, msg, wparam, lparam);
184
185 return TRUE;
186 }
187
188 } // namespace
189
190 // static
191 void RenderWidgetHostViewBase::MovePluginWindowsHelper(
192 HWND parent,
193 const std::vector<webkit::npapi::WebPluginGeometry>& moves) {
194 if (moves.empty())
195 return;
196
197 bool oop_plugins =
198 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) &&
199 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessPlugins);
200
201 HDWP defer_window_pos_info =
202 ::BeginDeferWindowPos(static_cast<int>(moves.size()));
203
204 if (!defer_window_pos_info) {
205 NOTREACHED();
206 return;
207 }
208
209 for (size_t i = 0; i < moves.size(); ++i) {
210 unsigned long flags = 0;
211 const webkit::npapi::WebPluginGeometry& move = moves[i];
212 HWND window = move.window;
213
214 // As the plugin parent window which lives on the browser UI thread is
215 // destroyed asynchronously, it is possible that we have a stale window
216 // sent in by the renderer for moving around.
217 // Note: get the parent before checking if the window is valid, to avoid a
218 // race condition where the window is destroyed after the check but before
219 // the GetParent call.
220 HWND cur_parent = ::GetParent(window);
221 if (!::IsWindow(window))
222 continue;
223
224 if (oop_plugins) {
225 if (cur_parent == parent) {
226 // The plugin window is a direct child of this window, add an
227 // intermediate window that lives on this thread to speed up scrolling.
228 // Note this only works with out of process plugins since we depend on
229 // PluginProcessHost to destroy the intermediate HWNDs.
230 cur_parent = ReparentWindow(window);
231 ::ShowWindow(window, SW_SHOW); // Window was created hidden.
232 } else if (::GetParent(cur_parent) != parent) {
233 // The renderer should only be trying to move windows that are children
234 // of its render widget window. However, this may happen as a result of
235 // a race condition, so we ignore it and not kill the plugin process.
236 continue;
237 }
238
239 // We move the intermediate parent window which doesn't result in cross-
240 // process synchronous Windows messages.
241 window = cur_parent;
242 }
243
244 if (move.visible)
245 flags |= SWP_SHOWWINDOW;
246 else
247 flags |= SWP_HIDEWINDOW;
248
249 #if defined(USE_AURA)
250 // Without this flag, Windows repaints the parent area uncovered by this
251 // move. However it only looks at the plugin rectangle and ignores the
252 // clipping region. In Aura, the browser chrome could be under the plugin,
253 // and if Windows tries to paint it synchronously inside EndDeferWindowsPos
254 // then it won't have the data and it will flash white. So instead we
255 // manually redraw the plugin.
256 // Why not do this for native Windows? Not sure if there are any performance
257 // issues with this.
258 flags |= SWP_NOREDRAW;
259 #endif
260
261 if (move.rects_valid) {
262 HRGN hrgn = ::CreateRectRgn(move.clip_rect.x(),
263 move.clip_rect.y(),
264 move.clip_rect.right(),
265 move.clip_rect.bottom());
266 gfx::SubtractRectanglesFromRegion(hrgn, move.cutout_rects);
267
268 // Note: System will own the hrgn after we call SetWindowRgn,
269 // so we don't need to call DeleteObject(hrgn)
270 ::SetWindowRgn(window, hrgn, !move.clip_rect.IsEmpty());
271 } else {
272 flags |= SWP_NOMOVE;
273 flags |= SWP_NOSIZE;
274 }
275
276 defer_window_pos_info = ::DeferWindowPos(defer_window_pos_info,
277 window, NULL,
278 move.window_rect.x(),
279 move.window_rect.y(),
280 move.window_rect.width(),
281 move.window_rect.height(), flags);
282
283 if (!defer_window_pos_info) {
284 DCHECK(false) << "DeferWindowPos failed, so all plugin moves ignored.";
285 return;
286 }
287 }
288
289 ::EndDeferWindowPos(defer_window_pos_info);
290
291 #if defined(USE_AURA)
292 for (size_t i = 0; i < moves.size(); ++i) {
293 const webkit::npapi::WebPluginGeometry& move = moves[i];
294 RECT r;
295 GetWindowRect(move.window, &r);
296 gfx::Rect gr(r);
297 PainEnumChildProc(move.window, reinterpret_cast<LPARAM>(&gr));
298 }
299 #endif
300 }
301
302 // static
303 void RenderWidgetHostViewBase::PaintPluginWindowsHelper(
304 HWND parent, const gfx::Rect& damaged_screen_rect) {
305 LPARAM lparam = reinterpret_cast<LPARAM>(&damaged_screen_rect);
306 EnumChildWindows(parent, PainEnumChildProc, lparam);
307 }
308
309 #endif // OS_WIN
310
42 RenderWidgetHostViewBase::RenderWidgetHostViewBase() 311 RenderWidgetHostViewBase::RenderWidgetHostViewBase()
43 : popup_type_(WebKit::WebPopupTypeNone), 312 : popup_type_(WebKit::WebPopupTypeNone),
44 mouse_locked_(false), 313 mouse_locked_(false),
45 showing_context_menu_(false), 314 showing_context_menu_(false),
46 selection_text_offset_(0), 315 selection_text_offset_(0),
47 selection_range_(ui::Range::InvalidRange()), 316 selection_range_(ui::Range::InvalidRange()),
48 current_device_scale_factor_(0) { 317 current_device_scale_factor_(0) {
49 } 318 }
50 319
51 RenderWidgetHostViewBase::~RenderWidgetHostViewBase() { 320 RenderWidgetHostViewBase::~RenderWidgetHostViewBase() {
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 bool scroll_down_; 432 bool scroll_down_;
164 bool scroll_far_; 433 bool scroll_far_;
165 }; 434 };
166 435
167 SmoothScrollGesture* RenderWidgetHostViewBase::CreateSmoothScrollGesture( 436 SmoothScrollGesture* RenderWidgetHostViewBase::CreateSmoothScrollGesture(
168 bool scroll_down, bool scroll_far) { 437 bool scroll_down, bool scroll_far) {
169 return new BasicMouseWheelSmoothScrollGesture(scroll_down, scroll_far); 438 return new BasicMouseWheelSmoothScrollGesture(scroll_down, scroll_far);
170 } 439 }
171 440
172 } // namespace content 441 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698