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