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/browser_plugin/browser_plugin_embedder.h"
     22 #include "content/browser/browser_plugin/browser_plugin_guest.h"
     23 #include "content/browser/browser_plugin/browser_plugin_guest_manager.h"
     24 #include "content/browser/child_process_security_policy_impl.h"
     25 #include "content/browser/devtools/devtools_manager_impl.h"
     26 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
     27 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
     28 #include "content/browser/download/download_stats.h"
     29 #include "content/browser/download/mhtml_generation_manager.h"
     30 #include "content/browser/download/save_package.h"
     31 #include "content/browser/frame_host/interstitial_page_impl.h"
     32 #include "content/browser/frame_host/navigation_entry_impl.h"
     33 #include "content/browser/frame_host/navigator_impl.h"
     34 #include "content/browser/frame_host/render_frame_host_impl.h"
     35 #include "content/browser/host_zoom_map_impl.h"
     36 #include "content/browser/loader/resource_dispatcher_host_impl.h"
     37 #include "content/browser/message_port_message_filter.h"
     38 #include "content/browser/message_port_service.h"
     39 #include "content/browser/power_save_blocker_impl.h"
     40 #include "content/browser/renderer_host/render_process_host_impl.h"
     41 #include "content/browser/renderer_host/render_view_host_impl.h"
     42 #include "content/browser/renderer_host/render_widget_host_impl.h"
     43 #include "content/browser/site_instance_impl.h"
     44 #include "content/browser/web_contents/web_contents_view_guest.h"
     45 #include "content/browser/webui/generic_handler.h"
     46 #include "content/browser/webui/web_ui_controller_factory_registry.h"
     47 #include "content/browser/webui/web_ui_impl.h"
     48 #include "content/common/browser_plugin/browser_plugin_constants.h"
     49 #include "content/common/browser_plugin/browser_plugin_messages.h"
     50 #include "content/common/frame_messages.h"
     51 #include "content/common/image_messages.h"
     52 #include "content/common/ssl_status_serialization.h"
     53 #include "content/common/view_messages.h"
     54 #include "content/port/browser/render_view_host_delegate_view.h"
     55 #include "content/port/browser/render_widget_host_view_port.h"
     56 #include "content/public/browser/browser_context.h"
     57 #include "content/public/browser/color_chooser.h"
     58 #include "content/public/browser/content_browser_client.h"
     59 #include "content/public/browser/devtools_agent_host.h"
     60 #include "content/public/browser/download_manager.h"
     61 #include "content/public/browser/download_url_parameters.h"
     62 #include "content/public/browser/invalidate_type.h"
     63 #include "content/public/browser/javascript_dialog_manager.h"
     64 #include "content/public/browser/load_from_memory_cache_details.h"
     65 #include "content/public/browser/load_notification_details.h"
     66 #include "content/public/browser/navigation_details.h"
     67 #include "content/public/browser/notification_details.h"
     68 #include "content/public/browser/notification_service.h"
     69 #include "content/public/browser/resource_request_details.h"
     70 #include "content/public/browser/storage_partition.h"
     71 #include "content/public/browser/user_metrics.h"
     72 #include "content/public/browser/web_contents_delegate.h"
     73 #include "content/public/browser/web_contents_observer.h"
     74 #include "content/public/browser/web_contents_view.h"
     75 #include "content/public/common/bindings_policy.h"
     76 #include "content/public/common/content_constants.h"
     77 #include "content/public/common/content_switches.h"
     78 #include "content/public/common/page_zoom.h"
     79 #include "content/public/common/result_codes.h"
     80 #include "content/public/common/url_constants.h"
     81 #include "content/public/common/url_utils.h"
     82 #include "net/base/mime_util.h"
     83 #include "net/base/net_util.h"
     84 #include "net/http/http_cache.h"
     85 #include "net/http/http_transaction_factory.h"
     86 #include "net/url_request/url_request_context.h"
     87 #include "net/url_request/url_request_context_getter.h"
     88 #include "ui/base/layout.h"
     89 #include "ui/gfx/display.h"
     90 #include "ui/gfx/screen.h"
     91 #include "ui/gl/gl_switches.h"
     92 #include "webkit/common/webpreferences.h"
     93 
     94 #if defined(OS_ANDROID)
     95 #include "content/browser/android/date_time_chooser_android.h"
     96 #include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
     97 #include "content/browser/web_contents/web_contents_android.h"
     98 #include "content/common/java_bridge_messages.h"
     99 #include "content/public/browser/android/content_view_core.h"
    100 #endif
    101 
    102 #if defined(OS_MACOSX)
    103 #include "base/mac/foundation_util.h"
    104 #include "ui/gl/io_surface_support_mac.h"
    105 #endif
    106 
    107 // Cross-Site Navigations
    108 //
    109 // If a WebContentsImpl is told to navigate to a different web site (as
    110 // determined by SiteInstance), it will replace its current RenderViewHost with
    111 // a new RenderViewHost dedicated to the new SiteInstance.  This works as
    112 // follows:
    113 //
    114 // - RVHM::Navigate determines whether the destination is cross-site, and if so,
    115 //   it creates a pending_render_view_host_.
    116 // - The pending RVH is "suspended," so that no navigation messages are sent to
    117 //   its renderer until the beforeunload JavaScript handler has a chance to
    118 //   run in the current RVH.
    119 // - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton)
    120 //   that it has a pending cross-site request.  We will check this on the IO
    121 //   thread when deciding how to handle the response.
    122 // - The current RVH runs its beforeunload handler.  If it returns false, we
    123 //   cancel all the pending logic.  Otherwise we allow the pending RVH to send
    124 //   the navigation request to its renderer.
    125 // - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the
    126 //   main resource load on the pending RVH.  It creates a
    127 //   CrossSiteResourceHandler to check whether a process swap is needed when
    128 //   the request is ready to commit.
    129 // - When RDH receives a response, the BufferedResourceHandler determines
    130 //   whether it is a download.  If so, it sends a message to the new renderer
    131 //   causing it to cancel the request, and the download proceeds. For now, the
    132 //   pending RVH remains until the next DidNavigate event for this
    133 //   WebContentsImpl. This isn't ideal, but it doesn't affect any functionality.
    134 // - After RDH receives a response and determines that it is safe and not a
    135 //   download, the CrossSiteResourceHandler checks whether a process swap is
    136 //   needed (either because CrossSiteRequestManager has state for it or because
    137 //   a transfer was needed for a redirect).
    138 // - If so, CrossSiteResourceHandler pauses the response to first run the old
    139 //   page's unload handler.  It does this by asynchronously calling the
    140 //   OnCrossSiteResponse method of RenderFrameHostManager on the UI thread,
    141 //   which sends a SwapOut message to the current RVH.
    142 // - Once the unload handler is finished, RVHM::SwappedOut checks if a transfer
    143 //   to a new process is needed, based on the stored pending_nav_params_.  (This
    144 //   is independent of whether we started out with a cross-process navigation.)
    145 //   - If not, it just tells the ResourceDispatcherHost to resume the response
    146 //     to its current RenderViewHost.
    147 //   - If so, it cancels the current pending RenderViewHost and sets up a new
    148 //     navigation using RequestTransferURL.  When the transferred request
    149 //     arrives in the ResourceDispatcherHost, we transfer the response and
    150 //     resume it.
    151 // - The pending renderer sends a FrameNavigate message that invokes the
    152 //   DidNavigate method.  This replaces the current RVH with the
    153 //   pending RVH.
    154 // - The previous renderer is kept swapped out in RenderFrameHostManager in case
    155 //   the user goes back.  The process only stays live if another tab is using
    156 //   it, but if so, the existing frame relationships will be maintained.
    157 
    158 namespace content {
    159 namespace {
    160 
    161 const char kDotGoogleDotCom[] = ".google.com";
    162 
    163 #if defined(OS_ANDROID)
    164 const char kWebContentsAndroidKey[] = "web_contents_android";
    165 #endif  // OS_ANDROID
    166 
    167 base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> >
    168 g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
    169 
    170 static int StartDownload(content::RenderViewHost* rvh,
    171                          const GURL& url,
    172                          bool is_favicon,
    173                          uint32_t max_bitmap_size) {
    174   static int g_next_image_download_id = 0;
    175   rvh->Send(new ImageMsg_DownloadImage(rvh->GetRoutingID(),
    176                                        ++g_next_image_download_id,
    177                                        url,
    178                                        is_favicon,
    179                                        max_bitmap_size));
    180   return g_next_image_download_id;
    181 }
    182 
    183 ViewMsg_Navigate_Type::Value GetNavigationType(
    184     BrowserContext* browser_context, const NavigationEntryImpl& entry,
    185     NavigationController::ReloadType reload_type) {
    186   switch (reload_type) {
    187     case NavigationControllerImpl::RELOAD:
    188       return ViewMsg_Navigate_Type::RELOAD;
    189     case NavigationControllerImpl::RELOAD_IGNORING_CACHE:
    190       return ViewMsg_Navigate_Type::RELOAD_IGNORING_CACHE;
    191     case NavigationControllerImpl::RELOAD_ORIGINAL_REQUEST_URL:
    192       return ViewMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL;
    193     case NavigationControllerImpl::NO_RELOAD:
    194       break;  // Fall through to rest of function.
    195   }
    196 
    197   // |RenderViewImpl::PopulateStateFromPendingNavigationParams| differentiates
    198   // between |RESTORE_WITH_POST| and |RESTORE|.
    199   if (entry.restore_type() ==
    200       NavigationEntryImpl::RESTORE_LAST_SESSION_EXITED_CLEANLY) {
    201     if (entry.GetHasPostData())
    202       return ViewMsg_Navigate_Type::RESTORE_WITH_POST;
    203     return ViewMsg_Navigate_Type::RESTORE;
    204   }
    205 
    206   return ViewMsg_Navigate_Type::NORMAL;
    207 }
    208 
    209 void MakeNavigateParams(const NavigationEntryImpl& entry,
    210                         const NavigationControllerImpl& controller,
    211                         WebContentsDelegate* delegate,
    212                         NavigationController::ReloadType reload_type,
    213                         ViewMsg_Navigate_Params* params) {
    214   params->page_id = entry.GetPageID();
    215   params->should_clear_history_list = entry.should_clear_history_list();
    216   params->should_replace_current_entry = entry.should_replace_entry();
    217   if (entry.should_clear_history_list()) {
    218     // Set the history list related parameters to the same values a
    219     // NavigationController would return before its first navigation. This will
    220     // fully clear the RenderView's view of the session history.
    221     params->pending_history_list_offset = -1;
    222     params->current_history_list_offset = -1;
    223     params->current_history_list_length = 0;
    224   } else {
    225     params->pending_history_list_offset = controller.GetIndexOfEntry(&entry);
    226     params->current_history_list_offset =
    227         controller.GetLastCommittedEntryIndex();
    228     params->current_history_list_length = controller.GetEntryCount();
    229   }
    230   params->url = entry.GetURL();
    231   if (!entry.GetBaseURLForDataURL().is_empty()) {
    232     params->base_url_for_data_url = entry.GetBaseURLForDataURL();
    233     params->history_url_for_data_url = entry.GetVirtualURL();
    234   }
    235   params->referrer = entry.GetReferrer();
    236   params->transition = entry.GetTransitionType();
    237   params->page_state = entry.GetPageState();
    238   params->navigation_type =
    239       GetNavigationType(controller.GetBrowserContext(), entry, reload_type);
    240   params->request_time = base::Time::Now();
    241   params->extra_headers = entry.extra_headers();
    242   params->transferred_request_child_id =
    243       entry.transferred_global_request_id().child_id;
    244   params->transferred_request_request_id =
    245       entry.transferred_global_request_id().request_id;
    246   params->is_overriding_user_agent = entry.GetIsOverridingUserAgent();
    247   // Avoid downloading when in view-source mode.
    248   params->allow_download = !entry.IsViewSourceMode();
    249   params->is_post = entry.GetHasPostData();
    250   if (entry.GetBrowserInitiatedPostData()) {
    251     params->browser_initiated_post_data.assign(
    252         entry.GetBrowserInitiatedPostData()->front(),
    253         entry.GetBrowserInitiatedPostData()->front() +
    254             entry.GetBrowserInitiatedPostData()->size());
    255   }
    256 
    257   params->redirects = entry.redirect_chain();
    258 
    259   params->can_load_local_resources = entry.GetCanLoadLocalResources();
    260   params->frame_to_navigate = entry.GetFrameToNavigate();
    261 
    262   if (delegate)
    263     delegate->AddNavigationHeaders(params->url, &params->extra_headers);
    264 }
    265 
    266 void NotifyCacheOnIO(
    267     scoped_refptr<net::URLRequestContextGetter> request_context,
    268     const GURL& url,
    269     const std::string& http_method) {
    270   request_context->GetURLRequestContext()->http_transaction_factory()->
    271       GetCache()->OnExternalCacheHit(url, http_method);
    272 }
    273 
    274 // Helper function for retrieving all the sites in a frame tree.
    275 bool CollectSites(BrowserContext* context,
    276                   std::set<GURL>* sites,
    277                   FrameTreeNode* node) {
    278   sites->insert(SiteInstance::GetSiteForURL(context, node->current_url()));
    279   return true;
    280 }
    281 
    282 }  // namespace
    283 
    284 WebContents* WebContents::Create(const WebContents::CreateParams& params) {
    285   return WebContentsImpl::CreateWithOpener(
    286       params, static_cast<WebContentsImpl*>(params.opener));
    287 }
    288 
    289 WebContents* WebContents::CreateWithSessionStorage(
    290     const WebContents::CreateParams& params,
    291     const SessionStorageNamespaceMap& session_storage_namespace_map) {
    292   WebContentsImpl* new_contents = new WebContentsImpl(
    293       params.browser_context, NULL);
    294 
    295   for (SessionStorageNamespaceMap::const_iterator it =
    296            session_storage_namespace_map.begin();
    297        it != session_storage_namespace_map.end();
    298        ++it) {
    299     new_contents->GetController()
    300         .SetSessionStorageNamespace(it->first, it->second.get());
    301   }
    302 
    303   new_contents->Init(params);
    304   return new_contents;
    305 }
    306 
    307 void WebContentsImpl::AddCreatedCallback(const CreatedCallback& callback) {
    308   g_created_callbacks.Get().push_back(callback);
    309 }
    310 
    311 void WebContentsImpl::RemoveCreatedCallback(const CreatedCallback& callback) {
    312   for (size_t i = 0; i < g_created_callbacks.Get().size(); ++i) {
    313     if (g_created_callbacks.Get().at(i).Equals(callback)) {
    314       g_created_callbacks.Get().erase(g_created_callbacks.Get().begin() + i);
    315       return;
    316     }
    317   }
    318 }
    319 
    320 WebContents* WebContents::FromRenderViewHost(const RenderViewHost* rvh) {
    321   return rvh->GetDelegate()->GetAsWebContents();
    322 }
    323 
    324 // WebContentsImpl::DestructionObserver ----------------------------------------
    325 
    326 class WebContentsImpl::DestructionObserver : public WebContentsObserver {
    327  public:
    328   DestructionObserver(WebContentsImpl* owner, WebContents* watched_contents)
    329       : WebContentsObserver(watched_contents),
    330         owner_(owner) {
    331   }
    332 
    333   // WebContentsObserver:
    334   virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE {
    335     owner_->OnWebContentsDestroyed(static_cast<WebContentsImpl*>(web_contents));
    336   }
    337 
    338  private:
    339   WebContentsImpl* owner_;
    340 
    341   DISALLOW_COPY_AND_ASSIGN(DestructionObserver);
    342 };
    343 
    344 // WebContentsImpl -------------------------------------------------------------
    345 
    346 WebContentsImpl::WebContentsImpl(
    347     BrowserContext* browser_context,
    348     WebContentsImpl* opener)
    349     : delegate_(NULL),
    350       controller_(this, browser_context),
    351       render_view_host_delegate_view_(NULL),
    352       opener_(opener),
    353 #if defined(OS_WIN) && defined(USE_AURA)
    354       accessible_parent_(NULL),
    355 #endif
    356       frame_tree_(new NavigatorImpl(&controller_, this),
    357                   this, this, this, this),
    358       is_loading_(false),
    359       crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
    360       crashed_error_code_(0),
    361       waiting_for_response_(false),
    362       load_state_(net::LOAD_STATE_IDLE, base::string16()),
    363       upload_size_(0),
    364       upload_position_(0),
    365       displayed_insecure_content_(false),
    366       capturer_count_(0),
    367       should_normally_be_visible_(true),
    368       is_being_destroyed_(false),
    369       notify_disconnection_(false),
    370       dialog_manager_(NULL),
    371       is_showing_before_unload_dialog_(false),
    372       closed_by_user_gesture_(false),
    373       minimum_zoom_percent_(static_cast<int>(kMinimumZoomFactor * 100)),
    374       maximum_zoom_percent_(static_cast<int>(kMaximumZoomFactor * 100)),
    375       temporary_zoom_settings_(false),
    376       color_chooser_identifier_(0),
    377       render_view_message_source_(NULL),
    378       fullscreen_widget_routing_id_(MSG_ROUTING_NONE) {
    379   for (size_t i = 0; i < g_created_callbacks.Get().size(); i++)
    380     g_created_callbacks.Get().at(i).Run(this);
    381   frame_tree_.SetFrameRemoveListener(
    382       base::Bind(&WebContentsImpl::OnFrameRemoved,
    383                  base::Unretained(this)));
    384 }
    385 
    386 WebContentsImpl::~WebContentsImpl() {
    387   is_being_destroyed_ = true;
    388 
    389   ClearAllPowerSaveBlockers();
    390 
    391   for (std::set<RenderWidgetHostImpl*>::iterator iter =
    392            created_widgets_.begin(); iter != created_widgets_.end(); ++iter) {
    393     (*iter)->DetachDelegate();
    394   }
    395   created_widgets_.clear();
    396 
    397   // Clear out any JavaScript state.
    398   if (dialog_manager_)
    399     dialog_manager_->WebContentsDestroyed(this);
    400 
    401   if (color_chooser_)
    402     color_chooser_->End();
    403 
    404   NotifyDisconnected();
    405 
    406   // Notify any observer that have a reference on this WebContents.
    407   NotificationService::current()->Notify(
    408       NOTIFICATION_WEB_CONTENTS_DESTROYED,
    409       Source<WebContents>(this),
    410       NotificationService::NoDetails());
    411 
    412   // TODO(brettw) this should be moved to the view.
    413 #if defined(OS_WIN) && !defined(USE_AURA)
    414   // If we still have a window handle, destroy it. GetNativeView can return
    415   // NULL if this contents was part of a window that closed.
    416   if (view_->GetNativeView()) {
    417     RenderViewHost* host = GetRenderViewHost();
    418     if (host && host->GetView())
    419       RenderWidgetHostViewPort::FromRWHV(host->GetView())->WillWmDestroy();
    420   }
    421 #endif
    422 
    423   RenderViewHost* pending_rvh = GetRenderManager()->pending_render_view_host();
    424   if (pending_rvh) {
    425     FOR_EACH_OBSERVER(WebContentsObserver,
    426                       observers_,
    427                       RenderViewDeleted(pending_rvh));
    428   }
    429 
    430   FOR_EACH_OBSERVER(WebContentsObserver,
    431                     observers_,
    432                     RenderViewDeleted(GetRenderManager()->current_host()));
    433 
    434   FOR_EACH_OBSERVER(WebContentsObserver,
    435                     observers_,
    436                     WebContentsImplDestroyed());
    437 
    438   SetDelegate(NULL);
    439 
    440   STLDeleteContainerPairSecondPointers(destruction_observers_.begin(),
    441                                        destruction_observers_.end());
    442 }
    443 
    444 WebContentsImpl* WebContentsImpl::CreateWithOpener(
    445     const WebContents::CreateParams& params,
    446     WebContentsImpl* opener) {
    447   TRACE_EVENT0("browser", "WebContentsImpl::CreateWithOpener");
    448   WebContentsImpl* new_contents = new WebContentsImpl(
    449       params.browser_context, opener);
    450 
    451   new_contents->Init(params);
    452   return new_contents;
    453 }
    454 
    455 // static
    456 BrowserPluginGuest* WebContentsImpl::CreateGuest(
    457     BrowserContext* browser_context,
    458     SiteInstance* site_instance,
    459     int guest_instance_id,
    460     scoped_ptr<base::DictionaryValue> extra_params) {
    461   WebContentsImpl* new_contents = new WebContentsImpl(browser_context, NULL);
    462 
    463   // This makes |new_contents| act as a guest.
    464   // For more info, see comment above class BrowserPluginGuest.
    465   BrowserPluginGuest::Create(
    466       guest_instance_id, site_instance, new_contents, extra_params.Pass());
    467 
    468   WebContents::CreateParams create_params(browser_context, site_instance);
    469   new_contents->Init(create_params);
    470 
    471   // We are instantiating a WebContents for browser plugin. Set its subframe bit
    472   // to true.
    473   static_cast<RenderViewHostImpl*>(
    474       new_contents->GetRenderViewHost())->set_is_subframe(true);
    475 
    476   return new_contents->browser_plugin_guest_.get();
    477 }
    478 
    479 RenderFrameHostManager* WebContentsImpl::GetRenderManagerForTesting() {
    480   return GetRenderManager();
    481 }
    482 
    483 bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
    484                                         const IPC::Message& message) {
    485   return OnMessageReceived(render_view_host, NULL, message);
    486 }
    487 
    488 bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
    489                                         RenderFrameHost* render_frame_host,
    490                                         const IPC::Message& message) {
    491   DCHECK(render_view_host || render_frame_host);
    492   if (GetWebUI() &&
    493       static_cast<WebUIImpl*>(GetWebUI())->OnMessageReceived(message)) {
    494     return true;
    495   }
    496 
    497   ObserverListBase<WebContentsObserver>::Iterator it(observers_);
    498   WebContentsObserver* observer;
    499   while ((observer = it.GetNext()) != NULL)
    500     if (observer->OnMessageReceived(message))
    501       return true;
    502 
    503   // Message handlers should be aware of which RenderViewHost sent the
    504   // message, which is temporarily stored in render_view_message_source_.
    505   render_view_message_source_ = render_view_host;
    506   bool handled = true;
    507   bool message_is_ok = true;
    508   IPC_BEGIN_MESSAGE_MAP_EX(WebContentsImpl, message, message_is_ok)
    509     IPC_MESSAGE_HANDLER(FrameHostMsg_PepperPluginHung, OnPepperPluginHung)
    510     IPC_MESSAGE_HANDLER(FrameHostMsg_PluginCrashed, OnPluginCrashed)
    511     IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache,
    512                         OnDidLoadResourceFromMemoryCache)
    513     IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent,
    514                         OnDidDisplayInsecureContent)
    515     IPC_MESSAGE_HANDLER(ViewHostMsg_DidRunInsecureContent,
    516                         OnDidRunInsecureContent)
    517     IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentLoadedInFrame,
    518                         OnDocumentLoadedInFrame)
    519     IPC_MESSAGE_HANDLER(ViewHostMsg_DidFinishLoad, OnDidFinishLoad)
    520     IPC_MESSAGE_HANDLER(ViewHostMsg_DidFailLoadWithError,
    521                         OnDidFailLoadWithError)
    522     IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset, OnGoToEntryAtOffset)
    523     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits, OnUpdateZoomLimits)
    524     IPC_MESSAGE_HANDLER(ViewHostMsg_EnumerateDirectory, OnEnumerateDirectory)
    525     IPC_MESSAGE_HANDLER(ViewHostMsg_JSOutOfMemory, OnJSOutOfMemory)
    526     IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler,
    527                         OnRegisterProtocolHandler)
    528     IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnFindReply)
    529     IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed, OnAppCacheAccessed)
    530     IPC_MESSAGE_HANDLER(ViewHostMsg_OpenColorChooser, OnOpenColorChooser)
    531     IPC_MESSAGE_HANDLER(ViewHostMsg_EndColorChooser, OnEndColorChooser)
    532     IPC_MESSAGE_HANDLER(ViewHostMsg_SetSelectedColorInColorChooser,
    533                         OnSetSelectedColorInColorChooser)
    534     IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnWebUISend)
    535     IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission,
    536                         OnRequestPpapiBrokerPermission)
    537     IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_AllocateInstanceID,
    538                                 OnBrowserPluginMessage(message))
    539     IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_Attach,
    540                                 OnBrowserPluginMessage(message))
    541     IPC_MESSAGE_HANDLER(ImageHostMsg_DidDownloadImage, OnDidDownloadImage)
    542     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFaviconURL, OnUpdateFaviconURL)
    543 #if defined(OS_ANDROID)
    544     IPC_MESSAGE_HANDLER(ViewHostMsg_FindMatchRects_Reply,
    545                         OnFindMatchRectsReply)
    546     IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog,
    547                         OnOpenDateTimeDialog)
    548     IPC_MESSAGE_HANDLER_DELAY_REPLY(JavaBridgeHostMsg_GetChannelHandle,
    549                                     OnJavaBridgeGetChannelHandle)
    550 #endif
    551     IPC_MESSAGE_HANDLER(ViewHostMsg_MediaNotification, OnMediaNotification)
    552     IPC_MESSAGE_HANDLER(ViewHostMsg_DidFirstVisuallyNonEmptyPaint,
    553                         OnFirstVisuallyNonEmptyPaint)
    554     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowValidationMessage,
    555                         OnShowValidationMessage)
    556     IPC_MESSAGE_HANDLER(ViewHostMsg_HideValidationMessage,
    557                         OnHideValidationMessage)
    558     IPC_MESSAGE_HANDLER(ViewHostMsg_MoveValidationMessage,
    559                         OnMoveValidationMessage)
    560     IPC_MESSAGE_UNHANDLED(handled = false)
    561   IPC_END_MESSAGE_MAP_EX()
    562   render_view_message_source_ = NULL;
    563 
    564   if (!message_is_ok) {
    565     RecordAction(UserMetricsAction("BadMessageTerminate_RVD"));
    566     GetRenderProcessHost()->ReceivedBadMessage();
    567   }
    568 
    569   return handled;
    570 }
    571 
    572 void WebContentsImpl::RunFileChooser(
    573     RenderViewHost* render_view_host,
    574     const FileChooserParams& params) {
    575   if (delegate_)
    576     delegate_->RunFileChooser(this, params);
    577 }
    578 
    579 NavigationControllerImpl& WebContentsImpl::GetController() {
    580   return controller_;
    581 }
    582 
    583 const NavigationControllerImpl& WebContentsImpl::GetController() const {
    584   return controller_;
    585 }
    586 
    587 BrowserContext* WebContentsImpl::GetBrowserContext() const {
    588   return controller_.GetBrowserContext();
    589 }
    590 
    591 const GURL& WebContentsImpl::GetURL() const {
    592   // We may not have a navigation entry yet.
    593   NavigationEntry* entry = controller_.GetVisibleEntry();
    594   return entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
    595 }
    596 
    597 const GURL& WebContentsImpl::GetVisibleURL() const {
    598   // We may not have a navigation entry yet.
    599   NavigationEntry* entry = controller_.GetVisibleEntry();
    600   return entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
    601 }
    602 
    603 const GURL& WebContentsImpl::GetLastCommittedURL() const {
    604   // We may not have a navigation entry yet.
    605   NavigationEntry* entry = controller_.GetLastCommittedEntry();
    606   return entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
    607 }
    608 
    609 WebContentsDelegate* WebContentsImpl::GetDelegate() {
    610   return delegate_;
    611 }
    612 
    613 void WebContentsImpl::SetDelegate(WebContentsDelegate* delegate) {
    614   // TODO(cbentzel): remove this debugging code?
    615   if (delegate == delegate_)
    616     return;
    617   if (delegate_)
    618     delegate_->Detach(this);
    619   delegate_ = delegate;
    620   if (delegate_) {
    621     delegate_->Attach(this);
    622     // Ensure the visible RVH reflects the new delegate's preferences.
    623     if (view_)
    624       view_->SetOverscrollControllerEnabled(delegate->CanOverscrollContent());
    625   }
    626 }
    627 
    628 RenderProcessHost* WebContentsImpl::GetRenderProcessHost() const {
    629   RenderViewHostImpl* host = GetRenderManager()->current_host();
    630   return host ? host->GetProcess() : NULL;
    631 }
    632 
    633 RenderFrameHost* WebContentsImpl::GetMainFrame() {
    634   return frame_tree_.root()->render_frame_host();
    635 }
    636 
    637 RenderViewHost* WebContentsImpl::GetRenderViewHost() const {
    638   return GetRenderManager()->current_host();
    639 }
    640 
    641 void WebContentsImpl::GetRenderViewHostAtPosition(
    642     int x,
    643     int y,
    644     const base::Callback<void(RenderViewHost*, int, int)>& callback) {
    645   BrowserPluginEmbedder* embedder = GetBrowserPluginEmbedder();
    646   if (embedder)
    647     embedder->GetRenderViewHostAtPosition(x, y, callback);
    648   else
    649     callback.Run(GetRenderViewHost(), x, y);
    650 }
    651 
    652 WebContents* WebContentsImpl::GetEmbedderWebContents() const {
    653   BrowserPluginGuest* guest = GetBrowserPluginGuest();
    654   if (guest)
    655     return guest->embedder_web_contents();
    656   return NULL;
    657 }
    658 
    659 int WebContentsImpl::GetEmbeddedInstanceID() const {
    660   BrowserPluginGuest* guest = GetBrowserPluginGuest();
    661   if (guest)
    662     return guest->instance_id();
    663   return 0;
    664 }
    665 
    666 int WebContentsImpl::GetRoutingID() const {
    667   if (!GetRenderViewHost())
    668     return MSG_ROUTING_NONE;
    669 
    670   return GetRenderViewHost()->GetRoutingID();
    671 }
    672 
    673 int WebContentsImpl::GetFullscreenWidgetRoutingID() const {
    674   return fullscreen_widget_routing_id_;
    675 }
    676 
    677 RenderWidgetHostView* WebContentsImpl::GetRenderWidgetHostView() const {
    678   return GetRenderManager()->GetRenderWidgetHostView();
    679 }
    680 
    681 RenderWidgetHostViewPort* WebContentsImpl::GetRenderWidgetHostViewPort() const {
    682   BrowserPluginGuest* guest = GetBrowserPluginGuest();
    683   if (guest && guest->embedder_web_contents()) {
    684     return guest->embedder_web_contents()->GetRenderWidgetHostViewPort();
    685   }
    686   return RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
    687 }
    688 
    689 RenderWidgetHostView* WebContentsImpl::GetFullscreenRenderWidgetHostView()
    690     const {
    691   RenderWidgetHost* const widget_host =
    692       RenderWidgetHostImpl::FromID(GetRenderProcessHost()->GetID(),
    693                                    GetFullscreenWidgetRoutingID());
    694   return widget_host ? widget_host->GetView() : NULL;
    695 }
    696 
    697 WebContentsView* WebContentsImpl::GetView() const {
    698   return view_.get();
    699 }
    700 
    701 WebUI* WebContentsImpl::CreateWebUI(const GURL& url) {
    702   WebUIImpl* web_ui = new WebUIImpl(this);
    703   WebUIController* controller = WebUIControllerFactoryRegistry::GetInstance()->
    704       CreateWebUIControllerForURL(web_ui, url);
    705   if (controller) {
    706     web_ui->AddMessageHandler(new GenericHandler());
    707     web_ui->SetController(controller);
    708     return web_ui;
    709   }
    710 
    711   delete web_ui;
    712   return NULL;
    713 }
    714 
    715 WebUI* WebContentsImpl::GetWebUI() const {
    716   return GetRenderManager()->web_ui() ? GetRenderManager()->web_ui()
    717       : GetRenderManager()->pending_web_ui();
    718 }
    719 
    720 WebUI* WebContentsImpl::GetCommittedWebUI() const {
    721   return GetRenderManager()->web_ui();
    722 }
    723 
    724 void WebContentsImpl::SetUserAgentOverride(const std::string& override) {
    725   if (GetUserAgentOverride() == override)
    726     return;
    727 
    728   renderer_preferences_.user_agent_override = override;
    729 
    730   // Send the new override string to the renderer.
    731   RenderViewHost* host = GetRenderViewHost();
    732   if (host)
    733     host->SyncRendererPrefs();
    734 
    735   // Reload the page if a load is currently in progress to avoid having
    736   // different parts of the page loaded using different user agents.
    737   NavigationEntry* entry = controller_.GetVisibleEntry();
    738   if (is_loading_ && entry != NULL && entry->GetIsOverridingUserAgent())
    739     controller_.ReloadIgnoringCache(true);
    740 
    741   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
    742                     UserAgentOverrideSet(override));
    743 }
    744 
    745 const std::string& WebContentsImpl::GetUserAgentOverride() const {
    746   return renderer_preferences_.user_agent_override;
    747 }
    748 
    749 #if defined(OS_WIN) && defined(USE_AURA)
    750 void WebContentsImpl::SetParentNativeViewAccessible(
    751 gfx::NativeViewAccessible accessible_parent) {
    752   accessible_parent_ = accessible_parent;
    753   if (GetRenderViewHost())
    754     GetRenderViewHostImpl()->SetParentNativeViewAccessible(accessible_parent);
    755 }
    756 #endif
    757 
    758 const base::string16& WebContentsImpl::GetTitle() const {
    759   // Transient entries take precedence. They are used for interstitial pages
    760   // that are shown on top of existing pages.
    761   NavigationEntry* entry = controller_.GetTransientEntry();
    762   std::string accept_languages =
    763       GetContentClient()->browser()->GetAcceptLangs(
    764           GetBrowserContext());
    765   if (entry) {
    766     return entry->GetTitleForDisplay(accept_languages);
    767   }
    768   WebUI* our_web_ui = GetRenderManager()->pending_web_ui() ?
    769       GetRenderManager()->pending_web_ui() : GetRenderManager()->web_ui();
    770   if (our_web_ui) {
    771     // Don't override the title in view source mode.
    772     entry = controller_.GetVisibleEntry();
    773     if (!(entry && entry->IsViewSourceMode())) {
    774       // Give the Web UI the chance to override our title.
    775       const base::string16& title = our_web_ui->GetOverriddenTitle();
    776       if (!title.empty())
    777         return title;
    778     }
    779   }
    780 
    781   // We use the title for the last committed entry rather than a pending
    782   // navigation entry. For example, when the user types in a URL, we want to
    783   // keep the old page's title until the new load has committed and we get a new
    784   // title.
    785   entry = controller_.GetLastCommittedEntry();
    786 
    787   // We make an exception for initial navigations.
    788   if (controller_.IsInitialNavigation()) {
    789     // We only want to use the title from the visible entry in one of two cases:
    790     // 1. There's already a committed entry for an initial navigation, in which
    791     //    case we are doing a history navigation in a new tab (e.g., Ctrl+Back).
    792     // 2. The pending entry has been explicitly assigned a title to display.
    793     //
    794     // If there's no last committed entry and no assigned title, we should fall
    795     // back to |page_title_when_no_navigation_entry_| rather than showing the
    796     // URL.
    797     if (entry ||
    798         (controller_.GetVisibleEntry() &&
    799          !controller_.GetVisibleEntry()->GetTitle().empty())) {
    800       entry = controller_.GetVisibleEntry();
    801     }
    802   }
    803 
    804   if (entry) {
    805     return entry->GetTitleForDisplay(accept_languages);
    806   }
    807 
    808   // |page_title_when_no_navigation_entry_| is finally used
    809   // if no title cannot be retrieved.
    810   return page_title_when_no_navigation_entry_;
    811 }
    812 
    813 int32 WebContentsImpl::GetMaxPageID() {
    814   return GetMaxPageIDForSiteInstance(GetSiteInstance());
    815 }
    816 
    817 int32 WebContentsImpl::GetMaxPageIDForSiteInstance(
    818     SiteInstance* site_instance) {
    819   if (max_page_ids_.find(site_instance->GetId()) == max_page_ids_.end())
    820     max_page_ids_[site_instance->GetId()] = -1;
    821 
    822   return max_page_ids_[site_instance->GetId()];
    823 }
    824 
    825 void WebContentsImpl::UpdateMaxPageID(int32 page_id) {
    826   UpdateMaxPageIDForSiteInstance(GetSiteInstance(), page_id);
    827 }
    828 
    829 void WebContentsImpl::UpdateMaxPageIDForSiteInstance(
    830     SiteInstance* site_instance, int32 page_id) {
    831   if (GetMaxPageIDForSiteInstance(site_instance) < page_id)
    832     max_page_ids_[site_instance->GetId()] = page_id;
    833 }
    834 
    835 void WebContentsImpl::CopyMaxPageIDsFrom(WebContents* web_contents) {
    836   WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents);
    837   max_page_ids_ = contents->max_page_ids_;
    838 }
    839 
    840 SiteInstance* WebContentsImpl::GetSiteInstance() const {
    841   return GetRenderManager()->current_host()->GetSiteInstance();
    842 }
    843 
    844 SiteInstance* WebContentsImpl::GetPendingSiteInstance() const {
    845   RenderViewHost* dest_rvh = GetRenderManager()->pending_render_view_host() ?
    846       GetRenderManager()->pending_render_view_host() :
    847       GetRenderManager()->current_host();
    848   return dest_rvh->GetSiteInstance();
    849 }
    850 
    851 bool WebContentsImpl::IsLoading() const {
    852   return is_loading_;
    853 }
    854 
    855 bool WebContentsImpl::IsWaitingForResponse() const {
    856   return waiting_for_response_;
    857 }
    858 
    859 const net::LoadStateWithParam& WebContentsImpl::GetLoadState() const {
    860   return load_state_;
    861 }
    862 
    863 const base::string16& WebContentsImpl::GetLoadStateHost() const {
    864   return load_state_host_;
    865 }
    866 
    867 uint64 WebContentsImpl::GetUploadSize() const {
    868   return upload_size_;
    869 }
    870 
    871 uint64 WebContentsImpl::GetUploadPosition() const {
    872   return upload_position_;
    873 }
    874 
    875 std::set<GURL> WebContentsImpl::GetSitesInTab() const {
    876   std::set<GURL> sites;
    877   frame_tree_.ForEach(Bind(&CollectSites,
    878                            base::Unretained(GetBrowserContext()),
    879                            base::Unretained(&sites)));
    880   return sites;
    881 }
    882 
    883 const std::string& WebContentsImpl::GetEncoding() const {
    884   return encoding_;
    885 }
    886 
    887 bool WebContentsImpl::DisplayedInsecureContent() const {
    888   return displayed_insecure_content_;
    889 }
    890 
    891 void WebContentsImpl::IncrementCapturerCount() {
    892   DCHECK(!is_being_destroyed_);
    893   ++capturer_count_;
    894   DVLOG(1) << "There are now " << capturer_count_
    895            << " capturing(s) of WebContentsImpl@" << this;
    896 }
    897 
    898 void WebContentsImpl::DecrementCapturerCount() {
    899   --capturer_count_;
    900   DVLOG(1) << "There are now " << capturer_count_
    901            << " capturing(s) of WebContentsImpl@" << this;
    902   DCHECK_LE(0, capturer_count_);
    903 
    904   if (is_being_destroyed_)
    905     return;
    906 
    907   if (IsHidden()) {
    908     DVLOG(1) << "Executing delayed WasHidden().";
    909     WasHidden();
    910   }
    911 }
    912 
    913 int WebContentsImpl::GetCapturerCount() const {
    914   return capturer_count_;
    915 }
    916 
    917 bool WebContentsImpl::IsCrashed() const {
    918   return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED ||
    919           crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION ||
    920           crashed_status_ == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
    921 }
    922 
    923 void WebContentsImpl::SetIsCrashed(base::TerminationStatus status,
    924                                    int error_code) {
    925   if (status == crashed_status_)
    926     return;
    927 
    928   crashed_status_ = status;
    929   crashed_error_code_ = error_code;
    930   NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
    931 }
    932 
    933 base::TerminationStatus WebContentsImpl::GetCrashedStatus() const {
    934   return crashed_status_;
    935 }
    936 
    937 bool WebContentsImpl::IsBeingDestroyed() const {
    938   return is_being_destroyed_;
    939 }
    940 
    941 void WebContentsImpl::NotifyNavigationStateChanged(unsigned changed_flags) {
    942   if (delegate_)
    943     delegate_->NavigationStateChanged(this, changed_flags);
    944 }
    945 
    946 base::TimeTicks WebContentsImpl::GetLastSelectedTime() const {
    947   return last_selected_time_;
    948 }
    949 
    950 void WebContentsImpl::WasShown() {
    951   controller_.SetActive(true);
    952   RenderWidgetHostViewPort* rwhv =
    953       RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
    954   if (rwhv) {
    955     rwhv->Show();
    956 #if defined(OS_MACOSX)
    957     rwhv->SetActive(true);
    958 #endif
    959   }
    960 
    961   last_selected_time_ = base::TimeTicks::Now();
    962 
    963   // The resize rect might have changed while this was inactive -- send the new
    964   // one to make sure it's up to date.
    965   RenderViewHostImpl* rvh =
    966       static_cast<RenderViewHostImpl*>(GetRenderViewHost());
    967   if (rvh) {
    968     rvh->ResizeRectChanged(GetRootWindowResizerRect());
    969   }
    970 
    971   FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasShown());
    972 
    973   should_normally_be_visible_ = true;
    974 }
    975 
    976 void WebContentsImpl::WasHidden() {
    977   // If there are entities capturing screenshots or video (e.g., mirroring),
    978   // don't activate the "disable rendering" optimization.
    979   if (capturer_count_ == 0) {
    980     // |GetRenderViewHost()| can be NULL if the user middle clicks a link to
    981     // open a tab in the background, then closes the tab before selecting it.
    982     // This is because closing the tab calls WebContentsImpl::Destroy(), which
    983     // removes the |GetRenderViewHost()|; then when we actually destroy the
    984     // window, OnWindowPosChanged() notices and calls WasHidden() (which
    985     // calls us).
    986     RenderWidgetHostViewPort* rwhv =
    987         RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
    988     if (rwhv)
    989       rwhv->Hide();
    990   }
    991 
    992   FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasHidden());
    993 
    994   should_normally_be_visible_ = false;
    995 }
    996 
    997 bool WebContentsImpl::NeedToFireBeforeUnload() {
    998   // TODO(creis): Should we fire even for interstitial pages?
    999   return WillNotifyDisconnection() &&
   1000       !ShowingInterstitialPage() &&
   1001       !static_cast<RenderViewHostImpl*>(
   1002           GetRenderViewHost())->SuddenTerminationAllowed();
   1003 }
   1004 
   1005 void WebContentsImpl::Stop() {
   1006   GetRenderManager()->Stop();
   1007   FOR_EACH_OBSERVER(WebContentsObserver, observers_, NavigationStopped());
   1008 }
   1009 
   1010 WebContents* WebContentsImpl::Clone() {
   1011   // We use our current SiteInstance since the cloned entry will use it anyway.
   1012   // We pass our own opener so that the cloned page can access it if it was
   1013   // before.
   1014   CreateParams create_params(GetBrowserContext(), GetSiteInstance());
   1015   create_params.initial_size = view_->GetContainerSize();
   1016   WebContentsImpl* tc = CreateWithOpener(create_params, opener_);
   1017   tc->GetController().CopyStateFrom(controller_);
   1018   FOR_EACH_OBSERVER(WebContentsObserver,
   1019                     observers_,
   1020                     DidCloneToNewWebContents(this, tc));
   1021   return tc;
   1022 }
   1023 
   1024 void WebContentsImpl::Observe(int type,
   1025                               const NotificationSource& source,
   1026                               const NotificationDetails& details) {
   1027   switch (type) {
   1028     case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED: {
   1029       RenderWidgetHost* host = Source<RenderWidgetHost>(source).ptr();
   1030       for (PendingWidgetViews::iterator i = pending_widget_views_.begin();
   1031            i != pending_widget_views_.end(); ++i) {
   1032         if (host->GetView() == i->second) {
   1033           pending_widget_views_.erase(i);
   1034           break;
   1035         }
   1036       }
   1037       break;
   1038     }
   1039     default:
   1040       NOTREACHED();
   1041   }
   1042 }
   1043 
   1044 WebContents* WebContentsImpl::GetWebContents() {
   1045   return this;
   1046 }
   1047 
   1048 void WebContentsImpl::Init(const WebContents::CreateParams& params) {
   1049   // This is set before initializing the render manager since
   1050   // RenderFrameHostManager::Init calls back into us via its delegate to ask if
   1051   // it should be hidden.
   1052   should_normally_be_visible_ = !params.initially_hidden;
   1053 
   1054   GetRenderManager()->Init(
   1055       params.browser_context, params.site_instance, params.routing_id,
   1056       params.main_frame_routing_id);
   1057 
   1058   view_.reset(GetContentClient()->browser()->
   1059       OverrideCreateWebContentsView(this, &render_view_host_delegate_view_));
   1060   if (view_) {
   1061     CHECK(render_view_host_delegate_view_);
   1062   } else {
   1063     WebContentsViewDelegate* delegate =
   1064         GetContentClient()->browser()->GetWebContentsViewDelegate(this);
   1065 
   1066     if (browser_plugin_guest_) {
   1067       scoped_ptr<WebContentsViewPort> platform_view(CreateWebContentsView(
   1068           this, delegate, &render_view_host_delegate_view_));
   1069 
   1070       WebContentsViewGuest* rv = new WebContentsViewGuest(
   1071           this, browser_plugin_guest_.get(), platform_view.Pass(),
   1072           render_view_host_delegate_view_);
   1073       render_view_host_delegate_view_ = rv;
   1074       view_.reset(rv);
   1075     } else {
   1076       // Regular WebContentsView.
   1077       view_.reset(CreateWebContentsView(
   1078           this, delegate, &render_view_host_delegate_view_));
   1079     }
   1080     CHECK(render_view_host_delegate_view_);
   1081   }
   1082   CHECK(view_.get());
   1083 
   1084   gfx::Size initial_size = params.initial_size;
   1085   view_->CreateView(initial_size, params.context);
   1086 
   1087   // Listen for whether our opener gets destroyed.
   1088   if (opener_)
   1089     AddDestructionObserver(opener_);
   1090 
   1091   registrar_.Add(this,
   1092                  NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
   1093                  NotificationService::AllBrowserContextsAndSources());
   1094 #if defined(OS_ANDROID)
   1095   java_bridge_dispatcher_host_manager_.reset(
   1096       new JavaBridgeDispatcherHostManager(this));
   1097   date_time_chooser_.reset(new DateTimeChooserAndroid());
   1098 #endif
   1099 }
   1100 
   1101 void WebContentsImpl::OnWebContentsDestroyed(WebContentsImpl* web_contents) {
   1102   RemoveDestructionObserver(web_contents);
   1103 
   1104   // Clear the opener if it has been closed.
   1105   if (web_contents == opener_) {
   1106     opener_ = NULL;
   1107     return;
   1108   }
   1109   // Clear a pending contents that has been closed before being shown.
   1110   for (PendingContents::iterator iter = pending_contents_.begin();
   1111        iter != pending_contents_.end();
   1112        ++iter) {
   1113     if (iter->second != web_contents)
   1114       continue;
   1115     pending_contents_.erase(iter);
   1116     return;
   1117   }
   1118   NOTREACHED();
   1119 }
   1120 
   1121 void WebContentsImpl::AddDestructionObserver(WebContentsImpl* web_contents) {
   1122   if (!ContainsKey(destruction_observers_, web_contents)) {
   1123     destruction_observers_[web_contents] =
   1124         new DestructionObserver(this, web_contents);
   1125   }
   1126 }
   1127 
   1128 void WebContentsImpl::RemoveDestructionObserver(WebContentsImpl* web_contents) {
   1129   DestructionObservers::iterator iter =
   1130       destruction_observers_.find(web_contents);
   1131   if (iter != destruction_observers_.end()) {
   1132     delete destruction_observers_[web_contents];
   1133     destruction_observers_.erase(iter);
   1134   }
   1135 }
   1136 
   1137 void WebContentsImpl::AddObserver(WebContentsObserver* observer) {
   1138   observers_.AddObserver(observer);
   1139 }
   1140 
   1141 void WebContentsImpl::RemoveObserver(WebContentsObserver* observer) {
   1142   observers_.RemoveObserver(observer);
   1143 }
   1144 
   1145 void WebContentsImpl::Activate() {
   1146   if (delegate_)
   1147     delegate_->ActivateContents(this);
   1148 }
   1149 
   1150 void WebContentsImpl::Deactivate() {
   1151   if (delegate_)
   1152     delegate_->DeactivateContents(this);
   1153 }
   1154 
   1155 void WebContentsImpl::LostCapture() {
   1156   if (delegate_)
   1157     delegate_->LostCapture();
   1158 }
   1159 
   1160 void WebContentsImpl::RenderWidgetDeleted(
   1161     RenderWidgetHostImpl* render_widget_host) {
   1162   if (is_being_destroyed_) {
   1163     // |created_widgets_| might have been destroyed.
   1164     return;
   1165   }
   1166 
   1167   std::set<RenderWidgetHostImpl*>::iterator iter =
   1168       created_widgets_.find(render_widget_host);
   1169   if (iter != created_widgets_.end())
   1170     created_widgets_.erase(iter);
   1171 
   1172   if (render_widget_host &&
   1173       render_widget_host->GetRoutingID() == fullscreen_widget_routing_id_) {
   1174     if (delegate_ && delegate_->EmbedsFullscreenWidget())
   1175       delegate_->ToggleFullscreenModeForTab(this, false);
   1176     FOR_EACH_OBSERVER(WebContentsObserver,
   1177                       observers_,
   1178                       DidDestroyFullscreenWidget(
   1179                           fullscreen_widget_routing_id_));
   1180     fullscreen_widget_routing_id_ = MSG_ROUTING_NONE;
   1181   }
   1182 }
   1183 
   1184 bool WebContentsImpl::PreHandleKeyboardEvent(
   1185     const NativeWebKeyboardEvent& event,
   1186     bool* is_keyboard_shortcut) {
   1187   return delegate_ &&
   1188       delegate_->PreHandleKeyboardEvent(this, event, is_keyboard_shortcut);
   1189 }
   1190 
   1191 void WebContentsImpl::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
   1192   if (browser_plugin_embedder_ &&
   1193       browser_plugin_embedder_->HandleKeyboardEvent(event)) {
   1194     return;
   1195   }
   1196 
   1197   if (delegate_)
   1198     delegate_->HandleKeyboardEvent(this, event);
   1199 }
   1200 
   1201 bool WebContentsImpl::PreHandleWheelEvent(
   1202     const blink::WebMouseWheelEvent& event) {
   1203 #if !defined(OS_MACOSX)
   1204   // On platforms other than Mac, control+mousewheel changes zoom. On Mac, this
   1205   // isn't done for two reasons:
   1206   //   -the OS already has a gesture to do this through pinch-zoom
   1207   //   -if a user starts an inertial scroll, let's go, and presses control
   1208   //      (i.e. control+tab) then the OS's buffered scroll events will come in
   1209   //      with control key set which isn't what the user wants
   1210   if (delegate_ &&
   1211       event.wheelTicksY &&
   1212       (event.modifiers & blink::WebInputEvent::ControlKey)) {
   1213     delegate_->ContentsZoomChange(event.wheelTicksY > 0);
   1214     return true;
   1215   }
   1216 #endif
   1217 
   1218   return false;
   1219 }
   1220 
   1221 #if defined(OS_WIN) && defined(USE_AURA)
   1222 gfx::NativeViewAccessible WebContentsImpl::GetParentNativeViewAccessible() {
   1223   return accessible_parent_;
   1224 }
   1225 #endif
   1226 
   1227 void WebContentsImpl::HandleMouseDown() {
   1228   if (delegate_)
   1229     delegate_->HandleMouseDown();
   1230 }
   1231 
   1232 void WebContentsImpl::HandleMouseUp() {
   1233   if (delegate_)
   1234     delegate_->HandleMouseUp();
   1235 }
   1236 
   1237 void WebContentsImpl::HandlePointerActivate() {
   1238   if (delegate_)
   1239     delegate_->HandlePointerActivate();
   1240 }
   1241 
   1242 void WebContentsImpl::HandleGestureBegin() {
   1243   if (delegate_)
   1244     delegate_->HandleGestureBegin();
   1245 }
   1246 
   1247 void WebContentsImpl::HandleGestureEnd() {
   1248   if (delegate_)
   1249     delegate_->HandleGestureEnd();
   1250 }
   1251 
   1252 void WebContentsImpl::ToggleFullscreenMode(bool enter_fullscreen) {
   1253   // This method is being called to enter or leave renderer-initiated fullscreen
   1254   // mode.  Either way, make sure any existing fullscreen widget is shut down
   1255   // first.
   1256   RenderWidgetHostView* const widget_view = GetFullscreenRenderWidgetHostView();
   1257   if (widget_view)
   1258     RenderWidgetHostImpl::From(widget_view->GetRenderWidgetHost())->Shutdown();
   1259 
   1260   if (delegate_)
   1261     delegate_->ToggleFullscreenModeForTab(this, enter_fullscreen);
   1262 }
   1263 
   1264 bool WebContentsImpl::IsFullscreenForCurrentTab() const {
   1265   return delegate_ ? delegate_->IsFullscreenForTabOrPending(this) : false;
   1266 }
   1267 
   1268 void WebContentsImpl::RequestToLockMouse(bool user_gesture,
   1269                                          bool last_unlocked_by_target) {
   1270   if (delegate_) {
   1271     delegate_->RequestToLockMouse(this, user_gesture, last_unlocked_by_target);
   1272   } else {
   1273     GotResponseToLockMouseRequest(false);
   1274   }
   1275 }
   1276 
   1277 void WebContentsImpl::LostMouseLock() {
   1278   if (delegate_)
   1279     delegate_->LostMouseLock();
   1280 }
   1281 
   1282 void WebContentsImpl::CreateNewWindow(
   1283     int render_process_id,
   1284     int route_id,
   1285     int main_frame_route_id,
   1286     const ViewHostMsg_CreateWindow_Params& params,
   1287     SessionStorageNamespace* session_storage_namespace) {
   1288   // We usually create the new window in the same BrowsingInstance (group of
   1289   // script-related windows), by passing in the current SiteInstance.  However,
   1290   // if the opener is being suppressed (in a non-guest), we create a new
   1291   // SiteInstance in its own BrowsingInstance.
   1292   bool is_guest = GetRenderProcessHost()->IsGuest();
   1293 
   1294   // If the opener is to be suppressed, the new window can be in any process.
   1295   // Since routing ids are process specific, we must not have one passed in
   1296   // as argument here.
   1297   DCHECK(!params.opener_suppressed || route_id == MSG_ROUTING_NONE);
   1298 
   1299   scoped_refptr<SiteInstance> site_instance =
   1300       params.opener_suppressed && !is_guest ?
   1301       SiteInstance::CreateForURL(GetBrowserContext(), params.target_url) :
   1302       GetSiteInstance();
   1303 
   1304   // A message to create a new window can only come from the active process for
   1305   // this WebContentsImpl instance. If any other process sends the request,
   1306   // it is invalid and the process must be terminated.
   1307   if (GetRenderProcessHost()->GetID() != render_process_id) {
   1308     base::ProcessHandle process_handle =
   1309         RenderProcessHost::FromID(render_process_id)->GetHandle();
   1310     if (process_handle != base::kNullProcessHandle) {
   1311       RecordAction(
   1312           UserMetricsAction("Terminate_ProcessMismatch_CreateNewWindow"));
   1313       base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false);
   1314     }
   1315     return;
   1316   }
   1317 
   1318   // We must assign the SessionStorageNamespace before calling Init().
   1319   //
   1320   // http://crbug.com/142685
   1321   const std::string& partition_id =
   1322       GetContentClient()->browser()->
   1323           GetStoragePartitionIdForSite(GetBrowserContext(),
   1324                                        site_instance->GetSiteURL());
   1325   StoragePartition* partition = BrowserContext::GetStoragePartition(
   1326       GetBrowserContext(), site_instance.get());
   1327   DOMStorageContextWrapper* dom_storage_context =
   1328       static_cast<DOMStorageContextWrapper*>(partition->GetDOMStorageContext());
   1329   SessionStorageNamespaceImpl* session_storage_namespace_impl =
   1330       static_cast<SessionStorageNamespaceImpl*>(session_storage_namespace);
   1331   CHECK(session_storage_namespace_impl->IsFromContext(dom_storage_context));
   1332 
   1333   if (delegate_ &&
   1334       !delegate_->ShouldCreateWebContents(this,
   1335                                           route_id,
   1336                                           params.window_container_type,
   1337                                           params.frame_name,
   1338                                           params.target_url,
   1339                                           partition_id,
   1340                                           session_storage_namespace)) {
   1341     GetRenderViewHost()->GetProcess()->ResumeRequestsForView(route_id);
   1342     GetRenderViewHost()->GetProcess()->ResumeRequestsForView(
   1343         main_frame_route_id);
   1344     return;
   1345   }
   1346 
   1347   // Create the new web contents. This will automatically create the new
   1348   // WebContentsView. In the future, we may want to create the view separately.
   1349   WebContentsImpl* new_contents =
   1350       new WebContentsImpl(GetBrowserContext(),
   1351                           params.opener_suppressed ? NULL : this);
   1352 
   1353   new_contents->GetController().SetSessionStorageNamespace(
   1354       partition_id,
   1355       session_storage_namespace);
   1356   CreateParams create_params(GetBrowserContext(), site_instance.get());
   1357   create_params.routing_id = route_id;
   1358   create_params.main_frame_routing_id = main_frame_route_id;
   1359   if (!is_guest) {
   1360     create_params.context = view_->GetNativeView();
   1361     create_params.initial_size = view_->GetContainerSize();
   1362   } else {
   1363     // This makes |new_contents| act as a guest.
   1364     // For more info, see comment above class BrowserPluginGuest.
   1365     int instance_id = GetBrowserPluginGuestManager()->get_next_instance_id();
   1366     WebContentsImpl* new_contents_impl =
   1367         static_cast<WebContentsImpl*>(new_contents);
   1368     BrowserPluginGuest::CreateWithOpener(instance_id,
   1369                                          new_contents_impl->opener() != NULL,
   1370                                          new_contents_impl,
   1371                                          GetBrowserPluginGuest());
   1372   }
   1373   if (params.disposition == NEW_BACKGROUND_TAB)
   1374     create_params.initially_hidden = true;
   1375   new_contents->Init(create_params);
   1376 
   1377   // Save the window for later if we're not suppressing the opener (since it
   1378   // will be shown immediately).
   1379   if (!params.opener_suppressed) {
   1380     if (!is_guest) {
   1381       WebContentsViewPort* new_view = new_contents->view_.get();
   1382 
   1383       // TODO(brettw): It seems bogus that we have to call this function on the
   1384       // newly created object and give it one of its own member variables.
   1385       new_view->CreateViewForWidget(new_contents->GetRenderViewHost());
   1386     }
   1387     // Save the created window associated with the route so we can show it
   1388     // later.
   1389     DCHECK_NE(MSG_ROUTING_NONE, route_id);
   1390     pending_contents_[route_id] = new_contents;
   1391     AddDestructionObserver(new_contents);
   1392   }
   1393 
   1394   if (delegate_) {
   1395     delegate_->WebContentsCreated(
   1396         this, params.opener_frame_id, params.frame_name,
   1397         params.target_url, new_contents);
   1398   }
   1399 
   1400   if (params.opener_suppressed) {
   1401     // When the opener is suppressed, the original renderer cannot access the
   1402     // new window.  As a result, we need to show and navigate the window here.
   1403     bool was_blocked = false;
   1404     if (delegate_) {
   1405       gfx::Rect initial_pos;
   1406       delegate_->AddNewContents(
   1407           this, new_contents, params.disposition, initial_pos,
   1408           params.user_gesture, &was_blocked);
   1409     }
   1410     if (!was_blocked) {
   1411       OpenURLParams open_params(params.target_url,
   1412                                 Referrer(),
   1413                                 CURRENT_TAB,
   1414                                 PAGE_TRANSITION_LINK,
   1415                                 true /* is_renderer_initiated */);
   1416       open_params.user_gesture = params.user_gesture;
   1417       new_contents->OpenURL(open_params);
   1418     }
   1419   }
   1420 }
   1421 
   1422 void WebContentsImpl::CreateNewWidget(int render_process_id,
   1423                                       int route_id,
   1424                                       blink::WebPopupType popup_type) {
   1425   CreateNewWidget(render_process_id, route_id, false, popup_type);
   1426 }
   1427 
   1428 void WebContentsImpl::CreateNewFullscreenWidget(int render_process_id,
   1429                                                 int route_id) {
   1430   CreateNewWidget(render_process_id, route_id, true, blink::WebPopupTypeNone);
   1431 }
   1432 
   1433 void WebContentsImpl::CreateNewWidget(int render_process_id,
   1434                                       int route_id,
   1435                                       bool is_fullscreen,
   1436                                       blink::WebPopupType popup_type) {
   1437   RenderProcessHost* process = GetRenderProcessHost();
   1438   // A message to create a new widget can only come from the active process for
   1439   // this WebContentsImpl instance. If any other process sends the request,
   1440   // it is invalid and the process must be terminated.
   1441   if (process->GetID() != render_process_id) {
   1442     base::ProcessHandle process_handle =
   1443         RenderProcessHost::FromID(render_process_id)->GetHandle();
   1444     if (process_handle != base::kNullProcessHandle) {
   1445       RecordAction(
   1446           UserMetricsAction("Terminate_ProcessMismatch_CreateNewWidget"));
   1447       base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false);
   1448     }
   1449     return;
   1450   }
   1451 
   1452   RenderWidgetHostImpl* widget_host =
   1453       new RenderWidgetHostImpl(this, process, route_id, IsHidden());
   1454   created_widgets_.insert(widget_host);
   1455 
   1456   RenderWidgetHostViewPort* widget_view = RenderWidgetHostViewPort::FromRWHV(
   1457       view_->CreateViewForPopupWidget(widget_host));
   1458   if (!widget_view)
   1459     return;
   1460   if (!is_fullscreen) {
   1461     // Popups should not get activated.
   1462     widget_view->SetPopupType(popup_type);
   1463   }
   1464   // Save the created widget associated with the route so we can show it later.
   1465   pending_widget_views_[route_id] = widget_view;
   1466 
   1467 #if defined(OS_MACOSX)
   1468   // A RenderWidgetHostViewMac has lifetime scoped to the view. We'll retain it
   1469   // to allow it to survive the trip without being hosted.
   1470   base::mac::NSObjectRetain(widget_view->GetNativeView());
   1471 #endif
   1472 }
   1473 
   1474 void WebContentsImpl::ShowCreatedWindow(int route_id,
   1475                                         WindowOpenDisposition disposition,
   1476                                         const gfx::Rect& initial_pos,
   1477                                         bool user_gesture) {
   1478   WebContentsImpl* contents = GetCreatedWindow(route_id);
   1479   if (contents) {
   1480     WebContentsDelegate* delegate = GetDelegate();
   1481     if (delegate) {
   1482       delegate->AddNewContents(
   1483           this, contents, disposition, initial_pos, user_gesture, NULL);
   1484     }
   1485   }
   1486 }
   1487 
   1488 void WebContentsImpl::ShowCreatedWidget(int route_id,
   1489                                         const gfx::Rect& initial_pos) {
   1490   ShowCreatedWidget(route_id, false, initial_pos);
   1491 }
   1492 
   1493 void WebContentsImpl::ShowCreatedFullscreenWidget(int route_id) {
   1494   ShowCreatedWidget(route_id, true, gfx::Rect());
   1495 }
   1496 
   1497 void WebContentsImpl::ShowCreatedWidget(int route_id,
   1498                                         bool is_fullscreen,
   1499                                         const gfx::Rect& initial_pos) {
   1500   if (delegate_)
   1501     delegate_->RenderWidgetShowing();
   1502 
   1503   RenderWidgetHostViewPort* widget_host_view =
   1504       RenderWidgetHostViewPort::FromRWHV(GetCreatedWidget(route_id));
   1505   if (!widget_host_view)
   1506     return;
   1507   if (is_fullscreen) {
   1508     DCHECK_EQ(MSG_ROUTING_NONE, fullscreen_widget_routing_id_);
   1509     fullscreen_widget_routing_id_ = route_id;
   1510     if (delegate_ && delegate_->EmbedsFullscreenWidget()) {
   1511       widget_host_view->InitAsChild(GetRenderWidgetHostView()->GetNativeView());
   1512       delegate_->ToggleFullscreenModeForTab(this, true);
   1513     } else {
   1514       widget_host_view->InitAsFullscreen(GetRenderWidgetHostViewPort());
   1515     }
   1516     FOR_EACH_OBSERVER(WebContentsObserver,
   1517                       observers_,
   1518                       DidShowFullscreenWidget(route_id));
   1519     if (!widget_host_view->HasFocus())
   1520       widget_host_view->Focus();
   1521   } else {
   1522     widget_host_view->InitAsPopup(GetRenderWidgetHostViewPort(), initial_pos);
   1523   }
   1524 
   1525   RenderWidgetHostImpl* render_widget_host_impl =
   1526       RenderWidgetHostImpl::From(widget_host_view->GetRenderWidgetHost());
   1527   render_widget_host_impl->Init();
   1528   // Only allow privileged mouse lock for fullscreen render widget, which is
   1529   // used to implement Pepper Flash fullscreen.
   1530   render_widget_host_impl->set_allow_privileged_mouse_lock(is_fullscreen);
   1531 
   1532 #if defined(OS_MACOSX)
   1533   // A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's
   1534   // properly embedded (or purposefully ignored) we can release the retain we
   1535   // took in CreateNewWidget().
   1536   base::mac::NSObjectRelease(widget_host_view->GetNativeView());
   1537 #endif
   1538 }
   1539 
   1540 WebContentsImpl* WebContentsImpl::GetCreatedWindow(int route_id) {
   1541   PendingContents::iterator iter = pending_contents_.find(route_id);
   1542 
   1543   // Certain systems can block the creation of new windows. If we didn't succeed
   1544   // in creating one, just return NULL.
   1545   if (iter == pending_contents_.end()) {
   1546     return NULL;
   1547   }
   1548 
   1549   WebContentsImpl* new_contents = iter->second;
   1550   pending_contents_.erase(route_id);
   1551   RemoveDestructionObserver(new_contents);
   1552 
   1553   // Don't initialize the guest WebContents immediately.
   1554   if (new_contents->GetRenderProcessHost()->IsGuest())
   1555     return new_contents;
   1556 
   1557   if (!new_contents->GetRenderProcessHost()->HasConnection() ||
   1558       !new_contents->GetRenderViewHost()->GetView())
   1559     return NULL;
   1560 
   1561   // TODO(brettw): It seems bogus to reach into here and initialize the host.
   1562   static_cast<RenderViewHostImpl*>(new_contents->GetRenderViewHost())->Init();
   1563   return new_contents;
   1564 }
   1565 
   1566 RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int route_id) {
   1567   PendingWidgetViews::iterator iter = pending_widget_views_.find(route_id);
   1568   if (iter == pending_widget_views_.end()) {
   1569     DCHECK(false);
   1570     return NULL;
   1571   }
   1572 
   1573   RenderWidgetHostView* widget_host_view = iter->second;
   1574   pending_widget_views_.erase(route_id);
   1575 
   1576   RenderWidgetHost* widget_host = widget_host_view->GetRenderWidgetHost();
   1577   if (!widget_host->GetProcess()->HasConnection()) {
   1578     // The view has gone away or the renderer crashed. Nothing to do.
   1579     return NULL;
   1580   }
   1581 
   1582   return widget_host_view;
   1583 }
   1584 
   1585 void WebContentsImpl::ShowContextMenu(const ContextMenuParams& params) {
   1586   // Allow WebContentsDelegates to handle the context menu operation first.
   1587   if (delegate_ && delegate_->HandleContextMenu(params))
   1588     return;
   1589 
   1590   render_view_host_delegate_view_->ShowContextMenu(params);
   1591 }
   1592 
   1593 void WebContentsImpl::RequestMediaAccessPermission(
   1594     const MediaStreamRequest& request,
   1595     const MediaResponseCallback& callback) {
   1596   if (delegate_)
   1597     delegate_->RequestMediaAccessPermission(this, request, callback);
   1598   else
   1599     callback.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
   1600 }
   1601 
   1602 SessionStorageNamespace* WebContentsImpl::GetSessionStorageNamespace(
   1603     SiteInstance* instance) {
   1604   return controller_.GetSessionStorageNamespace(instance);
   1605 }
   1606 
   1607 FrameTree* WebContentsImpl::GetFrameTree() {
   1608   return &frame_tree_;
   1609 }
   1610 
   1611 void WebContentsImpl::OnShowValidationMessage(
   1612     const gfx::Rect& anchor_in_root_view,
   1613     const string16& main_text,
   1614     const string16& sub_text) {
   1615   if (delegate_)
   1616     delegate_->ShowValidationMessage(
   1617         this, anchor_in_root_view, main_text, sub_text);
   1618 }
   1619 
   1620 void WebContentsImpl::OnHideValidationMessage() {
   1621   if (delegate_)
   1622     delegate_->HideValidationMessage(this);
   1623 }
   1624 
   1625 void WebContentsImpl::OnMoveValidationMessage(
   1626     const gfx::Rect& anchor_in_root_view) {
   1627   if (delegate_)
   1628     delegate_->MoveValidationMessage(this, anchor_in_root_view);
   1629 }
   1630 
   1631 void WebContentsImpl::DidSendScreenRects(RenderWidgetHostImpl* rwh) {
   1632   if (browser_plugin_embedder_)
   1633     browser_plugin_embedder_->DidSendScreenRects();
   1634 }
   1635 
   1636 void WebContentsImpl::UpdatePreferredSize(const gfx::Size& pref_size) {
   1637   preferred_size_ = pref_size;
   1638   if (delegate_)
   1639     delegate_->UpdatePreferredSize(this, pref_size);
   1640 }
   1641 
   1642 void WebContentsImpl::ResizeDueToAutoResize(const gfx::Size& new_size) {
   1643   if (delegate_)
   1644     delegate_->ResizeDueToAutoResize(this, new_size);
   1645 }
   1646 
   1647 WebContents* WebContentsImpl::OpenURL(const OpenURLParams& params) {
   1648   if (!delegate_)
   1649     return NULL;
   1650 
   1651   WebContents* new_contents = delegate_->OpenURLFromTab(this, params);
   1652   return new_contents;
   1653 }
   1654 
   1655 bool WebContentsImpl::Send(IPC::Message* message) {
   1656   if (!GetRenderViewHost()) {
   1657     delete message;
   1658     return false;
   1659   }
   1660 
   1661   return GetRenderViewHost()->Send(message);
   1662 }
   1663 
   1664 bool WebContentsImpl::NavigateToPendingEntry(
   1665     NavigationController::ReloadType reload_type) {
   1666   return NavigateToEntry(
   1667       *NavigationEntryImpl::FromNavigationEntry(controller_.GetPendingEntry()),
   1668       reload_type);
   1669 }
   1670 
   1671 void WebContentsImpl::RenderViewForInterstitialPageCreated(
   1672     RenderViewHost* render_view_host) {
   1673   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   1674                     RenderViewForInterstitialPageCreated(render_view_host));
   1675 }
   1676 
   1677 void WebContentsImpl::AttachInterstitialPage(
   1678     InterstitialPageImpl* interstitial_page) {
   1679   DCHECK(interstitial_page);
   1680   GetRenderManager()->set_interstitial_page(interstitial_page);
   1681 
   1682   // Cancel any visible dialogs so that they don't interfere with the
   1683   // interstitial.
   1684   if (dialog_manager_)
   1685     dialog_manager_->CancelActiveAndPendingDialogs(this);
   1686 
   1687   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   1688                     DidAttachInterstitialPage());
   1689 }
   1690 
   1691 void WebContentsImpl::DetachInterstitialPage() {
   1692   if (GetInterstitialPage())
   1693     GetRenderManager()->remove_interstitial_page();
   1694   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   1695                     DidDetachInterstitialPage());
   1696 }
   1697 
   1698 bool WebContentsImpl::NavigateToEntry(
   1699     const NavigationEntryImpl& entry,
   1700     NavigationController::ReloadType reload_type) {
   1701   TRACE_EVENT0("browser", "WebContentsImpl::NavigateToEntry");
   1702 
   1703   // The renderer will reject IPC messages with URLs longer than
   1704   // this limit, so don't attempt to navigate with a longer URL.
   1705   if (entry.GetURL().spec().size() > GetMaxURLChars()) {
   1706     LOG(WARNING) << "Refusing to load URL as it exceeds " << GetMaxURLChars()
   1707                  << " characters.";
   1708     return false;
   1709   }
   1710 
   1711   // TODO(creis): Use entry->frame_tree_node_id() to pick which
   1712   // RenderFrameHostManager to use.
   1713   RenderViewHostImpl* dest_render_view_host =
   1714       static_cast<RenderViewHostImpl*>(GetRenderManager()->Navigate(entry));
   1715   if (!dest_render_view_host)
   1716     return false;  // Unable to create the desired render view host.
   1717 
   1718   // For security, we should never send non-Web-UI URLs to a Web UI renderer.
   1719   // Double check that here.
   1720   int enabled_bindings = dest_render_view_host->GetEnabledBindings();
   1721   bool data_urls_allowed = delegate_ && delegate_->CanLoadDataURLsInWebUI();
   1722   bool is_allowed_in_web_ui_renderer =
   1723       WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
   1724           GetBrowserContext(), entry.GetURL(), data_urls_allowed);
   1725   if ((enabled_bindings & BINDINGS_POLICY_WEB_UI) &&
   1726       !is_allowed_in_web_ui_renderer) {
   1727     // Log the URL to help us diagnose any future failures of this CHECK.
   1728     GetContentClient()->SetActiveURL(entry.GetURL());
   1729     CHECK(0);
   1730   }
   1731 
   1732   // Notify observers that we will navigate in this RV.
   1733   FOR_EACH_OBSERVER(WebContentsObserver,
   1734                     observers_,
   1735                     AboutToNavigateRenderView(dest_render_view_host));
   1736 
   1737   // Used for page load time metrics.
   1738   current_load_start_ = base::TimeTicks::Now();
   1739 
   1740   // Navigate in the desired RenderViewHost.
   1741   ViewMsg_Navigate_Params navigate_params;
   1742   MakeNavigateParams(entry, controller_, delegate_, reload_type,
   1743                      &navigate_params);
   1744   dest_render_view_host->Navigate(navigate_params);
   1745 
   1746   if (entry.GetPageID() == -1) {
   1747     // HACK!!  This code suppresses javascript: URLs from being added to
   1748     // session history, which is what we want to do for javascript: URLs that
   1749     // do not generate content.  What we really need is a message from the
   1750     // renderer telling us that a new page was not created.  The same message
   1751     // could be used for mailto: URLs and the like.
   1752     if (entry.GetURL().SchemeIs(kJavaScriptScheme))
   1753       return false;
   1754   }
   1755 
   1756   // Notify observers about navigation.
   1757   FOR_EACH_OBSERVER(
   1758       WebContentsObserver,
   1759       observers_,
   1760       DidStartNavigationToPendingEntry(entry.GetURL(), reload_type));
   1761 
   1762   if (delegate_)
   1763     delegate_->DidNavigateToPendingEntry(this);
   1764 
   1765   return true;
   1766 }
   1767 
   1768 void WebContentsImpl::SetHistoryLengthAndPrune(
   1769     const SiteInstance* site_instance,
   1770     int history_length,
   1771     int32 minimum_page_id) {
   1772   // SetHistoryLengthAndPrune doesn't work when there are pending cross-site
   1773   // navigations. Callers should ensure that this is the case.
   1774   if (GetRenderManager()->pending_render_view_host()) {
   1775     NOTREACHED();
   1776     return;
   1777   }
   1778   RenderViewHostImpl* rvh = GetRenderViewHostImpl();
   1779   if (!rvh) {
   1780     NOTREACHED();
   1781     return;
   1782   }
   1783   if (site_instance && rvh->GetSiteInstance() != site_instance) {
   1784     NOTREACHED();
   1785     return;
   1786   }
   1787   Send(new ViewMsg_SetHistoryLengthAndPrune(GetRoutingID(),
   1788                                             history_length,
   1789                                             minimum_page_id));
   1790 }
   1791 
   1792 void WebContentsImpl::FocusThroughTabTraversal(bool reverse) {
   1793   if (ShowingInterstitialPage()) {
   1794     GetRenderManager()->interstitial_page()->FocusThroughTabTraversal(reverse);
   1795     return;
   1796   }
   1797   GetRenderViewHostImpl()->SetInitialFocus(reverse);
   1798 }
   1799 
   1800 bool WebContentsImpl::ShowingInterstitialPage() const {
   1801   return GetRenderManager()->interstitial_page() != NULL;
   1802 }
   1803 
   1804 InterstitialPage* WebContentsImpl::GetInterstitialPage() const {
   1805   return GetRenderManager()->interstitial_page();
   1806 }
   1807 
   1808 bool WebContentsImpl::IsSavable() {
   1809   // WebKit creates Document object when MIME type is application/xhtml+xml,
   1810   // so we also support this MIME type.
   1811   return contents_mime_type_ == "text/html" ||
   1812          contents_mime_type_ == "text/xml" ||
   1813          contents_mime_type_ == "application/xhtml+xml" ||
   1814          contents_mime_type_ == "text/plain" ||
   1815          contents_mime_type_ == "text/css" ||
   1816          net::IsSupportedJavascriptMimeType(contents_mime_type_.c_str());
   1817 }
   1818 
   1819 void WebContentsImpl::OnSavePage() {
   1820   // If we can not save the page, try to download it.
   1821   if (!IsSavable()) {
   1822     RecordDownloadSource(INITIATED_BY_SAVE_PACKAGE_ON_NON_HTML);
   1823     SaveFrame(GetURL(), Referrer());
   1824     return;
   1825   }
   1826 
   1827   Stop();
   1828 
   1829   // Create the save package and possibly prompt the user for the name to save
   1830   // the page as. The user prompt is an asynchronous operation that runs on
   1831   // another thread.
   1832   save_package_ = new SavePackage(this);
   1833   save_package_->GetSaveInfo();
   1834 }
   1835 
   1836 // Used in automated testing to bypass prompting the user for file names.
   1837 // Instead, the names and paths are hard coded rather than running them through
   1838 // file name sanitation and extension / mime checking.
   1839 bool WebContentsImpl::SavePage(const base::FilePath& main_file,
   1840                                const base::FilePath& dir_path,
   1841                                SavePageType save_type) {
   1842   // Stop the page from navigating.
   1843   Stop();
   1844 
   1845   save_package_ = new SavePackage(this, save_type, main_file, dir_path);
   1846   return save_package_->Init(SavePackageDownloadCreatedCallback());
   1847 }
   1848 
   1849 void WebContentsImpl::SaveFrame(const GURL& url,
   1850                                 const Referrer& referrer) {
   1851   if (!GetURL().is_valid())
   1852     return;
   1853   bool is_main_frame = (url == GetURL());
   1854 
   1855   DownloadManager* dlm =
   1856       BrowserContext::GetDownloadManager(GetBrowserContext());
   1857   if (!dlm)
   1858     return;
   1859   int64 post_id = -1;
   1860   if (is_main_frame) {
   1861     const NavigationEntry* entry = controller_.GetLastCommittedEntry();
   1862     if (entry)
   1863       post_id = entry->GetPostID();
   1864   }
   1865   scoped_ptr<DownloadUrlParameters> params(
   1866       DownloadUrlParameters::FromWebContents(this, url));
   1867   params->set_referrer(referrer);
   1868   params->set_post_id(post_id);
   1869   params->set_prefer_cache(true);
   1870   if (post_id >= 0)
   1871     params->set_method("POST");
   1872   params->set_prompt(true);
   1873   dlm->DownloadUrl(params.Pass());
   1874 }
   1875 
   1876 void WebContentsImpl::GenerateMHTML(
   1877     const base::FilePath& file,
   1878     const base::Callback<void(int64)>& callback) {
   1879   MHTMLGenerationManager::GetInstance()->SaveMHTML(this, file, callback);
   1880 }
   1881 
   1882 // TODO(nasko): Rename this method to IsVisibleEntry.
   1883 bool WebContentsImpl::IsActiveEntry(int32 page_id) {
   1884   NavigationEntryImpl* visible_entry =
   1885       NavigationEntryImpl::FromNavigationEntry(controller_.GetVisibleEntry());
   1886   return (visible_entry != NULL &&
   1887           visible_entry->site_instance() == GetSiteInstance() &&
   1888           visible_entry->GetPageID() == page_id);
   1889 }
   1890 
   1891 const std::string& WebContentsImpl::GetContentsMimeType() const {
   1892   return contents_mime_type_;
   1893 }
   1894 
   1895 bool WebContentsImpl::WillNotifyDisconnection() const {
   1896   return notify_disconnection_;
   1897 }
   1898 
   1899 void WebContentsImpl::SetOverrideEncoding(const std::string& encoding) {
   1900   SetEncoding(encoding);
   1901   Send(new ViewMsg_SetPageEncoding(GetRoutingID(), encoding));
   1902 }
   1903 
   1904 void WebContentsImpl::ResetOverrideEncoding() {
   1905   encoding_.clear();
   1906   Send(new ViewMsg_ResetPageEncodingToDefault(GetRoutingID()));
   1907 }
   1908 
   1909 RendererPreferences* WebContentsImpl::GetMutableRendererPrefs() {
   1910   return &renderer_preferences_;
   1911 }
   1912 
   1913 void WebContentsImpl::Close() {
   1914   Close(GetRenderViewHost());
   1915 }
   1916 
   1917 void WebContentsImpl::DragSourceEndedAt(int client_x, int client_y,
   1918     int screen_x, int screen_y, blink::WebDragOperation operation) {
   1919   if (browser_plugin_embedder_.get())
   1920     browser_plugin_embedder_->DragSourceEndedAt(client_x, client_y,
   1921         screen_x, screen_y, operation);
   1922   if (GetRenderViewHost())
   1923     GetRenderViewHostImpl()->DragSourceEndedAt(client_x, client_y,
   1924         screen_x, screen_y, operation);
   1925 }
   1926 
   1927 void WebContentsImpl::DragSourceMovedTo(int client_x, int client_y,
   1928                                         int screen_x, int screen_y) {
   1929   if (browser_plugin_embedder_.get())
   1930     browser_plugin_embedder_->DragSourceMovedTo(client_x, client_y,
   1931                                                 screen_x, screen_y);
   1932   if (GetRenderViewHost())
   1933     GetRenderViewHostImpl()->DragSourceMovedTo(client_x, client_y,
   1934                                                screen_x, screen_y);
   1935 }
   1936 
   1937 void WebContentsImpl::SystemDragEnded() {
   1938   if (GetRenderViewHost())
   1939     GetRenderViewHostImpl()->DragSourceSystemDragEnded();
   1940   if (delegate_)
   1941     delegate_->DragEnded();
   1942   if (browser_plugin_embedder_.get())
   1943     browser_plugin_embedder_->SystemDragEnded();
   1944 }
   1945 
   1946 void WebContentsImpl::UserGestureDone() {
   1947   OnUserGesture();
   1948 }
   1949 
   1950 void WebContentsImpl::SetClosedByUserGesture(bool value) {
   1951   closed_by_user_gesture_ = value;
   1952 }
   1953 
   1954 bool WebContentsImpl::GetClosedByUserGesture() const {
   1955   return closed_by_user_gesture_;
   1956 }
   1957 
   1958 double WebContentsImpl::GetZoomLevel() const {
   1959   HostZoomMapImpl* zoom_map = static_cast<HostZoomMapImpl*>(
   1960       HostZoomMap::GetForBrowserContext(GetBrowserContext()));
   1961   if (!zoom_map)
   1962     return 0;
   1963 
   1964   double zoom_level;
   1965   if (temporary_zoom_settings_) {
   1966     zoom_level = zoom_map->GetTemporaryZoomLevel(
   1967         GetRenderProcessHost()->GetID(), GetRenderViewHost()->GetRoutingID());
   1968   } else {
   1969     GURL url;
   1970     NavigationEntry* entry = GetController().GetLastCommittedEntry();
   1971     // Since zoom map is updated using rewritten URL, use rewritten URL
   1972     // to get the zoom level.
   1973     url = entry ? entry->GetURL() : GURL::EmptyGURL();
   1974     zoom_level = zoom_map->GetZoomLevelForHostAndScheme(url.scheme(),
   1975         net::GetHostOrSpecFromURL(url));
   1976   }
   1977   return zoom_level;
   1978 }
   1979 
   1980 int WebContentsImpl::GetZoomPercent(bool* enable_increment,
   1981                                     bool* enable_decrement) const {
   1982   *enable_decrement = *enable_increment = false;
   1983   // Calculate the zoom percent from the factor. Round up to the nearest whole
   1984   // number.
   1985   int percent = static_cast<int>(
   1986       ZoomLevelToZoomFactor(GetZoomLevel()) * 100 + 0.5);
   1987   *enable_decrement = percent > minimum_zoom_percent_;
   1988   *enable_increment = percent < maximum_zoom_percent_;
   1989   return percent;
   1990 }
   1991 
   1992 void WebContentsImpl::ViewSource() {
   1993   if (!delegate_)
   1994     return;
   1995 
   1996   NavigationEntry* entry = GetController().GetLastCommittedEntry();
   1997   if (!entry)
   1998     return;
   1999 
   2000   delegate_->ViewSourceForTab(this, entry->GetURL());
   2001 }
   2002 
   2003 void WebContentsImpl::ViewFrameSource(const GURL& url,
   2004                                       const PageState& page_state) {
   2005   if (!delegate_)
   2006     return;
   2007 
   2008   delegate_->ViewSourceForFrame(this, url, page_state);
   2009 }
   2010 
   2011 int WebContentsImpl::GetMinimumZoomPercent() const {
   2012   return minimum_zoom_percent_;
   2013 }
   2014 
   2015 int WebContentsImpl::GetMaximumZoomPercent() const {
   2016   return maximum_zoom_percent_;
   2017 }
   2018 
   2019 gfx::Size WebContentsImpl::GetPreferredSize() const {
   2020   return preferred_size_;
   2021 }
   2022 
   2023 bool WebContentsImpl::GotResponseToLockMouseRequest(bool allowed) {
   2024   return GetRenderViewHost() ?
   2025       GetRenderViewHostImpl()->GotResponseToLockMouseRequest(allowed) : false;
   2026 }
   2027 
   2028 bool WebContentsImpl::HasOpener() const {
   2029   return opener_ != NULL;
   2030 }
   2031 
   2032 void WebContentsImpl::DidChooseColorInColorChooser(SkColor color) {
   2033   Send(new ViewMsg_DidChooseColorResponse(
   2034       GetRoutingID(), color_chooser_identifier_, color));
   2035 }
   2036 
   2037 void WebContentsImpl::DidEndColorChooser() {
   2038   Send(new ViewMsg_DidEndColorChooser(GetRoutingID(),
   2039                                       color_chooser_identifier_));
   2040   color_chooser_.reset();
   2041   color_chooser_identifier_ = 0;
   2042 }
   2043 
   2044 int WebContentsImpl::DownloadImage(const GURL& url,
   2045                                    bool is_favicon,
   2046                                    uint32_t max_bitmap_size,
   2047                                    const ImageDownloadCallback& callback) {
   2048   RenderViewHost* host = GetRenderViewHost();
   2049   int id = StartDownload(host, url, is_favicon, max_bitmap_size);
   2050   image_download_map_[id] = callback;
   2051   return id;
   2052 }
   2053 
   2054 void WebContentsImpl::SetZoomLevel(double level) {
   2055   Send(new ViewMsg_SetZoomLevel(GetRoutingID(), level));
   2056   BrowserPluginEmbedder* embedder = GetBrowserPluginEmbedder();
   2057   if (embedder)
   2058     embedder->SetZoomLevel(level);
   2059 }
   2060 
   2061 bool WebContentsImpl::FocusLocationBarByDefault() {
   2062   NavigationEntry* entry = controller_.GetVisibleEntry();
   2063   if (entry && entry->GetURL() == GURL(kAboutBlankURL))
   2064     return true;
   2065   return delegate_ && delegate_->ShouldFocusLocationBarByDefault(this);
   2066 }
   2067 
   2068 void WebContentsImpl::SetFocusToLocationBar(bool select_all) {
   2069   if (delegate_)
   2070     delegate_->SetFocusToLocationBar(select_all);
   2071 }
   2072 
   2073 void WebContentsImpl::DidStartProvisionalLoad(
   2074     RenderFrameHostImpl* render_frame_host,
   2075     int64 frame_id,
   2076     int64 parent_frame_id,
   2077     bool is_main_frame,
   2078     const GURL& validated_url,
   2079     bool is_error_page,
   2080     bool is_iframe_srcdoc) {
   2081   if (is_main_frame)
   2082     DidChangeLoadProgress(0);
   2083 
   2084   // Notify observers about the start of the provisional load.
   2085   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2086                     DidStartProvisionalLoadForFrame(frame_id, parent_frame_id,
   2087                     is_main_frame, validated_url, is_error_page,
   2088                     is_iframe_srcdoc, render_frame_host->render_view_host()));
   2089 
   2090   if (is_main_frame) {
   2091     FOR_EACH_OBSERVER(
   2092         WebContentsObserver,
   2093         observers_,
   2094         ProvisionalChangeToMainFrameUrl(validated_url,
   2095                                         render_frame_host->render_view_host()));
   2096   }
   2097 }
   2098 
   2099 void WebContentsImpl::NotifyChangedNavigationState(
   2100     InvalidateTypes changed_flags) {
   2101   NotifyNavigationStateChanged(changed_flags);
   2102 }
   2103 
   2104 void WebContentsImpl::DidRedirectProvisionalLoad(
   2105     RenderViewHost* render_view_host,
   2106     int32 page_id,
   2107     const GURL& source_url,
   2108     const GURL& target_url) {
   2109   // TODO(creis): Remove this method and have the pre-rendering code listen to
   2110   // WebContentsObserver::DidGetRedirectForResourceRequest instead.
   2111   // See http://crbug.com/78512.
   2112   GURL validated_source_url(source_url);
   2113   GURL validated_target_url(target_url);
   2114   RenderProcessHost* render_process_host =
   2115       render_view_host->GetProcess();
   2116   RenderViewHost::FilterURL(render_process_host, false, &validated_source_url);
   2117   RenderViewHost::FilterURL(render_process_host, false, &validated_target_url);
   2118   NavigationEntry* entry;
   2119   if (page_id == -1) {
   2120     entry = controller_.GetPendingEntry();
   2121   } else {
   2122     entry = controller_.GetEntryWithPageID(render_view_host->GetSiteInstance(),
   2123                                            page_id);
   2124   }
   2125   if (!entry || entry->GetURL() != validated_source_url)
   2126     return;
   2127 
   2128   // Notify observers about the provisional change in the main frame URL.
   2129   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2130                     ProvisionalChangeToMainFrameUrl(validated_target_url,
   2131                                                     render_view_host));
   2132 }
   2133 
   2134 void WebContentsImpl::DidFailProvisionalLoadWithError(
   2135     RenderViewHost* render_view_host,
   2136     const ViewHostMsg_DidFailProvisionalLoadWithError_Params& params) {
   2137   VLOG(1) << "Failed Provisional Load: " << params.url.possibly_invalid_spec()
   2138           << ", error_code: " << params.error_code
   2139           << ", error_description: " << params.error_description
   2140           << ", is_main_frame: " << params.is_main_frame
   2141           << ", showing_repost_interstitial: " <<
   2142             params.showing_repost_interstitial
   2143           << ", frame_id: " << params.frame_id;
   2144   GURL validated_url(params.url);
   2145   RenderProcessHost* render_process_host =
   2146       render_view_host->GetProcess();
   2147   RenderViewHost::FilterURL(render_process_host, false, &validated_url);
   2148 
   2149   if (net::ERR_ABORTED == params.error_code) {
   2150     // EVIL HACK ALERT! Ignore failed loads when we're showing interstitials.
   2151     // This means that the interstitial won't be torn down properly, which is
   2152     // bad. But if we have an interstitial, go back to another tab type, and
   2153     // then load the same interstitial again, we could end up getting the first
   2154     // interstitial's "failed" message (as a result of the cancel) when we're on
   2155     // the second one.
   2156     //
   2157     // We can't tell this apart, so we think we're tearing down the current page
   2158     // which will cause a crash later one. There is also some code in
   2159     // RenderFrameHostManager::RendererAbortedProvisionalLoad that is commented
   2160     // out because of this problem.
   2161     //
   2162     // http://code.google.com/p/chromium/issues/detail?id=2855
   2163     // Because this will not tear down the interstitial properly, if "back" is
   2164     // back to another tab type, the interstitial will still be somewhat alive
   2165     // in the previous tab type. If you navigate somewhere that activates the
   2166     // tab with the interstitial again, you'll see a flash before the new load
   2167     // commits of the interstitial page.
   2168     if (ShowingInterstitialPage()) {
   2169       LOG(WARNING) << "Discarding message during interstitial.";
   2170       return;
   2171     }
   2172 
   2173     GetRenderManager()->RendererAbortedProvisionalLoad(render_view_host);
   2174   }
   2175 
   2176   // Do not usually clear the pending entry if one exists, so that the user's
   2177   // typed URL is not lost when a navigation fails or is aborted.  However, in
   2178   // cases that we don't show the pending entry (e.g., renderer-initiated
   2179   // navigations in an existing tab), we don't keep it around.  That prevents
   2180   // spoofs on in-page navigations that don't go through
   2181   // DidStartProvisionalLoadForFrame.
   2182   // In general, we allow the view to clear the pending entry and typed URL if
   2183   // the user requests (e.g., hitting Escape with focus in the address bar).
   2184   // Note: don't touch the transient entry, since an interstitial may exist.
   2185   if (controller_.GetPendingEntry() != controller_.GetVisibleEntry())
   2186     controller_.DiscardPendingEntry();
   2187 
   2188   FOR_EACH_OBSERVER(WebContentsObserver,
   2189                     observers_,
   2190                     DidFailProvisionalLoad(params.frame_id,
   2191                                            params.frame_unique_name,
   2192                                            params.is_main_frame,
   2193                                            validated_url,
   2194                                            params.error_code,
   2195                                            params.error_description,
   2196                                            render_view_host));
   2197 }
   2198 
   2199 void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
   2200     const GURL& url,
   2201     const std::string& security_info,
   2202     const std::string& http_method,
   2203     const std::string& mime_type,
   2204     ResourceType::Type resource_type) {
   2205   base::StatsCounter cache("WebKit.CacheHit");
   2206   cache.Increment();
   2207 
   2208   // Send out a notification that we loaded a resource from our memory cache.
   2209   int cert_id = 0;
   2210   net::CertStatus cert_status = 0;
   2211   int security_bits = -1;
   2212   int connection_status = 0;
   2213   SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
   2214   DeserializeSecurityInfo(security_info, &cert_id, &cert_status,
   2215                           &security_bits, &connection_status,
   2216                           &signed_certificate_timestamp_ids);
   2217   // TODO(alcutter,eranm): Pass signed_certificate_timestamp_ids into details
   2218   LoadFromMemoryCacheDetails details(
   2219       url, GetRenderProcessHost()->GetID(), cert_id, cert_status, http_method,
   2220       mime_type, resource_type);
   2221 
   2222   controller_.ssl_manager()->DidLoadFromMemoryCache(details);
   2223 
   2224   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2225                     DidLoadResourceFromMemoryCache(details));
   2226 
   2227   if (url.is_valid() && url.SchemeIsHTTPOrHTTPS()) {
   2228     scoped_refptr<net::URLRequestContextGetter> request_context(
   2229         resource_type == ResourceType::MEDIA ?
   2230             GetBrowserContext()->GetMediaRequestContextForRenderProcess(
   2231                 GetRenderProcessHost()->GetID()) :
   2232             GetBrowserContext()->GetRequestContextForRenderProcess(
   2233                 GetRenderProcessHost()->GetID()));
   2234     BrowserThread::PostTask(
   2235         BrowserThread::IO,
   2236         FROM_HERE,
   2237         base::Bind(&NotifyCacheOnIO, request_context, url, http_method));
   2238   }
   2239 }
   2240 
   2241 void WebContentsImpl::OnDidDisplayInsecureContent() {
   2242   RecordAction(UserMetricsAction("SSL.DisplayedInsecureContent"));
   2243   displayed_insecure_content_ = true;
   2244   SSLManager::NotifySSLInternalStateChanged(
   2245       GetController().GetBrowserContext());
   2246 }
   2247 
   2248 void WebContentsImpl::OnDidRunInsecureContent(
   2249     const std::string& security_origin, const GURL& target_url) {
   2250   LOG(WARNING) << security_origin << " ran insecure content from "
   2251                << target_url.possibly_invalid_spec();
   2252   RecordAction(UserMetricsAction("SSL.RanInsecureContent"));
   2253   if (EndsWith(security_origin, kDotGoogleDotCom, false))
   2254     RecordAction(UserMetricsAction("SSL.RanInsecureContentGoogle"));
   2255   controller_.ssl_manager()->DidRunInsecureContent(security_origin);
   2256   displayed_insecure_content_ = true;
   2257   SSLManager::NotifySSLInternalStateChanged(
   2258       GetController().GetBrowserContext());
   2259 }
   2260 
   2261 void WebContentsImpl::OnDocumentLoadedInFrame(int64 frame_id) {
   2262   FOR_EACH_OBSERVER(
   2263       WebContentsObserver, observers_,
   2264       DocumentLoadedInFrame(frame_id, render_view_message_source_));
   2265 }
   2266 
   2267 void WebContentsImpl::OnDidFinishLoad(
   2268     int64 frame_id,
   2269     const GURL& url,
   2270     bool is_main_frame) {
   2271   GURL validated_url(url);
   2272   RenderProcessHost* render_process_host =
   2273       render_view_message_source_->GetProcess();
   2274   RenderViewHost::FilterURL(render_process_host, false, &validated_url);
   2275   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2276                     DidFinishLoad(frame_id, validated_url, is_main_frame,
   2277                                   render_view_message_source_));
   2278 }
   2279 
   2280 void WebContentsImpl::OnDidFailLoadWithError(
   2281     int64 frame_id,
   2282     const GURL& url,
   2283     bool is_main_frame,
   2284     int error_code,
   2285     const base::string16& error_description) {
   2286   GURL validated_url(url);
   2287   RenderProcessHost* render_process_host =
   2288       render_view_message_source_->GetProcess();
   2289   RenderViewHost::FilterURL(render_process_host, false, &validated_url);
   2290   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2291                     DidFailLoad(frame_id, validated_url, is_main_frame,
   2292                                 error_code, error_description,
   2293                                 render_view_message_source_));
   2294 }
   2295 
   2296 void WebContentsImpl::OnGoToEntryAtOffset(int offset) {
   2297   if (!delegate_ || delegate_->OnGoToEntryOffset(offset)) {
   2298     NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
   2299         controller_.GetEntryAtOffset(offset));
   2300     if (!entry)
   2301       return;
   2302     // Note that we don't call NavigationController::GotToOffset() as we don't
   2303     // want to create a pending navigation entry (it might end up lingering
   2304     // http://crbug.com/51680).
   2305     entry->SetTransitionType(
   2306         PageTransitionFromInt(
   2307             entry->GetTransitionType() |
   2308             PAGE_TRANSITION_FORWARD_BACK));
   2309     NavigateToEntry(*entry, NavigationControllerImpl::NO_RELOAD);
   2310 
   2311     // If the entry is being restored and doesn't have a SiteInstance yet, fill
   2312     // it in now that we know. This allows us to find the entry when it commits.
   2313     if (!entry->site_instance() &&
   2314         entry->restore_type() != NavigationEntryImpl::RESTORE_NONE) {
   2315       entry->set_site_instance(
   2316           static_cast<SiteInstanceImpl*>(GetPendingSiteInstance()));
   2317     }
   2318   }
   2319 }
   2320 
   2321 void WebContentsImpl::OnUpdateZoomLimits(int minimum_percent,
   2322                                          int maximum_percent,
   2323                                          bool remember) {
   2324   minimum_zoom_percent_ = minimum_percent;
   2325   maximum_zoom_percent_ = maximum_percent;
   2326   temporary_zoom_settings_ = !remember;
   2327 }
   2328 
   2329 void WebContentsImpl::OnEnumerateDirectory(int request_id,
   2330                                            const base::FilePath& path) {
   2331   if (!delegate_)
   2332     return;
   2333 
   2334   ChildProcessSecurityPolicyImpl* policy =
   2335       ChildProcessSecurityPolicyImpl::GetInstance();
   2336   if (policy->CanReadFile(GetRenderProcessHost()->GetID(), path))
   2337     delegate_->EnumerateDirectory(this, request_id, path);
   2338 }
   2339 
   2340 void WebContentsImpl::OnJSOutOfMemory() {
   2341   if (delegate_)
   2342     delegate_->JSOutOfMemory(this);
   2343 }
   2344 
   2345 void WebContentsImpl::OnRegisterProtocolHandler(const std::string& protocol,
   2346                                                 const GURL& url,
   2347                                                 const base::string16& title,
   2348                                                 bool user_gesture) {
   2349   if (!delegate_)
   2350     return;
   2351 
   2352   ChildProcessSecurityPolicyImpl* policy =
   2353       ChildProcessSecurityPolicyImpl::GetInstance();
   2354   if (policy->IsPseudoScheme(protocol))
   2355     return;
   2356 
   2357   delegate_->RegisterProtocolHandler(this, protocol, url, title, user_gesture);
   2358 }
   2359 
   2360 void WebContentsImpl::OnFindReply(int request_id,
   2361                                   int number_of_matches,
   2362                                   const gfx::Rect& selection_rect,
   2363                                   int active_match_ordinal,
   2364                                   bool final_update) {
   2365   if (delegate_) {
   2366     delegate_->FindReply(this, request_id, number_of_matches, selection_rect,
   2367                          active_match_ordinal, final_update);
   2368   }
   2369 }
   2370 
   2371 #if defined(OS_ANDROID)
   2372 void WebContentsImpl::OnFindMatchRectsReply(
   2373     int version,
   2374     const std::vector<gfx::RectF>& rects,
   2375     const gfx::RectF& active_rect) {
   2376   if (delegate_)
   2377     delegate_->FindMatchRectsReply(this, version, rects, active_rect);
   2378 }
   2379 
   2380 void WebContentsImpl::OnOpenDateTimeDialog(
   2381     const ViewHostMsg_DateTimeDialogValue_Params& value) {
   2382   date_time_chooser_->ShowDialog(ContentViewCore::FromWebContents(this),
   2383                                  GetRenderViewHost(),
   2384                                  value.dialog_type,
   2385                                  value.dialog_value,
   2386                                  value.minimum,
   2387                                  value.maximum,
   2388                                  value.step,
   2389                                  value.suggestions);
   2390 }
   2391 
   2392 void WebContentsImpl::OnJavaBridgeGetChannelHandle(IPC::Message* reply_msg) {
   2393   java_bridge_dispatcher_host_manager_->OnGetChannelHandle(
   2394       render_view_message_source_, reply_msg);
   2395 }
   2396 
   2397 #endif
   2398 
   2399 void WebContentsImpl::OnPepperPluginHung(int plugin_child_id,
   2400                                          const base::FilePath& path,
   2401                                          bool is_hung) {
   2402   UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1);
   2403 
   2404   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2405                     PluginHungStatusChanged(plugin_child_id, path, is_hung));
   2406 }
   2407 
   2408 void WebContentsImpl::OnPluginCrashed(const base::FilePath& plugin_path,
   2409                                       base::ProcessId plugin_pid) {
   2410   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2411                     PluginCrashed(plugin_path, plugin_pid));
   2412 }
   2413 
   2414 void WebContentsImpl::OnAppCacheAccessed(const GURL& manifest_url,
   2415                                          bool blocked_by_policy) {
   2416   // Notify observers about navigation.
   2417   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2418                     AppCacheAccessed(manifest_url, blocked_by_policy));
   2419 }
   2420 
   2421 void WebContentsImpl::OnOpenColorChooser(
   2422       int color_chooser_id,
   2423       SkColor color,
   2424       const std::vector<ColorSuggestion>& suggestions) {
   2425   ColorChooser* new_color_chooser =
   2426       delegate_->OpenColorChooser(this, color, suggestions);
   2427   if (!new_color_chooser)
   2428     return;
   2429   if (color_chooser_)
   2430     color_chooser_->End();
   2431   color_chooser_.reset(new_color_chooser);
   2432   color_chooser_identifier_ = color_chooser_id;
   2433 }
   2434 
   2435 void WebContentsImpl::OnEndColorChooser(int color_chooser_id) {
   2436   if (color_chooser_ &&
   2437       color_chooser_id == color_chooser_identifier_)
   2438     color_chooser_->End();
   2439 }
   2440 
   2441 void WebContentsImpl::OnSetSelectedColorInColorChooser(int color_chooser_id,
   2442                                                        SkColor color) {
   2443   if (color_chooser_ &&
   2444       color_chooser_id == color_chooser_identifier_)
   2445     color_chooser_->SetSelectedColor(color);
   2446 }
   2447 
   2448 // This exists for render views that don't have a WebUI, but do have WebUI
   2449 // bindings enabled.
   2450 void WebContentsImpl::OnWebUISend(const GURL& source_url,
   2451                                   const std::string& name,
   2452                                   const base::ListValue& args) {
   2453   if (delegate_)
   2454     delegate_->WebUISend(this, source_url, name, args);
   2455 }
   2456 
   2457 void WebContentsImpl::OnRequestPpapiBrokerPermission(
   2458     int routing_id,
   2459     const GURL& url,
   2460     const base::FilePath& plugin_path) {
   2461   if (!delegate_) {
   2462     OnPpapiBrokerPermissionResult(routing_id, false);
   2463     return;
   2464   }
   2465 
   2466   if (!delegate_->RequestPpapiBrokerPermission(
   2467       this, url, plugin_path,
   2468       base::Bind(&WebContentsImpl::OnPpapiBrokerPermissionResult,
   2469                  base::Unretained(this), routing_id))) {
   2470     NOTIMPLEMENTED();
   2471     OnPpapiBrokerPermissionResult(routing_id, false);
   2472   }
   2473 }
   2474 
   2475 void WebContentsImpl::OnPpapiBrokerPermissionResult(int routing_id,
   2476                                                     bool result) {
   2477   Send(new ViewMsg_PpapiBrokerPermissionResult(routing_id, result));
   2478 }
   2479 
   2480 void WebContentsImpl::OnBrowserPluginMessage(const IPC::Message& message) {
   2481   // This creates a BrowserPluginEmbedder, which handles all the BrowserPlugin
   2482   // specific messages for this WebContents. This means that any message from
   2483   // a BrowserPlugin prior to this will be ignored.
   2484   // For more info, see comment above classes BrowserPluginEmbedder and
   2485   // BrowserPluginGuest.
   2486   CHECK(!browser_plugin_embedder_.get());
   2487   browser_plugin_embedder_.reset(BrowserPluginEmbedder::Create(this));
   2488   browser_plugin_embedder_->OnMessageReceived(message);
   2489 }
   2490 
   2491 void WebContentsImpl::OnDidDownloadImage(
   2492     int id,
   2493     int http_status_code,
   2494     const GURL& image_url,
   2495     const std::vector<SkBitmap>& bitmaps,
   2496     const std::vector<gfx::Size>& original_bitmap_sizes) {
   2497   if (bitmaps.size() != original_bitmap_sizes.size())
   2498     return;
   2499 
   2500   ImageDownloadMap::iterator iter = image_download_map_.find(id);
   2501   if (iter == image_download_map_.end()) {
   2502     // Currently WebContents notifies us of ANY downloads so that it is
   2503     // possible to get here.
   2504     return;
   2505   }
   2506   if (!iter->second.is_null()) {
   2507     iter->second.Run(
   2508         id, http_status_code, image_url, bitmaps, original_bitmap_sizes);
   2509   }
   2510   image_download_map_.erase(id);
   2511 }
   2512 
   2513 void WebContentsImpl::OnUpdateFaviconURL(
   2514     int32 page_id,
   2515     const std::vector<FaviconURL>& candidates) {
   2516   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2517                     DidUpdateFaviconURL(page_id, candidates));
   2518 }
   2519 
   2520 void WebContentsImpl::OnMediaNotification(int64 player_cookie,
   2521                                           bool has_video,
   2522                                           bool has_audio,
   2523                                           bool is_playing) {
   2524   // Chrome OS does its own detection of audio and video.
   2525 #if !defined(OS_CHROMEOS)
   2526   if (is_playing) {
   2527     scoped_ptr<PowerSaveBlocker> blocker;
   2528     if (has_video) {
   2529       blocker = PowerSaveBlocker::Create(
   2530           PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
   2531           "Playing video");
   2532 #if defined(OS_ANDROID)
   2533       static_cast<PowerSaveBlockerImpl*>(blocker.get())->
   2534           InitDisplaySleepBlocker(GetView()->GetNativeView());
   2535 #endif
   2536     } else if (has_audio) {
   2537       blocker = PowerSaveBlocker::Create(
   2538           PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
   2539           "Playing audio");
   2540     }
   2541 
   2542     if (blocker) {
   2543       power_save_blockers_[render_view_message_source_][player_cookie] =
   2544           blocker.release();
   2545     }
   2546   } else {
   2547     delete power_save_blockers_[render_view_message_source_][player_cookie];
   2548     power_save_blockers_[render_view_message_source_].erase(player_cookie);
   2549   }
   2550 #endif  // !defined(OS_CHROMEOS)
   2551 }
   2552 
   2553 void WebContentsImpl::OnFirstVisuallyNonEmptyPaint(int32 page_id) {
   2554   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2555                     DidFirstVisuallyNonEmptyPaint(page_id));
   2556 }
   2557 
   2558 void WebContentsImpl::DidChangeVisibleSSLState() {
   2559   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2560                     DidChangeVisibleSSLState());
   2561 }
   2562 
   2563 void WebContentsImpl::NotifyBeforeFormRepostWarningShow() {
   2564   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2565                     BeforeFormRepostWarningShow());
   2566 }
   2567 
   2568 
   2569 void WebContentsImpl::ActivateAndShowRepostFormWarningDialog() {
   2570   Activate();
   2571   if (delegate_)
   2572     delegate_->ShowRepostFormWarningDialog(this);
   2573 }
   2574 
   2575 // Notifies the RenderWidgetHost instance about the fact that the page is
   2576 // loading, or done loading.
   2577 void WebContentsImpl::SetIsLoading(RenderViewHost* render_view_host,
   2578                                    bool is_loading,
   2579                                    LoadNotificationDetails* details) {
   2580   if (is_loading == is_loading_)
   2581     return;
   2582 
   2583   if (!is_loading) {
   2584     load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE,
   2585                                           base::string16());
   2586     load_state_host_.clear();
   2587     upload_size_ = 0;
   2588     upload_position_ = 0;
   2589   }
   2590 
   2591   GetRenderManager()->SetIsLoading(is_loading);
   2592 
   2593   is_loading_ = is_loading;
   2594   waiting_for_response_ = is_loading;
   2595 
   2596   if (delegate_)
   2597     delegate_->LoadingStateChanged(this);
   2598   NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD);
   2599 
   2600   std::string url = (details ? details->url.possibly_invalid_spec() : "NULL");
   2601   if (is_loading) {
   2602     TRACE_EVENT_ASYNC_BEGIN1("browser", "WebContentsImpl Loading", this,
   2603                              "URL", url);
   2604     FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2605                       DidStartLoading(render_view_host));
   2606   } else {
   2607     TRACE_EVENT_ASYNC_END1("browser", "WebContentsImpl Loading", this,
   2608                            "URL", url);
   2609     FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2610                       DidStopLoading(render_view_host));
   2611   }
   2612 
   2613   // TODO(avi): Remove. http://crbug.com/170921
   2614   int type = is_loading ? NOTIFICATION_LOAD_START : NOTIFICATION_LOAD_STOP;
   2615   NotificationDetails det = NotificationService::NoDetails();
   2616   if (details)
   2617       det = Details<LoadNotificationDetails>(details);
   2618   NotificationService::current()->Notify(
   2619       type, Source<NavigationController>(&controller_), det);
   2620 }
   2621 
   2622 void WebContentsImpl::DidNavigateMainFramePostCommit(
   2623     const LoadCommittedDetails& details,
   2624     const ViewHostMsg_FrameNavigate_Params& params) {
   2625   if (details.is_navigation_to_different_page()) {
   2626     // Clear the status bubble. This is a workaround for a bug where WebKit
   2627     // doesn't let us know that the cursor left an element during a
   2628     // transition (this is also why the mouse cursor remains as a hand after
   2629     // clicking on a link); see bugs 1184641 and 980803. We don't want to
   2630     // clear the bubble when a user navigates to a named anchor in the same
   2631     // page.
   2632     UpdateTargetURL(details.entry->GetPageID(), GURL());
   2633   }
   2634 
   2635   if (!details.is_in_page) {
   2636     // Once the main frame is navigated, we're no longer considered to have
   2637     // displayed insecure content.
   2638     displayed_insecure_content_ = false;
   2639     SSLManager::NotifySSLInternalStateChanged(
   2640         GetController().GetBrowserContext());
   2641   }
   2642 
   2643   // Notify observers about navigation.
   2644   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2645                     DidNavigateMainFrame(details, params));
   2646 }
   2647 
   2648 void WebContentsImpl::DidNavigateAnyFramePostCommit(
   2649     RenderViewHost* render_view_host,
   2650     const LoadCommittedDetails& details,
   2651     const ViewHostMsg_FrameNavigate_Params& params) {
   2652   // If we navigate off the page, close all JavaScript dialogs.
   2653   if (dialog_manager_ && !details.is_in_page)
   2654     dialog_manager_->CancelActiveAndPendingDialogs(this);
   2655 
   2656   // Notify observers about navigation.
   2657   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2658                     DidNavigateAnyFrame(details, params));
   2659 }
   2660 
   2661 bool WebContentsImpl::ShouldAssignSiteForURL(const GURL& url) {
   2662   // about:blank should not "use up" a new SiteInstance.  The SiteInstance can
   2663   // still be used for a normal web site.
   2664   if (url == GURL(kAboutBlankURL))
   2665     return false;
   2666 
   2667   // The embedder will then have the opportunity to determine if the URL
   2668   // should "use up" the SiteInstance.
   2669   return GetContentClient()->browser()->ShouldAssignSiteForURL(url);
   2670 }
   2671 
   2672 void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) {
   2673   // If we are creating a RVH for a restored controller, then we need to make
   2674   // sure the RenderView starts with a next_page_id_ larger than the number
   2675   // of restored entries.  This must be called before the RenderView starts
   2676   // navigating (to avoid a race between the browser updating max_page_id and
   2677   // the renderer updating next_page_id_).  Because of this, we only call this
   2678   // from CreateRenderView and allow that to notify the RenderView for us.
   2679   int max_restored_page_id = controller_.GetMaxRestoredPageID();
   2680   if (max_restored_page_id >
   2681       GetMaxPageIDForSiteInstance(rvh->GetSiteInstance()))
   2682     UpdateMaxPageIDForSiteInstance(rvh->GetSiteInstance(),
   2683                                    max_restored_page_id);
   2684 }
   2685 
   2686 bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl* entry,
   2687                                           const base::string16& title) {
   2688   // For file URLs without a title, use the pathname instead. In the case of a
   2689   // synthesized title, we don't want the update to count toward the "one set
   2690   // per page of the title to history."
   2691   base::string16 final_title;
   2692   bool explicit_set;
   2693   if (entry && entry->GetURL().SchemeIsFile() && title.empty()) {
   2694     final_title = UTF8ToUTF16(entry->GetURL().ExtractFileName());
   2695     explicit_set = false;  // Don't count synthetic titles toward the set limit.
   2696   } else {
   2697     TrimWhitespace(title, TRIM_ALL, &final_title);
   2698     explicit_set = true;
   2699   }
   2700 
   2701   // If a page is created via window.open and never navigated,
   2702   // there will be no navigation entry. In this situation,
   2703   // |page_title_when_no_navigation_entry_| will be used for page title.
   2704   if (entry) {
   2705     if (final_title == entry->GetTitle())
   2706       return false;  // Nothing changed, don't bother.
   2707 
   2708     entry->SetTitle(final_title);
   2709   } else {
   2710     if (page_title_when_no_navigation_entry_ == final_title)
   2711       return false;  // Nothing changed, don't bother.
   2712 
   2713     page_title_when_no_navigation_entry_ = final_title;
   2714   }
   2715 
   2716   // Lastly, set the title for the view.
   2717   view_->SetPageTitle(final_title);
   2718 
   2719   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2720                     TitleWasSet(entry, explicit_set));
   2721 
   2722   // TODO(avi): Remove. http://crbug.com/170921
   2723   std::pair<NavigationEntry*, bool> details =
   2724       std::make_pair(entry, explicit_set);
   2725   NotificationService::current()->Notify(
   2726       NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
   2727       Source<WebContents>(this),
   2728       Details<std::pair<NavigationEntry*, bool> >(&details));
   2729 
   2730   return true;
   2731 }
   2732 
   2733 void WebContentsImpl::NotifySwapped(RenderViewHost* old_host,
   2734                                     RenderViewHost* new_host) {
   2735   // After sending out a swap notification, we need to send a disconnect
   2736   // notification so that clients that pick up a pointer to |this| can NULL the
   2737   // pointer.  See Bug 1230284.
   2738   notify_disconnection_ = true;
   2739   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2740                     RenderViewHostChanged(old_host, new_host));
   2741 
   2742   // TODO(avi): Remove. http://crbug.com/170921
   2743   std::pair<RenderViewHost*, RenderViewHost*> details =
   2744       std::make_pair(old_host, new_host);
   2745   NotificationService::current()->Notify(
   2746       NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
   2747       Source<WebContents>(this),
   2748       Details<std::pair<RenderViewHost*, RenderViewHost*> >(&details));
   2749 
   2750   // Ensure that the associated embedder gets cleared after a RenderViewHost
   2751   // gets swapped, so we don't reuse the same embedder next time a
   2752   // RenderViewHost is attached to this WebContents.
   2753   RemoveBrowserPluginEmbedder();
   2754 }
   2755 
   2756 // TODO(avi): Remove this entire function because this notification is already
   2757 // covered by two observer functions. http://crbug.com/170921
   2758 void WebContentsImpl::NotifyDisconnected() {
   2759   if (!notify_disconnection_)
   2760     return;
   2761 
   2762   notify_disconnection_ = false;
   2763   NotificationService::current()->Notify(
   2764       NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
   2765       Source<WebContents>(this),
   2766       NotificationService::NoDetails());
   2767 }
   2768 
   2769 void WebContentsImpl::NotifyNavigationEntryCommitted(
   2770     const LoadCommittedDetails& load_details) {
   2771   FOR_EACH_OBSERVER(
   2772       WebContentsObserver, observers_, NavigationEntryCommitted(load_details));
   2773 }
   2774 
   2775 bool WebContentsImpl::OnMessageReceived(RenderFrameHost* render_frame_host,
   2776                                         const IPC::Message& message) {
   2777   return OnMessageReceived(NULL, render_frame_host, message);
   2778 }
   2779 
   2780 void WebContentsImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) {
   2781   // Note this is only for subframes, the notification for the main frame
   2782   // happens in RenderViewCreated.
   2783   FOR_EACH_OBSERVER(WebContentsObserver,
   2784                     observers_,
   2785                     RenderFrameCreated(render_frame_host));
   2786 }
   2787 
   2788 void WebContentsImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
   2789   FOR_EACH_OBSERVER(WebContentsObserver,
   2790                     observers_,
   2791                     RenderFrameDeleted(render_frame_host));
   2792 }
   2793 
   2794 RenderViewHostDelegateView* WebContentsImpl::GetDelegateView() {
   2795   return render_view_host_delegate_view_;
   2796 }
   2797 
   2798 RenderViewHostDelegate::RendererManagement*
   2799 WebContentsImpl::GetRendererManagementDelegate() {
   2800   return GetRenderManager();
   2801 }
   2802 
   2803 RendererPreferences WebContentsImpl::GetRendererPrefs(
   2804     BrowserContext* browser_context) const {
   2805   return renderer_preferences_;
   2806 }
   2807 
   2808 WebContents* WebContentsImpl::GetAsWebContents() {
   2809   return this;
   2810 }
   2811 
   2812 gfx::Rect WebContentsImpl::GetRootWindowResizerRect() const {
   2813   if (delegate_)
   2814     return delegate_->GetRootWindowResizerRect();
   2815   return gfx::Rect();
   2816 }
   2817 
   2818 void WebContentsImpl::RemoveBrowserPluginEmbedder() {
   2819   if (browser_plugin_embedder_)
   2820     browser_plugin_embedder_.reset();
   2821 }
   2822 
   2823 void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) {
   2824   // Don't send notifications if we are just creating a swapped-out RVH for
   2825   // the opener chain.  These won't be used for view-source or WebUI, so it's
   2826   // ok to return early.
   2827   if (static_cast<RenderViewHostImpl*>(render_view_host)->is_swapped_out())
   2828     return;
   2829 
   2830   if (delegate_)
   2831     view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent());
   2832 
   2833   NotificationService::current()->Notify(
   2834       NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
   2835       Source<WebContents>(this),
   2836       Details<RenderViewHost>(render_view_host));
   2837 
   2838   // When we're creating views, we're still doing initial setup, so we always
   2839   // use the pending Web UI rather than any possibly existing committed one.
   2840   if (GetRenderManager()->pending_web_ui())
   2841     GetRenderManager()->pending_web_ui()->RenderViewCreated(render_view_host);
   2842 
   2843   NavigationEntry* entry = controller_.GetPendingEntry();
   2844   if (entry && entry->IsViewSourceMode()) {
   2845     // Put the renderer in view source mode.
   2846     render_view_host->Send(
   2847         new ViewMsg_EnableViewSourceMode(render_view_host->GetRoutingID()));
   2848   }
   2849 
   2850   view_->RenderViewCreated(render_view_host);
   2851 
   2852   FOR_EACH_OBSERVER(
   2853       WebContentsObserver, observers_, RenderViewCreated(render_view_host));
   2854 
   2855   // We tell the observers now instead of when the main RenderFrameHostImpl is
   2856   // constructed because otherwise it would be too early (i.e. IPCs sent to the
   2857   // frame would be dropped because it's not created yet).
   2858   RenderFrameHost* main_frame = GetMainFrame();
   2859   FOR_EACH_OBSERVER(
   2860       WebContentsObserver, observers_, RenderFrameCreated(main_frame));
   2861 }
   2862 
   2863 void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) {
   2864   if (rvh != GetRenderViewHost()) {
   2865     // Don't notify the world, since this came from a renderer in the
   2866     // background.
   2867     return;
   2868   }
   2869 
   2870   notify_disconnection_ = true;
   2871   // TODO(avi): Remove. http://crbug.com/170921
   2872   NotificationService::current()->Notify(
   2873       NOTIFICATION_WEB_CONTENTS_CONNECTED,
   2874       Source<WebContents>(this),
   2875       NotificationService::NoDetails());
   2876 
   2877   bool was_crashed = IsCrashed();
   2878   SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING, 0);
   2879 
   2880   // Restore the focus to the tab (otherwise the focus will be on the top
   2881   // window).
   2882   if (was_crashed && !FocusLocationBarByDefault() &&
   2883       (!delegate_ || delegate_->ShouldFocusPageAfterCrash())) {
   2884     view_->Focus();
   2885   }
   2886 
   2887   FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewReady());
   2888 }
   2889 
   2890 void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
   2891                                            base::TerminationStatus status,
   2892                                            int error_code) {
   2893   if (rvh != GetRenderViewHost()) {
   2894     // The pending page's RenderViewHost is gone.
   2895     return;
   2896   }
   2897 
   2898   // Cancel any visible dialogs so they are not left dangling over the sad tab.
   2899   if (dialog_manager_)
   2900     dialog_manager_->CancelActiveAndPendingDialogs(this);
   2901 
   2902   ClearPowerSaveBlockers(rvh);
   2903   SetIsLoading(rvh, false, NULL);
   2904   NotifyDisconnected();
   2905   SetIsCrashed(status, error_code);
   2906   GetView()->OnTabCrashed(GetCrashedStatus(), crashed_error_code_);
   2907 
   2908   FOR_EACH_OBSERVER(WebContentsObserver,
   2909                     observers_,
   2910                     RenderProcessGone(GetCrashedStatus()));
   2911 }
   2912 
   2913 void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) {
   2914   ClearPowerSaveBlockers(rvh);
   2915   GetRenderManager()->RenderViewDeleted(rvh);
   2916   FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh));
   2917 }
   2918 
   2919 void WebContentsImpl::DidGetResourceResponseStart(
   2920   const ResourceRequestDetails& details) {
   2921   controller_.ssl_manager()->DidStartResourceResponse(details);
   2922 
   2923   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2924                     DidGetResourceResponseStart(details));
   2925 
   2926   // TODO(avi): Remove. http://crbug.com/170921
   2927   NotificationService::current()->Notify(
   2928       NOTIFICATION_RESOURCE_RESPONSE_STARTED,
   2929       Source<WebContents>(this),
   2930       Details<const ResourceRequestDetails>(&details));
   2931 }
   2932 
   2933 void WebContentsImpl::DidGetRedirectForResourceRequest(
   2934   const ResourceRedirectDetails& details) {
   2935   controller_.ssl_manager()->DidReceiveResourceRedirect(details);
   2936 
   2937   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   2938                     DidGetRedirectForResourceRequest(details));
   2939 
   2940   // TODO(avi): Remove. http://crbug.com/170921
   2941   NotificationService::current()->Notify(
   2942       NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
   2943       Source<WebContents>(this),
   2944       Details<const ResourceRedirectDetails>(&details));
   2945 }
   2946 
   2947 void WebContentsImpl::DidNavigate(
   2948     RenderViewHost* rvh,
   2949     const ViewHostMsg_FrameNavigate_Params& params) {
   2950   if (frame_tree_.IsFirstNavigationAfterSwap()) {
   2951     // First navigation should be a main frame navigation.
   2952     DCHECK(PageTransitionIsMainFrame(params.transition));
   2953     frame_tree_.OnFirstNavigationAfterSwap(params.frame_id);
   2954   }
   2955 
   2956   if (PageTransitionIsMainFrame(params.transition)) {
   2957     // When overscroll navigation gesture is enabled, a screenshot of the page
   2958     // in its current state is taken so that it can be used during the
   2959     // nav-gesture. It is necessary to take the screenshot here, before calling
   2960     // RenderFrameHostManager::DidNavigateMainFrame, because that can change
   2961     // WebContents::GetRenderViewHost to return the new host, instead of the one
   2962     // that may have just been swapped out.
   2963     if (delegate_ && delegate_->CanOverscrollContent())
   2964       controller_.TakeScreenshot();
   2965 
   2966     GetRenderManager()->DidNavigateMainFrame(rvh);
   2967   }
   2968 
   2969   // Update the site of the SiteInstance if it doesn't have one yet, unless
   2970   // assigning a site is not necessary for this URL.  In that case, the
   2971   // SiteInstance can still be considered unused until a navigation to a real
   2972   // page.
   2973   if (!static_cast<SiteInstanceImpl*>(GetSiteInstance())->HasSite() &&
   2974       ShouldAssignSiteForURL(params.url)) {
   2975     static_cast<SiteInstanceImpl*>(GetSiteInstance())->SetSite(params.url);
   2976   }
   2977 
   2978   // Need to update MIME type here because it's referred to in
   2979   // UpdateNavigationCommands() called by RendererDidNavigate() to
   2980   // determine whether or not to enable the encoding menu.
   2981   // It's updated only for the main frame. For a subframe,
   2982   // RenderView::UpdateURL does not set params.contents_mime_type.
   2983   // (see http://code.google.com/p/chromium/issues/detail?id=2929 )
   2984   // TODO(jungshik): Add a test for the encoding menu to avoid
   2985   // regressing it again.
   2986   if (PageTransitionIsMainFrame(params.transition))
   2987     contents_mime_type_ = params.contents_mime_type;
   2988 
   2989   LoadCommittedDetails details;
   2990   bool did_navigate = controller_.RendererDidNavigate(params, &details);
   2991 
   2992   // For now, keep track of each frame's URL in its FrameTreeNode.  This lets
   2993   // us estimate our process count for implementing OOP iframes.
   2994   // TODO(creis): Remove this when we track which pages commit in each frame.
   2995   frame_tree_.SetFrameUrl(params.frame_id, params.url);
   2996 
   2997   // Send notification about committed provisional loads. This notification is
   2998   // different from the NAV_ENTRY_COMMITTED notification which doesn't include
   2999   // the actual URL navigated to and isn't sent for AUTO_SUBFRAME navigations.
   3000   if (details.type != NAVIGATION_TYPE_NAV_IGNORE) {
   3001     // For AUTO_SUBFRAME navigations, an event for the main frame is generated
   3002     // that is not recorded in the navigation history. For the purpose of
   3003     // tracking navigation events, we treat this event as a sub frame navigation
   3004     // event.
   3005     bool is_main_frame = did_navigate ? details.is_main_frame : false;
   3006     PageTransition transition_type = params.transition;
   3007     // Whether or not a page transition was triggered by going backward or
   3008     // forward in the history is only stored in the navigation controller's
   3009     // entry list.
   3010     if (did_navigate &&
   3011         (controller_.GetLastCommittedEntry()->GetTransitionType() &
   3012             PAGE_TRANSITION_FORWARD_BACK)) {
   3013       transition_type = PageTransitionFromInt(
   3014           params.transition | PAGE_TRANSITION_FORWARD_BACK);
   3015     }
   3016     // Notify observers about the commit of the provisional load.
   3017     FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3018                       DidCommitProvisionalLoadForFrame(
   3019                           params.frame_id,
   3020                           params.frame_unique_name,
   3021                           is_main_frame,
   3022                           params.url,
   3023                           transition_type,
   3024                           rvh));
   3025   }
   3026 
   3027   if (!did_navigate)
   3028     return;  // No navigation happened.
   3029 
   3030   // DO NOT ADD MORE STUFF TO THIS FUNCTION! Your component should either listen
   3031   // for the appropriate notification (best) or you can add it to
   3032   // DidNavigateMainFramePostCommit / DidNavigateAnyFramePostCommit (only if
   3033   // necessary, please).
   3034 
   3035   // Run post-commit tasks.
   3036   if (details.is_main_frame) {
   3037     DidNavigateMainFramePostCommit(details, params);
   3038     if (delegate_) {
   3039       delegate_->DidNavigateMainFramePostCommit(this);
   3040       view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent());
   3041     }
   3042   }
   3043   DidNavigateAnyFramePostCommit(rvh, details, params);
   3044 }
   3045 
   3046 void WebContentsImpl::UpdateState(RenderViewHost* rvh,
   3047                                   int32 page_id,
   3048                                   const PageState& page_state) {
   3049   // Ensure that this state update comes from either the active RVH or one of
   3050   // the swapped out RVHs.  We don't expect to hear from any other RVHs.
   3051   DCHECK(rvh == GetRenderViewHost() ||
   3052          GetRenderManager()->IsOnSwappedOutList(rvh));
   3053 
   3054   // We must be prepared to handle state updates for any page, these occur
   3055   // when the user is scrolling and entering form data, as well as when we're
   3056   // leaving a page, in which case our state may have already been moved to
   3057   // the next page. The navigation controller will look up the appropriate
   3058   // NavigationEntry and update it when it is notified via the delegate.
   3059 
   3060   int entry_index = controller_.GetEntryIndexWithPageID(
   3061       rvh->GetSiteInstance(), page_id);
   3062   if (entry_index < 0)
   3063     return;
   3064   NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index);
   3065 
   3066   if (page_state == entry->GetPageState())
   3067     return;  // Nothing to update.
   3068   entry->SetPageState(page_state);
   3069   controller_.NotifyEntryChanged(entry, entry_index);
   3070 }
   3071 
   3072 void WebContentsImpl::UpdateTitle(RenderViewHost* rvh,
   3073                                   int32 page_id,
   3074                                   const base::string16& title,
   3075                                   base::i18n::TextDirection title_direction) {
   3076   // If we have a title, that's a pretty good indication that we've started
   3077   // getting useful data.
   3078   SetNotWaitingForResponse();
   3079 
   3080   // Try to find the navigation entry, which might not be the current one.
   3081   // For example, it might be from a pending RVH for the pending entry.
   3082   NavigationEntryImpl* entry = controller_.GetEntryWithPageID(
   3083       rvh->GetSiteInstance(), page_id);
   3084 
   3085   // We can handle title updates when we don't have an entry in
   3086   // UpdateTitleForEntry, but only if the update is from the current RVH.
   3087   if (!entry && rvh != GetRenderViewHost())
   3088     return;
   3089 
   3090   // TODO(evan): make use of title_direction.
   3091   // http://code.google.com/p/chromium/issues/detail?id=27094
   3092   if (!UpdateTitleForEntry(entry, title))
   3093     return;
   3094 
   3095   // Broadcast notifications when the UI should be updated.
   3096   if (entry == controller_.GetEntryAtOffset(0))
   3097     NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE);
   3098 }
   3099 
   3100 void WebContentsImpl::UpdateEncoding(RenderViewHost* render_view_host,
   3101                                      const std::string& encoding) {
   3102   SetEncoding(encoding);
   3103 }
   3104 
   3105 void WebContentsImpl::UpdateTargetURL(int32 page_id, const GURL& url) {
   3106   if (delegate_)
   3107     delegate_->UpdateTargetURL(this, page_id, url);
   3108 }
   3109 
   3110 void WebContentsImpl::Close(RenderViewHost* rvh) {
   3111 #if defined(OS_MACOSX)
   3112   // The UI may be in an event-tracking loop, such as between the
   3113   // mouse-down and mouse-up in text selection or a button click.
   3114   // Defer the close until after tracking is complete, so that we
   3115   // don't free objects out from under the UI.
   3116   // TODO(shess): This could get more fine-grained.  For instance,
   3117   // closing a tab in another window while selecting text in the
   3118   // current window's Omnibox should be just fine.
   3119   if (view_->IsEventTracking()) {
   3120     view_->CloseTabAfterEventTracking();
   3121     return;
   3122   }
   3123 #endif
   3124 
   3125   // Ignore this if it comes from a RenderViewHost that we aren't showing.
   3126   if (delegate_ && rvh == GetRenderViewHost())
   3127     delegate_->CloseContents(this);
   3128 }
   3129 
   3130 void WebContentsImpl::SwappedOut(RenderViewHost* rvh) {
   3131   if (delegate_ && rvh == GetRenderViewHost())
   3132     delegate_->SwappedOut(this);
   3133 
   3134   // Allow the navigation to proceed.
   3135   GetRenderManager()->SwappedOut(rvh);
   3136 }
   3137 
   3138 void WebContentsImpl::RequestMove(const gfx::Rect& new_bounds) {
   3139   if (delegate_ && delegate_->IsPopupOrPanel(this))
   3140     delegate_->MoveContents(this, new_bounds);
   3141 }
   3142 
   3143 void WebContentsImpl::DidStartLoading(RenderViewHost* render_view_host) {
   3144   SetIsLoading(render_view_host, true, NULL);
   3145 }
   3146 
   3147 void WebContentsImpl::DidStopLoading(RenderViewHost* render_view_host) {
   3148   scoped_ptr<LoadNotificationDetails> details;
   3149 
   3150   // Use the last committed entry rather than the active one, in case a
   3151   // pending entry has been created.
   3152   NavigationEntry* entry = controller_.GetLastCommittedEntry();
   3153 
   3154   // An entry may not exist for a stop when loading an initial blank page or
   3155   // if an iframe injected by script into a blank page finishes loading.
   3156   if (entry) {
   3157     base::TimeDelta elapsed = base::TimeTicks::Now() - current_load_start_;
   3158 
   3159     details.reset(new LoadNotificationDetails(
   3160         entry->GetVirtualURL(),
   3161         entry->GetTransitionType(),
   3162         elapsed,
   3163         &controller_,
   3164         controller_.GetCurrentEntryIndex()));
   3165   }
   3166 
   3167   SetIsLoading(render_view_host, false, details.get());
   3168 }
   3169 
   3170 void WebContentsImpl::DidCancelLoading() {
   3171   controller_.DiscardNonCommittedEntries();
   3172 
   3173   // Update the URL display.
   3174   NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
   3175 }
   3176 
   3177 void WebContentsImpl::DidChangeLoadProgress(double progress) {
   3178   if (delegate_)
   3179     delegate_->LoadProgressChanged(this, progress);
   3180 }
   3181 
   3182 void WebContentsImpl::DidDisownOpener(RenderViewHost* rvh) {
   3183   if (opener_) {
   3184     // Clear our opener so that future cross-process navigations don't have an
   3185     // opener assigned.
   3186     RemoveDestructionObserver(opener_);
   3187     opener_ = NULL;
   3188   }
   3189 
   3190   // Notify all swapped out RenderViewHosts for this tab.  This is important
   3191   // in case we go back to them, or if another window in those processes tries
   3192   // to access window.opener.
   3193   GetRenderManager()->DidDisownOpener(rvh);
   3194 }
   3195 
   3196 void WebContentsImpl::DidAccessInitialDocument() {
   3197   // Update the URL display.
   3198   NotifyNavigationStateChanged(content::INVALIDATE_TYPE_URL);
   3199 }
   3200 
   3201 void WebContentsImpl::DocumentAvailableInMainFrame(
   3202     RenderViewHost* render_view_host) {
   3203   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3204                     DocumentAvailableInMainFrame());
   3205 }
   3206 
   3207 void WebContentsImpl::DocumentOnLoadCompletedInMainFrame(
   3208     RenderViewHost* render_view_host,
   3209     int32 page_id) {
   3210   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3211                     DocumentOnLoadCompletedInMainFrame(page_id));
   3212 
   3213   // TODO(avi): Remove. http://crbug.com/170921
   3214   NotificationService::current()->Notify(
   3215       NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
   3216       Source<WebContents>(this),
   3217       Details<int>(&page_id));
   3218 }
   3219 
   3220 void WebContentsImpl::RequestOpenURL(RenderViewHost* rvh,
   3221                                      const GURL& url,
   3222                                      const Referrer& referrer,
   3223                                      WindowOpenDisposition disposition,
   3224                                      int64 source_frame_id,
   3225                                      bool should_replace_current_entry,
   3226                                      bool user_gesture) {
   3227   // If this came from a swapped out RenderViewHost, we only allow the request
   3228   // if we are still in the same BrowsingInstance.
   3229   if (static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out() &&
   3230       !rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance())) {
   3231     return;
   3232   }
   3233 
   3234   // Delegate to RequestTransferURL because this is just the generic
   3235   // case where |old_request_id| is empty.
   3236   // TODO(creis): Pass the redirect_chain into this method to support client
   3237   // redirects.  http://crbug.com/311721.
   3238   std::vector<GURL> redirect_chain;
   3239   RequestTransferURL(url, redirect_chain, referrer, PAGE_TRANSITION_LINK,
   3240                      disposition, source_frame_id, GlobalRequestID(),
   3241                      should_replace_current_entry, user_gesture);
   3242 }
   3243 
   3244 void WebContentsImpl::RequestTransferURL(
   3245     const GURL& url,
   3246     const std::vector<GURL>& redirect_chain,
   3247     const Referrer& referrer,
   3248     PageTransition page_transition,
   3249     WindowOpenDisposition disposition,
   3250     int64 source_frame_id,
   3251     const GlobalRequestID& old_request_id,
   3252     bool should_replace_current_entry,
   3253     bool user_gesture) {
   3254   WebContents* new_contents = NULL;
   3255   GURL dest_url(url);
   3256   if (!GetContentClient()->browser()->ShouldAllowOpenURL(
   3257           GetSiteInstance(), url))
   3258     dest_url = GURL(kAboutBlankURL);
   3259 
   3260   // TODO(creis): Look up the FrameTreeNode ID corresponding to source_frame_id.
   3261   int frame_tree_node_id = -1;
   3262   OpenURLParams params(dest_url, referrer, source_frame_id,
   3263       frame_tree_node_id, disposition,
   3264       page_transition, true /* is_renderer_initiated */);
   3265   if (redirect_chain.size() > 0)
   3266     params.redirect_chain = redirect_chain;
   3267   params.transferred_global_request_id = old_request_id;
   3268   params.should_replace_current_entry = should_replace_current_entry;
   3269   params.user_gesture = user_gesture;
   3270 
   3271   if (GetRenderManager()->web_ui()) {
   3272     // Web UI pages sometimes want to override the page transition type for
   3273     // link clicks (e.g., so the new tab page can specify AUTO_BOOKMARK for
   3274     // automatically generated suggestions).  We don't override other types
   3275     // like TYPED because they have different implications (e.g., autocomplete).
   3276     if (PageTransitionCoreTypeIs(params.transition, PAGE_TRANSITION_LINK))
   3277       params.transition = GetRenderManager()->web_ui()->GetLinkTransitionType();
   3278 
   3279     // Note also that we hide the referrer for Web UI pages. We don't really
   3280     // want web sites to see a referrer of "chrome://blah" (and some
   3281     // chrome: URLs might have search terms or other stuff we don't want to
   3282     // send to the site), so we send no referrer.
   3283     params.referrer = Referrer();
   3284 
   3285     // Navigations in Web UI pages count as browser-initiated navigations.
   3286     params.is_renderer_initiated = false;
   3287   }
   3288 
   3289   new_contents = OpenURL(params);
   3290 
   3291   if (new_contents) {
   3292     // Notify observers.
   3293     FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3294                       DidOpenRequestedURL(new_contents,
   3295                                           dest_url,
   3296                                           referrer,
   3297                                           disposition,
   3298                                           params.transition,
   3299                                           source_frame_id));
   3300   }
   3301 }
   3302 
   3303 void WebContentsImpl::RouteCloseEvent(RenderViewHost* rvh) {
   3304   // Tell the active RenderViewHost to run unload handlers and close, as long
   3305   // as the request came from a RenderViewHost in the same BrowsingInstance.
   3306   // In most cases, we receive this from a swapped out RenderViewHost.
   3307   // It is possible to receive it from one that has just been swapped in,
   3308   // in which case we might as well deliver the message anyway.
   3309   if (rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()))
   3310     GetRenderViewHost()->ClosePage();
   3311 }
   3312 
   3313 void WebContentsImpl::RouteMessageEvent(
   3314     RenderViewHost* rvh,
   3315     const ViewMsg_PostMessage_Params& params) {
   3316   // Only deliver the message to the active RenderViewHost if the request
   3317   // came from a RenderViewHost in the same BrowsingInstance or if this
   3318   // WebContents is dedicated to a browser plugin guest.
   3319   // Note: This check means that an embedder could theoretically receive a
   3320   // postMessage from anyone (not just its own guests). However, this is
   3321   // probably not a risk for apps since other pages won't have references
   3322   // to App windows.
   3323   if (!rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()) &&
   3324       !GetBrowserPluginGuest() && !GetBrowserPluginEmbedder())
   3325     return;
   3326 
   3327   ViewMsg_PostMessage_Params new_params(params);
   3328 
   3329   if (!params.message_port_ids.empty()) {
   3330     MessagePortMessageFilter* message_port_message_filter =
   3331         static_cast<RenderProcessHostImpl*>(GetRenderProcessHost())
   3332             ->message_port_message_filter();
   3333     std::vector<int> new_routing_ids(params.message_port_ids.size());
   3334     for (size_t i = 0; i < params.message_port_ids.size(); ++i) {
   3335       new_routing_ids[i] = message_port_message_filter->GetNextRoutingID();
   3336       MessagePortService::GetInstance()->UpdateMessagePort(
   3337           params.message_port_ids[i],
   3338           message_port_message_filter,
   3339           new_routing_ids[i]);
   3340     }
   3341     new_params.new_routing_ids = new_routing_ids;
   3342   }
   3343 
   3344   // If there is a source_routing_id, translate it to the routing ID for
   3345   // the equivalent swapped out RVH in the target process.  If we need
   3346   // to create a swapped out RVH for the source tab, we create its opener
   3347   // chain as well, since those will also be accessible to the target page.
   3348   if (new_params.source_routing_id != MSG_ROUTING_NONE) {
   3349     // Try to look up the WebContents for the source page.
   3350     WebContentsImpl* source_contents = NULL;
   3351     RenderViewHostImpl* source_rvh = RenderViewHostImpl::FromID(
   3352         rvh->GetProcess()->GetID(), params.source_routing_id);
   3353     if (source_rvh) {
   3354       source_contents = static_cast<WebContentsImpl*>(
   3355           source_rvh->GetDelegate()->GetAsWebContents());
   3356     }
   3357 
   3358     if (source_contents) {
   3359       if (GetBrowserPluginGuest()) {
   3360         // We create a swapped out RenderView for the embedder in the guest's
   3361         // render process but we intentionally do not expose the embedder's
   3362         // opener chain to it.
   3363         new_params.source_routing_id =
   3364             source_contents->CreateSwappedOutRenderView(GetSiteInstance());
   3365       } else {
   3366         new_params.source_routing_id =
   3367             source_contents->CreateOpenerRenderViews(GetSiteInstance());
   3368       }
   3369     } else {
   3370       // We couldn't find it, so don't pass a source frame.
   3371       new_params.source_routing_id = MSG_ROUTING_NONE;
   3372     }
   3373   }
   3374 
   3375   // In most cases, we receive this from a swapped out RenderViewHost.
   3376   // It is possible to receive it from one that has just been swapped in,
   3377   // in which case we might as well deliver the message anyway.
   3378   Send(new ViewMsg_PostMessageEvent(GetRoutingID(), new_params));
   3379 }
   3380 
   3381 void WebContentsImpl::RunJavaScriptMessage(
   3382     RenderViewHost* rvh,
   3383     const base::string16& message,
   3384     const base::string16& default_prompt,
   3385     const GURL& frame_url,
   3386     JavaScriptMessageType javascript_message_type,
   3387     IPC::Message* reply_msg,
   3388     bool* did_suppress_message) {
   3389   // Suppress JavaScript dialogs when requested. Also suppress messages when
   3390   // showing an interstitial as it's shown over the previous page and we don't
   3391   // want the hidden page's dialogs to interfere with the interstitial.
   3392   bool suppress_this_message =
   3393       static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out() ||
   3394       ShowingInterstitialPage() ||
   3395       !delegate_ ||
   3396       delegate_->ShouldSuppressDialogs() ||
   3397       !delegate_->GetJavaScriptDialogManager();
   3398 
   3399   if (!suppress_this_message) {
   3400     std::string accept_lang = GetContentClient()->browser()->
   3401       GetAcceptLangs(GetBrowserContext());
   3402     dialog_manager_ = delegate_->GetJavaScriptDialogManager();
   3403     dialog_manager_->RunJavaScriptDialog(
   3404         this,
   3405         frame_url.GetOrigin(),
   3406         accept_lang,
   3407         javascript_message_type,
   3408         message,
   3409         default_prompt,
   3410         base::Bind(&WebContentsImpl::OnDialogClosed,
   3411                    base::Unretained(this),
   3412                    rvh,
   3413                    reply_msg),
   3414         &suppress_this_message);
   3415   }
   3416 
   3417   *did_suppress_message = suppress_this_message;
   3418 
   3419   if (suppress_this_message) {
   3420     // If we are suppressing messages, just reply as if the user immediately
   3421     // pressed "Cancel".
   3422     OnDialogClosed(rvh, reply_msg, false, base::string16());
   3423   }
   3424 
   3425   // OnDialogClosed (two lines up) may have caused deletion of this object (see
   3426   // http://crbug.com/288961 ). The only safe thing to do here is return.
   3427 }
   3428 
   3429 void WebContentsImpl::RunBeforeUnloadConfirm(RenderViewHost* rvh,
   3430                                              const base::string16& message,
   3431                                              bool is_reload,
   3432                                              IPC::Message* reply_msg) {
   3433   RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh);
   3434   if (delegate_)
   3435     delegate_->WillRunBeforeUnloadConfirm();
   3436 
   3437   bool suppress_this_message =
   3438       rvhi->is_swapped_out() ||
   3439       !delegate_ ||
   3440       delegate_->ShouldSuppressDialogs() ||
   3441       !delegate_->GetJavaScriptDialogManager();
   3442   if (suppress_this_message) {
   3443     // The reply must be sent to the RVH that sent the request.
   3444     rvhi->JavaScriptDialogClosed(reply_msg, true, base::string16());
   3445     return;
   3446   }
   3447 
   3448   is_showing_before_unload_dialog_ = true;
   3449   dialog_manager_ = delegate_->GetJavaScriptDialogManager();
   3450   dialog_manager_->RunBeforeUnloadDialog(
   3451       this, message, is_reload,
   3452       base::Bind(&WebContentsImpl::OnDialogClosed, base::Unretained(this), rvh,
   3453                  reply_msg));
   3454 }
   3455 
   3456 bool WebContentsImpl::AddMessageToConsole(int32 level,
   3457                                           const base::string16& message,
   3458                                           int32 line_no,
   3459                                           const base::string16& source_id) {
   3460   if (!delegate_)
   3461     return false;
   3462   return delegate_->AddMessageToConsole(this, level, message, line_no,
   3463                                         source_id);
   3464 }
   3465 
   3466 WebPreferences WebContentsImpl::GetWebkitPrefs() {
   3467   // We want to base the page config off of the actual URL, rather than the
   3468   // virtual URL.
   3469   // TODO(nasko): Investigate how to remove the GetActiveEntry usage here,
   3470   // as it is deprecated and can be out of sync with GetRenderViewHost().
   3471   GURL url = controller_.GetActiveEntry()
   3472       ? controller_.GetActiveEntry()->GetURL() : GURL::EmptyGURL();
   3473 
   3474   return GetRenderManager()->current_host()->GetWebkitPrefs(url);
   3475 }
   3476 
   3477 int WebContentsImpl::CreateSwappedOutRenderView(
   3478     SiteInstance* instance) {
   3479   return GetRenderManager()->CreateRenderView(instance, MSG_ROUTING_NONE,
   3480                                               true, true);
   3481 }
   3482 
   3483 void WebContentsImpl::OnUserGesture() {
   3484   // Notify observers.
   3485   FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetUserGesture());
   3486 
   3487   ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
   3488   if (rdh)  // NULL in unittests.
   3489     rdh->OnUserGesture(this);
   3490 }
   3491 
   3492 void WebContentsImpl::OnIgnoredUIEvent() {
   3493   // Notify observers.
   3494   FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetIgnoredUIEvent());
   3495 }
   3496 
   3497 void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh,
   3498                                            bool is_during_beforeunload,
   3499                                            bool is_during_unload) {
   3500   // Don't show hung renderer dialog for a swapped out RVH.
   3501   if (rvh != GetRenderViewHost())
   3502     return;
   3503 
   3504   RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh);
   3505 
   3506   // Ignore renderer unresponsive event if debugger is attached to the tab
   3507   // since the event may be a result of the renderer sitting on a breakpoint.
   3508   // See http://crbug.com/65458
   3509   if (DevToolsAgentHost::IsDebuggerAttached(this))
   3510     return;
   3511 
   3512   if (is_during_beforeunload || is_during_unload) {
   3513     // Hang occurred while firing the beforeunload/unload handler.
   3514     // Pretend the handler fired so tab closing continues as if it had.
   3515     rvhi->set_sudden_termination_allowed(true);
   3516 
   3517     if (!GetRenderManager()->ShouldCloseTabOnUnresponsiveRenderer())
   3518       return;
   3519 
   3520     // If the tab hangs in the beforeunload/unload handler there's really
   3521     // nothing we can do to recover. If the hang is in the beforeunload handler,
   3522     // pretend the beforeunload listeners have all fired and allow the delegate
   3523     // to continue closing; the user will not have the option of cancelling the
   3524     // close. Otherwise, pretend the unload listeners have all fired and close
   3525     // the tab.
   3526     bool close = true;
   3527     if (is_during_beforeunload) {
   3528       delegate_->BeforeUnloadFired(this, true, &close);
   3529     }
   3530     if (close)
   3531       Close(rvh);
   3532     return;
   3533   }
   3534 
   3535   if (!GetRenderViewHostImpl() || !GetRenderViewHostImpl()->IsRenderViewLive())
   3536     return;
   3537 
   3538   if (delegate_)
   3539     delegate_->RendererUnresponsive(this);
   3540 }
   3541 
   3542 void WebContentsImpl::RendererResponsive(RenderViewHost* render_view_host) {
   3543   if (delegate_)
   3544     delegate_->RendererResponsive(this);
   3545 }
   3546 
   3547 void WebContentsImpl::LoadStateChanged(
   3548     const GURL& url,
   3549     const net::LoadStateWithParam& load_state,
   3550     uint64 upload_position,
   3551     uint64 upload_size) {
   3552   load_state_ = load_state;
   3553   upload_position_ = upload_position;
   3554   upload_size_ = upload_size;
   3555   load_state_host_ = net::IDNToUnicode(url.host(),
   3556       GetContentClient()->browser()->GetAcceptLangs(
   3557           GetBrowserContext()));
   3558   if (load_state_.state == net::LOAD_STATE_READING_RESPONSE)
   3559     SetNotWaitingForResponse();
   3560   if (IsLoading()) {
   3561     NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD | INVALIDATE_TYPE_TAB);
   3562   }
   3563 }
   3564 
   3565 void WebContentsImpl::WorkerCrashed() {
   3566   if (delegate_)
   3567     delegate_->WorkerCrashed(this);
   3568 }
   3569 
   3570 void WebContentsImpl::BeforeUnloadFiredFromRenderManager(
   3571     bool proceed, const base::TimeTicks& proceed_time,
   3572     bool* proceed_to_fire_unload) {
   3573   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3574                     BeforeUnloadFired(proceed_time));
   3575   if (delegate_)
   3576     delegate_->BeforeUnloadFired(this, proceed, proceed_to_fire_unload);
   3577   // Note: |this| might be deleted at this point.
   3578 }
   3579 
   3580 void WebContentsImpl::RenderProcessGoneFromRenderManager(
   3581     RenderViewHost* render_view_host) {
   3582   DCHECK(crashed_status_ != base::TERMINATION_STATUS_STILL_RUNNING);
   3583   RenderViewTerminated(render_view_host, crashed_status_, crashed_error_code_);
   3584 }
   3585 
   3586 void WebContentsImpl::UpdateRenderViewSizeForRenderManager() {
   3587   // TODO(brettw) this is a hack. See WebContentsView::SizeContents.
   3588   gfx::Size size = GetSizeForNewRenderView();
   3589   // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be
   3590   // here during container initialization and normal window size will be set
   3591   // later. In case of tab duplication this resizing to 0x0 prevents setting
   3592   // normal size later so just ignore it.
   3593   if (!size.IsEmpty())
   3594     view_->SizeContents(size);
   3595 }
   3596 
   3597 void WebContentsImpl::CancelModalDialogsForRenderManager() {
   3598   // We need to cancel modal dialogs when doing a process swap, since the load
   3599   // deferrer would prevent us from swapping out.
   3600   if (dialog_manager_)
   3601     dialog_manager_->CancelActiveAndPendingDialogs(this);
   3602 }
   3603 
   3604 void WebContentsImpl::NotifySwappedFromRenderManager(RenderViewHost* old_host,
   3605                                                      RenderViewHost* new_host) {
   3606   NotifySwapped(old_host, new_host);
   3607 
   3608   // Make sure the visible RVH reflects the new delegate's preferences.
   3609   if (delegate_)
   3610     view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent());
   3611 
   3612   view_->RenderViewSwappedIn(new_host);
   3613 }
   3614 
   3615 int WebContentsImpl::CreateOpenerRenderViewsForRenderManager(
   3616     SiteInstance* instance) {
   3617   if (!opener_)
   3618     return MSG_ROUTING_NONE;
   3619 
   3620   // Recursively create RenderViews for anything else in the opener chain.
   3621   return opener_->CreateOpenerRenderViews(instance);
   3622 }
   3623 
   3624 int WebContentsImpl::CreateOpenerRenderViews(SiteInstance* instance) {
   3625   int opener_route_id = MSG_ROUTING_NONE;
   3626 
   3627   // If this tab has an opener, ensure it has a RenderView in the given
   3628   // SiteInstance as well.
   3629   if (opener_)
   3630     opener_route_id = opener_->CreateOpenerRenderViews(instance);
   3631 
   3632   // If any of the renderers (current, pending, or swapped out) for this
   3633   // WebContents has the same SiteInstance, use it.
   3634   if (GetRenderManager()->current_host()->GetSiteInstance() == instance)
   3635     return GetRenderManager()->current_host()->GetRoutingID();
   3636 
   3637   if (GetRenderManager()->pending_render_view_host() &&
   3638       GetRenderManager()->pending_render_view_host()->GetSiteInstance() ==
   3639           instance)
   3640     return GetRenderManager()->pending_render_view_host()->GetRoutingID();
   3641 
   3642   RenderViewHostImpl* rvh = GetRenderManager()->GetSwappedOutRenderViewHost(
   3643       instance);
   3644   if (rvh)
   3645     return rvh->GetRoutingID();
   3646 
   3647   // Create a swapped out RenderView in the given SiteInstance if none exists,
   3648   // setting its opener to the given route_id.  Return the new view's route_id.
   3649   return GetRenderManager()->CreateRenderView(instance, opener_route_id,
   3650                                               true, true);
   3651 }
   3652 
   3653 NavigationControllerImpl& WebContentsImpl::GetControllerForRenderManager() {
   3654   return GetController();
   3655 }
   3656 
   3657 WebUIImpl* WebContentsImpl::CreateWebUIForRenderManager(const GURL& url) {
   3658   return static_cast<WebUIImpl*>(CreateWebUI(url));
   3659 }
   3660 
   3661 NavigationEntry*
   3662     WebContentsImpl::GetLastCommittedNavigationEntryForRenderManager() {
   3663   return controller_.GetLastCommittedEntry();
   3664 }
   3665 
   3666 bool WebContentsImpl::CreateRenderViewForRenderManager(
   3667     RenderViewHost* render_view_host, int opener_route_id) {
   3668   TRACE_EVENT0("browser", "WebContentsImpl::CreateRenderViewForRenderManager");
   3669   // Can be NULL during tests.
   3670   RenderWidgetHostView* rwh_view = view_->CreateViewForWidget(render_view_host);
   3671 
   3672   // Now that the RenderView has been created, we need to tell it its size.
   3673   if (rwh_view)
   3674     rwh_view->SetSize(GetSizeForNewRenderView());
   3675 
   3676   // Make sure we use the correct starting page_id in the new RenderView.
   3677   UpdateMaxPageIDIfNecessary(render_view_host);
   3678   int32 max_page_id =
   3679       GetMaxPageIDForSiteInstance(render_view_host->GetSiteInstance());
   3680 
   3681   if (!static_cast<RenderViewHostImpl*>(
   3682           render_view_host)->CreateRenderView(base::string16(),
   3683                                               opener_route_id,
   3684                                               max_page_id)) {
   3685     return false;
   3686   }
   3687 
   3688 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
   3689   // Force a ViewMsg_Resize to be sent, needed to make plugins show up on
   3690   // linux. See crbug.com/83941.
   3691   if (rwh_view) {
   3692     if (RenderWidgetHost* render_widget_host = rwh_view->GetRenderWidgetHost())
   3693       render_widget_host->WasResized();
   3694   }
   3695 #endif
   3696 
   3697   return true;
   3698 }
   3699 
   3700 #if defined(OS_ANDROID)
   3701 base::android::ScopedJavaLocalRef<jobject>
   3702 WebContentsImpl::GetJavaWebContents() {
   3703   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   3704 
   3705   WebContentsAndroid* web_contents_android =
   3706       static_cast<WebContentsAndroid*>(GetUserData(kWebContentsAndroidKey));
   3707   if (!web_contents_android) {
   3708     web_contents_android = new WebContentsAndroid(this);
   3709     SetUserData(kWebContentsAndroidKey, web_contents_android);
   3710   }
   3711   return web_contents_android->GetJavaObject();
   3712 }
   3713 
   3714 bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() {
   3715   return CreateRenderViewForRenderManager(GetRenderViewHost(),
   3716                                           MSG_ROUTING_NONE);
   3717 }
   3718 #endif
   3719 
   3720 void WebContentsImpl::OnDialogClosed(RenderViewHost* rvh,
   3721                                      IPC::Message* reply_msg,
   3722                                      bool success,
   3723                                      const base::string16& user_input) {
   3724   if (is_showing_before_unload_dialog_ && !success) {
   3725     // If a beforeunload dialog is canceled, we need to stop the throbber from
   3726     // spinning, since we forced it to start spinning in Navigate.
   3727     DidStopLoading(rvh);
   3728     controller_.DiscardNonCommittedEntries();
   3729 
   3730     FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3731                       BeforeUnloadDialogCancelled());
   3732   }
   3733   is_showing_before_unload_dialog_ = false;
   3734   static_cast<RenderViewHostImpl*>(
   3735       rvh)->JavaScriptDialogClosed(reply_msg, success, user_input);
   3736 }
   3737 
   3738 void WebContentsImpl::SetEncoding(const std::string& encoding) {
   3739   encoding_ = GetContentClient()->browser()->
   3740       GetCanonicalEncodingNameByAliasName(encoding);
   3741 }
   3742 
   3743 void WebContentsImpl::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) {
   3744   RenderWidgetHostView* rwh_view = view_->CreateViewForWidget(rvh);
   3745   // Can be NULL during tests.
   3746   if (rwh_view)
   3747     rwh_view->SetSize(GetView()->GetContainerSize());
   3748 }
   3749 
   3750 bool WebContentsImpl::IsHidden() {
   3751   return capturer_count_ == 0 && !should_normally_be_visible_;
   3752 }
   3753 
   3754 RenderFrameHostManager* WebContentsImpl::GetRenderManager() const {
   3755   return frame_tree_.root()->render_manager();
   3756 }
   3757 
   3758 RenderViewHostImpl* WebContentsImpl::GetRenderViewHostImpl() {
   3759   return static_cast<RenderViewHostImpl*>(GetRenderViewHost());
   3760 }
   3761 
   3762 BrowserPluginGuest* WebContentsImpl::GetBrowserPluginGuest() const {
   3763   return browser_plugin_guest_.get();
   3764 }
   3765 
   3766 void WebContentsImpl::SetBrowserPluginGuest(BrowserPluginGuest* guest) {
   3767   CHECK(!browser_plugin_guest_);
   3768   browser_plugin_guest_.reset(guest);
   3769 }
   3770 
   3771 BrowserPluginEmbedder* WebContentsImpl::GetBrowserPluginEmbedder() const {
   3772   return browser_plugin_embedder_.get();
   3773 }
   3774 
   3775 BrowserPluginGuestManager*
   3776     WebContentsImpl::GetBrowserPluginGuestManager() const {
   3777   return static_cast<BrowserPluginGuestManager*>(
   3778       GetBrowserContext()->GetUserData(
   3779           browser_plugin::kBrowserPluginGuestManagerKeyName));
   3780 }
   3781 
   3782 void WebContentsImpl::ClearPowerSaveBlockers(
   3783     RenderViewHost* render_view_host) {
   3784   STLDeleteValues(&power_save_blockers_[render_view_host]);
   3785   power_save_blockers_.erase(render_view_host);
   3786 }
   3787 
   3788 void WebContentsImpl::ClearAllPowerSaveBlockers() {
   3789   for (PowerSaveBlockerMap::iterator i(power_save_blockers_.begin());
   3790        i != power_save_blockers_.end(); ++i)
   3791     STLDeleteValues(&power_save_blockers_[i->first]);
   3792   power_save_blockers_.clear();
   3793 }
   3794 
   3795 gfx::Size WebContentsImpl::GetSizeForNewRenderView() const {
   3796   gfx::Size size;
   3797   if (delegate_)
   3798     size = delegate_->GetSizeForNewRenderView(this);
   3799   if (size.IsEmpty())
   3800     size = view_->GetContainerSize();
   3801   return size;
   3802 }
   3803 
   3804 void WebContentsImpl::OnFrameRemoved(
   3805     RenderViewHostImpl* render_view_host,
   3806     int64 frame_id) {
   3807    FOR_EACH_OBSERVER(WebContentsObserver, observers_,
   3808                      FrameDetached(render_view_host, frame_id));
   3809 }
   3810 
   3811 }  // namespace content
   3812