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