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.
5 #include "content/browser/renderer_host/render_widget_host_view_base.h"
7 #include "base/logging.h"
8 #include "base/profiler/scoped_tracker.h"
9 #include "content/browser/accessibility/browser_accessibility_manager.h"
10 #include "content/browser/gpu/gpu_data_manager_impl.h"
11 #include "content/browser/renderer_host/input/synthetic_gesture_target_base.h"
12 #include "content/browser/renderer_host/render_process_host_impl.h"
13 #include "content/browser/renderer_host/render_widget_host_impl.h"
14 #include "content/common/content_switches_internal.h"
15 #include "content/public/browser/render_widget_host_view_frame_subscriber.h"
16 #include "ui/gfx/display.h"
17 #include "ui/gfx/geometry/size_conversions.h"
18 #include "ui/gfx/geometry/size_f.h"
19 #include "ui/gfx/screen.h"
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"
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.
45 void NotifyPluginProcessHostHelper(HWND window
, HWND parent
, int tries
) {
46 // How long to wait between each try.
47 static const int kTryDelayMs
= 200;
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;
57 if (base::GetProcId(iter
.GetData().handle
) == plugin_process_id
) {
58 iter
->AddWindow(parent
);
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
68 base::MessageLoop::current()->PostDelayedTask(
70 base::Bind(&NotifyPluginProcessHostHelper
, window
, parent
, tries
- 1),
71 base::TimeDelta::FromMilliseconds(kTryDelayMs
));
76 // The plugin process might have died in the time to execute the task, don't
78 PostMessage(parent
, WM_CLOSE
, 0, 0);
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.
85 LRESULT CALLBACK
PluginWrapperWindowProc(HWND window
, unsigned int message
,
86 WPARAM wparam
, LPARAM lparam
) {
87 if (message
== WM_PARENTNOTIFY
) {
88 switch (LOWORD(wparam
)) {
92 ::SendMessage(GetParent(window
), message
, wparam
, lparam
);
98 return ::DefWindowProc(window
, message
, wparam
, lparam
);
101 bool IsPluginWrapperWindow(HWND window
) {
102 return gfx::GetClassNameW(window
) ==
103 base::string16(kWrapperNativeWindowClassName
);
106 // Create an intermediate window between the given HWND and its parent.
107 HWND
ReparentWindow(HWND window
, HWND parent
) {
108 static ATOM atom
= 0;
109 static HMODULE instance
= NULL
;
111 WNDCLASSEX window_class
;
112 base::win::InitializeWindowClass(
113 kWrapperNativeWindowClassName
,
114 &base::win::WrappedWindowProc
<PluginWrapperWindowProc
>,
119 // xxx reinterpret_cast<HBRUSH>(COLOR_WINDOW+1),
120 reinterpret_cast<HBRUSH
>(COLOR_GRAYTEXT
+1),
125 instance
= window_class
.hInstance
;
126 atom
= RegisterClassEx(&window_class
);
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
139 static const int kMaxTries
= 5;
140 BrowserThread::PostTask(
143 base::Bind(&NotifyPluginProcessHostHelper
, window
, new_parent
,
148 BOOL CALLBACK
PaintEnumChildProc(HWND hwnd
, LPARAM lparam
) {
149 if (!PluginServiceImpl::GetInstance()->IsPluginWindow(hwnd
))
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());
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
);
166 // Windows callback for OnDestroy to detach the plugin windows.
167 BOOL CALLBACK
DetachPluginWindowsCallbackInternal(HWND window
, LPARAM param
) {
168 RenderWidgetHostViewBase::DetachPluginWindowsCallback(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
);
184 void RenderWidgetHostViewBase::MovePluginWindowsHelper(
186 const std::vector
<WebPluginGeometry
>& moves
) {
190 bool oop_plugins
= !base::CommandLine::ForCurrentProcess()->HasSwitch(
191 switches::kSingleProcess
);
193 HDWP defer_window_pos_info
=
194 ::BeginDeferWindowPos(static_cast<int>(moves
.size()));
196 if (!defer_window_pos_info
) {
201 #if defined(USE_AURA)
202 std::vector
<RECT
> invalidate_rects
;
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
;
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
))
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.
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.
239 // We move the intermediate parent window which doesn't result in cross-
240 // process synchronous Windows messages.
243 if (cur_parent
== GetDesktopWindow())
244 SetParent(window
, parent
);
248 flags
|= SWP_SHOWWINDOW
;
250 flags
|= SWP_HIDEWINDOW
;
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
;
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
);
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);
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
283 if (clip_rect_in_pixel
.IsEmpty() &&
284 !GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
286 GetClientRect(window
, &r
);
287 MapWindowPoints(window
, parent
, reinterpret_cast<POINT
*>(&r
), 2);
288 invalidate_rects
.push_back(r
);
296 gfx::Rect window_rect_in_pixel
=
297 gfx::win::DIPToScreenRect(move
.window_rect
);
298 defer_window_pos_info
= ::DeferWindowPos(defer_window_pos_info
,
300 window_rect_in_pixel
.x(),
301 window_rect_in_pixel
.y(),
302 window_rect_in_pixel
.width(),
303 window_rect_in_pixel
.height(),
306 if (!defer_window_pos_info
) {
307 DCHECK(false) << "DeferWindowPos failed, so all plugin moves ignored.";
312 ::EndDeferWindowPos(defer_window_pos_info
);
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
];
319 GetWindowRect(move
.window
, &r
);
321 PaintEnumChildProc(move
.window
, reinterpret_cast<LPARAM
>(&gr
));
324 for (size_t i
= 0; i
< invalidate_rects
.size(); ++i
) {
326 parent
, &invalidate_rects
[i
], NULL
,
327 // These flags are from WebPluginDelegateImpl::NativeWndProc.
328 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_FRAME
| RDW_UPDATENOW
);
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
);
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.
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.
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
);
363 // How many microseconds apart input events should be flushed.
364 const int kFlushInputRateInUs
= 16666;
368 RenderWidgetHostViewBase::RenderWidgetHostViewBase()
369 : popup_type_(blink::WebPopupTypeNone
),
370 background_color_(SK_ColorWHITE
),
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 weak_factory_(this) {
382 RenderWidgetHostViewBase::~RenderWidgetHostViewBase() {
383 DCHECK(!mouse_locked_
);
386 bool RenderWidgetHostViewBase::OnMessageReceived(const IPC::Message
& msg
){
390 void RenderWidgetHostViewBase::SetBackgroundColor(SkColor color
) {
391 background_color_
= color
;
394 void RenderWidgetHostViewBase::SetBackgroundColorToDefault() {
395 SetBackgroundColor(SK_ColorWHITE
);
398 bool RenderWidgetHostViewBase::GetBackgroundOpaque() {
399 return SkColorGetA(background_color_
) == SK_AlphaOPAQUE
;
402 gfx::Size
RenderWidgetHostViewBase::GetPhysicalBackingSize() const {
403 gfx::NativeView view
= GetNativeView();
404 gfx::Display display
=
405 gfx::Screen::GetScreenFor(view
)->GetDisplayNearestWindow(view
);
406 return gfx::ToCeiledSize(gfx::ScaleSize(GetRequestedRendererSize(),
407 display
.device_scale_factor()));
410 bool RenderWidgetHostViewBase::DoTopControlsShrinkBlinkSize() const {
414 float RenderWidgetHostViewBase::GetTopControlsHeight() const {
418 void RenderWidgetHostViewBase::SelectionChanged(const base::string16
& text
,
420 const gfx::Range
& range
) {
421 selection_text_
= text
;
422 selection_text_offset_
= offset
;
423 selection_range_
.set_start(range
.start());
424 selection_range_
.set_end(range
.end());
427 gfx::Size
RenderWidgetHostViewBase::GetRequestedRendererSize() const {
428 return GetViewBounds().size();
431 ui::TextInputClient
* RenderWidgetHostViewBase::GetTextInputClient() {
436 bool RenderWidgetHostViewBase::IsShowingContextMenu() const {
437 return showing_context_menu_
;
440 void RenderWidgetHostViewBase::SetShowingContextMenu(bool showing
) {
441 DCHECK_NE(showing_context_menu_
, showing
);
442 showing_context_menu_
= showing
;
445 base::string16
RenderWidgetHostViewBase::GetSelectedText() const {
446 if (!selection_range_
.IsValid())
447 return base::string16();
448 return selection_text_
.substr(
449 selection_range_
.GetMin() - selection_text_offset_
,
450 selection_range_
.length());
453 bool RenderWidgetHostViewBase::IsMouseLocked() {
454 return mouse_locked_
;
457 InputEventAckState
RenderWidgetHostViewBase::FilterInputEvent(
458 const blink::WebInputEvent
& input_event
) {
459 // By default, input events are simply forwarded to the renderer.
460 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED
;
463 void RenderWidgetHostViewBase::OnSetNeedsFlushInput() {
464 if (flush_input_timer_
.IsRunning())
467 flush_input_timer_
.Start(
469 base::TimeDelta::FromMicroseconds(kFlushInputRateInUs
),
471 &RenderWidgetHostViewBase::FlushInput
);
474 void RenderWidgetHostViewBase::WheelEventAck(
475 const blink::WebMouseWheelEvent
& event
,
476 InputEventAckState ack_result
) {
479 void RenderWidgetHostViewBase::GestureEventAck(
480 const blink::WebGestureEvent
& event
,
481 InputEventAckState ack_result
) {
484 void RenderWidgetHostViewBase::SetPopupType(blink::WebPopupType popup_type
) {
485 popup_type_
= popup_type
;
488 blink::WebPopupType
RenderWidgetHostViewBase::GetPopupType() {
492 BrowserAccessibilityManager
*
493 RenderWidgetHostViewBase::CreateBrowserAccessibilityManager(
494 BrowserAccessibilityDelegate
* delegate
) {
499 void RenderWidgetHostViewBase::AccessibilityShowMenu(const gfx::Point
& point
) {
500 RenderWidgetHostImpl
* impl
= NULL
;
501 if (GetRenderWidgetHost())
502 impl
= RenderWidgetHostImpl::From(GetRenderWidgetHost());
505 impl
->ShowContextMenuAtPoint(point
);
508 gfx::Point
RenderWidgetHostViewBase::AccessibilityOriginInScreen(
509 const gfx::Rect
& bounds
) {
510 return bounds
.origin();
513 gfx::AcceleratedWidget
514 RenderWidgetHostViewBase::AccessibilityGetAcceleratedWidget() {
515 return gfx::kNullAcceleratedWidget
;
518 gfx::NativeViewAccessible
519 RenderWidgetHostViewBase::AccessibilityGetNativeViewAccessible() {
523 void RenderWidgetHostViewBase::UpdateScreenInfo(gfx::NativeView view
) {
524 RenderWidgetHostImpl
* impl
= NULL
;
525 if (GetRenderWidgetHost())
526 impl
= RenderWidgetHostImpl::From(GetRenderWidgetHost());
529 impl
->SendScreenRects();
531 if (HasDisplayPropertyChanged(view
) && impl
)
532 impl
->NotifyScreenInfoChanged();
535 bool RenderWidgetHostViewBase::HasDisplayPropertyChanged(gfx::NativeView view
) {
536 gfx::Display display
=
537 gfx::Screen::GetScreenFor(view
)->GetDisplayNearestWindow(view
);
538 if (current_display_area_
== display
.work_area() &&
539 current_device_scale_factor_
== display
.device_scale_factor() &&
540 current_display_rotation_
== display
.rotation()) {
544 current_display_area_
= display
.work_area();
545 current_device_scale_factor_
= display
.device_scale_factor();
546 current_display_rotation_
= display
.rotation();
550 base::WeakPtr
<RenderWidgetHostViewBase
> RenderWidgetHostViewBase::GetWeakPtr() {
551 return weak_factory_
.GetWeakPtr();
554 scoped_ptr
<SyntheticGestureTarget
>
555 RenderWidgetHostViewBase::CreateSyntheticGestureTarget() {
556 RenderWidgetHostImpl
* host
=
557 RenderWidgetHostImpl::From(GetRenderWidgetHost());
558 return scoped_ptr
<SyntheticGestureTarget
>(
559 new SyntheticGestureTargetBase(host
));
562 // Platform implementation should override this method to allow frame
563 // subscription. Frame subscriber is set to RenderProcessHost, which is
564 // platform independent. It should be set to the specific presenter on each
566 bool RenderWidgetHostViewBase::CanSubscribeFrame() const {
571 // Base implementation for this method sets the subscriber to RenderProcessHost,
572 // which is platform independent. Note: Implementation only support subscribing
573 // to accelerated composited frames.
574 void RenderWidgetHostViewBase::BeginFrameSubscription(
575 scoped_ptr
<RenderWidgetHostViewFrameSubscriber
> subscriber
) {
576 RenderWidgetHostImpl
* impl
= NULL
;
577 if (GetRenderWidgetHost())
578 impl
= RenderWidgetHostImpl::From(GetRenderWidgetHost());
581 RenderProcessHostImpl
* render_process_host
=
582 static_cast<RenderProcessHostImpl
*>(impl
->GetProcess());
583 render_process_host
->BeginFrameSubscription(impl
->GetRoutingID(),
587 void RenderWidgetHostViewBase::EndFrameSubscription() {
588 RenderWidgetHostImpl
* impl
= NULL
;
589 if (GetRenderWidgetHost())
590 impl
= RenderWidgetHostImpl::From(GetRenderWidgetHost());
593 RenderProcessHostImpl
* render_process_host
=
594 static_cast<RenderProcessHostImpl
*>(impl
->GetProcess());
595 render_process_host
->EndFrameSubscription(impl
->GetRoutingID());
598 uint32
RenderWidgetHostViewBase::RendererFrameNumber() {
599 return renderer_frame_number_
;
602 void RenderWidgetHostViewBase::DidReceiveRendererFrame() {
603 ++renderer_frame_number_
;
606 void RenderWidgetHostViewBase::FlushInput() {
607 RenderWidgetHostImpl
* impl
= NULL
;
608 if (GetRenderWidgetHost())
609 impl
= RenderWidgetHostImpl::From(GetRenderWidgetHost());
615 void RenderWidgetHostViewBase::OnTextSurroundingSelectionResponse(
616 const base::string16
& content
,
622 void RenderWidgetHostViewBase::ShowDisambiguationPopup(
623 const gfx::Rect
& rect_pixels
,
624 const SkBitmap
& zoomed_bitmap
) {
628 gfx::Size
RenderWidgetHostViewBase::GetVisibleViewportSize() const {
629 return GetViewBounds().size();
632 void RenderWidgetHostViewBase::SetInsets(const gfx::Insets
& insets
) {
637 blink::WebScreenOrientationType
638 RenderWidgetHostViewBase::GetOrientationTypeForMobile(
639 const gfx::Display
& display
) {
640 int angle
= display
.RotationAsDegree();
641 const gfx::Rect
& bounds
= display
.bounds();
643 // Whether the device's natural orientation is portrait.
644 bool natural_portrait
= false;
645 if (angle
== 0 || angle
== 180) // The device is in its natural orientation.
646 natural_portrait
= bounds
.height() >= bounds
.width();
648 natural_portrait
= bounds
.height() <= bounds
.width();
652 return natural_portrait
? blink::WebScreenOrientationPortraitPrimary
653 : blink::WebScreenOrientationLandscapePrimary
;
655 return natural_portrait
? blink::WebScreenOrientationLandscapePrimary
656 : blink::WebScreenOrientationPortraitSecondary
;
658 return natural_portrait
? blink::WebScreenOrientationPortraitSecondary
659 : blink::WebScreenOrientationLandscapeSecondary
;
661 return natural_portrait
? blink::WebScreenOrientationLandscapeSecondary
662 : blink::WebScreenOrientationPortraitPrimary
;
665 return blink::WebScreenOrientationPortraitPrimary
;
670 blink::WebScreenOrientationType
671 RenderWidgetHostViewBase::GetOrientationTypeForDesktop(
672 const gfx::Display
& display
) {
673 static int primary_landscape_angle
= -1;
674 static int primary_portrait_angle
= -1;
676 int angle
= display
.RotationAsDegree();
677 const gfx::Rect
& bounds
= display
.bounds();
678 bool is_portrait
= bounds
.height() >= bounds
.width();
680 if (is_portrait
&& primary_portrait_angle
== -1)
681 primary_portrait_angle
= angle
;
683 if (!is_portrait
&& primary_landscape_angle
== -1)
684 primary_landscape_angle
= angle
;
687 return primary_portrait_angle
== angle
688 ? blink::WebScreenOrientationPortraitPrimary
689 : blink::WebScreenOrientationPortraitSecondary
;
692 return primary_landscape_angle
== angle
693 ? blink::WebScreenOrientationLandscapePrimary
694 : blink::WebScreenOrientationLandscapeSecondary
;
697 void RenderWidgetHostViewBase::OnDidNavigateMainFrameToNewPage() {
700 uint32_t RenderWidgetHostViewBase::GetSurfaceIdNamespace() {
704 } // namespace content