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/lazy_instance.h"
     18 #include "base/message_loop/message_loop.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/time/time.h"
     24 #include "base/values.h"
     25 #include "content/browser/child_process_security_policy_impl.h"
     26 #include "content/browser/cross_site_request_manager.h"
     27 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
     28 #include "content/browser/gpu/gpu_surface_tracker.h"
     29 #include "content/browser/host_zoom_map_impl.h"
     30 #include "content/browser/renderer_host/dip_util.h"
     31 #include "content/browser/renderer_host/render_process_host_impl.h"
     32 #include "content/browser/renderer_host/render_view_host_delegate.h"
     33 #include "content/common/accessibility_messages.h"
     34 #include "content/common/browser_plugin/browser_plugin_messages.h"
     35 #include "content/common/desktop_notification_messages.h"
     36 #include "content/common/drag_messages.h"
     37 #include "content/common/input_messages.h"
     38 #include "content/common/inter_process_time_ticks_converter.h"
     39 #include "content/common/speech_recognition_messages.h"
     40 #include "content/common/swapped_out_messages.h"
     41 #include "content/common/view_messages.h"
     42 #include "content/port/browser/render_view_host_delegate_view.h"
     43 #include "content/port/browser/render_widget_host_view_port.h"
     44 #include "content/public/browser/browser_accessibility_state.h"
     45 #include "content/public/browser/browser_context.h"
     46 #include "content/public/browser/browser_message_filter.h"
     47 #include "content/public/browser/content_browser_client.h"
     48 #include "content/public/browser/dom_operation_notification_details.h"
     49 #include "content/public/browser/native_web_keyboard_event.h"
     50 #include "content/public/browser/notification_details.h"
     51 #include "content/public/browser/notification_service.h"
     52 #include "content/public/browser/notification_types.h"
     53 #include "content/public/browser/render_view_host_observer.h"
     54 #include "content/public/browser/user_metrics.h"
     55 #include "content/public/common/bindings_policy.h"
     56 #include "content/public/common/content_constants.h"
     57 #include "content/public/common/content_switches.h"
     58 #include "content/public/common/context_menu_params.h"
     59 #include "content/public/common/drop_data.h"
     60 #include "content/public/common/result_codes.h"
     61 #include "content/public/common/url_constants.h"
     62 #include "content/public/common/url_utils.h"
     63 #include "net/base/net_util.h"
     64 #include "net/url_request/url_request_context_getter.h"
     65 #include "third_party/skia/include/core/SkBitmap.h"
     66 #include "ui/gfx/image/image_skia.h"
     67 #include "ui/gfx/native_widget_types.h"
     68 #include "ui/shell_dialogs/selected_file_info.h"
     69 #include "ui/snapshot/snapshot.h"
     70 #include "webkit/browser/fileapi/isolated_context.h"
     71 
     72 #if defined(OS_MACOSX)
     73 #include "content/browser/renderer_host/popup_menu_helper_mac.h"
     74 #elif defined(OS_ANDROID)
     75 #include "media/base/android/media_player_manager.h"
     76 #endif
     77 
     78 using base::TimeDelta;
     79 using WebKit::WebConsoleMessage;
     80 using WebKit::WebDragOperation;
     81 using WebKit::WebDragOperationNone;
     82 using WebKit::WebDragOperationsMask;
     83 using WebKit::WebInputEvent;
     84 using WebKit::WebMediaPlayerAction;
     85 using WebKit::WebPluginAction;
     86 
     87 namespace content {
     88 namespace {
     89 
     90 // Delay to wait on closing the WebContents for a beforeunload/unload handler to
     91 // fire.
     92 const int kUnloadTimeoutMS = 1000;
     93 
     94 // Translate a WebKit text direction into a base::i18n one.
     95 base::i18n::TextDirection WebTextDirectionToChromeTextDirection(
     96     WebKit::WebTextDirection dir) {
     97   switch (dir) {
     98     case WebKit::WebTextDirectionLeftToRight:
     99       return base::i18n::LEFT_TO_RIGHT;
    100     case WebKit::WebTextDirectionRightToLeft:
    101       return base::i18n::RIGHT_TO_LEFT;
    102     default:
    103       NOTREACHED();
    104       return base::i18n::UNKNOWN_DIRECTION;
    105   }
    106 }
    107 
    108 base::LazyInstance<std::vector<RenderViewHost::CreatedCallback> >
    109 g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
    110 
    111 }  // namespace
    112 
    113 ///////////////////////////////////////////////////////////////////////////////
    114 // RenderViewHost, public:
    115 
    116 // static
    117 RenderViewHost* RenderViewHost::FromID(int render_process_id,
    118                                        int render_view_id) {
    119   RenderWidgetHost* widget =
    120       RenderWidgetHost::FromID(render_process_id, render_view_id);
    121   if (!widget || !widget->IsRenderView())
    122     return NULL;
    123   return static_cast<RenderViewHostImpl*>(RenderWidgetHostImpl::From(widget));
    124 }
    125 
    126 // static
    127 RenderViewHost* RenderViewHost::From(RenderWidgetHost* rwh) {
    128   DCHECK(rwh->IsRenderView());
    129   return static_cast<RenderViewHostImpl*>(RenderWidgetHostImpl::From(rwh));
    130 }
    131 
    132 // static
    133 void RenderViewHost::FilterURL(const RenderProcessHost* process,
    134                                bool empty_allowed,
    135                                GURL* url) {
    136   RenderViewHostImpl::FilterURL(ChildProcessSecurityPolicyImpl::GetInstance(),
    137                                 process, empty_allowed, url);
    138 }
    139 
    140 ///////////////////////////////////////////////////////////////////////////////
    141 // RenderViewHostImpl, public:
    142 
    143 // static
    144 RenderViewHostImpl* RenderViewHostImpl::FromID(int render_process_id,
    145                                                int render_view_id) {
    146   return static_cast<RenderViewHostImpl*>(
    147       RenderViewHost::FromID(render_process_id, render_view_id));
    148 }
    149 
    150 RenderViewHostImpl::RenderViewHostImpl(
    151     SiteInstance* instance,
    152     RenderViewHostDelegate* delegate,
    153     RenderWidgetHostDelegate* widget_delegate,
    154     int routing_id,
    155     int main_frame_routing_id,
    156     bool swapped_out)
    157     : RenderWidgetHostImpl(widget_delegate, instance->GetProcess(), routing_id),
    158       delegate_(delegate),
    159       instance_(static_cast<SiteInstanceImpl*>(instance)),
    160       waiting_for_drag_context_response_(false),
    161       enabled_bindings_(0),
    162       navigations_suspended_(false),
    163       has_accessed_initial_document_(false),
    164       is_swapped_out_(swapped_out),
    165       is_subframe_(false),
    166       main_frame_id_(-1),
    167       run_modal_reply_msg_(NULL),
    168       run_modal_opener_id_(MSG_ROUTING_NONE),
    169       is_waiting_for_beforeunload_ack_(false),
    170       is_waiting_for_unload_ack_(false),
    171       has_timed_out_on_unload_(false),
    172       unload_ack_is_for_cross_site_transition_(false),
    173       are_javascript_messages_suppressed_(false),
    174       sudden_termination_allowed_(false),
    175       render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING) {
    176   DCHECK(instance_.get());
    177   CHECK(delegate_);  // http://crbug.com/82827
    178 
    179   if (main_frame_routing_id == MSG_ROUTING_NONE)
    180     main_frame_routing_id = GetProcess()->GetNextRoutingID();
    181 
    182   main_render_frame_host_.reset(
    183       new RenderFrameHostImpl(this, main_frame_routing_id, is_swapped_out_));
    184 
    185   GetProcess()->EnableSendQueue();
    186 
    187   for (size_t i = 0; i < g_created_callbacks.Get().size(); i++)
    188     g_created_callbacks.Get().at(i).Run(this);
    189 
    190   if (!swapped_out)
    191     instance_->increment_active_view_count();
    192 
    193 #if defined(OS_ANDROID)
    194   media_player_manager_ = media::MediaPlayerManager::Create(this);
    195 #endif
    196 }
    197 
    198 RenderViewHostImpl::~RenderViewHostImpl() {
    199   FOR_EACH_OBSERVER(
    200       RenderViewHostObserver, observers_, RenderViewHostDestruction());
    201 
    202     GetDelegate()->RenderViewDeleted(this);
    203 
    204   // Be sure to clean up any leftover state from cross-site requests.
    205   CrossSiteRequestManager::GetInstance()->SetHasPendingCrossSiteRequest(
    206       GetProcess()->GetID(), GetRoutingID(), false);
    207 
    208   // If this was swapped out, it already decremented the active view
    209   // count of the SiteInstance it belongs to.
    210   if (!is_swapped_out_)
    211     instance_->decrement_active_view_count();
    212 }
    213 
    214 RenderViewHostDelegate* RenderViewHostImpl::GetDelegate() const {
    215   return delegate_;
    216 }
    217 
    218 SiteInstance* RenderViewHostImpl::GetSiteInstance() const {
    219   return instance_.get();
    220 }
    221 
    222 bool RenderViewHostImpl::CreateRenderView(
    223     const string16& frame_name,
    224     int opener_route_id,
    225     int32 max_page_id) {
    226   TRACE_EVENT0("renderer_host", "RenderViewHostImpl::CreateRenderView");
    227   DCHECK(!IsRenderViewLive()) << "Creating view twice";
    228 
    229   // The process may (if we're sharing a process with another host that already
    230   // initialized it) or may not (we have our own process or the old process
    231   // crashed) have been initialized. Calling Init multiple times will be
    232   // ignored, so this is safe.
    233   if (!GetProcess()->Init())
    234     return false;
    235   DCHECK(GetProcess()->HasConnection());
    236   DCHECK(GetProcess()->GetBrowserContext());
    237 
    238   renderer_initialized_ = true;
    239 
    240   GpuSurfaceTracker::Get()->SetSurfaceHandle(
    241       surface_id(), GetCompositingSurface());
    242 
    243   // Ensure the RenderView starts with a next_page_id larger than any existing
    244   // page ID it might be asked to render.
    245   int32 next_page_id = 1;
    246   if (max_page_id > -1)
    247     next_page_id = max_page_id + 1;
    248 
    249   ViewMsg_New_Params params;
    250   params.renderer_preferences =
    251       delegate_->GetRendererPrefs(GetProcess()->GetBrowserContext());
    252   params.web_preferences = delegate_->GetWebkitPrefs();
    253   params.view_id = GetRoutingID();
    254   params.main_frame_routing_id = main_render_frame_host_->routing_id();
    255   params.surface_id = surface_id();
    256   params.session_storage_namespace_id =
    257       delegate_->GetSessionStorageNamespace(instance_)->id();
    258   params.frame_name = frame_name;
    259   // Ensure the RenderView sets its opener correctly.
    260   params.opener_route_id = opener_route_id;
    261   params.swapped_out = is_swapped_out_;
    262   params.next_page_id = next_page_id;
    263   GetWebScreenInfo(&params.screen_info);
    264   params.accessibility_mode = accessibility_mode();
    265   params.allow_partial_swap = !GetProcess()->IsGuest();
    266 
    267   Send(new ViewMsg_New(params));
    268 
    269   // If it's enabled, tell the renderer to set up the Javascript bindings for
    270   // sending messages back to the browser.
    271   if (GetProcess()->IsGuest())
    272     DCHECK_EQ(0, enabled_bindings_);
    273   Send(new ViewMsg_AllowBindings(GetRoutingID(), enabled_bindings_));
    274   // Let our delegate know that we created a RenderView.
    275   delegate_->RenderViewCreated(this);
    276 
    277   FOR_EACH_OBSERVER(
    278       RenderViewHostObserver, observers_, RenderViewHostInitialized());
    279 
    280   return true;
    281 }
    282 
    283 bool RenderViewHostImpl::IsRenderViewLive() const {
    284   return GetProcess()->HasConnection() && renderer_initialized_;
    285 }
    286 
    287 bool RenderViewHostImpl::IsSubframe() const {
    288   return is_subframe_;
    289 }
    290 
    291 void RenderViewHostImpl::SyncRendererPrefs() {
    292   Send(new ViewMsg_SetRendererPrefs(GetRoutingID(),
    293                                     delegate_->GetRendererPrefs(
    294                                         GetProcess()->GetBrowserContext())));
    295 }
    296 
    297 void RenderViewHostImpl::Navigate(const ViewMsg_Navigate_Params& params) {
    298   TRACE_EVENT0("renderer_host", "RenderViewHostImpl::Navigate");
    299   // Browser plugin guests are not allowed to navigate outside web-safe schemes,
    300   // so do not grant them the ability to request additional URLs.
    301   if (!GetProcess()->IsGuest()) {
    302     ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestURL(
    303         GetProcess()->GetID(), params.url);
    304     if (params.url.SchemeIs(chrome::kDataScheme) &&
    305         params.base_url_for_data_url.SchemeIs(chrome::kFileScheme)) {
    306       // If 'data:' is used, and we have a 'file:' base url, grant access to
    307       // local files.
    308       ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestURL(
    309           GetProcess()->GetID(), params.base_url_for_data_url);
    310     }
    311   }
    312 
    313   // Only send the message if we aren't suspended at the start of a cross-site
    314   // request.
    315   if (navigations_suspended_) {
    316     // Shouldn't be possible to have a second navigation while suspended, since
    317     // navigations will only be suspended during a cross-site request.  If a
    318     // second navigation occurs, WebContentsImpl will cancel this pending RVH
    319     // create a new pending RVH.
    320     DCHECK(!suspended_nav_params_.get());
    321     suspended_nav_params_.reset(new ViewMsg_Navigate_Params(params));
    322   } else {
    323     // Get back to a clean state, in case we start a new navigation without
    324     // completing a RVH swap or unload handler.
    325     SetSwappedOut(false);
    326 
    327     Send(new ViewMsg_Navigate(GetRoutingID(), params));
    328   }
    329 
    330   // Force the throbber to start. We do this because WebKit's "started
    331   // loading" message will be received asynchronously from the UI of the
    332   // browser. But we want to keep the throbber in sync with what's happening
    333   // in the UI. For example, we want to start throbbing immediately when the
    334   // user naivgates even if the renderer is delayed. There is also an issue
    335   // with the throbber starting because the WebUI (which controls whether the
    336   // favicon is displayed) happens synchronously. If the start loading
    337   // messages was asynchronous, then the default favicon would flash in.
    338   //
    339   // WebKit doesn't send throb notifications for JavaScript URLs, so we
    340   // don't want to either.
    341   if (!params.url.SchemeIs(chrome::kJavaScriptScheme))
    342     delegate_->DidStartLoading(this);
    343 
    344   FOR_EACH_OBSERVER(RenderViewHostObserver, observers_, Navigate(params.url));
    345 }
    346 
    347 void RenderViewHostImpl::NavigateToURL(const GURL& url) {
    348   ViewMsg_Navigate_Params params;
    349   params.page_id = -1;
    350   params.pending_history_list_offset = -1;
    351   params.current_history_list_offset = -1;
    352   params.current_history_list_length = 0;
    353   params.url = url;
    354   params.transition = PAGE_TRANSITION_LINK;
    355   params.navigation_type = ViewMsg_Navigate_Type::NORMAL;
    356   Navigate(params);
    357 }
    358 
    359 void RenderViewHostImpl::SetNavigationsSuspended(
    360     bool suspend,
    361     const base::TimeTicks& proceed_time) {
    362   // This should only be called to toggle the state.
    363   DCHECK(navigations_suspended_ != suspend);
    364 
    365   navigations_suspended_ = suspend;
    366   if (!suspend && suspended_nav_params_) {
    367     // There's navigation message params waiting to be sent.  Now that we're not
    368     // suspended anymore, resume navigation by sending them.  If we were swapped
    369     // out, we should also stop filtering out the IPC messages now.
    370     SetSwappedOut(false);
    371 
    372     DCHECK(!proceed_time.is_null());
    373     suspended_nav_params_->browser_navigation_start = proceed_time;
    374     Send(new ViewMsg_Navigate(GetRoutingID(), *suspended_nav_params_.get()));
    375     suspended_nav_params_.reset();
    376   }
    377 }
    378 
    379 void RenderViewHostImpl::CancelSuspendedNavigations() {
    380   // Clear any state if a pending navigation is canceled or pre-empted.
    381   if (suspended_nav_params_)
    382     suspended_nav_params_.reset();
    383   navigations_suspended_ = false;
    384 }
    385 
    386 void RenderViewHostImpl::FirePageBeforeUnload(bool for_cross_site_transition) {
    387   if (!IsRenderViewLive()) {
    388     // This RenderViewHostImpl doesn't have a live renderer, so just
    389     // skip running the onbeforeunload handler.
    390     is_waiting_for_beforeunload_ack_ = true;  // Checked by OnShouldCloseACK.
    391     unload_ack_is_for_cross_site_transition_ = for_cross_site_transition;
    392     base::TimeTicks now = base::TimeTicks::Now();
    393     OnShouldCloseACK(true, now, now);
    394     return;
    395   }
    396 
    397   // This may be called more than once (if the user clicks the tab close button
    398   // several times, or if she clicks the tab close button then the browser close
    399   // button), and we only send the message once.
    400   if (is_waiting_for_beforeunload_ack_) {
    401     // Some of our close messages could be for the tab, others for cross-site
    402     // transitions. We always want to think it's for closing the tab if any
    403     // of the messages were, since otherwise it might be impossible to close
    404     // (if there was a cross-site "close" request pending when the user clicked
    405     // the close button). We want to keep the "for cross site" flag only if
    406     // both the old and the new ones are also for cross site.
    407     unload_ack_is_for_cross_site_transition_ =
    408         unload_ack_is_for_cross_site_transition_ && for_cross_site_transition;
    409   } else {
    410     // Start the hang monitor in case the renderer hangs in the beforeunload
    411     // handler.
    412     is_waiting_for_beforeunload_ack_ = true;
    413     unload_ack_is_for_cross_site_transition_ = for_cross_site_transition;
    414     // Increment the in-flight event count, to ensure that input events won't
    415     // cancel the timeout timer.
    416     increment_in_flight_event_count();
    417     StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
    418     send_should_close_start_time_ = base::TimeTicks::Now();
    419     Send(new ViewMsg_ShouldClose(GetRoutingID()));
    420   }
    421 }
    422 
    423 void RenderViewHostImpl::SwapOut() {
    424   // This will be set back to false in OnSwapOutACK, just before we replace
    425   // this RVH with the pending RVH.
    426   is_waiting_for_unload_ack_ = true;
    427   // Start the hang monitor in case the renderer hangs in the unload handler.
    428   // Increment the in-flight event count, to ensure that input events won't
    429   // cancel the timeout timer.
    430   increment_in_flight_event_count();
    431   StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
    432 
    433   if (IsRenderViewLive()) {
    434     Send(new ViewMsg_SwapOut(GetRoutingID()));
    435   } else {
    436     // This RenderViewHost doesn't have a live renderer, so just skip the unload
    437     // event.
    438     OnSwappedOut(true);
    439   }
    440 }
    441 
    442 void RenderViewHostImpl::OnSwapOutACK() {
    443   OnSwappedOut(false);
    444 }
    445 
    446 void RenderViewHostImpl::OnSwappedOut(bool timed_out) {
    447   // Stop the hang monitor now that the unload handler has finished.
    448   decrement_in_flight_event_count();
    449   StopHangMonitorTimeout();
    450   is_waiting_for_unload_ack_ = false;
    451   has_timed_out_on_unload_ = timed_out;
    452   delegate_->SwappedOut(this);
    453 }
    454 
    455 void RenderViewHostImpl::WasSwappedOut() {
    456   // Don't bother reporting hung state anymore.
    457   StopHangMonitorTimeout();
    458 
    459   // If we have timed out on running the unload handler, we consider
    460   // the process hung and we should terminate it if there are no other tabs
    461   // using the process. If there are other views using this process, the
    462   // unresponsive renderer timeout will catch it.
    463   bool hung = has_timed_out_on_unload_;
    464 
    465   // Now that we're no longer the active RVH in the tab, start filtering out
    466   // most IPC messages.  Usually the renderer will have stopped sending
    467   // messages as of OnSwapOutACK.  However, we may have timed out waiting
    468   // for that message, and additional IPC messages may keep streaming in.
    469   // We filter them out, as long as that won't cause problems (e.g., we
    470   // still allow synchronous messages through).
    471   SetSwappedOut(true);
    472 
    473   // If we are not running the renderer in process and no other tab is using
    474   // the hung process, consider it eligible to be killed, assuming it is a real
    475   // process (unit tests don't have real processes).
    476   if (hung) {
    477     base::ProcessHandle process_handle = GetProcess()->GetHandle();
    478     int views = 0;
    479 
    480     // Count the number of active widget hosts for the process, which
    481     // is equivalent to views using the process as of this writing.
    482     RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
    483     for (size_t i = 0; i < widgets.size(); ++i) {
    484       if (widgets[i]->GetProcess()->GetID() == GetProcess()->GetID())
    485         ++views;
    486     }
    487 
    488     if (!RenderProcessHost::run_renderer_in_process() &&
    489         process_handle && views <= 1) {
    490       // The process can safely be terminated, only if WebContents sets
    491       // SuddenTerminationAllowed, which indicates that the timer has expired.
    492       // This is not the case if we load data URLs or about:blank. The reason
    493       // is that those have no network requests and this code is hit without
    494       // setting the unresponsiveness timer. This allows a corner case where a
    495       // navigation to a data URL will leave a process running, if the
    496       // beforeunload handler completes fine, but the unload handler hangs.
    497       // At this time, the complexity to solve this edge case is not worthwhile.
    498       if (SuddenTerminationAllowed()) {
    499         // We should kill the process, but for now, just log the data so we can
    500         // diagnose the kill rate and investigate if separate timer is needed.
    501         // http://crbug.com/104346.
    502 
    503         // Log a histogram point to help us diagnose how many of those kills
    504         // we have performed. 1 is the enum value for RendererType Normal for
    505         // the histogram.
    506         UMA_HISTOGRAM_PERCENTAGE(
    507             "BrowserRenderProcessHost.ChildKillsUnresponsive", 1);
    508       }
    509     }
    510   }
    511 
    512   // Inform the renderer that it can exit if no one else is using it.
    513   Send(new ViewMsg_WasSwappedOut(GetRoutingID()));
    514 }
    515 
    516 void RenderViewHostImpl::ClosePage() {
    517   // Start the hang monitor in case the renderer hangs in the unload handler.
    518   is_waiting_for_unload_ack_ = true;
    519   StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
    520 
    521   if (IsRenderViewLive()) {
    522     // Since we are sending an IPC message to the renderer, increase the event
    523     // count to prevent the hang monitor timeout from being stopped by input
    524     // event acknowledgements.
    525     increment_in_flight_event_count();
    526 
    527     // TODO(creis): Should this be moved to Shutdown?  It may not be called for
    528     // RenderViewHosts that have been swapped out.
    529     NotificationService::current()->Notify(
    530         NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW,
    531         Source<RenderViewHost>(this),
    532         NotificationService::NoDetails());
    533 
    534     Send(new ViewMsg_ClosePage(GetRoutingID()));
    535   } else {
    536     // This RenderViewHost doesn't have a live renderer, so just skip the unload
    537     // event and close the page.
    538     ClosePageIgnoringUnloadEvents();
    539   }
    540 }
    541 
    542 void RenderViewHostImpl::ClosePageIgnoringUnloadEvents() {
    543   StopHangMonitorTimeout();
    544   is_waiting_for_beforeunload_ack_ = false;
    545   is_waiting_for_unload_ack_ = false;
    546 
    547   sudden_termination_allowed_ = true;
    548   delegate_->Close(this);
    549 }
    550 
    551 bool RenderViewHostImpl::HasPendingCrossSiteRequest() {
    552   return CrossSiteRequestManager::GetInstance()->HasPendingCrossSiteRequest(
    553       GetProcess()->GetID(), GetRoutingID());
    554 }
    555 
    556 void RenderViewHostImpl::SetHasPendingCrossSiteRequest(
    557     bool has_pending_request) {
    558   CrossSiteRequestManager::GetInstance()->SetHasPendingCrossSiteRequest(
    559       GetProcess()->GetID(), GetRoutingID(), has_pending_request);
    560 }
    561 
    562 #if defined(OS_ANDROID)
    563 void RenderViewHostImpl::ActivateNearestFindResult(int request_id,
    564                                                    float x,
    565                                                    float y) {
    566   Send(new InputMsg_ActivateNearestFindResult(GetRoutingID(),
    567                                               request_id, x, y));
    568 }
    569 
    570 void RenderViewHostImpl::RequestFindMatchRects(int current_version) {
    571   Send(new ViewMsg_FindMatchRects(GetRoutingID(), current_version));
    572 }
    573 #endif
    574 
    575 void RenderViewHostImpl::DragTargetDragEnter(
    576     const DropData& drop_data,
    577     const gfx::Point& client_pt,
    578     const gfx::Point& screen_pt,
    579     WebDragOperationsMask operations_allowed,
    580     int key_modifiers) {
    581   const int renderer_id = GetProcess()->GetID();
    582   ChildProcessSecurityPolicyImpl* policy =
    583       ChildProcessSecurityPolicyImpl::GetInstance();
    584 
    585   // The URL could have been cobbled together from any highlighted text string,
    586   // and can't be interpreted as a capability.
    587   DropData filtered_data(drop_data);
    588   FilterURL(policy, GetProcess(), true, &filtered_data.url);
    589 
    590   // The filenames vector, on the other hand, does represent a capability to
    591   // access the given files.
    592   fileapi::IsolatedContext::FileInfoSet files;
    593   for (std::vector<DropData::FileInfo>::iterator iter(
    594            filtered_data.filenames.begin());
    595        iter != filtered_data.filenames.end(); ++iter) {
    596     // A dragged file may wind up as the value of an input element, or it
    597     // may be used as the target of a navigation instead.  We don't know
    598     // which will happen at this point, so generously grant both access
    599     // and request permissions to the specific file to cover both cases.
    600     // We do not give it the permission to request all file:// URLs.
    601     base::FilePath path =
    602         base::FilePath::FromUTF8Unsafe(UTF16ToUTF8(iter->path));
    603 
    604     // Make sure we have the same display_name as the one we register.
    605     if (iter->display_name.empty()) {
    606       std::string name;
    607       files.AddPath(path, &name);
    608       iter->display_name = UTF8ToUTF16(name);
    609     } else {
    610       files.AddPathWithName(path, UTF16ToUTF8(iter->display_name));
    611     }
    612 
    613     policy->GrantRequestSpecificFileURL(renderer_id,
    614                                         net::FilePathToFileURL(path));
    615 
    616     // If the renderer already has permission to read these paths, we don't need
    617     // to re-grant them. This prevents problems with DnD for files in the CrOS
    618     // file manager--the file manager already had read/write access to those
    619     // directories, but dragging a file would cause the read/write access to be
    620     // overwritten with read-only access, making them impossible to delete or
    621     // rename until the renderer was killed.
    622     if (!policy->CanReadFile(renderer_id, path)) {
    623       policy->GrantReadFile(renderer_id, path);
    624       // Allow dragged directories to be enumerated by the child process.
    625       // Note that we can't tell a file from a directory at this point.
    626       policy->GrantReadDirectory(renderer_id, path);
    627     }
    628   }
    629 
    630   fileapi::IsolatedContext* isolated_context =
    631       fileapi::IsolatedContext::GetInstance();
    632   DCHECK(isolated_context);
    633   std::string filesystem_id = isolated_context->RegisterDraggedFileSystem(
    634       files);
    635   if (!filesystem_id.empty()) {
    636     // Grant the permission iff the ID is valid.
    637     policy->GrantReadFileSystem(renderer_id, filesystem_id);
    638   }
    639   filtered_data.filesystem_id = UTF8ToUTF16(filesystem_id);
    640 
    641   Send(new DragMsg_TargetDragEnter(GetRoutingID(), filtered_data, client_pt,
    642                                    screen_pt, operations_allowed,
    643                                    key_modifiers));
    644 }
    645 
    646 void RenderViewHostImpl::DragTargetDragOver(
    647     const gfx::Point& client_pt,
    648     const gfx::Point& screen_pt,
    649     WebDragOperationsMask operations_allowed,
    650     int key_modifiers) {
    651   Send(new DragMsg_TargetDragOver(GetRoutingID(), client_pt, screen_pt,
    652                                   operations_allowed, key_modifiers));
    653 }
    654 
    655 void RenderViewHostImpl::DragTargetDragLeave() {
    656   Send(new DragMsg_TargetDragLeave(GetRoutingID()));
    657 }
    658 
    659 void RenderViewHostImpl::DragTargetDrop(
    660     const gfx::Point& client_pt,
    661     const gfx::Point& screen_pt,
    662     int key_modifiers) {
    663   Send(new DragMsg_TargetDrop(GetRoutingID(), client_pt, screen_pt,
    664                               key_modifiers));
    665 }
    666 
    667 void RenderViewHostImpl::DesktopNotificationPermissionRequestDone(
    668     int callback_context) {
    669   Send(new DesktopNotificationMsg_PermissionRequestDone(
    670       GetRoutingID(), callback_context));
    671 }
    672 
    673 void RenderViewHostImpl::DesktopNotificationPostDisplay(int callback_context) {
    674   Send(new DesktopNotificationMsg_PostDisplay(GetRoutingID(),
    675                                               callback_context));
    676 }
    677 
    678 void RenderViewHostImpl::DesktopNotificationPostError(int notification_id,
    679                                                       const string16& message) {
    680   Send(new DesktopNotificationMsg_PostError(
    681       GetRoutingID(), notification_id, message));
    682 }
    683 
    684 void RenderViewHostImpl::DesktopNotificationPostClose(int notification_id,
    685                                                       bool by_user) {
    686   Send(new DesktopNotificationMsg_PostClose(
    687       GetRoutingID(), notification_id, by_user));
    688 }
    689 
    690 void RenderViewHostImpl::DesktopNotificationPostClick(int notification_id) {
    691   Send(new DesktopNotificationMsg_PostClick(GetRoutingID(), notification_id));
    692 }
    693 
    694 void RenderViewHostImpl::ExecuteJavascriptInWebFrame(
    695     const string16& frame_xpath,
    696     const string16& jscript) {
    697   Send(new ViewMsg_ScriptEvalRequest(GetRoutingID(), frame_xpath, jscript,
    698                                      0, false));
    699 }
    700 
    701 void RenderViewHostImpl::ExecuteJavascriptInWebFrameCallbackResult(
    702      const string16& frame_xpath,
    703      const string16& jscript,
    704      const JavascriptResultCallback& callback) {
    705   static int next_id = 1;
    706   int key = next_id++;
    707   Send(new ViewMsg_ScriptEvalRequest(GetRoutingID(), frame_xpath, jscript,
    708                                      key, true));
    709   javascript_callbacks_.insert(std::make_pair(key, callback));
    710 }
    711 
    712 void RenderViewHostImpl::JavaScriptDialogClosed(IPC::Message* reply_msg,
    713                                                 bool success,
    714                                                 const string16& user_input) {
    715   GetProcess()->SetIgnoreInputEvents(false);
    716   bool is_waiting =
    717       is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_;
    718 
    719   // If we are executing as part of (before)unload event handling, we don't
    720   // want to use the regular hung_renderer_delay_ms_ if the user has agreed to
    721   // leave the current page. In this case, use the regular timeout value used
    722   // during the (before)unload handling.
    723   if (is_waiting) {
    724     StartHangMonitorTimeout(TimeDelta::FromMilliseconds(
    725         success ? kUnloadTimeoutMS : hung_renderer_delay_ms_));
    726   }
    727 
    728   ViewHostMsg_RunJavaScriptMessage::WriteReplyParams(reply_msg,
    729                                                      success, user_input);
    730   Send(reply_msg);
    731 
    732   // If we are waiting for an unload or beforeunload ack and the user has
    733   // suppressed messages, kill the tab immediately; a page that's spamming
    734   // alerts in onbeforeunload is presumably malicious, so there's no point in
    735   // continuing to run its script and dragging out the process.
    736   // This must be done after sending the reply since RenderView can't close
    737   // correctly while waiting for a response.
    738   if (is_waiting && are_javascript_messages_suppressed_)
    739     delegate_->RendererUnresponsive(this, is_waiting);
    740 }
    741 
    742 void RenderViewHostImpl::DragSourceEndedAt(
    743     int client_x, int client_y, int screen_x, int screen_y,
    744     WebDragOperation operation) {
    745   Send(new DragMsg_SourceEndedOrMoved(
    746       GetRoutingID(),
    747       gfx::Point(client_x, client_y),
    748       gfx::Point(screen_x, screen_y),
    749       true, operation));
    750 }
    751 
    752 void RenderViewHostImpl::DragSourceMovedTo(
    753     int client_x, int client_y, int screen_x, int screen_y) {
    754   Send(new DragMsg_SourceEndedOrMoved(
    755       GetRoutingID(),
    756       gfx::Point(client_x, client_y),
    757       gfx::Point(screen_x, screen_y),
    758       false, WebDragOperationNone));
    759 }
    760 
    761 void RenderViewHostImpl::DragSourceSystemDragEnded() {
    762   Send(new DragMsg_SourceSystemDragEnded(GetRoutingID()));
    763 }
    764 
    765 void RenderViewHostImpl::AllowBindings(int bindings_flags) {
    766   // Ensure we aren't granting WebUI bindings to a process that has already
    767   // been used for non-privileged views.
    768   if (bindings_flags & BINDINGS_POLICY_WEB_UI &&
    769       GetProcess()->HasConnection() &&
    770       !ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
    771           GetProcess()->GetID())) {
    772     // This process has no bindings yet. Make sure it does not have more
    773     // than this single active view.
    774     RenderProcessHostImpl* process =
    775         static_cast<RenderProcessHostImpl*>(GetProcess());
    776     if (process->GetActiveViewCount() > 1)
    777       return;
    778   }
    779 
    780   // Never grant any bindings to browser plugin guests.
    781   if (GetProcess()->IsGuest()) {
    782     NOTREACHED() << "Never grant bindings to a guest process.";
    783     return;
    784   }
    785 
    786   if (bindings_flags & BINDINGS_POLICY_WEB_UI) {
    787     ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
    788         GetProcess()->GetID());
    789   }
    790 
    791   enabled_bindings_ |= bindings_flags;
    792   if (renderer_initialized_)
    793     Send(new ViewMsg_AllowBindings(GetRoutingID(), enabled_bindings_));
    794 }
    795 
    796 int RenderViewHostImpl::GetEnabledBindings() const {
    797   return enabled_bindings_;
    798 }
    799 
    800 void RenderViewHostImpl::SetWebUIProperty(const std::string& name,
    801                                           const std::string& value) {
    802   // This is a sanity check before telling the renderer to enable the property.
    803   // It could lie and send the corresponding IPC messages anyway, but we will
    804   // not act on them if enabled_bindings_ doesn't agree. If we get here without
    805   // WebUI bindings, kill the renderer process.
    806   if (enabled_bindings_ & BINDINGS_POLICY_WEB_UI) {
    807     Send(new ViewMsg_SetWebUIProperty(GetRoutingID(), name, value));
    808   } else {
    809     RecordAction(UserMetricsAction("BindingsMismatchTerminate_RVH_WebUI"));
    810     base::KillProcess(
    811         GetProcess()->GetHandle(), content::RESULT_CODE_KILLED, false);
    812   }
    813 }
    814 
    815 void RenderViewHostImpl::GotFocus() {
    816   RenderWidgetHostImpl::GotFocus();  // Notifies the renderer it got focus.
    817 
    818   RenderViewHostDelegateView* view = delegate_->GetDelegateView();
    819   if (view)
    820     view->GotFocus();
    821 }
    822 
    823 void RenderViewHostImpl::LostCapture() {
    824   RenderWidgetHostImpl::LostCapture();
    825   delegate_->LostCapture();
    826 }
    827 
    828 void RenderViewHostImpl::LostMouseLock() {
    829   RenderWidgetHostImpl::LostMouseLock();
    830   delegate_->LostMouseLock();
    831 }
    832 
    833 void RenderViewHostImpl::SetInitialFocus(bool reverse) {
    834   Send(new ViewMsg_SetInitialFocus(GetRoutingID(), reverse));
    835 }
    836 
    837 void RenderViewHostImpl::FilesSelectedInChooser(
    838     const std::vector<ui::SelectedFileInfo>& files,
    839     FileChooserParams::Mode permissions) {
    840   // Grant the security access requested to the given files.
    841   for (size_t i = 0; i < files.size(); ++i) {
    842     const ui::SelectedFileInfo& file = files[i];
    843     if (permissions == FileChooserParams::Save) {
    844       ChildProcessSecurityPolicyImpl::GetInstance()->GrantCreateWriteFile(
    845           GetProcess()->GetID(), file.local_path);
    846     } else {
    847       ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
    848           GetProcess()->GetID(), file.local_path);
    849     }
    850   }
    851   Send(new ViewMsg_RunFileChooserResponse(GetRoutingID(), files));
    852 }
    853 
    854 void RenderViewHostImpl::DirectoryEnumerationFinished(
    855     int request_id,
    856     const std::vector<base::FilePath>& files) {
    857   // Grant the security access requested to the given files.
    858   for (std::vector<base::FilePath>::const_iterator file = files.begin();
    859        file != files.end(); ++file) {
    860     ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
    861         GetProcess()->GetID(), *file);
    862   }
    863   Send(new ViewMsg_EnumerateDirectoryResponse(GetRoutingID(),
    864                                               request_id,
    865                                               files));
    866 }
    867 
    868 void RenderViewHostImpl::LoadStateChanged(
    869     const GURL& url,
    870     const net::LoadStateWithParam& load_state,
    871     uint64 upload_position,
    872     uint64 upload_size) {
    873   delegate_->LoadStateChanged(url, load_state, upload_position, upload_size);
    874 }
    875 
    876 bool RenderViewHostImpl::SuddenTerminationAllowed() const {
    877   return sudden_termination_allowed_ ||
    878       GetProcess()->SuddenTerminationAllowed();
    879 }
    880 
    881 ///////////////////////////////////////////////////////////////////////////////
    882 // RenderViewHostImpl, IPC message handlers:
    883 
    884 bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
    885   if (!BrowserMessageFilter::CheckCanDispatchOnUI(msg, this))
    886     return true;
    887 
    888   // Filter out most IPC messages if this renderer is swapped out.
    889   // We still want to handle certain ACKs to keep our state consistent.
    890   if (is_swapped_out_) {
    891     if (!SwappedOutMessages::CanHandleWhileSwappedOut(msg)) {
    892       // If this is a synchronous message and we decided not to handle it,
    893       // we must send an error reply, or else the renderer will be stuck
    894       // and won't respond to future requests.
    895       if (msg.is_sync()) {
    896         IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
    897         reply->set_reply_error();
    898         Send(reply);
    899       }
    900       // Don't continue looking for someone to handle it.
    901       return true;
    902     }
    903   }
    904 
    905   ObserverListBase<RenderViewHostObserver>::Iterator it(observers_);
    906   RenderViewHostObserver* observer;
    907   while ((observer = it.GetNext()) != NULL) {
    908     if (observer->OnMessageReceived(msg))
    909       return true;
    910   }
    911 
    912   if (delegate_->OnMessageReceived(this, msg))
    913     return true;
    914 
    915   // TODO(jochen): Consider removing message handlers that only add a this
    916   // pointer and forward the messages to the RenderViewHostDelegate. The
    917   // respective delegates can handle the messages themselves in their
    918   // OnMessageReceived implementation.
    919   bool handled = true;
    920   bool msg_is_ok = true;
    921   IPC_BEGIN_MESSAGE_MAP_EX(RenderViewHostImpl, msg, msg_is_ok)
    922     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowView, OnShowView)
    923     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
    924     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowFullscreenWidget,
    925                         OnShowFullscreenWidget)
    926     IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunModal, OnRunModal)
    927     IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnRenderViewReady)
    928     IPC_MESSAGE_HANDLER(ViewHostMsg_RenderProcessGone, OnRenderProcessGone)
    929     IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartProvisionalLoadForFrame,
    930                         OnDidStartProvisionalLoadForFrame)
    931     IPC_MESSAGE_HANDLER(ViewHostMsg_DidRedirectProvisionalLoad,
    932                         OnDidRedirectProvisionalLoad)
    933     IPC_MESSAGE_HANDLER(ViewHostMsg_DidFailProvisionalLoadWithError,
    934                         OnDidFailProvisionalLoadWithError)
    935     IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_FrameNavigate, OnNavigate(msg))
    936     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateState, OnUpdateState)
    937     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTitle, OnUpdateTitle)
    938     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateEncoding, OnUpdateEncoding)
    939     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTargetURL, OnUpdateTargetURL)
    940     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateInspectorSetting,
    941                         OnUpdateInspectorSetting)
    942     IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
    943     IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnRequestMove)
    944     IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartLoading, OnDidStartLoading)
    945     IPC_MESSAGE_HANDLER(ViewHostMsg_DidStopLoading, OnDidStopLoading)
    946     IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeLoadProgress,
    947                         OnDidChangeLoadProgress)
    948     IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisownOpener, OnDidDisownOpener)
    949     IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentAvailableInMainFrame,
    950                         OnDocumentAvailableInMainFrame)
    951     IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentOnLoadCompletedInMainFrame,
    952                         OnDocumentOnLoadCompletedInMainFrame)
    953     IPC_MESSAGE_HANDLER(ViewHostMsg_ContextMenu, OnContextMenu)
    954     IPC_MESSAGE_HANDLER(ViewHostMsg_ToggleFullscreen, OnToggleFullscreen)
    955     IPC_MESSAGE_HANDLER(ViewHostMsg_OpenURL, OnOpenURL)
    956     IPC_MESSAGE_HANDLER(ViewHostMsg_DidContentsPreferredSizeChange,
    957                         OnDidContentsPreferredSizeChange)
    958     IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeScrollOffset,
    959                         OnDidChangeScrollOffset)
    960     IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeScrollbarsForMainFrame,
    961                         OnDidChangeScrollbarsForMainFrame)
    962     IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeScrollOffsetPinningForMainFrame,
    963                         OnDidChangeScrollOffsetPinningForMainFrame)
    964     IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeNumWheelEvents,
    965                         OnDidChangeNumWheelEvents)
    966     IPC_MESSAGE_HANDLER(ViewHostMsg_RouteCloseEvent,
    967                         OnRouteCloseEvent)
    968     IPC_MESSAGE_HANDLER(ViewHostMsg_RouteMessageEvent, OnRouteMessageEvent)
    969     IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunJavaScriptMessage,
    970                                     OnRunJavaScriptMessage)
    971     IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunBeforeUnloadConfirm,
    972                                     OnRunBeforeUnloadConfirm)
    973     IPC_MESSAGE_HANDLER(DragHostMsg_StartDragging, OnStartDragging)
    974     IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor, OnUpdateDragCursor)
    975     IPC_MESSAGE_HANDLER(DragHostMsg_TargetDrop_ACK, OnTargetDropACK)
    976     IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
    977     IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeChanged, OnFocusedNodeChanged)
    978     IPC_MESSAGE_HANDLER(ViewHostMsg_AddMessageToConsole, OnAddMessageToConsole)
    979     IPC_MESSAGE_HANDLER(ViewHostMsg_ShouldClose_ACK, OnShouldCloseACK)
    980     IPC_MESSAGE_HANDLER(ViewHostMsg_ClosePage_ACK, OnClosePageACK)
    981     IPC_MESSAGE_HANDLER(ViewHostMsg_SwapOut_ACK, OnSwapOutACK)
    982     IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionChanged, OnSelectionChanged)
    983     IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionBoundsChanged,
    984                         OnSelectionBoundsChanged)
    985     IPC_MESSAGE_HANDLER(ViewHostMsg_ScriptEvalResponse, OnScriptEvalResponse)
    986     IPC_MESSAGE_HANDLER(ViewHostMsg_DidZoomURL, OnDidZoomURL)
    987     IPC_MESSAGE_HANDLER(ViewHostMsg_GetWindowSnapshot, OnGetWindowSnapshot)
    988     IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_RequestPermission,
    989                         OnRequestDesktopNotificationPermission)
    990     IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_Show,
    991                         OnShowDesktopNotification)
    992     IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_Cancel,
    993                         OnCancelDesktopNotification)
    994 #if defined(OS_MACOSX) || defined(OS_ANDROID)
    995     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnShowPopup)
    996 #endif
    997     IPC_MESSAGE_HANDLER(ViewHostMsg_RunFileChooser, OnRunFileChooser)
    998     IPC_MESSAGE_HANDLER(ViewHostMsg_DidAccessInitialDocument,
    999                         OnDidAccessInitialDocument)
   1000     IPC_MESSAGE_HANDLER(ViewHostMsg_DomOperationResponse,
   1001                         OnDomOperationResponse)
   1002     IPC_MESSAGE_HANDLER(AccessibilityHostMsg_Notifications,
   1003                         OnAccessibilityNotifications)
   1004     // Have the super handle all other messages.
   1005     IPC_MESSAGE_UNHANDLED(
   1006         handled = RenderWidgetHostImpl::OnMessageReceived(msg))
   1007   IPC_END_MESSAGE_MAP_EX()
   1008 
   1009   if (!msg_is_ok) {
   1010     // The message had a handler, but its de-serialization failed.
   1011     // Kill the renderer.
   1012     RecordAction(UserMetricsAction("BadMessageTerminate_RVH"));
   1013     GetProcess()->ReceivedBadMessage();
   1014   }
   1015 
   1016   return handled;
   1017 }
   1018 
   1019 void RenderViewHostImpl::Shutdown() {
   1020   // If we are being run modally (see RunModal), then we need to cleanup.
   1021   if (run_modal_reply_msg_) {
   1022     Send(run_modal_reply_msg_);
   1023     run_modal_reply_msg_ = NULL;
   1024     RenderViewHostImpl* opener =
   1025         RenderViewHostImpl::FromID(GetProcess()->GetID(), run_modal_opener_id_);
   1026     if (opener) {
   1027       opener->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(
   1028           hung_renderer_delay_ms_));
   1029       // Balance out the decrement when we got created.
   1030       opener->increment_in_flight_event_count();
   1031     }
   1032     run_modal_opener_id_ = MSG_ROUTING_NONE;
   1033   }
   1034 
   1035   RenderWidgetHostImpl::Shutdown();
   1036 }
   1037 
   1038 bool RenderViewHostImpl::IsRenderView() const {
   1039   return true;
   1040 }
   1041 
   1042 void RenderViewHostImpl::CreateNewWindow(
   1043     int route_id,
   1044     int main_frame_route_id,
   1045     const ViewHostMsg_CreateWindow_Params& params,
   1046     SessionStorageNamespace* session_storage_namespace) {
   1047   ViewHostMsg_CreateWindow_Params validated_params(params);
   1048   ChildProcessSecurityPolicyImpl* policy =
   1049       ChildProcessSecurityPolicyImpl::GetInstance();
   1050   FilterURL(policy, GetProcess(), false, &validated_params.target_url);
   1051   FilterURL(policy, GetProcess(), false, &validated_params.opener_url);
   1052   FilterURL(policy, GetProcess(), true,
   1053             &validated_params.opener_security_origin);
   1054 
   1055   delegate_->CreateNewWindow(route_id, main_frame_route_id,
   1056                              validated_params, session_storage_namespace);
   1057 }
   1058 
   1059 void RenderViewHostImpl::CreateNewWidget(int route_id,
   1060                                      WebKit::WebPopupType popup_type) {
   1061   delegate_->CreateNewWidget(route_id, popup_type);
   1062 }
   1063 
   1064 void RenderViewHostImpl::CreateNewFullscreenWidget(int route_id) {
   1065   delegate_->CreateNewFullscreenWidget(route_id);
   1066 }
   1067 
   1068 void RenderViewHostImpl::OnShowView(int route_id,
   1069                                     WindowOpenDisposition disposition,
   1070                                     const gfx::Rect& initial_pos,
   1071                                     bool user_gesture) {
   1072   if (!is_swapped_out_) {
   1073     delegate_->ShowCreatedWindow(
   1074         route_id, disposition, initial_pos, user_gesture);
   1075   }
   1076   Send(new ViewMsg_Move_ACK(route_id));
   1077 }
   1078 
   1079 void RenderViewHostImpl::OnShowWidget(int route_id,
   1080                                       const gfx::Rect& initial_pos) {
   1081   if (!is_swapped_out_)
   1082     delegate_->ShowCreatedWidget(route_id, initial_pos);
   1083   Send(new ViewMsg_Move_ACK(route_id));
   1084 }
   1085 
   1086 void RenderViewHostImpl::OnShowFullscreenWidget(int route_id) {
   1087   if (!is_swapped_out_)
   1088     delegate_->ShowCreatedFullscreenWidget(route_id);
   1089   Send(new ViewMsg_Move_ACK(route_id));
   1090 }
   1091 
   1092 void RenderViewHostImpl::OnRunModal(int opener_id, IPC::Message* reply_msg) {
   1093   DCHECK(!run_modal_reply_msg_);
   1094   run_modal_reply_msg_ = reply_msg;
   1095   run_modal_opener_id_ = opener_id;
   1096 
   1097   RecordAction(UserMetricsAction("ShowModalDialog"));
   1098 
   1099   RenderViewHostImpl* opener =
   1100       RenderViewHostImpl::FromID(GetProcess()->GetID(), run_modal_opener_id_);
   1101   if (opener) {
   1102     opener->StopHangMonitorTimeout();
   1103     // The ack for the mouse down won't come until the dialog closes, so fake it
   1104     // so that we don't get a timeout.
   1105     opener->decrement_in_flight_event_count();
   1106   }
   1107 
   1108   // TODO(darin): Bug 1107929: Need to inform our delegate to show this view in
   1109   // an app-modal fashion.
   1110 }
   1111 
   1112 void RenderViewHostImpl::OnRenderViewReady() {
   1113   render_view_termination_status_ = base::TERMINATION_STATUS_STILL_RUNNING;
   1114   SendScreenRects();
   1115   WasResized();
   1116   delegate_->RenderViewReady(this);
   1117 }
   1118 
   1119 void RenderViewHostImpl::OnRenderProcessGone(int status, int exit_code) {
   1120   // Keep the termination status so we can get at it later when we
   1121   // need to know why it died.
   1122   render_view_termination_status_ =
   1123       static_cast<base::TerminationStatus>(status);
   1124 
   1125   // Reset state.
   1126   main_frame_id_ = -1;
   1127 
   1128   // Our base class RenderWidgetHost needs to reset some stuff.
   1129   RendererExited(render_view_termination_status_, exit_code);
   1130 
   1131   delegate_->RenderViewTerminated(this,
   1132                                   static_cast<base::TerminationStatus>(status),
   1133                                   exit_code);
   1134 }
   1135 
   1136 void RenderViewHostImpl::OnDidStartProvisionalLoadForFrame(
   1137     int64 frame_id,
   1138     int64 parent_frame_id,
   1139     bool is_main_frame,
   1140     const GURL& url) {
   1141   delegate_->DidStartProvisionalLoadForFrame(
   1142       this, frame_id, parent_frame_id, is_main_frame, url);
   1143 }
   1144 
   1145 void RenderViewHostImpl::OnDidRedirectProvisionalLoad(
   1146     int32 page_id,
   1147     const GURL& source_url,
   1148     const GURL& target_url) {
   1149   delegate_->DidRedirectProvisionalLoad(
   1150       this, page_id, source_url, target_url);
   1151 }
   1152 
   1153 void RenderViewHostImpl::OnDidFailProvisionalLoadWithError(
   1154     const ViewHostMsg_DidFailProvisionalLoadWithError_Params& params) {
   1155   delegate_->DidFailProvisionalLoadWithError(this, params);
   1156 }
   1157 
   1158 // Called when the renderer navigates.  For every frame loaded, we'll get this
   1159 // notification containing parameters identifying the navigation.
   1160 //
   1161 // Subframes are identified by the page transition type.  For subframes loaded
   1162 // as part of a wider page load, the page_id will be the same as for the top
   1163 // level frame.  If the user explicitly requests a subframe navigation, we will
   1164 // get a new page_id because we need to create a new navigation entry for that
   1165 // action.
   1166 void RenderViewHostImpl::OnNavigate(const IPC::Message& msg) {
   1167   // Read the parameters out of the IPC message directly to avoid making another
   1168   // copy when we filter the URLs.
   1169   PickleIterator iter(msg);
   1170   ViewHostMsg_FrameNavigate_Params validated_params;
   1171   if (!IPC::ParamTraits<ViewHostMsg_FrameNavigate_Params>::
   1172       Read(&msg, &iter, &validated_params))
   1173     return;
   1174 
   1175   // If we're waiting for a cross-site beforeunload ack from this renderer and
   1176   // we receive a Navigate message from the main frame, then the renderer was
   1177   // navigating already and sent it before hearing the ViewMsg_Stop message.
   1178   // We do not want to cancel the pending navigation in this case, since the
   1179   // old page will soon be stopped.  Instead, treat this as a beforeunload ack
   1180   // to allow the pending navigation to continue.
   1181   if (is_waiting_for_beforeunload_ack_ &&
   1182       unload_ack_is_for_cross_site_transition_ &&
   1183       PageTransitionIsMainFrame(validated_params.transition)) {
   1184     OnShouldCloseACK(true, send_should_close_start_time_,
   1185                         base::TimeTicks::Now());
   1186     return;
   1187   }
   1188 
   1189   // If we're waiting for an unload ack from this renderer and we receive a
   1190   // Navigate message, then the renderer was navigating before it received the
   1191   // unload request.  It will either respond to the unload request soon or our
   1192   // timer will expire.  Either way, we should ignore this message, because we
   1193   // have already committed to closing this renderer.
   1194   if (is_waiting_for_unload_ack_)
   1195     return;
   1196 
   1197   // Cache the main frame id, so we can use it for creating the frame tree
   1198   // root node when needed.
   1199   if (PageTransitionIsMainFrame(validated_params.transition)) {
   1200     if (main_frame_id_ == -1) {
   1201       main_frame_id_ = validated_params.frame_id;
   1202     } else {
   1203       // TODO(nasko): We plan to remove the usage of frame_id in navigation
   1204       // and move to routing ids. This is in place to ensure that a
   1205       // renderer is not misbehaving and sending us incorrect data.
   1206       DCHECK_EQ(main_frame_id_, validated_params.frame_id);
   1207     }
   1208   }
   1209   RenderProcessHost* process = GetProcess();
   1210 
   1211   // Attempts to commit certain off-limits URL should be caught more strictly
   1212   // than our FilterURL checks below.  If a renderer violates this policy, it
   1213   // should be killed.
   1214   if (!CanCommitURL(validated_params.url)) {
   1215     VLOG(1) << "Blocked URL " << validated_params.url.spec();
   1216     validated_params.url = GURL(kAboutBlankURL);
   1217     RecordAction(UserMetricsAction("CanCommitURL_BlockedAndKilled"));
   1218     // Kills the process.
   1219     process->ReceivedBadMessage();
   1220   }
   1221 
   1222   // Now that something has committed, we don't need to track whether the
   1223   // initial page has been accessed.
   1224   has_accessed_initial_document_ = false;
   1225 
   1226   ChildProcessSecurityPolicyImpl* policy =
   1227       ChildProcessSecurityPolicyImpl::GetInstance();
   1228   // Without this check, an evil renderer can trick the browser into creating
   1229   // a navigation entry for a banned URL.  If the user clicks the back button
   1230   // followed by the forward button (or clicks reload, or round-trips through
   1231   // session restore, etc), we'll think that the browser commanded the
   1232   // renderer to load the URL and grant the renderer the privileges to request
   1233   // the URL.  To prevent this attack, we block the renderer from inserting
   1234   // banned URLs into the navigation controller in the first place.
   1235   FilterURL(policy, process, false, &validated_params.url);
   1236   FilterURL(policy, process, true, &validated_params.referrer.url);
   1237   for (std::vector<GURL>::iterator it(validated_params.redirects.begin());
   1238       it != validated_params.redirects.end(); ++it) {
   1239     FilterURL(policy, process, false, &(*it));
   1240   }
   1241   FilterURL(policy, process, true, &validated_params.searchable_form_url);
   1242   FilterURL(policy, process, true, &validated_params.password_form.origin);
   1243   FilterURL(policy, process, true, &validated_params.password_form.action);
   1244 
   1245   // Without this check, the renderer can trick the browser into using
   1246   // filenames it can't access in a future session restore.
   1247   if (!CanAccessFilesOfPageState(validated_params.page_state)) {
   1248     GetProcess()->ReceivedBadMessage();
   1249     return;
   1250   }
   1251 
   1252   delegate_->DidNavigate(this, validated_params);
   1253 }
   1254 
   1255 void RenderViewHostImpl::OnUpdateState(int32 page_id, const PageState& state) {
   1256   // Without this check, the renderer can trick the browser into using
   1257   // filenames it can't access in a future session restore.
   1258   if (!CanAccessFilesOfPageState(state)) {
   1259     GetProcess()->ReceivedBadMessage();
   1260     return;
   1261   }
   1262 
   1263   delegate_->UpdateState(this, page_id, state);
   1264 }
   1265 
   1266 void RenderViewHostImpl::OnUpdateTitle(
   1267     int32 page_id,
   1268     const string16& title,
   1269     WebKit::WebTextDirection title_direction) {
   1270   if (title.length() > kMaxTitleChars) {
   1271     NOTREACHED() << "Renderer sent too many characters in title.";
   1272     return;
   1273   }
   1274 
   1275   delegate_->UpdateTitle(this, page_id, title,
   1276                          WebTextDirectionToChromeTextDirection(
   1277                              title_direction));
   1278 }
   1279 
   1280 void RenderViewHostImpl::OnUpdateEncoding(const std::string& encoding_name) {
   1281   delegate_->UpdateEncoding(this, encoding_name);
   1282 }
   1283 
   1284 void RenderViewHostImpl::OnUpdateTargetURL(int32 page_id, const GURL& url) {
   1285   if (!is_swapped_out_)
   1286     delegate_->UpdateTargetURL(page_id, url);
   1287 
   1288   // Send a notification back to the renderer that we are ready to
   1289   // receive more target urls.
   1290   Send(new ViewMsg_UpdateTargetURL_ACK(GetRoutingID()));
   1291 }
   1292 
   1293 void RenderViewHostImpl::OnUpdateInspectorSetting(
   1294     const std::string& key, const std::string& value) {
   1295   GetContentClient()->browser()->UpdateInspectorSetting(
   1296       this, key, value);
   1297 }
   1298 
   1299 void RenderViewHostImpl::OnClose() {
   1300   // If the renderer is telling us to close, it has already run the unload
   1301   // events, and we can take the fast path.
   1302   ClosePageIgnoringUnloadEvents();
   1303 }
   1304 
   1305 void RenderViewHostImpl::OnRequestMove(const gfx::Rect& pos) {
   1306   if (!is_swapped_out_)
   1307     delegate_->RequestMove(pos);
   1308   Send(new ViewMsg_Move_ACK(GetRoutingID()));
   1309 }
   1310 
   1311 void RenderViewHostImpl::OnDidStartLoading() {
   1312   delegate_->DidStartLoading(this);
   1313 }
   1314 
   1315 void RenderViewHostImpl::OnDidStopLoading() {
   1316   delegate_->DidStopLoading(this);
   1317 }
   1318 
   1319 void RenderViewHostImpl::OnDidChangeLoadProgress(double load_progress) {
   1320   delegate_->DidChangeLoadProgress(load_progress);
   1321 }
   1322 
   1323 void RenderViewHostImpl::OnDidDisownOpener() {
   1324   delegate_->DidDisownOpener(this);
   1325 }
   1326 
   1327 void RenderViewHostImpl::OnDocumentAvailableInMainFrame() {
   1328   delegate_->DocumentAvailableInMainFrame(this);
   1329 }
   1330 
   1331 void RenderViewHostImpl::OnDocumentOnLoadCompletedInMainFrame(
   1332     int32 page_id) {
   1333   delegate_->DocumentOnLoadCompletedInMainFrame(this, page_id);
   1334 }
   1335 
   1336 void RenderViewHostImpl::OnContextMenu(const ContextMenuParams& params) {
   1337   // Validate the URLs in |params|.  If the renderer can't request the URLs
   1338   // directly, don't show them in the context menu.
   1339   ContextMenuParams validated_params(params);
   1340   RenderProcessHost* process = GetProcess();
   1341   ChildProcessSecurityPolicyImpl* policy =
   1342       ChildProcessSecurityPolicyImpl::GetInstance();
   1343 
   1344   // We don't validate |unfiltered_link_url| so that this field can be used
   1345   // when users want to copy the original link URL.
   1346   FilterURL(policy, process, true, &validated_params.link_url);
   1347   FilterURL(policy, process, true, &validated_params.src_url);
   1348   FilterURL(policy, process, false, &validated_params.page_url);
   1349   FilterURL(policy, process, true, &validated_params.frame_url);
   1350 
   1351   delegate_->ShowContextMenu(validated_params);
   1352 }
   1353 
   1354 void RenderViewHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
   1355   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   1356   delegate_->ToggleFullscreenMode(enter_fullscreen);
   1357   WasResized();
   1358 }
   1359 
   1360 void RenderViewHostImpl::OnOpenURL(
   1361     const ViewHostMsg_OpenURL_Params& params) {
   1362   GURL validated_url(params.url);
   1363   FilterURL(ChildProcessSecurityPolicyImpl::GetInstance(),
   1364             GetProcess(), false, &validated_url);
   1365 
   1366   delegate_->RequestOpenURL(
   1367       this, validated_url, params.referrer, params.disposition, params.frame_id,
   1368       params.should_replace_current_entry, params.user_gesture);
   1369 }
   1370 
   1371 void RenderViewHostImpl::OnDidContentsPreferredSizeChange(
   1372     const gfx::Size& new_size) {
   1373   delegate_->UpdatePreferredSize(new_size);
   1374 }
   1375 
   1376 void RenderViewHostImpl::OnRenderAutoResized(const gfx::Size& new_size) {
   1377   delegate_->ResizeDueToAutoResize(new_size);
   1378 }
   1379 
   1380 void RenderViewHostImpl::OnDidChangeScrollOffset() {
   1381   if (view_)
   1382     view_->ScrollOffsetChanged();
   1383 }
   1384 
   1385 void RenderViewHostImpl::OnDidChangeScrollbarsForMainFrame(
   1386     bool has_horizontal_scrollbar, bool has_vertical_scrollbar) {
   1387   if (view_)
   1388     view_->SetHasHorizontalScrollbar(has_horizontal_scrollbar);
   1389 }
   1390 
   1391 void RenderViewHostImpl::OnDidChangeScrollOffsetPinningForMainFrame(
   1392     bool is_pinned_to_left, bool is_pinned_to_right) {
   1393   if (view_)
   1394     view_->SetScrollOffsetPinning(is_pinned_to_left, is_pinned_to_right);
   1395 }
   1396 
   1397 void RenderViewHostImpl::OnDidChangeNumWheelEvents(int count) {
   1398 }
   1399 
   1400 void RenderViewHostImpl::OnSelectionChanged(const string16& text,
   1401                                             size_t offset,
   1402                                             const ui::Range& range) {
   1403   if (view_)
   1404     view_->SelectionChanged(text, offset, range);
   1405 }
   1406 
   1407 void RenderViewHostImpl::OnSelectionBoundsChanged(
   1408     const ViewHostMsg_SelectionBounds_Params& params) {
   1409   if (view_) {
   1410     view_->SelectionBoundsChanged(params);
   1411   }
   1412 }
   1413 
   1414 void RenderViewHostImpl::OnRouteCloseEvent() {
   1415   // Have the delegate route this to the active RenderViewHost.
   1416   delegate_->RouteCloseEvent(this);
   1417 }
   1418 
   1419 void RenderViewHostImpl::OnRouteMessageEvent(
   1420     const ViewMsg_PostMessage_Params& params) {
   1421   // Give to the delegate to route to the active RenderViewHost.
   1422   delegate_->RouteMessageEvent(this, params);
   1423 }
   1424 
   1425 void RenderViewHostImpl::OnRunJavaScriptMessage(
   1426     const string16& message,
   1427     const string16& default_prompt,
   1428     const GURL& frame_url,
   1429     JavaScriptMessageType type,
   1430     IPC::Message* reply_msg) {
   1431   // While a JS message dialog is showing, tabs in the same process shouldn't
   1432   // process input events.
   1433   GetProcess()->SetIgnoreInputEvents(true);
   1434   StopHangMonitorTimeout();
   1435   delegate_->RunJavaScriptMessage(this, message, default_prompt, frame_url,
   1436                                   type, reply_msg,
   1437                                   &are_javascript_messages_suppressed_);
   1438 }
   1439 
   1440 void RenderViewHostImpl::OnRunBeforeUnloadConfirm(const GURL& frame_url,
   1441                                                   const string16& message,
   1442                                                   bool is_reload,
   1443                                                   IPC::Message* reply_msg) {
   1444   // While a JS before unload dialog is showing, tabs in the same process
   1445   // shouldn't process input events.
   1446   GetProcess()->SetIgnoreInputEvents(true);
   1447   StopHangMonitorTimeout();
   1448   delegate_->RunBeforeUnloadConfirm(this, message, is_reload, reply_msg);
   1449 }
   1450 
   1451 void RenderViewHostImpl::OnStartDragging(
   1452     const DropData& drop_data,
   1453     WebDragOperationsMask drag_operations_mask,
   1454     const SkBitmap& bitmap,
   1455     const gfx::Vector2d& bitmap_offset_in_dip,
   1456     const DragEventSourceInfo& event_info) {
   1457   RenderViewHostDelegateView* view = delegate_->GetDelegateView();
   1458   if (!view)
   1459     return;
   1460 
   1461   DropData filtered_data(drop_data);
   1462   RenderProcessHost* process = GetProcess();
   1463   ChildProcessSecurityPolicyImpl* policy =
   1464       ChildProcessSecurityPolicyImpl::GetInstance();
   1465 
   1466   // Allow drag of Javascript URLs to enable bookmarklet drag to bookmark bar.
   1467   if (!filtered_data.url.SchemeIs(chrome::kJavaScriptScheme))
   1468     FilterURL(policy, process, true, &filtered_data.url);
   1469   FilterURL(policy, process, false, &filtered_data.html_base_url);
   1470   // Filter out any paths that the renderer didn't have access to. This prevents
   1471   // the following attack on a malicious renderer:
   1472   // 1. StartDragging IPC sent with renderer-specified filesystem paths that it
   1473   //    doesn't have read permissions for.
   1474   // 2. We initiate a native DnD operation.
   1475   // 3. DnD operation immediately ends since mouse is not held down. DnD events
   1476   //    still fire though, which causes read permissions to be granted to the
   1477   //    renderer for any file paths in the drop.
   1478   filtered_data.filenames.clear();
   1479   for (std::vector<DropData::FileInfo>::const_iterator it =
   1480            drop_data.filenames.begin();
   1481        it != drop_data.filenames.end(); ++it) {
   1482     base::FilePath path(base::FilePath::FromUTF8Unsafe(UTF16ToUTF8(it->path)));
   1483     if (policy->CanReadFile(GetProcess()->GetID(), path))
   1484       filtered_data.filenames.push_back(*it);
   1485   }
   1486   ui::ScaleFactor scale_factor = GetScaleFactorForView(GetView());
   1487   gfx::ImageSkia image(gfx::ImageSkiaRep(bitmap, scale_factor));
   1488   view->StartDragging(filtered_data, drag_operations_mask, image,
   1489       bitmap_offset_in_dip, event_info);
   1490 }
   1491 
   1492 void RenderViewHostImpl::OnUpdateDragCursor(WebDragOperation current_op) {
   1493   RenderViewHostDelegateView* view = delegate_->GetDelegateView();
   1494   if (view)
   1495     view->UpdateDragCursor(current_op);
   1496 }
   1497 
   1498 void RenderViewHostImpl::OnTargetDropACK() {
   1499   NotificationService::current()->Notify(
   1500       NOTIFICATION_RENDER_VIEW_HOST_DID_RECEIVE_DRAG_TARGET_DROP_ACK,
   1501       Source<RenderViewHost>(this),
   1502       NotificationService::NoDetails());
   1503 }
   1504 
   1505 void RenderViewHostImpl::OnTakeFocus(bool reverse) {
   1506   RenderViewHostDelegateView* view = delegate_->GetDelegateView();
   1507   if (view)
   1508     view->TakeFocus(reverse);
   1509 }
   1510 
   1511 void RenderViewHostImpl::OnFocusedNodeChanged(bool is_editable_node) {
   1512   NotificationService::current()->Notify(
   1513       NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
   1514       Source<RenderViewHost>(this),
   1515       Details<const bool>(&is_editable_node));
   1516 }
   1517 
   1518 void RenderViewHostImpl::OnAddMessageToConsole(
   1519     int32 level,
   1520     const string16& message,
   1521     int32 line_no,
   1522     const string16& source_id) {
   1523   if (delegate_->AddMessageToConsole(level, message, line_no, source_id))
   1524     return;
   1525   // Pass through log level only on WebUI pages to limit console spew.
   1526   int32 resolved_level = HasWebUIScheme(delegate_->GetURL()) ? level : 0;
   1527 
   1528   if (resolved_level >= ::logging::GetMinLogLevel()) {
   1529     logging::LogMessage("CONSOLE", line_no, resolved_level).stream() << "\"" <<
   1530         message << "\", source: " << source_id << " (" << line_no << ")";
   1531   }
   1532 }
   1533 
   1534 void RenderViewHostImpl::AddObserver(RenderViewHostObserver* observer) {
   1535   observers_.AddObserver(observer);
   1536 }
   1537 
   1538 void RenderViewHostImpl::RemoveObserver(RenderViewHostObserver* observer) {
   1539   observers_.RemoveObserver(observer);
   1540 }
   1541 
   1542 void RenderViewHostImpl::OnUserGesture() {
   1543   delegate_->OnUserGesture();
   1544 }
   1545 
   1546 void RenderViewHostImpl::OnShouldCloseACK(
   1547     bool proceed,
   1548     const base::TimeTicks& renderer_before_unload_start_time,
   1549     const base::TimeTicks& renderer_before_unload_end_time) {
   1550   decrement_in_flight_event_count();
   1551   StopHangMonitorTimeout();
   1552   // If this renderer navigated while the beforeunload request was in flight, we
   1553   // may have cleared this state in OnNavigate, in which case we can ignore
   1554   // this message.
   1555   if (!is_waiting_for_beforeunload_ack_ || is_swapped_out_)
   1556     return;
   1557 
   1558   is_waiting_for_beforeunload_ack_ = false;
   1559 
   1560   RenderViewHostDelegate::RendererManagement* management_delegate =
   1561       delegate_->GetRendererManagementDelegate();
   1562   if (management_delegate) {
   1563     base::TimeTicks before_unload_end_time;
   1564     if (!send_should_close_start_time_.is_null() &&
   1565         !renderer_before_unload_start_time.is_null() &&
   1566         !renderer_before_unload_end_time.is_null()) {
   1567       // When passing TimeTicks across process boundaries, we need to compensate
   1568       // for any skew between the processes. Here we are converting the
   1569       // renderer's notion of before_unload_end_time to TimeTicks in the browser
   1570       // process. See comments in inter_process_time_ticks_converter.h for more.
   1571       InterProcessTimeTicksConverter converter(
   1572           LocalTimeTicks::FromTimeTicks(send_should_close_start_time_),
   1573           LocalTimeTicks::FromTimeTicks(base::TimeTicks::Now()),
   1574           RemoteTimeTicks::FromTimeTicks(renderer_before_unload_start_time),
   1575           RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
   1576       LocalTimeTicks browser_before_unload_end_time =
   1577           converter.ToLocalTimeTicks(
   1578               RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
   1579       before_unload_end_time = browser_before_unload_end_time.ToTimeTicks();
   1580     }
   1581     management_delegate->ShouldClosePage(
   1582         unload_ack_is_for_cross_site_transition_, proceed,
   1583         before_unload_end_time);
   1584   }
   1585 
   1586   // If canceled, notify the delegate to cancel its pending navigation entry.
   1587   if (!proceed)
   1588     delegate_->DidCancelLoading();
   1589 }
   1590 
   1591 void RenderViewHostImpl::OnClosePageACK() {
   1592   decrement_in_flight_event_count();
   1593   ClosePageIgnoringUnloadEvents();
   1594 }
   1595 
   1596 void RenderViewHostImpl::NotifyRendererUnresponsive() {
   1597   delegate_->RendererUnresponsive(
   1598       this, is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_);
   1599 }
   1600 
   1601 void RenderViewHostImpl::NotifyRendererResponsive() {
   1602   delegate_->RendererResponsive(this);
   1603 }
   1604 
   1605 void RenderViewHostImpl::RequestToLockMouse(bool user_gesture,
   1606                                             bool last_unlocked_by_target) {
   1607   delegate_->RequestToLockMouse(user_gesture, last_unlocked_by_target);
   1608 }
   1609 
   1610 bool RenderViewHostImpl::IsFullscreen() const {
   1611   return delegate_->IsFullscreenForCurrentTab();
   1612 }
   1613 
   1614 void RenderViewHostImpl::OnFocus() {
   1615   // Note: We allow focus and blur from swapped out RenderViewHosts, even when
   1616   // the active RenderViewHost is in a different BrowsingInstance (e.g., WebUI).
   1617   delegate_->Activate();
   1618 }
   1619 
   1620 void RenderViewHostImpl::OnBlur() {
   1621   delegate_->Deactivate();
   1622 }
   1623 
   1624 gfx::Rect RenderViewHostImpl::GetRootWindowResizerRect() const {
   1625   return delegate_->GetRootWindowResizerRect();
   1626 }
   1627 
   1628 void RenderViewHostImpl::ForwardMouseEvent(
   1629     const WebKit::WebMouseEvent& mouse_event) {
   1630 
   1631   // We make a copy of the mouse event because
   1632   // RenderWidgetHost::ForwardMouseEvent will delete |mouse_event|.
   1633   WebKit::WebMouseEvent event_copy(mouse_event);
   1634   RenderWidgetHostImpl::ForwardMouseEvent(event_copy);
   1635 
   1636   switch (event_copy.type) {
   1637     case WebInputEvent::MouseMove:
   1638       delegate_->HandleMouseMove();
   1639       break;
   1640     case WebInputEvent::MouseLeave:
   1641       delegate_->HandleMouseLeave();
   1642       break;
   1643     case WebInputEvent::MouseDown:
   1644       delegate_->HandleMouseDown();
   1645       break;
   1646     case WebInputEvent::MouseWheel:
   1647       if (ignore_input_events())
   1648         delegate_->OnIgnoredUIEvent();
   1649       break;
   1650     case WebInputEvent::MouseUp:
   1651       delegate_->HandleMouseUp();
   1652     default:
   1653       // For now, we don't care about the rest.
   1654       break;
   1655   }
   1656 }
   1657 
   1658 void RenderViewHostImpl::OnPointerEventActivate() {
   1659   delegate_->HandlePointerActivate();
   1660 }
   1661 
   1662 void RenderViewHostImpl::ForwardKeyboardEvent(
   1663     const NativeWebKeyboardEvent& key_event) {
   1664   if (ignore_input_events()) {
   1665     if (key_event.type == WebInputEvent::RawKeyDown)
   1666       delegate_->OnIgnoredUIEvent();
   1667     return;
   1668   }
   1669   RenderWidgetHostImpl::ForwardKeyboardEvent(key_event);
   1670 }
   1671 
   1672 #if defined(OS_ANDROID)
   1673 void RenderViewHostImpl::DidSelectPopupMenuItems(
   1674     const std::vector<int>& selected_indices) {
   1675   Send(new ViewMsg_SelectPopupMenuItems(GetRoutingID(), false,
   1676                                         selected_indices));
   1677 }
   1678 
   1679 void RenderViewHostImpl::DidCancelPopupMenu() {
   1680   Send(new ViewMsg_SelectPopupMenuItems(GetRoutingID(), true,
   1681                                         std::vector<int>()));
   1682 }
   1683 #endif
   1684 
   1685 #if defined(OS_MACOSX)
   1686 void RenderViewHostImpl::DidSelectPopupMenuItem(int selected_index) {
   1687   Send(new ViewMsg_SelectPopupMenuItem(GetRoutingID(), selected_index));
   1688 }
   1689 
   1690 void RenderViewHostImpl::DidCancelPopupMenu() {
   1691   Send(new ViewMsg_SelectPopupMenuItem(GetRoutingID(), -1));
   1692 }
   1693 #endif
   1694 
   1695 void RenderViewHostImpl::SendOrientationChangeEvent(int orientation) {
   1696   Send(new ViewMsg_OrientationChangeEvent(GetRoutingID(), orientation));
   1697 }
   1698 
   1699 void RenderViewHostImpl::ToggleSpeechInput() {
   1700   Send(new InputTagSpeechMsg_ToggleSpeechInput(GetRoutingID()));
   1701 }
   1702 
   1703 bool RenderViewHostImpl::CanCommitURL(const GURL& url) {
   1704   // TODO(creis): We should also check for WebUI pages here.  Also, when the
   1705   // out-of-process iframes implementation is ready, we should check for
   1706   // cross-site URLs that are not allowed to commit in this process.
   1707 
   1708   // Give the client a chance to disallow URLs from committing.
   1709   return GetContentClient()->browser()->CanCommitURL(GetProcess(), url);
   1710 }
   1711 
   1712 void RenderViewHostImpl::FilterURL(ChildProcessSecurityPolicyImpl* policy,
   1713                                    const RenderProcessHost* process,
   1714                                    bool empty_allowed,
   1715                                    GURL* url) {
   1716   if (empty_allowed && url->is_empty())
   1717     return;
   1718 
   1719   // The browser process should never hear the swappedout:// URL from any
   1720   // of the renderer's messages.  Check for this in debug builds, but don't
   1721   // let it crash a release browser.
   1722   DCHECK(GURL(kSwappedOutURL) != *url);
   1723 
   1724   if (!url->is_valid()) {
   1725     // Have to use about:blank for the denied case, instead of an empty GURL.
   1726     // This is because the browser treats navigation to an empty GURL as a
   1727     // navigation to the home page. This is often a privileged page
   1728     // (chrome://newtab/) which is exactly what we don't want.
   1729     *url = GURL(kAboutBlankURL);
   1730     RecordAction(UserMetricsAction("FilterURLTermiate_Invalid"));
   1731     return;
   1732   }
   1733 
   1734   if (url->SchemeIs(chrome::kAboutScheme)) {
   1735     // The renderer treats all URLs in the about: scheme as being about:blank.
   1736     // Canonicalize about: URLs to about:blank.
   1737     *url = GURL(kAboutBlankURL);
   1738     RecordAction(UserMetricsAction("FilterURLTermiate_About"));
   1739   }
   1740 
   1741   // Do not allow browser plugin guests to navigate to non-web URLs, since they
   1742   // cannot swap processes or grant bindings.
   1743   bool non_web_url_in_guest = process->IsGuest() &&
   1744       !(url->is_valid() && policy->IsWebSafeScheme(url->scheme()));
   1745 
   1746   if (non_web_url_in_guest || !policy->CanRequestURL(process->GetID(), *url)) {
   1747     // If this renderer is not permitted to request this URL, we invalidate the
   1748     // URL.  This prevents us from storing the blocked URL and becoming confused
   1749     // later.
   1750     VLOG(1) << "Blocked URL " << url->spec();
   1751     *url = GURL(kAboutBlankURL);
   1752     RecordAction(UserMetricsAction("FilterURLTermiate_Blocked"));
   1753   }
   1754 }
   1755 
   1756 void RenderViewHost::AddCreatedCallback(const CreatedCallback& callback) {
   1757   g_created_callbacks.Get().push_back(callback);
   1758 }
   1759 
   1760 void RenderViewHost::RemoveCreatedCallback(const CreatedCallback& callback) {
   1761   for (size_t i = 0; i < g_created_callbacks.Get().size(); ++i) {
   1762     if (g_created_callbacks.Get().at(i).Equals(callback)) {
   1763       g_created_callbacks.Get().erase(g_created_callbacks.Get().begin() + i);
   1764       return;
   1765     }
   1766   }
   1767 }
   1768 
   1769 void RenderViewHostImpl::SetAltErrorPageURL(const GURL& url) {
   1770   Send(new ViewMsg_SetAltErrorPageURL(GetRoutingID(), url));
   1771 }
   1772 
   1773 void RenderViewHostImpl::ExitFullscreen() {
   1774   RejectMouseLockOrUnlockIfNecessary();
   1775   // We need to notify the contents that its fullscreen state has changed. This
   1776   // is done as part of the resize message.
   1777   WasResized();
   1778 }
   1779 
   1780 WebPreferences RenderViewHostImpl::GetWebkitPreferences() {
   1781   return delegate_->GetWebkitPrefs();
   1782 }
   1783 
   1784 void RenderViewHostImpl::DisownOpener() {
   1785   // This should only be called when swapped out.
   1786   DCHECK(is_swapped_out_);
   1787 
   1788   Send(new ViewMsg_DisownOpener(GetRoutingID()));
   1789 }
   1790 
   1791 void RenderViewHostImpl::SetAccessibilityCallbackForTesting(
   1792     const base::Callback<void(AccessibilityNotification)>& callback) {
   1793   accessibility_testing_callback_ = callback;
   1794 }
   1795 
   1796 void RenderViewHostImpl::UpdateWebkitPreferences(const WebPreferences& prefs) {
   1797   Send(new ViewMsg_UpdateWebPreferences(GetRoutingID(), prefs));
   1798 }
   1799 
   1800 void RenderViewHostImpl::NotifyTimezoneChange() {
   1801   Send(new ViewMsg_TimezoneChange(GetRoutingID()));
   1802 }
   1803 
   1804 void RenderViewHostImpl::ClearFocusedNode() {
   1805   Send(new ViewMsg_ClearFocusedNode(GetRoutingID()));
   1806 }
   1807 
   1808 void RenderViewHostImpl::SetZoomLevel(double level) {
   1809   Send(new ViewMsg_SetZoomLevel(GetRoutingID(), level));
   1810 }
   1811 
   1812 void RenderViewHostImpl::Zoom(PageZoom zoom) {
   1813   Send(new ViewMsg_Zoom(GetRoutingID(), zoom));
   1814 }
   1815 
   1816 void RenderViewHostImpl::ReloadFrame() {
   1817   Send(new ViewMsg_ReloadFrame(GetRoutingID()));
   1818 }
   1819 
   1820 void RenderViewHostImpl::Find(int request_id,
   1821                               const string16& search_text,
   1822                               const WebKit::WebFindOptions& options) {
   1823   Send(new ViewMsg_Find(GetRoutingID(), request_id, search_text, options));
   1824 }
   1825 
   1826 void RenderViewHostImpl::InsertCSS(const string16& frame_xpath,
   1827                                    const std::string& css) {
   1828   Send(new ViewMsg_CSSInsertRequest(GetRoutingID(), frame_xpath, css));
   1829 }
   1830 
   1831 void RenderViewHostImpl::DisableScrollbarsForThreshold(const gfx::Size& size) {
   1832   Send(new ViewMsg_DisableScrollbarsForSmallWindows(GetRoutingID(), size));
   1833 }
   1834 
   1835 void RenderViewHostImpl::EnablePreferredSizeMode() {
   1836   Send(new ViewMsg_EnablePreferredSizeChangedMode(GetRoutingID()));
   1837 }
   1838 
   1839 void RenderViewHostImpl::EnableAutoResize(const gfx::Size& min_size,
   1840                                           const gfx::Size& max_size) {
   1841   SetShouldAutoResize(true);
   1842   Send(new ViewMsg_EnableAutoResize(GetRoutingID(), min_size, max_size));
   1843 }
   1844 
   1845 void RenderViewHostImpl::DisableAutoResize(const gfx::Size& new_size) {
   1846   SetShouldAutoResize(false);
   1847   Send(new ViewMsg_DisableAutoResize(GetRoutingID(), new_size));
   1848 }
   1849 
   1850 void RenderViewHostImpl::ExecuteCustomContextMenuCommand(
   1851     int action, const CustomContextMenuContext& context) {
   1852   Send(new ViewMsg_CustomContextMenuAction(GetRoutingID(), context, action));
   1853 }
   1854 
   1855 void RenderViewHostImpl::NotifyContextMenuClosed(
   1856     const CustomContextMenuContext& context) {
   1857   Send(new ViewMsg_ContextMenuClosed(GetRoutingID(), context));
   1858 }
   1859 
   1860 void RenderViewHostImpl::CopyImageAt(int x, int y) {
   1861   Send(new ViewMsg_CopyImageAt(GetRoutingID(), x, y));
   1862 }
   1863 
   1864 void RenderViewHostImpl::ExecuteMediaPlayerActionAtLocation(
   1865   const gfx::Point& location, const WebKit::WebMediaPlayerAction& action) {
   1866   Send(new ViewMsg_MediaPlayerActionAt(GetRoutingID(), location, action));
   1867 }
   1868 
   1869 void RenderViewHostImpl::ExecutePluginActionAtLocation(
   1870   const gfx::Point& location, const WebKit::WebPluginAction& action) {
   1871   Send(new ViewMsg_PluginActionAt(GetRoutingID(), location, action));
   1872 }
   1873 
   1874 void RenderViewHostImpl::DisassociateFromPopupCount() {
   1875   Send(new ViewMsg_DisassociateFromPopupCount(GetRoutingID()));
   1876 }
   1877 
   1878 void RenderViewHostImpl::NotifyMoveOrResizeStarted() {
   1879   Send(new ViewMsg_MoveOrResizeStarted(GetRoutingID()));
   1880 }
   1881 
   1882 void RenderViewHostImpl::StopFinding(StopFindAction action) {
   1883   Send(new ViewMsg_StopFinding(GetRoutingID(), action));
   1884 }
   1885 
   1886 void RenderViewHostImpl::OnAccessibilityNotifications(
   1887     const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
   1888   if (view_ && !is_swapped_out_)
   1889     view_->OnAccessibilityNotifications(params);
   1890 
   1891   // Always send an ACK or the renderer can be in a bad state.
   1892   Send(new AccessibilityMsg_Notifications_ACK(GetRoutingID()));
   1893 
   1894   // The rest of this code is just for testing; bail out if we're not
   1895   // in that mode.
   1896   if (accessibility_testing_callback_.is_null())
   1897     return;
   1898 
   1899   for (unsigned i = 0; i < params.size(); i++) {
   1900     const AccessibilityHostMsg_NotificationParams& param = params[i];
   1901     AccessibilityNotification src_type = param.notification_type;
   1902     if (src_type == AccessibilityNotificationLayoutComplete ||
   1903         src_type == AccessibilityNotificationLoadComplete) {
   1904       MakeAccessibilityNodeDataTree(param.nodes, &accessibility_tree_);
   1905     }
   1906     accessibility_testing_callback_.Run(src_type);
   1907   }
   1908 }
   1909 
   1910 void RenderViewHostImpl::OnScriptEvalResponse(int id,
   1911                                               const base::ListValue& result) {
   1912   const base::Value* result_value;
   1913   if (!result.Get(0, &result_value)) {
   1914     // Programming error or rogue renderer.
   1915     NOTREACHED() << "Got bad arguments for OnScriptEvalResponse";
   1916     return;
   1917   }
   1918 
   1919   std::map<int, JavascriptResultCallback>::iterator it =
   1920       javascript_callbacks_.find(id);
   1921   if (it != javascript_callbacks_.end()) {
   1922     // ExecuteJavascriptInWebFrameCallbackResult was used; do callback.
   1923     it->second.Run(result_value);
   1924     javascript_callbacks_.erase(it);
   1925   } else {
   1926     NOTREACHED() << "Received script response for unknown request";
   1927   }
   1928 }
   1929 
   1930 void RenderViewHostImpl::OnDidZoomURL(double zoom_level,
   1931                                       bool remember,
   1932                                       const GURL& url) {
   1933   HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
   1934       HostZoomMap::GetForBrowserContext(GetProcess()->GetBrowserContext()));
   1935   if (remember) {
   1936     host_zoom_map->
   1937         SetZoomLevelForHost(net::GetHostOrSpecFromURL(url), zoom_level);
   1938   } else {
   1939     host_zoom_map->SetTemporaryZoomLevel(
   1940         GetProcess()->GetID(), GetRoutingID(), zoom_level);
   1941   }
   1942 }
   1943 
   1944 void RenderViewHostImpl::OnRequestDesktopNotificationPermission(
   1945     const GURL& source_origin, int callback_context) {
   1946   GetContentClient()->browser()->RequestDesktopNotificationPermission(
   1947       source_origin, callback_context, GetProcess()->GetID(), GetRoutingID());
   1948 }
   1949 
   1950 void RenderViewHostImpl::OnShowDesktopNotification(
   1951     const ShowDesktopNotificationHostMsgParams& params) {
   1952   // Disallow HTML notifications from javascript: and file: schemes as this
   1953   // allows unwanted cross-domain access.
   1954   GURL url = params.contents_url;
   1955   if (params.is_html &&
   1956       (url.SchemeIs(chrome::kJavaScriptScheme) ||
   1957        url.SchemeIs(chrome::kFileScheme))) {
   1958     return;
   1959   }
   1960 
   1961   GetContentClient()->browser()->ShowDesktopNotification(
   1962       params, GetProcess()->GetID(), GetRoutingID(), false);
   1963 }
   1964 
   1965 void RenderViewHostImpl::OnCancelDesktopNotification(int notification_id) {
   1966   GetContentClient()->browser()->CancelDesktopNotification(
   1967       GetProcess()->GetID(), GetRoutingID(), notification_id);
   1968 }
   1969 
   1970 void RenderViewHostImpl::OnRunFileChooser(const FileChooserParams& params) {
   1971   delegate_->RunFileChooser(this, params);
   1972 }
   1973 
   1974 void RenderViewHostImpl::OnDidAccessInitialDocument() {
   1975   has_accessed_initial_document_ = true;
   1976   delegate_->DidAccessInitialDocument();
   1977 }
   1978 
   1979 void RenderViewHostImpl::OnDomOperationResponse(
   1980     const std::string& json_string, int automation_id) {
   1981   DomOperationNotificationDetails details(json_string, automation_id);
   1982   NotificationService::current()->Notify(
   1983       NOTIFICATION_DOM_OPERATION_RESPONSE,
   1984       Source<RenderViewHost>(this),
   1985       Details<DomOperationNotificationDetails>(&details));
   1986 }
   1987 
   1988 void RenderViewHostImpl::OnGetWindowSnapshot(const int snapshot_id) {
   1989   std::vector<unsigned char> png;
   1990 
   1991   // This feature is behind the kEnableGpuBenchmarking command line switch
   1992   // because it poses security concerns and should only be used for testing.
   1993   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
   1994   if (command_line.HasSwitch(switches::kEnableGpuBenchmarking)) {
   1995     gfx::Rect view_bounds = GetView()->GetViewBounds();
   1996     gfx::Rect snapshot_bounds(view_bounds.size());
   1997     gfx::Size snapshot_size = snapshot_bounds.size();
   1998 
   1999     if (ui::GrabViewSnapshot(GetView()->GetNativeView(),
   2000                              &png, snapshot_bounds)) {
   2001       Send(new ViewMsg_WindowSnapshotCompleted(
   2002           GetRoutingID(), snapshot_id, snapshot_size, png));
   2003       return;
   2004     }
   2005   }
   2006 
   2007   Send(new ViewMsg_WindowSnapshotCompleted(
   2008       GetRoutingID(), snapshot_id, gfx::Size(), png));
   2009 }
   2010 
   2011 #if defined(OS_MACOSX) || defined(OS_ANDROID)
   2012 void RenderViewHostImpl::OnShowPopup(
   2013     const ViewHostMsg_ShowPopup_Params& params) {
   2014   RenderViewHostDelegateView* view = delegate_->GetDelegateView();
   2015   if (view) {
   2016     view->ShowPopupMenu(params.bounds,
   2017                         params.item_height,
   2018                         params.item_font_size,
   2019                         params.selected_item,
   2020                         params.popup_items,
   2021                         params.right_aligned,
   2022                         params.allow_multiple_selection);
   2023   }
   2024 }
   2025 #endif
   2026 
   2027 void RenderViewHostImpl::SetSwappedOut(bool is_swapped_out) {
   2028   // We update the number of RenderViews in a SiteInstance when the
   2029   // swapped out status of this RenderView gets flipped.
   2030   if (is_swapped_out_ && !is_swapped_out)
   2031     instance_->increment_active_view_count();
   2032   else if (!is_swapped_out_ && is_swapped_out)
   2033     instance_->decrement_active_view_count();
   2034 
   2035   is_swapped_out_ = is_swapped_out;
   2036 
   2037   // Whenever we change swap out state, we should not be waiting for
   2038   // beforeunload or unload acks.  We clear them here to be safe, since they
   2039   // can cause navigations to be ignored in OnNavigate.
   2040   is_waiting_for_beforeunload_ack_ = false;
   2041   is_waiting_for_unload_ack_ = false;
   2042   has_timed_out_on_unload_ = false;
   2043 }
   2044 
   2045 bool RenderViewHostImpl::CanAccessFilesOfPageState(
   2046     const PageState& state) const {
   2047   ChildProcessSecurityPolicyImpl* policy =
   2048       ChildProcessSecurityPolicyImpl::GetInstance();
   2049 
   2050   const std::vector<base::FilePath>& file_paths = state.GetReferencedFiles();
   2051   for (std::vector<base::FilePath>::const_iterator file = file_paths.begin();
   2052        file != file_paths.end(); ++file) {
   2053     if (!policy->CanReadFile(GetProcess()->GetID(), *file))
   2054       return false;
   2055   }
   2056   return true;
   2057 }
   2058 
   2059 }  // namespace content
   2060