Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / content / browser / renderer_host / render_view_host_impl.cc
blobc329fb07f677bf7828f71350764490f53d99cc3c
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"
7 #include <set>
8 #include <string>
9 #include <utility>
10 #include <vector>
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"
96 #elif defined(OS_WIN)
97 #include "base/win/win_util.h"
98 #endif
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;
109 namespace content {
110 namespace {
112 // Translate a WebKit text direction into a base::i18n one.
113 base::i18n::TextDirection WebTextDirectionToChromeTextDirection(
114 blink::WebTextDirection dir) {
115 switch (dir) {
116 case blink::WebTextDirectionLeftToRight:
117 return base::i18n::LEFT_TO_RIGHT;
118 case blink::WebTextDirectionRightToLeft:
119 return base::i18n::RIGHT_TO_LEFT;
120 default:
121 NOTREACHED();
122 return base::i18n::UNKNOWN_DIRECTION;
126 #if defined(OS_WIN)
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;
142 } else {
143 virtual_keyboard_display_retries = 0;
147 #endif
149 } // namespace
151 // static
152 const int RenderViewHostImpl::kUnloadTimeoutMS = 1000;
154 ///////////////////////////////////////////////////////////////////////////////
155 // RenderViewHost, public:
157 // static
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)
163 return true;
164 return false;
167 // static
168 RenderViewHost* RenderViewHost::FromID(int render_process_id,
169 int render_view_id) {
170 return RenderViewHostImpl::FromID(render_process_id, render_view_id);
173 // static
174 RenderViewHost* RenderViewHost::From(RenderWidgetHost* rwh) {
175 DCHECK(rwh->IsRenderView());
176 return static_cast<RenderViewHostImpl*>(RenderWidgetHostImpl::From(rwh));
179 ///////////////////////////////////////////////////////////////////////////////
180 // RenderViewHostImpl, public:
182 // static
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())
188 return NULL;
189 return static_cast<RenderViewHostImpl*>(RenderWidgetHostImpl::From(widget));
192 RenderViewHostImpl::RenderViewHostImpl(
193 SiteInstance* instance,
194 RenderViewHostDelegate* delegate,
195 RenderWidgetHostDelegate* widget_delegate,
196 int routing_id,
197 int main_frame_routing_id,
198 bool swapped_out,
199 bool hidden)
200 : RenderWidgetHostImpl(widget_delegate,
201 instance->GetProcess(),
202 routing_id,
203 hidden),
204 frames_ref_count_(0),
205 delegate_(delegate),
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();
224 if (swapped_out) {
225 rvh_state_ = STATE_SWAPPED_OUT;
226 } else {
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));
241 #endif
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 {
269 return delegate_;
272 SiteInstance* RenderViewHostImpl::GetSiteInstance() const {
273 return instance_.get();
276 bool RenderViewHostImpl::CreateRenderView(
277 const base::string16& frame_name,
278 int opener_route_id,
279 int32 max_page_id,
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())
289 return false;
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(&params.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);
334 return true;
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);
359 prefs.java_enabled =
360 !command_line.HasSwitch(switches::kDisableJava);
362 prefs.remote_fonts_enabled =
363 !command_line.HasSwitch(switches::kDisableRemoteFonts);
364 prefs.xslt_enabled =
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);
379 #endif
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);
440 #endif
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;
447 #endif
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;
458 #else
459 bool default_enable_scroll_animator = false;
460 #endif
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);
504 return 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(
517 bool suspend,
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())
551 return;
552 unload_event_monitor_timeout_->Stop();
553 if (timed_out) {
554 base::ProcessHandle process_handle = GetProcess()->GetHandle();
555 int views = 0;
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())
563 ++views;
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
583 // the histogram.
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);
593 break;
594 case STATE_PENDING_SWAP_OUT:
595 SetState(STATE_SWAPPED_OUT);
596 break;
597 case STATE_PENDING_SHUTDOWN:
598 DCHECK(!pending_shutdown_on_swap_out_.is_null());
599 pending_shutdown_on_swap_out_.Run();
600 break;
601 default:
602 NOTREACHED();
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);
621 } else {
622 NOTREACHED();
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()));
649 } else {
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.";
679 return;
682 if ((enabled_bindings_ & BINDINGS_POLICY_WEB_UI) == 0) {
683 NOTREACHED() << "You must grant bindings before setting the handle";
684 return;
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,
699 float x,
700 float y) {
701 Send(new InputMsg_ActivateNearestFindResult(GetRoutingID(),
702 request_id, x, y));
705 void RenderViewHostImpl::RequestFindMatchRects(int current_version) {
706 Send(new ViewMsg_FindMatchRects(GetRoutingID(), current_version));
708 #endif
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,
715 int key_modifiers) {
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();
734 ++iter) {
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()) {
743 std::string name;
744 files.AddPath(iter->path, &name);
745 iter->display_name = base::FilePath::FromUTF8Unsafe(name);
746 } else {
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(
767 files);
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(), &register_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(),
792 filesystem_id,
793 std::string()).append(register_name));
796 Send(new DragMsg_TargetDragEnter(GetRoutingID(), filtered_data, client_pt,
797 screen_pt, operations_allowed,
798 key_modifiers));
801 void RenderViewHostImpl::DragTargetDragOver(
802 const gfx::Point& client_pt,
803 const gfx::Point& screen_pt,
804 WebDragOperationsMask operations_allowed,
805 int key_modifiers) {
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,
817 int key_modifiers) {
818 Send(new DragMsg_TargetDrop(GetRoutingID(), client_pt, screen_pt,
819 key_modifiers));
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),
828 operation));
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.";
843 return;
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))
859 return;
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));
884 } else {
885 RecordAction(
886 base::UserMetricsAction("BindingsMismatchTerminate_RVH_WebUI"));
887 base::KillProcess(
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();
896 if (view)
897 view->GotFocus();
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);
923 } else {
924 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
925 GetProcess()->GetID(), file.local_path);
928 Send(new ViewMsg_RunFileChooserResponse(GetRoutingID(), files));
931 void RenderViewHostImpl::DirectoryEnumerationFinished(
932 int request_id,
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(),
941 request_id,
942 files));
945 void RenderViewHostImpl::LoadStateChanged(
946 const GURL& url,
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))
963 return true;
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.
972 if (msg.is_sync()) {
973 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
974 reply->set_reply_error();
975 Send(reply);
977 // Don't continue looking for someone to handle it.
978 return true;
982 if (delegate_->OnMessageReceived(this, msg))
983 return true;
985 bool handled = true;
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,
1017 OnRouteCloseEvent)
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)
1028 #endif
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)
1033 #endif
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()
1044 if (!msg_is_ok) {
1045 // The message had a handler, but its de-serialization failed.
1046 // Kill the renderer.
1047 RecordAction(base::UserMetricsAction("BadMessageTerminate_RVH"));
1048 GetProcess()->ReceivedBadMessage();
1051 return handled;
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_);
1065 if (opener) {
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 {
1078 return true;
1081 void RenderViewHostImpl::CreateNewWindow(
1082 int route_id,
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_);
1138 if (opener) {
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;
1151 SendScreenRects();
1152 WasResized();
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),
1172 exit_code);
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();
1180 return;
1183 delegate_->UpdateState(this, page_id, state);
1186 void RenderViewHostImpl::OnUpdateTitle(
1187 int32 page_id,
1188 const base::string16& title,
1189 blink::WebTextDirection title_direction) {
1190 if (title.length() > kMaxTitleChars) {
1191 NOTREACHED() << "Renderer sent too many characters in title.";
1192 return;
1195 delegate_->UpdateTitle(this, page_id, title,
1196 WebTextDirectionToChromeTextDirection(
1197 title_direction));
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(
1216 this, key, value);
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.
1244 WasResized();
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() {
1257 if (view_)
1258 view_->ScrollOffsetChanged();
1261 void RenderViewHostImpl::OnDidChangeScrollOffsetPinningForMainFrame(
1262 bool is_pinned_to_left, bool is_pinned_to_right) {
1263 if (view_)
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) {
1273 if (view_) {
1274 view_->SelectionRootBoundsChanged(bounds);
1277 #endif
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();
1297 if (!view)
1298 return;
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();
1321 ++it) {
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();
1346 if (view)
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();
1359 if (view)
1360 view->TakeFocus(reverse);
1363 void RenderViewHostImpl::OnFocusedNodeChanged(bool is_editable_node) {
1364 if (view_)
1365 view_->FocusedNodeChanged(is_editable_node);
1366 #if defined(OS_WIN)
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));
1374 #endif
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();
1433 break;
1434 case WebInputEvent::MouseLeave:
1435 delegate_->HandleMouseLeave();
1436 break;
1437 case WebInputEvent::MouseDown:
1438 delegate_->HandleMouseDown();
1439 break;
1440 case WebInputEvent::MouseWheel:
1441 if (ignore_input_events())
1442 delegate_->OnIgnoredUIEvent();
1443 break;
1444 case WebInputEvent::MouseUp:
1445 delegate_->HandleMouseUp();
1446 default:
1447 // For now, we don't care about the rest.
1448 break;
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();
1461 return;
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,
1470 selected_indices));
1473 void RenderViewHostImpl::DidCancelPopupMenu() {
1474 Send(new ViewMsg_SelectPopupMenuItems(GetRoutingID(), true,
1475 std::vector<int>()));
1477 #endif
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));
1487 #endif
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();
1586 if (manager)
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,
1594 param.event_type,
1595 param.id,
1596 GetProcess()->GetID(),
1597 GetRoutingID());
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
1608 // in that mode.
1609 if (accessibility_testing_callback_.is_null())
1610 return;
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)
1615 continue;
1616 if (!ax_tree_)
1617 ax_tree_.reset(new ui::AXTree(param.update));
1618 else
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();
1631 if (manager)
1632 manager->OnLocationChanges(params);
1634 // TODO(aboxhall): send location change events to web contents observers too
1638 void RenderViewHostImpl::OnDidZoomURL(double zoom_level,
1639 bool remember,
1640 const GURL& url) {
1641 HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
1642 HostZoomMap::GetForBrowserContext(GetProcess()->GetBrowserContext()));
1643 if (remember) {
1644 host_zoom_map->
1645 SetZoomLevelForHost(net::GetHostOrSpecFromURL(url), zoom_level);
1646 } else {
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) {
1657 #if defined(OS_WIN)
1658 if (editable) {
1659 virtual_keyboard_requested_ = base::win::DisplayVirtualKeyboard();
1660 } else {
1661 virtual_keyboard_requested_ = false;
1662 base::win::DismissVirtualKeyboard();
1664 #endif
1667 #if defined(OS_MACOSX) || defined(OS_ANDROID)
1668 void RenderViewHostImpl::OnShowPopup(
1669 const ViewHostMsg_ShowPopup_Params& params) {
1670 RenderViewHostDelegateView* view = delegate_->GetDelegateView();
1671 if (view) {
1672 view->ShowPopupMenu(params.bounds,
1673 params.item_height,
1674 params.item_font_size,
1675 params.selected_item,
1676 params.popup_items,
1677 params.right_aligned,
1678 params.allow_multiple_selection);
1682 void RenderViewHostImpl::OnHidePopup() {
1683 RenderViewHostDelegateView* view = delegate_->GetDelegateView();
1684 if (view)
1685 view->HidePopupMenu();
1687 #endif
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))
1719 return false;
1721 return true;
1724 void RenderViewHostImpl::AttachToFrameTree() {
1725 FrameTree* frame_tree = delegate_->GetFrameTree();
1727 frame_tree->ResetForMainFrameSwap();
1730 } // namespace content