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