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