• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "content/browser/renderer_host/render_widget_host_view_base.h"
6 
7 #include "base/logging.h"
8 #include "content/browser/accessibility/browser_accessibility_manager.h"
9 #include "content/browser/gpu/gpu_data_manager_impl.h"
10 #include "content/browser/renderer_host/input/synthetic_gesture_target_base.h"
11 #include "content/browser/renderer_host/render_process_host_impl.h"
12 #include "content/browser/renderer_host/render_widget_host_impl.h"
13 #include "content/port/browser/render_widget_host_view_frame_subscriber.h"
14 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
15 #include "ui/gfx/display.h"
16 #include "ui/gfx/screen.h"
17 #include "ui/gfx/size_conversions.h"
18 #include "ui/gfx/size_f.h"
19 
20 #if defined(OS_WIN)
21 #include "base/command_line.h"
22 #include "base/message_loop/message_loop.h"
23 #include "base/win/wrapped_window_proc.h"
24 #include "content/browser/plugin_process_host.h"
25 #include "content/browser/plugin_service_impl.h"
26 #include "content/common/plugin_constants_win.h"
27 #include "content/common/webplugin_geometry.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/child_process_data.h"
30 #include "content/public/common/content_switches.h"
31 #include "ui/gfx/gdi_util.h"
32 #include "ui/gfx/win/dpi.h"
33 #include "ui/gfx/win/hwnd_util.h"
34 #endif
35 
36 #if defined(TOOLKIT_GTK)
37 #include <gdk/gdkx.h>
38 #include <gtk/gtk.h>
39 
40 #include "content/browser/renderer_host/gtk_window_utils.h"
41 #endif
42 
43 namespace content {
44 
45 // static
FromRWHV(RenderWidgetHostView * rwhv)46 RenderWidgetHostViewPort* RenderWidgetHostViewPort::FromRWHV(
47     RenderWidgetHostView* rwhv) {
48   return static_cast<RenderWidgetHostViewPort*>(rwhv);
49 }
50 
51 // static
CreateViewForWidget(RenderWidgetHost * widget)52 RenderWidgetHostViewPort* RenderWidgetHostViewPort::CreateViewForWidget(
53     RenderWidgetHost* widget) {
54   return FromRWHV(RenderWidgetHostView::CreateViewForWidget(widget));
55 }
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.
NotifyPluginProcessHostHelper(HWND window,HWND parent,int tries)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       base::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.
PluginWrapperWindowProc(HWND window,unsigned int message,WPARAM wparam,LPARAM lparam)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 
IsPluginWrapperWindow(HWND window)119 bool IsPluginWrapperWindow(HWND window) {
120   return gfx::GetClassNameW(window) ==
121       base::string16(kWrapperNativeWindowClassName);
122 }
123 
124 // Create an intermediate window between the given HWND and its parent.
ReparentWindow(HWND window,HWND parent)125 HWND ReparentWindow(HWND window, HWND parent) {
126   static ATOM atom = 0;
127   static HMODULE instance = NULL;
128   if (!atom) {
129     WNDCLASSEX window_class;
130     base::win::InitializeWindowClass(
131         kWrapperNativeWindowClassName,
132         &base::win::WrappedWindowProc<PluginWrapperWindowProc>,
133         CS_DBLCLKS,
134         0,
135         0,
136         NULL,
137         // xxx reinterpret_cast<HBRUSH>(COLOR_WINDOW+1),
138         reinterpret_cast<HBRUSH>(COLOR_GRAYTEXT+1),
139         NULL,
140         NULL,
141         NULL,
142         &window_class);
143     instance = window_class.hInstance;
144     atom = RegisterClassEx(&window_class);
145   }
146   DCHECK(atom);
147 
148   HWND new_parent = CreateWindowEx(
149       WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
150       MAKEINTATOM(atom), 0,
151       WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
152       0, 0, 0, 0, parent, 0, instance, 0);
153   gfx::CheckWindowCreated(new_parent);
154   ::SetParent(window, new_parent);
155   // How many times we try to find a PluginProcessHost whose process matches
156   // the HWND.
157   static const int kMaxTries = 5;
158   BrowserThread::PostTask(
159       BrowserThread::IO,
160       FROM_HERE,
161       base::Bind(&NotifyPluginProcessHostHelper, window, new_parent,
162                  kMaxTries));
163   return new_parent;
164 }
165 
PaintEnumChildProc(HWND hwnd,LPARAM lparam)166 BOOL CALLBACK PaintEnumChildProc(HWND hwnd, LPARAM lparam) {
167   if (!PluginServiceImpl::GetInstance()->IsPluginWindow(hwnd))
168     return TRUE;
169 
170   gfx::Rect* rect = reinterpret_cast<gfx::Rect*>(lparam);
171   gfx::Rect rect_in_pixels = gfx::win::DIPToScreenRect(*rect);
172   static UINT msg = RegisterWindowMessage(kPaintMessageName);
173   WPARAM wparam = MAKEWPARAM(rect_in_pixels.x(), rect_in_pixels.y());
174   lparam = MAKELPARAM(rect_in_pixels.width(), rect_in_pixels.height());
175 
176   // SendMessage gets the message across much quicker than PostMessage, since it
177   // doesn't get queued.  When the plugin thread calls PeekMessage or other
178   // Win32 APIs, sent messages are dispatched automatically.
179   SendNotifyMessage(hwnd, msg, wparam, lparam);
180 
181   return TRUE;
182 }
183 
184 // Windows callback for OnDestroy to detach the plugin windows.
DetachPluginWindowsCallbackInternal(HWND window,LPARAM param)185 BOOL CALLBACK DetachPluginWindowsCallbackInternal(HWND window, LPARAM param) {
186   RenderWidgetHostViewBase::DetachPluginWindowsCallback(window);
187   return TRUE;
188 }
189 
190 }  // namespace
191 
192 // static
DetachPluginWindowsCallback(HWND window)193 void RenderWidgetHostViewBase::DetachPluginWindowsCallback(HWND window) {
194   if (PluginServiceImpl::GetInstance()->IsPluginWindow(window) &&
195       !IsHungAppWindow(window)) {
196     ::ShowWindow(window, SW_HIDE);
197     SetParent(window, NULL);
198   }
199 }
200 
201 // static
MovePluginWindowsHelper(HWND parent,const std::vector<WebPluginGeometry> & moves)202 void RenderWidgetHostViewBase::MovePluginWindowsHelper(
203     HWND parent,
204     const std::vector<WebPluginGeometry>& moves) {
205   if (moves.empty())
206     return;
207 
208   bool oop_plugins =
209     !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) &&
210     !CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessPlugins);
211 
212   HDWP defer_window_pos_info =
213       ::BeginDeferWindowPos(static_cast<int>(moves.size()));
214 
215   if (!defer_window_pos_info) {
216     NOTREACHED();
217     return;
218   }
219 
220 #if defined(USE_AURA)
221   std::vector<RECT> invalidate_rects;
222 #endif
223 
224   for (size_t i = 0; i < moves.size(); ++i) {
225     unsigned long flags = 0;
226     const WebPluginGeometry& move = moves[i];
227     HWND window = move.window;
228 
229     // As the plugin parent window which lives on the browser UI thread is
230     // destroyed asynchronously, it is possible that we have a stale window
231     // sent in by the renderer for moving around.
232     // Note: get the parent before checking if the window is valid, to avoid a
233     // race condition where the window is destroyed after the check but before
234     // the GetParent call.
235     HWND cur_parent = ::GetParent(window);
236     if (!::IsWindow(window))
237       continue;
238 
239     if (!PluginServiceImpl::GetInstance()->IsPluginWindow(window)) {
240       // The renderer should only be trying to move plugin windows. However,
241       // this may happen as a result of a race condition (i.e. even after the
242       // check right above), so we ignore it.
243       continue;
244     }
245 
246     if (oop_plugins) {
247       if (cur_parent == GetDesktopWindow()) {
248         // The plugin window hasn't been parented yet, add an intermediate
249         // window that lives on this thread to speed up scrolling. Note this
250         // only works with out of process plugins since we depend on
251         // PluginProcessHost to destroy the intermediate HWNDs.
252         cur_parent = ReparentWindow(window, parent);
253         ::ShowWindow(window, SW_SHOW);  // Window was created hidden.
254       } else if (!IsPluginWrapperWindow(cur_parent)) {
255         continue;  // Race if plugin process is shutting down.
256       }
257 
258       // We move the intermediate parent window which doesn't result in cross-
259       // process synchronous Windows messages.
260       window = cur_parent;
261     } else {
262       if (cur_parent == GetDesktopWindow())
263         SetParent(window, parent);
264     }
265 
266     if (move.visible)
267       flags |= SWP_SHOWWINDOW;
268     else
269       flags |= SWP_HIDEWINDOW;
270 
271 #if defined(USE_AURA)
272     if (GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
273       // Without this flag, Windows repaints the parent area uncovered by this
274       // move. However when software compositing is used the clipping region is
275       // ignored. Since in Aura the browser chrome could be under the plugin, if
276       // if Windows tries to paint it synchronously inside EndDeferWindowsPos
277       // then it won't have the data and it will flash white. So instead we
278       // manually redraw the plugin.
279       // Why not do this for native Windows? Not sure if there are any
280       // performance issues with this.
281       flags |= SWP_NOREDRAW;
282     }
283 #endif
284 
285     if (move.rects_valid) {
286       gfx::Rect clip_rect_in_pixel = gfx::win::DIPToScreenRect(move.clip_rect);
287       HRGN hrgn = ::CreateRectRgn(clip_rect_in_pixel.x(),
288                                   clip_rect_in_pixel.y(),
289                                   clip_rect_in_pixel.right(),
290                                   clip_rect_in_pixel.bottom());
291       gfx::SubtractRectanglesFromRegion(hrgn, move.cutout_rects);
292 
293       // Note: System will own the hrgn after we call SetWindowRgn,
294       // so we don't need to call DeleteObject(hrgn)
295       ::SetWindowRgn(window, hrgn, !move.clip_rect.IsEmpty());
296 
297 #if defined(USE_AURA)
298       // When using the software compositor, if the clipping rectangle is empty
299       // then DeferWindowPos won't redraw the newly uncovered area under the
300       // plugin.
301       if (clip_rect_in_pixel.IsEmpty() &&
302           !GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
303         RECT r;
304         GetClientRect(window, &r);
305         MapWindowPoints(window, parent, reinterpret_cast<POINT*>(&r), 2);
306         invalidate_rects.push_back(r);
307       }
308 #endif
309     } else {
310       flags |= SWP_NOMOVE;
311       flags |= SWP_NOSIZE;
312     }
313 
314     gfx::Rect window_rect_in_pixel =
315         gfx::win::DIPToScreenRect(move.window_rect);
316     defer_window_pos_info = ::DeferWindowPos(defer_window_pos_info,
317                                              window, NULL,
318                                              window_rect_in_pixel.x(),
319                                              window_rect_in_pixel.y(),
320                                              window_rect_in_pixel.width(),
321                                              window_rect_in_pixel.height(),
322                                              flags);
323 
324     if (!defer_window_pos_info) {
325       DCHECK(false) << "DeferWindowPos failed, so all plugin moves ignored.";
326       return;
327     }
328   }
329 
330   ::EndDeferWindowPos(defer_window_pos_info);
331 
332 #if defined(USE_AURA)
333   if (GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
334     for (size_t i = 0; i < moves.size(); ++i) {
335       const WebPluginGeometry& move = moves[i];
336       RECT r;
337       GetWindowRect(move.window, &r);
338       gfx::Rect gr(r);
339       PaintEnumChildProc(move.window, reinterpret_cast<LPARAM>(&gr));
340     }
341   } else {
342       for (size_t i = 0; i < invalidate_rects.size(); ++i) {
343       ::RedrawWindow(
344           parent, &invalidate_rects[i], NULL,
345           // These flags are from WebPluginDelegateImpl::NativeWndProc.
346           RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_FRAME | RDW_UPDATENOW);
347     }
348   }
349 #endif
350 }
351 
352 // static
PaintPluginWindowsHelper(HWND parent,const gfx::Rect & damaged_screen_rect)353 void RenderWidgetHostViewBase::PaintPluginWindowsHelper(
354     HWND parent, const gfx::Rect& damaged_screen_rect) {
355   LPARAM lparam = reinterpret_cast<LPARAM>(&damaged_screen_rect);
356   EnumChildWindows(parent, PaintEnumChildProc, lparam);
357 }
358 
359 // static
DetachPluginsHelper(HWND parent)360 void RenderWidgetHostViewBase::DetachPluginsHelper(HWND parent) {
361   // When a tab is closed all its child plugin windows are destroyed
362   // automatically. This happens before plugins get any notification that its
363   // instances are tearing down.
364   //
365   // Plugins like Quicktime assume that their windows will remain valid as long
366   // as they have plugin instances active. Quicktime crashes in this case
367   // because its windowing code cleans up an internal data structure that the
368   // handler for NPP_DestroyStream relies on.
369   //
370   // The fix is to detach plugin windows from web contents when it is going
371   // away. This will prevent the plugin windows from getting destroyed
372   // automatically. The detached plugin windows will get cleaned up in proper
373   // sequence as part of the usual cleanup when the plugin instance goes away.
374   EnumChildWindows(parent, DetachPluginWindowsCallbackInternal, NULL);
375 }
376 
377 #endif  // OS_WIN
378 
379 namespace {
380 
381 // How many microseconds apart input events should be flushed.
382 const int kFlushInputRateInUs = 16666;
383 
384 }
385 
RenderWidgetHostViewBase()386 RenderWidgetHostViewBase::RenderWidgetHostViewBase()
387     : popup_type_(blink::WebPopupTypeNone),
388       mouse_locked_(false),
389       showing_context_menu_(false),
390       selection_text_offset_(0),
391       selection_range_(gfx::Range::InvalidRange()),
392       current_device_scale_factor_(0),
393       renderer_frame_number_(0) {
394 }
395 
~RenderWidgetHostViewBase()396 RenderWidgetHostViewBase::~RenderWidgetHostViewBase() {
397   DCHECK(!mouse_locked_);
398 }
399 
OnMessageReceived(const IPC::Message & msg)400 bool RenderWidgetHostViewBase::OnMessageReceived(const IPC::Message& msg){
401   return false;
402 }
403 
SetBackground(const SkBitmap & background)404 void RenderWidgetHostViewBase::SetBackground(const SkBitmap& background) {
405   background_ = background;
406 }
407 
GetBackground()408 const SkBitmap& RenderWidgetHostViewBase::GetBackground() {
409   return background_;
410 }
411 
GetPhysicalBackingSize() const412 gfx::Size RenderWidgetHostViewBase::GetPhysicalBackingSize() const {
413   gfx::NativeView view = GetNativeView();
414   gfx::Display display =
415       gfx::Screen::GetScreenFor(view)->GetDisplayNearestWindow(view);
416   return gfx::ToCeiledSize(gfx::ScaleSize(GetViewBounds().size(),
417                                           display.device_scale_factor()));
418 }
419 
GetOverdrawBottomHeight() const420 float RenderWidgetHostViewBase::GetOverdrawBottomHeight() const {
421   return 0.f;
422 }
423 
SelectionChanged(const base::string16 & text,size_t offset,const gfx::Range & range)424 void RenderWidgetHostViewBase::SelectionChanged(const base::string16& text,
425                                                 size_t offset,
426                                                 const gfx::Range& range) {
427   selection_text_ = text;
428   selection_text_offset_ = offset;
429   selection_range_.set_start(range.start());
430   selection_range_.set_end(range.end());
431 }
432 
IsShowingContextMenu() const433 bool RenderWidgetHostViewBase::IsShowingContextMenu() const {
434   return showing_context_menu_;
435 }
436 
SetShowingContextMenu(bool showing)437 void RenderWidgetHostViewBase::SetShowingContextMenu(bool showing) {
438   DCHECK_NE(showing_context_menu_, showing);
439   showing_context_menu_ = showing;
440 }
441 
GetSelectedText() const442 base::string16 RenderWidgetHostViewBase::GetSelectedText() const {
443   if (!selection_range_.IsValid())
444     return base::string16();
445   return selection_text_.substr(
446       selection_range_.GetMin() - selection_text_offset_,
447       selection_range_.length());
448 }
449 
IsMouseLocked()450 bool RenderWidgetHostViewBase::IsMouseLocked() {
451   return mouse_locked_;
452 }
453 
UnhandledWheelEvent(const blink::WebMouseWheelEvent & event)454 void RenderWidgetHostViewBase::UnhandledWheelEvent(
455     const blink::WebMouseWheelEvent& event) {
456   // Most implementations don't need to do anything here.
457 }
458 
FilterInputEvent(const blink::WebInputEvent & input_event)459 InputEventAckState RenderWidgetHostViewBase::FilterInputEvent(
460     const blink::WebInputEvent& input_event) {
461   // By default, input events are simply forwarded to the renderer.
462   return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
463 }
464 
OnDidFlushInput()465 void RenderWidgetHostViewBase::OnDidFlushInput() {
466   // The notification can safely be ignored by most implementations.
467 }
468 
OnSetNeedsFlushInput()469 void RenderWidgetHostViewBase::OnSetNeedsFlushInput() {
470   if (flush_input_timer_.IsRunning())
471     return;
472 
473   flush_input_timer_.Start(
474       FROM_HERE,
475       base::TimeDelta::FromMicroseconds(kFlushInputRateInUs),
476       this,
477       &RenderWidgetHostViewBase::FlushInput);
478 }
479 
GestureEventAck(int gesture_event_type,InputEventAckState ack_result)480 void RenderWidgetHostViewBase::GestureEventAck(int gesture_event_type,
481                                                InputEventAckState ack_result) {}
482 
SetPopupType(blink::WebPopupType popup_type)483 void RenderWidgetHostViewBase::SetPopupType(blink::WebPopupType popup_type) {
484   popup_type_ = popup_type;
485 }
486 
GetPopupType()487 blink::WebPopupType RenderWidgetHostViewBase::GetPopupType() {
488   return popup_type_;
489 }
490 
491 BrowserAccessibilityManager*
GetBrowserAccessibilityManager() const492     RenderWidgetHostViewBase::GetBrowserAccessibilityManager() const {
493   return browser_accessibility_manager_.get();
494 }
495 
SetBrowserAccessibilityManager(BrowserAccessibilityManager * manager)496 void RenderWidgetHostViewBase::SetBrowserAccessibilityManager(
497     BrowserAccessibilityManager* manager) {
498   browser_accessibility_manager_.reset(manager);
499 }
500 
UpdateScreenInfo(gfx::NativeView view)501 void RenderWidgetHostViewBase::UpdateScreenInfo(gfx::NativeView view) {
502   RenderWidgetHostImpl* impl = NULL;
503   if (GetRenderWidgetHost())
504     impl = RenderWidgetHostImpl::From(GetRenderWidgetHost());
505 
506   if (impl)
507     impl->SendScreenRects();
508 
509   if (HasDisplayPropertyChanged(view) && impl)
510     impl->NotifyScreenInfoChanged();
511 }
512 
HasDisplayPropertyChanged(gfx::NativeView view)513 bool RenderWidgetHostViewBase::HasDisplayPropertyChanged(gfx::NativeView view) {
514   gfx::Display display =
515       gfx::Screen::GetScreenFor(view)->GetDisplayNearestWindow(view);
516   if (current_display_area_ == display.work_area() &&
517       current_device_scale_factor_ == display.device_scale_factor()) {
518     return false;
519   }
520   current_display_area_ = display.work_area();
521   current_device_scale_factor_ = display.device_scale_factor();
522   return true;
523 }
524 
ProcessAckedTouchEvent(const TouchEventWithLatencyInfo & touch,InputEventAckState ack_result)525 void RenderWidgetHostViewBase::ProcessAckedTouchEvent(
526     const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
527 }
528 
529 scoped_ptr<SyntheticGestureTarget>
CreateSyntheticGestureTarget()530 RenderWidgetHostViewBase::CreateSyntheticGestureTarget() {
531   RenderWidgetHostImpl* host =
532       RenderWidgetHostImpl::From(GetRenderWidgetHost());
533   return scoped_ptr<SyntheticGestureTarget>(
534       new SyntheticGestureTargetBase(host));
535 }
536 
537 // Platform implementation should override this method to allow frame
538 // subscription. Frame subscriber is set to RenderProcessHost, which is
539 // platform independent. It should be set to the specific presenter on each
540 // platform.
CanSubscribeFrame() const541 bool RenderWidgetHostViewBase::CanSubscribeFrame() const {
542   NOTIMPLEMENTED();
543   return false;
544 }
545 
546 // Base implementation for this method sets the subscriber to RenderProcessHost,
547 // which is platform independent. Note: Implementation only support subscribing
548 // to accelerated composited frames.
BeginFrameSubscription(scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber)549 void RenderWidgetHostViewBase::BeginFrameSubscription(
550     scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
551   RenderWidgetHostImpl* impl = NULL;
552   if (GetRenderWidgetHost())
553     impl = RenderWidgetHostImpl::From(GetRenderWidgetHost());
554   if (!impl)
555     return;
556   RenderProcessHostImpl* render_process_host =
557       static_cast<RenderProcessHostImpl*>(impl->GetProcess());
558   render_process_host->BeginFrameSubscription(impl->GetRoutingID(),
559                                               subscriber.Pass());
560 }
561 
EndFrameSubscription()562 void RenderWidgetHostViewBase::EndFrameSubscription() {
563   RenderWidgetHostImpl* impl = NULL;
564   if (GetRenderWidgetHost())
565     impl = RenderWidgetHostImpl::From(GetRenderWidgetHost());
566   if (!impl)
567     return;
568   RenderProcessHostImpl* render_process_host =
569       static_cast<RenderProcessHostImpl*>(impl->GetProcess());
570   render_process_host->EndFrameSubscription(impl->GetRoutingID());
571 }
572 
OnOverscrolled(gfx::Vector2dF accumulated_overscroll,gfx::Vector2dF current_fling_velocity)573 void RenderWidgetHostViewBase::OnOverscrolled(
574     gfx::Vector2dF accumulated_overscroll,
575     gfx::Vector2dF current_fling_velocity) {
576 }
577 
RendererFrameNumber()578 uint32 RenderWidgetHostViewBase::RendererFrameNumber() {
579   return renderer_frame_number_;
580 }
581 
DidReceiveRendererFrame()582 void RenderWidgetHostViewBase::DidReceiveRendererFrame() {
583   ++renderer_frame_number_;
584 }
585 
FlushInput()586 void RenderWidgetHostViewBase::FlushInput() {
587   RenderWidgetHostImpl* impl = NULL;
588   if (GetRenderWidgetHost())
589     impl = RenderWidgetHostImpl::From(GetRenderWidgetHost());
590   if (!impl)
591     return;
592   impl->FlushInput();
593 }
594 
595 }  // namespace content
596