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