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