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