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