Home | History | Annotate | Download | only in web_contents
      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/web_contents/web_contents_impl.h"
      6 
      7 #include <utility>
      8 
      9 #include "base/command_line.h"
     10 #include "base/debug/trace_event.h"
     11 #include "base/lazy_instance.h"
     12 #include "base/logging.h"
     13 #include "base/metrics/histogram.h"
     14 #include "base/metrics/stats_counters.h"
     15 #include "base/process/process.h"
     16 #include "base/strings/string16.h"
     17 #include "base/strings/string_number_conversions.h"
     18 #include "base/strings/string_util.h"
     19 #include "base/strings/utf_string_conversions.h"
     20 #include "base/time/time.h"
     21 #include "content/browser/accessibility/accessibility_mode_helper.h"
     22 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
     23 #include "content/browser/browser_plugin/browser_plugin_embedder.h"
     24 #include "content/browser/browser_plugin/browser_plugin_guest.h"
     25 #include "content/browser/child_process_security_policy_impl.h"
     26 #include "content/browser/devtools/render_view_devtools_agent_host.h"
     27 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
     28 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
     29 #include "content/browser/download/download_stats.h"
     30 #include "content/browser/download/mhtml_generation_manager.h"
     31 #include "content/browser/download/save_package.h"
     32 #include "content/browser/frame_host/cross_process_frame_connector.h"
     33 #include "content/browser/frame_host/interstitial_page_impl.h"
     34 #include "content/browser/frame_host/navigation_entry_impl.h"
     35 #include "content/browser/frame_host/navigator_impl.h"
     36 #include "content/browser/frame_host/render_frame_host_impl.h"
     37 #include "content/browser/frame_host/render_widget_host_view_child_frame.h"
     38 #include "content/browser/geolocation/geolocation_dispatcher_host.h"
     39 #include "content/browser/host_zoom_map_impl.h"
     40 #include "content/browser/loader/resource_dispatcher_host_impl.h"
     41 #include "content/browser/manifest/manifest_manager_host.h"
     42 #include "content/browser/media/audio_stream_monitor.h"
     43 #include "content/browser/media/capture/web_contents_audio_muter.h"
     44 #include "content/browser/media/midi_dispatcher_host.h"
     45 #include "content/browser/message_port_message_filter.h"
     46 #include "content/browser/message_port_service.h"
     47 #include "content/browser/power_save_blocker_impl.h"
     48 #include "content/browser/renderer_host/render_process_host_impl.h"
     49 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
     50 #include "content/browser/renderer_host/render_view_host_impl.h"
     51 #include "content/browser/renderer_host/render_widget_host_impl.h"
     52 #include "content/browser/renderer_host/render_widget_host_view_base.h"
     53 #include "content/browser/screen_orientation/screen_orientation_dispatcher_host_impl.h"
     54 #include "content/browser/site_instance_impl.h"
     55 #include "content/browser/web_contents/web_contents_view_guest.h"
     56 #include "content/browser/webui/generic_handler.h"
     57 #include "content/browser/webui/web_ui_controller_factory_registry.h"
     58 #include "content/browser/webui/web_ui_impl.h"
     59 #include "content/common/browser_plugin/browser_plugin_constants.h"
     60 #include "content/common/browser_plugin/browser_plugin_messages.h"
     61 #include "content/common/frame_messages.h"
     62 #include "content/common/image_messages.h"
     63 #include "content/common/input_messages.h"
     64 #include "content/common/ssl_status_serialization.h"
     65 #include "content/common/view_messages.h"
     66 #include "content/public/browser/ax_event_notification_details.h"
     67 #include "content/public/browser/browser_context.h"
     68 #include "content/public/browser/browser_plugin_guest_manager.h"
     69 #include "content/public/browser/content_browser_client.h"
     70 #include "content/public/browser/devtools_agent_host.h"
     71 #include "content/public/browser/download_manager.h"
     72 #include "content/public/browser/download_url_parameters.h"
     73 #include "content/public/browser/invalidate_type.h"
     74 #include "content/public/browser/javascript_dialog_manager.h"
     75 #include "content/public/browser/load_from_memory_cache_details.h"
     76 #include "content/public/browser/load_notification_details.h"
     77 #include "content/public/browser/navigation_details.h"
     78 #include "content/public/browser/notification_details.h"
     79 #include "content/public/browser/notification_service.h"
     80 #include "content/public/browser/render_widget_host_iterator.h"
     81 #include "content/public/browser/resource_request_details.h"
     82 #include "content/public/browser/screen_orientation_dispatcher_host.h"
     83 #include "content/public/browser/storage_partition.h"
     84 #include "content/public/browser/user_metrics.h"
     85 #include "content/public/browser/web_contents_delegate.h"
     86 #include "content/public/browser/web_contents_observer.h"
     87 #include "content/public/common/bindings_policy.h"
     88 #include "content/public/common/content_constants.h"
     89 #include "content/public/common/content_switches.h"
     90 #include "content/public/common/page_zoom.h"
     91 #include "content/public/common/result_codes.h"
     92 #include "content/public/common/url_constants.h"
     93 #include "content/public/common/url_utils.h"
     94 #include "content/public/common/web_preferences.h"
     95 #include "net/base/mime_util.h"
     96 #include "net/base/net_util.h"
     97 #include "net/http/http_cache.h"
     98 #include "net/http/http_transaction_factory.h"
     99 #include "net/url_request/url_request_context.h"
    100 #include "net/url_request/url_request_context_getter.h"
    101 #include "ui/base/layout.h"
    102 #include "ui/gfx/display.h"
    103 #include "ui/gfx/screen.h"
    104 #include "ui/gl/gl_switches.h"
    105 
    106 #if defined(OS_ANDROID)
    107 #include "content/browser/android/content_view_core_impl.h"
    108 #include "content/browser/android/date_time_chooser_android.h"
    109 #include "content/browser/media/android/browser_media_player_manager.h"
    110 #include "content/browser/web_contents/web_contents_android.h"
    111 #include "content/public/browser/android/content_view_core.h"
    112 #endif
    113 
    114 #if defined(OS_MACOSX)
    115 #include "base/mac/foundation_util.h"
    116 #endif
    117 
    118 // Cross-Site Navigations
    119 //
    120 // If a WebContentsImpl is told to navigate to a different web site (as
    121 // determined by SiteInstance), it will replace its current RenderViewHost with
    122 // a new RenderViewHost dedicated to the new SiteInstance.  This works as
    123 // follows:
    124 //
    125 // - RVHM::Navigate determines whether the destination is cross-site, and if so,
    126 //   it creates a pending_render_view_host_.
    127 // - The pending RVH is "suspended," so that no navigation messages are sent to
    128 //   its renderer until the beforeunload JavaScript handler has a chance to
    129 //   run in the current RVH.
    130 // - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton)
    131 //   that it has a pending cross-site request.  We will check this on the IO
    132 //   thread when deciding how to handle the response.
    133 // - The current RVH runs its beforeunload handler.  If it returns false, we
    134 //   cancel all the pending logic.  Otherwise we allow the pending RVH to send
    135 //   the navigation request to its renderer.
    136 // - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the
    137 //   main resource load on the pending RVH.  It creates a
    138 //   CrossSiteResourceHandler to check whether a process swap is needed when
    139 //   the request is ready to commit.
    140 // - When RDH receives a response, the BufferedResourceHandler determines
    141 //   whether it is a download.  If so, it sends a message to the new renderer
    142 //   causing it to cancel the request, and the download proceeds. For now, the
    143 //   pending RVH remains until the next DidNavigate event for this
    144 //   WebContentsImpl. This isn't ideal, but it doesn't affect any functionality.
    145 // - After RDH receives a response and determines that it is safe and not a
    146 //   download, the CrossSiteResourceHandler checks whether a process swap is
    147 //   needed (either because CrossSiteRequestManager has state for it or because
    148 //   a transfer was needed for a redirect).
    149 // - If so, CrossSiteResourceHandler pauses the response to first run the old
    150 //   page's unload handler.  It does this by asynchronously calling the
    151 //   OnCrossSiteResponse method of RenderFrameHostManager on the UI thread,
    152 //   which sends a SwapOut message to the current RVH.
    153 // - Once the unload handler is finished, RVHM::SwappedOut checks if a transfer
    154 //   to a new process is needed, based on the stored pending_nav_params_.  (This
    155 //   is independent of whether we started out with a cross-process navigation.)
    156 //   - If not, it just tells the ResourceDispatcherHost to resume the response
    157 //     to its current RenderViewHost.
    158 //   - If so, it cancels the current pending RenderViewHost and sets up a new
    159 //     navigation using RequestTransferURL.  When the transferred request
    160 //     arrives in the ResourceDispatcherHost, we transfer the response and
    161 //     resume it.
    162 // - The pending renderer sends a FrameNavigate message that invokes the
    163 //   DidNavigate method.  This replaces the current RVH with the
    164 //   pending RVH.
    165 // - The previous renderer is kept swapped out in RenderFrameHostManager in case
    166 //   the user goes back.  The process only stays live if another tab is using
    167 //   it, but if so, the existing frame relationships will be maintained.
    168 
    169 namespace content {
    170 namespace {
    171 
    172 const int kMinimumDelayBetweenLoadingUpdatesMS = 100;
    173 
    174 // This matches what Blink's ProgressTracker has traditionally used for a
    175 // minimum progress value.
    176 const double kMinimumLoadingProgress = 0.1;
    177 
    178 const char kDotGoogleDotCom[] = ".google.com";
    179 
    180 #if defined(OS_ANDROID)
    181 const char kWebContentsAndroidKey[] = "web_contents_android";
    182 #endif  // OS_ANDROID
    183 
    184 base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> >
    185 g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
    186 
    187 static int StartDownload(RenderFrameHost* rfh,
    188                          const GURL& url,
    189                          bool is_favicon,
    190                          uint32_t max_bitmap_size) {
    191   static int g_next_image_download_id = 0;
    192   rfh->Send(new ImageMsg_DownloadImage(rfh->GetRoutingID(),
    193                                        ++g_next_image_download_id,
    194                                        url,
    195                                        is_favicon,
    196                                        max_bitmap_size));
    197   return g_next_image_download_id;
    198 }
    199 
    200 void NotifyCacheOnIO(
    201     scoped_refptr<net::URLRequestContextGetter> request_context,
    202     const GURL& url,
    203     const std::string& http_method) {
    204   request_context->GetURLRequestContext()->http_transaction_factory()->
    205       GetCache()->OnExternalCacheHit(url, http_method);
    206 }
    207 
    208 // Helper function for retrieving all the sites in a frame tree.
    209 bool CollectSites(BrowserContext* context,
    210                   std::set<GURL>* sites,
    211                   FrameTreeNode* node) {
    212   sites->insert(SiteInstance::GetSiteForURL(context, node->current_url()));
    213   return true;
    214 }
    215 
    216 bool ForEachFrameInternal(
    217     const base::Callback<void(RenderFrameHost*)>& on_frame,
    218     FrameTreeNode* node) {
    219   on_frame.Run(node->current_frame_host());
    220   return true;
    221 }
    222 
    223 bool ForEachPendingFrameInternal(
    224     const base::Callback<void(RenderFrameHost*)>& on_frame,
    225     FrameTreeNode* node) {
    226   RenderFrameHost* pending_frame_host =
    227       node->render_manager()->pending_frame_host();
    228   if (pending_frame_host)
    229     on_frame.Run(pending_frame_host);
    230   return true;
    231 }
    232 
    233 void SendToAllFramesInternal(IPC::Message* message, RenderFrameHost* rfh) {
    234   IPC::Message* message_copy = new IPC::Message(*message);
    235   message_copy->set_routing_id(rfh->GetRoutingID());
    236   rfh->Send(message_copy);
    237 }
    238 
    239 void AddRenderWidgetHostViewToSet(std::set<RenderWidgetHostView*>* set,
    240                                   RenderFrameHost* rfh) {
    241   RenderWidgetHostView* rwhv = static_cast<RenderFrameHostImpl*>(rfh)
    242                                    ->frame_tree_node()
    243                                    ->render_manager()
    244                                    ->GetRenderWidgetHostView();
    245   set->insert(rwhv);
    246 }
    247 
    248 void SetAccessibilityModeOnFrame(AccessibilityMode mode,
    249                                  RenderFrameHost* frame_host) {
    250   static_cast<RenderFrameHostImpl*>(frame_host)->SetAccessibilityMode(mode);
    251 }
    252 
    253 }  // namespace
    254 
    255 WebContents* WebContents::Create(const WebContents::CreateParams& params) {
    256   return WebContentsImpl::CreateWithOpener(
    257       params, static_cast<WebContentsImpl*>(params.opener));
    258 }
    259 
    260 WebContents* WebContents::CreateWithSessionStorage(
    261     const WebContents::CreateParams& params,
    262     const SessionStorageNamespaceMap& session_storage_namespace_map) {
    263   WebContentsImpl* new_contents = new WebContentsImpl(
    264       params.browser_context, NULL);
    265 
    266   for (SessionStorageNamespaceMap::const_iterator it =
    267            session_storage_namespace_map.begin();
    268        it != session_storage_namespace_map.end();
    269        ++it) {
    270     new_contents->GetController()
    271         .SetSessionStorageNamespace(it->first, it->second.get());
    272   }
    273 
    274   new_contents->Init(params);
    275   return new_contents;
    276 }
    277 
    278 void WebContentsImpl::AddCreatedCallback(const CreatedCallback& callback) {
    279   g_created_callbacks.Get().push_back(callback);
    280 }
    281 
    282 void WebContentsImpl::RemoveCreatedCallback(const CreatedCallback& callback) {
    283   for (size_t i = 0; i < g_created_callbacks.Get().size(); ++i) {
    284     if (g_created_callbacks.Get().at(i).Equals(callback)) {
    285       g_created_callbacks.Get().erase(g_created_callbacks.Get().begin() + i);
    286       return;
    287     }
    288   }
    289 }
    290 
    291 WebContents* WebContents::FromRenderViewHost(const RenderViewHost* rvh) {
    292   return rvh->GetDelegate()->GetAsWebContents();
    293 }
    294 
    295 WebContents* WebContents::FromRenderFrameHost(RenderFrameHost* rfh) {
    296   RenderFrameHostImpl* rfh_impl = static_cast<RenderFrameHostImpl*>(rfh);
    297   if (!rfh_impl)
    298     return NULL;
    299   return rfh_impl->delegate()->GetAsWebContents();
    300 }
    301 
    302 // WebContentsImpl::DestructionObserver ----------------------------------------
    303 
    304 class WebContentsImpl::DestructionObserver : public WebContentsObserver {
    305  public:
    306   DestructionObserver(WebContentsImpl* owner, WebContents* watched_contents)
    307       : WebContentsObserver(watched_contents),
    308         owner_(owner) {
    309   }
    310 
    311   // WebContentsObserver:
    312   virtual void WebContentsDestroyed() OVERRIDE {
    313     owner_->OnWebContentsDestroyed(
    314         static_cast<WebContentsImpl*>(web_contents()));
    315   }
    316 
    317  private:
    318   WebContentsImpl* owner_;
    319 
    320   DISALLOW_COPY_AND_ASSIGN(DestructionObserver);
    321 };
    322 
    323 WebContentsImpl::ColorChooserInfo::ColorChooserInfo(int render_process_id,
    324                                                     int render_frame_id,
    325                                                     ColorChooser* chooser,
    326                                                     int identifier)
    327     : render_process_id(render_process_id),
    328       render_frame_id(render_frame_id),
    329       chooser(chooser),
    330       identifier(identifier) {
    331 }
    332 
    333 WebContentsImpl::ColorChooserInfo::~ColorChooserInfo() {
    334 }
    335 
    336 // WebContentsImpl -------------------------------------------------------------
    337 
    338 WebContentsImpl::WebContentsImpl(
    339     BrowserContext* browser_context,
    340     WebContentsImpl* opener)
    341     : delegate_(NULL),
    342       controller_(this, browser_context),
    343       render_view_host_delegate_view_(NULL),
    344       opener_(opener),
    345       created_with_opener_(!!opener),
    346 #if defined(OS_WIN)
    347       accessible_parent_(NULL),
    348 #endif
    349       frame_tree_(new NavigatorImpl(&controller_, this),
    350                   this, this, this, this),
    351       is_loading_(false),
    352       is_load_to_different_document_(false),
    353       crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
    354       crashed_error_code_(0),
    355       waiting_for_response_(false),
    356       load_state_(net::LOAD_STATE_IDLE, base::string16()),
    357       loading_total_progress_(0.0),
    358       loading_frames_in_progress_(0),
    359       upload_size_(0),
    360       upload_position_(0),
    361       displayed_insecure_content_(false),
    362       has_accessed_initial_document_(false),
    363       capturer_count_(0),
    364       should_normally_be_visible_(true),
    365       is_being_destroyed_(false),
    366       notify_disconnection_(false),
    367       dialog_manager_(NULL),
    368       is_showing_before_unload_dialog_(false),
    369       last_active_time_(base::TimeTicks::Now()),
    370       closed_by_user_gesture_(false),
    371       minimum_zoom_percent_(static_cast<int>(kMinimumZoomFactor * 100)),
    372       maximum_zoom_percent_(static_cast<int>(kMaximumZoomFactor * 100)),
    373       totalPinchGestureAmount_(0),
    374       currentPinchZoomStepDelta_(0),
    375       render_view_message_source_(NULL),
    376       fullscreen_widget_routing_id_(MSG_ROUTING_NONE),
    377       fullscreen_widget_had_focus_at_shutdown_(false),
    378       is_subframe_(false),
    379       force_disable_overscroll_content_(false),
    380       last_dialog_suppressed_(false),
    381       accessibility_mode_(
    382           BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode()),
    383       audio_stream_monitor_(this),
    384       loading_weak_factory_(this) {
    385   for (size_t i = 0; i < g_created_callbacks.Get().size(); i++)
    386     g_created_callbacks.Get().at(i).Run(this);
    387   frame_tree_.SetFrameRemoveListener(
    388       base::Bind(&WebContentsImpl::OnFrameRemoved,
    389                  base::Unretained(this)));
    390 }
    391 
    392 WebContentsImpl::~WebContentsImpl() {
    393   is_being_destroyed_ = true;
    394 
    395   // Delete all RFH pending shutdown, which will lead the corresponding RVH to
    396   // shutdown and be deleted as well.
    397   frame_tree_.ForEach(
    398       base::Bind(&RenderFrameHostManager::ClearRFHsPendingShutdown));
    399 
    400   ClearAllPowerSaveBlockers();
    401 
    402   for (std::set<RenderWidgetHostImpl*>::iterator iter =
    403            created_widgets_.begin(); iter != created_widgets_.end(); ++iter) {
    404     (*iter)->DetachDelegate();
    405   }
    406   created_widgets_.clear();
    407 
    408   // Clear out any JavaScript state.
    409   if (dialog_manager_)
    410     dialog_manager_->WebContentsDestroyed(this);
    411 
    412   if (color_chooser_info_.get())
    413     color_chooser_info_->chooser->End();
    414 
    415   NotifyDisconnected();
    416 
    417   // Notify any observer that have a reference on this WebContents.
    418   NotificationService::current()->Notify(
    419       NOTIFICATION_WEB_CONTENTS_DESTROYED,
    420       Source<WebContents>(this),
    421       NotificationService::NoDetails());
    422 
    423   // Destroy all frame tree nodes except for the root; this notifies observers.
    424   frame_tree_.ResetForMainFrameSwap();
    425   GetRenderManager()->ResetProxyHosts();
    426 
    427   // Manually call the observer methods for the root frame tree node.
    428   RenderFrameHostManager* root = GetRenderManager();
    429   if (root->pending_frame_host()) {
    430     FOR_EACH_OBSERVER(WebContentsObserver,
    431                       observers_,
    432                       RenderFrameDeleted(root->pending_frame_host()));
    433   }
    434   FOR_EACH_OBSERVER(WebContentsObserver,
    435                     observers_,
    436                     RenderFrameDeleted(root->current_frame_host()));
    437 
    438   if (root->pending_render_view_host()) {
    439     FOR_EACH_OBSERVER(WebContentsObserver,
    440                       observers_,
    441                       RenderViewDeleted(root->pending_render_view_host()));
    442   }
    443 
    444   FOR_EACH_OBSERVER(WebContentsObserver,
    445                     observers_,
    446                     RenderViewDeleted(root->current_host()));
    447 
    448   FOR_EACH_OBSERVER(WebContentsObserver,
    449                     observers_,
    450                     WebContentsDestroyed());
    451 
    452   FOR_EACH_OBSERVER(WebContentsObserver,
    453                     observers_,
    454                     ResetWebContents());
    455 
    456   SetDelegate(NULL);
    457 
    458   STLDeleteContainerPairSecondPointers(destruction_observers_.begin(),
    459                                        destruction_observers_.end());
    460 }
    461 
    462 WebContentsImpl* WebContentsImpl::CreateWithOpener(
    463     const WebContents::CreateParams& params,
    464     WebContentsImpl* opener) {
    465   TRACE_EVENT0("browser", "WebContentsImpl::CreateWithOpener");
    466   WebContentsImpl* new_contents = new WebContentsImpl(
    467       params.browser_context, params.opener_suppressed ? NULL : opener);
    468 
    469   if (params.guest_delegate) {
    470     // This makes |new_contents| act as a guest.
    471     // For more info, see comment above class BrowserPluginGuest.
    472     BrowserPluginGuest::Create(new_contents, params.guest_delegate);
    473     // We are instantiating a WebContents for browser plugin. Set its subframe
    474     // bit to true.
    475     new_contents->is_subframe_ = true;
    476   }
    477   new_contents->Init(params);
    478   return new_contents;
    479 }
    480 
    481 // static
    482 std::vector<WebContentsImpl*> WebContentsImpl::GetAllWebContents() {
    483   std::vector<WebContentsImpl*> result;
    484   scoped_ptr<RenderWidgetHostIterator> widgets(
    485       RenderWidgetHostImpl::GetRenderWidgetHosts());
    486   std::set<WebContentsImpl*> web_contents_set;
    487   while (RenderWidgetHost* rwh = widgets->GetNextHost()) {
    488     if (!rwh->IsRenderView())
    489       continue;
    490     RenderViewHost* rvh = RenderViewHost::From(rwh);
    491     if (!rvh)
    492       continue;
    493     WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
    494     if (!web_contents)
    495       continue;
    496     WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents);
    497     if (web_contents_set.find(wci) == web_contents_set.end()) {
    498       web_contents_set.insert(wci);
    499       result.push_back(wci);
    500     }
    501   }
    502   return result;
    503 }
    504 
    505 RenderFrameHostManager* WebContentsImpl::GetRenderManagerForTesting() {
    506   return GetRenderManager();
    507 }
    508 
    509 bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
    510                                         const IPC::Message& message) {
    511   return OnMessageReceived(render_view_host, NULL, message);
    512 }
    513 
    514 bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
    515                                         RenderFrameHost* render_frame_host,
    516                                         const IPC::Message& message) {
    517   DCHECK(render_view_host || render_frame_host);
    518   if (GetWebUI() &&
    519       static_cast<WebUIImpl*>(GetWebUI())->OnMessageReceived(message)) {
    520     return true;
    521   }
    522 
    523   ObserverListBase<WebContentsObserver>::Iterator it(observers_);
    524   WebContentsObserver* observer;
    525   if (render_frame_host) {
    526     while ((observer = it.GetNext()) != NULL)
    527       if (observer->OnMessageReceived(message, render_frame_host))
    528         return true;
    529   } else {
    530     while ((observer = it.GetNext()) != NULL)
    531       if (observer->OnMessageReceived(message))
    532         return true;
    533   }
    534 
    535   // Message handlers should be aware of which
    536   // RenderViewHost/RenderFrameHost sent the message, which is temporarily
    537   // stored in render_(view|frame)_message_source_.
    538   if (render_frame_host)
    539     render_frame_message_source_ = render_frame_host;
    540   else
    541     render_view_message_source_ = render_view_host;
    542 
    543   bool handled = true;
    544   IPC_BEGIN_MESSAGE_MAP(WebContentsImpl, message)
    545     IPC_MESSAGE_HANDLER(FrameHostMsg_PepperPluginHung, OnPepperPluginHung)
    546     IPC_MESSAGE_HANDLER(FrameHostMsg_PluginCrashed, OnPluginCrashed)
    547     IPC_MESSAGE_HANDLER(FrameHostMsg_DomOperationResponse,
    548                         OnDomOperationResponse)
    549     IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeThemeColor,
    550                         OnThemeColorChanged)
    551     IPC_MESSAGE_HANDLER(FrameHostMsg_DidFinishDocumentLoad,
    552                         OnDocumentLoadedInFrame)
    553     IPC_MESSAGE_HANDLER(FrameHostMsg_DidFinishLoad, OnDidFinishLoad)
    554     IPC_MESSAGE_HANDLER(FrameHostMsg_DidStartLoading, OnDidStartLoading)
    555     IPC_MESSAGE_HANDLER(FrameHostMsg_DidStopLoading, OnDidStopLoading)
    556     IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeLoadProgress,
    557                         OnDidChangeLoadProgress)
    558     IPC_MESSAGE_HANDLER(FrameHostMsg_OpenColorChooser, OnOpenColorChooser)
    559     IPC_MESSAGE_HANDLER(FrameHostMsg_EndColorChooser, OnEndColorChooser)
    560     IPC_MESSAGE_HANDLER(FrameHostMsg_SetSelectedColorInColorChooser,
    561                         OnSetSelectedColorInColorChooser)
    562     IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPlayingNotification,
    563                         OnMediaPlayingNotification)
    564     IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPausedNotification,
    565                         OnMediaPausedNotification)
    566     IPC_MESSAGE_HANDLER(FrameHostMsg_DidFirstVisuallyNonEmptyPaint,
    567                         OnFirstVisuallyNonEmptyPaint)
    568     IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache,
    569                         OnDidLoadResourceFromMemoryCache)
    570     IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent,
    571                         OnDidDisplayInsecureContent)
    572     IPC_MESSAGE_HANDLER(ViewHostMsg_DidRunInsecureContent,
    573                         OnDidRunInsecureContent)
    574     IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset, OnGoToEntryAtOffset)
    575     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits, OnUpdateZoomLimits)
    576     IPC_MESSAGE_HANDLER(ViewHostMsg_EnumerateDirectory, OnEnumerateDirectory)
    577     IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler,
    578                         OnRegisterProtocolHandler)
    579     IPC_MESSAGE_HANDLER(ViewHostMsg_UnregisterProtocolHandler,
    580                         OnUnregisterProtocolHandler)
    581     IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnFindReply)
    582     IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed, OnAppCacheAccessed)
    583     IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnWebUISend)
    584 #if defined(ENABLE_PLUGINS)
    585     IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission,
    586                         OnRequestPpapiBrokerPermission)
    587     IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_Attach,
    588                                 OnBrowserPluginMessage(message))
    589 #endif
    590     IPC_MESSAGE_HANDLER(ImageHostMsg_DidDownloadImage, OnDidDownloadImage)
    591     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFaviconURL, OnUpdateFaviconURL)
    592     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowValidationMessage,
    593                         OnShowValidationMessage)
    594     IPC_MESSAGE_HANDLER(ViewHostMsg_HideValidationMessage,
    595                         OnHideValidationMessage)
    596     IPC_MESSAGE_HANDLER(ViewHostMsg_MoveValidationMessage,
    597                         OnMoveValidationMessage)
    598 #if defined(OS_ANDROID)
    599     IPC_MESSAGE_HANDLER(ViewHostMsg_FindMatchRects_Reply,
    600                         OnFindMatchRectsReply)
    601     IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog,
    602                         OnOpenDateTimeDialog)
    603 #endif
    604     IPC_MESSAGE_UNHANDLED(handled = false)
    605   IPC_END_MESSAGE_MAP()
    606   render_view_message_source_ = NULL;
    607   render_frame_message_source_ = NULL;
    608 
    609   return handled;
    610 }
    611 
    612 void WebContentsImpl::RunFileChooser(
    613     RenderViewHost* render_view_host,
    614     const FileChooserParams& params) {
    615   if (delegate_)
    616     delegate_->RunFileChooser(this, params);
    617 }
    618 
    619 NavigationControllerImpl& WebContentsImpl::GetController() {
    620   return controller_;
    621 }
    622 
    623 const NavigationControllerImpl& WebContentsImpl::GetController() const {
    624   return controller_;
    625 }
    626 
    627 BrowserContext* WebContentsImpl::GetBrowserContext() const {
    628   return controller_.GetBrowserContext();
    629 }
    630 
    631 const GURL& WebContentsImpl::GetURL() const {
    632   // We may not have a navigation entry yet.
    633   NavigationEntry* entry = controller_.GetVisibleEntry();
    634   return entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
    635 }
    636 
    637 const GURL& WebContentsImpl::GetVisibleURL() const {
    638   // We may not have a navigation entry yet.
    639   NavigationEntry* entry = controller_.GetVisibleEntry();
    640   return entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
    641 }
    642 
    643 const GURL& WebContentsImpl::GetLastCommittedURL() const {
    644   // We may not have a navigation entry yet.
    645   NavigationEntry* entry = controller_.GetLastCommittedEntry();
    646   return entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
    647 }
    648 
    649 WebContentsDelegate* WebContentsImpl::GetDelegate() {
    650   return delegate_;
    651 }
    652 
    653 void WebContentsImpl::SetDelegate(WebContentsDelegate* delegate) {
    654   // TODO(cbentzel): remove this debugging code?
    655   if (delegate == delegate_)
    656     return;
    657   if (delegate_)
    658     delegate_->Detach(this);
    659   delegate_ = delegate;
    660   if (delegate_) {
    661     delegate_->Attach(this);
    662     // Ensure the visible RVH reflects the new delegate's preferences.
    663     if (view_)
    664       view_->SetOverscrollControllerEnabled(CanOverscrollContent());
    665   }
    666 }
    667 
    668 RenderProcessHost* WebContentsImpl::GetRenderProcessHost() const {
    669   RenderViewHostImpl* host = GetRenderManager()->current_host();
    670   return host ? host->GetProcess() : NULL;
    671 }
    672 
    673 RenderFrameHost* WebContentsImpl::GetMainFrame() {
    674   return frame_tree_.root()->current_frame_host();
    675 }
    676 
    677 RenderFrameHost* WebContentsImpl::GetFocusedFrame() {
    678   if (!frame_tree_.GetFocusedFrame())
    679     return NULL;
    680   return frame_tree_.GetFocusedFrame()->current_frame_host();
    681 }
    682 
    683 void WebContentsImpl::ForEachFrame(
    684     const base::Callback<void(RenderFrameHost*)>& on_frame) {
    685   frame_tree_.ForEach(base::Bind(&ForEachFrameInternal, on_frame));
    686 }
    687 
    688 void WebContentsImpl::SendToAllFrames(IPC::Message* message) {
    689   ForEachFrame(base::Bind(&SendToAllFramesInternal, message));
    690   delete message;
    691 }
    692 
    693 RenderViewHost* WebContentsImpl::GetRenderViewHost() const {
    694   return GetRenderManager()->current_host();
    695 }
    696 
    697 int WebContentsImpl::GetRoutingID() const {
    698   if (!GetRenderViewHost())
    699     return MSG_ROUTING_NONE;
    700 
    701   return GetRenderViewHost()->GetRoutingID();
    702 }
    703 
    704 int WebContentsImpl::GetFullscreenWidgetRoutingID() const {
    705   return fullscreen_widget_routing_id_;
    706 }
    707 
    708 RenderWidgetHostView* WebContentsImpl::GetRenderWidgetHostView() const {
    709   return GetRenderManager()->GetRenderWidgetHostView();
    710 }
    711 
    712 RenderWidgetHostView* WebContentsImpl::GetFullscreenRenderWidgetHostView()
    713     const {
    714   RenderWidgetHost* const widget_host =
    715       RenderWidgetHostImpl::FromID(GetRenderProcessHost()->GetID(),
    716                                    GetFullscreenWidgetRoutingID());
    717   return widget_host ? widget_host->GetView() : NULL;
    718 }
    719 
    720 WebContentsView* WebContentsImpl::GetView() const {
    721   return view_.get();
    722 }
    723 
    724 void WebContentsImpl::SetAccessibilityMode(AccessibilityMode mode) {
    725   if (mode == accessibility_mode_)
    726     return;
    727 
    728   accessibility_mode_ = mode;
    729   frame_tree_.ForEach(
    730       base::Bind(&ForEachFrameInternal,
    731                  base::Bind(&SetAccessibilityModeOnFrame, mode)));
    732   frame_tree_.ForEach(
    733       base::Bind(&ForEachPendingFrameInternal,
    734                  base::Bind(&SetAccessibilityModeOnFrame, mode)));
    735 }
    736 
    737 void WebContentsImpl::AddAccessibilityMode(AccessibilityMode mode) {
    738   SetAccessibilityMode(AddAccessibilityModeTo(accessibility_mode_, mode));
    739 }
    740 
    741 void WebContentsImpl::RemoveAccessibilityMode(AccessibilityMode mode) {
    742   SetAccessibilityMode(RemoveAccessibilityModeFrom(accessibility_mode_, mode));
    743 }
    744 
    745 WebUI* WebContentsImpl::CreateWebUI(const GURL& url) {
    746   WebUIImpl* web_ui = new WebUIImpl(this);
    747   WebUIController* controller = WebUIControllerFactoryRegistry::GetInstance()->
    748       CreateWebUIControllerForURL(web_ui, url);
    749   if (controller) {
    750     web_ui->AddMessageHandler(new GenericHandler());
    751     web_ui->SetController(controller);
    752     return web_ui;
    753   }
    754 
    755   delete web_ui;
    756   return NULL;
    757 }
    758 
    759 WebUI* WebContentsImpl::GetWebUI() const {
    760   return GetRenderManager()->web_ui() ? GetRenderManager()->web_ui()
    761       : GetRenderManager()->pending_web_ui();
    762 }
    763 
    764 WebUI* WebContentsImpl::GetCommittedWebUI() const {
    765   return GetRenderManager()->web_ui();
    766 }
    767 
    768 void WebContentsImpl::SetUserAgentOverride(const std::string& override) {
    769   if (GetUserAgentOverride() == override)
    770     return;
    771 
    772   renderer_preferences_.user_agent_override = override;
    773 
    774   // Send the new override string to the renderer.
    775   RenderViewHost* host = GetRenderViewHost();
    776   if (host)
    777     host->SyncRendererPrefs();
    778 
    779   // Reload the page if a load is currently in progress to avoid having
    780   // different parts of the page loaded using different user agents.
    781   NavigationEntry* entry = controller_.GetVisibleEntry();
    782   if (is_loading_ && entry != NULL && entry->GetIsOverridingUserAgent())
    783     controller_.ReloadIgnoringCache(true);
    784 
    785   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
    786                     UserAgentOverrideSet(override));
    787 }
    788 
    789 const std::string& WebContentsImpl::GetUserAgentOverride() const {
    790   return renderer_preferences_.user_agent_override;
    791 }
    792 
    793 void WebContentsImpl::EnableTreeOnlyAccessibilityMode() {
    794   AddAccessibilityMode(AccessibilityModeTreeOnly);
    795 }
    796 
    797 bool WebContentsImpl::IsTreeOnlyAccessibilityModeForTesting() const {
    798   return accessibility_mode_ == AccessibilityModeTreeOnly;
    799 }
    800 
    801 bool WebContentsImpl::IsFullAccessibilityModeForTesting() const {
    802   return accessibility_mode_ == AccessibilityModeComplete;
    803 }
    804 
    805 #if defined(OS_WIN)
    806 void WebContentsImpl::SetParentNativeViewAccessible(
    807 gfx::NativeViewAccessible accessible_parent) {
    808   accessible_parent_ = accessible_parent;
    809   RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame());
    810   if (rfh)
    811     rfh->SetParentNativeViewAccessible(accessible_parent);
    812 }
    813 #endif
    814 
    815 const base::string16& WebContentsImpl::GetTitle() const {
    816   // Transient entries take precedence. They are used for interstitial pages
    817   // that are shown on top of existing pages.
    818   NavigationEntry* entry = controller_.GetTransientEntry();
    819   std::string accept_languages =
    820       GetContentClient()->browser()->GetAcceptLangs(
    821           GetBrowserContext());
    822   if (entry) {
    823     return entry->GetTitleForDisplay(accept_languages);
    824   }
    825   WebUI* our_web_ui = GetRenderManager()->pending_web_ui() ?
    826       GetRenderManager()->pending_web_ui() : GetRenderManager()->web_ui();
    827   if (our_web_ui) {
    828     // Don't override the title in view source mode.
    829     entry = controller_.GetVisibleEntry();
    830     if (!(entry && entry->IsViewSourceMode())) {
    831       // Give the Web UI the chance to override our title.
    832       const base::string16& title = our_web_ui->GetOverriddenTitle();
    833       if (!title.empty())
    834         return title;
    835     }
    836   }
    837 
    838   // We use the title for the last committed entry rather than a pending
    839   // navigation entry. For example, when the user types in a URL, we want to
    840   // keep the old page's title until the new load has committed and we get a new
    841   // title.
    842   entry = controller_.GetLastCommittedEntry();
    843 
    844   // We make an exception for initial navigations.
    845   if (controller_.IsInitialNavigation()) {
    846     // We only want to use the title from the visible entry in one of two cases:
    847     // 1. There's already a committed entry for an initial navigation, in which
    848     //    case we are doing a history navigation in a new tab (e.g., Ctrl+Back).
    849     // 2. The pending entry has been explicitly assigned a title to display.
    850     //
    851     // If there's no last committed entry and no assigned title, we should fall
    852     // back to |page_title_when_no_navigation_entry_| rather than showing the
    853     // URL.
    854     if (entry ||
    855         (controller_.GetVisibleEntry() &&
    856          !controller_.GetVisibleEntry()->GetTitle().empty())) {
    857       entry = controller_.GetVisibleEntry();
    858     }
    859   }
    860 
    861   if (entry) {
    862     return entry->GetTitleForDisplay(accept_languages);
    863   }
    864 
    865   // |page_title_when_no_navigation_entry_| is finally used
    866   // if no title cannot be retrieved.
    867   return page_title_when_no_navigation_entry_;
    868 }
    869 
    870 int32 WebContentsImpl::GetMaxPageID() {
    871   return GetMaxPageIDForSiteInstance(GetSiteInstance());
    872 }
    873 
    874 int32 WebContentsImpl::GetMaxPageIDForSiteInstance(
    875     SiteInstance* site_instance) {
    876   if (max_page_ids_.find(site_instance->GetId()) == max_page_ids_.end())
    877     max_page_ids_[site_instance->GetId()] = -1;
    878 
    879   return max_page_ids_[site_instance->GetId()];
    880 }
    881 
    882 void WebContentsImpl::UpdateMaxPageID(int32 page_id) {
    883   UpdateMaxPageIDForSiteInstance(GetSiteInstance(), page_id);
    884 }
    885 
    886 void WebContentsImpl::UpdateMaxPageIDForSiteInstance(
    887     SiteInstance* site_instance, int32 page_id) {
    888   if (GetMaxPageIDForSiteInstance(site_instance) < page_id)
    889     max_page_ids_[site_instance->GetId()] = page_id;
    890 }
    891 
    892 void WebContentsImpl::CopyMaxPageIDsFrom(WebContents* web_contents) {
    893   WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents);
    894   max_page_ids_ = contents->max_page_ids_;
    895 }
    896 
    897 SiteInstance* WebContentsImpl::GetSiteInstance() const {
    898   return GetRenderManager()->current_host()->GetSiteInstance();
    899 }
    900 
    901 SiteInstance* WebContentsImpl::GetPendingSiteInstance() const {
    902   RenderViewHost* dest_rvh = GetRenderManager()->pending_render_view_host() ?
    903       GetRenderManager()->pending_render_view_host() :
    904       GetRenderManager()->current_host();
    905   return dest_rvh->GetSiteInstance();
    906 }
    907 
    908 bool WebContentsImpl::IsLoading() const {
    909   return is_loading_;
    910 }
    911 
    912 bool WebContentsImpl::IsLoadingToDifferentDocument() const {
    913   return is_loading_ && is_load_to_different_document_;
    914 }
    915 
    916 bool WebContentsImpl::IsWaitingForResponse() const {
    917   return waiting_for_response_ && is_load_to_different_document_;
    918 }
    919 
    920 const net::LoadStateWithParam& WebContentsImpl::GetLoadState() const {
    921   return load_state_;
    922 }
    923 
    924 const base::string16& WebContentsImpl::GetLoadStateHost() const {
    925   return load_state_host_;
    926 }
    927 
    928 uint64 WebContentsImpl::GetUploadSize() const {
    929   return upload_size_;
    930 }
    931 
    932 uint64 WebContentsImpl::GetUploadPosition() const {
    933   return upload_position_;
    934 }
    935 
    936 std::set<GURL> WebContentsImpl::GetSitesInTab() const {
    937   std::set<GURL> sites;
    938   frame_tree_.ForEach(base::Bind(&CollectSites,
    939                                  base::Unretained(GetBrowserContext()),
    940                                  base::Unretained(&sites)));
    941   return sites;
    942 }
    943 
    944 const std::string& WebContentsImpl::GetEncoding() const {
    945   return canonical_encoding_;
    946 }
    947 
    948 bool WebContentsImpl::DisplayedInsecureContent() const {
    949   return displayed_insecure_content_;
    950 }
    951 
    952 void WebContentsImpl::IncrementCapturerCount(const gfx::Size& capture_size) {
    953   DCHECK(!is_being_destroyed_);
    954   ++capturer_count_;
    955   DVLOG(1) << "There are now " << capturer_count_
    956            << " capturing(s) of WebContentsImpl@" << this;
    957 
    958   // Note: This provides a hint to upstream code to size the views optimally
    959   // for quality (e.g., to avoid scaling).
    960   if (!capture_size.IsEmpty() && preferred_size_for_capture_.IsEmpty()) {
    961     preferred_size_for_capture_ = capture_size;
    962     OnPreferredSizeChanged(preferred_size_);
    963   }
    964 }
    965 
    966 void WebContentsImpl::DecrementCapturerCount() {
    967   --capturer_count_;
    968   DVLOG(1) << "There are now " << capturer_count_
    969            << " capturing(s) of WebContentsImpl@" << this;
    970   DCHECK_LE(0, capturer_count_);
    971 
    972   if (is_being_destroyed_)
    973     return;
    974 
    975   if (capturer_count_ == 0) {
    976     const gfx::Size old_size = preferred_size_for_capture_;
    977     preferred_size_for_capture_ = gfx::Size();
    978     OnPreferredSizeChanged(old_size);
    979   }
    980 
    981   if (IsHidden()) {
    982     DVLOG(1) << "Executing delayed WasHidden().";
    983     WasHidden();
    984   }
    985 }
    986 
    987 int WebContentsImpl::GetCapturerCount() const {
    988   return capturer_count_;
    989 }
    990 
    991 bool WebContentsImpl::IsAudioMuted() const {
    992   return audio_muter_.get() && audio_muter_->is_muting();
    993 }
    994 
    995 void WebContentsImpl::SetAudioMuted(bool mute) {
    996   DVLOG(1) << "SetAudioMuted(mute=" << mute << "), was " << IsAudioMuted()
    997            << " for WebContentsImpl@" << this;
    998 
    999   if (mute == IsAudioMuted())
   1000     return;
   1001 
   1002   if (mute) {
   1003     if (!audio_muter_)
   1004       audio_muter_.reset(new WebContentsAudioMuter(this));
   1005     audio_muter_->StartMuting();
   1006   } else {
   1007     DCHECK(audio_muter_);
   1008     audio_muter_->StopMuting();
   1009   }
   1010 
   1011   // Notification for UI updates in response to the changed muting state.
   1012   NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
   1013 }
   1014 
   1015 bool WebContentsImpl::IsCrashed() const {
   1016   return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED ||
   1017           crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION ||
   1018           crashed_status_ == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
   1019 }
   1020 
   1021 void WebContentsImpl::SetIsCrashed(base::TerminationStatus status,
   1022                                    int error_code) {
   1023   if (status == crashed_status_)
   1024     return;
   1025 
   1026   crashed_status_ = status;
   1027   crashed_error_code_ = error_code;
   1028   NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
   1029 }
   1030 
   1031 base::TerminationStatus WebContentsImpl::GetCrashedStatus() const {
   1032   return crashed_status_;
   1033 }
   1034 
   1035 bool WebContentsImpl::IsBeingDestroyed() const {
   1036   return is_being_destroyed_;
   1037 }
   1038 
   1039 void WebContentsImpl::NotifyNavigationStateChanged(
   1040     InvalidateTypes changed_flags) {
   1041   // Create and release the audio power save blocker depending on whether the
   1042   // tab is actively producing audio or not.
   1043   if (changed_flags == INVALIDATE_TYPE_TAB &&
   1044       AudioStreamMonitor::monitoring_available()) {
   1045     if (WasRecentlyAudible()) {
   1046       if (!audio_power_save_blocker_)
   1047         CreateAudioPowerSaveBlocker();
   1048     } else {
   1049       audio_power_save_blocker_.reset();
   1050     }
   1051   }
   1052 
   1053   if (delegate_)
   1054     delegate_->NavigationStateChanged(this, changed_flags);
   1055 }
   1056 
   1057 base::TimeTicks WebContentsImpl::GetLastActiveTime() const {
   1058   return last_active_time_;
   1059 }
   1060 
   1061 void WebContentsImpl::WasShown() {
   1062   controller_.SetActive(true);
   1063 
   1064   std::set<RenderWidgetHostView*> widgets = GetRenderWidgetHostViewsInTree();
   1065   for (std::set<RenderWidgetHostView*>::iterator iter = widgets.begin();
   1066        iter != widgets.end();
   1067        iter++) {
   1068     if (*iter) {
   1069       (*iter)->Show();
   1070 #if defined(OS_MACOSX)
   1071       (*iter)->SetActive(true);
   1072 #endif
   1073     }
   1074   }
   1075 
   1076   last_active_time_ = base::TimeTicks::Now();
   1077 
   1078   // The resize rect might have changed while this was inactive -- send the new
   1079   // one to make sure it's up to date.
   1080   RenderViewHostImpl* rvh =
   1081       static_cast<RenderViewHostImpl*>(GetRenderViewHost());
   1082   if (rvh) {
   1083     rvh->ResizeRectChanged(GetRootWindowResizerRect());
   1084   }
   1085 
   1086   // Restore power save blocker if there are active video players running.
   1087   if (!active_video_players_.empty() && !video_power_save_blocker_)
   1088     CreateVideoPowerSaveBlocker();
   1089 
   1090   FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasShown());
   1091 
   1092   should_normally_be_visible_ = true;
   1093 }
   1094 
   1095 void WebContentsImpl::WasHidden() {
   1096   // If there are entities capturing screenshots or video (e.g., mirroring),
   1097   // don't activate the "disable rendering" optimization.
   1098   if (capturer_count_ == 0) {
   1099     // |GetRenderViewHost()| can be NULL if the user middle clicks a link to
   1100     // open a tab in the background, then closes the tab before selecting it.
   1101     // This is because closing the tab calls WebContentsImpl::Destroy(), which
   1102     // removes the |GetRenderViewHost()|; then when we actually destroy the
   1103     // window, OnWindowPosChanged() notices and calls WasHidden() (which
   1104     // calls us).
   1105     std::set<RenderWidgetHostView*> widgets = GetRenderWidgetHostViewsInTree();
   1106     for (std::set<RenderWidgetHostView*>::iterator iter = widgets.begin();
   1107          iter != widgets.end();
   1108          iter++) {
   1109       if (*iter)
   1110         (*iter)->Hide();
   1111     }
   1112 
   1113     // Release any video power save blockers held as video is not visible.
   1114     video_power_save_blocker_.reset();
   1115   }
   1116 
   1117   FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasHidden());
   1118 
   1119   should_normally_be_visible_ = false;
   1120 }
   1121 
   1122 bool WebContentsImpl::NeedToFireBeforeUnload() {
   1123   // TODO(creis): Should we fire even for interstitial pages?
   1124   return WillNotifyDisconnection() &&
   1125       !ShowingInterstitialPage() &&
   1126       !static_cast<RenderViewHostImpl*>(
   1127           GetRenderViewHost())->SuddenTerminationAllowed();
   1128 }
   1129 
   1130 void WebContentsImpl::DispatchBeforeUnload(bool for_cross_site_transition) {
   1131   static_cast<RenderFrameHostImpl*>(GetMainFrame())->DispatchBeforeUnload(
   1132       for_cross_site_transition);
   1133 }
   1134 
   1135 void WebContentsImpl::Stop() {
   1136   GetRenderManager()->Stop();
   1137   FOR_EACH_OBSERVER(WebContentsObserver, observers_, NavigationStopped());
   1138 }
   1139 
   1140 WebContents* WebContentsImpl::Clone() {
   1141   // We use our current SiteInstance since the cloned entry will use it anyway.
   1142   // We pass our own opener so that the cloned page can access it if it was
   1143   // before.
   1144   CreateParams create_params(GetBrowserContext(), GetSiteInstance());
   1145   create_params.initial_size = GetContainerBounds().size();
   1146   WebContentsImpl* tc = CreateWithOpener(create_params, opener_);
   1147   tc->GetController().CopyStateFrom(controller_);
   1148   FOR_EACH_OBSERVER(WebContentsObserver,
   1149                     observers_,
   1150                     DidCloneToNewWebContents(this, tc));
   1151   return tc;
   1152 }
   1153 
   1154 void WebContentsImpl::Observe(int type,
   1155                               const NotificationSource& source,
   1156                               const NotificationDetails& details) {
   1157   switch (type) {
   1158     case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED: {
   1159       RenderWidgetHost* host = Source<RenderWidgetHost>(source).ptr();
   1160       RenderWidgetHostView* view = host->GetView();
   1161       if (view == GetFullscreenRenderWidgetHostView()) {
   1162         // We cannot just call view_->RestoreFocus() here.  On some platforms,
   1163         // attempting to focus the currently-invisible WebContentsView will be
   1164         // flat-out ignored.  Therefore, this boolean is used to track whether
   1165         // we will request focus after the fullscreen widget has been
   1166         // destroyed.
   1167         fullscreen_widget_had_focus_at_shutdown_ = (view && view->HasFocus());
   1168       } else {
   1169         for (PendingWidgetViews::iterator i = pending_widget_views_.begin();
   1170              i != pending_widget_views_.end(); ++i) {
   1171           if (host->GetView() == i->second) {
   1172             pending_widget_views_.erase(i);
   1173             break;
   1174           }
   1175         }
   1176       }
   1177       break;
   1178     }
   1179     default:
   1180       NOTREACHED();
   1181   }
   1182 }
   1183 
   1184 WebContents* WebContentsImpl::GetWebContents() {
   1185   return this;
   1186 }
   1187 
   1188 void WebContentsImpl::Init(const WebContents::CreateParams& params) {
   1189   // This is set before initializing the render manager since
   1190   // RenderFrameHostManager::Init calls back into us via its delegate to ask if
   1191   // it should be hidden.
   1192   should_normally_be_visible_ = !params.initially_hidden;
   1193 
   1194   GetRenderManager()->Init(
   1195       params.browser_context, params.site_instance, params.routing_id,
   1196       params.main_frame_routing_id);
   1197 
   1198   WebContentsViewDelegate* delegate =
   1199       GetContentClient()->browser()->GetWebContentsViewDelegate(this);
   1200 
   1201   if (browser_plugin_guest_) {
   1202     scoped_ptr<WebContentsView> platform_view(CreateWebContentsView(
   1203         this, delegate, &render_view_host_delegate_view_));
   1204 
   1205     WebContentsViewGuest* rv = new WebContentsViewGuest(
   1206         this, browser_plugin_guest_.get(), platform_view.Pass(),
   1207         render_view_host_delegate_view_);
   1208     render_view_host_delegate_view_ = rv;
   1209     view_.reset(rv);
   1210   } else {
   1211     // Regular WebContentsView.
   1212     view_.reset(CreateWebContentsView(
   1213         this, delegate, &render_view_host_delegate_view_));
   1214   }
   1215   CHECK(render_view_host_delegate_view_);
   1216   CHECK(view_.get());
   1217 
   1218   gfx::Size initial_size = params.initial_size;
   1219   view_->CreateView(initial_size, params.context);
   1220 
   1221   // Listen for whether our opener gets destroyed.
   1222   if (opener_)
   1223     AddDestructionObserver(opener_);
   1224 
   1225   registrar_.Add(this,
   1226                  NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
   1227                  NotificationService::AllBrowserContextsAndSources());
   1228 
   1229   geolocation_dispatcher_host_.reset(new GeolocationDispatcherHost(this));
   1230   midi_dispatcher_host_.reset(new MidiDispatcherHost(this));
   1231 
   1232   screen_orientation_dispatcher_host_.reset(
   1233       new ScreenOrientationDispatcherHostImpl(this));
   1234 
   1235   manifest_manager_host_.reset(new ManifestManagerHost(this));
   1236 
   1237 #if defined(OS_ANDROID)
   1238   date_time_chooser_.reset(new DateTimeChooserAndroid());
   1239 #endif
   1240 }
   1241 
   1242 void WebContentsImpl::OnWebContentsDestroyed(WebContentsImpl* web_contents) {
   1243   RemoveDestructionObserver(web_contents);
   1244 
   1245   // Clear the opener if it has been closed.
   1246   if (web_contents == opener_) {
   1247     opener_ = NULL;
   1248     return;
   1249   }
   1250   // Clear a pending contents that has been closed before being shown.
   1251   for (PendingContents::iterator iter = pending_contents_.begin();
   1252        iter != pending_contents_.end();
   1253        ++iter) {
   1254     if (iter->second != web_contents)
   1255       continue;
   1256     pending_contents_.erase(iter);
   1257     return;
   1258   }
   1259   NOTREACHED();
   1260 }
   1261 
   1262 void WebContentsImpl::AddDestructionObserver(WebContentsImpl* web_contents) {
   1263   if (!ContainsKey(destruction_observers_, web_contents)) {
   1264     destruction_observers_[web_contents] =
   1265         new DestructionObserver(this, web_contents);
   1266   }
   1267 }
   1268 
   1269 void WebContentsImpl::RemoveDestructionObserver(WebContentsImpl* web_contents) {
   1270   DestructionObservers::iterator iter =
   1271       destruction_observers_.find(web_contents);
   1272   if (iter != destruction_observers_.end()) {
   1273     delete destruction_observers_[web_contents];
   1274     destruction_observers_.erase(iter);
   1275   }
   1276 }
   1277 
   1278 void WebContentsImpl::AddObserver(WebContentsObserver* observer) {
   1279   observers_.AddObserver(observer);
   1280 }
   1281 
   1282 void WebContentsImpl::RemoveObserver(WebContentsObserver* observer) {
   1283   observers_.RemoveObserver(observer);
   1284 }
   1285 
   1286 std::set<RenderWidgetHostView*>
   1287 WebContentsImpl::GetRenderWidgetHostViewsInTree() {
   1288   std::set<RenderWidgetHostView*> set;
   1289   if (ShowingInterstitialPage()) {
   1290     set.insert(GetRenderWidgetHostView());
   1291   } else {
   1292     ForEachFrame(
   1293         base::Bind(&AddRenderWidgetHostViewToSet, base::Unretained(&set)));
   1294   }
   1295   return set;
   1296 }
   1297 
   1298 void WebContentsImpl::Activate() {
   1299   if (delegate_)
   1300     delegate_->ActivateContents(this);
   1301 }
   1302 
   1303 void WebContentsImpl::Deactivate() {
   1304   if (delegate_)
   1305     delegate_->DeactivateContents(this);
   1306 }
   1307 
   1308 void WebContentsImpl::LostCapture() {
   1309   if (delegate_)
   1310     delegate_->LostCapture();
   1311 }
   1312 
   1313 void WebContentsImpl::RenderWidgetDeleted(
   1314     RenderWidgetHostImpl* render_widget_host) {
   1315   if (is_being_destroyed_) {
   1316     // |created_widgets_| might have been destroyed.
   1317     return;
   1318   }
   1319 
   1320   std::set<RenderWidgetHostImpl*>::iterator iter =
   1321       created_widgets_.find(render_widget_host);
   1322   if (iter != created_widgets_.end())
   1323     created_widgets_.erase(iter);
   1324 
   1325   if (render_widget_host &&
   1326       render_widget_host->GetRoutingID() == fullscreen_widget_routing_id_) {
   1327     if (delegate_ && delegate_->EmbedsFullscreenWidget())
   1328       delegate_->ToggleFullscreenModeForTab(this, false);
   1329     FOR_EACH_OBSERVER(WebContentsObserver,
   1330                       observers_,
   1331                       DidDestroyFullscreenWidget(
   1332                           fullscreen_widget_routing_id_));
   1333     fullscreen_widget_routing_id_ = MSG_ROUTING_NONE;
   1334     if (fullscreen_widget_had_focus_at_shutdown_)
   1335       view_->RestoreFocus();
   1336   }
   1337 }
   1338 
   1339 bool WebContentsImpl::PreHandleKeyboardEvent(
   1340     const NativeWebKeyboardEvent& event,
   1341     bool* is_keyboard_shortcut) {
   1342   return delegate_ &&
   1343       delegate_->PreHandleKeyboardEvent(this, event, is_keyboard_shortcut);
   1344 }
   1345 
   1346 void WebContentsImpl::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
   1347   if (browser_plugin_embedder_ &&
   1348       browser_plugin_embedder_->HandleKeyboardEvent(event)) {
   1349     return;
   1350   }
   1351   if (delegate_)
   1352     delegate_->HandleKeyboardEvent(this, event);
   1353 }
   1354 
   1355 bool WebContentsImpl::HandleWheelEvent(
   1356     const blink::WebMouseWheelEvent& event) {
   1357 #if !defined(OS_MACOSX)
   1358   // On platforms other than Mac, control+mousewheel changes zoom. On Mac, this
   1359   // isn't done for two reasons:
   1360   //   -the OS already has a gesture to do this through pinch-zoom
   1361   //   -if a user starts an inertial scroll, let's go, and presses control
   1362   //      (i.e. control+tab) then the OS's buffered scroll events will come in
   1363   //      with control key set which isn't what the user wants
   1364   if (delegate_ &&
   1365       event.wheelTicksY &&
   1366       (event.modifiers & blink::WebInputEvent::ControlKey) &&
   1367       // Avoid adjusting the zoom in response to two-finger-scrolling touchpad
   1368       // gestures, which are regrettably easy to trigger accidentally.
   1369       !event.hasPreciseScrollingDeltas) {
   1370     delegate_->ContentsZoomChange(event.wheelTicksY > 0);
   1371     return true;
   1372   }
   1373 #endif
   1374   return false;
   1375 }
   1376 
   1377 bool WebContentsImpl::PreHandleGestureEvent(
   1378     const blink::WebGestureEvent& event) {
   1379   return delegate_ && delegate_->PreHandleGestureEvent(this, event);
   1380 }
   1381 
   1382 bool WebContentsImpl::HandleGestureEvent(
   1383     const blink::WebGestureEvent& event) {
   1384   // Some platforms (eg. Mac) send GesturePinch events for trackpad pinch-zoom.
   1385   // Use them to implement browser zoom, as for HandleWheelEvent above.
   1386   if (event.type == blink::WebInputEvent::GesturePinchUpdate &&
   1387       event.sourceDevice == blink::WebGestureDeviceTouchpad) {
   1388     // The scale difference necessary to trigger a zoom action. Derived from
   1389     // experimentation to find a value that feels reasonable.
   1390     const float kZoomStepValue = 0.6f;
   1391 
   1392     // Find the (absolute) thresholds on either side of the current zoom factor,
   1393     // then convert those to actual numbers to trigger a zoom in or out.
   1394     // This logic deliberately makes the range around the starting zoom value
   1395     // for the gesture twice as large as the other ranges (i.e., the notches are
   1396     // at ..., -3*step, -2*step, -step, step, 2*step, 3*step, ... but not at 0)
   1397     // so that it's easier to get back to your starting point than it is to
   1398     // overshoot.
   1399     float nextStep = (abs(currentPinchZoomStepDelta_) + 1) * kZoomStepValue;
   1400     float backStep = abs(currentPinchZoomStepDelta_) * kZoomStepValue;
   1401     float zoomInThreshold = (currentPinchZoomStepDelta_ >= 0) ? nextStep
   1402         : -backStep;
   1403     float zoomOutThreshold = (currentPinchZoomStepDelta_ <= 0) ? -nextStep
   1404         : backStep;
   1405 
   1406     totalPinchGestureAmount_ += (event.data.pinchUpdate.scale - 1.0);
   1407     if (totalPinchGestureAmount_ > zoomInThreshold) {
   1408       currentPinchZoomStepDelta_++;
   1409       if (delegate_)
   1410         delegate_->ContentsZoomChange(true);
   1411     } else if (totalPinchGestureAmount_ < zoomOutThreshold) {
   1412       currentPinchZoomStepDelta_--;
   1413       if (delegate_)
   1414         delegate_->ContentsZoomChange(false);
   1415     }
   1416     return true;
   1417   }
   1418 
   1419   return false;
   1420 }
   1421 
   1422 void WebContentsImpl::HandleMouseDown() {
   1423   if (delegate_)
   1424     delegate_->HandleMouseDown();
   1425 }
   1426 
   1427 void WebContentsImpl::HandleMouseUp() {
   1428   if (delegate_)
   1429     delegate_->HandleMouseUp();
   1430 }
   1431 
   1432 void WebContentsImpl::HandlePointerActivate() {
   1433   if (delegate_)
   1434     delegate_->HandlePointerActivate();
   1435 }
   1436 
   1437 void WebContentsImpl::HandleGestureBegin() {
   1438   if (delegate_)
   1439     delegate_->HandleGestureBegin();
   1440 }
   1441 
   1442 void WebContentsImpl::HandleGestureEnd() {
   1443   if (delegate_)
   1444     delegate_->HandleGestureEnd();
   1445 }
   1446 
   1447 void WebContentsImpl::ToggleFullscreenMode(bool enter_fullscreen) {
   1448   // This method is being called to enter or leave renderer-initiated fullscreen
   1449   // mode.  Either way, make sure any existing fullscreen widget is shut down
   1450   // first.
   1451   RenderWidgetHostView* const widget_view = GetFullscreenRenderWidgetHostView();
   1452   if (widget_view)
   1453     RenderWidgetHostImpl::From(widget_view->GetRenderWidgetHost())->Shutdown();
   1454 
   1455   if (delegate_)
   1456     delegate_->ToggleFullscreenModeForTab(this, enter_fullscreen);
   1457 
   1458   FOR_EACH_OBSERVER(WebContentsObserver,
   1459                     observers_,
   1460                     DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab()));
   1461 }
   1462 
   1463 bool WebContentsImpl::IsFullscreenForCurrentTab() const {
   1464   return delegate_ ? delegate_->IsFullscreenForTabOrPending(this) : false;
   1465 }
   1466 
   1467 void WebContentsImpl::RequestToLockMouse(bool user_gesture,
   1468                                          bool last_unlocked_by_target) {
   1469   if (delegate_) {
   1470     delegate_->RequestToLockMouse(this, user_gesture, last_unlocked_by_target);
   1471   } else {
   1472     GotResponseToLockMouseRequest(false);
   1473   }
   1474 }
   1475 
   1476 void WebContentsImpl::LostMouseLock() {
   1477   if (delegate_)
   1478     delegate_->LostMouseLock();
   1479 }
   1480 
   1481 void WebContentsImpl::CreateNewWindow(
   1482     int render_process_id,
   1483     int route_id,
   1484     int main_frame_route_id,
   1485     const ViewHostMsg_CreateWindow_Params& params,
   1486     SessionStorageNamespace* session_storage_namespace) {
   1487   // We usually create the new window in the same BrowsingInstance (group of
   1488   // script-related windows), by passing in the current SiteInstance.  However,
   1489   // if the opener is being suppressed (in a non-guest), we create a new
   1490   // SiteInstance in its own BrowsingInstance.
   1491   bool is_guest = BrowserPluginGuest::IsGuest(this);
   1492 
   1493   // If the opener is to be suppressed, the new window can be in any process.
   1494   // Since routing ids are process specific, we must not have one passed in
   1495   // as argument here.
   1496   DCHECK(!params.opener_suppressed || route_id == MSG_ROUTING_NONE);
   1497 
   1498   scoped_refptr<SiteInstance> site_instance =
   1499       params.opener_suppressed && !is_guest ?
   1500       SiteInstance::CreateForURL(GetBrowserContext(), params.target_url) :
   1501       GetSiteInstance();
   1502 
   1503   // A message to create a new window can only come from the active process for
   1504   // this WebContentsImpl instance. If any other process sends the request,
   1505   // it is invalid and the process must be terminated.
   1506   if (GetRenderProcessHost()->GetID() != render_process_id) {
   1507     base::ProcessHandle process_handle =
   1508         RenderProcessHost::FromID(render_process_id)->GetHandle();
   1509     if (process_handle != base::kNullProcessHandle) {
   1510       RecordAction(
   1511           base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWindow"));
   1512       base::KillProcess(process_handle, RESULT_CODE_KILLED, false);
   1513     }
   1514     return;
   1515   }
   1516 
   1517   // We must assign the SessionStorageNamespace before calling Init().
   1518   //
   1519   // http://crbug.com/142685
   1520   const std::string& partition_id =
   1521       GetContentClient()->browser()->
   1522           GetStoragePartitionIdForSite(GetBrowserContext(),
   1523                                        site_instance->GetSiteURL());
   1524   StoragePartition* partition = BrowserContext::GetStoragePartition(
   1525       GetBrowserContext(), site_instance.get());
   1526   DOMStorageContextWrapper* dom_storage_context =
   1527       static_cast<DOMStorageContextWrapper*>(partition->GetDOMStorageContext());
   1528   SessionStorageNamespaceImpl* session_storage_namespace_impl =
   1529       static_cast<SessionStorageNamespaceImpl*>(session_storage_namespace);
   1530   CHECK(session_storage_namespace_impl->IsFromContext(dom_storage_context));
   1531 
   1532   if (delegate_ &&
   1533       !delegate_->ShouldCreateWebContents(this,
   1534                                           route_id,
   1535                                           params.window_container_type,
   1536                                           params.frame_name,
   1537                                           params.target_url,
   1538                                           partition_id,
   1539                                           session_storage_namespace)) {
   1540     if (route_id != MSG_ROUTING_NONE &&
   1541         !RenderViewHost::FromID(render_process_id, route_id)) {
   1542       // If the embedder didn't create a WebContents for this route, we need to
   1543       // delete the RenderView that had already been created.
   1544       Send(new ViewMsg_Close(route_id));
   1545     }
   1546     GetRenderViewHost()->GetProcess()->ResumeRequestsForView(route_id);
   1547     GetRenderViewHost()->GetProcess()->ResumeRequestsForView(
   1548         main_frame_route_id);
   1549     return;
   1550   }
   1551 
   1552   // Create the new web contents. This will automatically create the new
   1553   // WebContentsView. In the future, we may want to create the view separately.
   1554   CreateParams create_params(GetBrowserContext(), site_instance.get());
   1555   create_params.routing_id = route_id;
   1556   create_params.main_frame_routing_id = main_frame_route_id;
   1557   create_params.opener = this;
   1558   create_params.opener_suppressed = params.opener_suppressed;
   1559   if (params.disposition == NEW_BACKGROUND_TAB)
   1560     create_params.initially_hidden = true;
   1561 
   1562   WebContentsImpl* new_contents = NULL;
   1563   if (!is_guest) {
   1564     create_params.context = view_->GetNativeView();
   1565     create_params.initial_size = GetContainerBounds().size();
   1566     new_contents = static_cast<WebContentsImpl*>(
   1567         WebContents::Create(create_params));
   1568   }  else {
   1569     new_contents = GetBrowserPluginGuest()->CreateNewGuestWindow(create_params);
   1570   }
   1571   new_contents->GetController().SetSessionStorageNamespace(
   1572       partition_id,
   1573       session_storage_namespace);
   1574   new_contents->RenderViewCreated(new_contents->GetRenderViewHost());
   1575 
   1576   // Save the window for later if we're not suppressing the opener (since it
   1577   // will be shown immediately).
   1578   if (!params.opener_suppressed) {
   1579     if (!is_guest) {
   1580       WebContentsView* new_view = new_contents->view_.get();
   1581 
   1582       // TODO(brettw): It seems bogus that we have to call this function on the
   1583       // newly created object and give it one of its own member variables.
   1584       new_view->CreateViewForWidget(new_contents->GetRenderViewHost());
   1585     }
   1586     // Save the created window associated with the route so we can show it
   1587     // later.
   1588     DCHECK_NE(MSG_ROUTING_NONE, route_id);
   1589     pending_contents_[route_id] = new_contents;
   1590     AddDestructionObserver(new_contents);
   1591   }
   1592 
   1593   if (delegate_) {
   1594     delegate_->WebContentsCreated(
   1595         this, params.opener_render_frame_id, params.frame_name,
   1596         params.target_url, new_contents);
   1597   }
   1598 
   1599   if (params.opener_suppressed) {
   1600     // When the opener is suppressed, the original renderer cannot access the
   1601     // new window.  As a result, we need to show and navigate the window here.
   1602     bool was_blocked = false;
   1603     if (delegate_) {
   1604       gfx::Rect initial_pos;
   1605       delegate_->AddNewContents(
   1606           this, new_contents, params.disposition, initial_pos,
   1607           params.user_gesture, &was_blocked);
   1608     }
   1609     if (!was_blocked) {
   1610       OpenURLParams open_params(params.target_url,
   1611                                 Referrer(),
   1612                                 CURRENT_TAB,
   1613                                 ui::PAGE_TRANSITION_LINK,
   1614                                 true /* is_renderer_initiated */);
   1615       open_params.user_gesture = params.user_gesture;
   1616       new_contents->OpenURL(open_params);
   1617     }
   1618   }
   1619 }
   1620 
   1621 void WebContentsImpl::CreateNewWidget(int render_process_id,
   1622                                       int route_id,
   1623                                       blink::WebPopupType popup_type) {
   1624   CreateNewWidget(render_process_id, route_id, false, popup_type);
   1625 }
   1626 
   1627 void WebContentsImpl::CreateNewFullscreenWidget(int render_process_id,
   1628                                                 int route_id) {
   1629   CreateNewWidget(render_process_id, route_id, true, blink::WebPopupTypeNone);
   1630 }
   1631 
   1632 void WebContentsImpl::CreateNewWidget(int render_process_id,
   1633                                       int route_id,
   1634                                       bool is_fullscreen,
   1635                                       blink::WebPopupType popup_type) {
   1636   RenderProcessHost* process = GetRenderProcessHost();
   1637   // A message to create a new widget can only come from the active process for
   1638   // this WebContentsImpl instance. If any other process sends the request,
   1639   // it is invalid and the process must be terminated.
   1640   if (process->GetID() != render_process_id) {
   1641     base::ProcessHandle process_handle =
   1642         RenderProcessHost::FromID(render_process_id)->GetHandle();
   1643     if (process_handle != base::kNullProcessHandle) {
   1644       RecordAction(
   1645           base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWidget"));
   1646       base::KillProcess(process_handle, RESULT_CODE_KILLED, false);
   1647     }
   1648     return;
   1649   }
   1650 
   1651   RenderWidgetHostImpl* widget_host =
   1652       new RenderWidgetHostImpl(this, process, route_id, IsHidden());
   1653   created_widgets_.insert(widget_host);
   1654 
   1655   RenderWidgetHostViewBase* widget_view =
   1656       static_cast<RenderWidgetHostViewBase*>(
   1657           view_->CreateViewForPopupWidget(widget_host));
   1658   if (!widget_view)
   1659     return;
   1660   if (!is_fullscreen) {
   1661     // Popups should not get activated.
   1662     widget_view->SetPopupType(popup_type);
   1663   }
   1664   // Save the created widget associated with the route so we can show it later.
   1665   pending_widget_views_[route_id] = widget_view;
   1666 
   1667 #if defined(OS_MACOSX)
   1668   // A RenderWidgetHostViewMac has lifetime scoped to the view. We'll retain it
   1669   // to allow it to survive the trip without being hosted.
   1670   base::mac::NSObjectRetain(widget_view->GetNativeView());
   1671 #endif
   1672 }
   1673 
   1674 void WebContentsImpl::ShowCreatedWindow(int route_id,
   1675                                         WindowOpenDisposition disposition,
   1676                                         const gfx::Rect& initial_pos,
   1677                                         bool user_gesture) {
   1678   WebContentsImpl* contents = GetCreatedWindow(route_id);
   1679   if (contents) {
   1680     WebContentsDelegate* delegate = GetDelegate();
   1681     if (delegate) {
   1682       delegate->AddNewContents(
   1683           this, contents, disposition, initial_pos, user_gesture, NULL);
   1684     }
   1685   }
   1686 }
   1687 
   1688 void WebContentsImpl::ShowCreatedWidget(int route_id,
   1689                                         const gfx::Rect& initial_pos) {
   1690   ShowCreatedWidget(route_id, false, initial_pos);
   1691 }
   1692 
   1693 void WebContentsImpl::ShowCreatedFullscreenWidget(int route_id) {
   1694   ShowCreatedWidget(route_id, true, gfx::Rect());
   1695 }
   1696 
   1697 void WebContentsImpl::ShowCreatedWidget(int route_id,
   1698                                         bool is_fullscreen,
   1699                                         const gfx::Rect& initial_pos) {
   1700   RenderWidgetHostViewBase* widget_host_view =
   1701       static_cast<RenderWidgetHostViewBase*>(GetCreatedWidget(route_id));
   1702   if (!widget_host_view)
   1703     return;
   1704 
   1705   RenderWidgetHostView* view = NULL;
   1706   BrowserPluginGuest* guest = GetBrowserPluginGuest();
   1707   if (guest && guest->embedder_web_contents()) {
   1708     view = guest->embedder_web_contents()->GetRenderWidgetHostView();
   1709   } else {
   1710     view = GetRenderWidgetHostView();
   1711   }
   1712 
   1713   if (is_fullscreen) {
   1714     DCHECK_EQ(MSG_ROUTING_NONE, fullscreen_widget_routing_id_);
   1715     view_->StoreFocus();
   1716     fullscreen_widget_routing_id_ = route_id;
   1717     if (delegate_ && delegate_->EmbedsFullscreenWidget()) {
   1718       widget_host_view->InitAsChild(GetRenderWidgetHostView()->GetNativeView());
   1719       delegate_->ToggleFullscreenModeForTab(this, true);
   1720     } else {
   1721       widget_host_view->InitAsFullscreen(view);
   1722     }
   1723     FOR_EACH_OBSERVER(WebContentsObserver,
   1724                       observers_,
   1725                       DidShowFullscreenWidget(route_id));
   1726     if (!widget_host_view->HasFocus())
   1727       widget_host_view->Focus();
   1728   } else {
   1729     widget_host_view->InitAsPopup(view, initial_pos);
   1730   }
   1731 
   1732   RenderWidgetHostImpl* render_widget_host_impl =
   1733       RenderWidgetHostImpl::From(widget_host_view->GetRenderWidgetHost());
   1734   render_widget_host_impl->Init();
   1735   // Only allow privileged mouse lock for fullscreen render widget, which is
   1736   // used to implement Pepper Flash fullscreen.
   1737   render_widget_host_impl->set_allow_privileged_mouse_lock(is_fullscreen);
   1738 
   1739 #if defined(OS_MACOSX)
   1740   // A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's
   1741   // properly embedded (or purposefully ignored) we can release the retain we
   1742   // took in CreateNewWidget().
   1743   base::mac::NSObjectRelease(widget_host_view->GetNativeView());
   1744 #endif
   1745 }
   1746 
   1747 WebContentsImpl* WebContentsImpl::GetCreatedWindow(int route_id) {
   1748   PendingContents::iterator iter = pending_contents_.find(route_id);
   1749 
   1750   // Certain systems can block the creation of new windows. If we didn't succeed
   1751   // in creating one, just return NULL.
   1752   if (iter == pending_contents_.end()) {
   1753     return NULL;
   1754   }
   1755 
   1756   WebContentsImpl* new_contents = iter->second;
   1757   pending_contents_.erase(route_id);
   1758   RemoveDestructionObserver(new_contents);
   1759 
   1760   // Don't initialize the guest WebContents immediately.
   1761   if (BrowserPluginGuest::IsGuest(new_contents))
   1762     return new_contents;
   1763 
   1764   if (!new_contents->GetRenderProcessHost()->HasConnection() ||
   1765       !new_contents->GetRenderViewHost()->GetView())
   1766     return NULL;
   1767 
   1768   // Resume blocked requests for both the RenderViewHost and RenderFrameHost.
   1769   // TODO(brettw): It seems bogus to reach into here and initialize the host.
   1770   static_cast<RenderViewHostImpl*>(new_contents->GetRenderViewHost())->Init();
   1771   static_cast<RenderFrameHostImpl*>(new_contents->GetMainFrame())->Init();
   1772 
   1773   return new_contents;
   1774 }
   1775 
   1776 RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int route_id) {
   1777   PendingWidgetViews::iterator iter = pending_widget_views_.find(route_id);
   1778   if (iter == pending_widget_views_.end()) {
   1779     DCHECK(false);
   1780     return NULL;
   1781   }
   1782 
   1783   RenderWidgetHostView* widget_host_view = iter->second;
   1784   pending_widget_views_.erase(route_id);
   1785 
   1786   RenderWidgetHost* widget_host = widget_host_view->GetRenderWidgetHost();
   1787   if (!widget_host->GetProcess()->HasConnection()) {
   1788     // The view has gone away or the renderer crashed. Nothing to do.
   1789     return NULL;
   1790   }
   1791 
   1792   return widget_host_view;
   1793 }
   1794 
   1795 void WebContentsImpl::RequestMediaAccessPermission(
   1796     const MediaStreamRequest& request,
   1797     const MediaResponseCallback& callback) {
   1798   if (delegate_) {
   1799     delegate_->RequestMediaAccessPermission(this, request, callback);
   1800   } else {
   1801     callback.Run(MediaStreamDevices(),
   1802                  MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN,
   1803                  scoped_ptr<MediaStreamUI>());
   1804   }
   1805 }
   1806 
   1807 bool WebContentsImpl::CheckMediaAccessPermission(const GURL& security_origin,
   1808                                                  MediaStreamType type) {
   1809   DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
   1810          type == MEDIA_DEVICE_VIDEO_CAPTURE);
   1811   return delegate_ &&
   1812          delegate_->CheckMediaAccessPermission(this, security_origin, type);
   1813 }
   1814 
   1815 SessionStorageNamespace* WebContentsImpl::GetSessionStorageNamespace(
   1816     SiteInstance* instance) {
   1817   return controller_.GetSessionStorageNamespace(instance);
   1818 }
   1819 
   1820 SessionStorageNamespaceMap WebContentsImpl::GetSessionStorageNamespaceMap() {
   1821   return controller_.GetSessionStorageNamespaceMap();
   1822 }
   1823 
   1824 FrameTree* WebContentsImpl::GetFrameTree() {
   1825   return &frame_tree_;
   1826 }
   1827 
   1828 void WebContentsImpl::SetIsVirtualKeyboardRequested(bool requested) {
   1829   virtual_keyboard_requested_ = requested;
   1830 }
   1831 
   1832 bool WebContentsImpl::IsVirtualKeyboardRequested() {
   1833   return virtual_keyboard_requested_;
   1834 }
   1835 
   1836 AccessibilityMode WebContentsImpl::GetAccessibilityMode() const {
   1837   return accessibility_mode_;
   1838 }
   1839 
   1840 void WebContentsImpl::AccessibilityEventReceived(
   1841     const std::vector<AXEventNotificationDetails>& details) {
   1842   FOR_EACH_OBSERVER(
   1843       WebContentsObserver, observers_, AccessibilityEventReceived(details));
   1844 }
   1845 
   1846 RenderFrameHost* WebContentsImpl::GetGuestByInstanceID(
   1847     int browser_plugin_instance_id) {
   1848   BrowserPluginGuestManager* guest_manager =
   1849       GetBrowserContext()->GetGuestManager();
   1850   WebContents* guest = guest_manager->GetGuestByInstanceID(
   1851       this, browser_plugin_instance_id);
   1852   if (!guest)
   1853     return NULL;
   1854   return guest->GetMainFrame();
   1855 }
   1856 
   1857 void WebContentsImpl::OnShowValidationMessage(
   1858     const gfx::Rect& anchor_in_root_view,
   1859     const base::string16& main_text,
   1860     const base::string16& sub_text) {
   1861   if (delegate_)
   1862     delegate_->ShowValidationMessage(
   1863         this, anchor_in_root_view, main_text, sub_text);
   1864 }
   1865 
   1866 void WebContentsImpl::OnHideValidationMessage() {
   1867   if (delegate_)
   1868     delegate_->HideValidationMessage(this);
   1869 }
   1870 
   1871 void WebContentsImpl::OnMoveValidationMessage(
   1872     const gfx::Rect& anchor_in_root_view) {
   1873   if (delegate_)
   1874     delegate_->MoveValidationMessage(this, anchor_in_root_view);
   1875 }
   1876 
   1877 void WebContentsImpl::DidSendScreenRects(RenderWidgetHostImpl* rwh) {
   1878   if (browser_plugin_embedder_)
   1879     browser_plugin_embedder_->DidSendScreenRects();
   1880 }
   1881 
   1882 BrowserAccessibilityManager*
   1883     WebContentsImpl::GetRootBrowserAccessibilityManager() {
   1884   RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame());
   1885   return rfh ? rfh->browser_accessibility_manager() : NULL;
   1886 }
   1887 
   1888 BrowserAccessibilityManager*
   1889     WebContentsImpl::GetOrCreateRootBrowserAccessibilityManager() {
   1890   RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame());
   1891   return rfh ? rfh->GetOrCreateBrowserAccessibilityManager() : NULL;
   1892 }
   1893 
   1894 void WebContentsImpl::UpdatePreferredSize(const gfx::Size& pref_size) {
   1895   const gfx::Size old_size = GetPreferredSize();
   1896   preferred_size_ = pref_size;
   1897   OnPreferredSizeChanged(old_size);
   1898 }
   1899 
   1900 void WebContentsImpl::ResizeDueToAutoResize(const gfx::Size& new_size) {
   1901   if (delegate_)
   1902     delegate_->ResizeDueToAutoResize(this, new_size);
   1903 }
   1904 
   1905 WebContents* WebContentsImpl::OpenURL(const OpenURLParams& params) {
   1906   if (!delegate_)
   1907     return NULL;
   1908 
   1909   WebContents* new_contents = delegate_->OpenURLFromTab(this, params);
   1910   return new_contents;
   1911 }
   1912 
   1913 bool WebContentsImpl::Send(IPC::Message* message) {
   1914   if (!GetRenderViewHost()) {
   1915     delete message;
   1916     return false;
   1917   }
   1918 
   1919   return GetRenderViewHost()->Send(message);
   1920 }
   1921 
   1922 bool WebContentsImpl::NavigateToPendingEntry(
   1923     NavigationController::ReloadType reload_type) {
   1924   FrameTreeNode* node = frame_tree_.root();
   1925 
   1926   // Navigate in the FrameTreeNode specified in the pending entry, if any.  This
   1927   // is currently only used in --site-per-process and tests.
   1928   NavigationEntryImpl* pending_entry =
   1929       NavigationEntryImpl::FromNavigationEntry(controller_.GetPendingEntry());
   1930   if (pending_entry->frame_tree_node_id() != -1) {
   1931     FrameTreeNode* subframe =
   1932         frame_tree_.FindByID(pending_entry->frame_tree_node_id());
   1933     DCHECK(subframe);
   1934     if (subframe)
   1935       node = subframe;
   1936   }
   1937 
   1938   return node->navigator()->NavigateToPendingEntry(
   1939       node->current_frame_host(), reload_type);
   1940 }
   1941 
   1942 void WebContentsImpl::RenderFrameForInterstitialPageCreated(
   1943     RenderFrameHost* render_frame_host) {
   1944   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   1945                     RenderFrameForInterstitialPageCreated(render_frame_host));
   1946 }
   1947 
   1948 void WebContentsImpl::AttachInterstitialPage(
   1949     InterstitialPageImpl* interstitial_page) {
   1950   DCHECK(interstitial_page);
   1951   GetRenderManager()->set_interstitial_page(interstitial_page);
   1952 
   1953   // Cancel any visible dialogs so that they don't interfere with the
   1954   // interstitial.
   1955   if (dialog_manager_)
   1956     dialog_manager_->CancelActiveAndPendingDialogs(this);
   1957 
   1958   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   1959                     DidAttachInterstitialPage());
   1960 }
   1961 
   1962 void WebContentsImpl::DetachInterstitialPage() {
   1963   if (ShowingInterstitialPage())
   1964     GetRenderManager()->remove_interstitial_page();
   1965   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   1966                     DidDetachInterstitialPage());
   1967 }
   1968 
   1969 void WebContentsImpl::SetHistoryLengthAndPrune(
   1970     const SiteInstance* site_instance,
   1971     int history_length,
   1972     int32 minimum_page_id) {
   1973   // SetHistoryLengthAndPrune doesn't work when there are pending cross-site
   1974   // navigations. Callers should ensure that this is the case.
   1975   if (GetRenderManager()->pending_render_view_host()) {
   1976     NOTREACHED();
   1977     return;
   1978   }
   1979   RenderViewHostImpl* rvh = GetRenderViewHostImpl();
   1980   if (!rvh) {
   1981     NOTREACHED();
   1982     return;
   1983   }
   1984   if (site_instance && rvh->GetSiteInstance() != site_instance) {
   1985     NOTREACHED();
   1986     return;
   1987   }
   1988   Send(new ViewMsg_SetHistoryLengthAndPrune(GetRoutingID(),
   1989                                             history_length,
   1990                                             minimum_page_id));
   1991 }
   1992 
   1993 void WebContentsImpl::ReloadFocusedFrame(bool ignore_cache) {
   1994   RenderFrameHost* focused_frame = GetFocusedFrame();
   1995   if (!focused_frame)
   1996     return;
   1997 
   1998   focused_frame->Send(new FrameMsg_Reload(
   1999       focused_frame->GetRoutingID(), ignore_cache));
   2000 }
   2001 
   2002 void WebContentsImpl::Undo() {
   2003   RenderFrameHost* focused_frame = GetFocusedFrame();
   2004   if (!focused_frame)
   2005     return;
   2006 
   2007   focused_frame->Send(new InputMsg_Undo(focused_frame->GetRoutingID()));
   2008   RecordAction(base::UserMetricsAction("Undo"));
   2009 }
   2010 
   2011 void WebContentsImpl::Redo() {
   2012   RenderFrameHost* focused_frame = GetFocusedFrame();
   2013   if (!focused_frame)
   2014     return;
   2015   focused_frame->Send(new InputMsg_Redo(focused_frame->GetRoutingID()));
   2016   RecordAction(base::UserMetricsAction("Redo"));
   2017 }
   2018 
   2019 void WebContentsImpl::Cut() {
   2020   RenderFrameHost* focused_frame = GetFocusedFrame();
   2021   if (!focused_frame)
   2022     return;
   2023 
   2024   focused_frame->Send(new InputMsg_Cut(focused_frame->GetRoutingID()));
   2025   RecordAction(base::UserMetricsAction("Cut"));
   2026 }
   2027 
   2028 void WebContentsImpl::Copy() {
   2029   RenderFrameHost* focused_frame = GetFocusedFrame();
   2030   if (!focused_frame)
   2031     return;
   2032 
   2033   focused_frame->Send(new InputMsg_Copy(focused_frame->GetRoutingID()));
   2034   RecordAction(base::UserMetricsAction("Copy"));
   2035 }
   2036 
   2037 void WebContentsImpl::CopyToFindPboard() {
   2038 #if defined(OS_MACOSX)
   2039   RenderFrameHost* focused_frame = GetFocusedFrame();
   2040   if (!focused_frame)
   2041     return;
   2042 
   2043   // Windows/Linux don't have the concept of a find pasteboard.
   2044   focused_frame->Send(
   2045       new InputMsg_CopyToFindPboard(focused_frame->GetRoutingID()));
   2046   RecordAction(base::UserMetricsAction("CopyToFindPboard"));
   2047 #endif
   2048 }
   2049 
   2050 void WebContentsImpl::Paste() {
   2051   RenderFrameHost* focused_frame = GetFocusedFrame();
   2052   if (!focused_frame)
   2053     return;
   2054 
   2055   focused_frame->Send(new InputMsg_Paste(focused_frame->GetRoutingID()));
   2056   RecordAction(base::UserMetricsAction("Paste"));
   2057 }
   2058 
   2059 void WebContentsImpl::PasteAndMatchStyle() {
   2060   RenderFrameHost* focused_frame = GetFocusedFrame();
   2061   if (!focused_frame)
   2062     return;
   2063 
   2064   focused_frame->Send(new InputMsg_PasteAndMatchStyle(
   2065       focused_frame->GetRoutingID()));
   2066   RecordAction(base::UserMetricsAction("PasteAndMatchStyle"));
   2067 }
   2068 
   2069 void WebContentsImpl::Delete() {
   2070   RenderFrameHost* focused_frame = GetFocusedFrame();
   2071   if (!focused_frame)
   2072     return;
   2073 
   2074   focused_frame->Send(new InputMsg_Delete(focused_frame->GetRoutingID()));
   2075   RecordAction(base::UserMetricsAction("DeleteSelection"));
   2076 }
   2077 
   2078 void WebContentsImpl::SelectAll() {
   2079   RenderFrameHost* focused_frame = GetFocusedFrame();
   2080   if (!focused_frame)
   2081     return;
   2082 
   2083   focused_frame->Send(new InputMsg_SelectAll(focused_frame->GetRoutingID()));
   2084   RecordAction(base::UserMetricsAction("SelectAll"));
   2085 }
   2086 
   2087 void WebContentsImpl::Unselect() {
   2088   RenderFrameHost* focused_frame = GetFocusedFrame();
   2089   if (!focused_frame)
   2090     return;
   2091 
   2092   focused_frame->Send(new InputMsg_Unselect(focused_frame->GetRoutingID()));
   2093   RecordAction(base::UserMetricsAction("Unselect"));
   2094 }
   2095 
   2096 void WebContentsImpl::Replace(const base::string16& word) {
   2097   RenderFrameHost* focused_frame = GetFocusedFrame();
   2098   if (!focused_frame)
   2099     return;
   2100 
   2101   focused_frame->Send(new InputMsg_Replace(
   2102       focused_frame->GetRoutingID(), word));
   2103 }
   2104 
   2105 void WebContentsImpl::ReplaceMisspelling(const base::string16& word) {
   2106   RenderFrameHost* focused_frame = GetFocusedFrame();
   2107   if (!focused_frame)
   2108     return;
   2109 
   2110   focused_frame->Send(new InputMsg_ReplaceMisspelling(
   2111       focused_frame->GetRoutingID(), word));
   2112 }
   2113 
   2114 void WebContentsImpl::NotifyContextMenuClosed(
   2115     const CustomContextMenuContext& context) {
   2116   RenderFrameHost* focused_frame = GetFocusedFrame();
   2117   if (!focused_frame)
   2118     return;
   2119 
   2120   focused_frame->Send(new FrameMsg_ContextMenuClosed(
   2121       focused_frame->GetRoutingID(), context));
   2122 }
   2123 
   2124 void WebContentsImpl::ExecuteCustomContextMenuCommand(
   2125     int action, const CustomContextMenuContext& context) {
   2126   RenderFrameHost* focused_frame = GetFocusedFrame();
   2127   if (!focused_frame)
   2128     return;
   2129 
   2130   focused_frame->Send(new FrameMsg_CustomContextMenuAction(
   2131       focused_frame->GetRoutingID(), context, action));
   2132 }
   2133 
   2134 gfx::NativeView WebContentsImpl::GetNativeView() {
   2135   return view_->GetNativeView();
   2136 }
   2137 
   2138 gfx::NativeView WebContentsImpl::GetContentNativeView() {
   2139   return view_->GetContentNativeView();
   2140 }
   2141 
   2142 gfx::NativeWindow WebContentsImpl::GetTopLevelNativeWindow() {
   2143   return view_->GetTopLevelNativeWindow();
   2144 }
   2145 
   2146 gfx::Rect WebContentsImpl::GetViewBounds() {
   2147   return view_->GetViewBounds();
   2148 }
   2149 
   2150 gfx::Rect WebContentsImpl::GetContainerBounds() {
   2151   gfx::Rect rv;
   2152   view_->GetContainerBounds(&rv);
   2153   return rv;
   2154 }
   2155 
   2156 DropData* WebContentsImpl::GetDropData() {
   2157   return view_->GetDropData();
   2158 }
   2159 
   2160 void WebContentsImpl::Focus() {
   2161   RenderWidgetHostView* const fullscreen_view =
   2162       GetFullscreenRenderWidgetHostView();
   2163   if (fullscreen_view)
   2164     fullscreen_view->Focus();
   2165   else
   2166     view_->Focus();
   2167 }
   2168 
   2169 void WebContentsImpl::SetInitialFocus() {
   2170   RenderWidgetHostView* const fullscreen_view =
   2171       GetFullscreenRenderWidgetHostView();
   2172   if (fullscreen_view)
   2173     fullscreen_view->Focus();
   2174   else
   2175     view_->SetInitialFocus();
   2176 }
   2177 
   2178 void WebContentsImpl::StoreFocus() {
   2179   if (!GetFullscreenRenderWidgetHostView())
   2180     view_->StoreFocus();
   2181 }
   2182 
   2183 void WebContentsImpl::RestoreFocus() {
   2184   RenderWidgetHostView* const fullscreen_view =
   2185       GetFullscreenRenderWidgetHostView();
   2186   if (fullscreen_view)
   2187     fullscreen_view->Focus();
   2188   else
   2189     view_->RestoreFocus();
   2190 }
   2191 
   2192 void WebContentsImpl::FocusThroughTabTraversal(bool reverse) {
   2193   if (ShowingInterstitialPage()) {
   2194     GetRenderManager()->interstitial_page()->FocusThroughTabTraversal(reverse);
   2195     return;
   2196   }
   2197   RenderWidgetHostView* const fullscreen_view =
   2198       GetFullscreenRenderWidgetHostView();
   2199   if (fullscreen_view) {
   2200     fullscreen_view->Focus();
   2201     return;
   2202   }
   2203   GetRenderViewHostImpl()->SetInitialFocus(reverse);
   2204 }
   2205 
   2206 bool WebContentsImpl::ShowingInterstitialPage() const {
   2207   return GetRenderManager()->interstitial_page() != NULL;
   2208 }
   2209 
   2210 InterstitialPage* WebContentsImpl::GetInterstitialPage() const {
   2211   return GetRenderManager()->interstitial_page();
   2212 }
   2213 
   2214 bool WebContentsImpl::IsSavable() {
   2215   // WebKit creates Document object when MIME type is application/xhtml+xml,
   2216   // so we also support this MIME type.
   2217   return contents_mime_type_ == "text/html" ||
   2218          contents_mime_type_ == "text/xml" ||
   2219          contents_mime_type_ == "application/xhtml+xml" ||
   2220          contents_mime_type_ == "text/plain" ||
   2221          contents_mime_type_ == "text/css" ||
   2222          net::IsSupportedJavascriptMimeType(contents_mime_type_.c_str());
   2223 }
   2224 
   2225 void WebContentsImpl::OnSavePage() {
   2226   // If we can not save the page, try to download it.
   2227   if (!IsSavable()) {
   2228     RecordDownloadSource(INITIATED_BY_SAVE_PACKAGE_ON_NON_HTML);
   2229     SaveFrame(GetURL(), Referrer());
   2230     return;
   2231   }
   2232 
   2233   Stop();
   2234 
   2235   // Create the save package and possibly prompt the user for the name to save
   2236   // the page as. The user prompt is an asynchronous operation that runs on
   2237   // another thread.
   2238   save_package_ = new SavePackage(this);
   2239   save_package_->GetSaveInfo();
   2240 }
   2241 
   2242 // Used in automated testing to bypass prompting the user for file names.
   2243 // Instead, the names and paths are hard coded rather than running them through
   2244 // file name sanitation and extension / mime checking.
   2245 bool WebContentsImpl::SavePage(const base::FilePath& main_file,
   2246                                const base::FilePath& dir_path,
   2247                                SavePageType save_type) {
   2248   // Stop the page from navigating.
   2249   Stop();
   2250 
   2251   save_package_ = new SavePackage(this, save_type, main_file, dir_path);
   2252   return save_package_->Init(SavePackageDownloadCreatedCallback());
   2253 }
   2254 
   2255 void WebContentsImpl::SaveFrame(const GURL& url,
   2256                                 const Referrer& referrer) {
   2257   if (!GetURL().is_valid())
   2258     return;
   2259   bool is_main_frame = (url == GetURL());
   2260 
   2261   DownloadManager* dlm =
   2262       BrowserContext::GetDownloadManager(GetBrowserContext());
   2263   if (!dlm)
   2264     return;
   2265   int64 post_id = -1;
   2266   if (is_main_frame) {
   2267     const NavigationEntry* entry = controller_.GetLastCommittedEntry();
   2268     if (entry)
   2269       post_id = entry->GetPostID();
   2270   }
   2271   scoped_ptr<DownloadUrlParameters> params(
   2272       DownloadUrlParameters::FromWebContents(this, url));
   2273   params->set_referrer(referrer);
   2274   params->set_post_id(post_id);
   2275   params->set_prefer_cache(true);
   2276   if (post_id >= 0)
   2277     params->set_method("POST");
   2278   params->set_prompt(true);
   2279   dlm->DownloadUrl(params.Pass());
   2280 }
   2281 
   2282 void WebContentsImpl::GenerateMHTML(
   2283     const base::FilePath& file,
   2284     const base::Callback<void(int64)>& callback) {
   2285   MHTMLGenerationManager::GetInstance()->SaveMHTML(this, file, callback);
   2286 }
   2287 
   2288 const std::string& WebContentsImpl::GetContentsMimeType() const {
   2289   return contents_mime_type_;
   2290 }
   2291 
   2292 bool WebContentsImpl::WillNotifyDisconnection() const {
   2293   return notify_disconnection_;
   2294 }
   2295 
   2296 void WebContentsImpl::SetOverrideEncoding(const std::string& encoding) {
   2297   SetEncoding(encoding);
   2298   Send(new ViewMsg_SetPageEncoding(GetRoutingID(), encoding));
   2299 }
   2300 
   2301 void WebContentsImpl::ResetOverrideEncoding() {
   2302   canonical_encoding_.clear();
   2303   Send(new ViewMsg_ResetPageEncodingToDefault(GetRoutingID()));
   2304 }
   2305 
   2306 RendererPreferences* WebContentsImpl::GetMutableRendererPrefs() {
   2307   return &renderer_preferences_;
   2308 }
   2309 
   2310 void WebContentsImpl::Close() {
   2311   Close(GetRenderViewHost());
   2312 }
   2313 
   2314 void WebContentsImpl::DragSourceEndedAt(int client_x, int client_y,
   2315     int screen_x, int screen_y, blink::WebDragOperation operation) {
   2316   if (browser_plugin_embedder_.get())
   2317     browser_plugin_embedder_->DragSourceEndedAt(client_x, client_y,
   2318         screen_x, screen_y, operation);
   2319   if (GetRenderViewHost())
   2320     GetRenderViewHostImpl()->DragSourceEndedAt(client_x, client_y,
   2321         screen_x, screen_y, operation);
   2322 }
   2323 
   2324 void WebContentsImpl::DidGetResourceResponseStart(
   2325   const ResourceRequestDetails& details) {
   2326   controller_.ssl_manager()->DidStartResourceResponse(details);
   2327 
   2328   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2329                     DidGetResourceResponseStart(details));
   2330 
   2331   // TODO(avi): Remove. http://crbug.com/170921
   2332   NotificationService::current()->Notify(
   2333       NOTIFICATION_RESOURCE_RESPONSE_STARTED,
   2334       Source<WebContents>(this),
   2335       Details<const ResourceRequestDetails>(&details));
   2336 }
   2337 
   2338 void WebContentsImpl::DidGetRedirectForResourceRequest(
   2339   RenderViewHost* render_view_host,
   2340   const ResourceRedirectDetails& details) {
   2341   controller_.ssl_manager()->DidReceiveResourceRedirect(details);
   2342 
   2343   FOR_EACH_OBSERVER(
   2344       WebContentsObserver,
   2345       observers_,
   2346       DidGetRedirectForResourceRequest(render_view_host, details));
   2347 
   2348   // TODO(avi): Remove. http://crbug.com/170921
   2349   NotificationService::current()->Notify(
   2350       NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
   2351       Source<WebContents>(this),
   2352       Details<const ResourceRedirectDetails>(&details));
   2353 }
   2354 
   2355 void WebContentsImpl::SystemDragEnded() {
   2356   if (GetRenderViewHost())
   2357     GetRenderViewHostImpl()->DragSourceSystemDragEnded();
   2358   if (delegate_)
   2359     delegate_->DragEnded();
   2360   if (browser_plugin_embedder_.get())
   2361     browser_plugin_embedder_->SystemDragEnded();
   2362 }
   2363 
   2364 void WebContentsImpl::UserGestureDone() {
   2365   OnUserGesture();
   2366 }
   2367 
   2368 void WebContentsImpl::SetClosedByUserGesture(bool value) {
   2369   closed_by_user_gesture_ = value;
   2370 }
   2371 
   2372 bool WebContentsImpl::GetClosedByUserGesture() const {
   2373   return closed_by_user_gesture_;
   2374 }
   2375 
   2376 void WebContentsImpl::ViewSource() {
   2377   if (!delegate_)
   2378     return;
   2379 
   2380   NavigationEntry* entry = GetController().GetLastCommittedEntry();
   2381   if (!entry)
   2382     return;
   2383 
   2384   delegate_->ViewSourceForTab(this, entry->GetURL());
   2385 }
   2386 
   2387 void WebContentsImpl::ViewFrameSource(const GURL& url,
   2388                                       const PageState& page_state) {
   2389   if (!delegate_)
   2390     return;
   2391 
   2392   delegate_->ViewSourceForFrame(this, url, page_state);
   2393 }
   2394 
   2395 int WebContentsImpl::GetMinimumZoomPercent() const {
   2396   return minimum_zoom_percent_;
   2397 }
   2398 
   2399 int WebContentsImpl::GetMaximumZoomPercent() const {
   2400   return maximum_zoom_percent_;
   2401 }
   2402 
   2403 gfx::Size WebContentsImpl::GetPreferredSize() const {
   2404   return capturer_count_ == 0 ? preferred_size_ : preferred_size_for_capture_;
   2405 }
   2406 
   2407 bool WebContentsImpl::GotResponseToLockMouseRequest(bool allowed) {
   2408   if (GetBrowserPluginGuest())
   2409     return GetBrowserPluginGuest()->LockMouse(allowed);
   2410 
   2411   return GetRenderViewHost() ?
   2412       GetRenderViewHostImpl()->GotResponseToLockMouseRequest(allowed) : false;
   2413 }
   2414 
   2415 bool WebContentsImpl::HasOpener() const {
   2416   return opener_ != NULL;
   2417 }
   2418 
   2419 void WebContentsImpl::DidChooseColorInColorChooser(SkColor color) {
   2420   if (!color_chooser_info_.get())
   2421     return;
   2422   RenderFrameHost* rfh = RenderFrameHost::FromID(
   2423       color_chooser_info_->render_process_id,
   2424       color_chooser_info_->render_frame_id);
   2425   if (!rfh)
   2426     return;
   2427 
   2428   rfh->Send(new FrameMsg_DidChooseColorResponse(
   2429       rfh->GetRoutingID(), color_chooser_info_->identifier, color));
   2430 }
   2431 
   2432 void WebContentsImpl::DidEndColorChooser() {
   2433   if (!color_chooser_info_.get())
   2434     return;
   2435   RenderFrameHost* rfh = RenderFrameHost::FromID(
   2436       color_chooser_info_->render_process_id,
   2437       color_chooser_info_->render_frame_id);
   2438   if (!rfh)
   2439     return;
   2440 
   2441   rfh->Send(new FrameMsg_DidEndColorChooser(
   2442       rfh->GetRoutingID(), color_chooser_info_->identifier));
   2443   color_chooser_info_.reset();
   2444 }
   2445 
   2446 int WebContentsImpl::DownloadImage(const GURL& url,
   2447                                    bool is_favicon,
   2448                                    uint32_t max_bitmap_size,
   2449                                    const ImageDownloadCallback& callback) {
   2450   int id = StartDownload(GetMainFrame(), url, is_favicon, max_bitmap_size);
   2451   image_download_map_[id] = callback;
   2452   return id;
   2453 }
   2454 
   2455 bool WebContentsImpl::IsSubframe() const {
   2456   return is_subframe_;
   2457 }
   2458 
   2459 void WebContentsImpl::Find(int request_id,
   2460                            const base::string16& search_text,
   2461                            const blink::WebFindOptions& options) {
   2462   Send(new ViewMsg_Find(GetRoutingID(), request_id, search_text, options));
   2463 }
   2464 
   2465 void WebContentsImpl::StopFinding(StopFindAction action) {
   2466   Send(new ViewMsg_StopFinding(GetRoutingID(), action));
   2467 }
   2468 
   2469 void WebContentsImpl::InsertCSS(const std::string& css) {
   2470   GetMainFrame()->Send(new FrameMsg_CSSInsertRequest(
   2471       GetMainFrame()->GetRoutingID(), css));
   2472 }
   2473 
   2474 bool WebContentsImpl::WasRecentlyAudible() {
   2475   return audio_stream_monitor_.WasRecentlyAudible();
   2476 }
   2477 
   2478 void WebContentsImpl::GetManifest(const GetManifestCallback& callback) {
   2479   manifest_manager_host_->GetManifest(GetMainFrame(), callback);
   2480 }
   2481 
   2482 bool WebContentsImpl::FocusLocationBarByDefault() {
   2483   NavigationEntry* entry = controller_.GetVisibleEntry();
   2484   if (entry && entry->GetURL() == GURL(url::kAboutBlankURL))
   2485     return true;
   2486   return delegate_ && delegate_->ShouldFocusLocationBarByDefault(this);
   2487 }
   2488 
   2489 void WebContentsImpl::SetFocusToLocationBar(bool select_all) {
   2490   if (delegate_)
   2491     delegate_->SetFocusToLocationBar(select_all);
   2492 }
   2493 
   2494 void WebContentsImpl::DidStartProvisionalLoad(
   2495     RenderFrameHostImpl* render_frame_host,
   2496     const GURL& validated_url,
   2497     bool is_error_page,
   2498     bool is_iframe_srcdoc) {
   2499   // Notify observers about the start of the provisional load.
   2500   FOR_EACH_OBSERVER(
   2501       WebContentsObserver,
   2502       observers_,
   2503       DidStartProvisionalLoadForFrame(
   2504           render_frame_host, validated_url, is_error_page, is_iframe_srcdoc));
   2505 }
   2506 
   2507 void WebContentsImpl::DidStartNavigationTransition(
   2508     RenderFrameHostImpl* render_frame_host) {
   2509 #if defined(OS_ANDROID)
   2510   int render_frame_id = render_frame_host->GetRoutingID();
   2511   GetWebContentsAndroid()->DidStartNavigationTransitionForFrame(
   2512       render_frame_id);
   2513 #endif
   2514 }
   2515 
   2516 void WebContentsImpl::DidFailProvisionalLoadWithError(
   2517     RenderFrameHostImpl* render_frame_host,
   2518     const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) {
   2519   GURL validated_url(params.url);
   2520   FOR_EACH_OBSERVER(WebContentsObserver,
   2521                     observers_,
   2522                     DidFailProvisionalLoad(render_frame_host,
   2523                                            validated_url,
   2524                                            params.error_code,
   2525                                            params.error_description));
   2526 }
   2527 
   2528 void WebContentsImpl::DidFailLoadWithError(
   2529     RenderFrameHostImpl* render_frame_host,
   2530     const GURL& url,
   2531     int error_code,
   2532     const base::string16& error_description) {
   2533   FOR_EACH_OBSERVER(
   2534       WebContentsObserver,
   2535       observers_,
   2536       DidFailLoad(render_frame_host, url, error_code, error_description));
   2537 }
   2538 
   2539 void WebContentsImpl::NotifyChangedNavigationState(
   2540     InvalidateTypes changed_flags) {
   2541   NotifyNavigationStateChanged(changed_flags);
   2542 }
   2543 
   2544 void WebContentsImpl::AboutToNavigateRenderFrame(
   2545       RenderFrameHostImpl* render_frame_host) {
   2546   // Notify observers that we will navigate in this RenderView.
   2547   RenderViewHost* render_view_host = render_frame_host->render_view_host();
   2548   FOR_EACH_OBSERVER(
   2549       WebContentsObserver,
   2550       observers_,
   2551       AboutToNavigateRenderView(render_view_host));
   2552 }
   2553 
   2554 void WebContentsImpl::DidStartNavigationToPendingEntry(
   2555       RenderFrameHostImpl* render_frame_host,
   2556       const GURL& url,
   2557       NavigationController::ReloadType reload_type) {
   2558   // Notify observers about navigation.
   2559   FOR_EACH_OBSERVER(
   2560       WebContentsObserver,
   2561       observers_,
   2562       DidStartNavigationToPendingEntry(url, reload_type));
   2563 }
   2564 
   2565 void WebContentsImpl::RequestOpenURL(RenderFrameHostImpl* render_frame_host,
   2566                                      const OpenURLParams& params) {
   2567   int source_render_frame_id = render_frame_host->GetRoutingID();
   2568   WebContents* new_contents = OpenURL(params);
   2569 
   2570   if (new_contents) {
   2571     // Notify observers.
   2572     FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2573                       DidOpenRequestedURL(new_contents,
   2574                                           params.url,
   2575                                           params.referrer,
   2576                                           params.disposition,
   2577                                           params.transition,
   2578                                           source_render_frame_id));
   2579   }
   2580 }
   2581 
   2582 bool WebContentsImpl::ShouldPreserveAbortedURLs() {
   2583   if (!delegate_)
   2584     return false;
   2585   return delegate_->ShouldPreserveAbortedURLs(this);
   2586 }
   2587 
   2588 void WebContentsImpl::DidCommitProvisionalLoad(
   2589     RenderFrameHostImpl* render_frame_host,
   2590     const GURL& url,
   2591     ui::PageTransition transition_type) {
   2592   // Notify observers about the commit of the provisional load.
   2593   FOR_EACH_OBSERVER(WebContentsObserver,
   2594                     observers_,
   2595                     DidCommitProvisionalLoadForFrame(
   2596                         render_frame_host, url, transition_type));
   2597 }
   2598 
   2599 void WebContentsImpl::DidNavigateMainFramePreCommit(
   2600     bool navigation_is_within_page) {
   2601   // Ensure fullscreen mode is exited before committing the navigation to a
   2602   // different page.  The next page will not start out assuming it is in
   2603   // fullscreen mode.
   2604   if (navigation_is_within_page) {
   2605     // No page change?  Then, the renderer and browser can remain in fullscreen.
   2606     return;
   2607   }
   2608   if (IsFullscreenForCurrentTab())
   2609     GetRenderViewHost()->ExitFullscreen();
   2610   DCHECK(!IsFullscreenForCurrentTab());
   2611 }
   2612 
   2613 void WebContentsImpl::DidNavigateMainFramePostCommit(
   2614     const LoadCommittedDetails& details,
   2615     const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
   2616   if (details.is_navigation_to_different_page()) {
   2617     // Clear the status bubble. This is a workaround for a bug where WebKit
   2618     // doesn't let us know that the cursor left an element during a
   2619     // transition (this is also why the mouse cursor remains as a hand after
   2620     // clicking on a link); see bugs 1184641 and 980803. We don't want to
   2621     // clear the bubble when a user navigates to a named anchor in the same
   2622     // page.
   2623     UpdateTargetURL(GURL());
   2624   }
   2625 
   2626   if (!details.is_in_page) {
   2627     // Once the main frame is navigated, we're no longer considered to have
   2628     // displayed insecure content.
   2629     displayed_insecure_content_ = false;
   2630     SSLManager::NotifySSLInternalStateChanged(
   2631         GetController().GetBrowserContext());
   2632   }
   2633 
   2634   // Notify observers about navigation.
   2635   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2636                     DidNavigateMainFrame(details, params));
   2637 
   2638   if (delegate_)
   2639     delegate_->DidNavigateMainFramePostCommit(this);
   2640   view_->SetOverscrollControllerEnabled(CanOverscrollContent());
   2641 }
   2642 
   2643 void WebContentsImpl::DidNavigateAnyFramePostCommit(
   2644     RenderFrameHostImpl* render_frame_host,
   2645     const LoadCommittedDetails& details,
   2646     const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
   2647   // Now that something has committed, we don't need to track whether the
   2648   // initial page has been accessed.
   2649   has_accessed_initial_document_ = false;
   2650 
   2651   // If we navigate off the page, close all JavaScript dialogs.
   2652   if (dialog_manager_ && !details.is_in_page)
   2653     dialog_manager_->CancelActiveAndPendingDialogs(this);
   2654 
   2655   // Notify observers about navigation.
   2656   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2657                     DidNavigateAnyFrame(details, params));
   2658 }
   2659 
   2660 void WebContentsImpl::SetMainFrameMimeType(const std::string& mime_type) {
   2661   contents_mime_type_ = mime_type;
   2662 }
   2663 
   2664 bool WebContentsImpl::CanOverscrollContent() const {
   2665   // Disable overscroll when touch emulation is on. See crbug.com/369938.
   2666   if (force_disable_overscroll_content_)
   2667     return false;
   2668 
   2669   if (delegate_)
   2670     return delegate_->CanOverscrollContent();
   2671 
   2672   return false;
   2673 }
   2674 
   2675 void WebContentsImpl::OnThemeColorChanged(SkColor theme_color) {
   2676   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2677                     DidChangeThemeColor(theme_color));
   2678 }
   2679 
   2680 void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
   2681     const GURL& url,
   2682     const std::string& security_info,
   2683     const std::string& http_method,
   2684     const std::string& mime_type,
   2685     ResourceType resource_type) {
   2686   base::StatsCounter cache("WebKit.CacheHit");
   2687   cache.Increment();
   2688 
   2689   // Send out a notification that we loaded a resource from our memory cache.
   2690   int cert_id = 0;
   2691   net::CertStatus cert_status = 0;
   2692   int security_bits = -1;
   2693   int connection_status = 0;
   2694   SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
   2695   DeserializeSecurityInfo(security_info, &cert_id, &cert_status,
   2696                           &security_bits, &connection_status,
   2697                           &signed_certificate_timestamp_ids);
   2698   // TODO(alcutter,eranm): Pass signed_certificate_timestamp_ids into details
   2699   LoadFromMemoryCacheDetails details(
   2700       url, GetRenderProcessHost()->GetID(), cert_id, cert_status, http_method,
   2701       mime_type, resource_type);
   2702 
   2703   controller_.ssl_manager()->DidLoadFromMemoryCache(details);
   2704 
   2705   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2706                     DidLoadResourceFromMemoryCache(details));
   2707 
   2708   if (url.is_valid() && url.SchemeIsHTTPOrHTTPS()) {
   2709     scoped_refptr<net::URLRequestContextGetter> request_context(
   2710         resource_type == RESOURCE_TYPE_MEDIA ?
   2711             GetBrowserContext()->GetMediaRequestContextForRenderProcess(
   2712                 GetRenderProcessHost()->GetID()) :
   2713             GetBrowserContext()->GetRequestContextForRenderProcess(
   2714                 GetRenderProcessHost()->GetID()));
   2715     BrowserThread::PostTask(
   2716         BrowserThread::IO,
   2717         FROM_HERE,
   2718         base::Bind(&NotifyCacheOnIO, request_context, url, http_method));
   2719   }
   2720 }
   2721 
   2722 void WebContentsImpl::OnDidDisplayInsecureContent() {
   2723   RecordAction(base::UserMetricsAction("SSL.DisplayedInsecureContent"));
   2724   displayed_insecure_content_ = true;
   2725   SSLManager::NotifySSLInternalStateChanged(
   2726       GetController().GetBrowserContext());
   2727 }
   2728 
   2729 void WebContentsImpl::OnDidRunInsecureContent(
   2730     const std::string& security_origin, const GURL& target_url) {
   2731   LOG(WARNING) << security_origin << " ran insecure content from "
   2732                << target_url.possibly_invalid_spec();
   2733   RecordAction(base::UserMetricsAction("SSL.RanInsecureContent"));
   2734   if (EndsWith(security_origin, kDotGoogleDotCom, false))
   2735     RecordAction(base::UserMetricsAction("SSL.RanInsecureContentGoogle"));
   2736   controller_.ssl_manager()->DidRunInsecureContent(security_origin);
   2737   displayed_insecure_content_ = true;
   2738   SSLManager::NotifySSLInternalStateChanged(
   2739       GetController().GetBrowserContext());
   2740 }
   2741 
   2742 void WebContentsImpl::OnDocumentLoadedInFrame() {
   2743   CHECK(render_frame_message_source_);
   2744   CHECK(!render_view_message_source_);
   2745   RenderFrameHostImpl* rfh =
   2746       static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
   2747   FOR_EACH_OBSERVER(
   2748       WebContentsObserver, observers_, DocumentLoadedInFrame(rfh));
   2749 }
   2750 
   2751 void WebContentsImpl::OnDidFinishLoad(
   2752     const GURL& url) {
   2753   if (!render_frame_message_source_) {
   2754     RecordAction(base::UserMetricsAction("BadMessageTerminate_RVD2"));
   2755     GetRenderProcessHost()->ReceivedBadMessage();
   2756     return;
   2757   }
   2758 
   2759   GURL validated_url(url);
   2760   RenderProcessHost* render_process_host =
   2761       render_frame_message_source_->GetProcess();
   2762   render_process_host->FilterURL(false, &validated_url);
   2763 
   2764   RenderFrameHostImpl* rfh =
   2765       static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
   2766   FOR_EACH_OBSERVER(
   2767       WebContentsObserver, observers_, DidFinishLoad(rfh, validated_url));
   2768 }
   2769 
   2770 void WebContentsImpl::OnDidStartLoading(bool to_different_document) {
   2771   RenderFrameHostImpl* rfh =
   2772       static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
   2773   int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id();
   2774 
   2775   // It is possible to get multiple calls to OnDidStartLoading that don't have
   2776   // corresponding calls to OnDidStopLoading:
   2777   // - With "swappedout://" URLs, this happens when a RenderView gets swapped
   2778   //   out for a cross-process navigation, and it turns into a placeholder for
   2779   //   one being rendered in a different process.
   2780   // - Also, there might be more than one RenderFrameHost sharing the same
   2781   //   FrameTreeNode (and thus sharing its ID) each sending a start.
   2782   // - But in the future, once clamy@ moves navigation network requests to the
   2783   //   browser process, there's a good chance that callbacks about starting and
   2784   //   stopping will all be handled by the browser. When that happens, there
   2785   //   should no longer be a start/stop call imbalance. TODO(avi): When this
   2786   //   future arrives, update this code to not allow this case.
   2787   DCHECK_GE(loading_frames_in_progress_, 0);
   2788   if (loading_progresses_.find(render_frame_id) == loading_progresses_.end()) {
   2789     if (loading_frames_in_progress_ == 0)
   2790       DidStartLoading(rfh, to_different_document);
   2791     ++loading_frames_in_progress_;
   2792   }
   2793 
   2794   loading_progresses_[render_frame_id] = kMinimumLoadingProgress;
   2795   SendLoadProgressChanged();
   2796 }
   2797 
   2798 void WebContentsImpl::OnDidStopLoading() {
   2799   RenderFrameHostImpl* rfh =
   2800       static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
   2801   int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id();
   2802 
   2803   if (loading_progresses_.find(render_frame_id) != loading_progresses_.end()) {
   2804     // Load stopped while we were still tracking load.  Make sure we update
   2805     // progress based on this frame's completion.
   2806     loading_progresses_[render_frame_id] = 1.0;
   2807     SendLoadProgressChanged();
   2808     // Then we clean-up our states.
   2809     if (loading_total_progress_ == 1.0)
   2810       ResetLoadProgressState();
   2811   }
   2812 
   2813   // TODO(japhet): This should be a DCHECK, but the pdf plugin sometimes
   2814   // calls DidStopLoading() without a matching DidStartLoading().
   2815   if (loading_frames_in_progress_ == 0)
   2816     return;
   2817   --loading_frames_in_progress_;
   2818   if (loading_frames_in_progress_ == 0)
   2819     DidStopLoading(rfh);
   2820 }
   2821 
   2822 void WebContentsImpl::OnDidChangeLoadProgress(double load_progress) {
   2823   RenderFrameHostImpl* rfh =
   2824       static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
   2825   int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id();
   2826 
   2827   loading_progresses_[render_frame_id] = load_progress;
   2828 
   2829   // We notify progress change immediately for the first and last updates.
   2830   // Also, since the message loop may be pretty busy when a page is loaded, it
   2831   // might not execute a posted task in a timely manner so we make sure to
   2832   // immediately send progress report if enough time has passed.
   2833   base::TimeDelta min_delay =
   2834       base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenLoadingUpdatesMS);
   2835   if (load_progress == 1.0 || loading_last_progress_update_.is_null() ||
   2836       base::TimeTicks::Now() - loading_last_progress_update_ > min_delay) {
   2837     // If there is a pending task to send progress, it is now obsolete.
   2838     loading_weak_factory_.InvalidateWeakPtrs();
   2839     SendLoadProgressChanged();
   2840     if (loading_total_progress_ == 1.0)
   2841       ResetLoadProgressState();
   2842     return;
   2843   }
   2844 
   2845   if (loading_weak_factory_.HasWeakPtrs())
   2846     return;
   2847 
   2848   base::MessageLoop::current()->PostDelayedTask(
   2849       FROM_HERE,
   2850       base::Bind(&WebContentsImpl::SendLoadProgressChanged,
   2851                  loading_weak_factory_.GetWeakPtr()),
   2852       min_delay);
   2853 }
   2854 
   2855 void WebContentsImpl::OnGoToEntryAtOffset(int offset) {
   2856   if (!delegate_ || delegate_->OnGoToEntryOffset(offset))
   2857     controller_.GoToOffset(offset);
   2858 }
   2859 
   2860 void WebContentsImpl::OnUpdateZoomLimits(int minimum_percent,
   2861                                          int maximum_percent) {
   2862   minimum_zoom_percent_ = minimum_percent;
   2863   maximum_zoom_percent_ = maximum_percent;
   2864 }
   2865 
   2866 void WebContentsImpl::OnEnumerateDirectory(int request_id,
   2867                                            const base::FilePath& path) {
   2868   if (!delegate_)
   2869     return;
   2870 
   2871   ChildProcessSecurityPolicyImpl* policy =
   2872       ChildProcessSecurityPolicyImpl::GetInstance();
   2873   if (policy->CanReadFile(GetRenderProcessHost()->GetID(), path))
   2874     delegate_->EnumerateDirectory(this, request_id, path);
   2875 }
   2876 
   2877 void WebContentsImpl::OnRegisterProtocolHandler(const std::string& protocol,
   2878                                                 const GURL& url,
   2879                                                 const base::string16& title,
   2880                                                 bool user_gesture) {
   2881   if (!delegate_)
   2882     return;
   2883 
   2884   ChildProcessSecurityPolicyImpl* policy =
   2885       ChildProcessSecurityPolicyImpl::GetInstance();
   2886   if (policy->IsPseudoScheme(protocol))
   2887     return;
   2888 
   2889   delegate_->RegisterProtocolHandler(this, protocol, url, user_gesture);
   2890 }
   2891 
   2892 void WebContentsImpl::OnUnregisterProtocolHandler(const std::string& protocol,
   2893                                                   const GURL& url,
   2894                                                   bool user_gesture) {
   2895   if (!delegate_)
   2896     return;
   2897 
   2898   ChildProcessSecurityPolicyImpl* policy =
   2899       ChildProcessSecurityPolicyImpl::GetInstance();
   2900   if (policy->IsPseudoScheme(protocol))
   2901     return;
   2902 
   2903   delegate_->UnregisterProtocolHandler(this, protocol, url, user_gesture);
   2904 }
   2905 
   2906 void WebContentsImpl::OnFindReply(int request_id,
   2907                                   int number_of_matches,
   2908                                   const gfx::Rect& selection_rect,
   2909                                   int active_match_ordinal,
   2910                                   bool final_update) {
   2911   if (delegate_) {
   2912     delegate_->FindReply(this, request_id, number_of_matches, selection_rect,
   2913                          active_match_ordinal, final_update);
   2914   }
   2915 }
   2916 
   2917 #if defined(OS_ANDROID)
   2918 void WebContentsImpl::OnFindMatchRectsReply(
   2919     int version,
   2920     const std::vector<gfx::RectF>& rects,
   2921     const gfx::RectF& active_rect) {
   2922   if (delegate_)
   2923     delegate_->FindMatchRectsReply(this, version, rects, active_rect);
   2924 }
   2925 
   2926 void WebContentsImpl::OnOpenDateTimeDialog(
   2927     const ViewHostMsg_DateTimeDialogValue_Params& value) {
   2928   date_time_chooser_->ShowDialog(ContentViewCore::FromWebContents(this),
   2929                                  GetRenderViewHost(),
   2930                                  value.dialog_type,
   2931                                  value.dialog_value,
   2932                                  value.minimum,
   2933                                  value.maximum,
   2934                                  value.step,
   2935                                  value.suggestions);
   2936 }
   2937 
   2938 #endif
   2939 
   2940 void WebContentsImpl::OnPepperPluginHung(int plugin_child_id,
   2941                                          const base::FilePath& path,
   2942                                          bool is_hung) {
   2943   UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1);
   2944 
   2945   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2946                     PluginHungStatusChanged(plugin_child_id, path, is_hung));
   2947 }
   2948 
   2949 void WebContentsImpl::OnPluginCrashed(const base::FilePath& plugin_path,
   2950                                       base::ProcessId plugin_pid) {
   2951   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2952                     PluginCrashed(plugin_path, plugin_pid));
   2953 }
   2954 
   2955 void WebContentsImpl::OnDomOperationResponse(const std::string& json_string,
   2956                                              int automation_id) {
   2957   DomOperationNotificationDetails details(json_string, automation_id);
   2958   NotificationService::current()->Notify(
   2959       NOTIFICATION_DOM_OPERATION_RESPONSE,
   2960       Source<WebContents>(this),
   2961       Details<DomOperationNotificationDetails>(&details));
   2962 }
   2963 
   2964 void WebContentsImpl::OnAppCacheAccessed(const GURL& manifest_url,
   2965                                          bool blocked_by_policy) {
   2966   // Notify observers about navigation.
   2967   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2968                     AppCacheAccessed(manifest_url, blocked_by_policy));
   2969 }
   2970 
   2971 void WebContentsImpl::OnOpenColorChooser(
   2972     int color_chooser_id,
   2973     SkColor color,
   2974     const std::vector<ColorSuggestion>& suggestions) {
   2975   ColorChooser* new_color_chooser = delegate_ ?
   2976       delegate_->OpenColorChooser(this, color, suggestions) :
   2977       NULL;
   2978   if (!new_color_chooser)
   2979     return;
   2980   if (color_chooser_info_.get())
   2981     color_chooser_info_->chooser->End();
   2982 
   2983   color_chooser_info_.reset(new ColorChooserInfo(
   2984       render_frame_message_source_->GetProcess()->GetID(),
   2985       render_frame_message_source_->GetRoutingID(),
   2986       new_color_chooser,
   2987       color_chooser_id));
   2988 }
   2989 
   2990 void WebContentsImpl::OnEndColorChooser(int color_chooser_id) {
   2991   if (color_chooser_info_ &&
   2992       color_chooser_id == color_chooser_info_->identifier)
   2993     color_chooser_info_->chooser->End();
   2994 }
   2995 
   2996 void WebContentsImpl::OnSetSelectedColorInColorChooser(int color_chooser_id,
   2997                                                        SkColor color) {
   2998   if (color_chooser_info_ &&
   2999       color_chooser_id == color_chooser_info_->identifier)
   3000     color_chooser_info_->chooser->SetSelectedColor(color);
   3001 }
   3002 
   3003 // This exists for render views that don't have a WebUI, but do have WebUI
   3004 // bindings enabled.
   3005 void WebContentsImpl::OnWebUISend(const GURL& source_url,
   3006                                   const std::string& name,
   3007                                   const base::ListValue& args) {
   3008   if (delegate_)
   3009     delegate_->WebUISend(this, source_url, name, args);
   3010 }
   3011 
   3012 #if defined(ENABLE_PLUGINS)
   3013 void WebContentsImpl::OnRequestPpapiBrokerPermission(
   3014     int routing_id,
   3015     const GURL& url,
   3016     const base::FilePath& plugin_path) {
   3017   if (!delegate_) {
   3018     OnPpapiBrokerPermissionResult(routing_id, false);
   3019     return;
   3020   }
   3021 
   3022   if (!delegate_->RequestPpapiBrokerPermission(
   3023       this, url, plugin_path,
   3024       base::Bind(&WebContentsImpl::OnPpapiBrokerPermissionResult,
   3025                  base::Unretained(this), routing_id))) {
   3026     NOTIMPLEMENTED();
   3027     OnPpapiBrokerPermissionResult(routing_id, false);
   3028   }
   3029 }
   3030 
   3031 void WebContentsImpl::OnPpapiBrokerPermissionResult(int routing_id,
   3032                                                     bool result) {
   3033   Send(new ViewMsg_PpapiBrokerPermissionResult(routing_id, result));
   3034 }
   3035 
   3036 void WebContentsImpl::OnBrowserPluginMessage(const IPC::Message& message) {
   3037   // This creates a BrowserPluginEmbedder, which handles all the BrowserPlugin
   3038   // specific messages for this WebContents. This means that any message from
   3039   // a BrowserPlugin prior to this will be ignored.
   3040   // For more info, see comment above classes BrowserPluginEmbedder and
   3041   // BrowserPluginGuest.
   3042   CHECK(!browser_plugin_embedder_.get());
   3043   browser_plugin_embedder_.reset(BrowserPluginEmbedder::Create(this));
   3044   browser_plugin_embedder_->OnMessageReceived(message);
   3045 }
   3046 #endif
   3047 
   3048 void WebContentsImpl::OnDidDownloadImage(
   3049     int id,
   3050     int http_status_code,
   3051     const GURL& image_url,
   3052     const std::vector<SkBitmap>& bitmaps,
   3053     const std::vector<gfx::Size>& original_bitmap_sizes) {
   3054   if (bitmaps.size() != original_bitmap_sizes.size())
   3055     return;
   3056 
   3057   ImageDownloadMap::iterator iter = image_download_map_.find(id);
   3058   if (iter == image_download_map_.end()) {
   3059     // Currently WebContents notifies us of ANY downloads so that it is
   3060     // possible to get here.
   3061     return;
   3062   }
   3063   if (!iter->second.is_null()) {
   3064     iter->second.Run(
   3065         id, http_status_code, image_url, bitmaps, original_bitmap_sizes);
   3066   }
   3067   image_download_map_.erase(id);
   3068 }
   3069 
   3070 void WebContentsImpl::OnUpdateFaviconURL(
   3071     const std::vector<FaviconURL>& candidates) {
   3072   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3073                     DidUpdateFaviconURL(candidates));
   3074 }
   3075 
   3076 void WebContentsImpl::CreateAudioPowerSaveBlocker() {
   3077   // ChromeOS has its own way of handling power save blocks for media.
   3078 #if !defined(OS_CHROMEOS)
   3079   DCHECK(!audio_power_save_blocker_);
   3080   audio_power_save_blocker_ = PowerSaveBlocker::Create(
   3081       PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, "Playing Audio");
   3082 #endif
   3083 }
   3084 
   3085 void WebContentsImpl::CreateVideoPowerSaveBlocker() {
   3086   // ChromeOS has its own way of handling power save blocks for media.
   3087 #if !defined(OS_CHROMEOS)
   3088   DCHECK(!video_power_save_blocker_);
   3089   DCHECK(!active_video_players_.empty());
   3090   video_power_save_blocker_ = PowerSaveBlocker::Create(
   3091       PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, "Playing Video");
   3092 #if defined(OS_ANDROID)
   3093   static_cast<PowerSaveBlockerImpl*>(video_power_save_blocker_.get())
   3094       ->InitDisplaySleepBlocker(GetView()->GetNativeView());
   3095 #endif
   3096 #endif
   3097 }
   3098 
   3099 void WebContentsImpl::MaybeReleasePowerSaveBlockers() {
   3100   // If there are no more audio players and we don't have audio stream
   3101   // monitoring, release the audio power save blocker here instead of during
   3102   // NotifyNavigationStateChanged().
   3103   if (active_audio_players_.empty() &&
   3104       !AudioStreamMonitor::monitoring_available()) {
   3105     audio_power_save_blocker_.reset();
   3106   }
   3107 
   3108   // If there are no more video players, clear the video power save blocker.
   3109   if (active_video_players_.empty())
   3110     video_power_save_blocker_.reset();
   3111 }
   3112 
   3113 void WebContentsImpl::OnMediaPlayingNotification(int64 player_cookie,
   3114                                                  bool has_video,
   3115                                                  bool has_audio,
   3116                                                  bool is_remote) {
   3117   // Ignore the videos playing remotely and don't hold the wake lock for the
   3118   // screen.
   3119   if (is_remote) return;
   3120 
   3121   if (has_audio) {
   3122     AddMediaPlayerEntry(player_cookie, &active_audio_players_);
   3123 
   3124     // If we don't have audio stream monitoring, allocate the audio power save
   3125     // blocker here instead of during NotifyNavigationStateChanged().
   3126     if (!audio_power_save_blocker_ &&
   3127         !AudioStreamMonitor::monitoring_available()) {
   3128       CreateAudioPowerSaveBlocker();
   3129     }
   3130   }
   3131 
   3132   if (has_video) {
   3133     AddMediaPlayerEntry(player_cookie, &active_video_players_);
   3134 
   3135     // If we're not hidden and have just created a player, create a blocker.
   3136     if (!video_power_save_blocker_ && !IsHidden())
   3137       CreateVideoPowerSaveBlocker();
   3138   }
   3139 }
   3140 
   3141 void WebContentsImpl::OnMediaPausedNotification(int64 player_cookie) {
   3142   RemoveMediaPlayerEntry(player_cookie, &active_audio_players_);
   3143   RemoveMediaPlayerEntry(player_cookie, &active_video_players_);
   3144   MaybeReleasePowerSaveBlockers();
   3145 }
   3146 
   3147 void WebContentsImpl::OnFirstVisuallyNonEmptyPaint() {
   3148   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3149                     DidFirstVisuallyNonEmptyPaint());
   3150 }
   3151 
   3152 void WebContentsImpl::DidChangeVisibleSSLState() {
   3153   if (delegate_)
   3154     delegate_->VisibleSSLStateChanged(this);
   3155 }
   3156 
   3157 void WebContentsImpl::NotifyBeforeFormRepostWarningShow() {
   3158   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3159                     BeforeFormRepostWarningShow());
   3160 }
   3161 
   3162 void WebContentsImpl::ActivateAndShowRepostFormWarningDialog() {
   3163   Activate();
   3164   if (delegate_)
   3165     delegate_->ShowRepostFormWarningDialog(this);
   3166 }
   3167 
   3168 bool WebContentsImpl::HasAccessedInitialDocument() {
   3169   return has_accessed_initial_document_;
   3170 }
   3171 
   3172 // Notifies the RenderWidgetHost instance about the fact that the page is
   3173 // loading, or done loading.
   3174 void WebContentsImpl::SetIsLoading(RenderViewHost* render_view_host,
   3175                                    bool is_loading,
   3176                                    bool to_different_document,
   3177                                    LoadNotificationDetails* details) {
   3178   if (is_loading == is_loading_)
   3179     return;
   3180 
   3181   if (!is_loading) {
   3182     load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE,
   3183                                           base::string16());
   3184     load_state_host_.clear();
   3185     upload_size_ = 0;
   3186     upload_position_ = 0;
   3187   }
   3188 
   3189   GetRenderManager()->SetIsLoading(is_loading);
   3190 
   3191   is_loading_ = is_loading;
   3192   waiting_for_response_ = is_loading;
   3193   is_load_to_different_document_ = to_different_document;
   3194 
   3195   if (delegate_)
   3196     delegate_->LoadingStateChanged(this, to_different_document);
   3197   NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD);
   3198 
   3199   std::string url = (details ? details->url.possibly_invalid_spec() : "NULL");
   3200   if (is_loading) {
   3201     TRACE_EVENT_ASYNC_BEGIN1("browser,navigation", "WebContentsImpl Loading",
   3202                              this, "URL", url);
   3203     FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3204                       DidStartLoading(render_view_host));
   3205   } else {
   3206     TRACE_EVENT_ASYNC_END1("browser,navigation", "WebContentsImpl Loading",
   3207                            this, "URL", url);
   3208     FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3209                       DidStopLoading(render_view_host));
   3210   }
   3211 
   3212   // TODO(avi): Remove. http://crbug.com/170921
   3213   int type = is_loading ? NOTIFICATION_LOAD_START : NOTIFICATION_LOAD_STOP;
   3214   NotificationDetails det = NotificationService::NoDetails();
   3215   if (details)
   3216       det = Details<LoadNotificationDetails>(details);
   3217   NotificationService::current()->Notify(
   3218       type, Source<NavigationController>(&controller_), det);
   3219 }
   3220 
   3221 void WebContentsImpl::SelectRange(const gfx::Point& start,
   3222                                   const gfx::Point& end) {
   3223   RenderFrameHost* focused_frame = GetFocusedFrame();
   3224   if (!focused_frame)
   3225     return;
   3226 
   3227   focused_frame->Send(
   3228       new InputMsg_SelectRange(focused_frame->GetRoutingID(), start, end));
   3229 }
   3230 
   3231 void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) {
   3232   // If we are creating a RVH for a restored controller, then we need to make
   3233   // sure the RenderView starts with a next_page_id_ larger than the number
   3234   // of restored entries.  This must be called before the RenderView starts
   3235   // navigating (to avoid a race between the browser updating max_page_id and
   3236   // the renderer updating next_page_id_).  Because of this, we only call this
   3237   // from CreateRenderView and allow that to notify the RenderView for us.
   3238   int max_restored_page_id = controller_.GetMaxRestoredPageID();
   3239   if (max_restored_page_id >
   3240       GetMaxPageIDForSiteInstance(rvh->GetSiteInstance()))
   3241     UpdateMaxPageIDForSiteInstance(rvh->GetSiteInstance(),
   3242                                    max_restored_page_id);
   3243 }
   3244 
   3245 bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl* entry,
   3246                                           const base::string16& title) {
   3247   // For file URLs without a title, use the pathname instead. In the case of a
   3248   // synthesized title, we don't want the update to count toward the "one set
   3249   // per page of the title to history."
   3250   base::string16 final_title;
   3251   bool explicit_set;
   3252   if (entry && entry->GetURL().SchemeIsFile() && title.empty()) {
   3253     final_title = base::UTF8ToUTF16(entry->GetURL().ExtractFileName());
   3254     explicit_set = false;  // Don't count synthetic titles toward the set limit.
   3255   } else {
   3256     base::TrimWhitespace(title, base::TRIM_ALL, &final_title);
   3257     explicit_set = true;
   3258   }
   3259 
   3260   // If a page is created via window.open and never navigated,
   3261   // there will be no navigation entry. In this situation,
   3262   // |page_title_when_no_navigation_entry_| will be used for page title.
   3263   if (entry) {
   3264     if (final_title == entry->GetTitle())
   3265       return false;  // Nothing changed, don't bother.
   3266 
   3267     entry->SetTitle(final_title);
   3268   } else {
   3269     if (page_title_when_no_navigation_entry_ == final_title)
   3270       return false;  // Nothing changed, don't bother.
   3271 
   3272     page_title_when_no_navigation_entry_ = final_title;
   3273   }
   3274 
   3275   // Lastly, set the title for the view.
   3276   view_->SetPageTitle(final_title);
   3277 
   3278   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3279                     TitleWasSet(entry, explicit_set));
   3280 
   3281   // TODO(avi): Remove. http://crbug.com/170921
   3282   std::pair<NavigationEntry*, bool> details =
   3283       std::make_pair(entry, explicit_set);
   3284   NotificationService::current()->Notify(
   3285       NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
   3286       Source<WebContents>(this),
   3287       Details<std::pair<NavigationEntry*, bool> >(&details));
   3288 
   3289   return true;
   3290 }
   3291 
   3292 void WebContentsImpl::SendLoadProgressChanged() {
   3293   loading_last_progress_update_ = base::TimeTicks::Now();
   3294   double progress = 0.0;
   3295   int frame_count = 0;
   3296 
   3297   for (LoadingProgressMap::iterator it = loading_progresses_.begin();
   3298        it != loading_progresses_.end();
   3299        ++it) {
   3300     progress += it->second;
   3301     ++frame_count;
   3302   }
   3303   if (frame_count == 0)
   3304     return;
   3305   progress /= frame_count;
   3306   DCHECK(progress <= 1.0);
   3307 
   3308   if (progress <= loading_total_progress_)
   3309     return;
   3310   loading_total_progress_ = progress;
   3311 
   3312   if (delegate_)
   3313     delegate_->LoadProgressChanged(this, progress);
   3314 }
   3315 
   3316 void WebContentsImpl::ResetLoadProgressState() {
   3317   loading_progresses_.clear();
   3318   loading_total_progress_ = 0.0;
   3319   loading_weak_factory_.InvalidateWeakPtrs();
   3320   loading_last_progress_update_ = base::TimeTicks();
   3321 }
   3322 
   3323 void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host,
   3324                                         RenderViewHost* new_host) {
   3325   // After sending out a swap notification, we need to send a disconnect
   3326   // notification so that clients that pick up a pointer to |this| can NULL the
   3327   // pointer.  See Bug 1230284.
   3328   notify_disconnection_ = true;
   3329   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3330                     RenderViewHostChanged(old_host, new_host));
   3331 
   3332   // TODO(avi): Remove. http://crbug.com/170921
   3333   std::pair<RenderViewHost*, RenderViewHost*> details =
   3334       std::make_pair(old_host, new_host);
   3335   NotificationService::current()->Notify(
   3336       NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
   3337       Source<WebContents>(this),
   3338       Details<std::pair<RenderViewHost*, RenderViewHost*> >(&details));
   3339 
   3340   // Ensure that the associated embedder gets cleared after a RenderViewHost
   3341   // gets swapped, so we don't reuse the same embedder next time a
   3342   // RenderViewHost is attached to this WebContents.
   3343   RemoveBrowserPluginEmbedder();
   3344 }
   3345 
   3346 void WebContentsImpl::NotifyFrameSwapped(RenderFrameHost* old_host,
   3347                                          RenderFrameHost* new_host) {
   3348   FOR_EACH_OBSERVER(WebContentsObserver,
   3349                     observers_,
   3350                     RenderFrameHostChanged(old_host, new_host));
   3351 }
   3352 
   3353 // TODO(avi): Remove this entire function because this notification is already
   3354 // covered by two observer functions. http://crbug.com/170921
   3355 void WebContentsImpl::NotifyDisconnected() {
   3356   if (!notify_disconnection_)
   3357     return;
   3358 
   3359   notify_disconnection_ = false;
   3360   NotificationService::current()->Notify(
   3361       NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
   3362       Source<WebContents>(this),
   3363       NotificationService::NoDetails());
   3364 }
   3365 
   3366 void WebContentsImpl::NotifyNavigationEntryCommitted(
   3367     const LoadCommittedDetails& load_details) {
   3368   FOR_EACH_OBSERVER(
   3369       WebContentsObserver, observers_, NavigationEntryCommitted(load_details));
   3370 }
   3371 
   3372 bool WebContentsImpl::OnMessageReceived(RenderFrameHost* render_frame_host,
   3373                                         const IPC::Message& message) {
   3374   return OnMessageReceived(NULL, render_frame_host, message);
   3375 }
   3376 
   3377 const GURL& WebContentsImpl::GetMainFrameLastCommittedURL() const {
   3378   return GetLastCommittedURL();
   3379 }
   3380 
   3381 void WebContentsImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) {
   3382   // Note this is only for subframes, the notification for the main frame
   3383   // happens in RenderViewCreated.
   3384   FOR_EACH_OBSERVER(WebContentsObserver,
   3385                     observers_,
   3386                     RenderFrameCreated(render_frame_host));
   3387   SetAccessibilityModeOnFrame(accessibility_mode_, render_frame_host);
   3388 }
   3389 
   3390 void WebContentsImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
   3391   ClearPowerSaveBlockers(render_frame_host);
   3392   FOR_EACH_OBSERVER(WebContentsObserver,
   3393                     observers_,
   3394                     RenderFrameDeleted(render_frame_host));
   3395 }
   3396 
   3397 void WebContentsImpl::WorkerCrashed(RenderFrameHost* render_frame_host) {
   3398   if (delegate_)
   3399     delegate_->WorkerCrashed(this);
   3400 }
   3401 
   3402 void WebContentsImpl::ShowContextMenu(RenderFrameHost* render_frame_host,
   3403                                       const ContextMenuParams& params) {
   3404   ContextMenuParams context_menu_params(params);
   3405   // Allow WebContentsDelegates to handle the context menu operation first.
   3406   if (GetBrowserPluginGuest()) {
   3407     WebContentsViewGuest* view_guest =
   3408         static_cast<WebContentsViewGuest*>(GetView());
   3409     context_menu_params = view_guest->ConvertContextMenuParams(params);
   3410   }
   3411   if (delegate_ && delegate_->HandleContextMenu(context_menu_params))
   3412     return;
   3413 
   3414   render_view_host_delegate_view_->ShowContextMenu(render_frame_host,
   3415                                                    context_menu_params);
   3416 }
   3417 
   3418 void WebContentsImpl::RunJavaScriptMessage(
   3419     RenderFrameHost* render_frame_host,
   3420     const base::string16& message,
   3421     const base::string16& default_prompt,
   3422     const GURL& frame_url,
   3423     JavaScriptMessageType javascript_message_type,
   3424     IPC::Message* reply_msg) {
   3425   // Suppress JavaScript dialogs when requested. Also suppress messages when
   3426   // showing an interstitial as it's shown over the previous page and we don't
   3427   // want the hidden page's dialogs to interfere with the interstitial.
   3428   bool suppress_this_message =
   3429       static_cast<RenderViewHostImpl*>(render_frame_host->GetRenderViewHost())->
   3430           IsSwappedOut() ||
   3431       ShowingInterstitialPage() ||
   3432       !delegate_ ||
   3433       delegate_->ShouldSuppressDialogs() ||
   3434       !delegate_->GetJavaScriptDialogManager();
   3435 
   3436   if (!suppress_this_message) {
   3437     std::string accept_lang = GetContentClient()->browser()->
   3438       GetAcceptLangs(GetBrowserContext());
   3439     dialog_manager_ = delegate_->GetJavaScriptDialogManager();
   3440     dialog_manager_->RunJavaScriptDialog(
   3441         this,
   3442         frame_url.GetOrigin(),
   3443         accept_lang,
   3444         javascript_message_type,
   3445         message,
   3446         default_prompt,
   3447         base::Bind(&WebContentsImpl::OnDialogClosed,
   3448                    base::Unretained(this),
   3449                    render_frame_host->GetProcess()->GetID(),
   3450                    render_frame_host->GetRoutingID(),
   3451                    reply_msg,
   3452                    false),
   3453         &suppress_this_message);
   3454   }
   3455 
   3456   if (suppress_this_message) {
   3457     // If we are suppressing messages, just reply as if the user immediately
   3458     // pressed "Cancel", passing true to |dialog_was_suppressed|.
   3459     OnDialogClosed(render_frame_host->GetProcess()->GetID(),
   3460                    render_frame_host->GetRoutingID(), reply_msg,
   3461                    true, false, base::string16());
   3462   }
   3463 
   3464   // OnDialogClosed (two lines up) may have caused deletion of this object (see
   3465   // http://crbug.com/288961 ). The only safe thing to do here is return.
   3466 }
   3467 
   3468 void WebContentsImpl::RunBeforeUnloadConfirm(
   3469     RenderFrameHost* render_frame_host,
   3470     const base::string16& message,
   3471     bool is_reload,
   3472     IPC::Message* reply_msg) {
   3473   RenderFrameHostImpl* rfhi =
   3474       static_cast<RenderFrameHostImpl*>(render_frame_host);
   3475   RenderViewHostImpl* rvhi =
   3476       static_cast<RenderViewHostImpl*>(render_frame_host->GetRenderViewHost());
   3477   if (delegate_)
   3478     delegate_->WillRunBeforeUnloadConfirm();
   3479 
   3480   bool suppress_this_message =
   3481       rvhi->rvh_state() != RenderViewHostImpl::STATE_DEFAULT ||
   3482       !delegate_ ||
   3483       delegate_->ShouldSuppressDialogs() ||
   3484       !delegate_->GetJavaScriptDialogManager();
   3485   if (suppress_this_message) {
   3486     rfhi->JavaScriptDialogClosed(reply_msg, true, base::string16(), true);
   3487     return;
   3488   }
   3489 
   3490   is_showing_before_unload_dialog_ = true;
   3491   dialog_manager_ = delegate_->GetJavaScriptDialogManager();
   3492   dialog_manager_->RunBeforeUnloadDialog(
   3493       this, message, is_reload,
   3494       base::Bind(&WebContentsImpl::OnDialogClosed, base::Unretained(this),
   3495                  render_frame_host->GetProcess()->GetID(),
   3496                  render_frame_host->GetRoutingID(), reply_msg,
   3497                  false));
   3498 }
   3499 
   3500 WebContents* WebContentsImpl::GetAsWebContents() {
   3501   return this;
   3502 }
   3503 
   3504 bool WebContentsImpl::IsNeverVisible() {
   3505   if (!delegate_)
   3506     return false;
   3507   return delegate_->IsNeverVisible(this);
   3508 }
   3509 
   3510 #if defined(OS_WIN)
   3511 gfx::NativeViewAccessible WebContentsImpl::GetParentNativeViewAccessible() {
   3512   return accessible_parent_;
   3513 }
   3514 #endif
   3515 
   3516 RenderViewHostDelegateView* WebContentsImpl::GetDelegateView() {
   3517   return render_view_host_delegate_view_;
   3518 }
   3519 
   3520 RendererPreferences WebContentsImpl::GetRendererPrefs(
   3521     BrowserContext* browser_context) const {
   3522   return renderer_preferences_;
   3523 }
   3524 
   3525 gfx::Rect WebContentsImpl::GetRootWindowResizerRect() const {
   3526   if (delegate_)
   3527     return delegate_->GetRootWindowResizerRect();
   3528   return gfx::Rect();
   3529 }
   3530 
   3531 void WebContentsImpl::RemoveBrowserPluginEmbedder() {
   3532   if (browser_plugin_embedder_)
   3533     browser_plugin_embedder_.reset();
   3534 }
   3535 
   3536 void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) {
   3537   // Don't send notifications if we are just creating a swapped-out RVH for
   3538   // the opener chain.  These won't be used for view-source or WebUI, so it's
   3539   // ok to return early.
   3540   if (static_cast<RenderViewHostImpl*>(render_view_host)->IsSwappedOut())
   3541     return;
   3542 
   3543   if (delegate_)
   3544     view_->SetOverscrollControllerEnabled(CanOverscrollContent());
   3545 
   3546   NotificationService::current()->Notify(
   3547       NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
   3548       Source<WebContents>(this),
   3549       Details<RenderViewHost>(render_view_host));
   3550 
   3551   // When we're creating views, we're still doing initial setup, so we always
   3552   // use the pending Web UI rather than any possibly existing committed one.
   3553   if (GetRenderManager()->pending_web_ui())
   3554     GetRenderManager()->pending_web_ui()->RenderViewCreated(render_view_host);
   3555 
   3556   NavigationEntry* entry = controller_.GetPendingEntry();
   3557   if (entry && entry->IsViewSourceMode()) {
   3558     // Put the renderer in view source mode.
   3559     render_view_host->Send(
   3560         new ViewMsg_EnableViewSourceMode(render_view_host->GetRoutingID()));
   3561   }
   3562 
   3563   view_->RenderViewCreated(render_view_host);
   3564 
   3565   FOR_EACH_OBSERVER(
   3566       WebContentsObserver, observers_, RenderViewCreated(render_view_host));
   3567 
   3568   // We tell the observers now instead of when the main RenderFrameHostImpl is
   3569   // constructed because otherwise it would be too early (i.e. IPCs sent to the
   3570   // frame would be dropped because it's not created yet).
   3571   RenderFrameHost* main_frame = render_view_host->GetMainFrame();
   3572   FOR_EACH_OBSERVER(
   3573       WebContentsObserver, observers_, RenderFrameCreated(main_frame));
   3574   SetAccessibilityModeOnFrame(accessibility_mode_, main_frame);
   3575 }
   3576 
   3577 void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) {
   3578   if (rvh != GetRenderViewHost()) {
   3579     // Don't notify the world, since this came from a renderer in the
   3580     // background.
   3581     return;
   3582   }
   3583 
   3584   notify_disconnection_ = true;
   3585   // TODO(avi): Remove. http://crbug.com/170921
   3586   NotificationService::current()->Notify(
   3587       NOTIFICATION_WEB_CONTENTS_CONNECTED,
   3588       Source<WebContents>(this),
   3589       NotificationService::NoDetails());
   3590 
   3591   bool was_crashed = IsCrashed();
   3592   SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING, 0);
   3593 
   3594   // Restore the focus to the tab (otherwise the focus will be on the top
   3595   // window).
   3596   if (was_crashed && !FocusLocationBarByDefault() &&
   3597       (!delegate_ || delegate_->ShouldFocusPageAfterCrash())) {
   3598     view_->Focus();
   3599   }
   3600 
   3601   FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewReady());
   3602 }
   3603 
   3604 void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
   3605                                            base::TerminationStatus status,
   3606                                            int error_code) {
   3607   if (rvh != GetRenderViewHost()) {
   3608     // The pending page's RenderViewHost is gone.
   3609     return;
   3610   }
   3611 
   3612   // Ensure fullscreen mode is exited in the |delegate_| since a crashed
   3613   // renderer may not have made a clean exit.
   3614   if (IsFullscreenForCurrentTab())
   3615     ToggleFullscreenMode(false);
   3616 
   3617   // Cancel any visible dialogs so they are not left dangling over the sad tab.
   3618   if (dialog_manager_)
   3619     dialog_manager_->CancelActiveAndPendingDialogs(this);
   3620 
   3621   if (delegate_)
   3622     delegate_->HideValidationMessage(this);
   3623 
   3624   SetIsLoading(rvh, false, true, NULL);
   3625   NotifyDisconnected();
   3626   SetIsCrashed(status, error_code);
   3627 
   3628   // Reset the loading progress. TODO(avi): What does it mean to have a
   3629   // "renderer crash" when there is more than one renderer process serving a
   3630   // webpage? Once this function is called at a more granular frame level, we
   3631   // probably will need to more granularly reset the state here.
   3632   ResetLoadProgressState();
   3633   loading_frames_in_progress_ = 0;
   3634 
   3635   FOR_EACH_OBSERVER(WebContentsObserver,
   3636                     observers_,
   3637                     RenderProcessGone(GetCrashedStatus()));
   3638 }
   3639 
   3640 void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) {
   3641   FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh));
   3642 }
   3643 
   3644 void WebContentsImpl::UpdateState(RenderViewHost* rvh,
   3645                                   int32 page_id,
   3646                                   const PageState& page_state) {
   3647   // Ensure that this state update comes from either the active RVH or one of
   3648   // the swapped out RVHs.  We don't expect to hear from any other RVHs.
   3649   // TODO(nasko): This should go through RenderFrameHost.
   3650   // TODO(creis): We can't update state for cross-process subframes until we
   3651   // have FrameNavigationEntries.  Once we do, this should be a DCHECK.
   3652   if (rvh != GetRenderViewHost() &&
   3653       !GetRenderManager()->IsRVHOnSwappedOutList(
   3654           static_cast<RenderViewHostImpl*>(rvh)))
   3655     return;
   3656 
   3657   // We must be prepared to handle state updates for any page, these occur
   3658   // when the user is scrolling and entering form data, as well as when we're
   3659   // leaving a page, in which case our state may have already been moved to
   3660   // the next page. The navigation controller will look up the appropriate
   3661   // NavigationEntry and update it when it is notified via the delegate.
   3662 
   3663   int entry_index = controller_.GetEntryIndexWithPageID(
   3664       rvh->GetSiteInstance(), page_id);
   3665   if (entry_index < 0)
   3666     return;
   3667   NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index);
   3668 
   3669   if (page_state == entry->GetPageState())
   3670     return;  // Nothing to update.
   3671   entry->SetPageState(page_state);
   3672   controller_.NotifyEntryChanged(entry, entry_index);
   3673 }
   3674 
   3675 void WebContentsImpl::UpdateTargetURL(const GURL& url) {
   3676   if (delegate_)
   3677     delegate_->UpdateTargetURL(this, url);
   3678 }
   3679 
   3680 void WebContentsImpl::Close(RenderViewHost* rvh) {
   3681 #if defined(OS_MACOSX)
   3682   // The UI may be in an event-tracking loop, such as between the
   3683   // mouse-down and mouse-up in text selection or a button click.
   3684   // Defer the close until after tracking is complete, so that we
   3685   // don't free objects out from under the UI.
   3686   // TODO(shess): This could get more fine-grained.  For instance,
   3687   // closing a tab in another window while selecting text in the
   3688   // current window's Omnibox should be just fine.
   3689   if (view_->IsEventTracking()) {
   3690     view_->CloseTabAfterEventTracking();
   3691     return;
   3692   }
   3693 #endif
   3694 
   3695   // Ignore this if it comes from a RenderViewHost that we aren't showing.
   3696   if (delegate_ && rvh == GetRenderViewHost())
   3697     delegate_->CloseContents(this);
   3698 }
   3699 
   3700 void WebContentsImpl::SwappedOut(RenderFrameHost* rfh) {
   3701   if (delegate_ && rfh->GetRenderViewHost() == GetRenderViewHost())
   3702     delegate_->SwappedOut(this);
   3703 }
   3704 
   3705 void WebContentsImpl::DidDeferAfterResponseStarted(
   3706     const TransitionLayerData& transition_data) {
   3707 #if defined(OS_ANDROID)
   3708   GetWebContentsAndroid()->DidDeferAfterResponseStarted(transition_data);
   3709 #endif
   3710 }
   3711 
   3712 bool WebContentsImpl::WillHandleDeferAfterResponseStarted() {
   3713 #if defined(OS_ANDROID)
   3714   return GetWebContentsAndroid()->WillHandleDeferAfterResponseStarted();
   3715 #else
   3716   return false;
   3717 #endif
   3718 }
   3719 
   3720 void WebContentsImpl::RequestMove(const gfx::Rect& new_bounds) {
   3721   if (delegate_ && delegate_->IsPopupOrPanel(this))
   3722     delegate_->MoveContents(this, new_bounds);
   3723 }
   3724 
   3725 void WebContentsImpl::DidStartLoading(RenderFrameHost* render_frame_host,
   3726                                       bool to_different_document) {
   3727   SetIsLoading(render_frame_host->GetRenderViewHost(), true,
   3728                to_different_document, NULL);
   3729 }
   3730 
   3731 void WebContentsImpl::DidStopLoading(RenderFrameHost* render_frame_host) {
   3732   scoped_ptr<LoadNotificationDetails> details;
   3733 
   3734   // Use the last committed entry rather than the active one, in case a
   3735   // pending entry has been created.
   3736   NavigationEntry* entry = controller_.GetLastCommittedEntry();
   3737   Navigator* navigator = frame_tree_.root()->navigator();
   3738 
   3739   // An entry may not exist for a stop when loading an initial blank page or
   3740   // if an iframe injected by script into a blank page finishes loading.
   3741   if (entry) {
   3742     base::TimeDelta elapsed =
   3743         base::TimeTicks::Now() - navigator->GetCurrentLoadStart();
   3744 
   3745     details.reset(new LoadNotificationDetails(
   3746         entry->GetVirtualURL(),
   3747         entry->GetTransitionType(),
   3748         elapsed,
   3749         &controller_,
   3750         controller_.GetCurrentEntryIndex()));
   3751   }
   3752 
   3753   SetIsLoading(render_frame_host->GetRenderViewHost(), false, true,
   3754                details.get());
   3755 }
   3756 
   3757 void WebContentsImpl::DidCancelLoading() {
   3758   controller_.DiscardNonCommittedEntries();
   3759 
   3760   // Update the URL display.
   3761   NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
   3762 }
   3763 
   3764 void WebContentsImpl::DidAccessInitialDocument() {
   3765   has_accessed_initial_document_ = true;
   3766 
   3767   // We may have left a failed browser-initiated navigation in the address bar
   3768   // to let the user edit it and try again.  Clear it now that content might
   3769   // show up underneath it.
   3770   if (!IsLoading() && controller_.GetPendingEntry())
   3771     controller_.DiscardPendingEntry();
   3772 
   3773   // Update the URL display.
   3774   NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
   3775 }
   3776 
   3777 void WebContentsImpl::DidDisownOpener(RenderFrameHost* render_frame_host) {
   3778   // No action is necessary if the opener has already been cleared.
   3779   if (!opener_)
   3780     return;
   3781 
   3782   // Clear our opener so that future cross-process navigations don't have an
   3783   // opener assigned.
   3784   RemoveDestructionObserver(opener_);
   3785   opener_ = NULL;
   3786 
   3787   // Notify all swapped out RenderViewHosts for this tab.  This is important
   3788   // in case we go back to them, or if another window in those processes tries
   3789   // to access window.opener.
   3790   GetRenderManager()->DidDisownOpener(render_frame_host);
   3791 }
   3792 
   3793 void WebContentsImpl::DocumentOnLoadCompleted(
   3794     RenderFrameHost* render_frame_host) {
   3795   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3796                     DocumentOnLoadCompletedInMainFrame());
   3797 
   3798   // TODO(avi): Remove. http://crbug.com/170921
   3799   NotificationService::current()->Notify(
   3800       NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
   3801       Source<WebContents>(this),
   3802       NotificationService::NoDetails());
   3803 }
   3804 
   3805 void WebContentsImpl::UpdateTitle(RenderFrameHost* render_frame_host,
   3806                                   int32 page_id,
   3807                                   const base::string16& title,
   3808                                   base::i18n::TextDirection title_direction) {
   3809   RenderViewHost* rvh = render_frame_host->GetRenderViewHost();
   3810 
   3811   // If we have a title, that's a pretty good indication that we've started
   3812   // getting useful data.
   3813   SetNotWaitingForResponse();
   3814 
   3815   // Try to find the navigation entry, which might not be the current one.
   3816   // For example, it might be from a pending RVH for the pending entry.
   3817   NavigationEntryImpl* entry = controller_.GetEntryWithPageID(
   3818       rvh->GetSiteInstance(), page_id);
   3819 
   3820   // We can handle title updates when we don't have an entry in
   3821   // UpdateTitleForEntry, but only if the update is from the current RVH.
   3822   // TODO(avi): Change to make decisions based on the RenderFrameHost.
   3823   if (!entry && rvh != GetRenderViewHost())
   3824     return;
   3825 
   3826   // TODO(evan): make use of title_direction.
   3827   // http://code.google.com/p/chromium/issues/detail?id=27094
   3828   if (!UpdateTitleForEntry(entry, title))
   3829     return;
   3830 
   3831   // Broadcast notifications when the UI should be updated.
   3832   if (entry == controller_.GetEntryAtOffset(0))
   3833     NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE);
   3834 }
   3835 
   3836 void WebContentsImpl::UpdateEncoding(RenderFrameHost* render_frame_host,
   3837                                      const std::string& encoding) {
   3838   SetEncoding(encoding);
   3839 }
   3840 
   3841 void WebContentsImpl::DocumentAvailableInMainFrame(
   3842     RenderViewHost* render_view_host) {
   3843   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3844                     DocumentAvailableInMainFrame());
   3845 }
   3846 void WebContentsImpl::RouteCloseEvent(RenderViewHost* rvh) {
   3847   // Tell the active RenderViewHost to run unload handlers and close, as long
   3848   // as the request came from a RenderViewHost in the same BrowsingInstance.
   3849   // In most cases, we receive this from a swapped out RenderViewHost.
   3850   // It is possible to receive it from one that has just been swapped in,
   3851   // in which case we might as well deliver the message anyway.
   3852   if (rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()))
   3853     GetRenderViewHost()->ClosePage();
   3854 }
   3855 
   3856 void WebContentsImpl::RouteMessageEvent(
   3857     RenderViewHost* rvh,
   3858     const ViewMsg_PostMessage_Params& params) {
   3859   // Only deliver the message to the active RenderViewHost if the request
   3860   // came from a RenderViewHost in the same BrowsingInstance or if this
   3861   // WebContents is dedicated to a browser plugin guest.
   3862   // Note: This check means that an embedder could theoretically receive a
   3863   // postMessage from anyone (not just its own guests). However, this is
   3864   // probably not a risk for apps since other pages won't have references
   3865   // to App windows.
   3866   if (!rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()) &&
   3867       !GetBrowserPluginGuest() && !GetBrowserPluginEmbedder())
   3868     return;
   3869 
   3870   ViewMsg_PostMessage_Params new_params(params);
   3871 
   3872   if (!params.message_port_ids.empty()) {
   3873     MessagePortMessageFilter* message_port_message_filter =
   3874         static_cast<RenderProcessHostImpl*>(GetRenderProcessHost())
   3875             ->message_port_message_filter();
   3876     message_port_message_filter->UpdateMessagePortsWithNewRoutes(
   3877         params.message_port_ids,
   3878         &new_params.new_routing_ids);
   3879   }
   3880 
   3881   // If there is a source_routing_id, translate it to the routing ID for
   3882   // the equivalent swapped out RVH in the target process.  If we need
   3883   // to create a swapped out RVH for the source tab, we create its opener
   3884   // chain as well, since those will also be accessible to the target page.
   3885   if (new_params.source_routing_id != MSG_ROUTING_NONE) {
   3886     // Try to look up the WebContents for the source page.
   3887     WebContentsImpl* source_contents = NULL;
   3888     RenderViewHostImpl* source_rvh = RenderViewHostImpl::FromID(
   3889         rvh->GetProcess()->GetID(), params.source_routing_id);
   3890     if (source_rvh) {
   3891       source_contents = static_cast<WebContentsImpl*>(
   3892           source_rvh->GetDelegate()->GetAsWebContents());
   3893     }
   3894 
   3895     if (source_contents) {
   3896       if (GetBrowserPluginGuest()) {
   3897         // We create a swapped out RenderView for the embedder in the guest's
   3898         // render process but we intentionally do not expose the embedder's
   3899         // opener chain to it.
   3900         new_params.source_routing_id =
   3901             source_contents->CreateSwappedOutRenderView(GetSiteInstance());
   3902       } else {
   3903         new_params.source_routing_id =
   3904             source_contents->CreateOpenerRenderViews(GetSiteInstance());
   3905       }
   3906     } else {
   3907       // We couldn't find it, so don't pass a source frame.
   3908       new_params.source_routing_id = MSG_ROUTING_NONE;
   3909     }
   3910   }
   3911 
   3912   // In most cases, we receive this from a swapped out RenderViewHost.
   3913   // It is possible to receive it from one that has just been swapped in,
   3914   // in which case we might as well deliver the message anyway.
   3915   Send(new ViewMsg_PostMessageEvent(GetRoutingID(), new_params));
   3916 }
   3917 
   3918 bool WebContentsImpl::AddMessageToConsole(int32 level,
   3919                                           const base::string16& message,
   3920                                           int32 line_no,
   3921                                           const base::string16& source_id) {
   3922   if (!delegate_)
   3923     return false;
   3924   return delegate_->AddMessageToConsole(this, level, message, line_no,
   3925                                         source_id);
   3926 }
   3927 
   3928 WebPreferences WebContentsImpl::ComputeWebkitPrefs() {
   3929   // We want to base the page config off of the actual URL, rather than the
   3930   // virtual URL.
   3931   // TODO(nasko): Investigate how to remove the GetActiveEntry usage here,
   3932   // as it is deprecated and can be out of sync with GetRenderViewHost().
   3933   GURL url = controller_.GetActiveEntry()
   3934       ? controller_.GetActiveEntry()->GetURL() : GURL::EmptyGURL();
   3935 
   3936   return GetRenderManager()->current_host()->ComputeWebkitPrefs(url);
   3937 }
   3938 
   3939 int WebContentsImpl::CreateSwappedOutRenderView(
   3940     SiteInstance* instance) {
   3941   return GetRenderManager()->CreateRenderFrame(
   3942       instance, MSG_ROUTING_NONE, true, true, true);
   3943 }
   3944 
   3945 void WebContentsImpl::OnUserGesture() {
   3946   // Notify observers.
   3947   FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetUserGesture());
   3948 
   3949   ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
   3950   if (rdh)  // NULL in unittests.
   3951     rdh->OnUserGesture(this);
   3952 }
   3953 
   3954 void WebContentsImpl::OnIgnoredUIEvent() {
   3955   // Notify observers.
   3956   FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetIgnoredUIEvent());
   3957 }
   3958 
   3959 void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh,
   3960                                            bool is_during_beforeunload,
   3961                                            bool is_during_unload) {
   3962   // Don't show hung renderer dialog for a swapped out RVH.
   3963   if (rvh != GetRenderViewHost())
   3964     return;
   3965 
   3966   RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh);
   3967 
   3968   // Ignore renderer unresponsive event if debugger is attached to the tab
   3969   // since the event may be a result of the renderer sitting on a breakpoint.
   3970   // See http://crbug.com/65458
   3971   if (DevToolsAgentHost::IsDebuggerAttached(this))
   3972     return;
   3973 
   3974   if (is_during_beforeunload || is_during_unload) {
   3975     // Hang occurred while firing the beforeunload/unload handler.
   3976     // Pretend the handler fired so tab closing continues as if it had.
   3977     rvhi->set_sudden_termination_allowed(true);
   3978 
   3979     if (!GetRenderManager()->ShouldCloseTabOnUnresponsiveRenderer())
   3980       return;
   3981 
   3982     // If the tab hangs in the beforeunload/unload handler there's really
   3983     // nothing we can do to recover. If the hang is in the beforeunload handler,
   3984     // pretend the beforeunload listeners have all fired and allow the delegate
   3985     // to continue closing; the user will not have the option of cancelling the
   3986     // close. Otherwise, pretend the unload listeners have all fired and close
   3987     // the tab.
   3988     bool close = true;
   3989     if (is_during_beforeunload && delegate_) {
   3990       delegate_->BeforeUnloadFired(this, true, &close);
   3991     }
   3992     if (close)
   3993       Close(rvh);
   3994     return;
   3995   }
   3996 
   3997   if (!GetRenderViewHostImpl() || !GetRenderViewHostImpl()->IsRenderViewLive())
   3998     return;
   3999 
   4000   if (delegate_)
   4001     delegate_->RendererUnresponsive(this);
   4002 }
   4003 
   4004 void WebContentsImpl::RendererResponsive(RenderViewHost* render_view_host) {
   4005   if (delegate_)
   4006     delegate_->RendererResponsive(this);
   4007 }
   4008 
   4009 void WebContentsImpl::LoadStateChanged(
   4010     const GURL& url,
   4011     const net::LoadStateWithParam& load_state,
   4012     uint64 upload_position,
   4013     uint64 upload_size) {
   4014   load_state_ = load_state;
   4015   upload_position_ = upload_position;
   4016   upload_size_ = upload_size;
   4017   load_state_host_ = net::IDNToUnicode(url.host(),
   4018       GetContentClient()->browser()->GetAcceptLangs(
   4019           GetBrowserContext()));
   4020   if (load_state_.state == net::LOAD_STATE_READING_RESPONSE)
   4021     SetNotWaitingForResponse();
   4022   if (IsLoading()) {
   4023     NotifyNavigationStateChanged(static_cast<InvalidateTypes>(
   4024         INVALIDATE_TYPE_LOAD | INVALIDATE_TYPE_TAB));
   4025   }
   4026 }
   4027 
   4028 void WebContentsImpl::BeforeUnloadFiredFromRenderManager(
   4029     bool proceed, const base::TimeTicks& proceed_time,
   4030     bool* proceed_to_fire_unload) {
   4031   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   4032                     BeforeUnloadFired(proceed_time));
   4033   if (delegate_)
   4034     delegate_->BeforeUnloadFired(this, proceed, proceed_to_fire_unload);
   4035   // Note: |this| might be deleted at this point.
   4036 }
   4037 
   4038 void WebContentsImpl::RenderProcessGoneFromRenderManager(
   4039     RenderViewHost* render_view_host) {
   4040   DCHECK(crashed_status_ != base::TERMINATION_STATUS_STILL_RUNNING);
   4041   RenderViewTerminated(render_view_host, crashed_status_, crashed_error_code_);
   4042 }
   4043 
   4044 void WebContentsImpl::UpdateRenderViewSizeForRenderManager() {
   4045   // TODO(brettw) this is a hack. See WebContentsView::SizeContents.
   4046   gfx::Size size = GetSizeForNewRenderView();
   4047   // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be
   4048   // here during container initialization and normal window size will be set
   4049   // later. In case of tab duplication this resizing to 0x0 prevents setting
   4050   // normal size later so just ignore it.
   4051   if (!size.IsEmpty())
   4052     view_->SizeContents(size);
   4053 }
   4054 
   4055 void WebContentsImpl::CancelModalDialogsForRenderManager() {
   4056   // We need to cancel modal dialogs when doing a process swap, since the load
   4057   // deferrer would prevent us from swapping out.
   4058   if (dialog_manager_)
   4059     dialog_manager_->CancelActiveAndPendingDialogs(this);
   4060 }
   4061 
   4062 void WebContentsImpl::NotifySwappedFromRenderManager(RenderFrameHost* old_host,
   4063                                                      RenderFrameHost* new_host,
   4064                                                      bool is_main_frame) {
   4065   if (is_main_frame) {
   4066     NotifyViewSwapped(old_host ? old_host->GetRenderViewHost() : NULL,
   4067                       new_host->GetRenderViewHost());
   4068 
   4069     // Make sure the visible RVH reflects the new delegate's preferences.
   4070     if (delegate_)
   4071       view_->SetOverscrollControllerEnabled(CanOverscrollContent());
   4072 
   4073     view_->RenderViewSwappedIn(new_host->GetRenderViewHost());
   4074   }
   4075 
   4076   NotifyFrameSwapped(old_host, new_host);
   4077 }
   4078 
   4079 int WebContentsImpl::CreateOpenerRenderViewsForRenderManager(
   4080     SiteInstance* instance) {
   4081   if (!opener_)
   4082     return MSG_ROUTING_NONE;
   4083 
   4084   // Recursively create RenderViews for anything else in the opener chain.
   4085   return opener_->CreateOpenerRenderViews(instance);
   4086 }
   4087 
   4088 int WebContentsImpl::CreateOpenerRenderViews(SiteInstance* instance) {
   4089   int opener_route_id = MSG_ROUTING_NONE;
   4090 
   4091   // If this tab has an opener, ensure it has a RenderView in the given
   4092   // SiteInstance as well.
   4093   if (opener_)
   4094     opener_route_id = opener_->CreateOpenerRenderViews(instance);
   4095 
   4096   // If any of the renderers (current, pending, or swapped out) for this
   4097   // WebContents has the same SiteInstance, use it.
   4098   if (GetRenderManager()->current_host()->GetSiteInstance() == instance)
   4099     return GetRenderManager()->current_host()->GetRoutingID();
   4100 
   4101   if (GetRenderManager()->pending_render_view_host() &&
   4102       GetRenderManager()->pending_render_view_host()->GetSiteInstance() ==
   4103           instance)
   4104     return GetRenderManager()->pending_render_view_host()->GetRoutingID();
   4105 
   4106   RenderViewHostImpl* rvh = GetRenderManager()->GetSwappedOutRenderViewHost(
   4107       instance);
   4108   if (rvh)
   4109     return rvh->GetRoutingID();
   4110 
   4111   // Create a swapped out RenderView in the given SiteInstance if none exists,
   4112   // setting its opener to the given route_id.  Return the new view's route_id.
   4113   return GetRenderManager()->CreateRenderFrame(
   4114       instance, opener_route_id, true, true, true);
   4115 }
   4116 
   4117 NavigationControllerImpl& WebContentsImpl::GetControllerForRenderManager() {
   4118   return GetController();
   4119 }
   4120 
   4121 WebUIImpl* WebContentsImpl::CreateWebUIForRenderManager(const GURL& url) {
   4122   return static_cast<WebUIImpl*>(CreateWebUI(url));
   4123 }
   4124 
   4125 NavigationEntry*
   4126     WebContentsImpl::GetLastCommittedNavigationEntryForRenderManager() {
   4127   return controller_.GetLastCommittedEntry();
   4128 }
   4129 
   4130 bool WebContentsImpl::CreateRenderViewForRenderManager(
   4131     RenderViewHost* render_view_host,
   4132     int opener_route_id,
   4133     int proxy_routing_id,
   4134     bool for_main_frame_navigation) {
   4135   TRACE_EVENT0("browser,navigation",
   4136                "WebContentsImpl::CreateRenderViewForRenderManager");
   4137   // Can be NULL during tests.
   4138   RenderWidgetHostViewBase* rwh_view;
   4139   // TODO(kenrb): RenderWidgetHostViewChildFrame special casing is temporary
   4140   // until RenderWidgetHost is attached to RenderFrameHost. We need to special
   4141   // case this because RWH is still a base class of RenderViewHost, and child
   4142   // frame RWHVs are unique in that they do not have their own WebContents.
   4143   if (!for_main_frame_navigation) {
   4144     RenderWidgetHostViewChildFrame* rwh_view_child =
   4145         new RenderWidgetHostViewChildFrame(render_view_host);
   4146     rwh_view = rwh_view_child;
   4147   } else {
   4148     rwh_view = view_->CreateViewForWidget(render_view_host);
   4149   }
   4150 
   4151   // Now that the RenderView has been created, we need to tell it its size.
   4152   if (rwh_view)
   4153     rwh_view->SetSize(GetSizeForNewRenderView());
   4154 
   4155   // Make sure we use the correct starting page_id in the new RenderView.
   4156   UpdateMaxPageIDIfNecessary(render_view_host);
   4157   int32 max_page_id =
   4158       GetMaxPageIDForSiteInstance(render_view_host->GetSiteInstance());
   4159 
   4160   if (!static_cast<RenderViewHostImpl*>(
   4161           render_view_host)->CreateRenderView(base::string16(),
   4162                                               opener_route_id,
   4163                                               proxy_routing_id,
   4164                                               max_page_id,
   4165                                               created_with_opener_)) {
   4166     return false;
   4167   }
   4168 
   4169 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
   4170   // Force a ViewMsg_Resize to be sent, needed to make plugins show up on
   4171   // linux. See crbug.com/83941.
   4172   if (rwh_view) {
   4173     if (RenderWidgetHost* render_widget_host = rwh_view->GetRenderWidgetHost())
   4174       render_widget_host->WasResized();
   4175   }
   4176 #endif
   4177 
   4178   return true;
   4179 }
   4180 
   4181 bool WebContentsImpl::CreateRenderFrameForRenderManager(
   4182     RenderFrameHost* render_frame_host,
   4183     int parent_routing_id) {
   4184   TRACE_EVENT0("browser,navigation",
   4185                "WebContentsImpl::CreateRenderFrameForRenderManager");
   4186 
   4187   RenderFrameHostImpl* rfh =
   4188       static_cast<RenderFrameHostImpl*>(render_frame_host);
   4189   if (!rfh->CreateRenderFrame(parent_routing_id))
   4190     return false;
   4191 
   4192   // TODO(nasko): When RenderWidgetHost is owned by RenderFrameHost, the passed
   4193   // RenderFrameHost will have to be associated with the appropriate
   4194   // RenderWidgetHostView or a new one should be created here.
   4195 
   4196   return true;
   4197 }
   4198 
   4199 #if defined(OS_ANDROID)
   4200 
   4201 base::android::ScopedJavaLocalRef<jobject>
   4202 WebContentsImpl::GetJavaWebContents() {
   4203   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   4204   return GetWebContentsAndroid()->GetJavaObject();
   4205 }
   4206 
   4207 WebContentsAndroid* WebContentsImpl::GetWebContentsAndroid() {
   4208   WebContentsAndroid* web_contents_android =
   4209       static_cast<WebContentsAndroid*>(GetUserData(kWebContentsAndroidKey));
   4210   if (!web_contents_android) {
   4211     web_contents_android = new WebContentsAndroid(this);
   4212     SetUserData(kWebContentsAndroidKey, web_contents_android);
   4213   }
   4214   return web_contents_android;
   4215 }
   4216 
   4217 bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() {
   4218   return CreateRenderViewForRenderManager(GetRenderViewHost(),
   4219                                           MSG_ROUTING_NONE,
   4220                                           MSG_ROUTING_NONE,
   4221                                           true);
   4222 }
   4223 
   4224 #elif defined(OS_MACOSX)
   4225 
   4226 void WebContentsImpl::SetAllowOtherViews(bool allow) {
   4227   view_->SetAllowOtherViews(allow);
   4228 }
   4229 
   4230 bool WebContentsImpl::GetAllowOtherViews() {
   4231   return view_->GetAllowOtherViews();
   4232 }
   4233 
   4234 #endif
   4235 
   4236 void WebContentsImpl::OnDialogClosed(int render_process_id,
   4237                                      int render_frame_id,
   4238                                      IPC::Message* reply_msg,
   4239                                      bool dialog_was_suppressed,
   4240                                      bool success,
   4241                                      const base::string16& user_input) {
   4242   RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(render_process_id,
   4243                                                          render_frame_id);
   4244   last_dialog_suppressed_ = dialog_was_suppressed;
   4245 
   4246   if (is_showing_before_unload_dialog_ && !success) {
   4247     // If a beforeunload dialog is canceled, we need to stop the throbber from
   4248     // spinning, since we forced it to start spinning in Navigate.
   4249     if (rfh)
   4250       DidStopLoading(rfh);
   4251     controller_.DiscardNonCommittedEntries();
   4252 
   4253     FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   4254                       BeforeUnloadDialogCancelled());
   4255   }
   4256 
   4257   is_showing_before_unload_dialog_ = false;
   4258   if (rfh) {
   4259     rfh->JavaScriptDialogClosed(reply_msg, success, user_input,
   4260                                 dialog_was_suppressed);
   4261   } else {
   4262     // Don't leak the sync IPC reply if the RFH or process is gone.
   4263     delete reply_msg;
   4264   }
   4265 }
   4266 
   4267 void WebContentsImpl::SetEncoding(const std::string& encoding) {
   4268   if (encoding == last_reported_encoding_)
   4269     return;
   4270   last_reported_encoding_ = encoding;
   4271 
   4272   canonical_encoding_ = GetContentClient()->browser()->
   4273       GetCanonicalEncodingNameByAliasName(encoding);
   4274 }
   4275 
   4276 void WebContentsImpl::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) {
   4277   RenderWidgetHostViewBase* rwh_view = view_->CreateViewForWidget(rvh);
   4278   // Can be NULL during tests.
   4279   if (rwh_view)
   4280     rwh_view->SetSize(GetContainerBounds().size());
   4281 }
   4282 
   4283 bool WebContentsImpl::IsHidden() {
   4284   return capturer_count_ == 0 && !should_normally_be_visible_;
   4285 }
   4286 
   4287 RenderFrameHostManager* WebContentsImpl::GetRenderManager() const {
   4288   return frame_tree_.root()->render_manager();
   4289 }
   4290 
   4291 RenderViewHostImpl* WebContentsImpl::GetRenderViewHostImpl() {
   4292   return static_cast<RenderViewHostImpl*>(GetRenderViewHost());
   4293 }
   4294 
   4295 BrowserPluginGuest* WebContentsImpl::GetBrowserPluginGuest() const {
   4296   return browser_plugin_guest_.get();
   4297 }
   4298 
   4299 void WebContentsImpl::SetBrowserPluginGuest(BrowserPluginGuest* guest) {
   4300   CHECK(!browser_plugin_guest_);
   4301   browser_plugin_guest_.reset(guest);
   4302 }
   4303 
   4304 BrowserPluginEmbedder* WebContentsImpl::GetBrowserPluginEmbedder() const {
   4305   return browser_plugin_embedder_.get();
   4306 }
   4307 
   4308 void WebContentsImpl::ClearPowerSaveBlockers(
   4309     RenderFrameHost* render_frame_host) {
   4310   RemoveAllMediaPlayerEntries(render_frame_host, &active_audio_players_);
   4311   RemoveAllMediaPlayerEntries(render_frame_host, &active_video_players_);
   4312   MaybeReleasePowerSaveBlockers();
   4313 }
   4314 
   4315 void WebContentsImpl::ClearAllPowerSaveBlockers() {
   4316   active_audio_players_.clear();
   4317   active_video_players_.clear();
   4318   audio_power_save_blocker_.reset();
   4319   video_power_save_blocker_.reset();
   4320 }
   4321 
   4322 gfx::Size WebContentsImpl::GetSizeForNewRenderView() {
   4323   gfx::Size size;
   4324   if (delegate_)
   4325     size = delegate_->GetSizeForNewRenderView(this);
   4326   if (size.IsEmpty())
   4327     size = GetContainerBounds().size();
   4328   return size;
   4329 }
   4330 
   4331 void WebContentsImpl::OnFrameRemoved(RenderFrameHost* render_frame_host) {
   4332   FOR_EACH_OBSERVER(
   4333       WebContentsObserver, observers_, FrameDetached(render_frame_host));
   4334 }
   4335 
   4336 void WebContentsImpl::OnPreferredSizeChanged(const gfx::Size& old_size) {
   4337   if (!delegate_)
   4338     return;
   4339   const gfx::Size new_size = GetPreferredSize();
   4340   if (new_size != old_size)
   4341     delegate_->UpdatePreferredSize(this, new_size);
   4342 }
   4343 
   4344 void WebContentsImpl::AddMediaPlayerEntry(int64 player_cookie,
   4345                                           ActiveMediaPlayerMap* player_map) {
   4346   const uintptr_t key =
   4347       reinterpret_cast<uintptr_t>(render_frame_message_source_);
   4348   DCHECK(std::find((*player_map)[key].begin(),
   4349                    (*player_map)[key].end(),
   4350                    player_cookie) == (*player_map)[key].end());
   4351   (*player_map)[key].push_back(player_cookie);
   4352 }
   4353 
   4354 void WebContentsImpl::RemoveMediaPlayerEntry(int64 player_cookie,
   4355                                              ActiveMediaPlayerMap* player_map) {
   4356   const uintptr_t key =
   4357       reinterpret_cast<uintptr_t>(render_frame_message_source_);
   4358   ActiveMediaPlayerMap::iterator it = player_map->find(key);
   4359   if (it == player_map->end())
   4360     return;
   4361 
   4362   // Remove the player.
   4363   PlayerList::iterator player_it =
   4364       std::find(it->second.begin(), it->second.end(), player_cookie);
   4365   if (player_it != it->second.end())
   4366     it->second.erase(player_it);
   4367 
   4368   // If there are no players left, remove the map entry.
   4369   if (it->second.empty())
   4370     player_map->erase(it);
   4371 }
   4372 
   4373 void WebContentsImpl::RemoveAllMediaPlayerEntries(
   4374     RenderFrameHost* render_frame_host,
   4375     ActiveMediaPlayerMap* player_map) {
   4376   ActiveMediaPlayerMap::iterator it =
   4377       player_map->find(reinterpret_cast<uintptr_t>(render_frame_host));
   4378   if (it == player_map->end())
   4379     return;
   4380   player_map->erase(it);
   4381 }
   4382 
   4383 void WebContentsImpl::ResumeResponseDeferredAtStart() {
   4384   FrameTreeNode* node = frame_tree_.root();
   4385   node->render_manager()->ResumeResponseDeferredAtStart();
   4386 }
   4387 
   4388 void WebContentsImpl::SetForceDisableOverscrollContent(bool force_disable) {
   4389   force_disable_overscroll_content_ = force_disable;
   4390   if (view_)
   4391     view_->SetOverscrollControllerEnabled(CanOverscrollContent());
   4392 }
   4393 
   4394 }  // namespace content
   4395