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.
5 #include "content/browser/web_contents/web_contents_impl.h"
9 #include "base/command_line.h"
10 #include "base/debug/trace_event.h"
11 #include "base/lazy_instance.h"
12 #include "base/logging.h"
13 #include "base/metrics/histogram.h"
14 #include "base/metrics/stats_counters.h"
15 #include "base/process/process.h"
16 #include "base/strings/string16.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/time/time.h"
21 #include "content/browser/browser_plugin/browser_plugin_embedder.h"
22 #include "content/browser/browser_plugin/browser_plugin_guest.h"
23 #include "content/browser/browser_plugin/browser_plugin_guest_manager.h"
24 #include "content/browser/child_process_security_policy_impl.h"
25 #include "content/browser/devtools/devtools_manager_impl.h"
26 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
27 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
28 #include "content/browser/download/download_stats.h"
29 #include "content/browser/download/mhtml_generation_manager.h"
30 #include "content/browser/download/save_package.h"
31 #include "content/browser/frame_host/cross_process_frame_connector.h"
32 #include "content/browser/frame_host/interstitial_page_impl.h"
33 #include "content/browser/frame_host/navigation_entry_impl.h"
34 #include "content/browser/frame_host/navigator_impl.h"
35 #include "content/browser/frame_host/render_frame_host_impl.h"
36 #include "content/browser/frame_host/render_widget_host_view_child_frame.h"
37 #include "content/browser/host_zoom_map_impl.h"
38 #include "content/browser/loader/resource_dispatcher_host_impl.h"
39 #include "content/browser/message_port_message_filter.h"
40 #include "content/browser/message_port_service.h"
41 #include "content/browser/power_save_blocker_impl.h"
42 #include "content/browser/renderer_host/render_process_host_impl.h"
43 #include "content/browser/renderer_host/render_view_host_impl.h"
44 #include "content/browser/renderer_host/render_widget_host_impl.h"
45 #include "content/browser/site_instance_impl.h"
46 #include "content/browser/web_contents/web_contents_view_guest.h"
47 #include "content/browser/webui/generic_handler.h"
48 #include "content/browser/webui/web_ui_controller_factory_registry.h"
49 #include "content/browser/webui/web_ui_impl.h"
50 #include "content/common/browser_plugin/browser_plugin_constants.h"
51 #include "content/common/browser_plugin/browser_plugin_messages.h"
52 #include "content/common/frame_messages.h"
53 #include "content/common/image_messages.h"
54 #include "content/common/ssl_status_serialization.h"
55 #include "content/common/view_messages.h"
56 #include "content/port/browser/render_view_host_delegate_view.h"
57 #include "content/port/browser/render_widget_host_view_port.h"
58 #include "content/public/browser/browser_context.h"
59 #include "content/public/browser/color_chooser.h"
60 #include "content/public/browser/content_browser_client.h"
61 #include "content/public/browser/devtools_agent_host.h"
62 #include "content/public/browser/download_manager.h"
63 #include "content/public/browser/download_url_parameters.h"
64 #include "content/public/browser/invalidate_type.h"
65 #include "content/public/browser/javascript_dialog_manager.h"
66 #include "content/public/browser/load_from_memory_cache_details.h"
67 #include "content/public/browser/load_notification_details.h"
68 #include "content/public/browser/navigation_details.h"
69 #include "content/public/browser/notification_details.h"
70 #include "content/public/browser/notification_service.h"
71 #include "content/public/browser/resource_request_details.h"
72 #include "content/public/browser/storage_partition.h"
73 #include "content/public/browser/user_metrics.h"
74 #include "content/public/browser/web_contents_delegate.h"
75 #include "content/public/browser/web_contents_observer.h"
76 #include "content/public/browser/web_contents_view.h"
77 #include "content/public/common/bindings_policy.h"
78 #include "content/public/common/content_constants.h"
79 #include "content/public/common/content_switches.h"
80 #include "content/public/common/page_zoom.h"
81 #include "content/public/common/result_codes.h"
82 #include "content/public/common/url_constants.h"
83 #include "content/public/common/url_utils.h"
84 #include "net/base/mime_util.h"
85 #include "net/base/net_util.h"
86 #include "net/http/http_cache.h"
87 #include "net/http/http_transaction_factory.h"
88 #include "net/url_request/url_request_context.h"
89 #include "net/url_request/url_request_context_getter.h"
90 #include "ui/base/layout.h"
91 #include "ui/gfx/display.h"
92 #include "ui/gfx/screen.h"
93 #include "ui/gl/gl_switches.h"
94 #include "webkit/common/webpreferences.h"
96 #if defined(OS_ANDROID)
97 #include "content/browser/android/date_time_chooser_android.h"
98 #include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
99 #include "content/browser/web_contents/web_contents_android.h"
100 #include "content/common/java_bridge_messages.h"
101 #include "content/public/browser/android/content_view_core.h"
104 #if defined(OS_MACOSX)
105 #include "base/mac/foundation_util.h"
106 #include "ui/gl/io_surface_support_mac.h"
109 // Cross-Site Navigations
111 // If a WebContentsImpl is told to navigate to a different web site (as
112 // determined by SiteInstance), it will replace its current RenderViewHost with
113 // a new RenderViewHost dedicated to the new SiteInstance. This works as
116 // - RVHM::Navigate determines whether the destination is cross-site, and if so,
117 // it creates a pending_render_view_host_.
118 // - The pending RVH is "suspended," so that no navigation messages are sent to
119 // its renderer until the beforeunload JavaScript handler has a chance to
120 // run in the current RVH.
121 // - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton)
122 // that it has a pending cross-site request. We will check this on the IO
123 // thread when deciding how to handle the response.
124 // - The current RVH runs its beforeunload handler. If it returns false, we
125 // cancel all the pending logic. Otherwise we allow the pending RVH to send
126 // the navigation request to its renderer.
127 // - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the
128 // main resource load on the pending RVH. It creates a
129 // CrossSiteResourceHandler to check whether a process swap is needed when
130 // the request is ready to commit.
131 // - When RDH receives a response, the BufferedResourceHandler determines
132 // whether it is a download. If so, it sends a message to the new renderer
133 // causing it to cancel the request, and the download proceeds. For now, the
134 // pending RVH remains until the next DidNavigate event for this
135 // WebContentsImpl. This isn't ideal, but it doesn't affect any functionality.
136 // - After RDH receives a response and determines that it is safe and not a
137 // download, the CrossSiteResourceHandler checks whether a process swap is
138 // needed (either because CrossSiteRequestManager has state for it or because
139 // a transfer was needed for a redirect).
140 // - If so, CrossSiteResourceHandler pauses the response to first run the old
141 // page's unload handler. It does this by asynchronously calling the
142 // OnCrossSiteResponse method of RenderFrameHostManager on the UI thread,
143 // which sends a SwapOut message to the current RVH.
144 // - Once the unload handler is finished, RVHM::SwappedOut checks if a transfer
145 // to a new process is needed, based on the stored pending_nav_params_. (This
146 // is independent of whether we started out with a cross-process navigation.)
147 // - If not, it just tells the ResourceDispatcherHost to resume the response
148 // to its current RenderViewHost.
149 // - If so, it cancels the current pending RenderViewHost and sets up a new
150 // navigation using RequestTransferURL. When the transferred request
151 // arrives in the ResourceDispatcherHost, we transfer the response and
153 // - The pending renderer sends a FrameNavigate message that invokes the
154 // DidNavigate method. This replaces the current RVH with the
156 // - The previous renderer is kept swapped out in RenderFrameHostManager in case
157 // the user goes back. The process only stays live if another tab is using
158 // it, but if so, the existing frame relationships will be maintained.
163 const char kDotGoogleDotCom[] = ".google.com";
165 #if defined(OS_ANDROID)
166 const char kWebContentsAndroidKey[] = "web_contents_android";
169 base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> >
170 g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
172 static int StartDownload(content::RenderViewHost* rvh,
175 uint32_t max_bitmap_size) {
176 static int g_next_image_download_id = 0;
177 rvh->Send(new ImageMsg_DownloadImage(rvh->GetRoutingID(),
178 ++g_next_image_download_id,
182 return g_next_image_download_id;
185 void NotifyCacheOnIO(
186 scoped_refptr<net::URLRequestContextGetter> request_context,
188 const std::string& http_method) {
189 request_context->GetURLRequestContext()->http_transaction_factory()->
190 GetCache()->OnExternalCacheHit(url, http_method);
193 // Helper function for retrieving all the sites in a frame tree.
194 bool CollectSites(BrowserContext* context,
195 std::set<GURL>* sites,
196 FrameTreeNode* node) {
197 sites->insert(SiteInstance::GetSiteForURL(context, node->current_url()));
201 bool ForEachFrameInternal(
202 const base::Callback<void(RenderFrameHost*)>& on_frame,
203 FrameTreeNode* node) {
204 on_frame.Run(node->current_frame_host());
208 void SendToAllFramesInternal(IPC::Message* message, RenderFrameHost* rfh) {
209 IPC::Message* message_copy = new IPC::Message(*message);
210 message_copy->set_routing_id(rfh->GetRoutingID());
211 rfh->Send(message_copy);
216 WebContents* WebContents::Create(const WebContents::CreateParams& params) {
217 return WebContentsImpl::CreateWithOpener(
218 params, static_cast<WebContentsImpl*>(params.opener));
221 WebContents* WebContents::CreateWithSessionStorage(
222 const WebContents::CreateParams& params,
223 const SessionStorageNamespaceMap& session_storage_namespace_map) {
224 WebContentsImpl* new_contents = new WebContentsImpl(
225 params.browser_context, NULL);
227 for (SessionStorageNamespaceMap::const_iterator it =
228 session_storage_namespace_map.begin();
229 it != session_storage_namespace_map.end();
231 new_contents->GetController()
232 .SetSessionStorageNamespace(it->first, it->second.get());
235 new_contents->Init(params);
239 void WebContentsImpl::AddCreatedCallback(const CreatedCallback& callback) {
240 g_created_callbacks.Get().push_back(callback);
243 void WebContentsImpl::RemoveCreatedCallback(const CreatedCallback& callback) {
244 for (size_t i = 0; i < g_created_callbacks.Get().size(); ++i) {
245 if (g_created_callbacks.Get().at(i).Equals(callback)) {
246 g_created_callbacks.Get().erase(g_created_callbacks.Get().begin() + i);
252 WebContents* WebContents::FromRenderViewHost(const RenderViewHost* rvh) {
253 return rvh->GetDelegate()->GetAsWebContents();
256 WebContents* WebContents::FromRenderFrameHost(RenderFrameHost* rfh) {
257 RenderFrameHostImpl* rfh_impl = static_cast<RenderFrameHostImpl*>(rfh);
260 return rfh_impl->delegate()->GetAsWebContents();
263 // WebContentsImpl::DestructionObserver ----------------------------------------
265 class WebContentsImpl::DestructionObserver : public WebContentsObserver {
267 DestructionObserver(WebContentsImpl* owner, WebContents* watched_contents)
268 : WebContentsObserver(watched_contents),
272 // WebContentsObserver:
273 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE {
274 owner_->OnWebContentsDestroyed(static_cast<WebContentsImpl*>(web_contents));
278 WebContentsImpl* owner_;
280 DISALLOW_COPY_AND_ASSIGN(DestructionObserver);
283 // WebContentsImpl -------------------------------------------------------------
285 WebContentsImpl::WebContentsImpl(
286 BrowserContext* browser_context,
287 WebContentsImpl* opener)
289 controller_(this, browser_context),
290 render_view_host_delegate_view_(NULL),
293 accessible_parent_(NULL),
295 frame_tree_(new NavigatorImpl(&controller_, this),
296 this, this, this, this),
298 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
299 crashed_error_code_(0),
300 waiting_for_response_(false),
301 load_state_(net::LOAD_STATE_IDLE, base::string16()),
304 displayed_insecure_content_(false),
306 should_normally_be_visible_(true),
307 is_being_destroyed_(false),
308 notify_disconnection_(false),
309 dialog_manager_(NULL),
310 is_showing_before_unload_dialog_(false),
311 last_active_time_(base::TimeTicks::Now()),
312 closed_by_user_gesture_(false),
313 minimum_zoom_percent_(static_cast<int>(kMinimumZoomFactor * 100)),
314 maximum_zoom_percent_(static_cast<int>(kMaximumZoomFactor * 100)),
315 temporary_zoom_settings_(false),
316 color_chooser_identifier_(0),
317 render_view_message_source_(NULL),
318 fullscreen_widget_routing_id_(MSG_ROUTING_NONE),
319 is_subframe_(false) {
320 for (size_t i = 0; i < g_created_callbacks.Get().size(); i++)
321 g_created_callbacks.Get().at(i).Run(this);
322 frame_tree_.SetFrameRemoveListener(
323 base::Bind(&WebContentsImpl::OnFrameRemoved,
324 base::Unretained(this)));
327 WebContentsImpl::~WebContentsImpl() {
328 is_being_destroyed_ = true;
330 ClearAllPowerSaveBlockers();
332 for (std::set<RenderWidgetHostImpl*>::iterator iter =
333 created_widgets_.begin(); iter != created_widgets_.end(); ++iter) {
334 (*iter)->DetachDelegate();
336 created_widgets_.clear();
338 // Clear out any JavaScript state.
340 dialog_manager_->WebContentsDestroyed(this);
343 color_chooser_->End();
345 NotifyDisconnected();
347 // Notify any observer that have a reference on this WebContents.
348 NotificationService::current()->Notify(
349 NOTIFICATION_WEB_CONTENTS_DESTROYED,
350 Source<WebContents>(this),
351 NotificationService::NoDetails());
353 RenderViewHost* pending_rvh = GetRenderManager()->pending_render_view_host();
355 FOR_EACH_OBSERVER(WebContentsObserver,
357 RenderViewDeleted(pending_rvh));
360 FOR_EACH_OBSERVER(WebContentsObserver,
362 RenderViewDeleted(GetRenderManager()->current_host()));
364 FOR_EACH_OBSERVER(WebContentsObserver,
366 WebContentsImplDestroyed());
370 STLDeleteContainerPairSecondPointers(destruction_observers_.begin(),
371 destruction_observers_.end());
374 WebContentsImpl* WebContentsImpl::CreateWithOpener(
375 const WebContents::CreateParams& params,
376 WebContentsImpl* opener) {
377 TRACE_EVENT0("browser", "WebContentsImpl::CreateWithOpener");
378 WebContentsImpl* new_contents = new WebContentsImpl(
379 params.browser_context, opener);
381 new_contents->Init(params);
386 BrowserPluginGuest* WebContentsImpl::CreateGuest(
387 BrowserContext* browser_context,
388 SiteInstance* site_instance,
389 int guest_instance_id,
390 scoped_ptr<base::DictionaryValue> extra_params) {
391 WebContentsImpl* new_contents = new WebContentsImpl(browser_context, NULL);
393 // This makes |new_contents| act as a guest.
394 // For more info, see comment above class BrowserPluginGuest.
395 BrowserPluginGuest::Create(
396 guest_instance_id, site_instance, new_contents, extra_params.Pass());
398 WebContents::CreateParams create_params(browser_context, site_instance);
399 new_contents->Init(create_params);
401 // We are instantiating a WebContents for browser plugin. Set its subframe bit
403 new_contents->is_subframe_ = true;
405 return new_contents->browser_plugin_guest_.get();
408 RenderFrameHostManager* WebContentsImpl::GetRenderManagerForTesting() {
409 return GetRenderManager();
412 bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
413 const IPC::Message& message) {
414 return OnMessageReceived(render_view_host, NULL, message);
417 bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
418 RenderFrameHost* render_frame_host,
419 const IPC::Message& message) {
420 DCHECK(render_view_host || render_frame_host);
422 static_cast<WebUIImpl*>(GetWebUI())->OnMessageReceived(message)) {
426 ObserverListBase<WebContentsObserver>::Iterator it(observers_);
427 WebContentsObserver* observer;
428 while ((observer = it.GetNext()) != NULL)
429 if (observer->OnMessageReceived(message))
432 // Message handlers should be aware of which
433 // RenderViewHost/RenderFrameHost sent the message, which is temporarily
434 // stored in render_(view|frame)_message_source_.
435 if (render_frame_host)
436 render_frame_message_source_ = render_frame_host;
438 render_view_message_source_ = render_view_host;
441 bool message_is_ok = true;
442 IPC_BEGIN_MESSAGE_MAP_EX(WebContentsImpl, message, message_is_ok)
443 IPC_MESSAGE_HANDLER(FrameHostMsg_PepperPluginHung, OnPepperPluginHung)
444 IPC_MESSAGE_HANDLER(FrameHostMsg_PluginCrashed, OnPluginCrashed)
445 IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache,
446 OnDidLoadResourceFromMemoryCache)
447 IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent,
448 OnDidDisplayInsecureContent)
449 IPC_MESSAGE_HANDLER(ViewHostMsg_DidRunInsecureContent,
450 OnDidRunInsecureContent)
451 IPC_MESSAGE_HANDLER(FrameHostMsg_DidFinishDocumentLoad,
452 OnDocumentLoadedInFrame)
453 IPC_MESSAGE_HANDLER(ViewHostMsg_DidFinishLoad, OnDidFinishLoad)
454 IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset, OnGoToEntryAtOffset)
455 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits, OnUpdateZoomLimits)
456 IPC_MESSAGE_HANDLER(ViewHostMsg_EnumerateDirectory, OnEnumerateDirectory)
457 IPC_MESSAGE_HANDLER(ViewHostMsg_JSOutOfMemory, OnJSOutOfMemory)
458 IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler,
459 OnRegisterProtocolHandler)
460 IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnFindReply)
461 IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed, OnAppCacheAccessed)
462 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenColorChooser, OnOpenColorChooser)
463 IPC_MESSAGE_HANDLER(ViewHostMsg_EndColorChooser, OnEndColorChooser)
464 IPC_MESSAGE_HANDLER(ViewHostMsg_SetSelectedColorInColorChooser,
465 OnSetSelectedColorInColorChooser)
466 IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnWebUISend)
467 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission,
468 OnRequestPpapiBrokerPermission)
469 IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_AllocateInstanceID,
470 OnBrowserPluginMessage(message))
471 IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_Attach,
472 OnBrowserPluginMessage(message))
473 IPC_MESSAGE_HANDLER(ImageHostMsg_DidDownloadImage, OnDidDownloadImage)
474 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFaviconURL, OnUpdateFaviconURL)
475 #if defined(OS_ANDROID)
476 IPC_MESSAGE_HANDLER(ViewHostMsg_FindMatchRects_Reply,
477 OnFindMatchRectsReply)
478 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog,
479 OnOpenDateTimeDialog)
480 IPC_MESSAGE_HANDLER_DELAY_REPLY(JavaBridgeHostMsg_GetChannelHandle,
481 OnJavaBridgeGetChannelHandle)
483 IPC_MESSAGE_HANDLER(ViewHostMsg_MediaPlayingNotification,
484 OnMediaPlayingNotification)
485 IPC_MESSAGE_HANDLER(ViewHostMsg_MediaPausedNotification,
486 OnMediaPausedNotification)
487 IPC_MESSAGE_HANDLER(ViewHostMsg_DidFirstVisuallyNonEmptyPaint,
488 OnFirstVisuallyNonEmptyPaint)
489 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowValidationMessage,
490 OnShowValidationMessage)
491 IPC_MESSAGE_HANDLER(ViewHostMsg_HideValidationMessage,
492 OnHideValidationMessage)
493 IPC_MESSAGE_HANDLER(ViewHostMsg_MoveValidationMessage,
494 OnMoveValidationMessage)
495 IPC_MESSAGE_UNHANDLED(handled = false)
496 IPC_END_MESSAGE_MAP_EX()
497 render_view_message_source_ = NULL;
498 render_frame_message_source_ = NULL;
500 if (!message_is_ok) {
501 RecordAction(base::UserMetricsAction("BadMessageTerminate_RVD"));
502 GetRenderProcessHost()->ReceivedBadMessage();
508 void WebContentsImpl::RunFileChooser(
509 RenderViewHost* render_view_host,
510 const FileChooserParams& params) {
512 delegate_->RunFileChooser(this, params);
515 NavigationControllerImpl& WebContentsImpl::GetController() {
519 const NavigationControllerImpl& WebContentsImpl::GetController() const {
523 BrowserContext* WebContentsImpl::GetBrowserContext() const {
524 return controller_.GetBrowserContext();
527 const GURL& WebContentsImpl::GetURL() const {
528 // We may not have a navigation entry yet.
529 NavigationEntry* entry = controller_.GetVisibleEntry();
530 return entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
533 const GURL& WebContentsImpl::GetVisibleURL() const {
534 // We may not have a navigation entry yet.
535 NavigationEntry* entry = controller_.GetVisibleEntry();
536 return entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
539 const GURL& WebContentsImpl::GetLastCommittedURL() const {
540 // We may not have a navigation entry yet.
541 NavigationEntry* entry = controller_.GetLastCommittedEntry();
542 return entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
545 WebContentsDelegate* WebContentsImpl::GetDelegate() {
549 void WebContentsImpl::SetDelegate(WebContentsDelegate* delegate) {
550 // TODO(cbentzel): remove this debugging code?
551 if (delegate == delegate_)
554 delegate_->Detach(this);
555 delegate_ = delegate;
557 delegate_->Attach(this);
558 // Ensure the visible RVH reflects the new delegate's preferences.
560 view_->SetOverscrollControllerEnabled(delegate->CanOverscrollContent());
564 RenderProcessHost* WebContentsImpl::GetRenderProcessHost() const {
565 RenderViewHostImpl* host = GetRenderManager()->current_host();
566 return host ? host->GetProcess() : NULL;
569 RenderFrameHost* WebContentsImpl::GetMainFrame() {
570 return frame_tree_.root()->current_frame_host();
573 void WebContentsImpl::ForEachFrame(
574 const base::Callback<void(RenderFrameHost*)>& on_frame) {
575 frame_tree_.ForEach(base::Bind(&ForEachFrameInternal, on_frame));
578 void WebContentsImpl::SendToAllFrames(IPC::Message* message) {
579 ForEachFrame(base::Bind(&SendToAllFramesInternal, message));
583 RenderViewHost* WebContentsImpl::GetRenderViewHost() const {
584 return GetRenderManager()->current_host();
587 void WebContentsImpl::GetRenderViewHostAtPosition(
590 const base::Callback<void(RenderViewHost*, int, int)>& callback) {
591 BrowserPluginEmbedder* embedder = GetBrowserPluginEmbedder();
593 embedder->GetRenderViewHostAtPosition(x, y, callback);
595 callback.Run(GetRenderViewHost(), x, y);
598 WebContents* WebContentsImpl::GetEmbedderWebContents() const {
599 BrowserPluginGuest* guest = GetBrowserPluginGuest();
601 return guest->embedder_web_contents();
605 int WebContentsImpl::GetEmbeddedInstanceID() const {
606 BrowserPluginGuest* guest = GetBrowserPluginGuest();
608 return guest->instance_id();
612 int WebContentsImpl::GetRoutingID() const {
613 if (!GetRenderViewHost())
614 return MSG_ROUTING_NONE;
616 return GetRenderViewHost()->GetRoutingID();
619 int WebContentsImpl::GetFullscreenWidgetRoutingID() const {
620 return fullscreen_widget_routing_id_;
623 RenderWidgetHostView* WebContentsImpl::GetRenderWidgetHostView() const {
624 return GetRenderManager()->GetRenderWidgetHostView();
627 RenderWidgetHostViewPort* WebContentsImpl::GetRenderWidgetHostViewPort() const {
628 BrowserPluginGuest* guest = GetBrowserPluginGuest();
629 if (guest && guest->embedder_web_contents()) {
630 return guest->embedder_web_contents()->GetRenderWidgetHostViewPort();
632 return RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
635 RenderWidgetHostView* WebContentsImpl::GetFullscreenRenderWidgetHostView()
637 RenderWidgetHost* const widget_host =
638 RenderWidgetHostImpl::FromID(GetRenderProcessHost()->GetID(),
639 GetFullscreenWidgetRoutingID());
640 return widget_host ? widget_host->GetView() : NULL;
643 WebContentsView* WebContentsImpl::GetView() const {
647 WebUI* WebContentsImpl::CreateWebUI(const GURL& url) {
648 WebUIImpl* web_ui = new WebUIImpl(this);
649 WebUIController* controller = WebUIControllerFactoryRegistry::GetInstance()->
650 CreateWebUIControllerForURL(web_ui, url);
652 web_ui->AddMessageHandler(new GenericHandler());
653 web_ui->SetController(controller);
661 WebUI* WebContentsImpl::GetWebUI() const {
662 return GetRenderManager()->web_ui() ? GetRenderManager()->web_ui()
663 : GetRenderManager()->pending_web_ui();
666 WebUI* WebContentsImpl::GetCommittedWebUI() const {
667 return GetRenderManager()->web_ui();
670 void WebContentsImpl::SetUserAgentOverride(const std::string& override) {
671 if (GetUserAgentOverride() == override)
674 renderer_preferences_.user_agent_override = override;
676 // Send the new override string to the renderer.
677 RenderViewHost* host = GetRenderViewHost();
679 host->SyncRendererPrefs();
681 // Reload the page if a load is currently in progress to avoid having
682 // different parts of the page loaded using different user agents.
683 NavigationEntry* entry = controller_.GetVisibleEntry();
684 if (is_loading_ && entry != NULL && entry->GetIsOverridingUserAgent())
685 controller_.ReloadIgnoringCache(true);
687 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
688 UserAgentOverrideSet(override));
691 const std::string& WebContentsImpl::GetUserAgentOverride() const {
692 return renderer_preferences_.user_agent_override;
696 void WebContentsImpl::SetParentNativeViewAccessible(
697 gfx::NativeViewAccessible accessible_parent) {
698 accessible_parent_ = accessible_parent;
699 if (GetRenderViewHost())
700 GetRenderViewHostImpl()->SetParentNativeViewAccessible(accessible_parent);
704 const base::string16& WebContentsImpl::GetTitle() const {
705 // Transient entries take precedence. They are used for interstitial pages
706 // that are shown on top of existing pages.
707 NavigationEntry* entry = controller_.GetTransientEntry();
708 std::string accept_languages =
709 GetContentClient()->browser()->GetAcceptLangs(
710 GetBrowserContext());
712 return entry->GetTitleForDisplay(accept_languages);
714 WebUI* our_web_ui = GetRenderManager()->pending_web_ui() ?
715 GetRenderManager()->pending_web_ui() : GetRenderManager()->web_ui();
717 // Don't override the title in view source mode.
718 entry = controller_.GetVisibleEntry();
719 if (!(entry && entry->IsViewSourceMode())) {
720 // Give the Web UI the chance to override our title.
721 const base::string16& title = our_web_ui->GetOverriddenTitle();
727 // We use the title for the last committed entry rather than a pending
728 // navigation entry. For example, when the user types in a URL, we want to
729 // keep the old page's title until the new load has committed and we get a new
731 entry = controller_.GetLastCommittedEntry();
733 // We make an exception for initial navigations.
734 if (controller_.IsInitialNavigation()) {
735 // We only want to use the title from the visible entry in one of two cases:
736 // 1. There's already a committed entry for an initial navigation, in which
737 // case we are doing a history navigation in a new tab (e.g., Ctrl+Back).
738 // 2. The pending entry has been explicitly assigned a title to display.
740 // If there's no last committed entry and no assigned title, we should fall
741 // back to |page_title_when_no_navigation_entry_| rather than showing the
744 (controller_.GetVisibleEntry() &&
745 !controller_.GetVisibleEntry()->GetTitle().empty())) {
746 entry = controller_.GetVisibleEntry();
751 return entry->GetTitleForDisplay(accept_languages);
754 // |page_title_when_no_navigation_entry_| is finally used
755 // if no title cannot be retrieved.
756 return page_title_when_no_navigation_entry_;
759 int32 WebContentsImpl::GetMaxPageID() {
760 return GetMaxPageIDForSiteInstance(GetSiteInstance());
763 int32 WebContentsImpl::GetMaxPageIDForSiteInstance(
764 SiteInstance* site_instance) {
765 if (max_page_ids_.find(site_instance->GetId()) == max_page_ids_.end())
766 max_page_ids_[site_instance->GetId()] = -1;
768 return max_page_ids_[site_instance->GetId()];
771 void WebContentsImpl::UpdateMaxPageID(int32 page_id) {
772 UpdateMaxPageIDForSiteInstance(GetSiteInstance(), page_id);
775 void WebContentsImpl::UpdateMaxPageIDForSiteInstance(
776 SiteInstance* site_instance, int32 page_id) {
777 if (GetMaxPageIDForSiteInstance(site_instance) < page_id)
778 max_page_ids_[site_instance->GetId()] = page_id;
781 void WebContentsImpl::CopyMaxPageIDsFrom(WebContents* web_contents) {
782 WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents);
783 max_page_ids_ = contents->max_page_ids_;
786 SiteInstance* WebContentsImpl::GetSiteInstance() const {
787 return GetRenderManager()->current_host()->GetSiteInstance();
790 SiteInstance* WebContentsImpl::GetPendingSiteInstance() const {
791 RenderViewHost* dest_rvh = GetRenderManager()->pending_render_view_host() ?
792 GetRenderManager()->pending_render_view_host() :
793 GetRenderManager()->current_host();
794 return dest_rvh->GetSiteInstance();
797 bool WebContentsImpl::IsLoading() const {
801 bool WebContentsImpl::IsWaitingForResponse() const {
802 return waiting_for_response_;
805 const net::LoadStateWithParam& WebContentsImpl::GetLoadState() const {
809 const base::string16& WebContentsImpl::GetLoadStateHost() const {
810 return load_state_host_;
813 uint64 WebContentsImpl::GetUploadSize() const {
817 uint64 WebContentsImpl::GetUploadPosition() const {
818 return upload_position_;
821 std::set<GURL> WebContentsImpl::GetSitesInTab() const {
822 std::set<GURL> sites;
823 frame_tree_.ForEach(base::Bind(&CollectSites,
824 base::Unretained(GetBrowserContext()),
825 base::Unretained(&sites)));
829 const std::string& WebContentsImpl::GetEncoding() const {
833 bool WebContentsImpl::DisplayedInsecureContent() const {
834 return displayed_insecure_content_;
837 void WebContentsImpl::IncrementCapturerCount(const gfx::Size& capture_size) {
838 DCHECK(!is_being_destroyed_);
840 DVLOG(1) << "There are now " << capturer_count_
841 << " capturing(s) of WebContentsImpl@" << this;
843 // Note: This provides a hint to upstream code to size the views optimally
844 // for quality (e.g., to avoid scaling).
845 if (!capture_size.IsEmpty() && preferred_size_for_capture_.IsEmpty()) {
846 preferred_size_for_capture_ = capture_size;
847 OnPreferredSizeChanged(preferred_size_);
851 void WebContentsImpl::DecrementCapturerCount() {
853 DVLOG(1) << "There are now " << capturer_count_
854 << " capturing(s) of WebContentsImpl@" << this;
855 DCHECK_LE(0, capturer_count_);
857 if (is_being_destroyed_)
860 if (capturer_count_ == 0) {
861 const gfx::Size old_size = preferred_size_for_capture_;
862 preferred_size_for_capture_ = gfx::Size();
863 OnPreferredSizeChanged(old_size);
867 DVLOG(1) << "Executing delayed WasHidden().";
872 int WebContentsImpl::GetCapturerCount() const {
873 return capturer_count_;
876 bool WebContentsImpl::IsCrashed() const {
877 return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED ||
878 crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION ||
879 crashed_status_ == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
882 void WebContentsImpl::SetIsCrashed(base::TerminationStatus status,
884 if (status == crashed_status_)
887 crashed_status_ = status;
888 crashed_error_code_ = error_code;
889 NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
892 base::TerminationStatus WebContentsImpl::GetCrashedStatus() const {
893 return crashed_status_;
896 bool WebContentsImpl::IsBeingDestroyed() const {
897 return is_being_destroyed_;
900 void WebContentsImpl::NotifyNavigationStateChanged(unsigned changed_flags) {
902 delegate_->NavigationStateChanged(this, changed_flags);
905 base::TimeTicks WebContentsImpl::GetLastActiveTime() const {
906 return last_active_time_;
909 void WebContentsImpl::WasShown() {
910 controller_.SetActive(true);
911 RenderWidgetHostViewPort* rwhv =
912 RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
915 #if defined(OS_MACOSX)
916 rwhv->SetActive(true);
920 last_active_time_ = base::TimeTicks::Now();
922 // The resize rect might have changed while this was inactive -- send the new
923 // one to make sure it's up to date.
924 RenderViewHostImpl* rvh =
925 static_cast<RenderViewHostImpl*>(GetRenderViewHost());
927 rvh->ResizeRectChanged(GetRootWindowResizerRect());
930 FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasShown());
932 should_normally_be_visible_ = true;
935 void WebContentsImpl::WasHidden() {
936 // If there are entities capturing screenshots or video (e.g., mirroring),
937 // don't activate the "disable rendering" optimization.
938 if (capturer_count_ == 0) {
939 // |GetRenderViewHost()| can be NULL if the user middle clicks a link to
940 // open a tab in the background, then closes the tab before selecting it.
941 // This is because closing the tab calls WebContentsImpl::Destroy(), which
942 // removes the |GetRenderViewHost()|; then when we actually destroy the
943 // window, OnWindowPosChanged() notices and calls WasHidden() (which
945 RenderWidgetHostViewPort* rwhv =
946 RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
951 FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasHidden());
953 should_normally_be_visible_ = false;
956 bool WebContentsImpl::NeedToFireBeforeUnload() {
957 // TODO(creis): Should we fire even for interstitial pages?
958 return WillNotifyDisconnection() &&
959 !ShowingInterstitialPage() &&
960 !static_cast<RenderViewHostImpl*>(
961 GetRenderViewHost())->SuddenTerminationAllowed();
964 void WebContentsImpl::Stop() {
965 GetRenderManager()->Stop();
966 FOR_EACH_OBSERVER(WebContentsObserver, observers_, NavigationStopped());
969 WebContents* WebContentsImpl::Clone() {
970 // We use our current SiteInstance since the cloned entry will use it anyway.
971 // We pass our own opener so that the cloned page can access it if it was
973 CreateParams create_params(GetBrowserContext(), GetSiteInstance());
974 create_params.initial_size = view_->GetContainerSize();
975 WebContentsImpl* tc = CreateWithOpener(create_params, opener_);
976 tc->GetController().CopyStateFrom(controller_);
977 FOR_EACH_OBSERVER(WebContentsObserver,
979 DidCloneToNewWebContents(this, tc));
983 void WebContentsImpl::Observe(int type,
984 const NotificationSource& source,
985 const NotificationDetails& details) {
987 case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED: {
988 RenderWidgetHost* host = Source<RenderWidgetHost>(source).ptr();
989 for (PendingWidgetViews::iterator i = pending_widget_views_.begin();
990 i != pending_widget_views_.end(); ++i) {
991 if (host->GetView() == i->second) {
992 pending_widget_views_.erase(i);
1003 WebContents* WebContentsImpl::GetWebContents() {
1007 void WebContentsImpl::Init(const WebContents::CreateParams& params) {
1008 // This is set before initializing the render manager since
1009 // RenderFrameHostManager::Init calls back into us via its delegate to ask if
1010 // it should be hidden.
1011 should_normally_be_visible_ = !params.initially_hidden;
1013 GetRenderManager()->Init(
1014 params.browser_context, params.site_instance, params.routing_id,
1015 params.main_frame_routing_id);
1017 view_.reset(GetContentClient()->browser()->
1018 OverrideCreateWebContentsView(this, &render_view_host_delegate_view_));
1020 CHECK(render_view_host_delegate_view_);
1022 WebContentsViewDelegate* delegate =
1023 GetContentClient()->browser()->GetWebContentsViewDelegate(this);
1025 if (browser_plugin_guest_) {
1026 scoped_ptr<WebContentsViewPort> platform_view(CreateWebContentsView(
1027 this, delegate, &render_view_host_delegate_view_));
1029 WebContentsViewGuest* rv = new WebContentsViewGuest(
1030 this, browser_plugin_guest_.get(), platform_view.Pass(),
1031 render_view_host_delegate_view_);
1032 render_view_host_delegate_view_ = rv;
1035 // Regular WebContentsView.
1036 view_.reset(CreateWebContentsView(
1037 this, delegate, &render_view_host_delegate_view_));
1039 CHECK(render_view_host_delegate_view_);
1043 gfx::Size initial_size = params.initial_size;
1044 view_->CreateView(initial_size, params.context);
1046 // Listen for whether our opener gets destroyed.
1048 AddDestructionObserver(opener_);
1050 registrar_.Add(this,
1051 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
1052 NotificationService::AllBrowserContextsAndSources());
1053 #if defined(OS_ANDROID)
1054 java_bridge_dispatcher_host_manager_.reset(
1055 new JavaBridgeDispatcherHostManager(this));
1056 date_time_chooser_.reset(new DateTimeChooserAndroid());
1060 void WebContentsImpl::OnWebContentsDestroyed(WebContentsImpl* web_contents) {
1061 RemoveDestructionObserver(web_contents);
1063 // Clear the opener if it has been closed.
1064 if (web_contents == opener_) {
1068 // Clear a pending contents that has been closed before being shown.
1069 for (PendingContents::iterator iter = pending_contents_.begin();
1070 iter != pending_contents_.end();
1072 if (iter->second != web_contents)
1074 pending_contents_.erase(iter);
1080 void WebContentsImpl::AddDestructionObserver(WebContentsImpl* web_contents) {
1081 if (!ContainsKey(destruction_observers_, web_contents)) {
1082 destruction_observers_[web_contents] =
1083 new DestructionObserver(this, web_contents);
1087 void WebContentsImpl::RemoveDestructionObserver(WebContentsImpl* web_contents) {
1088 DestructionObservers::iterator iter =
1089 destruction_observers_.find(web_contents);
1090 if (iter != destruction_observers_.end()) {
1091 delete destruction_observers_[web_contents];
1092 destruction_observers_.erase(iter);
1096 void WebContentsImpl::AddObserver(WebContentsObserver* observer) {
1097 observers_.AddObserver(observer);
1100 void WebContentsImpl::RemoveObserver(WebContentsObserver* observer) {
1101 observers_.RemoveObserver(observer);
1104 void WebContentsImpl::Activate() {
1106 delegate_->ActivateContents(this);
1109 void WebContentsImpl::Deactivate() {
1111 delegate_->DeactivateContents(this);
1114 void WebContentsImpl::LostCapture() {
1116 delegate_->LostCapture();
1119 void WebContentsImpl::RenderWidgetDeleted(
1120 RenderWidgetHostImpl* render_widget_host) {
1121 if (is_being_destroyed_) {
1122 // |created_widgets_| might have been destroyed.
1126 std::set<RenderWidgetHostImpl*>::iterator iter =
1127 created_widgets_.find(render_widget_host);
1128 if (iter != created_widgets_.end())
1129 created_widgets_.erase(iter);
1131 if (render_widget_host &&
1132 render_widget_host->GetRoutingID() == fullscreen_widget_routing_id_) {
1133 if (delegate_ && delegate_->EmbedsFullscreenWidget())
1134 delegate_->ToggleFullscreenModeForTab(this, false);
1135 FOR_EACH_OBSERVER(WebContentsObserver,
1137 DidDestroyFullscreenWidget(
1138 fullscreen_widget_routing_id_));
1139 fullscreen_widget_routing_id_ = MSG_ROUTING_NONE;
1143 bool WebContentsImpl::PreHandleKeyboardEvent(
1144 const NativeWebKeyboardEvent& event,
1145 bool* is_keyboard_shortcut) {
1147 delegate_->PreHandleKeyboardEvent(this, event, is_keyboard_shortcut);
1150 void WebContentsImpl::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
1151 if (browser_plugin_embedder_ &&
1152 browser_plugin_embedder_->HandleKeyboardEvent(event)) {
1157 delegate_->HandleKeyboardEvent(this, event);
1160 bool WebContentsImpl::PreHandleWheelEvent(
1161 const blink::WebMouseWheelEvent& event) {
1162 #if !defined(OS_MACOSX)
1163 // On platforms other than Mac, control+mousewheel changes zoom. On Mac, this
1164 // isn't done for two reasons:
1165 // -the OS already has a gesture to do this through pinch-zoom
1166 // -if a user starts an inertial scroll, let's go, and presses control
1167 // (i.e. control+tab) then the OS's buffered scroll events will come in
1168 // with control key set which isn't what the user wants
1170 event.wheelTicksY &&
1171 (event.modifiers & blink::WebInputEvent::ControlKey)) {
1172 delegate_->ContentsZoomChange(event.wheelTicksY > 0);
1180 bool WebContentsImpl::PreHandleGestureEvent(
1181 const blink::WebGestureEvent& event) {
1182 return delegate_ && delegate_->PreHandleGestureEvent(this, event);
1186 gfx::NativeViewAccessible WebContentsImpl::GetParentNativeViewAccessible() {
1187 return accessible_parent_;
1191 void WebContentsImpl::HandleMouseDown() {
1193 delegate_->HandleMouseDown();
1196 void WebContentsImpl::HandleMouseUp() {
1198 delegate_->HandleMouseUp();
1201 void WebContentsImpl::HandlePointerActivate() {
1203 delegate_->HandlePointerActivate();
1206 void WebContentsImpl::HandleGestureBegin() {
1208 delegate_->HandleGestureBegin();
1211 void WebContentsImpl::HandleGestureEnd() {
1213 delegate_->HandleGestureEnd();
1216 void WebContentsImpl::ToggleFullscreenMode(bool enter_fullscreen) {
1217 // This method is being called to enter or leave renderer-initiated fullscreen
1218 // mode. Either way, make sure any existing fullscreen widget is shut down
1220 RenderWidgetHostView* const widget_view = GetFullscreenRenderWidgetHostView();
1222 RenderWidgetHostImpl::From(widget_view->GetRenderWidgetHost())->Shutdown();
1225 delegate_->ToggleFullscreenModeForTab(this, enter_fullscreen);
1228 bool WebContentsImpl::IsFullscreenForCurrentTab() const {
1229 return delegate_ ? delegate_->IsFullscreenForTabOrPending(this) : false;
1232 void WebContentsImpl::RequestToLockMouse(bool user_gesture,
1233 bool last_unlocked_by_target) {
1235 delegate_->RequestToLockMouse(this, user_gesture, last_unlocked_by_target);
1237 GotResponseToLockMouseRequest(false);
1241 void WebContentsImpl::LostMouseLock() {
1243 delegate_->LostMouseLock();
1246 void WebContentsImpl::CreateNewWindow(
1247 int render_process_id,
1249 int main_frame_route_id,
1250 const ViewHostMsg_CreateWindow_Params& params,
1251 SessionStorageNamespace* session_storage_namespace) {
1252 // We usually create the new window in the same BrowsingInstance (group of
1253 // script-related windows), by passing in the current SiteInstance. However,
1254 // if the opener is being suppressed (in a non-guest), we create a new
1255 // SiteInstance in its own BrowsingInstance.
1256 bool is_guest = GetRenderProcessHost()->IsGuest();
1258 // If the opener is to be suppressed, the new window can be in any process.
1259 // Since routing ids are process specific, we must not have one passed in
1260 // as argument here.
1261 DCHECK(!params.opener_suppressed || route_id == MSG_ROUTING_NONE);
1263 scoped_refptr<SiteInstance> site_instance =
1264 params.opener_suppressed && !is_guest ?
1265 SiteInstance::CreateForURL(GetBrowserContext(), params.target_url) :
1268 // A message to create a new window can only come from the active process for
1269 // this WebContentsImpl instance. If any other process sends the request,
1270 // it is invalid and the process must be terminated.
1271 if (GetRenderProcessHost()->GetID() != render_process_id) {
1272 base::ProcessHandle process_handle =
1273 RenderProcessHost::FromID(render_process_id)->GetHandle();
1274 if (process_handle != base::kNullProcessHandle) {
1276 base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWindow"));
1277 base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false);
1282 // We must assign the SessionStorageNamespace before calling Init().
1284 // http://crbug.com/142685
1285 const std::string& partition_id =
1286 GetContentClient()->browser()->
1287 GetStoragePartitionIdForSite(GetBrowserContext(),
1288 site_instance->GetSiteURL());
1289 StoragePartition* partition = BrowserContext::GetStoragePartition(
1290 GetBrowserContext(), site_instance.get());
1291 DOMStorageContextWrapper* dom_storage_context =
1292 static_cast<DOMStorageContextWrapper*>(partition->GetDOMStorageContext());
1293 SessionStorageNamespaceImpl* session_storage_namespace_impl =
1294 static_cast<SessionStorageNamespaceImpl*>(session_storage_namespace);
1295 CHECK(session_storage_namespace_impl->IsFromContext(dom_storage_context));
1298 !delegate_->ShouldCreateWebContents(this,
1300 params.window_container_type,
1304 session_storage_namespace)) {
1305 if (route_id != MSG_ROUTING_NONE &&
1306 !RenderViewHost::FromID(render_process_id, route_id)) {
1307 // If the embedder didn't create a WebContents for this route, we need to
1308 // delete the RenderView that had already been created.
1309 Send(new ViewMsg_Close(route_id));
1311 GetRenderViewHost()->GetProcess()->ResumeRequestsForView(route_id);
1312 GetRenderViewHost()->GetProcess()->ResumeRequestsForView(
1313 main_frame_route_id);
1317 // Create the new web contents. This will automatically create the new
1318 // WebContentsView. In the future, we may want to create the view separately.
1319 WebContentsImpl* new_contents =
1320 new WebContentsImpl(GetBrowserContext(),
1321 params.opener_suppressed ? NULL : this);
1323 new_contents->GetController().SetSessionStorageNamespace(
1325 session_storage_namespace);
1326 CreateParams create_params(GetBrowserContext(), site_instance.get());
1327 create_params.routing_id = route_id;
1328 create_params.main_frame_routing_id = main_frame_route_id;
1330 create_params.context = view_->GetNativeView();
1331 create_params.initial_size = view_->GetContainerSize();
1333 // This makes |new_contents| act as a guest.
1334 // For more info, see comment above class BrowserPluginGuest.
1335 int instance_id = GetBrowserPluginGuestManager()->get_next_instance_id();
1336 WebContentsImpl* new_contents_impl =
1337 static_cast<WebContentsImpl*>(new_contents);
1338 BrowserPluginGuest::CreateWithOpener(instance_id,
1339 new_contents_impl->opener() != NULL,
1341 GetBrowserPluginGuest());
1343 if (params.disposition == NEW_BACKGROUND_TAB)
1344 create_params.initially_hidden = true;
1345 new_contents->Init(create_params);
1347 // Save the window for later if we're not suppressing the opener (since it
1348 // will be shown immediately).
1349 if (!params.opener_suppressed) {
1351 WebContentsViewPort* new_view = new_contents->view_.get();
1353 // TODO(brettw): It seems bogus that we have to call this function on the
1354 // newly created object and give it one of its own member variables.
1355 new_view->CreateViewForWidget(new_contents->GetRenderViewHost());
1357 // Save the created window associated with the route so we can show it
1359 DCHECK_NE(MSG_ROUTING_NONE, route_id);
1360 pending_contents_[route_id] = new_contents;
1361 AddDestructionObserver(new_contents);
1365 delegate_->WebContentsCreated(
1366 this, params.opener_frame_id, params.frame_name,
1367 params.target_url, new_contents);
1370 if (params.opener_suppressed) {
1371 // When the opener is suppressed, the original renderer cannot access the
1372 // new window. As a result, we need to show and navigate the window here.
1373 bool was_blocked = false;
1375 gfx::Rect initial_pos;
1376 delegate_->AddNewContents(
1377 this, new_contents, params.disposition, initial_pos,
1378 params.user_gesture, &was_blocked);
1381 OpenURLParams open_params(params.target_url,
1384 PAGE_TRANSITION_LINK,
1385 true /* is_renderer_initiated */);
1386 open_params.user_gesture = params.user_gesture;
1387 new_contents->OpenURL(open_params);
1392 void WebContentsImpl::CreateNewWidget(int render_process_id,
1394 blink::WebPopupType popup_type) {
1395 CreateNewWidget(render_process_id, route_id, false, popup_type);
1398 void WebContentsImpl::CreateNewFullscreenWidget(int render_process_id,
1400 CreateNewWidget(render_process_id, route_id, true, blink::WebPopupTypeNone);
1403 void WebContentsImpl::CreateNewWidget(int render_process_id,
1406 blink::WebPopupType popup_type) {
1407 RenderProcessHost* process = GetRenderProcessHost();
1408 // A message to create a new widget can only come from the active process for
1409 // this WebContentsImpl instance. If any other process sends the request,
1410 // it is invalid and the process must be terminated.
1411 if (process->GetID() != render_process_id) {
1412 base::ProcessHandle process_handle =
1413 RenderProcessHost::FromID(render_process_id)->GetHandle();
1414 if (process_handle != base::kNullProcessHandle) {
1416 base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWidget"));
1417 base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false);
1422 RenderWidgetHostImpl* widget_host =
1423 new RenderWidgetHostImpl(this, process, route_id, IsHidden());
1424 created_widgets_.insert(widget_host);
1426 RenderWidgetHostViewPort* widget_view = RenderWidgetHostViewPort::FromRWHV(
1427 view_->CreateViewForPopupWidget(widget_host));
1430 if (!is_fullscreen) {
1431 // Popups should not get activated.
1432 widget_view->SetPopupType(popup_type);
1434 // Save the created widget associated with the route so we can show it later.
1435 pending_widget_views_[route_id] = widget_view;
1437 #if defined(OS_MACOSX)
1438 // A RenderWidgetHostViewMac has lifetime scoped to the view. We'll retain it
1439 // to allow it to survive the trip without being hosted.
1440 base::mac::NSObjectRetain(widget_view->GetNativeView());
1444 void WebContentsImpl::ShowCreatedWindow(int route_id,
1445 WindowOpenDisposition disposition,
1446 const gfx::Rect& initial_pos,
1447 bool user_gesture) {
1448 WebContentsImpl* contents = GetCreatedWindow(route_id);
1450 WebContentsDelegate* delegate = GetDelegate();
1452 delegate->AddNewContents(
1453 this, contents, disposition, initial_pos, user_gesture, NULL);
1458 void WebContentsImpl::ShowCreatedWidget(int route_id,
1459 const gfx::Rect& initial_pos) {
1460 ShowCreatedWidget(route_id, false, initial_pos);
1463 void WebContentsImpl::ShowCreatedFullscreenWidget(int route_id) {
1464 ShowCreatedWidget(route_id, true, gfx::Rect());
1467 void WebContentsImpl::ShowCreatedWidget(int route_id,
1469 const gfx::Rect& initial_pos) {
1470 RenderWidgetHostViewPort* widget_host_view =
1471 RenderWidgetHostViewPort::FromRWHV(GetCreatedWidget(route_id));
1472 if (!widget_host_view)
1474 if (is_fullscreen) {
1475 DCHECK_EQ(MSG_ROUTING_NONE, fullscreen_widget_routing_id_);
1476 fullscreen_widget_routing_id_ = route_id;
1477 if (delegate_ && delegate_->EmbedsFullscreenWidget()) {
1478 widget_host_view->InitAsChild(GetRenderWidgetHostView()->GetNativeView());
1479 delegate_->ToggleFullscreenModeForTab(this, true);
1481 widget_host_view->InitAsFullscreen(GetRenderWidgetHostViewPort());
1483 FOR_EACH_OBSERVER(WebContentsObserver,
1485 DidShowFullscreenWidget(route_id));
1486 if (!widget_host_view->HasFocus())
1487 widget_host_view->Focus();
1489 widget_host_view->InitAsPopup(GetRenderWidgetHostViewPort(), initial_pos);
1492 RenderWidgetHostImpl* render_widget_host_impl =
1493 RenderWidgetHostImpl::From(widget_host_view->GetRenderWidgetHost());
1494 render_widget_host_impl->Init();
1495 // Only allow privileged mouse lock for fullscreen render widget, which is
1496 // used to implement Pepper Flash fullscreen.
1497 render_widget_host_impl->set_allow_privileged_mouse_lock(is_fullscreen);
1499 #if defined(OS_MACOSX)
1500 // A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's
1501 // properly embedded (or purposefully ignored) we can release the retain we
1502 // took in CreateNewWidget().
1503 base::mac::NSObjectRelease(widget_host_view->GetNativeView());
1507 WebContentsImpl* WebContentsImpl::GetCreatedWindow(int route_id) {
1508 PendingContents::iterator iter = pending_contents_.find(route_id);
1510 // Certain systems can block the creation of new windows. If we didn't succeed
1511 // in creating one, just return NULL.
1512 if (iter == pending_contents_.end()) {
1516 WebContentsImpl* new_contents = iter->second;
1517 pending_contents_.erase(route_id);
1518 RemoveDestructionObserver(new_contents);
1520 // Don't initialize the guest WebContents immediately.
1521 if (new_contents->GetRenderProcessHost()->IsGuest())
1522 return new_contents;
1524 if (!new_contents->GetRenderProcessHost()->HasConnection() ||
1525 !new_contents->GetRenderViewHost()->GetView())
1528 // TODO(brettw): It seems bogus to reach into here and initialize the host.
1529 static_cast<RenderViewHostImpl*>(new_contents->GetRenderViewHost())->Init();
1530 return new_contents;
1533 RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int route_id) {
1534 PendingWidgetViews::iterator iter = pending_widget_views_.find(route_id);
1535 if (iter == pending_widget_views_.end()) {
1540 RenderWidgetHostView* widget_host_view = iter->second;
1541 pending_widget_views_.erase(route_id);
1543 RenderWidgetHost* widget_host = widget_host_view->GetRenderWidgetHost();
1544 if (!widget_host->GetProcess()->HasConnection()) {
1545 // The view has gone away or the renderer crashed. Nothing to do.
1549 return widget_host_view;
1552 void WebContentsImpl::RequestMediaAccessPermission(
1553 const MediaStreamRequest& request,
1554 const MediaResponseCallback& callback) {
1556 delegate_->RequestMediaAccessPermission(this, request, callback);
1558 callback.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
1561 SessionStorageNamespace* WebContentsImpl::GetSessionStorageNamespace(
1562 SiteInstance* instance) {
1563 return controller_.GetSessionStorageNamespace(instance);
1566 FrameTree* WebContentsImpl::GetFrameTree() {
1567 return &frame_tree_;
1570 void WebContentsImpl::OnShowValidationMessage(
1571 const gfx::Rect& anchor_in_root_view,
1572 const base::string16& main_text,
1573 const base::string16& sub_text) {
1575 delegate_->ShowValidationMessage(
1576 this, anchor_in_root_view, main_text, sub_text);
1579 void WebContentsImpl::OnHideValidationMessage() {
1581 delegate_->HideValidationMessage(this);
1584 void WebContentsImpl::OnMoveValidationMessage(
1585 const gfx::Rect& anchor_in_root_view) {
1587 delegate_->MoveValidationMessage(this, anchor_in_root_view);
1590 void WebContentsImpl::DidSendScreenRects(RenderWidgetHostImpl* rwh) {
1591 if (browser_plugin_embedder_)
1592 browser_plugin_embedder_->DidSendScreenRects();
1595 void WebContentsImpl::UpdatePreferredSize(const gfx::Size& pref_size) {
1596 const gfx::Size old_size = GetPreferredSize();
1597 preferred_size_ = pref_size;
1598 OnPreferredSizeChanged(old_size);
1601 void WebContentsImpl::ResizeDueToAutoResize(const gfx::Size& new_size) {
1603 delegate_->ResizeDueToAutoResize(this, new_size);
1606 WebContents* WebContentsImpl::OpenURL(const OpenURLParams& params) {
1610 WebContents* new_contents = delegate_->OpenURLFromTab(this, params);
1611 return new_contents;
1614 bool WebContentsImpl::Send(IPC::Message* message) {
1615 if (!GetRenderViewHost()) {
1620 return GetRenderViewHost()->Send(message);
1623 bool WebContentsImpl::NavigateToPendingEntry(
1624 NavigationController::ReloadType reload_type) {
1625 return frame_tree_.root()->navigator()->NavigateToPendingEntry(
1626 frame_tree_.GetMainFrame(), reload_type);
1629 void WebContentsImpl::RenderFrameForInterstitialPageCreated(
1630 RenderFrameHost* render_frame_host) {
1631 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
1632 RenderFrameForInterstitialPageCreated(render_frame_host));
1635 void WebContentsImpl::AttachInterstitialPage(
1636 InterstitialPageImpl* interstitial_page) {
1637 DCHECK(interstitial_page);
1638 GetRenderManager()->set_interstitial_page(interstitial_page);
1640 // Cancel any visible dialogs so that they don't interfere with the
1642 if (dialog_manager_)
1643 dialog_manager_->CancelActiveAndPendingDialogs(this);
1645 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
1646 DidAttachInterstitialPage());
1649 void WebContentsImpl::DetachInterstitialPage() {
1650 if (GetInterstitialPage())
1651 GetRenderManager()->remove_interstitial_page();
1652 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
1653 DidDetachInterstitialPage());
1656 void WebContentsImpl::SetHistoryLengthAndPrune(
1657 const SiteInstance* site_instance,
1659 int32 minimum_page_id) {
1660 // SetHistoryLengthAndPrune doesn't work when there are pending cross-site
1661 // navigations. Callers should ensure that this is the case.
1662 if (GetRenderManager()->pending_render_view_host()) {
1666 RenderViewHostImpl* rvh = GetRenderViewHostImpl();
1671 if (site_instance && rvh->GetSiteInstance() != site_instance) {
1675 Send(new ViewMsg_SetHistoryLengthAndPrune(GetRoutingID(),
1680 void WebContentsImpl::FocusThroughTabTraversal(bool reverse) {
1681 if (ShowingInterstitialPage()) {
1682 GetRenderManager()->interstitial_page()->FocusThroughTabTraversal(reverse);
1685 GetRenderViewHostImpl()->SetInitialFocus(reverse);
1688 bool WebContentsImpl::ShowingInterstitialPage() const {
1689 return GetRenderManager()->interstitial_page() != NULL;
1692 InterstitialPage* WebContentsImpl::GetInterstitialPage() const {
1693 return GetRenderManager()->interstitial_page();
1696 bool WebContentsImpl::IsSavable() {
1697 // WebKit creates Document object when MIME type is application/xhtml+xml,
1698 // so we also support this MIME type.
1699 return contents_mime_type_ == "text/html" ||
1700 contents_mime_type_ == "text/xml" ||
1701 contents_mime_type_ == "application/xhtml+xml" ||
1702 contents_mime_type_ == "text/plain" ||
1703 contents_mime_type_ == "text/css" ||
1704 net::IsSupportedJavascriptMimeType(contents_mime_type_.c_str());
1707 void WebContentsImpl::OnSavePage() {
1708 // If we can not save the page, try to download it.
1710 RecordDownloadSource(INITIATED_BY_SAVE_PACKAGE_ON_NON_HTML);
1711 SaveFrame(GetURL(), Referrer());
1717 // Create the save package and possibly prompt the user for the name to save
1718 // the page as. The user prompt is an asynchronous operation that runs on
1720 save_package_ = new SavePackage(this);
1721 save_package_->GetSaveInfo();
1724 // Used in automated testing to bypass prompting the user for file names.
1725 // Instead, the names and paths are hard coded rather than running them through
1726 // file name sanitation and extension / mime checking.
1727 bool WebContentsImpl::SavePage(const base::FilePath& main_file,
1728 const base::FilePath& dir_path,
1729 SavePageType save_type) {
1730 // Stop the page from navigating.
1733 save_package_ = new SavePackage(this, save_type, main_file, dir_path);
1734 return save_package_->Init(SavePackageDownloadCreatedCallback());
1737 void WebContentsImpl::SaveFrame(const GURL& url,
1738 const Referrer& referrer) {
1739 if (!GetURL().is_valid())
1741 bool is_main_frame = (url == GetURL());
1743 DownloadManager* dlm =
1744 BrowserContext::GetDownloadManager(GetBrowserContext());
1748 if (is_main_frame) {
1749 const NavigationEntry* entry = controller_.GetLastCommittedEntry();
1751 post_id = entry->GetPostID();
1753 scoped_ptr<DownloadUrlParameters> params(
1754 DownloadUrlParameters::FromWebContents(this, url));
1755 params->set_referrer(referrer);
1756 params->set_post_id(post_id);
1757 params->set_prefer_cache(true);
1759 params->set_method("POST");
1760 params->set_prompt(true);
1761 dlm->DownloadUrl(params.Pass());
1764 void WebContentsImpl::GenerateMHTML(
1765 const base::FilePath& file,
1766 const base::Callback<void(int64)>& callback) {
1767 MHTMLGenerationManager::GetInstance()->SaveMHTML(this, file, callback);
1770 // TODO(nasko): Rename this method to IsVisibleEntry.
1771 bool WebContentsImpl::IsActiveEntry(int32 page_id) {
1772 NavigationEntryImpl* visible_entry =
1773 NavigationEntryImpl::FromNavigationEntry(controller_.GetVisibleEntry());
1774 return (visible_entry != NULL &&
1775 visible_entry->site_instance() == GetSiteInstance() &&
1776 visible_entry->GetPageID() == page_id);
1779 const std::string& WebContentsImpl::GetContentsMimeType() const {
1780 return contents_mime_type_;
1783 bool WebContentsImpl::WillNotifyDisconnection() const {
1784 return notify_disconnection_;
1787 void WebContentsImpl::SetOverrideEncoding(const std::string& encoding) {
1788 SetEncoding(encoding);
1789 Send(new ViewMsg_SetPageEncoding(GetRoutingID(), encoding));
1792 void WebContentsImpl::ResetOverrideEncoding() {
1794 Send(new ViewMsg_ResetPageEncodingToDefault(GetRoutingID()));
1797 RendererPreferences* WebContentsImpl::GetMutableRendererPrefs() {
1798 return &renderer_preferences_;
1801 void WebContentsImpl::Close() {
1802 Close(GetRenderViewHost());
1805 void WebContentsImpl::DragSourceEndedAt(int client_x, int client_y,
1806 int screen_x, int screen_y, blink::WebDragOperation operation) {
1807 if (browser_plugin_embedder_.get())
1808 browser_plugin_embedder_->DragSourceEndedAt(client_x, client_y,
1809 screen_x, screen_y, operation);
1810 if (GetRenderViewHost())
1811 GetRenderViewHostImpl()->DragSourceEndedAt(client_x, client_y,
1812 screen_x, screen_y, operation);
1815 void WebContentsImpl::DragSourceMovedTo(int client_x, int client_y,
1816 int screen_x, int screen_y) {
1817 if (browser_plugin_embedder_.get())
1818 browser_plugin_embedder_->DragSourceMovedTo(client_x, client_y,
1819 screen_x, screen_y);
1820 if (GetRenderViewHost())
1821 GetRenderViewHostImpl()->DragSourceMovedTo(client_x, client_y,
1822 screen_x, screen_y);
1825 void WebContentsImpl::DidGetResourceResponseStart(
1826 const ResourceRequestDetails& details) {
1827 controller_.ssl_manager()->DidStartResourceResponse(details);
1829 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
1830 DidGetResourceResponseStart(details));
1832 // TODO(avi): Remove. http://crbug.com/170921
1833 NotificationService::current()->Notify(
1834 NOTIFICATION_RESOURCE_RESPONSE_STARTED,
1835 Source<WebContents>(this),
1836 Details<const ResourceRequestDetails>(&details));
1839 void WebContentsImpl::DidGetRedirectForResourceRequest(
1840 RenderViewHost* render_view_host,
1841 const ResourceRedirectDetails& details) {
1842 controller_.ssl_manager()->DidReceiveResourceRedirect(details);
1845 WebContentsObserver,
1847 DidGetRedirectForResourceRequest(render_view_host, details));
1849 // TODO(avi): Remove. http://crbug.com/170921
1850 NotificationService::current()->Notify(
1851 NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
1852 Source<WebContents>(this),
1853 Details<const ResourceRedirectDetails>(&details));
1856 void WebContentsImpl::SystemDragEnded() {
1857 if (GetRenderViewHost())
1858 GetRenderViewHostImpl()->DragSourceSystemDragEnded();
1860 delegate_->DragEnded();
1861 if (browser_plugin_embedder_.get())
1862 browser_plugin_embedder_->SystemDragEnded();
1865 void WebContentsImpl::UserGestureDone() {
1869 void WebContentsImpl::SetClosedByUserGesture(bool value) {
1870 closed_by_user_gesture_ = value;
1873 bool WebContentsImpl::GetClosedByUserGesture() const {
1874 return closed_by_user_gesture_;
1877 double WebContentsImpl::GetZoomLevel() const {
1878 HostZoomMapImpl* zoom_map = static_cast<HostZoomMapImpl*>(
1879 HostZoomMap::GetForBrowserContext(GetBrowserContext()));
1884 if (temporary_zoom_settings_) {
1885 zoom_level = zoom_map->GetTemporaryZoomLevel(
1886 GetRenderProcessHost()->GetID(), GetRenderViewHost()->GetRoutingID());
1889 NavigationEntry* entry = GetController().GetLastCommittedEntry();
1890 // Since zoom map is updated using rewritten URL, use rewritten URL
1891 // to get the zoom level.
1892 url = entry ? entry->GetURL() : GURL::EmptyGURL();
1893 zoom_level = zoom_map->GetZoomLevelForHostAndScheme(url.scheme(),
1894 net::GetHostOrSpecFromURL(url));
1899 int WebContentsImpl::GetZoomPercent(bool* enable_increment,
1900 bool* enable_decrement) const {
1901 *enable_decrement = *enable_increment = false;
1902 // Calculate the zoom percent from the factor. Round up to the nearest whole
1904 int percent = static_cast<int>(
1905 ZoomLevelToZoomFactor(GetZoomLevel()) * 100 + 0.5);
1906 *enable_decrement = percent > minimum_zoom_percent_;
1907 *enable_increment = percent < maximum_zoom_percent_;
1911 void WebContentsImpl::ViewSource() {
1915 NavigationEntry* entry = GetController().GetLastCommittedEntry();
1919 delegate_->ViewSourceForTab(this, entry->GetURL());
1922 void WebContentsImpl::ViewFrameSource(const GURL& url,
1923 const PageState& page_state) {
1927 delegate_->ViewSourceForFrame(this, url, page_state);
1930 int WebContentsImpl::GetMinimumZoomPercent() const {
1931 return minimum_zoom_percent_;
1934 int WebContentsImpl::GetMaximumZoomPercent() const {
1935 return maximum_zoom_percent_;
1938 gfx::Size WebContentsImpl::GetPreferredSize() const {
1939 return capturer_count_ == 0 ? preferred_size_ : preferred_size_for_capture_;
1942 bool WebContentsImpl::GotResponseToLockMouseRequest(bool allowed) {
1943 return GetRenderViewHost() ?
1944 GetRenderViewHostImpl()->GotResponseToLockMouseRequest(allowed) : false;
1947 bool WebContentsImpl::HasOpener() const {
1948 return opener_ != NULL;
1951 void WebContentsImpl::DidChooseColorInColorChooser(SkColor color) {
1952 Send(new ViewMsg_DidChooseColorResponse(
1953 GetRoutingID(), color_chooser_identifier_, color));
1956 void WebContentsImpl::DidEndColorChooser() {
1957 Send(new ViewMsg_DidEndColorChooser(GetRoutingID(),
1958 color_chooser_identifier_));
1959 color_chooser_.reset();
1960 color_chooser_identifier_ = 0;
1963 int WebContentsImpl::DownloadImage(const GURL& url,
1965 uint32_t max_bitmap_size,
1966 const ImageDownloadCallback& callback) {
1967 RenderViewHost* host = GetRenderViewHost();
1968 int id = StartDownload(host, url, is_favicon, max_bitmap_size);
1969 image_download_map_[id] = callback;
1973 bool WebContentsImpl::IsSubframe() const {
1974 return is_subframe_;
1977 void WebContentsImpl::SetZoomLevel(double level) {
1978 Send(new ViewMsg_SetZoomLevel(GetRoutingID(), level));
1979 BrowserPluginEmbedder* embedder = GetBrowserPluginEmbedder();
1981 embedder->SetZoomLevel(level);
1984 void WebContentsImpl::Find(int request_id,
1985 const base::string16& search_text,
1986 const blink::WebFindOptions& options) {
1987 Send(new ViewMsg_Find(GetRoutingID(), request_id, search_text, options));
1990 void WebContentsImpl::StopFinding(StopFindAction action) {
1991 Send(new ViewMsg_StopFinding(GetRoutingID(), action));
1994 bool WebContentsImpl::FocusLocationBarByDefault() {
1995 NavigationEntry* entry = controller_.GetVisibleEntry();
1996 if (entry && entry->GetURL() == GURL(kAboutBlankURL))
1998 return delegate_ && delegate_->ShouldFocusLocationBarByDefault(this);
2001 void WebContentsImpl::SetFocusToLocationBar(bool select_all) {
2003 delegate_->SetFocusToLocationBar(select_all);
2006 void WebContentsImpl::DidStartProvisionalLoad(
2007 RenderFrameHostImpl* render_frame_host,
2009 int64 parent_frame_id,
2011 const GURL& validated_url,
2013 bool is_iframe_srcdoc) {
2015 DidChangeLoadProgress(0);
2017 // Notify observers about the start of the provisional load.
2018 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2019 DidStartProvisionalLoadForFrame(frame_id, parent_frame_id,
2020 is_main_frame, validated_url, is_error_page,
2021 is_iframe_srcdoc, render_frame_host->render_view_host()));
2023 if (is_main_frame) {
2025 WebContentsObserver,
2027 ProvisionalChangeToMainFrameUrl(validated_url,
2028 render_frame_host));
2032 void WebContentsImpl::DidFailProvisionalLoadWithError(
2033 RenderFrameHostImpl* render_frame_host,
2034 const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) {
2035 GURL validated_url(params.url);
2037 WebContentsObserver,
2039 DidFailProvisionalLoad(params.frame_id,
2040 params.frame_unique_name,
2041 params.is_main_frame,
2044 params.error_description,
2045 render_frame_host->render_view_host()));
2048 void WebContentsImpl::DidFailLoadWithError(
2049 RenderFrameHostImpl* render_frame_host,
2054 const base::string16& error_description) {
2055 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2056 DidFailLoad(frame_id, url, is_main_frame,
2057 error_code, error_description,
2058 render_frame_host->render_view_host()));
2061 void WebContentsImpl::NotifyChangedNavigationState(
2062 InvalidateTypes changed_flags) {
2063 NotifyNavigationStateChanged(changed_flags);
2066 void WebContentsImpl::AboutToNavigateRenderFrame(
2067 RenderFrameHostImpl* render_frame_host) {
2068 // Notify observers that we will navigate in this RenderView.
2070 WebContentsObserver,
2072 AboutToNavigateRenderView(render_frame_host->render_view_host()));
2075 void WebContentsImpl::DidStartNavigationToPendingEntry(
2076 RenderFrameHostImpl* render_frame_host,
2078 NavigationController::ReloadType reload_type) {
2079 // Notify observers about navigation.
2081 WebContentsObserver,
2083 DidStartNavigationToPendingEntry(url, reload_type));
2086 void WebContentsImpl::DidRedirectProvisionalLoad(
2087 RenderFrameHostImpl* render_frame_host,
2088 const GURL& validated_target_url) {
2089 // Notify observers about the provisional change in the main frame URL.
2091 WebContentsObserver,
2093 ProvisionalChangeToMainFrameUrl(validated_target_url,
2094 render_frame_host));
2097 void WebContentsImpl::DidCommitProvisionalLoad(
2099 const base::string16& frame_unique_name,
2102 PageTransition transition_type,
2103 RenderFrameHostImpl* render_frame_host) {
2104 RenderViewHost* render_view_host = render_frame_host->render_view_host();
2105 // Notify observers about the commit of the provisional load.
2107 WebContentsObserver,
2109 DidCommitProvisionalLoadForFrame(frame_id,
2117 void WebContentsImpl::DidNavigateMainFramePostCommit(
2118 const LoadCommittedDetails& details,
2119 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
2120 if (details.is_navigation_to_different_page()) {
2121 // Clear the status bubble. This is a workaround for a bug where WebKit
2122 // doesn't let us know that the cursor left an element during a
2123 // transition (this is also why the mouse cursor remains as a hand after
2124 // clicking on a link); see bugs 1184641 and 980803. We don't want to
2125 // clear the bubble when a user navigates to a named anchor in the same
2127 UpdateTargetURL(details.entry->GetPageID(), GURL());
2130 if (!details.is_in_page) {
2131 // Once the main frame is navigated, we're no longer considered to have
2132 // displayed insecure content.
2133 displayed_insecure_content_ = false;
2134 SSLManager::NotifySSLInternalStateChanged(
2135 GetController().GetBrowserContext());
2138 // Notify observers about navigation.
2139 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2140 DidNavigateMainFrame(details, params));
2143 delegate_->DidNavigateMainFramePostCommit(this);
2144 view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent());
2148 void WebContentsImpl::DidNavigateAnyFramePostCommit(
2149 RenderFrameHostImpl* render_frame_host,
2150 const LoadCommittedDetails& details,
2151 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
2152 // If we navigate off the page, close all JavaScript dialogs.
2153 if (dialog_manager_ && !details.is_in_page)
2154 dialog_manager_->CancelActiveAndPendingDialogs(this);
2156 // Notify observers about navigation.
2157 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2158 DidNavigateAnyFrame(details, params));
2161 void WebContentsImpl::SetMainFrameMimeType(const std::string& mime_type) {
2162 contents_mime_type_ = mime_type;
2165 bool WebContentsImpl::CanOverscrollContent() {
2167 return delegate_->CanOverscrollContent();
2172 void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
2174 const std::string& security_info,
2175 const std::string& http_method,
2176 const std::string& mime_type,
2177 ResourceType::Type resource_type) {
2178 base::StatsCounter cache("WebKit.CacheHit");
2181 // Send out a notification that we loaded a resource from our memory cache.
2183 net::CertStatus cert_status = 0;
2184 int security_bits = -1;
2185 int connection_status = 0;
2186 SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
2187 DeserializeSecurityInfo(security_info, &cert_id, &cert_status,
2188 &security_bits, &connection_status,
2189 &signed_certificate_timestamp_ids);
2190 // TODO(alcutter,eranm): Pass signed_certificate_timestamp_ids into details
2191 LoadFromMemoryCacheDetails details(
2192 url, GetRenderProcessHost()->GetID(), cert_id, cert_status, http_method,
2193 mime_type, resource_type);
2195 controller_.ssl_manager()->DidLoadFromMemoryCache(details);
2197 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2198 DidLoadResourceFromMemoryCache(details));
2200 if (url.is_valid() && url.SchemeIsHTTPOrHTTPS()) {
2201 scoped_refptr<net::URLRequestContextGetter> request_context(
2202 resource_type == ResourceType::MEDIA ?
2203 GetBrowserContext()->GetMediaRequestContextForRenderProcess(
2204 GetRenderProcessHost()->GetID()) :
2205 GetBrowserContext()->GetRequestContextForRenderProcess(
2206 GetRenderProcessHost()->GetID()));
2207 BrowserThread::PostTask(
2210 base::Bind(&NotifyCacheOnIO, request_context, url, http_method));
2214 void WebContentsImpl::OnDidDisplayInsecureContent() {
2215 RecordAction(base::UserMetricsAction("SSL.DisplayedInsecureContent"));
2216 displayed_insecure_content_ = true;
2217 SSLManager::NotifySSLInternalStateChanged(
2218 GetController().GetBrowserContext());
2221 void WebContentsImpl::OnDidRunInsecureContent(
2222 const std::string& security_origin, const GURL& target_url) {
2223 LOG(WARNING) << security_origin << " ran insecure content from "
2224 << target_url.possibly_invalid_spec();
2225 RecordAction(base::UserMetricsAction("SSL.RanInsecureContent"));
2226 if (EndsWith(security_origin, kDotGoogleDotCom, false))
2227 RecordAction(base::UserMetricsAction("SSL.RanInsecureContentGoogle"));
2228 controller_.ssl_manager()->DidRunInsecureContent(security_origin);
2229 displayed_insecure_content_ = true;
2230 SSLManager::NotifySSLInternalStateChanged(
2231 GetController().GetBrowserContext());
2234 void WebContentsImpl::OnDocumentLoadedInFrame(int64 frame_id) {
2235 CHECK(render_frame_message_source_);
2236 CHECK(!render_view_message_source_);
2237 RenderFrameHostImpl* rfh =
2238 static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2240 FOR_EACH_OBSERVER(WebContentsObserver,
2242 DocumentLoadedInFrame(frame_id, rfh->render_view_host()));
2245 void WebContentsImpl::OnDidFinishLoad(
2248 bool is_main_frame) {
2249 if (!render_view_message_source_) {
2250 RecordAction(base::UserMetricsAction("BadMessageTerminate_RVD2"));
2251 GetRenderProcessHost()->ReceivedBadMessage();
2255 // --site-per-process mode has a short-term hack allowing cross-process
2256 // subframe pages to commit thinking they are top-level. Correct it here to
2257 // avoid confusing the observers.
2258 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) &&
2259 render_view_message_source_ != GetRenderViewHost())
2260 is_main_frame = false;
2262 GURL validated_url(url);
2263 RenderProcessHost* render_process_host =
2264 render_view_message_source_->GetProcess();
2265 render_process_host->FilterURL(false, &validated_url);
2266 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2267 DidFinishLoad(frame_id, validated_url, is_main_frame,
2268 render_view_message_source_));
2271 void WebContentsImpl::OnGoToEntryAtOffset(int offset) {
2272 if (!delegate_ || delegate_->OnGoToEntryOffset(offset)) {
2273 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
2274 controller_.GetEntryAtOffset(offset));
2277 // Note that we don't call NavigationController::GotToOffset() as we don't
2278 // want to create a pending navigation entry (it might end up lingering
2279 // http://crbug.com/51680).
2280 entry->SetTransitionType(
2281 PageTransitionFromInt(
2282 entry->GetTransitionType() |
2283 PAGE_TRANSITION_FORWARD_BACK));
2284 frame_tree_.root()->navigator()->NavigateToEntry(
2285 frame_tree_.GetMainFrame(),
2287 NavigationControllerImpl::NO_RELOAD);
2289 // If the entry is being restored and doesn't have a SiteInstance yet, fill
2290 // it in now that we know. This allows us to find the entry when it commits.
2291 if (!entry->site_instance() &&
2292 entry->restore_type() != NavigationEntryImpl::RESTORE_NONE) {
2293 entry->set_site_instance(
2294 static_cast<SiteInstanceImpl*>(GetPendingSiteInstance()));
2299 void WebContentsImpl::OnUpdateZoomLimits(int minimum_percent,
2300 int maximum_percent,
2302 minimum_zoom_percent_ = minimum_percent;
2303 maximum_zoom_percent_ = maximum_percent;
2304 temporary_zoom_settings_ = !remember;
2307 void WebContentsImpl::OnEnumerateDirectory(int request_id,
2308 const base::FilePath& path) {
2312 ChildProcessSecurityPolicyImpl* policy =
2313 ChildProcessSecurityPolicyImpl::GetInstance();
2314 if (policy->CanReadFile(GetRenderProcessHost()->GetID(), path))
2315 delegate_->EnumerateDirectory(this, request_id, path);
2318 void WebContentsImpl::OnJSOutOfMemory() {
2320 delegate_->JSOutOfMemory(this);
2323 void WebContentsImpl::OnRegisterProtocolHandler(const std::string& protocol,
2325 const base::string16& title,
2326 bool user_gesture) {
2330 ChildProcessSecurityPolicyImpl* policy =
2331 ChildProcessSecurityPolicyImpl::GetInstance();
2332 if (policy->IsPseudoScheme(protocol))
2335 delegate_->RegisterProtocolHandler(this, protocol, url, title, user_gesture);
2338 void WebContentsImpl::OnFindReply(int request_id,
2339 int number_of_matches,
2340 const gfx::Rect& selection_rect,
2341 int active_match_ordinal,
2342 bool final_update) {
2344 delegate_->FindReply(this, request_id, number_of_matches, selection_rect,
2345 active_match_ordinal, final_update);
2349 #if defined(OS_ANDROID)
2350 void WebContentsImpl::OnFindMatchRectsReply(
2352 const std::vector<gfx::RectF>& rects,
2353 const gfx::RectF& active_rect) {
2355 delegate_->FindMatchRectsReply(this, version, rects, active_rect);
2358 void WebContentsImpl::OnOpenDateTimeDialog(
2359 const ViewHostMsg_DateTimeDialogValue_Params& value) {
2360 date_time_chooser_->ShowDialog(ContentViewCore::FromWebContents(this),
2361 GetRenderViewHost(),
2370 void WebContentsImpl::OnJavaBridgeGetChannelHandle(IPC::Message* reply_msg) {
2371 java_bridge_dispatcher_host_manager_->OnGetChannelHandle(
2372 render_view_message_source_, reply_msg);
2377 void WebContentsImpl::OnPepperPluginHung(int plugin_child_id,
2378 const base::FilePath& path,
2380 UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1);
2382 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2383 PluginHungStatusChanged(plugin_child_id, path, is_hung));
2386 void WebContentsImpl::OnPluginCrashed(const base::FilePath& plugin_path,
2387 base::ProcessId plugin_pid) {
2388 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2389 PluginCrashed(plugin_path, plugin_pid));
2392 void WebContentsImpl::OnAppCacheAccessed(const GURL& manifest_url,
2393 bool blocked_by_policy) {
2394 // Notify observers about navigation.
2395 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2396 AppCacheAccessed(manifest_url, blocked_by_policy));
2399 void WebContentsImpl::OnOpenColorChooser(
2400 int color_chooser_id,
2402 const std::vector<ColorSuggestion>& suggestions) {
2403 ColorChooser* new_color_chooser =
2404 delegate_->OpenColorChooser(this, color, suggestions);
2405 if (!new_color_chooser)
2408 color_chooser_->End();
2409 color_chooser_.reset(new_color_chooser);
2410 color_chooser_identifier_ = color_chooser_id;
2413 void WebContentsImpl::OnEndColorChooser(int color_chooser_id) {
2414 if (color_chooser_ &&
2415 color_chooser_id == color_chooser_identifier_)
2416 color_chooser_->End();
2419 void WebContentsImpl::OnSetSelectedColorInColorChooser(int color_chooser_id,
2421 if (color_chooser_ &&
2422 color_chooser_id == color_chooser_identifier_)
2423 color_chooser_->SetSelectedColor(color);
2426 // This exists for render views that don't have a WebUI, but do have WebUI
2427 // bindings enabled.
2428 void WebContentsImpl::OnWebUISend(const GURL& source_url,
2429 const std::string& name,
2430 const base::ListValue& args) {
2432 delegate_->WebUISend(this, source_url, name, args);
2435 void WebContentsImpl::OnRequestPpapiBrokerPermission(
2438 const base::FilePath& plugin_path) {
2440 OnPpapiBrokerPermissionResult(routing_id, false);
2444 if (!delegate_->RequestPpapiBrokerPermission(
2445 this, url, plugin_path,
2446 base::Bind(&WebContentsImpl::OnPpapiBrokerPermissionResult,
2447 base::Unretained(this), routing_id))) {
2449 OnPpapiBrokerPermissionResult(routing_id, false);
2453 void WebContentsImpl::OnPpapiBrokerPermissionResult(int routing_id,
2455 Send(new ViewMsg_PpapiBrokerPermissionResult(routing_id, result));
2458 void WebContentsImpl::OnBrowserPluginMessage(const IPC::Message& message) {
2459 // This creates a BrowserPluginEmbedder, which handles all the BrowserPlugin
2460 // specific messages for this WebContents. This means that any message from
2461 // a BrowserPlugin prior to this will be ignored.
2462 // For more info, see comment above classes BrowserPluginEmbedder and
2463 // BrowserPluginGuest.
2464 CHECK(!browser_plugin_embedder_.get());
2465 browser_plugin_embedder_.reset(BrowserPluginEmbedder::Create(this));
2466 browser_plugin_embedder_->OnMessageReceived(message);
2469 void WebContentsImpl::OnDidDownloadImage(
2471 int http_status_code,
2472 const GURL& image_url,
2473 const std::vector<SkBitmap>& bitmaps,
2474 const std::vector<gfx::Size>& original_bitmap_sizes) {
2475 if (bitmaps.size() != original_bitmap_sizes.size())
2478 ImageDownloadMap::iterator iter = image_download_map_.find(id);
2479 if (iter == image_download_map_.end()) {
2480 // Currently WebContents notifies us of ANY downloads so that it is
2481 // possible to get here.
2484 if (!iter->second.is_null()) {
2486 id, http_status_code, image_url, bitmaps, original_bitmap_sizes);
2488 image_download_map_.erase(id);
2491 void WebContentsImpl::OnUpdateFaviconURL(
2493 const std::vector<FaviconURL>& candidates) {
2494 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2495 DidUpdateFaviconURL(page_id, candidates));
2498 void WebContentsImpl::OnMediaPlayingNotification(int64 player_cookie,
2501 // Chrome OS does its own detection of audio and video.
2502 #if !defined(OS_CHROMEOS)
2503 scoped_ptr<PowerSaveBlocker> blocker;
2505 blocker = PowerSaveBlocker::Create(
2506 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, "Playing video");
2507 #if defined(OS_ANDROID)
2508 static_cast<PowerSaveBlockerImpl*>(blocker.get())
2509 ->InitDisplaySleepBlocker(GetView()->GetNativeView());
2511 } else if (has_audio) {
2512 blocker = PowerSaveBlocker::Create(
2513 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, "Playing audio");
2517 power_save_blockers_[render_view_message_source_][player_cookie] =
2520 #endif // !defined(OS_CHROMEOS)
2523 void WebContentsImpl::OnMediaPausedNotification(int64 player_cookie) {
2524 // Chrome OS does its own detection of audio and video.
2525 #if !defined(OS_CHROMEOS)
2526 delete power_save_blockers_[render_view_message_source_][player_cookie];
2527 power_save_blockers_[render_view_message_source_].erase(player_cookie);
2528 #endif // !defined(OS_CHROMEOS)
2531 void WebContentsImpl::OnFirstVisuallyNonEmptyPaint(int32 page_id) {
2532 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2533 DidFirstVisuallyNonEmptyPaint(page_id));
2536 void WebContentsImpl::DidChangeVisibleSSLState() {
2537 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2538 DidChangeVisibleSSLState());
2541 void WebContentsImpl::NotifyBeforeFormRepostWarningShow() {
2542 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2543 BeforeFormRepostWarningShow());
2547 void WebContentsImpl::ActivateAndShowRepostFormWarningDialog() {
2550 delegate_->ShowRepostFormWarningDialog(this);
2553 // Notifies the RenderWidgetHost instance about the fact that the page is
2554 // loading, or done loading.
2555 void WebContentsImpl::SetIsLoading(RenderViewHost* render_view_host,
2557 LoadNotificationDetails* details) {
2558 if (is_loading == is_loading_)
2562 load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE,
2564 load_state_host_.clear();
2566 upload_position_ = 0;
2569 GetRenderManager()->SetIsLoading(is_loading);
2571 is_loading_ = is_loading;
2572 waiting_for_response_ = is_loading;
2575 delegate_->LoadingStateChanged(this);
2576 NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD);
2578 std::string url = (details ? details->url.possibly_invalid_spec() : "NULL");
2580 TRACE_EVENT_ASYNC_BEGIN1("browser", "WebContentsImpl Loading", this,
2582 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2583 DidStartLoading(render_view_host));
2585 TRACE_EVENT_ASYNC_END1("browser", "WebContentsImpl Loading", this,
2587 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2588 DidStopLoading(render_view_host));
2591 // TODO(avi): Remove. http://crbug.com/170921
2592 int type = is_loading ? NOTIFICATION_LOAD_START : NOTIFICATION_LOAD_STOP;
2593 NotificationDetails det = NotificationService::NoDetails();
2595 det = Details<LoadNotificationDetails>(details);
2596 NotificationService::current()->Notify(
2597 type, Source<NavigationController>(&controller_), det);
2600 void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) {
2601 // If we are creating a RVH for a restored controller, then we need to make
2602 // sure the RenderView starts with a next_page_id_ larger than the number
2603 // of restored entries. This must be called before the RenderView starts
2604 // navigating (to avoid a race between the browser updating max_page_id and
2605 // the renderer updating next_page_id_). Because of this, we only call this
2606 // from CreateRenderView and allow that to notify the RenderView for us.
2607 int max_restored_page_id = controller_.GetMaxRestoredPageID();
2608 if (max_restored_page_id >
2609 GetMaxPageIDForSiteInstance(rvh->GetSiteInstance()))
2610 UpdateMaxPageIDForSiteInstance(rvh->GetSiteInstance(),
2611 max_restored_page_id);
2614 bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl* entry,
2615 const base::string16& title) {
2616 // For file URLs without a title, use the pathname instead. In the case of a
2617 // synthesized title, we don't want the update to count toward the "one set
2618 // per page of the title to history."
2619 base::string16 final_title;
2621 if (entry && entry->GetURL().SchemeIsFile() && title.empty()) {
2622 final_title = base::UTF8ToUTF16(entry->GetURL().ExtractFileName());
2623 explicit_set = false; // Don't count synthetic titles toward the set limit.
2625 TrimWhitespace(title, TRIM_ALL, &final_title);
2626 explicit_set = true;
2629 // If a page is created via window.open and never navigated,
2630 // there will be no navigation entry. In this situation,
2631 // |page_title_when_no_navigation_entry_| will be used for page title.
2633 if (final_title == entry->GetTitle())
2634 return false; // Nothing changed, don't bother.
2636 entry->SetTitle(final_title);
2638 if (page_title_when_no_navigation_entry_ == final_title)
2639 return false; // Nothing changed, don't bother.
2641 page_title_when_no_navigation_entry_ = final_title;
2644 // Lastly, set the title for the view.
2645 view_->SetPageTitle(final_title);
2647 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2648 TitleWasSet(entry, explicit_set));
2650 // TODO(avi): Remove. http://crbug.com/170921
2651 std::pair<NavigationEntry*, bool> details =
2652 std::make_pair(entry, explicit_set);
2653 NotificationService::current()->Notify(
2654 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
2655 Source<WebContents>(this),
2656 Details<std::pair<NavigationEntry*, bool> >(&details));
2661 void WebContentsImpl::NotifySwapped(RenderViewHost* old_host,
2662 RenderViewHost* new_host) {
2663 // After sending out a swap notification, we need to send a disconnect
2664 // notification so that clients that pick up a pointer to |this| can NULL the
2665 // pointer. See Bug 1230284.
2666 notify_disconnection_ = true;
2667 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2668 RenderViewHostChanged(old_host, new_host));
2670 // TODO(avi): Remove. http://crbug.com/170921
2671 std::pair<RenderViewHost*, RenderViewHost*> details =
2672 std::make_pair(old_host, new_host);
2673 NotificationService::current()->Notify(
2674 NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
2675 Source<WebContents>(this),
2676 Details<std::pair<RenderViewHost*, RenderViewHost*> >(&details));
2678 // Ensure that the associated embedder gets cleared after a RenderViewHost
2679 // gets swapped, so we don't reuse the same embedder next time a
2680 // RenderViewHost is attached to this WebContents.
2681 RemoveBrowserPluginEmbedder();
2684 // TODO(avi): Remove this entire function because this notification is already
2685 // covered by two observer functions. http://crbug.com/170921
2686 void WebContentsImpl::NotifyDisconnected() {
2687 if (!notify_disconnection_)
2690 notify_disconnection_ = false;
2691 NotificationService::current()->Notify(
2692 NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
2693 Source<WebContents>(this),
2694 NotificationService::NoDetails());
2697 void WebContentsImpl::NotifyNavigationEntryCommitted(
2698 const LoadCommittedDetails& load_details) {
2700 WebContentsObserver, observers_, NavigationEntryCommitted(load_details));
2703 bool WebContentsImpl::OnMessageReceived(RenderFrameHost* render_frame_host,
2704 const IPC::Message& message) {
2705 return OnMessageReceived(NULL, render_frame_host, message);
2708 void WebContentsImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) {
2709 // Note this is only for subframes, the notification for the main frame
2710 // happens in RenderViewCreated.
2711 FOR_EACH_OBSERVER(WebContentsObserver,
2713 RenderFrameCreated(render_frame_host));
2716 void WebContentsImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
2717 FOR_EACH_OBSERVER(WebContentsObserver,
2719 RenderFrameDeleted(render_frame_host));
2722 void WebContentsImpl::WorkerCrashed(RenderFrameHost* render_frame_host) {
2724 delegate_->WorkerCrashed(this);
2727 void WebContentsImpl::ShowContextMenu(RenderFrameHost* render_frame_host,
2728 const ContextMenuParams& params) {
2729 // Allow WebContentsDelegates to handle the context menu operation first.
2730 if (delegate_ && delegate_->HandleContextMenu(params))
2733 render_view_host_delegate_view_->ShowContextMenu(render_frame_host, params);
2736 WebContents* WebContentsImpl::GetAsWebContents() {
2740 RenderViewHostDelegateView* WebContentsImpl::GetDelegateView() {
2741 return render_view_host_delegate_view_;
2744 RenderViewHostDelegate::RendererManagement*
2745 WebContentsImpl::GetRendererManagementDelegate() {
2746 return GetRenderManager();
2749 RendererPreferences WebContentsImpl::GetRendererPrefs(
2750 BrowserContext* browser_context) const {
2751 return renderer_preferences_;
2754 gfx::Rect WebContentsImpl::GetRootWindowResizerRect() const {
2756 return delegate_->GetRootWindowResizerRect();
2760 void WebContentsImpl::RemoveBrowserPluginEmbedder() {
2761 if (browser_plugin_embedder_)
2762 browser_plugin_embedder_.reset();
2765 void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) {
2766 // Don't send notifications if we are just creating a swapped-out RVH for
2767 // the opener chain. These won't be used for view-source or WebUI, so it's
2768 // ok to return early.
2769 if (static_cast<RenderViewHostImpl*>(render_view_host)->IsSwappedOut())
2773 view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent());
2775 NotificationService::current()->Notify(
2776 NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
2777 Source<WebContents>(this),
2778 Details<RenderViewHost>(render_view_host));
2780 // When we're creating views, we're still doing initial setup, so we always
2781 // use the pending Web UI rather than any possibly existing committed one.
2782 if (GetRenderManager()->pending_web_ui())
2783 GetRenderManager()->pending_web_ui()->RenderViewCreated(render_view_host);
2785 NavigationEntry* entry = controller_.GetPendingEntry();
2786 if (entry && entry->IsViewSourceMode()) {
2787 // Put the renderer in view source mode.
2788 render_view_host->Send(
2789 new ViewMsg_EnableViewSourceMode(render_view_host->GetRoutingID()));
2792 view_->RenderViewCreated(render_view_host);
2795 WebContentsObserver, observers_, RenderViewCreated(render_view_host));
2797 // We tell the observers now instead of when the main RenderFrameHostImpl is
2798 // constructed because otherwise it would be too early (i.e. IPCs sent to the
2799 // frame would be dropped because it's not created yet).
2800 RenderFrameHost* main_frame = render_view_host->GetMainFrame();
2802 WebContentsObserver, observers_, RenderFrameCreated(main_frame));
2805 void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) {
2806 if (rvh != GetRenderViewHost()) {
2807 // Don't notify the world, since this came from a renderer in the
2812 notify_disconnection_ = true;
2813 // TODO(avi): Remove. http://crbug.com/170921
2814 NotificationService::current()->Notify(
2815 NOTIFICATION_WEB_CONTENTS_CONNECTED,
2816 Source<WebContents>(this),
2817 NotificationService::NoDetails());
2819 bool was_crashed = IsCrashed();
2820 SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING, 0);
2822 // Restore the focus to the tab (otherwise the focus will be on the top
2824 if (was_crashed && !FocusLocationBarByDefault() &&
2825 (!delegate_ || delegate_->ShouldFocusPageAfterCrash())) {
2829 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewReady());
2832 void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
2833 base::TerminationStatus status,
2835 if (rvh != GetRenderViewHost()) {
2836 // The pending page's RenderViewHost is gone.
2840 // Cancel any visible dialogs so they are not left dangling over the sad tab.
2841 if (dialog_manager_)
2842 dialog_manager_->CancelActiveAndPendingDialogs(this);
2844 ClearPowerSaveBlockers(rvh);
2845 SetIsLoading(rvh, false, NULL);
2846 NotifyDisconnected();
2847 SetIsCrashed(status, error_code);
2848 GetView()->OnTabCrashed(GetCrashedStatus(), crashed_error_code_);
2850 FOR_EACH_OBSERVER(WebContentsObserver,
2852 RenderProcessGone(GetCrashedStatus()));
2855 void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) {
2856 ClearPowerSaveBlockers(rvh);
2857 GetRenderManager()->RenderViewDeleted(rvh);
2858 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh));
2861 void WebContentsImpl::UpdateState(RenderViewHost* rvh,
2863 const PageState& page_state) {
2864 // Ensure that this state update comes from either the active RVH or one of
2865 // the swapped out RVHs. We don't expect to hear from any other RVHs.
2866 // TODO(nasko): This should go through RenderFrameHost.
2867 // TODO(creis): We can't update state for cross-process subframes until we
2868 // have FrameNavigationEntries. Once we do, this should be a DCHECK.
2869 if (rvh != GetRenderViewHost() &&
2870 !GetRenderManager()->IsRVHOnSwappedOutList(
2871 static_cast<RenderViewHostImpl*>(rvh)))
2874 // We must be prepared to handle state updates for any page, these occur
2875 // when the user is scrolling and entering form data, as well as when we're
2876 // leaving a page, in which case our state may have already been moved to
2877 // the next page. The navigation controller will look up the appropriate
2878 // NavigationEntry and update it when it is notified via the delegate.
2880 int entry_index = controller_.GetEntryIndexWithPageID(
2881 rvh->GetSiteInstance(), page_id);
2882 if (entry_index < 0)
2884 NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index);
2886 if (page_state == entry->GetPageState())
2887 return; // Nothing to update.
2888 entry->SetPageState(page_state);
2889 controller_.NotifyEntryChanged(entry, entry_index);
2892 void WebContentsImpl::UpdateTitle(RenderViewHost* rvh,
2894 const base::string16& title,
2895 base::i18n::TextDirection title_direction) {
2896 // If we have a title, that's a pretty good indication that we've started
2897 // getting useful data.
2898 SetNotWaitingForResponse();
2900 // Try to find the navigation entry, which might not be the current one.
2901 // For example, it might be from a pending RVH for the pending entry.
2902 NavigationEntryImpl* entry = controller_.GetEntryWithPageID(
2903 rvh->GetSiteInstance(), page_id);
2905 // We can handle title updates when we don't have an entry in
2906 // UpdateTitleForEntry, but only if the update is from the current RVH.
2907 if (!entry && rvh != GetRenderViewHost())
2910 // TODO(evan): make use of title_direction.
2911 // http://code.google.com/p/chromium/issues/detail?id=27094
2912 if (!UpdateTitleForEntry(entry, title))
2915 // Broadcast notifications when the UI should be updated.
2916 if (entry == controller_.GetEntryAtOffset(0))
2917 NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE);
2920 void WebContentsImpl::UpdateEncoding(RenderViewHost* render_view_host,
2921 const std::string& encoding) {
2922 SetEncoding(encoding);
2925 void WebContentsImpl::UpdateTargetURL(int32 page_id, const GURL& url) {
2927 delegate_->UpdateTargetURL(this, page_id, url);
2930 void WebContentsImpl::Close(RenderViewHost* rvh) {
2931 #if defined(OS_MACOSX)
2932 // The UI may be in an event-tracking loop, such as between the
2933 // mouse-down and mouse-up in text selection or a button click.
2934 // Defer the close until after tracking is complete, so that we
2935 // don't free objects out from under the UI.
2936 // TODO(shess): This could get more fine-grained. For instance,
2937 // closing a tab in another window while selecting text in the
2938 // current window's Omnibox should be just fine.
2939 if (view_->IsEventTracking()) {
2940 view_->CloseTabAfterEventTracking();
2945 // Ignore this if it comes from a RenderViewHost that we aren't showing.
2946 if (delegate_ && rvh == GetRenderViewHost())
2947 delegate_->CloseContents(this);
2950 void WebContentsImpl::SwappedOut(RenderViewHost* rvh) {
2951 if (delegate_ && rvh == GetRenderViewHost())
2952 delegate_->SwappedOut(this);
2954 // Allow the navigation to proceed.
2955 GetRenderManager()->SwappedOut(rvh);
2958 void WebContentsImpl::RequestMove(const gfx::Rect& new_bounds) {
2959 if (delegate_ && delegate_->IsPopupOrPanel(this))
2960 delegate_->MoveContents(this, new_bounds);
2963 void WebContentsImpl::DidStartLoading(RenderFrameHost* render_frame_host) {
2964 SetIsLoading(render_frame_host->GetRenderViewHost(), true, NULL);
2967 void WebContentsImpl::DidStopLoading(RenderFrameHost* render_frame_host) {
2968 scoped_ptr<LoadNotificationDetails> details;
2970 // Use the last committed entry rather than the active one, in case a
2971 // pending entry has been created.
2972 NavigationEntry* entry = controller_.GetLastCommittedEntry();
2973 Navigator* navigator = frame_tree_.root()->navigator();
2975 // An entry may not exist for a stop when loading an initial blank page or
2976 // if an iframe injected by script into a blank page finishes loading.
2978 base::TimeDelta elapsed =
2979 base::TimeTicks::Now() - navigator->GetCurrentLoadStart();
2981 details.reset(new LoadNotificationDetails(
2982 entry->GetVirtualURL(),
2983 entry->GetTransitionType(),
2986 controller_.GetCurrentEntryIndex()));
2989 SetIsLoading(render_frame_host->GetRenderViewHost(), false, details.get());
2992 void WebContentsImpl::DidCancelLoading() {
2993 controller_.DiscardNonCommittedEntries();
2995 // Update the URL display.
2996 NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
2999 void WebContentsImpl::DidChangeLoadProgress(double progress) {
3001 delegate_->LoadProgressChanged(this, progress);
3004 void WebContentsImpl::DidDisownOpener(RenderViewHost* rvh) {
3006 // Clear our opener so that future cross-process navigations don't have an
3008 RemoveDestructionObserver(opener_);
3012 // Notify all swapped out RenderViewHosts for this tab. This is important
3013 // in case we go back to them, or if another window in those processes tries
3014 // to access window.opener.
3015 GetRenderManager()->DidDisownOpener(rvh);
3018 void WebContentsImpl::DidAccessInitialDocument() {
3019 // Update the URL display.
3020 NotifyNavigationStateChanged(content::INVALIDATE_TYPE_URL);
3023 void WebContentsImpl::DocumentAvailableInMainFrame(
3024 RenderViewHost* render_view_host) {
3025 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3026 DocumentAvailableInMainFrame());
3029 void WebContentsImpl::DocumentOnLoadCompletedInMainFrame(
3030 RenderViewHost* render_view_host,
3032 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3033 DocumentOnLoadCompletedInMainFrame(page_id));
3035 // TODO(avi): Remove. http://crbug.com/170921
3036 NotificationService::current()->Notify(
3037 NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
3038 Source<WebContents>(this),
3039 Details<int>(&page_id));
3042 void WebContentsImpl::RequestOpenURL(RenderViewHost* rvh,
3044 const Referrer& referrer,
3045 WindowOpenDisposition disposition,
3046 int64 source_frame_id,
3047 bool should_replace_current_entry,
3048 bool user_gesture) {
3049 // If this came from a swapped out RenderViewHost, we only allow the request
3050 // if we are still in the same BrowsingInstance.
3051 if (static_cast<RenderViewHostImpl*>(rvh)->IsSwappedOut() &&
3052 !rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance())) {
3056 // Delegate to RequestTransferURL because this is just the generic
3057 // case where |old_request_id| is empty.
3058 // TODO(creis): Pass the redirect_chain into this method to support client
3059 // redirects. http://crbug.com/311721.
3060 std::vector<GURL> redirect_chain;
3061 RequestTransferURL(url, redirect_chain, referrer, PAGE_TRANSITION_LINK,
3062 disposition, source_frame_id, GlobalRequestID(),
3063 should_replace_current_entry, user_gesture);
3066 void WebContentsImpl::RequestTransferURL(
3068 const std::vector<GURL>& redirect_chain,
3069 const Referrer& referrer,
3070 PageTransition page_transition,
3071 WindowOpenDisposition disposition,
3072 int64 source_frame_id,
3073 const GlobalRequestID& old_request_id,
3074 bool should_replace_current_entry,
3075 bool user_gesture) {
3076 WebContents* new_contents = NULL;
3078 if (!GetContentClient()->browser()->ShouldAllowOpenURL(
3079 GetSiteInstance(), url))
3080 dest_url = GURL(kAboutBlankURL);
3082 // Look up the FrameTreeNode ID corresponding to source_frame_id.
3083 int64 frame_tree_node_id = -1;
3084 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) &&
3085 source_frame_id != -1) {
3086 FrameTreeNode* source_node = frame_tree_.FindByFrameID(source_frame_id);
3088 frame_tree_node_id = source_node->frame_tree_node_id();
3090 OpenURLParams params(dest_url, referrer, source_frame_id,
3091 frame_tree_node_id, disposition,
3092 page_transition, true /* is_renderer_initiated */);
3093 if (redirect_chain.size() > 0)
3094 params.redirect_chain = redirect_chain;
3095 params.transferred_global_request_id = old_request_id;
3096 params.should_replace_current_entry = should_replace_current_entry;
3097 params.user_gesture = user_gesture;
3099 if (GetRenderManager()->web_ui()) {
3100 // Web UI pages sometimes want to override the page transition type for
3101 // link clicks (e.g., so the new tab page can specify AUTO_BOOKMARK for
3102 // automatically generated suggestions). We don't override other types
3103 // like TYPED because they have different implications (e.g., autocomplete).
3104 if (PageTransitionCoreTypeIs(params.transition, PAGE_TRANSITION_LINK))
3105 params.transition = GetRenderManager()->web_ui()->GetLinkTransitionType();
3107 // Note also that we hide the referrer for Web UI pages. We don't really
3108 // want web sites to see a referrer of "chrome://blah" (and some
3109 // chrome: URLs might have search terms or other stuff we don't want to
3110 // send to the site), so we send no referrer.
3111 params.referrer = Referrer();
3113 // Navigations in Web UI pages count as browser-initiated navigations.
3114 params.is_renderer_initiated = false;
3117 new_contents = OpenURL(params);
3120 // Notify observers.
3121 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3122 DidOpenRequestedURL(new_contents,
3131 void WebContentsImpl::RouteCloseEvent(RenderViewHost* rvh) {
3132 // Tell the active RenderViewHost to run unload handlers and close, as long
3133 // as the request came from a RenderViewHost in the same BrowsingInstance.
3134 // In most cases, we receive this from a swapped out RenderViewHost.
3135 // It is possible to receive it from one that has just been swapped in,
3136 // in which case we might as well deliver the message anyway.
3137 if (rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()))
3138 GetRenderViewHost()->ClosePage();
3141 void WebContentsImpl::RouteMessageEvent(
3142 RenderViewHost* rvh,
3143 const ViewMsg_PostMessage_Params& params) {
3144 // Only deliver the message to the active RenderViewHost if the request
3145 // came from a RenderViewHost in the same BrowsingInstance or if this
3146 // WebContents is dedicated to a browser plugin guest.
3147 // Note: This check means that an embedder could theoretically receive a
3148 // postMessage from anyone (not just its own guests). However, this is
3149 // probably not a risk for apps since other pages won't have references
3151 if (!rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()) &&
3152 !GetBrowserPluginGuest() && !GetBrowserPluginEmbedder())
3155 ViewMsg_PostMessage_Params new_params(params);
3157 if (!params.message_port_ids.empty()) {
3158 MessagePortMessageFilter* message_port_message_filter =
3159 static_cast<RenderProcessHostImpl*>(GetRenderProcessHost())
3160 ->message_port_message_filter();
3161 std::vector<int> new_routing_ids(params.message_port_ids.size());
3162 for (size_t i = 0; i < params.message_port_ids.size(); ++i) {
3163 new_routing_ids[i] = message_port_message_filter->GetNextRoutingID();
3164 MessagePortService::GetInstance()->UpdateMessagePort(
3165 params.message_port_ids[i],
3166 message_port_message_filter,
3167 new_routing_ids[i]);
3169 new_params.new_routing_ids = new_routing_ids;
3172 // If there is a source_routing_id, translate it to the routing ID for
3173 // the equivalent swapped out RVH in the target process. If we need
3174 // to create a swapped out RVH for the source tab, we create its opener
3175 // chain as well, since those will also be accessible to the target page.
3176 if (new_params.source_routing_id != MSG_ROUTING_NONE) {
3177 // Try to look up the WebContents for the source page.
3178 WebContentsImpl* source_contents = NULL;
3179 RenderViewHostImpl* source_rvh = RenderViewHostImpl::FromID(
3180 rvh->GetProcess()->GetID(), params.source_routing_id);
3182 source_contents = static_cast<WebContentsImpl*>(
3183 source_rvh->GetDelegate()->GetAsWebContents());
3186 if (source_contents) {
3187 if (GetBrowserPluginGuest()) {
3188 // We create a swapped out RenderView for the embedder in the guest's
3189 // render process but we intentionally do not expose the embedder's
3190 // opener chain to it.
3191 new_params.source_routing_id =
3192 source_contents->CreateSwappedOutRenderView(GetSiteInstance());
3194 new_params.source_routing_id =
3195 source_contents->CreateOpenerRenderViews(GetSiteInstance());
3198 // We couldn't find it, so don't pass a source frame.
3199 new_params.source_routing_id = MSG_ROUTING_NONE;
3203 // In most cases, we receive this from a swapped out RenderViewHost.
3204 // It is possible to receive it from one that has just been swapped in,
3205 // in which case we might as well deliver the message anyway.
3206 Send(new ViewMsg_PostMessageEvent(GetRoutingID(), new_params));
3209 void WebContentsImpl::RunJavaScriptMessage(
3210 RenderViewHost* rvh,
3211 const base::string16& message,
3212 const base::string16& default_prompt,
3213 const GURL& frame_url,
3214 JavaScriptMessageType javascript_message_type,
3215 IPC::Message* reply_msg,
3216 bool* did_suppress_message) {
3217 // Suppress JavaScript dialogs when requested. Also suppress messages when
3218 // showing an interstitial as it's shown over the previous page and we don't
3219 // want the hidden page's dialogs to interfere with the interstitial.
3220 bool suppress_this_message =
3221 static_cast<RenderViewHostImpl*>(rvh)->IsSwappedOut() ||
3222 ShowingInterstitialPage() ||
3224 delegate_->ShouldSuppressDialogs() ||
3225 !delegate_->GetJavaScriptDialogManager();
3227 if (!suppress_this_message) {
3228 std::string accept_lang = GetContentClient()->browser()->
3229 GetAcceptLangs(GetBrowserContext());
3230 dialog_manager_ = delegate_->GetJavaScriptDialogManager();
3231 dialog_manager_->RunJavaScriptDialog(
3233 frame_url.GetOrigin(),
3235 javascript_message_type,
3238 base::Bind(&WebContentsImpl::OnDialogClosed,
3239 base::Unretained(this),
3242 &suppress_this_message);
3245 *did_suppress_message = suppress_this_message;
3247 if (suppress_this_message) {
3248 // If we are suppressing messages, just reply as if the user immediately
3249 // pressed "Cancel".
3250 OnDialogClosed(rvh, reply_msg, false, base::string16());
3253 // OnDialogClosed (two lines up) may have caused deletion of this object (see
3254 // http://crbug.com/288961 ). The only safe thing to do here is return.
3257 void WebContentsImpl::RunBeforeUnloadConfirm(RenderViewHost* rvh,
3258 const base::string16& message,
3260 IPC::Message* reply_msg) {
3261 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh);
3263 delegate_->WillRunBeforeUnloadConfirm();
3265 bool suppress_this_message =
3266 rvhi->rvh_state() != RenderViewHostImpl::STATE_DEFAULT ||
3268 delegate_->ShouldSuppressDialogs() ||
3269 !delegate_->GetJavaScriptDialogManager();
3270 if (suppress_this_message) {
3271 // The reply must be sent to the RVH that sent the request.
3272 rvhi->JavaScriptDialogClosed(reply_msg, true, base::string16());
3276 is_showing_before_unload_dialog_ = true;
3277 dialog_manager_ = delegate_->GetJavaScriptDialogManager();
3278 dialog_manager_->RunBeforeUnloadDialog(
3279 this, message, is_reload,
3280 base::Bind(&WebContentsImpl::OnDialogClosed, base::Unretained(this), rvh,
3284 bool WebContentsImpl::AddMessageToConsole(int32 level,
3285 const base::string16& message,
3287 const base::string16& source_id) {
3290 return delegate_->AddMessageToConsole(this, level, message, line_no,
3294 WebPreferences WebContentsImpl::GetWebkitPrefs() {
3295 // We want to base the page config off of the actual URL, rather than the
3297 // TODO(nasko): Investigate how to remove the GetActiveEntry usage here,
3298 // as it is deprecated and can be out of sync with GetRenderViewHost().
3299 GURL url = controller_.GetActiveEntry()
3300 ? controller_.GetActiveEntry()->GetURL() : GURL::EmptyGURL();
3302 return GetRenderManager()->current_host()->GetWebkitPrefs(url);
3305 int WebContentsImpl::CreateSwappedOutRenderView(
3306 SiteInstance* instance) {
3307 return GetRenderManager()->CreateRenderFrame(instance, MSG_ROUTING_NONE,
3311 void WebContentsImpl::OnUserGesture() {
3312 // Notify observers.
3313 FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetUserGesture());
3315 ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
3316 if (rdh) // NULL in unittests.
3317 rdh->OnUserGesture(this);
3320 void WebContentsImpl::OnIgnoredUIEvent() {
3321 // Notify observers.
3322 FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetIgnoredUIEvent());
3325 void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh,
3326 bool is_during_beforeunload,
3327 bool is_during_unload) {
3328 // Don't show hung renderer dialog for a swapped out RVH.
3329 if (rvh != GetRenderViewHost())
3332 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh);
3334 // Ignore renderer unresponsive event if debugger is attached to the tab
3335 // since the event may be a result of the renderer sitting on a breakpoint.
3336 // See http://crbug.com/65458
3337 if (DevToolsAgentHost::IsDebuggerAttached(this))
3340 if (is_during_beforeunload || is_during_unload) {
3341 // Hang occurred while firing the beforeunload/unload handler.
3342 // Pretend the handler fired so tab closing continues as if it had.
3343 rvhi->set_sudden_termination_allowed(true);
3345 if (!GetRenderManager()->ShouldCloseTabOnUnresponsiveRenderer())
3348 // If the tab hangs in the beforeunload/unload handler there's really
3349 // nothing we can do to recover. If the hang is in the beforeunload handler,
3350 // pretend the beforeunload listeners have all fired and allow the delegate
3351 // to continue closing; the user will not have the option of cancelling the
3352 // close. Otherwise, pretend the unload listeners have all fired and close
3355 if (is_during_beforeunload) {
3356 delegate_->BeforeUnloadFired(this, true, &close);
3363 if (!GetRenderViewHostImpl() || !GetRenderViewHostImpl()->IsRenderViewLive())
3367 delegate_->RendererUnresponsive(this);
3370 void WebContentsImpl::RendererResponsive(RenderViewHost* render_view_host) {
3372 delegate_->RendererResponsive(this);
3375 void WebContentsImpl::LoadStateChanged(
3377 const net::LoadStateWithParam& load_state,
3378 uint64 upload_position,
3379 uint64 upload_size) {
3380 load_state_ = load_state;
3381 upload_position_ = upload_position;
3382 upload_size_ = upload_size;
3383 load_state_host_ = net::IDNToUnicode(url.host(),
3384 GetContentClient()->browser()->GetAcceptLangs(
3385 GetBrowserContext()));
3386 if (load_state_.state == net::LOAD_STATE_READING_RESPONSE)
3387 SetNotWaitingForResponse();
3389 NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD | INVALIDATE_TYPE_TAB);
3393 void WebContentsImpl::BeforeUnloadFiredFromRenderManager(
3394 bool proceed, const base::TimeTicks& proceed_time,
3395 bool* proceed_to_fire_unload) {
3396 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3397 BeforeUnloadFired(proceed_time));
3399 delegate_->BeforeUnloadFired(this, proceed, proceed_to_fire_unload);
3400 // Note: |this| might be deleted at this point.
3403 void WebContentsImpl::RenderProcessGoneFromRenderManager(
3404 RenderViewHost* render_view_host) {
3405 DCHECK(crashed_status_ != base::TERMINATION_STATUS_STILL_RUNNING);
3406 RenderViewTerminated(render_view_host, crashed_status_, crashed_error_code_);
3409 void WebContentsImpl::UpdateRenderViewSizeForRenderManager() {
3410 // TODO(brettw) this is a hack. See WebContentsView::SizeContents.
3411 gfx::Size size = GetSizeForNewRenderView();
3412 // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be
3413 // here during container initialization and normal window size will be set
3414 // later. In case of tab duplication this resizing to 0x0 prevents setting
3415 // normal size later so just ignore it.
3416 if (!size.IsEmpty())
3417 view_->SizeContents(size);
3420 void WebContentsImpl::CancelModalDialogsForRenderManager() {
3421 // We need to cancel modal dialogs when doing a process swap, since the load
3422 // deferrer would prevent us from swapping out.
3423 if (dialog_manager_)
3424 dialog_manager_->CancelActiveAndPendingDialogs(this);
3427 void WebContentsImpl::NotifySwappedFromRenderManager(RenderViewHost* old_host,
3428 RenderViewHost* new_host) {
3429 NotifySwapped(old_host, new_host);
3431 // Make sure the visible RVH reflects the new delegate's preferences.
3433 view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent());
3435 view_->RenderViewSwappedIn(new_host);
3438 int WebContentsImpl::CreateOpenerRenderViewsForRenderManager(
3439 SiteInstance* instance) {
3441 return MSG_ROUTING_NONE;
3443 // Recursively create RenderViews for anything else in the opener chain.
3444 return opener_->CreateOpenerRenderViews(instance);
3447 int WebContentsImpl::CreateOpenerRenderViews(SiteInstance* instance) {
3448 int opener_route_id = MSG_ROUTING_NONE;
3450 // If this tab has an opener, ensure it has a RenderView in the given
3451 // SiteInstance as well.
3453 opener_route_id = opener_->CreateOpenerRenderViews(instance);
3455 // If any of the renderers (current, pending, or swapped out) for this
3456 // WebContents has the same SiteInstance, use it.
3457 if (GetRenderManager()->current_host()->GetSiteInstance() == instance)
3458 return GetRenderManager()->current_host()->GetRoutingID();
3460 if (GetRenderManager()->pending_render_view_host() &&
3461 GetRenderManager()->pending_render_view_host()->GetSiteInstance() ==
3463 return GetRenderManager()->pending_render_view_host()->GetRoutingID();
3465 RenderViewHostImpl* rvh = GetRenderManager()->GetSwappedOutRenderViewHost(
3468 return rvh->GetRoutingID();
3470 // Create a swapped out RenderView in the given SiteInstance if none exists,
3471 // setting its opener to the given route_id. Return the new view's route_id.
3472 return GetRenderManager()->CreateRenderFrame(instance, opener_route_id,
3476 NavigationControllerImpl& WebContentsImpl::GetControllerForRenderManager() {
3477 return GetController();
3480 WebUIImpl* WebContentsImpl::CreateWebUIForRenderManager(const GURL& url) {
3481 return static_cast<WebUIImpl*>(CreateWebUI(url));
3485 WebContentsImpl::GetLastCommittedNavigationEntryForRenderManager() {
3486 return controller_.GetLastCommittedEntry();
3489 bool WebContentsImpl::CreateRenderViewForRenderManager(
3490 RenderViewHost* render_view_host,
3491 int opener_route_id,
3492 CrossProcessFrameConnector* frame_connector) {
3493 TRACE_EVENT0("browser", "WebContentsImpl::CreateRenderViewForRenderManager");
3494 // Can be NULL during tests.
3495 RenderWidgetHostView* rwh_view;
3496 // TODO(kenrb): RenderWidgetHostViewChildFrame special casing is temporary
3497 // until RenderWidgetHost is attached to RenderFrameHost. We need to special
3498 // case this because RWH is still a base class of RenderViewHost, and child
3499 // frame RWHVs are unique in that they do not have their own WebContents.
3500 if (frame_connector) {
3501 RenderWidgetHostViewChildFrame* rwh_view_child =
3502 new RenderWidgetHostViewChildFrame(render_view_host);
3503 frame_connector->set_view(rwh_view_child);
3504 rwh_view = rwh_view_child;
3506 rwh_view = view_->CreateViewForWidget(render_view_host);
3509 // Now that the RenderView has been created, we need to tell it its size.
3511 rwh_view->SetSize(GetSizeForNewRenderView());
3513 // Make sure we use the correct starting page_id in the new RenderView.
3514 UpdateMaxPageIDIfNecessary(render_view_host);
3516 GetMaxPageIDForSiteInstance(render_view_host->GetSiteInstance());
3518 if (!static_cast<RenderViewHostImpl*>(
3519 render_view_host)->CreateRenderView(base::string16(),
3525 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
3526 // Force a ViewMsg_Resize to be sent, needed to make plugins show up on
3527 // linux. See crbug.com/83941.
3529 if (RenderWidgetHost* render_widget_host = rwh_view->GetRenderWidgetHost())
3530 render_widget_host->WasResized();
3537 #if defined(OS_ANDROID)
3538 base::android::ScopedJavaLocalRef<jobject>
3539 WebContentsImpl::GetJavaWebContents() {
3540 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3542 WebContentsAndroid* web_contents_android =
3543 static_cast<WebContentsAndroid*>(GetUserData(kWebContentsAndroidKey));
3544 if (!web_contents_android) {
3545 web_contents_android = new WebContentsAndroid(this);
3546 SetUserData(kWebContentsAndroidKey, web_contents_android);
3548 return web_contents_android->GetJavaObject();
3551 bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() {
3552 return CreateRenderViewForRenderManager(GetRenderViewHost(),
3558 void WebContentsImpl::OnDialogClosed(RenderViewHost* rvh,
3559 IPC::Message* reply_msg,
3561 const base::string16& user_input) {
3562 if (is_showing_before_unload_dialog_ && !success) {
3563 // If a beforeunload dialog is canceled, we need to stop the throbber from
3564 // spinning, since we forced it to start spinning in Navigate.
3565 DidStopLoading(rvh->GetMainFrame());
3566 controller_.DiscardNonCommittedEntries();
3568 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3569 BeforeUnloadDialogCancelled());
3571 is_showing_before_unload_dialog_ = false;
3572 static_cast<RenderViewHostImpl*>(
3573 rvh)->JavaScriptDialogClosed(reply_msg, success, user_input);
3576 void WebContentsImpl::SetEncoding(const std::string& encoding) {
3577 encoding_ = GetContentClient()->browser()->
3578 GetCanonicalEncodingNameByAliasName(encoding);
3581 void WebContentsImpl::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) {
3582 RenderWidgetHostView* rwh_view = view_->CreateViewForWidget(rvh);
3583 // Can be NULL during tests.
3585 rwh_view->SetSize(GetView()->GetContainerSize());
3588 bool WebContentsImpl::IsHidden() {
3589 return capturer_count_ == 0 && !should_normally_be_visible_;
3592 RenderFrameHostManager* WebContentsImpl::GetRenderManager() const {
3593 return frame_tree_.root()->render_manager();
3596 RenderViewHostImpl* WebContentsImpl::GetRenderViewHostImpl() {
3597 return static_cast<RenderViewHostImpl*>(GetRenderViewHost());
3600 BrowserPluginGuest* WebContentsImpl::GetBrowserPluginGuest() const {
3601 return browser_plugin_guest_.get();
3604 void WebContentsImpl::SetBrowserPluginGuest(BrowserPluginGuest* guest) {
3605 CHECK(!browser_plugin_guest_);
3606 browser_plugin_guest_.reset(guest);
3609 BrowserPluginEmbedder* WebContentsImpl::GetBrowserPluginEmbedder() const {
3610 return browser_plugin_embedder_.get();
3613 BrowserPluginGuestManager*
3614 WebContentsImpl::GetBrowserPluginGuestManager() const {
3615 return static_cast<BrowserPluginGuestManager*>(
3616 GetBrowserContext()->GetUserData(
3617 browser_plugin::kBrowserPluginGuestManagerKeyName));
3620 void WebContentsImpl::ClearPowerSaveBlockers(
3621 RenderViewHost* render_view_host) {
3622 STLDeleteValues(&power_save_blockers_[render_view_host]);
3623 power_save_blockers_.erase(render_view_host);
3626 void WebContentsImpl::ClearAllPowerSaveBlockers() {
3627 for (PowerSaveBlockerMap::iterator i(power_save_blockers_.begin());
3628 i != power_save_blockers_.end(); ++i)
3629 STLDeleteValues(&power_save_blockers_[i->first]);
3630 power_save_blockers_.clear();
3633 gfx::Size WebContentsImpl::GetSizeForNewRenderView() const {
3636 size = delegate_->GetSizeForNewRenderView(this);
3638 size = view_->GetContainerSize();
3642 void WebContentsImpl::OnFrameRemoved(
3643 RenderViewHostImpl* render_view_host,
3645 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3646 FrameDetached(render_view_host, frame_id));
3649 void WebContentsImpl::OnPreferredSizeChanged(const gfx::Size& old_size) {
3652 const gfx::Size new_size = GetPreferredSize();
3653 if (new_size != old_size)
3654 delegate_->UpdatePreferredSize(this, new_size);
3657 } // namespace content