• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/browser/renderer_host/render_view_host_impl.h"
6 
7 #include <set>
8 #include <string>
9 #include <utility>
10 #include <vector>
11 
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/field_trial.h"
19 #include "base/metrics/histogram.h"
20 #include "base/stl_util.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/sys_info.h"
24 #include "base/time/time.h"
25 #include "base/values.h"
26 #include "cc/base/switches.h"
27 #include "content/browser/child_process_security_policy_impl.h"
28 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
29 #include "content/browser/frame_host/frame_tree.h"
30 #include "content/browser/gpu/compositor_util.h"
31 #include "content/browser/gpu/gpu_data_manager_impl.h"
32 #include "content/browser/gpu/gpu_process_host.h"
33 #include "content/browser/gpu/gpu_surface_tracker.h"
34 #include "content/browser/host_zoom_map_impl.h"
35 #include "content/browser/loader/resource_dispatcher_host_impl.h"
36 #include "content/browser/renderer_host/dip_util.h"
37 #include "content/browser/renderer_host/input/timeout_monitor.h"
38 #include "content/browser/renderer_host/media/audio_renderer_host.h"
39 #include "content/browser/renderer_host/render_process_host_impl.h"
40 #include "content/browser/renderer_host/render_view_host_delegate.h"
41 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
42 #include "content/browser/renderer_host/render_widget_host_view_base.h"
43 #include "content/common/browser_plugin/browser_plugin_messages.h"
44 #include "content/common/content_switches_internal.h"
45 #include "content/common/drag_messages.h"
46 #include "content/common/frame_messages.h"
47 #include "content/common/input_messages.h"
48 #include "content/common/inter_process_time_ticks_converter.h"
49 #include "content/common/speech_recognition_messages.h"
50 #include "content/common/swapped_out_messages.h"
51 #include "content/common/view_messages.h"
52 #include "content/public/browser/ax_event_notification_details.h"
53 #include "content/public/browser/browser_accessibility_state.h"
54 #include "content/public/browser/browser_context.h"
55 #include "content/public/browser/browser_message_filter.h"
56 #include "content/public/browser/content_browser_client.h"
57 #include "content/public/browser/native_web_keyboard_event.h"
58 #include "content/public/browser/notification_details.h"
59 #include "content/public/browser/notification_service.h"
60 #include "content/public/browser/notification_types.h"
61 #include "content/public/browser/render_frame_host.h"
62 #include "content/public/browser/render_widget_host_iterator.h"
63 #include "content/public/browser/storage_partition.h"
64 #include "content/public/browser/user_metrics.h"
65 #include "content/public/common/bindings_policy.h"
66 #include "content/public/common/content_constants.h"
67 #include "content/public/common/content_switches.h"
68 #include "content/public/common/context_menu_params.h"
69 #include "content/public/common/drop_data.h"
70 #include "content/public/common/result_codes.h"
71 #include "content/public/common/url_utils.h"
72 #include "net/base/filename_util.h"
73 #include "net/base/net_util.h"
74 #include "net/base/network_change_notifier.h"
75 #include "net/url_request/url_request_context_getter.h"
76 #include "storage/browser/fileapi/isolated_context.h"
77 #include "third_party/skia/include/core/SkBitmap.h"
78 #include "ui/base/touch/touch_device.h"
79 #include "ui/base/touch/touch_enabled.h"
80 #include "ui/base/ui_base_switches.h"
81 #include "ui/gfx/image/image_skia.h"
82 #include "ui/gfx/native_widget_types.h"
83 #include "ui/native_theme/native_theme_switches.h"
84 #include "ui/shell_dialogs/selected_file_info.h"
85 #include "url/url_constants.h"
86 
87 #if defined(OS_WIN)
88 #include "base/win/win_util.h"
89 #endif
90 
91 #if defined(ENABLE_BROWSER_CDMS)
92 #include "content/browser/media/media_web_contents_observer.h"
93 #endif
94 
95 using base::TimeDelta;
96 using blink::WebConsoleMessage;
97 using blink::WebDragOperation;
98 using blink::WebDragOperationNone;
99 using blink::WebDragOperationsMask;
100 using blink::WebInputEvent;
101 using blink::WebMediaPlayerAction;
102 using blink::WebPluginAction;
103 
104 namespace content {
105 namespace {
106 
107 #if defined(OS_WIN)
108 
109 const int kVirtualKeyboardDisplayWaitTimeoutMs = 100;
110 const int kMaxVirtualKeyboardDisplayRetries = 5;
111 
DismissVirtualKeyboardTask()112 void DismissVirtualKeyboardTask() {
113   static int virtual_keyboard_display_retries = 0;
114   // If the virtual keyboard is not yet visible, then we execute the task again
115   // waiting for it to show up.
116   if (!base::win::DismissVirtualKeyboard()) {
117     if (virtual_keyboard_display_retries < kMaxVirtualKeyboardDisplayRetries) {
118       BrowserThread::PostDelayedTask(
119           BrowserThread::UI, FROM_HERE,
120           base::Bind(base::IgnoreResult(&DismissVirtualKeyboardTask)),
121           TimeDelta::FromMilliseconds(kVirtualKeyboardDisplayWaitTimeoutMs));
122       ++virtual_keyboard_display_retries;
123     } else {
124       virtual_keyboard_display_retries = 0;
125     }
126   }
127 }
128 #endif
129 
130 }  // namespace
131 
132 // static
133 const int RenderViewHostImpl::kUnloadTimeoutMS = 1000;
134 
135 ///////////////////////////////////////////////////////////////////////////////
136 // RenderViewHost, public:
137 
138 // static
IsRVHStateActive(RenderViewHostImplState rvh_state)139 bool RenderViewHostImpl::IsRVHStateActive(RenderViewHostImplState rvh_state) {
140   if (rvh_state == STATE_DEFAULT ||
141       rvh_state == STATE_WAITING_FOR_CLOSE)
142     return true;
143   return false;
144 }
145 
146 // static
FromID(int render_process_id,int render_view_id)147 RenderViewHost* RenderViewHost::FromID(int render_process_id,
148                                        int render_view_id) {
149   return RenderViewHostImpl::FromID(render_process_id, render_view_id);
150 }
151 
152 // static
From(RenderWidgetHost * rwh)153 RenderViewHost* RenderViewHost::From(RenderWidgetHost* rwh) {
154   DCHECK(rwh->IsRenderView());
155   return static_cast<RenderViewHostImpl*>(RenderWidgetHostImpl::From(rwh));
156 }
157 
158 ///////////////////////////////////////////////////////////////////////////////
159 // RenderViewHostImpl, public:
160 
161 // static
FromID(int render_process_id,int render_view_id)162 RenderViewHostImpl* RenderViewHostImpl::FromID(int render_process_id,
163                                                int render_view_id) {
164   RenderWidgetHost* widget =
165       RenderWidgetHost::FromID(render_process_id, render_view_id);
166   if (!widget || !widget->IsRenderView())
167     return NULL;
168   return static_cast<RenderViewHostImpl*>(RenderWidgetHostImpl::From(widget));
169 }
170 
RenderViewHostImpl(SiteInstance * instance,RenderViewHostDelegate * delegate,RenderWidgetHostDelegate * widget_delegate,int routing_id,int main_frame_routing_id,bool swapped_out,bool hidden)171 RenderViewHostImpl::RenderViewHostImpl(
172     SiteInstance* instance,
173     RenderViewHostDelegate* delegate,
174     RenderWidgetHostDelegate* widget_delegate,
175     int routing_id,
176     int main_frame_routing_id,
177     bool swapped_out,
178     bool hidden)
179     : RenderWidgetHostImpl(widget_delegate,
180                            instance->GetProcess(),
181                            routing_id,
182                            hidden),
183       frames_ref_count_(0),
184       delegate_(delegate),
185       instance_(static_cast<SiteInstanceImpl*>(instance)),
186       waiting_for_drag_context_response_(false),
187       enabled_bindings_(0),
188       page_id_(-1),
189       main_frame_routing_id_(main_frame_routing_id),
190       run_modal_reply_msg_(NULL),
191       run_modal_opener_id_(MSG_ROUTING_NONE),
192       is_waiting_for_beforeunload_ack_(false),
193       unload_ack_is_for_cross_site_transition_(false),
194       sudden_termination_allowed_(false),
195       render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING),
196       virtual_keyboard_requested_(false),
197       is_focused_element_editable_(false),
198       updating_web_preferences_(false),
199       weak_factory_(this) {
200   DCHECK(instance_.get());
201   CHECK(delegate_);  // http://crbug.com/82827
202 
203   GetProcess()->EnableSendQueue();
204 
205   if (swapped_out) {
206     rvh_state_ = STATE_SWAPPED_OUT;
207   } else {
208     rvh_state_ = STATE_DEFAULT;
209     instance_->increment_active_view_count();
210   }
211 
212   if (ResourceDispatcherHostImpl::Get()) {
213     BrowserThread::PostTask(
214         BrowserThread::IO, FROM_HERE,
215         base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostCreated,
216                    base::Unretained(ResourceDispatcherHostImpl::Get()),
217                    GetProcess()->GetID(), GetRoutingID(), !is_hidden()));
218   }
219 
220 #if defined(ENABLE_BROWSER_CDMS)
221   media_web_contents_observer_.reset(new MediaWebContentsObserver(this));
222 #endif
223 
224   unload_event_monitor_timeout_.reset(new TimeoutMonitor(base::Bind(
225       &RenderViewHostImpl::OnSwappedOut, weak_factory_.GetWeakPtr(), true)));
226 }
227 
~RenderViewHostImpl()228 RenderViewHostImpl::~RenderViewHostImpl() {
229   if (ResourceDispatcherHostImpl::Get()) {
230     BrowserThread::PostTask(
231         BrowserThread::IO, FROM_HERE,
232         base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostDeleted,
233                    base::Unretained(ResourceDispatcherHostImpl::Get()),
234                    GetProcess()->GetID(), GetRoutingID()));
235   }
236 
237   delegate_->RenderViewDeleted(this);
238 
239   // If this was swapped out, it already decremented the active view
240   // count of the SiteInstance it belongs to.
241   if (IsRVHStateActive(rvh_state_))
242     instance_->decrement_active_view_count();
243 }
244 
GetDelegate() const245 RenderViewHostDelegate* RenderViewHostImpl::GetDelegate() const {
246   return delegate_;
247 }
248 
GetSiteInstance() const249 SiteInstance* RenderViewHostImpl::GetSiteInstance() const {
250   return instance_.get();
251 }
252 
CreateRenderView(const base::string16 & frame_name,int opener_route_id,int proxy_route_id,int32 max_page_id,bool window_was_created_with_opener)253 bool RenderViewHostImpl::CreateRenderView(
254     const base::string16& frame_name,
255     int opener_route_id,
256     int proxy_route_id,
257     int32 max_page_id,
258     bool window_was_created_with_opener) {
259   TRACE_EVENT0("renderer_host,navigation",
260                "RenderViewHostImpl::CreateRenderView");
261   DCHECK(!IsRenderViewLive()) << "Creating view twice";
262 
263   // The process may (if we're sharing a process with another host that already
264   // initialized it) or may not (we have our own process or the old process
265   // crashed) have been initialized. Calling Init multiple times will be
266   // ignored, so this is safe.
267   if (!GetProcess()->Init())
268     return false;
269   DCHECK(GetProcess()->HasConnection());
270   DCHECK(GetProcess()->GetBrowserContext());
271 
272   renderer_initialized_ = true;
273 
274   GpuSurfaceTracker::Get()->SetSurfaceHandle(
275       surface_id(), GetCompositingSurface());
276 
277   // Ensure the RenderView starts with a next_page_id larger than any existing
278   // page ID it might be asked to render.
279   int32 next_page_id = 1;
280   if (max_page_id > -1)
281     next_page_id = max_page_id + 1;
282 
283   ViewMsg_New_Params params;
284   params.renderer_preferences =
285       delegate_->GetRendererPrefs(GetProcess()->GetBrowserContext());
286   params.web_preferences = GetWebkitPreferences();
287   params.view_id = GetRoutingID();
288   params.main_frame_routing_id = main_frame_routing_id_;
289   params.surface_id = surface_id();
290   params.session_storage_namespace_id =
291       delegate_->GetSessionStorageNamespace(instance_.get())->id();
292   params.frame_name = frame_name;
293   // Ensure the RenderView sets its opener correctly.
294   params.opener_route_id = opener_route_id;
295   params.swapped_out = !IsRVHStateActive(rvh_state_);
296   params.proxy_routing_id = proxy_route_id;
297   params.hidden = is_hidden();
298   params.never_visible = delegate_->IsNeverVisible();
299   params.window_was_created_with_opener = window_was_created_with_opener;
300   params.next_page_id = next_page_id;
301   params.enable_auto_resize = auto_resize_enabled();
302   params.min_size = min_size_for_auto_resize();
303   params.max_size = max_size_for_auto_resize();
304   GetResizeParams(&params.initial_size);
305 
306   if (!Send(new ViewMsg_New(params)))
307     return false;
308   SetInitialRenderSizeParams(params.initial_size);
309 
310   // If it's enabled, tell the renderer to set up the Javascript bindings for
311   // sending messages back to the browser.
312   if (GetProcess()->IsIsolatedGuest())
313     DCHECK_EQ(0, enabled_bindings_);
314   Send(new ViewMsg_AllowBindings(GetRoutingID(), enabled_bindings_));
315   // Let our delegate know that we created a RenderView.
316   delegate_->RenderViewCreated(this);
317 
318   return true;
319 }
320 
IsRenderViewLive() const321 bool RenderViewHostImpl::IsRenderViewLive() const {
322   return GetProcess()->HasConnection() && renderer_initialized_;
323 }
324 
SyncRendererPrefs()325 void RenderViewHostImpl::SyncRendererPrefs() {
326   Send(new ViewMsg_SetRendererPrefs(GetRoutingID(),
327                                     delegate_->GetRendererPrefs(
328                                         GetProcess()->GetBrowserContext())));
329 }
330 
ComputeWebkitPrefs(const GURL & url)331 WebPreferences RenderViewHostImpl::ComputeWebkitPrefs(const GURL& url) {
332   TRACE_EVENT0("browser", "RenderViewHostImpl::GetWebkitPrefs");
333   WebPreferences prefs;
334 
335   const base::CommandLine& command_line =
336       *base::CommandLine::ForCurrentProcess();
337 
338   prefs.javascript_enabled =
339       !command_line.HasSwitch(switches::kDisableJavaScript);
340   prefs.web_security_enabled =
341       !command_line.HasSwitch(switches::kDisableWebSecurity);
342   prefs.plugins_enabled =
343       !command_line.HasSwitch(switches::kDisablePlugins);
344   prefs.java_enabled =
345       !command_line.HasSwitch(switches::kDisableJava);
346 
347   prefs.remote_fonts_enabled =
348       !command_line.HasSwitch(switches::kDisableRemoteFonts);
349   prefs.xslt_enabled =
350       !command_line.HasSwitch(switches::kDisableXSLT);
351   prefs.xss_auditor_enabled =
352       !command_line.HasSwitch(switches::kDisableXSSAuditor);
353   prefs.application_cache_enabled =
354       !command_line.HasSwitch(switches::kDisableApplicationCache);
355 
356   prefs.local_storage_enabled =
357       !command_line.HasSwitch(switches::kDisableLocalStorage);
358   prefs.databases_enabled =
359       !command_line.HasSwitch(switches::kDisableDatabases);
360 #if defined(OS_ANDROID)
361   // WebAudio is enabled by default on x86 and ARM.
362   prefs.webaudio_enabled =
363       !command_line.HasSwitch(switches::kDisableWebAudio);
364 #endif
365 
366   prefs.experimental_webgl_enabled =
367       GpuProcessHost::gpu_enabled() &&
368       !command_line.HasSwitch(switches::kDisable3DAPIs) &&
369       !command_line.HasSwitch(switches::kDisableExperimentalWebGL);
370 
371   prefs.pepper_3d_enabled =
372       !command_line.HasSwitch(switches::kDisablePepper3d);
373 
374   prefs.flash_3d_enabled =
375       GpuProcessHost::gpu_enabled() &&
376       !command_line.HasSwitch(switches::kDisableFlash3d);
377   prefs.flash_stage3d_enabled =
378       GpuProcessHost::gpu_enabled() &&
379       !command_line.HasSwitch(switches::kDisableFlashStage3d);
380   prefs.flash_stage3d_baseline_enabled =
381       GpuProcessHost::gpu_enabled() &&
382       !command_line.HasSwitch(switches::kDisableFlashStage3d);
383 
384   prefs.allow_file_access_from_file_urls =
385       command_line.HasSwitch(switches::kAllowFileAccessFromFiles);
386 
387   prefs.layer_squashing_enabled = true;
388   if (command_line.HasSwitch(switches::kEnableLayerSquashing))
389       prefs.layer_squashing_enabled = true;
390   if (command_line.HasSwitch(switches::kDisableLayerSquashing))
391       prefs.layer_squashing_enabled = false;
392 
393   prefs.accelerated_2d_canvas_enabled =
394       GpuProcessHost::gpu_enabled() &&
395       !command_line.HasSwitch(switches::kDisableAccelerated2dCanvas);
396   prefs.antialiased_2d_canvas_disabled =
397       command_line.HasSwitch(switches::kDisable2dCanvasAntialiasing);
398   prefs.accelerated_2d_canvas_msaa_sample_count =
399       atoi(command_line.GetSwitchValueASCII(
400       switches::kAcceleratedCanvas2dMSAASampleCount).c_str());
401   prefs.deferred_filters_enabled =
402       !command_line.HasSwitch(switches::kDisableDeferredFilters);
403   prefs.container_culling_enabled =
404       command_line.HasSwitch(switches::kEnableContainerCulling);
405   prefs.region_based_columns_enabled =
406       command_line.HasSwitch(switches::kEnableRegionBasedColumns);
407 
408   if (IsPinchVirtualViewportEnabled()) {
409     prefs.pinch_virtual_viewport_enabled = true;
410     prefs.pinch_overlay_scrollbar_thickness = 10;
411   }
412   prefs.use_solid_color_scrollbars = ui::IsOverlayScrollbarEnabled();
413 
414 #if defined(OS_ANDROID)
415   prefs.user_gesture_required_for_media_playback = !command_line.HasSwitch(
416       switches::kDisableGestureRequirementForMediaPlayback);
417 #endif
418 
419   prefs.touch_enabled = ui::AreTouchEventsEnabled();
420   prefs.device_supports_touch = prefs.touch_enabled &&
421       ui::IsTouchDevicePresent();
422 #if defined(OS_ANDROID)
423   prefs.device_supports_mouse = false;
424 #endif
425 
426   prefs.pointer_events_max_touch_points = ui::MaxTouchPoints();
427 
428   prefs.touch_adjustment_enabled =
429       !command_line.HasSwitch(switches::kDisableTouchAdjustment);
430 
431 #if defined(OS_MACOSX) || defined(OS_CHROMEOS)
432   bool default_enable_scroll_animator = true;
433 #else
434   bool default_enable_scroll_animator = false;
435 #endif
436   prefs.enable_scroll_animator = default_enable_scroll_animator;
437   if (command_line.HasSwitch(switches::kEnableSmoothScrolling))
438     prefs.enable_scroll_animator = true;
439   if (command_line.HasSwitch(switches::kDisableSmoothScrolling))
440     prefs.enable_scroll_animator = false;
441 
442   // Certain GPU features might have been blacklisted.
443   GpuDataManagerImpl::GetInstance()->UpdateRendererWebPrefs(&prefs);
444 
445   if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
446           GetProcess()->GetID())) {
447     prefs.loads_images_automatically = true;
448     prefs.javascript_enabled = true;
449   }
450 
451   prefs.connection_type = net::NetworkChangeNotifier::GetConnectionType();
452   prefs.is_online =
453       prefs.connection_type != net::NetworkChangeNotifier::CONNECTION_NONE;
454 
455   prefs.number_of_cpu_cores = base::SysInfo::NumberOfProcessors();
456 
457   prefs.viewport_meta_enabled =
458       command_line.HasSwitch(switches::kEnableViewportMeta);
459 
460   prefs.viewport_enabled =
461       command_line.HasSwitch(switches::kEnableViewport) ||
462       prefs.viewport_meta_enabled;
463 
464   prefs.main_frame_resizes_are_orientation_changes =
465       command_line.HasSwitch(switches::kMainFrameResizesAreOrientationChanges);
466 
467   prefs.deferred_image_decoding_enabled =
468       command_line.HasSwitch(switches::kEnableDeferredImageDecoding) ||
469       content::IsImplSidePaintingEnabled();
470 
471   prefs.spatial_navigation_enabled = command_line.HasSwitch(
472       switches::kEnableSpatialNavigation);
473 
474   if (command_line.HasSwitch(switches::kV8CacheOptions)) {
475     const std::string v8_cache_options =
476         command_line.GetSwitchValueASCII(switches::kV8CacheOptions);
477     if (v8_cache_options == "parse") {
478       prefs.v8_cache_options = V8_CACHE_OPTIONS_PARSE;
479     } else if (v8_cache_options == "code") {
480       prefs.v8_cache_options = V8_CACHE_OPTIONS_CODE;
481     } else {
482       prefs.v8_cache_options = V8_CACHE_OPTIONS_OFF;
483     }
484   }
485 
486   prefs.v8_script_streaming_enabled =
487       command_line.HasSwitch(switches::kEnableV8ScriptStreaming) ||
488       base::FieldTrialList::FindFullName("V8ScriptStreaming") == "Enabled";
489 
490   GetContentClient()->browser()->OverrideWebkitPrefs(this, url, &prefs);
491   return prefs;
492 }
493 
SuppressDialogsUntilSwapOut()494 void RenderViewHostImpl::SuppressDialogsUntilSwapOut() {
495   Send(new ViewMsg_SuppressDialogsUntilSwapOut(GetRoutingID()));
496 }
497 
OnSwappedOut(bool timed_out)498 void RenderViewHostImpl::OnSwappedOut(bool timed_out) {
499   // Ignore spurious swap out ack.
500   if (!IsWaitingForUnloadACK())
501     return;
502 
503   TRACE_EVENT0("navigation", "RenderViewHostImpl::OnSwappedOut");
504   unload_event_monitor_timeout_->Stop();
505   if (timed_out) {
506     base::ProcessHandle process_handle = GetProcess()->GetHandle();
507     int views = 0;
508 
509     // Count the number of active widget hosts for the process, which
510     // is equivalent to views using the process as of this writing.
511     scoped_ptr<RenderWidgetHostIterator> widgets(
512       RenderWidgetHost::GetRenderWidgetHosts());
513     while (RenderWidgetHost* widget = widgets->GetNextHost()) {
514       if (widget->GetProcess()->GetID() == GetProcess()->GetID())
515         ++views;
516     }
517 
518     if (!RenderProcessHost::run_renderer_in_process() &&
519         process_handle && views <= 1) {
520       // The process can safely be terminated, only if WebContents sets
521       // SuddenTerminationAllowed, which indicates that the timer has expired.
522       // This is not the case if we load data URLs or about:blank. The reason
523       // is that those have no network requests and this code is hit without
524       // setting the unresponsiveness timer. This allows a corner case where a
525       // navigation to a data URL will leave a process running, if the
526       // beforeunload handler completes fine, but the unload handler hangs.
527       // At this time, the complexity to solve this edge case is not worthwhile.
528       if (SuddenTerminationAllowed()) {
529         // We should kill the process, but for now, just log the data so we can
530         // diagnose the kill rate and investigate if separate timer is needed.
531         // http://crbug.com/104346.
532 
533         // Log a histogram point to help us diagnose how many of those kills
534         // we have performed. 1 is the enum value for RendererType Normal for
535         // the histogram.
536         UMA_HISTOGRAM_PERCENTAGE(
537             "BrowserRenderProcessHost.ChildKillsUnresponsive", 1);
538       }
539     }
540     // This is going to be incorrect for subframes and will only hit if
541     // --site-per-process is specified.
542     TRACE_EVENT_ASYNC_END0("navigation", "RenderFrameHostImpl::SwapOut", this);
543   }
544 
545   switch (rvh_state_) {
546     case STATE_PENDING_SWAP_OUT:
547       SetState(STATE_SWAPPED_OUT);
548       break;
549     case STATE_PENDING_SHUTDOWN:
550       DCHECK(!pending_shutdown_on_swap_out_.is_null());
551       pending_shutdown_on_swap_out_.Run();
552       break;
553     default:
554       NOTREACHED();
555   }
556 }
557 
SetPendingShutdown(const base::Closure & on_swap_out)558 void RenderViewHostImpl::SetPendingShutdown(const base::Closure& on_swap_out) {
559   pending_shutdown_on_swap_out_ = on_swap_out;
560   SetState(STATE_PENDING_SHUTDOWN);
561 }
562 
ClosePage()563 void RenderViewHostImpl::ClosePage() {
564   SetState(STATE_WAITING_FOR_CLOSE);
565   StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
566 
567   if (IsRenderViewLive()) {
568     // Since we are sending an IPC message to the renderer, increase the event
569     // count to prevent the hang monitor timeout from being stopped by input
570     // event acknowledgements.
571     increment_in_flight_event_count();
572 
573     // TODO(creis): Should this be moved to Shutdown?  It may not be called for
574     // RenderViewHosts that have been swapped out.
575     NotificationService::current()->Notify(
576         NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW,
577         Source<RenderViewHost>(this),
578         NotificationService::NoDetails());
579 
580     Send(new ViewMsg_ClosePage(GetRoutingID()));
581   } else {
582     // This RenderViewHost doesn't have a live renderer, so just skip the unload
583     // event and close the page.
584     ClosePageIgnoringUnloadEvents();
585   }
586 }
587 
ClosePageIgnoringUnloadEvents()588 void RenderViewHostImpl::ClosePageIgnoringUnloadEvents() {
589   StopHangMonitorTimeout();
590   is_waiting_for_beforeunload_ack_ = false;
591 
592   sudden_termination_allowed_ = true;
593   delegate_->Close(this);
594 }
595 
596 #if defined(OS_ANDROID)
ActivateNearestFindResult(int request_id,float x,float y)597 void RenderViewHostImpl::ActivateNearestFindResult(int request_id,
598                                                    float x,
599                                                    float y) {
600   Send(new InputMsg_ActivateNearestFindResult(GetRoutingID(),
601                                               request_id, x, y));
602 }
603 
RequestFindMatchRects(int current_version)604 void RenderViewHostImpl::RequestFindMatchRects(int current_version) {
605   Send(new ViewMsg_FindMatchRects(GetRoutingID(), current_version));
606 }
607 #endif
608 
DragTargetDragEnter(const DropData & drop_data,const gfx::Point & client_pt,const gfx::Point & screen_pt,WebDragOperationsMask operations_allowed,int key_modifiers)609 void RenderViewHostImpl::DragTargetDragEnter(
610     const DropData& drop_data,
611     const gfx::Point& client_pt,
612     const gfx::Point& screen_pt,
613     WebDragOperationsMask operations_allowed,
614     int key_modifiers) {
615   const int renderer_id = GetProcess()->GetID();
616   ChildProcessSecurityPolicyImpl* policy =
617       ChildProcessSecurityPolicyImpl::GetInstance();
618 
619   // The URL could have been cobbled together from any highlighted text string,
620   // and can't be interpreted as a capability.
621   DropData filtered_data(drop_data);
622   GetProcess()->FilterURL(true, &filtered_data.url);
623   if (drop_data.did_originate_from_renderer) {
624     filtered_data.filenames.clear();
625   }
626 
627   // The filenames vector, on the other hand, does represent a capability to
628   // access the given files.
629   storage::IsolatedContext::FileInfoSet files;
630   for (std::vector<ui::FileInfo>::iterator iter(
631            filtered_data.filenames.begin());
632        iter != filtered_data.filenames.end();
633        ++iter) {
634     // A dragged file may wind up as the value of an input element, or it
635     // may be used as the target of a navigation instead.  We don't know
636     // which will happen at this point, so generously grant both access
637     // and request permissions to the specific file to cover both cases.
638     // We do not give it the permission to request all file:// URLs.
639 
640     // Make sure we have the same display_name as the one we register.
641     if (iter->display_name.empty()) {
642       std::string name;
643       files.AddPath(iter->path, &name);
644       iter->display_name = base::FilePath::FromUTF8Unsafe(name);
645     } else {
646       files.AddPathWithName(iter->path, iter->display_name.AsUTF8Unsafe());
647     }
648 
649     policy->GrantRequestSpecificFileURL(renderer_id,
650                                         net::FilePathToFileURL(iter->path));
651 
652     // If the renderer already has permission to read these paths, we don't need
653     // to re-grant them. This prevents problems with DnD for files in the CrOS
654     // file manager--the file manager already had read/write access to those
655     // directories, but dragging a file would cause the read/write access to be
656     // overwritten with read-only access, making them impossible to delete or
657     // rename until the renderer was killed.
658     if (!policy->CanReadFile(renderer_id, iter->path))
659       policy->GrantReadFile(renderer_id, iter->path);
660   }
661 
662   storage::IsolatedContext* isolated_context =
663       storage::IsolatedContext::GetInstance();
664   DCHECK(isolated_context);
665   std::string filesystem_id = isolated_context->RegisterDraggedFileSystem(
666       files);
667   if (!filesystem_id.empty()) {
668     // Grant the permission iff the ID is valid.
669     policy->GrantReadFileSystem(renderer_id, filesystem_id);
670   }
671   filtered_data.filesystem_id = base::UTF8ToUTF16(filesystem_id);
672 
673   storage::FileSystemContext* file_system_context =
674       BrowserContext::GetStoragePartition(GetProcess()->GetBrowserContext(),
675                                           GetSiteInstance())
676           ->GetFileSystemContext();
677   for (size_t i = 0; i < filtered_data.file_system_files.size(); ++i) {
678     storage::FileSystemURL file_system_url =
679         file_system_context->CrackURL(filtered_data.file_system_files[i].url);
680 
681     std::string register_name;
682     std::string filesystem_id = isolated_context->RegisterFileSystemForPath(
683         file_system_url.type(), file_system_url.filesystem_id(),
684         file_system_url.path(), &register_name);
685     policy->GrantReadFileSystem(renderer_id, filesystem_id);
686 
687     // Note: We are using the origin URL provided by the sender here. It may be
688     // different from the receiver's.
689     filtered_data.file_system_files[i].url =
690         GURL(storage::GetIsolatedFileSystemRootURIString(
691                  file_system_url.origin(), filesystem_id, std::string())
692                  .append(register_name));
693   }
694 
695   Send(new DragMsg_TargetDragEnter(GetRoutingID(), filtered_data, client_pt,
696                                    screen_pt, operations_allowed,
697                                    key_modifiers));
698 }
699 
DragTargetDragOver(const gfx::Point & client_pt,const gfx::Point & screen_pt,WebDragOperationsMask operations_allowed,int key_modifiers)700 void RenderViewHostImpl::DragTargetDragOver(
701     const gfx::Point& client_pt,
702     const gfx::Point& screen_pt,
703     WebDragOperationsMask operations_allowed,
704     int key_modifiers) {
705   Send(new DragMsg_TargetDragOver(GetRoutingID(), client_pt, screen_pt,
706                                   operations_allowed, key_modifiers));
707 }
708 
DragTargetDragLeave()709 void RenderViewHostImpl::DragTargetDragLeave() {
710   Send(new DragMsg_TargetDragLeave(GetRoutingID()));
711 }
712 
DragTargetDrop(const gfx::Point & client_pt,const gfx::Point & screen_pt,int key_modifiers)713 void RenderViewHostImpl::DragTargetDrop(
714     const gfx::Point& client_pt,
715     const gfx::Point& screen_pt,
716     int key_modifiers) {
717   Send(new DragMsg_TargetDrop(GetRoutingID(), client_pt, screen_pt,
718                               key_modifiers));
719 }
720 
DragSourceEndedAt(int client_x,int client_y,int screen_x,int screen_y,WebDragOperation operation)721 void RenderViewHostImpl::DragSourceEndedAt(
722     int client_x, int client_y, int screen_x, int screen_y,
723     WebDragOperation operation) {
724   Send(new DragMsg_SourceEnded(GetRoutingID(),
725                                gfx::Point(client_x, client_y),
726                                gfx::Point(screen_x, screen_y),
727                                operation));
728 }
729 
DragSourceSystemDragEnded()730 void RenderViewHostImpl::DragSourceSystemDragEnded() {
731   Send(new DragMsg_SourceSystemDragEnded(GetRoutingID()));
732 }
733 
GetMainFrame()734 RenderFrameHost* RenderViewHostImpl::GetMainFrame() {
735   return RenderFrameHost::FromID(GetProcess()->GetID(), main_frame_routing_id_);
736 }
737 
AllowBindings(int bindings_flags)738 void RenderViewHostImpl::AllowBindings(int bindings_flags) {
739   // Never grant any bindings to browser plugin guests.
740   if (GetProcess()->IsIsolatedGuest()) {
741     NOTREACHED() << "Never grant bindings to a guest process.";
742     return;
743   }
744 
745   // Ensure we aren't granting WebUI bindings to a process that has already
746   // been used for non-privileged views.
747   if (bindings_flags & BINDINGS_POLICY_WEB_UI &&
748       GetProcess()->HasConnection() &&
749       !ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
750           GetProcess()->GetID())) {
751     // This process has no bindings yet. Make sure it does not have more
752     // than this single active view.
753     RenderProcessHostImpl* process =
754         static_cast<RenderProcessHostImpl*>(GetProcess());
755     // --single-process only has one renderer.
756     if (process->GetActiveViewCount() > 1 &&
757         !base::CommandLine::ForCurrentProcess()->HasSwitch(
758             switches::kSingleProcess))
759       return;
760   }
761 
762   if (bindings_flags & BINDINGS_POLICY_WEB_UI) {
763     ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
764         GetProcess()->GetID());
765   }
766 
767   enabled_bindings_ |= bindings_flags;
768   if (renderer_initialized_)
769     Send(new ViewMsg_AllowBindings(GetRoutingID(), enabled_bindings_));
770 }
771 
GetEnabledBindings() const772 int RenderViewHostImpl::GetEnabledBindings() const {
773   return enabled_bindings_;
774 }
775 
SetWebUIProperty(const std::string & name,const std::string & value)776 void RenderViewHostImpl::SetWebUIProperty(const std::string& name,
777                                           const std::string& value) {
778   // This is a sanity check before telling the renderer to enable the property.
779   // It could lie and send the corresponding IPC messages anyway, but we will
780   // not act on them if enabled_bindings_ doesn't agree. If we get here without
781   // WebUI bindings, kill the renderer process.
782   if (enabled_bindings_ & BINDINGS_POLICY_WEB_UI) {
783     Send(new ViewMsg_SetWebUIProperty(GetRoutingID(), name, value));
784   } else {
785     RecordAction(
786         base::UserMetricsAction("BindingsMismatchTerminate_RVH_WebUI"));
787     base::KillProcess(
788         GetProcess()->GetHandle(), content::RESULT_CODE_KILLED, false);
789   }
790 }
791 
GotFocus()792 void RenderViewHostImpl::GotFocus() {
793   RenderWidgetHostImpl::GotFocus();  // Notifies the renderer it got focus.
794 
795   RenderViewHostDelegateView* view = delegate_->GetDelegateView();
796   if (view)
797     view->GotFocus();
798 }
799 
LostCapture()800 void RenderViewHostImpl::LostCapture() {
801   RenderWidgetHostImpl::LostCapture();
802   delegate_->LostCapture();
803 }
804 
LostMouseLock()805 void RenderViewHostImpl::LostMouseLock() {
806   RenderWidgetHostImpl::LostMouseLock();
807   delegate_->LostMouseLock();
808 }
809 
SetInitialFocus(bool reverse)810 void RenderViewHostImpl::SetInitialFocus(bool reverse) {
811   Send(new ViewMsg_SetInitialFocus(GetRoutingID(), reverse));
812 }
813 
FilesSelectedInChooser(const std::vector<ui::SelectedFileInfo> & files,FileChooserParams::Mode permissions)814 void RenderViewHostImpl::FilesSelectedInChooser(
815     const std::vector<ui::SelectedFileInfo>& files,
816     FileChooserParams::Mode permissions) {
817   // Grant the security access requested to the given files.
818   for (size_t i = 0; i < files.size(); ++i) {
819     const ui::SelectedFileInfo& file = files[i];
820     if (permissions == FileChooserParams::Save) {
821       ChildProcessSecurityPolicyImpl::GetInstance()->GrantCreateReadWriteFile(
822           GetProcess()->GetID(), file.local_path);
823     } else {
824       ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
825           GetProcess()->GetID(), file.local_path);
826     }
827   }
828   Send(new ViewMsg_RunFileChooserResponse(GetRoutingID(), files));
829 }
830 
DirectoryEnumerationFinished(int request_id,const std::vector<base::FilePath> & files)831 void RenderViewHostImpl::DirectoryEnumerationFinished(
832     int request_id,
833     const std::vector<base::FilePath>& files) {
834   // Grant the security access requested to the given files.
835   for (std::vector<base::FilePath>::const_iterator file = files.begin();
836        file != files.end(); ++file) {
837     ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
838         GetProcess()->GetID(), *file);
839   }
840   Send(new ViewMsg_EnumerateDirectoryResponse(GetRoutingID(),
841                                               request_id,
842                                               files));
843 }
844 
SetIsLoading(bool is_loading)845 void RenderViewHostImpl::SetIsLoading(bool is_loading) {
846   if (ResourceDispatcherHostImpl::Get()) {
847     BrowserThread::PostTask(
848         BrowserThread::IO,
849         FROM_HERE,
850         base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostSetIsLoading,
851                    base::Unretained(ResourceDispatcherHostImpl::Get()),
852                    GetProcess()->GetID(),
853                    GetRoutingID(),
854                    is_loading));
855   }
856   RenderWidgetHostImpl::SetIsLoading(is_loading);
857 }
858 
LoadStateChanged(const GURL & url,const net::LoadStateWithParam & load_state,uint64 upload_position,uint64 upload_size)859 void RenderViewHostImpl::LoadStateChanged(
860     const GURL& url,
861     const net::LoadStateWithParam& load_state,
862     uint64 upload_position,
863     uint64 upload_size) {
864   delegate_->LoadStateChanged(url, load_state, upload_position, upload_size);
865 }
866 
SuddenTerminationAllowed() const867 bool RenderViewHostImpl::SuddenTerminationAllowed() const {
868   return sudden_termination_allowed_ ||
869       GetProcess()->SuddenTerminationAllowed();
870 }
871 
872 ///////////////////////////////////////////////////////////////////////////////
873 // RenderViewHostImpl, IPC message handlers:
874 
OnMessageReceived(const IPC::Message & msg)875 bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
876   if (!BrowserMessageFilter::CheckCanDispatchOnUI(msg, this))
877     return true;
878 
879   // Filter out most IPC messages if this renderer is swapped out.
880   // We still want to handle certain ACKs to keep our state consistent.
881   if (IsSwappedOut()) {
882     if (!SwappedOutMessages::CanHandleWhileSwappedOut(msg)) {
883       // If this is a synchronous message and we decided not to handle it,
884       // we must send an error reply, or else the renderer will be stuck
885       // and won't respond to future requests.
886       if (msg.is_sync()) {
887         IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
888         reply->set_reply_error();
889         Send(reply);
890       }
891       // Don't continue looking for someone to handle it.
892       return true;
893     }
894   }
895 
896   if (delegate_->OnMessageReceived(this, msg))
897     return true;
898 
899   bool handled = true;
900   IPC_BEGIN_MESSAGE_MAP(RenderViewHostImpl, msg)
901     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowView, OnShowView)
902     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
903     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowFullscreenWidget,
904                         OnShowFullscreenWidget)
905     IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunModal, OnRunModal)
906     IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnRenderViewReady)
907     IPC_MESSAGE_HANDLER(ViewHostMsg_RenderProcessGone, OnRenderProcessGone)
908     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateState, OnUpdateState)
909     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTargetURL, OnUpdateTargetURL)
910     IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
911     IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnRequestMove)
912     IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentAvailableInMainFrame,
913                         OnDocumentAvailableInMainFrame)
914     IPC_MESSAGE_HANDLER(ViewHostMsg_ToggleFullscreen, OnToggleFullscreen)
915     IPC_MESSAGE_HANDLER(ViewHostMsg_DidContentsPreferredSizeChange,
916                         OnDidContentsPreferredSizeChange)
917     IPC_MESSAGE_HANDLER(ViewHostMsg_RouteCloseEvent,
918                         OnRouteCloseEvent)
919     IPC_MESSAGE_HANDLER(ViewHostMsg_RouteMessageEvent, OnRouteMessageEvent)
920     IPC_MESSAGE_HANDLER(DragHostMsg_StartDragging, OnStartDragging)
921     IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor, OnUpdateDragCursor)
922     IPC_MESSAGE_HANDLER(DragHostMsg_TargetDrop_ACK, OnTargetDropACK)
923     IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
924     IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeChanged, OnFocusedNodeChanged)
925     IPC_MESSAGE_HANDLER(ViewHostMsg_ClosePage_ACK, OnClosePageACK)
926     IPC_MESSAGE_HANDLER(ViewHostMsg_DidZoomURL, OnDidZoomURL)
927     IPC_MESSAGE_HANDLER(ViewHostMsg_RunFileChooser, OnRunFileChooser)
928     IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeTouched, OnFocusedNodeTouched)
929     // Have the super handle all other messages.
930     IPC_MESSAGE_UNHANDLED(
931         handled = RenderWidgetHostImpl::OnMessageReceived(msg))
932   IPC_END_MESSAGE_MAP()
933 
934   return handled;
935 }
936 
Init()937 void RenderViewHostImpl::Init() {
938   RenderWidgetHostImpl::Init();
939 }
940 
Shutdown()941 void RenderViewHostImpl::Shutdown() {
942   // If we are being run modally (see RunModal), then we need to cleanup.
943   if (run_modal_reply_msg_) {
944     Send(run_modal_reply_msg_);
945     run_modal_reply_msg_ = NULL;
946     RenderViewHostImpl* opener =
947         RenderViewHostImpl::FromID(GetProcess()->GetID(), run_modal_opener_id_);
948     if (opener) {
949       opener->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(
950           hung_renderer_delay_ms_));
951       // Balance out the decrement when we got created.
952       opener->increment_in_flight_event_count();
953     }
954     run_modal_opener_id_ = MSG_ROUTING_NONE;
955   }
956 
957   // We can't release the SessionStorageNamespace until our peer
958   // in the renderer has wound down.
959   if (GetProcess()->HasConnection()) {
960     RenderProcessHostImpl::ReleaseOnCloseACK(
961         GetProcess(),
962         delegate_->GetSessionStorageNamespaceMap(),
963         GetRoutingID());
964   }
965 
966   RenderWidgetHostImpl::Shutdown();
967 }
968 
WasHidden()969 void RenderViewHostImpl::WasHidden() {
970   if (ResourceDispatcherHostImpl::Get()) {
971     BrowserThread::PostTask(
972         BrowserThread::IO, FROM_HERE,
973         base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostWasHidden,
974                    base::Unretained(ResourceDispatcherHostImpl::Get()),
975                    GetProcess()->GetID(), GetRoutingID()));
976   }
977 
978   RenderWidgetHostImpl::WasHidden();
979 }
980 
WasShown(const ui::LatencyInfo & latency_info)981 void RenderViewHostImpl::WasShown(const ui::LatencyInfo& latency_info) {
982   if (ResourceDispatcherHostImpl::Get()) {
983     BrowserThread::PostTask(
984         BrowserThread::IO, FROM_HERE,
985         base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostWasShown,
986                    base::Unretained(ResourceDispatcherHostImpl::Get()),
987                    GetProcess()->GetID(), GetRoutingID()));
988   }
989 
990   RenderWidgetHostImpl::WasShown(latency_info);
991 }
992 
IsRenderView() const993 bool RenderViewHostImpl::IsRenderView() const {
994   return true;
995 }
996 
CreateNewWindow(int route_id,int main_frame_route_id,const ViewHostMsg_CreateWindow_Params & params,SessionStorageNamespace * session_storage_namespace)997 void RenderViewHostImpl::CreateNewWindow(
998     int route_id,
999     int main_frame_route_id,
1000     const ViewHostMsg_CreateWindow_Params& params,
1001     SessionStorageNamespace* session_storage_namespace) {
1002   ViewHostMsg_CreateWindow_Params validated_params(params);
1003   GetProcess()->FilterURL(false, &validated_params.target_url);
1004   GetProcess()->FilterURL(false, &validated_params.opener_url);
1005   GetProcess()->FilterURL(true, &validated_params.opener_security_origin);
1006 
1007   delegate_->CreateNewWindow(
1008       GetProcess()->GetID(), route_id, main_frame_route_id, validated_params,
1009       session_storage_namespace);
1010 }
1011 
CreateNewWidget(int route_id,blink::WebPopupType popup_type)1012 void RenderViewHostImpl::CreateNewWidget(int route_id,
1013                                      blink::WebPopupType popup_type) {
1014   delegate_->CreateNewWidget(GetProcess()->GetID(), route_id, popup_type);
1015 }
1016 
CreateNewFullscreenWidget(int route_id)1017 void RenderViewHostImpl::CreateNewFullscreenWidget(int route_id) {
1018   delegate_->CreateNewFullscreenWidget(GetProcess()->GetID(), route_id);
1019 }
1020 
OnShowView(int route_id,WindowOpenDisposition disposition,const gfx::Rect & initial_pos,bool user_gesture)1021 void RenderViewHostImpl::OnShowView(int route_id,
1022                                     WindowOpenDisposition disposition,
1023                                     const gfx::Rect& initial_pos,
1024                                     bool user_gesture) {
1025   if (IsRVHStateActive(rvh_state_)) {
1026     delegate_->ShowCreatedWindow(
1027         route_id, disposition, initial_pos, user_gesture);
1028   }
1029   Send(new ViewMsg_Move_ACK(route_id));
1030 }
1031 
OnShowWidget(int route_id,const gfx::Rect & initial_pos)1032 void RenderViewHostImpl::OnShowWidget(int route_id,
1033                                       const gfx::Rect& initial_pos) {
1034   if (IsRVHStateActive(rvh_state_))
1035     delegate_->ShowCreatedWidget(route_id, initial_pos);
1036   Send(new ViewMsg_Move_ACK(route_id));
1037 }
1038 
OnShowFullscreenWidget(int route_id)1039 void RenderViewHostImpl::OnShowFullscreenWidget(int route_id) {
1040   if (IsRVHStateActive(rvh_state_))
1041     delegate_->ShowCreatedFullscreenWidget(route_id);
1042   Send(new ViewMsg_Move_ACK(route_id));
1043 }
1044 
OnRunModal(int opener_id,IPC::Message * reply_msg)1045 void RenderViewHostImpl::OnRunModal(int opener_id, IPC::Message* reply_msg) {
1046   DCHECK(!run_modal_reply_msg_);
1047   run_modal_reply_msg_ = reply_msg;
1048   run_modal_opener_id_ = opener_id;
1049 
1050   RecordAction(base::UserMetricsAction("ShowModalDialog"));
1051 
1052   RenderViewHostImpl* opener =
1053       RenderViewHostImpl::FromID(GetProcess()->GetID(), run_modal_opener_id_);
1054   if (opener) {
1055     opener->StopHangMonitorTimeout();
1056     // The ack for the mouse down won't come until the dialog closes, so fake it
1057     // so that we don't get a timeout.
1058     opener->decrement_in_flight_event_count();
1059   }
1060 
1061   // TODO(darin): Bug 1107929: Need to inform our delegate to show this view in
1062   // an app-modal fashion.
1063 }
1064 
OnRenderViewReady()1065 void RenderViewHostImpl::OnRenderViewReady() {
1066   render_view_termination_status_ = base::TERMINATION_STATUS_STILL_RUNNING;
1067   SendScreenRects();
1068   WasResized();
1069   delegate_->RenderViewReady(this);
1070 }
1071 
OnRenderProcessGone(int status,int exit_code)1072 void RenderViewHostImpl::OnRenderProcessGone(int status, int exit_code) {
1073   // Keep the termination status so we can get at it later when we
1074   // need to know why it died.
1075   render_view_termination_status_ =
1076       static_cast<base::TerminationStatus>(status);
1077 
1078   // Reset frame tree state associated with this process.  This must happen
1079   // before RenderViewTerminated because observers expect the subframes of any
1080   // affected frames to be cleared first.
1081   delegate_->GetFrameTree()->RenderProcessGone(this);
1082 
1083   // Our base class RenderWidgetHost needs to reset some stuff.
1084   RendererExited(render_view_termination_status_, exit_code);
1085 
1086   delegate_->RenderViewTerminated(this,
1087                                   static_cast<base::TerminationStatus>(status),
1088                                   exit_code);
1089 }
1090 
OnUpdateState(int32 page_id,const PageState & state)1091 void RenderViewHostImpl::OnUpdateState(int32 page_id, const PageState& state) {
1092   // Without this check, the renderer can trick the browser into using
1093   // filenames it can't access in a future session restore.
1094   if (!CanAccessFilesOfPageState(state)) {
1095     GetProcess()->ReceivedBadMessage();
1096     return;
1097   }
1098 
1099   delegate_->UpdateState(this, page_id, state);
1100 }
1101 
OnUpdateTargetURL(const GURL & url)1102 void RenderViewHostImpl::OnUpdateTargetURL(const GURL& url) {
1103   if (IsRVHStateActive(rvh_state_))
1104     delegate_->UpdateTargetURL(url);
1105 
1106   // Send a notification back to the renderer that we are ready to
1107   // receive more target urls.
1108   Send(new ViewMsg_UpdateTargetURL_ACK(GetRoutingID()));
1109 }
1110 
OnClose()1111 void RenderViewHostImpl::OnClose() {
1112   // If the renderer is telling us to close, it has already run the unload
1113   // events, and we can take the fast path.
1114   ClosePageIgnoringUnloadEvents();
1115 }
1116 
OnRequestMove(const gfx::Rect & pos)1117 void RenderViewHostImpl::OnRequestMove(const gfx::Rect& pos) {
1118   if (IsRVHStateActive(rvh_state_))
1119     delegate_->RequestMove(pos);
1120   Send(new ViewMsg_Move_ACK(GetRoutingID()));
1121 }
1122 
OnDocumentAvailableInMainFrame(bool uses_temporary_zoom_level)1123 void RenderViewHostImpl::OnDocumentAvailableInMainFrame(
1124     bool uses_temporary_zoom_level) {
1125   delegate_->DocumentAvailableInMainFrame(this);
1126 
1127   if (!uses_temporary_zoom_level)
1128     return;
1129 
1130   HostZoomMapImpl* host_zoom_map =
1131       static_cast<HostZoomMapImpl*>(HostZoomMap::GetDefaultForBrowserContext(
1132           GetProcess()->GetBrowserContext()));
1133   host_zoom_map->SetTemporaryZoomLevel(GetProcess()->GetID(),
1134                                        GetRoutingID(),
1135                                        host_zoom_map->GetDefaultZoomLevel());
1136 }
1137 
OnToggleFullscreen(bool enter_fullscreen)1138 void RenderViewHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
1139   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1140   delegate_->ToggleFullscreenMode(enter_fullscreen);
1141   // We need to notify the contents that its fullscreen state has changed. This
1142   // is done as part of the resize message.
1143   WasResized();
1144 }
1145 
OnDidContentsPreferredSizeChange(const gfx::Size & new_size)1146 void RenderViewHostImpl::OnDidContentsPreferredSizeChange(
1147     const gfx::Size& new_size) {
1148   delegate_->UpdatePreferredSize(new_size);
1149 }
1150 
OnRenderAutoResized(const gfx::Size & new_size)1151 void RenderViewHostImpl::OnRenderAutoResized(const gfx::Size& new_size) {
1152   delegate_->ResizeDueToAutoResize(new_size);
1153 }
1154 
OnRouteCloseEvent()1155 void RenderViewHostImpl::OnRouteCloseEvent() {
1156   // Have the delegate route this to the active RenderViewHost.
1157   delegate_->RouteCloseEvent(this);
1158 }
1159 
OnRouteMessageEvent(const ViewMsg_PostMessage_Params & params)1160 void RenderViewHostImpl::OnRouteMessageEvent(
1161     const ViewMsg_PostMessage_Params& params) {
1162   // Give to the delegate to route to the active RenderViewHost.
1163   delegate_->RouteMessageEvent(this, params);
1164 }
1165 
OnStartDragging(const DropData & drop_data,WebDragOperationsMask drag_operations_mask,const SkBitmap & bitmap,const gfx::Vector2d & bitmap_offset_in_dip,const DragEventSourceInfo & event_info)1166 void RenderViewHostImpl::OnStartDragging(
1167     const DropData& drop_data,
1168     WebDragOperationsMask drag_operations_mask,
1169     const SkBitmap& bitmap,
1170     const gfx::Vector2d& bitmap_offset_in_dip,
1171     const DragEventSourceInfo& event_info) {
1172   RenderViewHostDelegateView* view = delegate_->GetDelegateView();
1173   if (!view)
1174     return;
1175 
1176   DropData filtered_data(drop_data);
1177   RenderProcessHost* process = GetProcess();
1178   ChildProcessSecurityPolicyImpl* policy =
1179       ChildProcessSecurityPolicyImpl::GetInstance();
1180 
1181   // Allow drag of Javascript URLs to enable bookmarklet drag to bookmark bar.
1182   if (!filtered_data.url.SchemeIs(url::kJavaScriptScheme))
1183     process->FilterURL(true, &filtered_data.url);
1184   process->FilterURL(false, &filtered_data.html_base_url);
1185   // Filter out any paths that the renderer didn't have access to. This prevents
1186   // the following attack on a malicious renderer:
1187   // 1. StartDragging IPC sent with renderer-specified filesystem paths that it
1188   //    doesn't have read permissions for.
1189   // 2. We initiate a native DnD operation.
1190   // 3. DnD operation immediately ends since mouse is not held down. DnD events
1191   //    still fire though, which causes read permissions to be granted to the
1192   //    renderer for any file paths in the drop.
1193   filtered_data.filenames.clear();
1194   for (std::vector<ui::FileInfo>::const_iterator it =
1195            drop_data.filenames.begin();
1196        it != drop_data.filenames.end();
1197        ++it) {
1198     if (policy->CanReadFile(GetProcess()->GetID(), it->path))
1199       filtered_data.filenames.push_back(*it);
1200   }
1201 
1202   storage::FileSystemContext* file_system_context =
1203       BrowserContext::GetStoragePartition(GetProcess()->GetBrowserContext(),
1204                                           GetSiteInstance())
1205           ->GetFileSystemContext();
1206   filtered_data.file_system_files.clear();
1207   for (size_t i = 0; i < drop_data.file_system_files.size(); ++i) {
1208     storage::FileSystemURL file_system_url =
1209         file_system_context->CrackURL(drop_data.file_system_files[i].url);
1210     if (policy->CanReadFileSystemFile(GetProcess()->GetID(), file_system_url))
1211       filtered_data.file_system_files.push_back(drop_data.file_system_files[i]);
1212   }
1213 
1214   float scale = GetScaleFactorForView(GetView());
1215   gfx::ImageSkia image(gfx::ImageSkiaRep(bitmap, scale));
1216   view->StartDragging(filtered_data, drag_operations_mask, image,
1217       bitmap_offset_in_dip, event_info);
1218 }
1219 
OnUpdateDragCursor(WebDragOperation current_op)1220 void RenderViewHostImpl::OnUpdateDragCursor(WebDragOperation current_op) {
1221   RenderViewHostDelegateView* view = delegate_->GetDelegateView();
1222   if (view)
1223     view->UpdateDragCursor(current_op);
1224 }
1225 
OnTargetDropACK()1226 void RenderViewHostImpl::OnTargetDropACK() {
1227   NotificationService::current()->Notify(
1228       NOTIFICATION_RENDER_VIEW_HOST_DID_RECEIVE_DRAG_TARGET_DROP_ACK,
1229       Source<RenderViewHost>(this),
1230       NotificationService::NoDetails());
1231 }
1232 
OnTakeFocus(bool reverse)1233 void RenderViewHostImpl::OnTakeFocus(bool reverse) {
1234   RenderViewHostDelegateView* view = delegate_->GetDelegateView();
1235   if (view)
1236     view->TakeFocus(reverse);
1237 }
1238 
OnFocusedNodeChanged(bool is_editable_node)1239 void RenderViewHostImpl::OnFocusedNodeChanged(bool is_editable_node) {
1240   is_focused_element_editable_ = is_editable_node;
1241   if (view_)
1242     view_->FocusedNodeChanged(is_editable_node);
1243 #if defined(OS_WIN)
1244   if (!is_editable_node && virtual_keyboard_requested_) {
1245     virtual_keyboard_requested_ = false;
1246     delegate_->SetIsVirtualKeyboardRequested(false);
1247     BrowserThread::PostDelayedTask(
1248         BrowserThread::UI, FROM_HERE,
1249         base::Bind(base::IgnoreResult(&DismissVirtualKeyboardTask)),
1250         TimeDelta::FromMilliseconds(kVirtualKeyboardDisplayWaitTimeoutMs));
1251   }
1252 #endif
1253   NotificationService::current()->Notify(
1254       NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
1255       Source<RenderViewHost>(this),
1256       Details<const bool>(&is_editable_node));
1257 }
1258 
OnUserGesture()1259 void RenderViewHostImpl::OnUserGesture() {
1260   delegate_->OnUserGesture();
1261 }
1262 
OnClosePageACK()1263 void RenderViewHostImpl::OnClosePageACK() {
1264   decrement_in_flight_event_count();
1265   ClosePageIgnoringUnloadEvents();
1266 }
1267 
NotifyRendererUnresponsive()1268 void RenderViewHostImpl::NotifyRendererUnresponsive() {
1269   delegate_->RendererUnresponsive(
1270       this, is_waiting_for_beforeunload_ack_, IsWaitingForUnloadACK());
1271 }
1272 
NotifyRendererResponsive()1273 void RenderViewHostImpl::NotifyRendererResponsive() {
1274   delegate_->RendererResponsive(this);
1275 }
1276 
RequestToLockMouse(bool user_gesture,bool last_unlocked_by_target)1277 void RenderViewHostImpl::RequestToLockMouse(bool user_gesture,
1278                                             bool last_unlocked_by_target) {
1279   delegate_->RequestToLockMouse(user_gesture, last_unlocked_by_target);
1280 }
1281 
IsFullscreen() const1282 bool RenderViewHostImpl::IsFullscreen() const {
1283   return delegate_->IsFullscreenForCurrentTab();
1284 }
1285 
OnFocus()1286 void RenderViewHostImpl::OnFocus() {
1287   // Note: We allow focus and blur from swapped out RenderViewHosts, even when
1288   // the active RenderViewHost is in a different BrowsingInstance (e.g., WebUI).
1289   delegate_->Activate();
1290 }
1291 
OnBlur()1292 void RenderViewHostImpl::OnBlur() {
1293   delegate_->Deactivate();
1294 }
1295 
GetRootWindowResizerRect() const1296 gfx::Rect RenderViewHostImpl::GetRootWindowResizerRect() const {
1297   return delegate_->GetRootWindowResizerRect();
1298 }
1299 
ForwardMouseEvent(const blink::WebMouseEvent & mouse_event)1300 void RenderViewHostImpl::ForwardMouseEvent(
1301     const blink::WebMouseEvent& mouse_event) {
1302 
1303   // We make a copy of the mouse event because
1304   // RenderWidgetHost::ForwardMouseEvent will delete |mouse_event|.
1305   blink::WebMouseEvent event_copy(mouse_event);
1306   RenderWidgetHostImpl::ForwardMouseEvent(event_copy);
1307 
1308   switch (event_copy.type) {
1309     case WebInputEvent::MouseMove:
1310       delegate_->HandleMouseMove();
1311       break;
1312     case WebInputEvent::MouseLeave:
1313       delegate_->HandleMouseLeave();
1314       break;
1315     case WebInputEvent::MouseDown:
1316       delegate_->HandleMouseDown();
1317       break;
1318     case WebInputEvent::MouseWheel:
1319       if (ignore_input_events())
1320         delegate_->OnIgnoredUIEvent();
1321       break;
1322     case WebInputEvent::MouseUp:
1323       delegate_->HandleMouseUp();
1324     default:
1325       // For now, we don't care about the rest.
1326       break;
1327   }
1328 }
1329 
OnPointerEventActivate()1330 void RenderViewHostImpl::OnPointerEventActivate() {
1331   delegate_->HandlePointerActivate();
1332 }
1333 
ForwardKeyboardEvent(const NativeWebKeyboardEvent & key_event)1334 void RenderViewHostImpl::ForwardKeyboardEvent(
1335     const NativeWebKeyboardEvent& key_event) {
1336   if (ignore_input_events()) {
1337     if (key_event.type == WebInputEvent::RawKeyDown)
1338       delegate_->OnIgnoredUIEvent();
1339     return;
1340   }
1341   RenderWidgetHostImpl::ForwardKeyboardEvent(key_event);
1342 }
1343 
IsWaitingForUnloadACK() const1344 bool RenderViewHostImpl::IsWaitingForUnloadACK() const {
1345   return rvh_state_ == STATE_WAITING_FOR_CLOSE ||
1346          rvh_state_ == STATE_PENDING_SHUTDOWN ||
1347          rvh_state_ == STATE_PENDING_SWAP_OUT;
1348 }
1349 
OnTextSurroundingSelectionResponse(const base::string16 & content,size_t start_offset,size_t end_offset)1350 void RenderViewHostImpl::OnTextSurroundingSelectionResponse(
1351     const base::string16& content,
1352     size_t start_offset,
1353     size_t end_offset) {
1354   if (!view_)
1355     return;
1356   view_->OnTextSurroundingSelectionResponse(content, start_offset, end_offset);
1357 }
1358 
ExitFullscreen()1359 void RenderViewHostImpl::ExitFullscreen() {
1360   RejectMouseLockOrUnlockIfNecessary();
1361   // Notify delegate_ and renderer of fullscreen state change.
1362   OnToggleFullscreen(false);
1363 }
1364 
GetWebkitPreferences()1365 WebPreferences RenderViewHostImpl::GetWebkitPreferences() {
1366   if (!web_preferences_.get()) {
1367     OnWebkitPreferencesChanged();
1368   }
1369   return *web_preferences_;
1370 }
1371 
UpdateWebkitPreferences(const WebPreferences & prefs)1372 void RenderViewHostImpl::UpdateWebkitPreferences(const WebPreferences& prefs) {
1373   web_preferences_.reset(new WebPreferences(prefs));
1374   Send(new ViewMsg_UpdateWebPreferences(GetRoutingID(), prefs));
1375 }
1376 
OnWebkitPreferencesChanged()1377 void RenderViewHostImpl::OnWebkitPreferencesChanged() {
1378   // This is defensive code to avoid infinite loops due to code run inside
1379   // UpdateWebkitPreferences() accidentally updating more preferences and thus
1380   // calling back into this code. See crbug.com/398751 for one past example.
1381   if (updating_web_preferences_)
1382     return;
1383   updating_web_preferences_ = true;
1384   UpdateWebkitPreferences(delegate_->ComputeWebkitPrefs());
1385   updating_web_preferences_ = false;
1386 }
1387 
GetAudioOutputControllers(const GetAudioOutputControllersCallback & callback) const1388 void RenderViewHostImpl::GetAudioOutputControllers(
1389     const GetAudioOutputControllersCallback& callback) const {
1390   scoped_refptr<AudioRendererHost> audio_host =
1391       static_cast<RenderProcessHostImpl*>(GetProcess())->audio_renderer_host();
1392   audio_host->GetOutputControllers(GetRoutingID(), callback);
1393 }
1394 
ClearFocusedElement()1395 void RenderViewHostImpl::ClearFocusedElement() {
1396   is_focused_element_editable_ = false;
1397   Send(new ViewMsg_ClearFocusedElement(GetRoutingID()));
1398 }
1399 
IsFocusedElementEditable()1400 bool RenderViewHostImpl::IsFocusedElementEditable() {
1401   return is_focused_element_editable_;
1402 }
1403 
Zoom(PageZoom zoom)1404 void RenderViewHostImpl::Zoom(PageZoom zoom) {
1405   Send(new ViewMsg_Zoom(GetRoutingID(), zoom));
1406 }
1407 
DisableScrollbarsForThreshold(const gfx::Size & size)1408 void RenderViewHostImpl::DisableScrollbarsForThreshold(const gfx::Size& size) {
1409   Send(new ViewMsg_DisableScrollbarsForSmallWindows(GetRoutingID(), size));
1410 }
1411 
EnablePreferredSizeMode()1412 void RenderViewHostImpl::EnablePreferredSizeMode() {
1413   Send(new ViewMsg_EnablePreferredSizeChangedMode(GetRoutingID()));
1414 }
1415 
EnableAutoResize(const gfx::Size & min_size,const gfx::Size & max_size)1416 void RenderViewHostImpl::EnableAutoResize(const gfx::Size& min_size,
1417                                           const gfx::Size& max_size) {
1418   SetAutoResize(true, min_size, max_size);
1419   Send(new ViewMsg_EnableAutoResize(GetRoutingID(), min_size, max_size));
1420 }
1421 
DisableAutoResize(const gfx::Size & new_size)1422 void RenderViewHostImpl::DisableAutoResize(const gfx::Size& new_size) {
1423   SetAutoResize(false, gfx::Size(), gfx::Size());
1424   Send(new ViewMsg_DisableAutoResize(GetRoutingID(), new_size));
1425   if (!new_size.IsEmpty())
1426     GetView()->SetSize(new_size);
1427 }
1428 
CopyImageAt(int x,int y)1429 void RenderViewHostImpl::CopyImageAt(int x, int y) {
1430   Send(new ViewMsg_CopyImageAt(GetRoutingID(), x, y));
1431 }
1432 
SaveImageAt(int x,int y)1433 void RenderViewHostImpl::SaveImageAt(int x, int y) {
1434   Send(new ViewMsg_SaveImageAt(GetRoutingID(), x, y));
1435 }
1436 
ExecuteMediaPlayerActionAtLocation(const gfx::Point & location,const blink::WebMediaPlayerAction & action)1437 void RenderViewHostImpl::ExecuteMediaPlayerActionAtLocation(
1438   const gfx::Point& location, const blink::WebMediaPlayerAction& action) {
1439   Send(new ViewMsg_MediaPlayerActionAt(GetRoutingID(), location, action));
1440 }
1441 
ExecutePluginActionAtLocation(const gfx::Point & location,const blink::WebPluginAction & action)1442 void RenderViewHostImpl::ExecutePluginActionAtLocation(
1443   const gfx::Point& location, const blink::WebPluginAction& action) {
1444   Send(new ViewMsg_PluginActionAt(GetRoutingID(), location, action));
1445 }
1446 
NotifyMoveOrResizeStarted()1447 void RenderViewHostImpl::NotifyMoveOrResizeStarted() {
1448   Send(new ViewMsg_MoveOrResizeStarted(GetRoutingID()));
1449 }
1450 
OnDidZoomURL(double zoom_level,const GURL & url)1451 void RenderViewHostImpl::OnDidZoomURL(double zoom_level,
1452                                       const GURL& url) {
1453   HostZoomMapImpl* host_zoom_map =
1454       static_cast<HostZoomMapImpl*>(HostZoomMap::GetDefaultForBrowserContext(
1455           GetProcess()->GetBrowserContext()));
1456 
1457   host_zoom_map->SetZoomLevelForView(GetProcess()->GetID(),
1458                                      GetRoutingID(),
1459                                      zoom_level,
1460                                      net::GetHostOrSpecFromURL(url));
1461 }
1462 
OnRunFileChooser(const FileChooserParams & params)1463 void RenderViewHostImpl::OnRunFileChooser(const FileChooserParams& params) {
1464   delegate_->RunFileChooser(this, params);
1465 }
1466 
OnFocusedNodeTouched(bool editable)1467 void RenderViewHostImpl::OnFocusedNodeTouched(bool editable) {
1468 #if defined(OS_WIN)
1469   if (editable) {
1470     virtual_keyboard_requested_ = base::win::DisplayVirtualKeyboard();
1471     delegate_->SetIsVirtualKeyboardRequested(true);
1472   } else {
1473     virtual_keyboard_requested_ = false;
1474     delegate_->SetIsVirtualKeyboardRequested(false);
1475     base::win::DismissVirtualKeyboard();
1476   }
1477 #endif
1478 }
1479 
SetState(RenderViewHostImplState rvh_state)1480 void RenderViewHostImpl::SetState(RenderViewHostImplState rvh_state) {
1481   // We update the number of RenderViews in a SiteInstance when the
1482   // swapped out status of this RenderView gets flipped to/from live.
1483   if (!IsRVHStateActive(rvh_state_) && IsRVHStateActive(rvh_state))
1484     instance_->increment_active_view_count();
1485   else if (IsRVHStateActive(rvh_state_) && !IsRVHStateActive(rvh_state))
1486     instance_->decrement_active_view_count();
1487 
1488   // Whenever we change the RVH state to and from live or swapped out state, we
1489   // should not be waiting for beforeunload or unload acks.  We clear them here
1490   // to be safe, since they can cause navigations to be ignored in OnNavigate.
1491   if (rvh_state == STATE_DEFAULT ||
1492       rvh_state == STATE_SWAPPED_OUT ||
1493       rvh_state_ == STATE_DEFAULT ||
1494       rvh_state_ == STATE_SWAPPED_OUT) {
1495     is_waiting_for_beforeunload_ack_ = false;
1496   }
1497   rvh_state_ = rvh_state;
1498 
1499 }
1500 
CanAccessFilesOfPageState(const PageState & state) const1501 bool RenderViewHostImpl::CanAccessFilesOfPageState(
1502     const PageState& state) const {
1503   ChildProcessSecurityPolicyImpl* policy =
1504       ChildProcessSecurityPolicyImpl::GetInstance();
1505 
1506   const std::vector<base::FilePath>& file_paths = state.GetReferencedFiles();
1507   for (std::vector<base::FilePath>::const_iterator file = file_paths.begin();
1508        file != file_paths.end(); ++file) {
1509     if (!policy->CanReadFile(GetProcess()->GetID(), *file))
1510       return false;
1511   }
1512   return true;
1513 }
1514 
AttachToFrameTree()1515 void RenderViewHostImpl::AttachToFrameTree() {
1516   FrameTree* frame_tree = delegate_->GetFrameTree();
1517 
1518   frame_tree->ResetForMainFrameSwap();
1519 }
1520 
SelectWordAroundCaret()1521 void RenderViewHostImpl::SelectWordAroundCaret() {
1522   Send(new ViewMsg_SelectWordAroundCaret(GetRoutingID()));
1523 }
1524 
1525 }  // namespace content
1526