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_view_host_impl.h"
12 #include "base/callback.h"
13 #include "base/command_line.h"
14 #include "base/debug/trace_event.h"
15 #include "base/i18n/rtl.h"
16 #include "base/json/json_reader.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/metrics/histogram.h"
19 #include "base/stl_util.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/sys_info.h"
23 #include "base/time/time.h"
24 #include "base/values.h"
25 #include "cc/base/switches.h"
26 #include "content/browser/accessibility/browser_accessibility_manager.h"
27 #include "content/browser/child_process_security_policy_impl.h"
28 #include "content/browser/cross_site_request_manager.h"
29 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
30 #include "content/browser/frame_host/frame_tree.h"
31 #include "content/browser/gpu/compositor_util.h"
32 #include "content/browser/gpu/gpu_data_manager_impl.h"
33 #include "content/browser/gpu/gpu_process_host.h"
34 #include "content/browser/gpu/gpu_surface_tracker.h"
35 #include "content/browser/host_zoom_map_impl.h"
36 #include "content/browser/loader/resource_dispatcher_host_impl.h"
37 #include "content/browser/renderer_host/dip_util.h"
38 #include "content/browser/renderer_host/input/timeout_monitor.h"
39 #include "content/browser/renderer_host/media/audio_renderer_host.h"
40 #include "content/browser/renderer_host/render_process_host_impl.h"
41 #include "content/browser/renderer_host/render_view_host_delegate.h"
42 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
43 #include "content/browser/renderer_host/render_widget_host_view_base.h"
44 #include "content/common/accessibility_messages.h"
45 #include "content/common/browser_plugin/browser_plugin_messages.h"
46 #include "content/common/content_switches_internal.h"
47 #include "content/common/drag_messages.h"
48 #include "content/common/frame_messages.h"
49 #include "content/common/input_messages.h"
50 #include "content/common/inter_process_time_ticks_converter.h"
51 #include "content/common/mojo/mojo_service_names.h"
52 #include "content/common/speech_recognition_messages.h"
53 #include "content/common/swapped_out_messages.h"
54 #include "content/common/view_messages.h"
55 #include "content/common/web_ui_setup.mojom.h"
56 #include "content/public/browser/ax_event_notification_details.h"
57 #include "content/public/browser/browser_accessibility_state.h"
58 #include "content/public/browser/browser_context.h"
59 #include "content/public/browser/browser_message_filter.h"
60 #include "content/public/browser/content_browser_client.h"
61 #include "content/public/browser/native_web_keyboard_event.h"
62 #include "content/public/browser/notification_details.h"
63 #include "content/public/browser/notification_service.h"
64 #include "content/public/browser/notification_types.h"
65 #include "content/public/browser/render_frame_host.h"
66 #include "content/public/browser/render_widget_host_iterator.h"
67 #include "content/public/browser/storage_partition.h"
68 #include "content/public/browser/user_metrics.h"
69 #include "content/public/common/bindings_policy.h"
70 #include "content/public/common/content_constants.h"
71 #include "content/public/common/content_switches.h"
72 #include "content/public/common/context_menu_params.h"
73 #include "content/public/common/drop_data.h"
74 #include "content/public/common/result_codes.h"
75 #include "content/public/common/url_constants.h"
76 #include "content/public/common/url_utils.h"
77 #include "net/base/filename_util.h"
78 #include "net/base/net_util.h"
79 #include "net/base/network_change_notifier.h"
80 #include "net/url_request/url_request_context_getter.h"
81 #include "third_party/skia/include/core/SkBitmap.h"
82 #include "ui/accessibility/ax_tree.h"
83 #include "ui/base/touch/touch_device.h"
84 #include "ui/base/touch/touch_enabled.h"
85 #include "ui/base/ui_base_switches.h"
86 #include "ui/gfx/image/image_skia.h"
87 #include "ui/gfx/native_widget_types.h"
88 #include "ui/native_theme/native_theme_switches.h"
89 #include "ui/shell_dialogs/selected_file_info.h"
90 #include "webkit/browser/fileapi/isolated_context.h"
92 #if defined(OS_MACOSX)
93 #include "content/browser/renderer_host/popup_menu_helper_mac.h"
94 #elif defined(OS_ANDROID)
95 #include "content/browser/media/android/browser_media_player_manager.h"
97 #include "base/win/win_util.h"
100 using base::TimeDelta
;
101 using blink::WebConsoleMessage
;
102 using blink::WebDragOperation
;
103 using blink::WebDragOperationNone
;
104 using blink::WebDragOperationsMask
;
105 using blink::WebInputEvent
;
106 using blink::WebMediaPlayerAction
;
107 using blink::WebPluginAction
;
112 // Translate a WebKit text direction into a base::i18n one.
113 base::i18n::TextDirection
WebTextDirectionToChromeTextDirection(
114 blink::WebTextDirection dir
) {
116 case blink::WebTextDirectionLeftToRight
:
117 return base::i18n::LEFT_TO_RIGHT
;
118 case blink::WebTextDirectionRightToLeft
:
119 return base::i18n::RIGHT_TO_LEFT
;
122 return base::i18n::UNKNOWN_DIRECTION
;
128 const int kVirtualKeyboardDisplayWaitTimeoutMs
= 100;
129 const int kMaxVirtualKeyboardDisplayRetries
= 5;
131 void DismissVirtualKeyboardTask() {
132 static int virtual_keyboard_display_retries
= 0;
133 // If the virtual keyboard is not yet visible, then we execute the task again
134 // waiting for it to show up.
135 if (!base::win::DismissVirtualKeyboard()) {
136 if (virtual_keyboard_display_retries
< kMaxVirtualKeyboardDisplayRetries
) {
137 BrowserThread::PostDelayedTask(
138 BrowserThread::UI
, FROM_HERE
,
139 base::Bind(base::IgnoreResult(&DismissVirtualKeyboardTask
)),
140 TimeDelta::FromMilliseconds(kVirtualKeyboardDisplayWaitTimeoutMs
));
141 ++virtual_keyboard_display_retries
;
143 virtual_keyboard_display_retries
= 0;
152 const int RenderViewHostImpl::kUnloadTimeoutMS
= 1000;
154 ///////////////////////////////////////////////////////////////////////////////
155 // RenderViewHost, public:
158 bool RenderViewHostImpl::IsRVHStateActive(RenderViewHostImplState rvh_state
) {
159 if (rvh_state
== STATE_DEFAULT
||
160 rvh_state
== STATE_WAITING_FOR_UNLOAD_ACK
||
161 rvh_state
== STATE_WAITING_FOR_COMMIT
||
162 rvh_state
== STATE_WAITING_FOR_CLOSE
)
168 RenderViewHost
* RenderViewHost::FromID(int render_process_id
,
169 int render_view_id
) {
170 return RenderViewHostImpl::FromID(render_process_id
, render_view_id
);
174 RenderViewHost
* RenderViewHost::From(RenderWidgetHost
* rwh
) {
175 DCHECK(rwh
->IsRenderView());
176 return static_cast<RenderViewHostImpl
*>(RenderWidgetHostImpl::From(rwh
));
179 ///////////////////////////////////////////////////////////////////////////////
180 // RenderViewHostImpl, public:
183 RenderViewHostImpl
* RenderViewHostImpl::FromID(int render_process_id
,
184 int render_view_id
) {
185 RenderWidgetHost
* widget
=
186 RenderWidgetHost::FromID(render_process_id
, render_view_id
);
187 if (!widget
|| !widget
->IsRenderView())
189 return static_cast<RenderViewHostImpl
*>(RenderWidgetHostImpl::From(widget
));
192 RenderViewHostImpl::RenderViewHostImpl(
193 SiteInstance
* instance
,
194 RenderViewHostDelegate
* delegate
,
195 RenderWidgetHostDelegate
* widget_delegate
,
197 int main_frame_routing_id
,
200 : RenderWidgetHostImpl(widget_delegate
,
201 instance
->GetProcess(),
204 frames_ref_count_(0),
206 instance_(static_cast<SiteInstanceImpl
*>(instance
)),
207 waiting_for_drag_context_response_(false),
208 enabled_bindings_(0),
209 navigations_suspended_(false),
210 main_frame_routing_id_(main_frame_routing_id
),
211 run_modal_reply_msg_(NULL
),
212 run_modal_opener_id_(MSG_ROUTING_NONE
),
213 is_waiting_for_beforeunload_ack_(false),
214 unload_ack_is_for_cross_site_transition_(false),
215 sudden_termination_allowed_(false),
216 render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING
),
217 virtual_keyboard_requested_(false),
218 weak_factory_(this) {
219 DCHECK(instance_
.get());
220 CHECK(delegate_
); // http://crbug.com/82827
222 GetProcess()->EnableSendQueue();
225 rvh_state_
= STATE_SWAPPED_OUT
;
227 rvh_state_
= STATE_DEFAULT
;
228 instance_
->increment_active_view_count();
231 if (ResourceDispatcherHostImpl::Get()) {
232 BrowserThread::PostTask(
233 BrowserThread::IO
, FROM_HERE
,
234 base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostCreated
,
235 base::Unretained(ResourceDispatcherHostImpl::Get()),
236 GetProcess()->GetID(), GetRoutingID()));
239 #if defined(OS_ANDROID)
240 media_player_manager_
.reset(BrowserMediaPlayerManager::Create(this));
243 unload_event_monitor_timeout_
.reset(new TimeoutMonitor(base::Bind(
244 &RenderViewHostImpl::OnSwappedOut
, weak_factory_
.GetWeakPtr(), true)));
247 RenderViewHostImpl::~RenderViewHostImpl() {
248 if (ResourceDispatcherHostImpl::Get()) {
249 BrowserThread::PostTask(
250 BrowserThread::IO
, FROM_HERE
,
251 base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostDeleted
,
252 base::Unretained(ResourceDispatcherHostImpl::Get()),
253 GetProcess()->GetID(), GetRoutingID()));
256 delegate_
->RenderViewDeleted(this);
258 // Be sure to clean up any leftover state from cross-site requests.
259 CrossSiteRequestManager::GetInstance()->SetHasPendingCrossSiteRequest(
260 GetProcess()->GetID(), GetRoutingID(), false);
262 // If this was swapped out, it already decremented the active view
263 // count of the SiteInstance it belongs to.
264 if (IsRVHStateActive(rvh_state_
))
265 instance_
->decrement_active_view_count();
268 RenderViewHostDelegate
* RenderViewHostImpl::GetDelegate() const {
272 SiteInstance
* RenderViewHostImpl::GetSiteInstance() const {
273 return instance_
.get();
276 bool RenderViewHostImpl::CreateRenderView(
277 const base::string16
& frame_name
,
280 bool window_was_created_with_opener
) {
281 TRACE_EVENT0("renderer_host", "RenderViewHostImpl::CreateRenderView");
282 DCHECK(!IsRenderViewLive()) << "Creating view twice";
284 // The process may (if we're sharing a process with another host that already
285 // initialized it) or may not (we have our own process or the old process
286 // crashed) have been initialized. Calling Init multiple times will be
287 // ignored, so this is safe.
288 if (!GetProcess()->Init())
290 DCHECK(GetProcess()->HasConnection());
291 DCHECK(GetProcess()->GetBrowserContext());
293 renderer_initialized_
= true;
295 GpuSurfaceTracker::Get()->SetSurfaceHandle(
296 surface_id(), GetCompositingSurface());
298 // Ensure the RenderView starts with a next_page_id larger than any existing
299 // page ID it might be asked to render.
300 int32 next_page_id
= 1;
301 if (max_page_id
> -1)
302 next_page_id
= max_page_id
+ 1;
304 ViewMsg_New_Params params
;
305 params
.renderer_preferences
=
306 delegate_
->GetRendererPrefs(GetProcess()->GetBrowserContext());
307 params
.web_preferences
= delegate_
->GetWebkitPrefs();
308 params
.view_id
= GetRoutingID();
309 params
.main_frame_routing_id
= main_frame_routing_id_
;
310 params
.surface_id
= surface_id();
311 params
.session_storage_namespace_id
=
312 delegate_
->GetSessionStorageNamespace(instance_
)->id();
313 params
.frame_name
= frame_name
;
314 // Ensure the RenderView sets its opener correctly.
315 params
.opener_route_id
= opener_route_id
;
316 params
.swapped_out
= !IsRVHStateActive(rvh_state_
);
317 params
.hidden
= is_hidden();
318 params
.never_visible
= delegate_
->IsNeverVisible();
319 params
.window_was_created_with_opener
= window_was_created_with_opener
;
320 params
.next_page_id
= next_page_id
;
321 GetWebScreenInfo(¶ms
.screen_info
);
322 params
.accessibility_mode
= accessibility_mode();
324 Send(new ViewMsg_New(params
));
326 // If it's enabled, tell the renderer to set up the Javascript bindings for
327 // sending messages back to the browser.
328 if (GetProcess()->IsGuest())
329 DCHECK_EQ(0, enabled_bindings_
);
330 Send(new ViewMsg_AllowBindings(GetRoutingID(), enabled_bindings_
));
331 // Let our delegate know that we created a RenderView.
332 delegate_
->RenderViewCreated(this);
337 bool RenderViewHostImpl::IsRenderViewLive() const {
338 return GetProcess()->HasConnection() && renderer_initialized_
;
341 void RenderViewHostImpl::SyncRendererPrefs() {
342 Send(new ViewMsg_SetRendererPrefs(GetRoutingID(),
343 delegate_
->GetRendererPrefs(
344 GetProcess()->GetBrowserContext())));
347 WebPreferences
RenderViewHostImpl::GetWebkitPrefs(const GURL
& url
) {
348 TRACE_EVENT0("browser", "RenderViewHostImpl::GetWebkitPrefs");
349 WebPreferences prefs
;
351 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
353 prefs
.javascript_enabled
=
354 !command_line
.HasSwitch(switches::kDisableJavaScript
);
355 prefs
.web_security_enabled
=
356 !command_line
.HasSwitch(switches::kDisableWebSecurity
);
357 prefs
.plugins_enabled
=
358 !command_line
.HasSwitch(switches::kDisablePlugins
);
360 !command_line
.HasSwitch(switches::kDisableJava
);
362 prefs
.remote_fonts_enabled
=
363 !command_line
.HasSwitch(switches::kDisableRemoteFonts
);
365 !command_line
.HasSwitch(switches::kDisableXSLT
);
366 prefs
.xss_auditor_enabled
=
367 !command_line
.HasSwitch(switches::kDisableXSSAuditor
);
368 prefs
.application_cache_enabled
=
369 !command_line
.HasSwitch(switches::kDisableApplicationCache
);
371 prefs
.local_storage_enabled
=
372 !command_line
.HasSwitch(switches::kDisableLocalStorage
);
373 prefs
.databases_enabled
=
374 !command_line
.HasSwitch(switches::kDisableDatabases
);
375 #if defined(OS_ANDROID)
376 // WebAudio is enabled by default on x86 and ARM.
377 prefs
.webaudio_enabled
=
378 !command_line
.HasSwitch(switches::kDisableWebAudio
);
381 prefs
.experimental_webgl_enabled
=
382 GpuProcessHost::gpu_enabled() &&
383 !command_line
.HasSwitch(switches::kDisable3DAPIs
) &&
384 !command_line
.HasSwitch(switches::kDisableExperimentalWebGL
);
386 prefs
.pepper_3d_enabled
=
387 !command_line
.HasSwitch(switches::kDisablePepper3d
);
389 prefs
.flash_3d_enabled
=
390 GpuProcessHost::gpu_enabled() &&
391 !command_line
.HasSwitch(switches::kDisableFlash3d
);
392 prefs
.flash_stage3d_enabled
=
393 GpuProcessHost::gpu_enabled() &&
394 !command_line
.HasSwitch(switches::kDisableFlashStage3d
);
395 prefs
.flash_stage3d_baseline_enabled
=
396 GpuProcessHost::gpu_enabled() &&
397 !command_line
.HasSwitch(switches::kDisableFlashStage3d
);
399 prefs
.gl_multisampling_enabled
=
400 !command_line
.HasSwitch(switches::kDisableGLMultisampling
);
401 prefs
.privileged_webgl_extensions_enabled
=
402 command_line
.HasSwitch(switches::kEnablePrivilegedWebGLExtensions
);
403 prefs
.site_specific_quirks_enabled
=
404 !command_line
.HasSwitch(switches::kDisableSiteSpecificQuirks
);
405 prefs
.allow_file_access_from_file_urls
=
406 command_line
.HasSwitch(switches::kAllowFileAccessFromFiles
);
408 prefs
.layer_squashing_enabled
= true;
409 if (command_line
.HasSwitch(switches::kEnableLayerSquashing
))
410 prefs
.layer_squashing_enabled
= true;
411 if (command_line
.HasSwitch(switches::kDisableLayerSquashing
))
412 prefs
.layer_squashing_enabled
= false;
414 prefs
.accelerated_2d_canvas_enabled
=
415 GpuProcessHost::gpu_enabled() &&
416 !command_line
.HasSwitch(switches::kDisableAccelerated2dCanvas
);
417 prefs
.antialiased_2d_canvas_disabled
=
418 command_line
.HasSwitch(switches::kDisable2dCanvasAntialiasing
);
419 prefs
.accelerated_2d_canvas_msaa_sample_count
=
420 atoi(command_line
.GetSwitchValueASCII(
421 switches::kAcceleratedCanvas2dMSAASampleCount
).c_str());
422 prefs
.deferred_filters_enabled
=
423 !command_line
.HasSwitch(switches::kDisableDeferredFilters
);
424 prefs
.container_culling_enabled
=
425 command_line
.HasSwitch(switches::kEnableContainerCulling
);
426 prefs
.lazy_layout_enabled
=
427 command_line
.HasSwitch(switches::kEnableExperimentalWebPlatformFeatures
);
428 prefs
.region_based_columns_enabled
=
429 command_line
.HasSwitch(switches::kEnableRegionBasedColumns
);
431 if (IsPinchVirtualViewportEnabled()) {
432 prefs
.pinch_virtual_viewport_enabled
= true;
433 prefs
.pinch_overlay_scrollbar_thickness
= 10;
435 prefs
.use_solid_color_scrollbars
= ui::IsOverlayScrollbarEnabled();
437 #if defined(OS_ANDROID)
438 prefs
.user_gesture_required_for_media_playback
= !command_line
.HasSwitch(
439 switches::kDisableGestureRequirementForMediaPlayback
);
442 prefs
.touch_enabled
= ui::AreTouchEventsEnabled();
443 prefs
.device_supports_touch
= prefs
.touch_enabled
&&
444 ui::IsTouchDevicePresent();
445 #if defined(OS_ANDROID)
446 prefs
.device_supports_mouse
= false;
449 prefs
.pointer_events_max_touch_points
= ui::MaxTouchPoints();
451 prefs
.touch_adjustment_enabled
=
452 !command_line
.HasSwitch(switches::kDisableTouchAdjustment
);
453 prefs
.compositor_touch_hit_testing
=
454 !command_line
.HasSwitch(cc::switches::kDisableCompositorTouchHitTesting
);
456 #if defined(OS_MACOSX) || defined(OS_CHROMEOS)
457 bool default_enable_scroll_animator
= true;
459 bool default_enable_scroll_animator
= false;
461 prefs
.enable_scroll_animator
= default_enable_scroll_animator
;
462 if (command_line
.HasSwitch(switches::kEnableSmoothScrolling
))
463 prefs
.enable_scroll_animator
= true;
464 if (command_line
.HasSwitch(switches::kDisableSmoothScrolling
))
465 prefs
.enable_scroll_animator
= false;
467 // Certain GPU features might have been blacklisted.
468 GpuDataManagerImpl::GetInstance()->UpdateRendererWebPrefs(&prefs
);
470 if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
471 GetProcess()->GetID())) {
472 prefs
.loads_images_automatically
= true;
473 prefs
.javascript_enabled
= true;
476 prefs
.is_online
= !net::NetworkChangeNotifier::IsOffline();
478 prefs
.fixed_position_creates_stacking_context
= !command_line
.HasSwitch(
479 switches::kDisableFixedPositionCreatesStackingContext
);
481 prefs
.gesture_tap_highlight_enabled
= !command_line
.HasSwitch(
482 switches::kDisableGestureTapHighlight
);
484 prefs
.number_of_cpu_cores
= base::SysInfo::NumberOfProcessors();
486 prefs
.viewport_meta_enabled
=
487 command_line
.HasSwitch(switches::kEnableViewportMeta
);
489 prefs
.viewport_enabled
=
490 command_line
.HasSwitch(switches::kEnableViewport
) ||
491 prefs
.viewport_meta_enabled
;
493 prefs
.main_frame_resizes_are_orientation_changes
=
494 command_line
.HasSwitch(switches::kMainFrameResizesAreOrientationChanges
);
496 prefs
.deferred_image_decoding_enabled
=
497 command_line
.HasSwitch(switches::kEnableDeferredImageDecoding
) ||
498 content::IsImplSidePaintingEnabled();
500 prefs
.spatial_navigation_enabled
= command_line
.HasSwitch(
501 switches::kEnableSpatialNavigation
);
503 GetContentClient()->browser()->OverrideWebkitPrefs(this, url
, &prefs
);
507 void RenderViewHostImpl::Navigate(const FrameMsg_Navigate_Params
& params
) {
508 TRACE_EVENT0("renderer_host", "RenderViewHostImpl::Navigate");
509 delegate_
->GetFrameTree()->GetMainFrame()->Navigate(params
);
512 void RenderViewHostImpl::NavigateToURL(const GURL
& url
) {
513 delegate_
->GetFrameTree()->GetMainFrame()->NavigateToURL(url
);
516 void RenderViewHostImpl::SetNavigationsSuspended(
518 const base::TimeTicks
& proceed_time
) {
519 // This should only be called to toggle the state.
520 DCHECK(navigations_suspended_
!= suspend
);
522 navigations_suspended_
= suspend
;
523 if (!suspend
&& suspended_nav_params_
) {
524 // There's navigation message params waiting to be sent. Now that we're not
525 // suspended anymore, resume navigation by sending them. If we were swapped
526 // out, we should also stop filtering out the IPC messages now.
527 SetState(STATE_DEFAULT
);
529 DCHECK(!proceed_time
.is_null());
530 suspended_nav_params_
->browser_navigation_start
= proceed_time
;
531 Send(new FrameMsg_Navigate(
532 main_frame_routing_id_
, *suspended_nav_params_
.get()));
533 suspended_nav_params_
.reset();
537 void RenderViewHostImpl::CancelSuspendedNavigations() {
538 // Clear any state if a pending navigation is canceled or pre-empted.
539 if (suspended_nav_params_
)
540 suspended_nav_params_
.reset();
541 navigations_suspended_
= false;
544 void RenderViewHostImpl::SuppressDialogsUntilSwapOut() {
545 Send(new ViewMsg_SuppressDialogsUntilSwapOut(GetRoutingID()));
548 void RenderViewHostImpl::OnSwappedOut(bool timed_out
) {
549 // Ignore spurious swap out ack.
550 if (!IsWaitingForUnloadACK())
552 unload_event_monitor_timeout_
->Stop();
554 base::ProcessHandle process_handle
= GetProcess()->GetHandle();
557 // Count the number of active widget hosts for the process, which
558 // is equivalent to views using the process as of this writing.
559 scoped_ptr
<RenderWidgetHostIterator
> widgets(
560 RenderWidgetHost::GetRenderWidgetHosts());
561 while (RenderWidgetHost
* widget
= widgets
->GetNextHost()) {
562 if (widget
->GetProcess()->GetID() == GetProcess()->GetID())
566 if (!RenderProcessHost::run_renderer_in_process() &&
567 process_handle
&& views
<= 1) {
568 // The process can safely be terminated, only if WebContents sets
569 // SuddenTerminationAllowed, which indicates that the timer has expired.
570 // This is not the case if we load data URLs or about:blank. The reason
571 // is that those have no network requests and this code is hit without
572 // setting the unresponsiveness timer. This allows a corner case where a
573 // navigation to a data URL will leave a process running, if the
574 // beforeunload handler completes fine, but the unload handler hangs.
575 // At this time, the complexity to solve this edge case is not worthwhile.
576 if (SuddenTerminationAllowed()) {
577 // We should kill the process, but for now, just log the data so we can
578 // diagnose the kill rate and investigate if separate timer is needed.
579 // http://crbug.com/104346.
581 // Log a histogram point to help us diagnose how many of those kills
582 // we have performed. 1 is the enum value for RendererType Normal for
584 UMA_HISTOGRAM_PERCENTAGE(
585 "BrowserRenderProcessHost.ChildKillsUnresponsive", 1);
590 switch (rvh_state_
) {
591 case STATE_WAITING_FOR_UNLOAD_ACK
:
592 SetState(STATE_WAITING_FOR_COMMIT
);
594 case STATE_PENDING_SWAP_OUT
:
595 SetState(STATE_SWAPPED_OUT
);
597 case STATE_PENDING_SHUTDOWN
:
598 DCHECK(!pending_shutdown_on_swap_out_
.is_null());
599 pending_shutdown_on_swap_out_
.Run();
606 void RenderViewHostImpl::WasSwappedOut(
607 const base::Closure
& pending_delete_on_swap_out
) {
608 Send(new ViewMsg_WasSwappedOut(GetRoutingID()));
609 if (rvh_state_
== STATE_WAITING_FOR_UNLOAD_ACK
) {
610 SetState(STATE_PENDING_SWAP_OUT
);
611 if (!instance_
->active_view_count())
612 SetPendingShutdown(pending_delete_on_swap_out
);
613 } else if (rvh_state_
== STATE_WAITING_FOR_COMMIT
) {
614 SetState(STATE_SWAPPED_OUT
);
615 } else if (rvh_state_
== STATE_DEFAULT
) {
616 // When the RenderView is not live, the RenderFrameHostManager will call
617 // CommitPending directly, without calling SwapOut on the old RVH. This will
618 // cause WasSwappedOut to be called directly on the live old RVH.
619 DCHECK(!IsRenderViewLive());
620 SetState(STATE_SWAPPED_OUT
);
626 void RenderViewHostImpl::SetPendingShutdown(const base::Closure
& on_swap_out
) {
627 pending_shutdown_on_swap_out_
= on_swap_out
;
628 SetState(STATE_PENDING_SHUTDOWN
);
631 void RenderViewHostImpl::ClosePage() {
632 SetState(STATE_WAITING_FOR_CLOSE
);
633 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS
));
635 if (IsRenderViewLive()) {
636 // Since we are sending an IPC message to the renderer, increase the event
637 // count to prevent the hang monitor timeout from being stopped by input
638 // event acknowledgements.
639 increment_in_flight_event_count();
641 // TODO(creis): Should this be moved to Shutdown? It may not be called for
642 // RenderViewHosts that have been swapped out.
643 NotificationService::current()->Notify(
644 NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW
,
645 Source
<RenderViewHost
>(this),
646 NotificationService::NoDetails());
648 Send(new ViewMsg_ClosePage(GetRoutingID()));
650 // This RenderViewHost doesn't have a live renderer, so just skip the unload
651 // event and close the page.
652 ClosePageIgnoringUnloadEvents();
656 void RenderViewHostImpl::ClosePageIgnoringUnloadEvents() {
657 StopHangMonitorTimeout();
658 is_waiting_for_beforeunload_ack_
= false;
660 sudden_termination_allowed_
= true;
661 delegate_
->Close(this);
664 bool RenderViewHostImpl::HasPendingCrossSiteRequest() {
665 return CrossSiteRequestManager::GetInstance()->HasPendingCrossSiteRequest(
666 GetProcess()->GetID(), GetRoutingID());
669 void RenderViewHostImpl::SetHasPendingCrossSiteRequest(
670 bool has_pending_request
) {
671 CrossSiteRequestManager::GetInstance()->SetHasPendingCrossSiteRequest(
672 GetProcess()->GetID(), GetRoutingID(), has_pending_request
);
675 void RenderViewHostImpl::SetWebUIHandle(mojo::ScopedMessagePipeHandle handle
) {
676 // Never grant any bindings to browser plugin guests.
677 if (GetProcess()->IsGuest()) {
678 NOTREACHED() << "Never grant bindings to a guest process.";
682 if ((enabled_bindings_
& BINDINGS_POLICY_WEB_UI
) == 0) {
683 NOTREACHED() << "You must grant bindings before setting the handle";
687 DCHECK(renderer_initialized_
);
689 mojo::InterfacePipe
<WebUISetup
, mojo::AnyInterface
> pipe
;
690 mojo::RemotePtr
<WebUISetup
> web_ui_setup(pipe
.handle_to_self
.Pass(), NULL
);
691 web_ui_setup
->SetWebUIHandle(GetRoutingID(), handle
.Pass());
693 static_cast<RenderProcessHostImpl
*>(GetProcess())->ConnectTo(
694 kRendererService_WebUISetup
, pipe
.handle_to_peer
.Pass());
697 #if defined(OS_ANDROID)
698 void RenderViewHostImpl::ActivateNearestFindResult(int request_id
,
701 Send(new InputMsg_ActivateNearestFindResult(GetRoutingID(),
705 void RenderViewHostImpl::RequestFindMatchRects(int current_version
) {
706 Send(new ViewMsg_FindMatchRects(GetRoutingID(), current_version
));
710 void RenderViewHostImpl::DragTargetDragEnter(
711 const DropData
& drop_data
,
712 const gfx::Point
& client_pt
,
713 const gfx::Point
& screen_pt
,
714 WebDragOperationsMask operations_allowed
,
716 const int renderer_id
= GetProcess()->GetID();
717 ChildProcessSecurityPolicyImpl
* policy
=
718 ChildProcessSecurityPolicyImpl::GetInstance();
720 // The URL could have been cobbled together from any highlighted text string,
721 // and can't be interpreted as a capability.
722 DropData
filtered_data(drop_data
);
723 GetProcess()->FilterURL(true, &filtered_data
.url
);
724 if (drop_data
.did_originate_from_renderer
) {
725 filtered_data
.filenames
.clear();
728 // The filenames vector, on the other hand, does represent a capability to
729 // access the given files.
730 fileapi::IsolatedContext::FileInfoSet files
;
731 for (std::vector
<ui::FileInfo
>::iterator
iter(
732 filtered_data
.filenames
.begin());
733 iter
!= filtered_data
.filenames
.end();
735 // A dragged file may wind up as the value of an input element, or it
736 // may be used as the target of a navigation instead. We don't know
737 // which will happen at this point, so generously grant both access
738 // and request permissions to the specific file to cover both cases.
739 // We do not give it the permission to request all file:// URLs.
741 // Make sure we have the same display_name as the one we register.
742 if (iter
->display_name
.empty()) {
744 files
.AddPath(iter
->path
, &name
);
745 iter
->display_name
= base::FilePath::FromUTF8Unsafe(name
);
747 files
.AddPathWithName(iter
->path
, iter
->display_name
.AsUTF8Unsafe());
750 policy
->GrantRequestSpecificFileURL(renderer_id
,
751 net::FilePathToFileURL(iter
->path
));
753 // If the renderer already has permission to read these paths, we don't need
754 // to re-grant them. This prevents problems with DnD for files in the CrOS
755 // file manager--the file manager already had read/write access to those
756 // directories, but dragging a file would cause the read/write access to be
757 // overwritten with read-only access, making them impossible to delete or
758 // rename until the renderer was killed.
759 if (!policy
->CanReadFile(renderer_id
, iter
->path
))
760 policy
->GrantReadFile(renderer_id
, iter
->path
);
763 fileapi::IsolatedContext
* isolated_context
=
764 fileapi::IsolatedContext::GetInstance();
765 DCHECK(isolated_context
);
766 std::string filesystem_id
= isolated_context
->RegisterDraggedFileSystem(
768 if (!filesystem_id
.empty()) {
769 // Grant the permission iff the ID is valid.
770 policy
->GrantReadFileSystem(renderer_id
, filesystem_id
);
772 filtered_data
.filesystem_id
= base::UTF8ToUTF16(filesystem_id
);
774 fileapi::FileSystemContext
* file_system_context
=
775 BrowserContext::GetStoragePartition(
776 GetProcess()->GetBrowserContext(),
777 GetSiteInstance())->GetFileSystemContext();
778 for (size_t i
= 0; i
< filtered_data
.file_system_files
.size(); ++i
) {
779 fileapi::FileSystemURL file_system_url
=
780 file_system_context
->CrackURL(filtered_data
.file_system_files
[i
].url
);
782 std::string register_name
;
783 std::string filesystem_id
= isolated_context
->RegisterFileSystemForPath(
784 file_system_url
.type(), file_system_url
.path(), ®ister_name
);
785 policy
->GrantReadFileSystem(renderer_id
, filesystem_id
);
787 // Note: We are using the origin URL provided by the sender here. It may be
788 // different from the receiver's.
789 filtered_data
.file_system_files
[i
].url
= GURL(
790 fileapi::GetIsolatedFileSystemRootURIString(
791 file_system_url
.origin(),
793 std::string()).append(register_name
));
796 Send(new DragMsg_TargetDragEnter(GetRoutingID(), filtered_data
, client_pt
,
797 screen_pt
, operations_allowed
,
801 void RenderViewHostImpl::DragTargetDragOver(
802 const gfx::Point
& client_pt
,
803 const gfx::Point
& screen_pt
,
804 WebDragOperationsMask operations_allowed
,
806 Send(new DragMsg_TargetDragOver(GetRoutingID(), client_pt
, screen_pt
,
807 operations_allowed
, key_modifiers
));
810 void RenderViewHostImpl::DragTargetDragLeave() {
811 Send(new DragMsg_TargetDragLeave(GetRoutingID()));
814 void RenderViewHostImpl::DragTargetDrop(
815 const gfx::Point
& client_pt
,
816 const gfx::Point
& screen_pt
,
818 Send(new DragMsg_TargetDrop(GetRoutingID(), client_pt
, screen_pt
,
822 void RenderViewHostImpl::DragSourceEndedAt(
823 int client_x
, int client_y
, int screen_x
, int screen_y
,
824 WebDragOperation operation
) {
825 Send(new DragMsg_SourceEnded(GetRoutingID(),
826 gfx::Point(client_x
, client_y
),
827 gfx::Point(screen_x
, screen_y
),
831 void RenderViewHostImpl::DragSourceSystemDragEnded() {
832 Send(new DragMsg_SourceSystemDragEnded(GetRoutingID()));
835 RenderFrameHost
* RenderViewHostImpl::GetMainFrame() {
836 return RenderFrameHost::FromID(GetProcess()->GetID(), main_frame_routing_id_
);
839 void RenderViewHostImpl::AllowBindings(int bindings_flags
) {
840 // Never grant any bindings to browser plugin guests.
841 if (GetProcess()->IsGuest()) {
842 NOTREACHED() << "Never grant bindings to a guest process.";
846 // Ensure we aren't granting WebUI bindings to a process that has already
847 // been used for non-privileged views.
848 if (bindings_flags
& BINDINGS_POLICY_WEB_UI
&&
849 GetProcess()->HasConnection() &&
850 !ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
851 GetProcess()->GetID())) {
852 // This process has no bindings yet. Make sure it does not have more
853 // than this single active view.
854 RenderProcessHostImpl
* process
=
855 static_cast<RenderProcessHostImpl
*>(GetProcess());
856 // --single-process only has one renderer.
857 if (process
->GetActiveViewCount() > 1 &&
858 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess
))
862 if (bindings_flags
& BINDINGS_POLICY_WEB_UI
) {
863 ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
864 GetProcess()->GetID());
867 enabled_bindings_
|= bindings_flags
;
868 if (renderer_initialized_
)
869 Send(new ViewMsg_AllowBindings(GetRoutingID(), enabled_bindings_
));
872 int RenderViewHostImpl::GetEnabledBindings() const {
873 return enabled_bindings_
;
876 void RenderViewHostImpl::SetWebUIProperty(const std::string
& name
,
877 const std::string
& value
) {
878 // This is a sanity check before telling the renderer to enable the property.
879 // It could lie and send the corresponding IPC messages anyway, but we will
880 // not act on them if enabled_bindings_ doesn't agree. If we get here without
881 // WebUI bindings, kill the renderer process.
882 if (enabled_bindings_
& BINDINGS_POLICY_WEB_UI
) {
883 Send(new ViewMsg_SetWebUIProperty(GetRoutingID(), name
, value
));
886 base::UserMetricsAction("BindingsMismatchTerminate_RVH_WebUI"));
888 GetProcess()->GetHandle(), content::RESULT_CODE_KILLED
, false);
892 void RenderViewHostImpl::GotFocus() {
893 RenderWidgetHostImpl::GotFocus(); // Notifies the renderer it got focus.
895 RenderViewHostDelegateView
* view
= delegate_
->GetDelegateView();
900 void RenderViewHostImpl::LostCapture() {
901 RenderWidgetHostImpl::LostCapture();
902 delegate_
->LostCapture();
905 void RenderViewHostImpl::LostMouseLock() {
906 RenderWidgetHostImpl::LostMouseLock();
907 delegate_
->LostMouseLock();
910 void RenderViewHostImpl::SetInitialFocus(bool reverse
) {
911 Send(new ViewMsg_SetInitialFocus(GetRoutingID(), reverse
));
914 void RenderViewHostImpl::FilesSelectedInChooser(
915 const std::vector
<ui::SelectedFileInfo
>& files
,
916 FileChooserParams::Mode permissions
) {
917 // Grant the security access requested to the given files.
918 for (size_t i
= 0; i
< files
.size(); ++i
) {
919 const ui::SelectedFileInfo
& file
= files
[i
];
920 if (permissions
== FileChooserParams::Save
) {
921 ChildProcessSecurityPolicyImpl::GetInstance()->GrantCreateReadWriteFile(
922 GetProcess()->GetID(), file
.local_path
);
924 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
925 GetProcess()->GetID(), file
.local_path
);
928 Send(new ViewMsg_RunFileChooserResponse(GetRoutingID(), files
));
931 void RenderViewHostImpl::DirectoryEnumerationFinished(
933 const std::vector
<base::FilePath
>& files
) {
934 // Grant the security access requested to the given files.
935 for (std::vector
<base::FilePath
>::const_iterator file
= files
.begin();
936 file
!= files
.end(); ++file
) {
937 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
938 GetProcess()->GetID(), *file
);
940 Send(new ViewMsg_EnumerateDirectoryResponse(GetRoutingID(),
945 void RenderViewHostImpl::LoadStateChanged(
947 const net::LoadStateWithParam
& load_state
,
948 uint64 upload_position
,
949 uint64 upload_size
) {
950 delegate_
->LoadStateChanged(url
, load_state
, upload_position
, upload_size
);
953 bool RenderViewHostImpl::SuddenTerminationAllowed() const {
954 return sudden_termination_allowed_
||
955 GetProcess()->SuddenTerminationAllowed();
958 ///////////////////////////////////////////////////////////////////////////////
959 // RenderViewHostImpl, IPC message handlers:
961 bool RenderViewHostImpl::OnMessageReceived(const IPC::Message
& msg
) {
962 if (!BrowserMessageFilter::CheckCanDispatchOnUI(msg
, this))
965 // Filter out most IPC messages if this renderer is swapped out.
966 // We still want to handle certain ACKs to keep our state consistent.
967 if (IsSwappedOut()) {
968 if (!SwappedOutMessages::CanHandleWhileSwappedOut(msg
)) {
969 // If this is a synchronous message and we decided not to handle it,
970 // we must send an error reply, or else the renderer will be stuck
971 // and won't respond to future requests.
973 IPC::Message
* reply
= IPC::SyncMessage::GenerateReply(&msg
);
974 reply
->set_reply_error();
977 // Don't continue looking for someone to handle it.
982 if (delegate_
->OnMessageReceived(this, msg
))
986 bool msg_is_ok
= true;
987 IPC_BEGIN_MESSAGE_MAP_EX(RenderViewHostImpl
, msg
, msg_is_ok
)
988 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowView
, OnShowView
)
989 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget
, OnShowWidget
)
990 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowFullscreenWidget
,
991 OnShowFullscreenWidget
)
992 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunModal
, OnRunModal
)
993 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady
, OnRenderViewReady
)
994 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderProcessGone
, OnRenderProcessGone
)
995 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateState
, OnUpdateState
)
996 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTitle
, OnUpdateTitle
)
997 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateEncoding
, OnUpdateEncoding
)
998 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTargetURL
, OnUpdateTargetURL
)
999 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateInspectorSetting
,
1000 OnUpdateInspectorSetting
)
1001 IPC_MESSAGE_HANDLER(ViewHostMsg_Close
, OnClose
)
1002 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove
, OnRequestMove
)
1003 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeLoadProgress
,
1004 OnDidChangeLoadProgress
)
1005 IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentAvailableInMainFrame
,
1006 OnDocumentAvailableInMainFrame
)
1007 IPC_MESSAGE_HANDLER(ViewHostMsg_ToggleFullscreen
, OnToggleFullscreen
)
1008 IPC_MESSAGE_HANDLER(ViewHostMsg_DidContentsPreferredSizeChange
,
1009 OnDidContentsPreferredSizeChange
)
1010 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeScrollOffset
,
1011 OnDidChangeScrollOffset
)
1012 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeScrollOffsetPinningForMainFrame
,
1013 OnDidChangeScrollOffsetPinningForMainFrame
)
1014 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeNumWheelEvents
,
1015 OnDidChangeNumWheelEvents
)
1016 IPC_MESSAGE_HANDLER(ViewHostMsg_RouteCloseEvent
,
1018 IPC_MESSAGE_HANDLER(ViewHostMsg_RouteMessageEvent
, OnRouteMessageEvent
)
1019 IPC_MESSAGE_HANDLER(DragHostMsg_StartDragging
, OnStartDragging
)
1020 IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor
, OnUpdateDragCursor
)
1021 IPC_MESSAGE_HANDLER(DragHostMsg_TargetDrop_ACK
, OnTargetDropACK
)
1022 IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus
, OnTakeFocus
)
1023 IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeChanged
, OnFocusedNodeChanged
)
1024 IPC_MESSAGE_HANDLER(ViewHostMsg_ClosePage_ACK
, OnClosePageACK
)
1025 #if defined(OS_ANDROID)
1026 IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionRootBoundsChanged
,
1027 OnSelectionRootBoundsChanged
)
1029 IPC_MESSAGE_HANDLER(ViewHostMsg_DidZoomURL
, OnDidZoomURL
)
1030 #if defined(OS_MACOSX) || defined(OS_ANDROID)
1031 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup
, OnShowPopup
)
1032 IPC_MESSAGE_HANDLER(ViewHostMsg_HidePopup
, OnHidePopup
)
1034 IPC_MESSAGE_HANDLER(ViewHostMsg_RunFileChooser
, OnRunFileChooser
)
1035 IPC_MESSAGE_HANDLER(AccessibilityHostMsg_Events
, OnAccessibilityEvents
)
1036 IPC_MESSAGE_HANDLER(AccessibilityHostMsg_LocationChanges
,
1037 OnAccessibilityLocationChanges
)
1038 IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeTouched
, OnFocusedNodeTouched
)
1039 // Have the super handle all other messages.
1040 IPC_MESSAGE_UNHANDLED(
1041 handled
= RenderWidgetHostImpl::OnMessageReceived(msg
))
1042 IPC_END_MESSAGE_MAP_EX()
1045 // The message had a handler, but its de-serialization failed.
1046 // Kill the renderer.
1047 RecordAction(base::UserMetricsAction("BadMessageTerminate_RVH"));
1048 GetProcess()->ReceivedBadMessage();
1054 void RenderViewHostImpl::Init() {
1055 RenderWidgetHostImpl::Init();
1058 void RenderViewHostImpl::Shutdown() {
1059 // If we are being run modally (see RunModal), then we need to cleanup.
1060 if (run_modal_reply_msg_
) {
1061 Send(run_modal_reply_msg_
);
1062 run_modal_reply_msg_
= NULL
;
1063 RenderViewHostImpl
* opener
=
1064 RenderViewHostImpl::FromID(GetProcess()->GetID(), run_modal_opener_id_
);
1066 opener
->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(
1067 hung_renderer_delay_ms_
));
1068 // Balance out the decrement when we got created.
1069 opener
->increment_in_flight_event_count();
1071 run_modal_opener_id_
= MSG_ROUTING_NONE
;
1074 RenderWidgetHostImpl::Shutdown();
1077 bool RenderViewHostImpl::IsRenderView() const {
1081 void RenderViewHostImpl::CreateNewWindow(
1083 int main_frame_route_id
,
1084 const ViewHostMsg_CreateWindow_Params
& params
,
1085 SessionStorageNamespace
* session_storage_namespace
) {
1086 ViewHostMsg_CreateWindow_Params
validated_params(params
);
1087 GetProcess()->FilterURL(false, &validated_params
.target_url
);
1088 GetProcess()->FilterURL(false, &validated_params
.opener_url
);
1089 GetProcess()->FilterURL(true, &validated_params
.opener_security_origin
);
1091 delegate_
->CreateNewWindow(
1092 GetProcess()->GetID(), route_id
, main_frame_route_id
, validated_params
,
1093 session_storage_namespace
);
1096 void RenderViewHostImpl::CreateNewWidget(int route_id
,
1097 blink::WebPopupType popup_type
) {
1098 delegate_
->CreateNewWidget(GetProcess()->GetID(), route_id
, popup_type
);
1101 void RenderViewHostImpl::CreateNewFullscreenWidget(int route_id
) {
1102 delegate_
->CreateNewFullscreenWidget(GetProcess()->GetID(), route_id
);
1105 void RenderViewHostImpl::OnShowView(int route_id
,
1106 WindowOpenDisposition disposition
,
1107 const gfx::Rect
& initial_pos
,
1108 bool user_gesture
) {
1109 if (IsRVHStateActive(rvh_state_
)) {
1110 delegate_
->ShowCreatedWindow(
1111 route_id
, disposition
, initial_pos
, user_gesture
);
1113 Send(new ViewMsg_Move_ACK(route_id
));
1116 void RenderViewHostImpl::OnShowWidget(int route_id
,
1117 const gfx::Rect
& initial_pos
) {
1118 if (IsRVHStateActive(rvh_state_
))
1119 delegate_
->ShowCreatedWidget(route_id
, initial_pos
);
1120 Send(new ViewMsg_Move_ACK(route_id
));
1123 void RenderViewHostImpl::OnShowFullscreenWidget(int route_id
) {
1124 if (IsRVHStateActive(rvh_state_
))
1125 delegate_
->ShowCreatedFullscreenWidget(route_id
);
1126 Send(new ViewMsg_Move_ACK(route_id
));
1129 void RenderViewHostImpl::OnRunModal(int opener_id
, IPC::Message
* reply_msg
) {
1130 DCHECK(!run_modal_reply_msg_
);
1131 run_modal_reply_msg_
= reply_msg
;
1132 run_modal_opener_id_
= opener_id
;
1134 RecordAction(base::UserMetricsAction("ShowModalDialog"));
1136 RenderViewHostImpl
* opener
=
1137 RenderViewHostImpl::FromID(GetProcess()->GetID(), run_modal_opener_id_
);
1139 opener
->StopHangMonitorTimeout();
1140 // The ack for the mouse down won't come until the dialog closes, so fake it
1141 // so that we don't get a timeout.
1142 opener
->decrement_in_flight_event_count();
1145 // TODO(darin): Bug 1107929: Need to inform our delegate to show this view in
1146 // an app-modal fashion.
1149 void RenderViewHostImpl::OnRenderViewReady() {
1150 render_view_termination_status_
= base::TERMINATION_STATUS_STILL_RUNNING
;
1153 delegate_
->RenderViewReady(this);
1156 void RenderViewHostImpl::OnRenderProcessGone(int status
, int exit_code
) {
1157 // Keep the termination status so we can get at it later when we
1158 // need to know why it died.
1159 render_view_termination_status_
=
1160 static_cast<base::TerminationStatus
>(status
);
1162 // Reset frame tree state associated with this process. This must happen
1163 // before RenderViewTerminated because observers expect the subframes of any
1164 // affected frames to be cleared first.
1165 delegate_
->GetFrameTree()->RenderProcessGone(this);
1167 // Our base class RenderWidgetHost needs to reset some stuff.
1168 RendererExited(render_view_termination_status_
, exit_code
);
1170 delegate_
->RenderViewTerminated(this,
1171 static_cast<base::TerminationStatus
>(status
),
1175 void RenderViewHostImpl::OnUpdateState(int32 page_id
, const PageState
& state
) {
1176 // Without this check, the renderer can trick the browser into using
1177 // filenames it can't access in a future session restore.
1178 if (!CanAccessFilesOfPageState(state
)) {
1179 GetProcess()->ReceivedBadMessage();
1183 delegate_
->UpdateState(this, page_id
, state
);
1186 void RenderViewHostImpl::OnUpdateTitle(
1188 const base::string16
& title
,
1189 blink::WebTextDirection title_direction
) {
1190 if (title
.length() > kMaxTitleChars
) {
1191 NOTREACHED() << "Renderer sent too many characters in title.";
1195 delegate_
->UpdateTitle(this, page_id
, title
,
1196 WebTextDirectionToChromeTextDirection(
1200 void RenderViewHostImpl::OnUpdateEncoding(const std::string
& encoding_name
) {
1201 delegate_
->UpdateEncoding(this, encoding_name
);
1204 void RenderViewHostImpl::OnUpdateTargetURL(int32 page_id
, const GURL
& url
) {
1205 if (IsRVHStateActive(rvh_state_
))
1206 delegate_
->UpdateTargetURL(page_id
, url
);
1208 // Send a notification back to the renderer that we are ready to
1209 // receive more target urls.
1210 Send(new ViewMsg_UpdateTargetURL_ACK(GetRoutingID()));
1213 void RenderViewHostImpl::OnUpdateInspectorSetting(
1214 const std::string
& key
, const std::string
& value
) {
1215 GetContentClient()->browser()->UpdateInspectorSetting(
1219 void RenderViewHostImpl::OnClose() {
1220 // If the renderer is telling us to close, it has already run the unload
1221 // events, and we can take the fast path.
1222 ClosePageIgnoringUnloadEvents();
1225 void RenderViewHostImpl::OnRequestMove(const gfx::Rect
& pos
) {
1226 if (IsRVHStateActive(rvh_state_
))
1227 delegate_
->RequestMove(pos
);
1228 Send(new ViewMsg_Move_ACK(GetRoutingID()));
1231 void RenderViewHostImpl::OnDidChangeLoadProgress(double load_progress
) {
1232 delegate_
->DidChangeLoadProgress(load_progress
);
1235 void RenderViewHostImpl::OnDocumentAvailableInMainFrame() {
1236 delegate_
->DocumentAvailableInMainFrame(this);
1239 void RenderViewHostImpl::OnToggleFullscreen(bool enter_fullscreen
) {
1240 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
1241 delegate_
->ToggleFullscreenMode(enter_fullscreen
);
1242 // We need to notify the contents that its fullscreen state has changed. This
1243 // is done as part of the resize message.
1247 void RenderViewHostImpl::OnDidContentsPreferredSizeChange(
1248 const gfx::Size
& new_size
) {
1249 delegate_
->UpdatePreferredSize(new_size
);
1252 void RenderViewHostImpl::OnRenderAutoResized(const gfx::Size
& new_size
) {
1253 delegate_
->ResizeDueToAutoResize(new_size
);
1256 void RenderViewHostImpl::OnDidChangeScrollOffset() {
1258 view_
->ScrollOffsetChanged();
1261 void RenderViewHostImpl::OnDidChangeScrollOffsetPinningForMainFrame(
1262 bool is_pinned_to_left
, bool is_pinned_to_right
) {
1264 view_
->SetScrollOffsetPinning(is_pinned_to_left
, is_pinned_to_right
);
1267 void RenderViewHostImpl::OnDidChangeNumWheelEvents(int count
) {
1270 #if defined(OS_ANDROID)
1271 void RenderViewHostImpl::OnSelectionRootBoundsChanged(
1272 const gfx::Rect
& bounds
) {
1274 view_
->SelectionRootBoundsChanged(bounds
);
1279 void RenderViewHostImpl::OnRouteCloseEvent() {
1280 // Have the delegate route this to the active RenderViewHost.
1281 delegate_
->RouteCloseEvent(this);
1284 void RenderViewHostImpl::OnRouteMessageEvent(
1285 const ViewMsg_PostMessage_Params
& params
) {
1286 // Give to the delegate to route to the active RenderViewHost.
1287 delegate_
->RouteMessageEvent(this, params
);
1290 void RenderViewHostImpl::OnStartDragging(
1291 const DropData
& drop_data
,
1292 WebDragOperationsMask drag_operations_mask
,
1293 const SkBitmap
& bitmap
,
1294 const gfx::Vector2d
& bitmap_offset_in_dip
,
1295 const DragEventSourceInfo
& event_info
) {
1296 RenderViewHostDelegateView
* view
= delegate_
->GetDelegateView();
1300 DropData
filtered_data(drop_data
);
1301 RenderProcessHost
* process
= GetProcess();
1302 ChildProcessSecurityPolicyImpl
* policy
=
1303 ChildProcessSecurityPolicyImpl::GetInstance();
1305 // Allow drag of Javascript URLs to enable bookmarklet drag to bookmark bar.
1306 if (!filtered_data
.url
.SchemeIs(kJavaScriptScheme
))
1307 process
->FilterURL(true, &filtered_data
.url
);
1308 process
->FilterURL(false, &filtered_data
.html_base_url
);
1309 // Filter out any paths that the renderer didn't have access to. This prevents
1310 // the following attack on a malicious renderer:
1311 // 1. StartDragging IPC sent with renderer-specified filesystem paths that it
1312 // doesn't have read permissions for.
1313 // 2. We initiate a native DnD operation.
1314 // 3. DnD operation immediately ends since mouse is not held down. DnD events
1315 // still fire though, which causes read permissions to be granted to the
1316 // renderer for any file paths in the drop.
1317 filtered_data
.filenames
.clear();
1318 for (std::vector
<ui::FileInfo
>::const_iterator it
=
1319 drop_data
.filenames
.begin();
1320 it
!= drop_data
.filenames
.end();
1322 if (policy
->CanReadFile(GetProcess()->GetID(), it
->path
))
1323 filtered_data
.filenames
.push_back(*it
);
1326 fileapi::FileSystemContext
* file_system_context
=
1327 BrowserContext::GetStoragePartition(
1328 GetProcess()->GetBrowserContext(),
1329 GetSiteInstance())->GetFileSystemContext();
1330 filtered_data
.file_system_files
.clear();
1331 for (size_t i
= 0; i
< drop_data
.file_system_files
.size(); ++i
) {
1332 fileapi::FileSystemURL file_system_url
=
1333 file_system_context
->CrackURL(drop_data
.file_system_files
[i
].url
);
1334 if (policy
->CanReadFileSystemFile(GetProcess()->GetID(), file_system_url
))
1335 filtered_data
.file_system_files
.push_back(drop_data
.file_system_files
[i
]);
1338 float scale
= ui::GetImageScale(GetScaleFactorForView(GetView()));
1339 gfx::ImageSkia
image(gfx::ImageSkiaRep(bitmap
, scale
));
1340 view
->StartDragging(filtered_data
, drag_operations_mask
, image
,
1341 bitmap_offset_in_dip
, event_info
);
1344 void RenderViewHostImpl::OnUpdateDragCursor(WebDragOperation current_op
) {
1345 RenderViewHostDelegateView
* view
= delegate_
->GetDelegateView();
1347 view
->UpdateDragCursor(current_op
);
1350 void RenderViewHostImpl::OnTargetDropACK() {
1351 NotificationService::current()->Notify(
1352 NOTIFICATION_RENDER_VIEW_HOST_DID_RECEIVE_DRAG_TARGET_DROP_ACK
,
1353 Source
<RenderViewHost
>(this),
1354 NotificationService::NoDetails());
1357 void RenderViewHostImpl::OnTakeFocus(bool reverse
) {
1358 RenderViewHostDelegateView
* view
= delegate_
->GetDelegateView();
1360 view
->TakeFocus(reverse
);
1363 void RenderViewHostImpl::OnFocusedNodeChanged(bool is_editable_node
) {
1365 view_
->FocusedNodeChanged(is_editable_node
);
1367 if (!is_editable_node
&& virtual_keyboard_requested_
) {
1368 virtual_keyboard_requested_
= false;
1369 BrowserThread::PostDelayedTask(
1370 BrowserThread::UI
, FROM_HERE
,
1371 base::Bind(base::IgnoreResult(&DismissVirtualKeyboardTask
)),
1372 TimeDelta::FromMilliseconds(kVirtualKeyboardDisplayWaitTimeoutMs
));
1375 NotificationService::current()->Notify(
1376 NOTIFICATION_FOCUS_CHANGED_IN_PAGE
,
1377 Source
<RenderViewHost
>(this),
1378 Details
<const bool>(&is_editable_node
));
1381 void RenderViewHostImpl::OnUserGesture() {
1382 delegate_
->OnUserGesture();
1385 void RenderViewHostImpl::OnClosePageACK() {
1386 decrement_in_flight_event_count();
1387 ClosePageIgnoringUnloadEvents();
1390 void RenderViewHostImpl::NotifyRendererUnresponsive() {
1391 delegate_
->RendererUnresponsive(
1392 this, is_waiting_for_beforeunload_ack_
, IsWaitingForUnloadACK());
1395 void RenderViewHostImpl::NotifyRendererResponsive() {
1396 delegate_
->RendererResponsive(this);
1399 void RenderViewHostImpl::RequestToLockMouse(bool user_gesture
,
1400 bool last_unlocked_by_target
) {
1401 delegate_
->RequestToLockMouse(user_gesture
, last_unlocked_by_target
);
1404 bool RenderViewHostImpl::IsFullscreen() const {
1405 return delegate_
->IsFullscreenForCurrentTab();
1408 void RenderViewHostImpl::OnFocus() {
1409 // Note: We allow focus and blur from swapped out RenderViewHosts, even when
1410 // the active RenderViewHost is in a different BrowsingInstance (e.g., WebUI).
1411 delegate_
->Activate();
1414 void RenderViewHostImpl::OnBlur() {
1415 delegate_
->Deactivate();
1418 gfx::Rect
RenderViewHostImpl::GetRootWindowResizerRect() const {
1419 return delegate_
->GetRootWindowResizerRect();
1422 void RenderViewHostImpl::ForwardMouseEvent(
1423 const blink::WebMouseEvent
& mouse_event
) {
1425 // We make a copy of the mouse event because
1426 // RenderWidgetHost::ForwardMouseEvent will delete |mouse_event|.
1427 blink::WebMouseEvent
event_copy(mouse_event
);
1428 RenderWidgetHostImpl::ForwardMouseEvent(event_copy
);
1430 switch (event_copy
.type
) {
1431 case WebInputEvent::MouseMove
:
1432 delegate_
->HandleMouseMove();
1434 case WebInputEvent::MouseLeave
:
1435 delegate_
->HandleMouseLeave();
1437 case WebInputEvent::MouseDown
:
1438 delegate_
->HandleMouseDown();
1440 case WebInputEvent::MouseWheel
:
1441 if (ignore_input_events())
1442 delegate_
->OnIgnoredUIEvent();
1444 case WebInputEvent::MouseUp
:
1445 delegate_
->HandleMouseUp();
1447 // For now, we don't care about the rest.
1452 void RenderViewHostImpl::OnPointerEventActivate() {
1453 delegate_
->HandlePointerActivate();
1456 void RenderViewHostImpl::ForwardKeyboardEvent(
1457 const NativeWebKeyboardEvent
& key_event
) {
1458 if (ignore_input_events()) {
1459 if (key_event
.type
== WebInputEvent::RawKeyDown
)
1460 delegate_
->OnIgnoredUIEvent();
1463 RenderWidgetHostImpl::ForwardKeyboardEvent(key_event
);
1466 #if defined(OS_ANDROID)
1467 void RenderViewHostImpl::DidSelectPopupMenuItems(
1468 const std::vector
<int>& selected_indices
) {
1469 Send(new ViewMsg_SelectPopupMenuItems(GetRoutingID(), false,
1473 void RenderViewHostImpl::DidCancelPopupMenu() {
1474 Send(new ViewMsg_SelectPopupMenuItems(GetRoutingID(), true,
1475 std::vector
<int>()));
1479 #if defined(OS_MACOSX)
1480 void RenderViewHostImpl::DidSelectPopupMenuItem(int selected_index
) {
1481 Send(new ViewMsg_SelectPopupMenuItem(GetRoutingID(), selected_index
));
1484 void RenderViewHostImpl::DidCancelPopupMenu() {
1485 Send(new ViewMsg_SelectPopupMenuItem(GetRoutingID(), -1));
1489 void RenderViewHostImpl::SendOrientationChangeEvent(int orientation
) {
1490 Send(new ViewMsg_OrientationChangeEvent(GetRoutingID(), orientation
));
1493 bool RenderViewHostImpl::IsWaitingForUnloadACK() const {
1494 return rvh_state_
== STATE_WAITING_FOR_UNLOAD_ACK
||
1495 rvh_state_
== STATE_WAITING_FOR_CLOSE
||
1496 rvh_state_
== STATE_PENDING_SHUTDOWN
||
1497 rvh_state_
== STATE_PENDING_SWAP_OUT
;
1500 void RenderViewHostImpl::ExitFullscreen() {
1501 RejectMouseLockOrUnlockIfNecessary();
1502 // Notify delegate_ and renderer of fullscreen state change.
1503 OnToggleFullscreen(false);
1506 WebPreferences
RenderViewHostImpl::GetWebkitPreferences() {
1507 return delegate_
->GetWebkitPrefs();
1510 void RenderViewHostImpl::DisownOpener() {
1511 // This should only be called when swapped out.
1512 DCHECK(IsSwappedOut());
1514 Send(new ViewMsg_DisownOpener(GetRoutingID()));
1517 void RenderViewHostImpl::SetAccessibilityCallbackForTesting(
1518 const base::Callback
<void(ui::AXEvent
)>& callback
) {
1519 accessibility_testing_callback_
= callback
;
1522 void RenderViewHostImpl::UpdateWebkitPreferences(const WebPreferences
& prefs
) {
1523 Send(new ViewMsg_UpdateWebPreferences(GetRoutingID(), prefs
));
1526 void RenderViewHostImpl::GetAudioOutputControllers(
1527 const GetAudioOutputControllersCallback
& callback
) const {
1528 AudioRendererHost
* audio_host
=
1529 static_cast<RenderProcessHostImpl
*>(GetProcess())->audio_renderer_host();
1530 audio_host
->GetOutputControllers(GetRoutingID(), callback
);
1533 void RenderViewHostImpl::ClearFocusedElement() {
1534 Send(new ViewMsg_ClearFocusedElement(GetRoutingID()));
1537 void RenderViewHostImpl::Zoom(PageZoom zoom
) {
1538 Send(new ViewMsg_Zoom(GetRoutingID(), zoom
));
1541 void RenderViewHostImpl::DisableScrollbarsForThreshold(const gfx::Size
& size
) {
1542 Send(new ViewMsg_DisableScrollbarsForSmallWindows(GetRoutingID(), size
));
1545 void RenderViewHostImpl::EnablePreferredSizeMode() {
1546 Send(new ViewMsg_EnablePreferredSizeChangedMode(GetRoutingID()));
1549 void RenderViewHostImpl::EnableAutoResize(const gfx::Size
& min_size
,
1550 const gfx::Size
& max_size
) {
1551 SetShouldAutoResize(true);
1552 Send(new ViewMsg_EnableAutoResize(GetRoutingID(), min_size
, max_size
));
1555 void RenderViewHostImpl::DisableAutoResize(const gfx::Size
& new_size
) {
1556 SetShouldAutoResize(false);
1557 Send(new ViewMsg_DisableAutoResize(GetRoutingID(), new_size
));
1560 void RenderViewHostImpl::CopyImageAt(int x
, int y
) {
1561 Send(new ViewMsg_CopyImageAt(GetRoutingID(), x
, y
));
1564 void RenderViewHostImpl::ExecuteMediaPlayerActionAtLocation(
1565 const gfx::Point
& location
, const blink::WebMediaPlayerAction
& action
) {
1566 Send(new ViewMsg_MediaPlayerActionAt(GetRoutingID(), location
, action
));
1569 void RenderViewHostImpl::ExecutePluginActionAtLocation(
1570 const gfx::Point
& location
, const blink::WebPluginAction
& action
) {
1571 Send(new ViewMsg_PluginActionAt(GetRoutingID(), location
, action
));
1574 void RenderViewHostImpl::NotifyMoveOrResizeStarted() {
1575 Send(new ViewMsg_MoveOrResizeStarted(GetRoutingID()));
1578 void RenderViewHostImpl::OnAccessibilityEvents(
1579 const std::vector
<AccessibilityHostMsg_EventParams
>& params
) {
1580 if ((accessibility_mode() != AccessibilityModeOff
) && view_
&&
1581 IsRVHStateActive(rvh_state_
)) {
1582 if (accessibility_mode() & AccessibilityModeFlagPlatform
) {
1583 view_
->CreateBrowserAccessibilityManagerIfNeeded();
1584 BrowserAccessibilityManager
* manager
=
1585 view_
->GetBrowserAccessibilityManager();
1587 manager
->OnAccessibilityEvents(params
);
1590 std::vector
<AXEventNotificationDetails
> details
;
1591 for (unsigned int i
= 0; i
< params
.size(); ++i
) {
1592 const AccessibilityHostMsg_EventParams
& param
= params
[i
];
1593 AXEventNotificationDetails
detail(param
.update
.nodes
,
1596 GetProcess()->GetID(),
1598 details
.push_back(detail
);
1601 delegate_
->AccessibilityEventReceived(details
);
1604 // Always send an ACK or the renderer can be in a bad state.
1605 Send(new AccessibilityMsg_Events_ACK(GetRoutingID()));
1607 // The rest of this code is just for testing; bail out if we're not
1609 if (accessibility_testing_callback_
.is_null())
1612 for (unsigned i
= 0; i
< params
.size(); i
++) {
1613 const AccessibilityHostMsg_EventParams
& param
= params
[i
];
1614 if (static_cast<int>(param
.event_type
) < 0)
1617 ax_tree_
.reset(new ui::AXTree(param
.update
));
1619 CHECK(ax_tree_
->Unserialize(param
.update
)) << ax_tree_
->error();
1620 accessibility_testing_callback_
.Run(param
.event_type
);
1624 void RenderViewHostImpl::OnAccessibilityLocationChanges(
1625 const std::vector
<AccessibilityHostMsg_LocationChangeParams
>& params
) {
1626 if (view_
&& IsRVHStateActive(rvh_state_
)) {
1627 if (accessibility_mode() & AccessibilityModeFlagPlatform
) {
1628 view_
->CreateBrowserAccessibilityManagerIfNeeded();
1629 BrowserAccessibilityManager
* manager
=
1630 view_
->GetBrowserAccessibilityManager();
1632 manager
->OnLocationChanges(params
);
1634 // TODO(aboxhall): send location change events to web contents observers too
1638 void RenderViewHostImpl::OnDidZoomURL(double zoom_level
,
1641 HostZoomMapImpl
* host_zoom_map
= static_cast<HostZoomMapImpl
*>(
1642 HostZoomMap::GetForBrowserContext(GetProcess()->GetBrowserContext()));
1645 SetZoomLevelForHost(net::GetHostOrSpecFromURL(url
), zoom_level
);
1647 host_zoom_map
->SetTemporaryZoomLevel(
1648 GetProcess()->GetID(), GetRoutingID(), zoom_level
);
1652 void RenderViewHostImpl::OnRunFileChooser(const FileChooserParams
& params
) {
1653 delegate_
->RunFileChooser(this, params
);
1656 void RenderViewHostImpl::OnFocusedNodeTouched(bool editable
) {
1659 virtual_keyboard_requested_
= base::win::DisplayVirtualKeyboard();
1661 virtual_keyboard_requested_
= false;
1662 base::win::DismissVirtualKeyboard();
1667 #if defined(OS_MACOSX) || defined(OS_ANDROID)
1668 void RenderViewHostImpl::OnShowPopup(
1669 const ViewHostMsg_ShowPopup_Params
& params
) {
1670 RenderViewHostDelegateView
* view
= delegate_
->GetDelegateView();
1672 view
->ShowPopupMenu(params
.bounds
,
1674 params
.item_font_size
,
1675 params
.selected_item
,
1677 params
.right_aligned
,
1678 params
.allow_multiple_selection
);
1682 void RenderViewHostImpl::OnHidePopup() {
1683 RenderViewHostDelegateView
* view
= delegate_
->GetDelegateView();
1685 view
->HidePopupMenu();
1689 void RenderViewHostImpl::SetState(RenderViewHostImplState rvh_state
) {
1690 // We update the number of RenderViews in a SiteInstance when the
1691 // swapped out status of this RenderView gets flipped to/from live.
1692 if (!IsRVHStateActive(rvh_state_
) && IsRVHStateActive(rvh_state
))
1693 instance_
->increment_active_view_count();
1694 else if (IsRVHStateActive(rvh_state_
) && !IsRVHStateActive(rvh_state
))
1695 instance_
->decrement_active_view_count();
1697 // Whenever we change the RVH state to and from live or swapped out state, we
1698 // should not be waiting for beforeunload or unload acks. We clear them here
1699 // to be safe, since they can cause navigations to be ignored in OnNavigate.
1700 if (rvh_state
== STATE_DEFAULT
||
1701 rvh_state
== STATE_SWAPPED_OUT
||
1702 rvh_state_
== STATE_DEFAULT
||
1703 rvh_state_
== STATE_SWAPPED_OUT
) {
1704 is_waiting_for_beforeunload_ack_
= false;
1706 rvh_state_
= rvh_state
;
1710 bool RenderViewHostImpl::CanAccessFilesOfPageState(
1711 const PageState
& state
) const {
1712 ChildProcessSecurityPolicyImpl
* policy
=
1713 ChildProcessSecurityPolicyImpl::GetInstance();
1715 const std::vector
<base::FilePath
>& file_paths
= state
.GetReferencedFiles();
1716 for (std::vector
<base::FilePath
>::const_iterator file
= file_paths
.begin();
1717 file
!= file_paths
.end(); ++file
) {
1718 if (!policy
->CanReadFile(GetProcess()->GetID(), *file
))
1724 void RenderViewHostImpl::AttachToFrameTree() {
1725 FrameTree
* frame_tree
= delegate_
->GetFrameTree();
1727 frame_tree
->ResetForMainFrameSwap();
1730 } // namespace content