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