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/render_view_devtools_agent_host.h"
26 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
27 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
28 #include "content/browser/download/download_stats.h"
29 #include "content/browser/download/mhtml_generation_manager.h"
30 #include "content/browser/download/save_package.h"
31 #include "content/browser/frame_host/cross_process_frame_connector.h"
32 #include "content/browser/frame_host/interstitial_page_impl.h"
33 #include "content/browser/frame_host/navigation_entry_impl.h"
34 #include "content/browser/frame_host/navigator_impl.h"
35 #include "content/browser/frame_host/render_frame_host_impl.h"
36 #include "content/browser/frame_host/render_widget_host_view_child_frame.h"
37 #include "content/browser/host_zoom_map_impl.h"
38 #include "content/browser/loader/resource_dispatcher_host_impl.h"
39 #include "content/browser/message_port_message_filter.h"
40 #include "content/browser/message_port_service.h"
41 #include "content/browser/power_save_blocker_impl.h"
42 #include "content/browser/renderer_host/render_process_host_impl.h"
43 #include "content/browser/renderer_host/render_view_host_impl.h"
44 #include "content/browser/renderer_host/render_widget_host_impl.h"
45 #include "content/browser/site_instance_impl.h"
46 #include "content/browser/web_contents/web_contents_view_guest.h"
47 #include "content/browser/webui/generic_handler.h"
48 #include "content/browser/webui/web_ui_controller_factory_registry.h"
49 #include "content/browser/webui/web_ui_impl.h"
50 #include "content/common/browser_plugin/browser_plugin_constants.h"
51 #include "content/common/browser_plugin/browser_plugin_messages.h"
52 #include "content/common/frame_messages.h"
53 #include "content/common/image_messages.h"
54 #include "content/common/ssl_status_serialization.h"
55 #include "content/common/view_messages.h"
56 #include "content/port/browser/render_view_host_delegate_view.h"
57 #include "content/port/browser/render_widget_host_view_port.h"
58 #include "content/public/browser/ax_event_notification_details.h"
59 #include "content/public/browser/browser_context.h"
60 #include "content/public/browser/color_chooser.h"
61 #include "content/public/browser/content_browser_client.h"
62 #include "content/public/browser/devtools_agent_host.h"
63 #include "content/public/browser/download_manager.h"
64 #include "content/public/browser/download_url_parameters.h"
65 #include "content/public/browser/invalidate_type.h"
66 #include "content/public/browser/javascript_dialog_manager.h"
67 #include "content/public/browser/load_from_memory_cache_details.h"
68 #include "content/public/browser/load_notification_details.h"
69 #include "content/public/browser/navigation_details.h"
70 #include "content/public/browser/notification_details.h"
71 #include "content/public/browser/notification_service.h"
72 #include "content/public/browser/resource_request_details.h"
73 #include "content/public/browser/storage_partition.h"
74 #include "content/public/browser/user_metrics.h"
75 #include "content/public/browser/web_contents_delegate.h"
76 #include "content/public/browser/web_contents_observer.h"
77 #include "content/public/browser/web_contents_view.h"
78 #include "content/public/common/bindings_policy.h"
79 #include "content/public/common/content_constants.h"
80 #include "content/public/common/content_switches.h"
81 #include "content/public/common/page_zoom.h"
82 #include "content/public/common/result_codes.h"
83 #include "content/public/common/url_constants.h"
84 #include "content/public/common/url_utils.h"
85 #include "net/base/mime_util.h"
86 #include "net/base/net_util.h"
87 #include "net/http/http_cache.h"
88 #include "net/http/http_transaction_factory.h"
89 #include "net/url_request/url_request_context.h"
90 #include "net/url_request/url_request_context_getter.h"
91 #include "ui/base/layout.h"
92 #include "ui/gfx/display.h"
93 #include "ui/gfx/screen.h"
94 #include "ui/gl/gl_switches.h"
95 #include "webkit/common/webpreferences.h"
97 #if defined(OS_ANDROID)
98 #include "content/browser/android/date_time_chooser_android.h"
99 #include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
100 #include "content/browser/web_contents/web_contents_android.h"
101 #include "content/common/java_bridge_messages.h"
102 #include "content/public/browser/android/content_view_core.h"
105 #if defined(OS_MACOSX)
106 #include "base/mac/foundation_util.h"
107 #include "ui/gl/io_surface_support_mac.h"
110 // Cross-Site Navigations
112 // If a WebContentsImpl is told to navigate to a different web site (as
113 // determined by SiteInstance), it will replace its current RenderViewHost with
114 // a new RenderViewHost dedicated to the new SiteInstance. This works as
117 // - RVHM::Navigate determines whether the destination is cross-site, and if so,
118 // it creates a pending_render_view_host_.
119 // - The pending RVH is "suspended," so that no navigation messages are sent to
120 // its renderer until the beforeunload JavaScript handler has a chance to
121 // run in the current RVH.
122 // - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton)
123 // that it has a pending cross-site request. We will check this on the IO
124 // thread when deciding how to handle the response.
125 // - The current RVH runs its beforeunload handler. If it returns false, we
126 // cancel all the pending logic. Otherwise we allow the pending RVH to send
127 // the navigation request to its renderer.
128 // - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the
129 // main resource load on the pending RVH. It creates a
130 // CrossSiteResourceHandler to check whether a process swap is needed when
131 // the request is ready to commit.
132 // - When RDH receives a response, the BufferedResourceHandler determines
133 // whether it is a download. If so, it sends a message to the new renderer
134 // causing it to cancel the request, and the download proceeds. For now, the
135 // pending RVH remains until the next DidNavigate event for this
136 // WebContentsImpl. This isn't ideal, but it doesn't affect any functionality.
137 // - After RDH receives a response and determines that it is safe and not a
138 // download, the CrossSiteResourceHandler checks whether a process swap is
139 // needed (either because CrossSiteRequestManager has state for it or because
140 // a transfer was needed for a redirect).
141 // - If so, CrossSiteResourceHandler pauses the response to first run the old
142 // page's unload handler. It does this by asynchronously calling the
143 // OnCrossSiteResponse method of RenderFrameHostManager on the UI thread,
144 // which sends a SwapOut message to the current RVH.
145 // - Once the unload handler is finished, RVHM::SwappedOut checks if a transfer
146 // to a new process is needed, based on the stored pending_nav_params_. (This
147 // is independent of whether we started out with a cross-process navigation.)
148 // - If not, it just tells the ResourceDispatcherHost to resume the response
149 // to its current RenderViewHost.
150 // - If so, it cancels the current pending RenderViewHost and sets up a new
151 // navigation using RequestTransferURL. When the transferred request
152 // arrives in the ResourceDispatcherHost, we transfer the response and
154 // - The pending renderer sends a FrameNavigate message that invokes the
155 // DidNavigate method. This replaces the current RVH with the
157 // - The previous renderer is kept swapped out in RenderFrameHostManager in case
158 // the user goes back. The process only stays live if another tab is using
159 // it, but if so, the existing frame relationships will be maintained.
164 const char kDotGoogleDotCom
[] = ".google.com";
166 #if defined(OS_ANDROID)
167 const char kWebContentsAndroidKey
[] = "web_contents_android";
170 base::LazyInstance
<std::vector
<WebContentsImpl::CreatedCallback
> >
171 g_created_callbacks
= LAZY_INSTANCE_INITIALIZER
;
173 static int StartDownload(content::RenderViewHost
* rvh
,
176 uint32_t max_bitmap_size
) {
177 static int g_next_image_download_id
= 0;
178 rvh
->Send(new ImageMsg_DownloadImage(rvh
->GetRoutingID(),
179 ++g_next_image_download_id
,
183 return g_next_image_download_id
;
186 void NotifyCacheOnIO(
187 scoped_refptr
<net::URLRequestContextGetter
> request_context
,
189 const std::string
& http_method
) {
190 request_context
->GetURLRequestContext()->http_transaction_factory()->
191 GetCache()->OnExternalCacheHit(url
, http_method
);
194 // Helper function for retrieving all the sites in a frame tree.
195 bool CollectSites(BrowserContext
* context
,
196 std::set
<GURL
>* sites
,
197 FrameTreeNode
* node
) {
198 sites
->insert(SiteInstance::GetSiteForURL(context
, node
->current_url()));
202 bool ForEachFrameInternal(
203 const base::Callback
<void(RenderFrameHost
*)>& on_frame
,
204 FrameTreeNode
* node
) {
205 on_frame
.Run(node
->current_frame_host());
209 bool ForEachPendingFrameInternal(
210 const base::Callback
<void(RenderFrameHost
*)>& on_frame
,
211 FrameTreeNode
* node
) {
212 RenderFrameHost
* pending_frame_host
=
213 node
->render_manager()->pending_frame_host();
214 if (pending_frame_host
)
215 on_frame
.Run(pending_frame_host
);
219 void SendToAllFramesInternal(IPC::Message
* message
, RenderFrameHost
* rfh
) {
220 IPC::Message
* message_copy
= new IPC::Message(*message
);
221 message_copy
->set_routing_id(rfh
->GetRoutingID());
222 rfh
->Send(message_copy
);
225 void RunRenderFrameDeleted(
226 ObserverList
<WebContentsObserver
>* observer_list
,
227 RenderFrameHost
* render_frame_host
) {
228 FOR_EACH_OBSERVER(WebContentsObserver
,
230 RenderFrameDeleted(render_frame_host
));
235 WebContents
* WebContents::Create(const WebContents::CreateParams
& params
) {
236 return WebContentsImpl::CreateWithOpener(
237 params
, static_cast<WebContentsImpl
*>(params
.opener
));
240 WebContents
* WebContents::CreateWithSessionStorage(
241 const WebContents::CreateParams
& params
,
242 const SessionStorageNamespaceMap
& session_storage_namespace_map
) {
243 WebContentsImpl
* new_contents
= new WebContentsImpl(
244 params
.browser_context
, NULL
);
246 for (SessionStorageNamespaceMap::const_iterator it
=
247 session_storage_namespace_map
.begin();
248 it
!= session_storage_namespace_map
.end();
250 new_contents
->GetController()
251 .SetSessionStorageNamespace(it
->first
, it
->second
.get());
254 new_contents
->Init(params
);
258 void WebContentsImpl::AddCreatedCallback(const CreatedCallback
& callback
) {
259 g_created_callbacks
.Get().push_back(callback
);
262 void WebContentsImpl::RemoveCreatedCallback(const CreatedCallback
& callback
) {
263 for (size_t i
= 0; i
< g_created_callbacks
.Get().size(); ++i
) {
264 if (g_created_callbacks
.Get().at(i
).Equals(callback
)) {
265 g_created_callbacks
.Get().erase(g_created_callbacks
.Get().begin() + i
);
271 WebContents
* WebContents::FromRenderViewHost(const RenderViewHost
* rvh
) {
272 return rvh
->GetDelegate()->GetAsWebContents();
275 WebContents
* WebContents::FromRenderFrameHost(RenderFrameHost
* rfh
) {
276 RenderFrameHostImpl
* rfh_impl
= static_cast<RenderFrameHostImpl
*>(rfh
);
279 return rfh_impl
->delegate()->GetAsWebContents();
282 // WebContentsImpl::DestructionObserver ----------------------------------------
284 class WebContentsImpl::DestructionObserver
: public WebContentsObserver
{
286 DestructionObserver(WebContentsImpl
* owner
, WebContents
* watched_contents
)
287 : WebContentsObserver(watched_contents
),
291 // WebContentsObserver:
292 virtual void WebContentsDestroyed(WebContents
* web_contents
) OVERRIDE
{
293 owner_
->OnWebContentsDestroyed(static_cast<WebContentsImpl
*>(web_contents
));
297 WebContentsImpl
* owner_
;
299 DISALLOW_COPY_AND_ASSIGN(DestructionObserver
);
302 // WebContentsImpl -------------------------------------------------------------
304 WebContentsImpl::WebContentsImpl(
305 BrowserContext
* browser_context
,
306 WebContentsImpl
* opener
)
308 controller_(this, browser_context
),
309 render_view_host_delegate_view_(NULL
),
312 accessible_parent_(NULL
),
314 frame_tree_(new NavigatorImpl(&controller_
, this),
315 this, this, this, this),
317 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING
),
318 crashed_error_code_(0),
319 waiting_for_response_(false),
320 load_state_(net::LOAD_STATE_IDLE
, base::string16()),
323 displayed_insecure_content_(false),
325 should_normally_be_visible_(true),
326 is_being_destroyed_(false),
327 notify_disconnection_(false),
328 dialog_manager_(NULL
),
329 is_showing_before_unload_dialog_(false),
330 last_active_time_(base::TimeTicks::Now()),
331 closed_by_user_gesture_(false),
332 minimum_zoom_percent_(static_cast<int>(kMinimumZoomFactor
* 100)),
333 maximum_zoom_percent_(static_cast<int>(kMaximumZoomFactor
* 100)),
334 temporary_zoom_settings_(false),
335 color_chooser_identifier_(0),
336 render_view_message_source_(NULL
),
337 fullscreen_widget_routing_id_(MSG_ROUTING_NONE
),
338 is_subframe_(false) {
339 for (size_t i
= 0; i
< g_created_callbacks
.Get().size(); i
++)
340 g_created_callbacks
.Get().at(i
).Run(this);
341 frame_tree_
.SetFrameRemoveListener(
342 base::Bind(&WebContentsImpl::OnFrameRemoved
,
343 base::Unretained(this)));
346 WebContentsImpl::~WebContentsImpl() {
347 is_being_destroyed_
= true;
349 // Delete all RFH pending shutdown, which will lead the corresponding RVH to
350 // shutdown and be deleted as well.
352 base::Bind(&RenderFrameHostManager::ClearRFHsPendingShutdown
));
354 ClearAllPowerSaveBlockers();
356 for (std::set
<RenderWidgetHostImpl
*>::iterator iter
=
357 created_widgets_
.begin(); iter
!= created_widgets_
.end(); ++iter
) {
358 (*iter
)->DetachDelegate();
360 created_widgets_
.clear();
362 // Clear out any JavaScript state.
364 dialog_manager_
->WebContentsDestroyed(this);
367 color_chooser_
->End();
369 NotifyDisconnected();
371 // Notify any observer that have a reference on this WebContents.
372 NotificationService::current()->Notify(
373 NOTIFICATION_WEB_CONTENTS_DESTROYED
,
374 Source
<WebContents
>(this),
375 NotificationService::NoDetails());
377 base::Callback
<void(RenderFrameHost
*)> run_render_frame_deleted_callback
=
378 base::Bind(&RunRenderFrameDeleted
, base::Unretained(&observers_
));
379 frame_tree_
.ForEach(base::Bind(&ForEachPendingFrameInternal
,
380 run_render_frame_deleted_callback
));
382 RenderViewHost
* pending_rvh
= GetRenderManager()->pending_render_view_host();
384 FOR_EACH_OBSERVER(WebContentsObserver
,
386 RenderViewDeleted(pending_rvh
));
389 ForEachFrame(run_render_frame_deleted_callback
);
391 FOR_EACH_OBSERVER(WebContentsObserver
,
393 RenderViewDeleted(GetRenderManager()->current_host()));
395 FOR_EACH_OBSERVER(WebContentsObserver
,
397 WebContentsImplDestroyed());
401 STLDeleteContainerPairSecondPointers(destruction_observers_
.begin(),
402 destruction_observers_
.end());
405 WebContentsImpl
* WebContentsImpl::CreateWithOpener(
406 const WebContents::CreateParams
& params
,
407 WebContentsImpl
* opener
) {
408 TRACE_EVENT0("browser", "WebContentsImpl::CreateWithOpener");
409 WebContentsImpl
* new_contents
= new WebContentsImpl(
410 params
.browser_context
, opener
);
412 new_contents
->Init(params
);
417 BrowserPluginGuest
* WebContentsImpl::CreateGuest(
418 BrowserContext
* browser_context
,
419 SiteInstance
* site_instance
,
420 int guest_instance_id
,
421 scoped_ptr
<base::DictionaryValue
> extra_params
) {
422 WebContentsImpl
* new_contents
= new WebContentsImpl(browser_context
, NULL
);
424 // This makes |new_contents| act as a guest.
425 // For more info, see comment above class BrowserPluginGuest.
426 BrowserPluginGuest::Create(
427 guest_instance_id
, site_instance
, new_contents
, extra_params
.Pass());
429 WebContents::CreateParams
create_params(browser_context
, site_instance
);
430 new_contents
->Init(create_params
);
432 // We are instantiating a WebContents for browser plugin. Set its subframe bit
434 new_contents
->is_subframe_
= true;
436 return new_contents
->browser_plugin_guest_
.get();
439 RenderFrameHostManager
* WebContentsImpl::GetRenderManagerForTesting() {
440 return GetRenderManager();
443 bool WebContentsImpl::OnMessageReceived(RenderViewHost
* render_view_host
,
444 const IPC::Message
& message
) {
445 return OnMessageReceived(render_view_host
, NULL
, message
);
448 bool WebContentsImpl::OnMessageReceived(RenderViewHost
* render_view_host
,
449 RenderFrameHost
* render_frame_host
,
450 const IPC::Message
& message
) {
451 DCHECK(render_view_host
|| render_frame_host
);
453 static_cast<WebUIImpl
*>(GetWebUI())->OnMessageReceived(message
)) {
457 ObserverListBase
<WebContentsObserver
>::Iterator
it(observers_
);
458 WebContentsObserver
* observer
;
459 while ((observer
= it
.GetNext()) != NULL
)
460 if (observer
->OnMessageReceived(message
))
463 // Message handlers should be aware of which
464 // RenderViewHost/RenderFrameHost sent the message, which is temporarily
465 // stored in render_(view|frame)_message_source_.
466 if (render_frame_host
) {
467 if (RenderViewDevToolsAgentHost::DispatchIPCMessage(
468 render_frame_host
->GetRenderViewHost(), message
))
470 render_frame_message_source_
= render_frame_host
;
472 if (RenderViewDevToolsAgentHost::DispatchIPCMessage(
473 render_view_host
, message
))
475 render_view_message_source_
= render_view_host
;
479 bool message_is_ok
= true;
480 IPC_BEGIN_MESSAGE_MAP_EX(WebContentsImpl
, message
, message_is_ok
)
481 IPC_MESSAGE_HANDLER(FrameHostMsg_PepperPluginHung
, OnPepperPluginHung
)
482 IPC_MESSAGE_HANDLER(FrameHostMsg_PluginCrashed
, OnPluginCrashed
)
483 IPC_MESSAGE_HANDLER(FrameHostMsg_DomOperationResponse
,
484 OnDomOperationResponse
)
485 IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache
,
486 OnDidLoadResourceFromMemoryCache
)
487 IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent
,
488 OnDidDisplayInsecureContent
)
489 IPC_MESSAGE_HANDLER(ViewHostMsg_DidRunInsecureContent
,
490 OnDidRunInsecureContent
)
491 IPC_MESSAGE_HANDLER(FrameHostMsg_DidFinishDocumentLoad
,
492 OnDocumentLoadedInFrame
)
493 IPC_MESSAGE_HANDLER(FrameHostMsg_DidFinishLoad
, OnDidFinishLoad
)
494 IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset
, OnGoToEntryAtOffset
)
495 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits
, OnUpdateZoomLimits
)
496 IPC_MESSAGE_HANDLER(ViewHostMsg_EnumerateDirectory
, OnEnumerateDirectory
)
497 IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler
,
498 OnRegisterProtocolHandler
)
499 IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply
, OnFindReply
)
500 IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed
, OnAppCacheAccessed
)
501 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenColorChooser
, OnOpenColorChooser
)
502 IPC_MESSAGE_HANDLER(ViewHostMsg_EndColorChooser
, OnEndColorChooser
)
503 IPC_MESSAGE_HANDLER(ViewHostMsg_SetSelectedColorInColorChooser
,
504 OnSetSelectedColorInColorChooser
)
505 IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend
, OnWebUISend
)
506 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission
,
507 OnRequestPpapiBrokerPermission
)
508 IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_AllocateInstanceID
,
509 OnBrowserPluginMessage(message
))
510 IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_Attach
,
511 OnBrowserPluginMessage(message
))
512 IPC_MESSAGE_HANDLER(ImageHostMsg_DidDownloadImage
, OnDidDownloadImage
)
513 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFaviconURL
, OnUpdateFaviconURL
)
514 #if defined(OS_ANDROID)
515 IPC_MESSAGE_HANDLER(ViewHostMsg_FindMatchRects_Reply
,
516 OnFindMatchRectsReply
)
517 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog
,
518 OnOpenDateTimeDialog
)
519 IPC_MESSAGE_HANDLER_DELAY_REPLY(JavaBridgeHostMsg_GetChannelHandle
,
520 OnJavaBridgeGetChannelHandle
)
522 IPC_MESSAGE_HANDLER(ViewHostMsg_MediaPlayingNotification
,
523 OnMediaPlayingNotification
)
524 IPC_MESSAGE_HANDLER(ViewHostMsg_MediaPausedNotification
,
525 OnMediaPausedNotification
)
526 IPC_MESSAGE_HANDLER(ViewHostMsg_DidFirstVisuallyNonEmptyPaint
,
527 OnFirstVisuallyNonEmptyPaint
)
528 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowValidationMessage
,
529 OnShowValidationMessage
)
530 IPC_MESSAGE_HANDLER(ViewHostMsg_HideValidationMessage
,
531 OnHideValidationMessage
)
532 IPC_MESSAGE_HANDLER(ViewHostMsg_MoveValidationMessage
,
533 OnMoveValidationMessage
)
534 IPC_MESSAGE_UNHANDLED(handled
= false)
535 IPC_END_MESSAGE_MAP_EX()
536 render_view_message_source_
= NULL
;
537 render_frame_message_source_
= NULL
;
539 if (!message_is_ok
) {
540 RecordAction(base::UserMetricsAction("BadMessageTerminate_RVD"));
541 GetRenderProcessHost()->ReceivedBadMessage();
547 void WebContentsImpl::RunFileChooser(
548 RenderViewHost
* render_view_host
,
549 const FileChooserParams
& params
) {
551 delegate_
->RunFileChooser(this, params
);
554 NavigationControllerImpl
& WebContentsImpl::GetController() {
558 const NavigationControllerImpl
& WebContentsImpl::GetController() const {
562 BrowserContext
* WebContentsImpl::GetBrowserContext() const {
563 return controller_
.GetBrowserContext();
566 const GURL
& WebContentsImpl::GetURL() const {
567 // We may not have a navigation entry yet.
568 NavigationEntry
* entry
= controller_
.GetVisibleEntry();
569 return entry
? entry
->GetVirtualURL() : GURL::EmptyGURL();
572 const GURL
& WebContentsImpl::GetVisibleURL() const {
573 // We may not have a navigation entry yet.
574 NavigationEntry
* entry
= controller_
.GetVisibleEntry();
575 return entry
? entry
->GetVirtualURL() : GURL::EmptyGURL();
578 const GURL
& WebContentsImpl::GetLastCommittedURL() const {
579 // We may not have a navigation entry yet.
580 NavigationEntry
* entry
= controller_
.GetLastCommittedEntry();
581 return entry
? entry
->GetVirtualURL() : GURL::EmptyGURL();
584 WebContentsDelegate
* WebContentsImpl::GetDelegate() {
588 void WebContentsImpl::SetDelegate(WebContentsDelegate
* delegate
) {
589 // TODO(cbentzel): remove this debugging code?
590 if (delegate
== delegate_
)
593 delegate_
->Detach(this);
594 delegate_
= delegate
;
596 delegate_
->Attach(this);
597 // Ensure the visible RVH reflects the new delegate's preferences.
599 view_
->SetOverscrollControllerEnabled(delegate
->CanOverscrollContent());
603 RenderProcessHost
* WebContentsImpl::GetRenderProcessHost() const {
604 RenderViewHostImpl
* host
= GetRenderManager()->current_host();
605 return host
? host
->GetProcess() : NULL
;
608 RenderFrameHost
* WebContentsImpl::GetMainFrame() {
609 return frame_tree_
.root()->current_frame_host();
612 RenderFrameHost
* WebContentsImpl::GetFocusedFrame() {
613 if (!frame_tree_
.GetFocusedFrame())
615 return frame_tree_
.GetFocusedFrame()->current_frame_host();
618 void WebContentsImpl::ForEachFrame(
619 const base::Callback
<void(RenderFrameHost
*)>& on_frame
) {
620 frame_tree_
.ForEach(base::Bind(&ForEachFrameInternal
, on_frame
));
623 void WebContentsImpl::SendToAllFrames(IPC::Message
* message
) {
624 ForEachFrame(base::Bind(&SendToAllFramesInternal
, message
));
628 RenderViewHost
* WebContentsImpl::GetRenderViewHost() const {
629 return GetRenderManager()->current_host();
632 WebContents
* WebContentsImpl::GetEmbedderWebContents() const {
633 BrowserPluginGuest
* guest
= GetBrowserPluginGuest();
635 return guest
->embedder_web_contents();
639 int WebContentsImpl::GetEmbeddedInstanceID() const {
640 BrowserPluginGuest
* guest
= GetBrowserPluginGuest();
642 return guest
->instance_id();
646 int WebContentsImpl::GetRoutingID() const {
647 if (!GetRenderViewHost())
648 return MSG_ROUTING_NONE
;
650 return GetRenderViewHost()->GetRoutingID();
653 int WebContentsImpl::GetFullscreenWidgetRoutingID() const {
654 return fullscreen_widget_routing_id_
;
657 RenderWidgetHostView
* WebContentsImpl::GetRenderWidgetHostView() const {
658 return GetRenderManager()->GetRenderWidgetHostView();
661 RenderWidgetHostViewPort
* WebContentsImpl::GetRenderWidgetHostViewPort() const {
662 BrowserPluginGuest
* guest
= GetBrowserPluginGuest();
663 if (guest
&& guest
->embedder_web_contents()) {
664 return guest
->embedder_web_contents()->GetRenderWidgetHostViewPort();
666 return RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
669 RenderWidgetHostView
* WebContentsImpl::GetFullscreenRenderWidgetHostView()
671 RenderWidgetHost
* const widget_host
=
672 RenderWidgetHostImpl::FromID(GetRenderProcessHost()->GetID(),
673 GetFullscreenWidgetRoutingID());
674 return widget_host
? widget_host
->GetView() : NULL
;
677 WebContentsView
* WebContentsImpl::GetView() const {
681 WebUI
* WebContentsImpl::CreateWebUI(const GURL
& url
) {
682 WebUIImpl
* web_ui
= new WebUIImpl(this);
683 WebUIController
* controller
= WebUIControllerFactoryRegistry::GetInstance()->
684 CreateWebUIControllerForURL(web_ui
, url
);
686 web_ui
->AddMessageHandler(new GenericHandler());
687 web_ui
->SetController(controller
);
695 WebUI
* WebContentsImpl::GetWebUI() const {
696 return GetRenderManager()->web_ui() ? GetRenderManager()->web_ui()
697 : GetRenderManager()->pending_web_ui();
700 WebUI
* WebContentsImpl::GetCommittedWebUI() const {
701 return GetRenderManager()->web_ui();
704 void WebContentsImpl::SetUserAgentOverride(const std::string
& override
) {
705 if (GetUserAgentOverride() == override
)
708 renderer_preferences_
.user_agent_override
= override
;
710 // Send the new override string to the renderer.
711 RenderViewHost
* host
= GetRenderViewHost();
713 host
->SyncRendererPrefs();
715 // Reload the page if a load is currently in progress to avoid having
716 // different parts of the page loaded using different user agents.
717 NavigationEntry
* entry
= controller_
.GetVisibleEntry();
718 if (is_loading_
&& entry
!= NULL
&& entry
->GetIsOverridingUserAgent())
719 controller_
.ReloadIgnoringCache(true);
721 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
722 UserAgentOverrideSet(override
));
725 const std::string
& WebContentsImpl::GetUserAgentOverride() const {
726 return renderer_preferences_
.user_agent_override
;
730 void WebContentsImpl::SetParentNativeViewAccessible(
731 gfx::NativeViewAccessible accessible_parent
) {
732 accessible_parent_
= accessible_parent
;
733 if (GetRenderViewHost())
734 GetRenderViewHostImpl()->SetParentNativeViewAccessible(accessible_parent
);
738 const base::string16
& WebContentsImpl::GetTitle() const {
739 // Transient entries take precedence. They are used for interstitial pages
740 // that are shown on top of existing pages.
741 NavigationEntry
* entry
= controller_
.GetTransientEntry();
742 std::string accept_languages
=
743 GetContentClient()->browser()->GetAcceptLangs(
744 GetBrowserContext());
746 return entry
->GetTitleForDisplay(accept_languages
);
748 WebUI
* our_web_ui
= GetRenderManager()->pending_web_ui() ?
749 GetRenderManager()->pending_web_ui() : GetRenderManager()->web_ui();
751 // Don't override the title in view source mode.
752 entry
= controller_
.GetVisibleEntry();
753 if (!(entry
&& entry
->IsViewSourceMode())) {
754 // Give the Web UI the chance to override our title.
755 const base::string16
& title
= our_web_ui
->GetOverriddenTitle();
761 // We use the title for the last committed entry rather than a pending
762 // navigation entry. For example, when the user types in a URL, we want to
763 // keep the old page's title until the new load has committed and we get a new
765 entry
= controller_
.GetLastCommittedEntry();
767 // We make an exception for initial navigations.
768 if (controller_
.IsInitialNavigation()) {
769 // We only want to use the title from the visible entry in one of two cases:
770 // 1. There's already a committed entry for an initial navigation, in which
771 // case we are doing a history navigation in a new tab (e.g., Ctrl+Back).
772 // 2. The pending entry has been explicitly assigned a title to display.
774 // If there's no last committed entry and no assigned title, we should fall
775 // back to |page_title_when_no_navigation_entry_| rather than showing the
778 (controller_
.GetVisibleEntry() &&
779 !controller_
.GetVisibleEntry()->GetTitle().empty())) {
780 entry
= controller_
.GetVisibleEntry();
785 return entry
->GetTitleForDisplay(accept_languages
);
788 // |page_title_when_no_navigation_entry_| is finally used
789 // if no title cannot be retrieved.
790 return page_title_when_no_navigation_entry_
;
793 int32
WebContentsImpl::GetMaxPageID() {
794 return GetMaxPageIDForSiteInstance(GetSiteInstance());
797 int32
WebContentsImpl::GetMaxPageIDForSiteInstance(
798 SiteInstance
* site_instance
) {
799 if (max_page_ids_
.find(site_instance
->GetId()) == max_page_ids_
.end())
800 max_page_ids_
[site_instance
->GetId()] = -1;
802 return max_page_ids_
[site_instance
->GetId()];
805 void WebContentsImpl::UpdateMaxPageID(int32 page_id
) {
806 UpdateMaxPageIDForSiteInstance(GetSiteInstance(), page_id
);
809 void WebContentsImpl::UpdateMaxPageIDForSiteInstance(
810 SiteInstance
* site_instance
, int32 page_id
) {
811 if (GetMaxPageIDForSiteInstance(site_instance
) < page_id
)
812 max_page_ids_
[site_instance
->GetId()] = page_id
;
815 void WebContentsImpl::CopyMaxPageIDsFrom(WebContents
* web_contents
) {
816 WebContentsImpl
* contents
= static_cast<WebContentsImpl
*>(web_contents
);
817 max_page_ids_
= contents
->max_page_ids_
;
820 SiteInstance
* WebContentsImpl::GetSiteInstance() const {
821 return GetRenderManager()->current_host()->GetSiteInstance();
824 SiteInstance
* WebContentsImpl::GetPendingSiteInstance() const {
825 RenderViewHost
* dest_rvh
= GetRenderManager()->pending_render_view_host() ?
826 GetRenderManager()->pending_render_view_host() :
827 GetRenderManager()->current_host();
828 return dest_rvh
->GetSiteInstance();
831 bool WebContentsImpl::IsLoading() const {
835 bool WebContentsImpl::IsWaitingForResponse() const {
836 return waiting_for_response_
;
839 const net::LoadStateWithParam
& WebContentsImpl::GetLoadState() const {
843 const base::string16
& WebContentsImpl::GetLoadStateHost() const {
844 return load_state_host_
;
847 uint64
WebContentsImpl::GetUploadSize() const {
851 uint64
WebContentsImpl::GetUploadPosition() const {
852 return upload_position_
;
855 std::set
<GURL
> WebContentsImpl::GetSitesInTab() const {
856 std::set
<GURL
> sites
;
857 frame_tree_
.ForEach(base::Bind(&CollectSites
,
858 base::Unretained(GetBrowserContext()),
859 base::Unretained(&sites
)));
863 const std::string
& WebContentsImpl::GetEncoding() const {
867 bool WebContentsImpl::DisplayedInsecureContent() const {
868 return displayed_insecure_content_
;
871 void WebContentsImpl::IncrementCapturerCount(const gfx::Size
& capture_size
) {
872 DCHECK(!is_being_destroyed_
);
874 DVLOG(1) << "There are now " << capturer_count_
875 << " capturing(s) of WebContentsImpl@" << this;
877 // Note: This provides a hint to upstream code to size the views optimally
878 // for quality (e.g., to avoid scaling).
879 if (!capture_size
.IsEmpty() && preferred_size_for_capture_
.IsEmpty()) {
880 preferred_size_for_capture_
= capture_size
;
881 OnPreferredSizeChanged(preferred_size_
);
885 void WebContentsImpl::DecrementCapturerCount() {
887 DVLOG(1) << "There are now " << capturer_count_
888 << " capturing(s) of WebContentsImpl@" << this;
889 DCHECK_LE(0, capturer_count_
);
891 if (is_being_destroyed_
)
894 if (capturer_count_
== 0) {
895 const gfx::Size old_size
= preferred_size_for_capture_
;
896 preferred_size_for_capture_
= gfx::Size();
897 OnPreferredSizeChanged(old_size
);
901 DVLOG(1) << "Executing delayed WasHidden().";
906 int WebContentsImpl::GetCapturerCount() const {
907 return capturer_count_
;
910 bool WebContentsImpl::IsCrashed() const {
911 return (crashed_status_
== base::TERMINATION_STATUS_PROCESS_CRASHED
||
912 crashed_status_
== base::TERMINATION_STATUS_ABNORMAL_TERMINATION
||
913 crashed_status_
== base::TERMINATION_STATUS_PROCESS_WAS_KILLED
);
916 void WebContentsImpl::SetIsCrashed(base::TerminationStatus status
,
918 if (status
== crashed_status_
)
921 crashed_status_
= status
;
922 crashed_error_code_
= error_code
;
923 NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB
);
926 base::TerminationStatus
WebContentsImpl::GetCrashedStatus() const {
927 return crashed_status_
;
930 bool WebContentsImpl::IsBeingDestroyed() const {
931 return is_being_destroyed_
;
934 void WebContentsImpl::NotifyNavigationStateChanged(unsigned changed_flags
) {
936 delegate_
->NavigationStateChanged(this, changed_flags
);
939 base::TimeTicks
WebContentsImpl::GetLastActiveTime() const {
940 return last_active_time_
;
943 void WebContentsImpl::WasShown() {
944 controller_
.SetActive(true);
945 RenderWidgetHostViewPort
* rwhv
=
946 RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
949 #if defined(OS_MACOSX)
950 rwhv
->SetActive(true);
954 last_active_time_
= base::TimeTicks::Now();
956 // The resize rect might have changed while this was inactive -- send the new
957 // one to make sure it's up to date.
958 RenderViewHostImpl
* rvh
=
959 static_cast<RenderViewHostImpl
*>(GetRenderViewHost());
961 rvh
->ResizeRectChanged(GetRootWindowResizerRect());
964 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, WasShown());
966 should_normally_be_visible_
= true;
969 void WebContentsImpl::WasHidden() {
970 // If there are entities capturing screenshots or video (e.g., mirroring),
971 // don't activate the "disable rendering" optimization.
972 if (capturer_count_
== 0) {
973 // |GetRenderViewHost()| can be NULL if the user middle clicks a link to
974 // open a tab in the background, then closes the tab before selecting it.
975 // This is because closing the tab calls WebContentsImpl::Destroy(), which
976 // removes the |GetRenderViewHost()|; then when we actually destroy the
977 // window, OnWindowPosChanged() notices and calls WasHidden() (which
979 RenderWidgetHostViewPort
* rwhv
=
980 RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
985 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, WasHidden());
987 should_normally_be_visible_
= false;
990 bool WebContentsImpl::NeedToFireBeforeUnload() {
991 // TODO(creis): Should we fire even for interstitial pages?
992 return WillNotifyDisconnection() &&
993 !ShowingInterstitialPage() &&
994 !static_cast<RenderViewHostImpl
*>(
995 GetRenderViewHost())->SuddenTerminationAllowed();
998 void WebContentsImpl::Stop() {
999 GetRenderManager()->Stop();
1000 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, NavigationStopped());
1003 WebContents
* WebContentsImpl::Clone() {
1004 // We use our current SiteInstance since the cloned entry will use it anyway.
1005 // We pass our own opener so that the cloned page can access it if it was
1007 CreateParams
create_params(GetBrowserContext(), GetSiteInstance());
1008 create_params
.initial_size
= view_
->GetContainerSize();
1009 WebContentsImpl
* tc
= CreateWithOpener(create_params
, opener_
);
1010 tc
->GetController().CopyStateFrom(controller_
);
1011 FOR_EACH_OBSERVER(WebContentsObserver
,
1013 DidCloneToNewWebContents(this, tc
));
1017 void WebContentsImpl::Observe(int type
,
1018 const NotificationSource
& source
,
1019 const NotificationDetails
& details
) {
1021 case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED
: {
1022 RenderWidgetHost
* host
= Source
<RenderWidgetHost
>(source
).ptr();
1023 for (PendingWidgetViews::iterator i
= pending_widget_views_
.begin();
1024 i
!= pending_widget_views_
.end(); ++i
) {
1025 if (host
->GetView() == i
->second
) {
1026 pending_widget_views_
.erase(i
);
1037 WebContents
* WebContentsImpl::GetWebContents() {
1041 void WebContentsImpl::Init(const WebContents::CreateParams
& params
) {
1042 // This is set before initializing the render manager since
1043 // RenderFrameHostManager::Init calls back into us via its delegate to ask if
1044 // it should be hidden.
1045 should_normally_be_visible_
= !params
.initially_hidden
;
1047 GetRenderManager()->Init(
1048 params
.browser_context
, params
.site_instance
, params
.routing_id
,
1049 params
.main_frame_routing_id
);
1051 view_
.reset(GetContentClient()->browser()->
1052 OverrideCreateWebContentsView(this, &render_view_host_delegate_view_
));
1054 CHECK(render_view_host_delegate_view_
);
1056 WebContentsViewDelegate
* delegate
=
1057 GetContentClient()->browser()->GetWebContentsViewDelegate(this);
1059 if (browser_plugin_guest_
) {
1060 scoped_ptr
<WebContentsViewPort
> platform_view(CreateWebContentsView(
1061 this, delegate
, &render_view_host_delegate_view_
));
1063 WebContentsViewGuest
* rv
= new WebContentsViewGuest(
1064 this, browser_plugin_guest_
.get(), platform_view
.Pass(),
1065 render_view_host_delegate_view_
);
1066 render_view_host_delegate_view_
= rv
;
1069 // Regular WebContentsView.
1070 view_
.reset(CreateWebContentsView(
1071 this, delegate
, &render_view_host_delegate_view_
));
1073 CHECK(render_view_host_delegate_view_
);
1077 gfx::Size initial_size
= params
.initial_size
;
1078 view_
->CreateView(initial_size
, params
.context
);
1080 // Listen for whether our opener gets destroyed.
1082 AddDestructionObserver(opener_
);
1084 registrar_
.Add(this,
1085 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED
,
1086 NotificationService::AllBrowserContextsAndSources());
1087 #if defined(OS_ANDROID)
1088 java_bridge_dispatcher_host_manager_
.reset(
1089 new JavaBridgeDispatcherHostManager(this));
1090 date_time_chooser_
.reset(new DateTimeChooserAndroid());
1094 void WebContentsImpl::OnWebContentsDestroyed(WebContentsImpl
* web_contents
) {
1095 RemoveDestructionObserver(web_contents
);
1097 // Clear the opener if it has been closed.
1098 if (web_contents
== opener_
) {
1102 // Clear a pending contents that has been closed before being shown.
1103 for (PendingContents::iterator iter
= pending_contents_
.begin();
1104 iter
!= pending_contents_
.end();
1106 if (iter
->second
!= web_contents
)
1108 pending_contents_
.erase(iter
);
1114 void WebContentsImpl::AddDestructionObserver(WebContentsImpl
* web_contents
) {
1115 if (!ContainsKey(destruction_observers_
, web_contents
)) {
1116 destruction_observers_
[web_contents
] =
1117 new DestructionObserver(this, web_contents
);
1121 void WebContentsImpl::RemoveDestructionObserver(WebContentsImpl
* web_contents
) {
1122 DestructionObservers::iterator iter
=
1123 destruction_observers_
.find(web_contents
);
1124 if (iter
!= destruction_observers_
.end()) {
1125 delete destruction_observers_
[web_contents
];
1126 destruction_observers_
.erase(iter
);
1130 void WebContentsImpl::AddObserver(WebContentsObserver
* observer
) {
1131 observers_
.AddObserver(observer
);
1134 void WebContentsImpl::RemoveObserver(WebContentsObserver
* observer
) {
1135 observers_
.RemoveObserver(observer
);
1138 void WebContentsImpl::Activate() {
1140 delegate_
->ActivateContents(this);
1143 void WebContentsImpl::Deactivate() {
1145 delegate_
->DeactivateContents(this);
1148 void WebContentsImpl::LostCapture() {
1150 delegate_
->LostCapture();
1153 void WebContentsImpl::RenderWidgetDeleted(
1154 RenderWidgetHostImpl
* render_widget_host
) {
1155 if (is_being_destroyed_
) {
1156 // |created_widgets_| might have been destroyed.
1160 std::set
<RenderWidgetHostImpl
*>::iterator iter
=
1161 created_widgets_
.find(render_widget_host
);
1162 if (iter
!= created_widgets_
.end())
1163 created_widgets_
.erase(iter
);
1165 if (render_widget_host
&&
1166 render_widget_host
->GetRoutingID() == fullscreen_widget_routing_id_
) {
1167 if (delegate_
&& delegate_
->EmbedsFullscreenWidget())
1168 delegate_
->ToggleFullscreenModeForTab(this, false);
1169 FOR_EACH_OBSERVER(WebContentsObserver
,
1171 DidDestroyFullscreenWidget(
1172 fullscreen_widget_routing_id_
));
1173 fullscreen_widget_routing_id_
= MSG_ROUTING_NONE
;
1177 bool WebContentsImpl::PreHandleKeyboardEvent(
1178 const NativeWebKeyboardEvent
& event
,
1179 bool* is_keyboard_shortcut
) {
1181 delegate_
->PreHandleKeyboardEvent(this, event
, is_keyboard_shortcut
);
1184 void WebContentsImpl::HandleKeyboardEvent(const NativeWebKeyboardEvent
& event
) {
1185 if (browser_plugin_embedder_
&&
1186 browser_plugin_embedder_
->HandleKeyboardEvent(event
)) {
1191 delegate_
->HandleKeyboardEvent(this, event
);
1194 bool WebContentsImpl::HandleWheelEvent(
1195 const blink::WebMouseWheelEvent
& event
) {
1196 #if !defined(OS_MACOSX)
1197 // On platforms other than Mac, control+mousewheel changes zoom. On Mac, this
1198 // isn't done for two reasons:
1199 // -the OS already has a gesture to do this through pinch-zoom
1200 // -if a user starts an inertial scroll, let's go, and presses control
1201 // (i.e. control+tab) then the OS's buffered scroll events will come in
1202 // with control key set which isn't what the user wants
1204 event
.wheelTicksY
&&
1205 (event
.modifiers
& blink::WebInputEvent::ControlKey
)) {
1206 delegate_
->ContentsZoomChange(event
.wheelTicksY
> 0);
1213 bool WebContentsImpl::PreHandleGestureEvent(
1214 const blink::WebGestureEvent
& event
) {
1215 return delegate_
&& delegate_
->PreHandleGestureEvent(this, event
);
1219 gfx::NativeViewAccessible
WebContentsImpl::GetParentNativeViewAccessible() {
1220 return accessible_parent_
;
1224 void WebContentsImpl::HandleMouseDown() {
1226 delegate_
->HandleMouseDown();
1229 void WebContentsImpl::HandleMouseUp() {
1231 delegate_
->HandleMouseUp();
1234 void WebContentsImpl::HandlePointerActivate() {
1236 delegate_
->HandlePointerActivate();
1239 void WebContentsImpl::HandleGestureBegin() {
1241 delegate_
->HandleGestureBegin();
1244 void WebContentsImpl::HandleGestureEnd() {
1246 delegate_
->HandleGestureEnd();
1249 void WebContentsImpl::ToggleFullscreenMode(bool enter_fullscreen
) {
1250 // This method is being called to enter or leave renderer-initiated fullscreen
1251 // mode. Either way, make sure any existing fullscreen widget is shut down
1253 RenderWidgetHostView
* const widget_view
= GetFullscreenRenderWidgetHostView();
1255 RenderWidgetHostImpl::From(widget_view
->GetRenderWidgetHost())->Shutdown();
1258 delegate_
->ToggleFullscreenModeForTab(this, enter_fullscreen
);
1260 FOR_EACH_OBSERVER(WebContentsObserver
,
1262 DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab()));
1265 bool WebContentsImpl::IsFullscreenForCurrentTab() const {
1266 return delegate_
? delegate_
->IsFullscreenForTabOrPending(this) : false;
1269 void WebContentsImpl::RequestToLockMouse(bool user_gesture
,
1270 bool last_unlocked_by_target
) {
1272 delegate_
->RequestToLockMouse(this, user_gesture
, last_unlocked_by_target
);
1274 GotResponseToLockMouseRequest(false);
1278 void WebContentsImpl::LostMouseLock() {
1280 delegate_
->LostMouseLock();
1283 void WebContentsImpl::CreateNewWindow(
1284 int render_process_id
,
1286 int main_frame_route_id
,
1287 const ViewHostMsg_CreateWindow_Params
& params
,
1288 SessionStorageNamespace
* session_storage_namespace
) {
1289 // We usually create the new window in the same BrowsingInstance (group of
1290 // script-related windows), by passing in the current SiteInstance. However,
1291 // if the opener is being suppressed (in a non-guest), we create a new
1292 // SiteInstance in its own BrowsingInstance.
1293 bool is_guest
= GetRenderProcessHost()->IsGuest();
1295 // If the opener is to be suppressed, the new window can be in any process.
1296 // Since routing ids are process specific, we must not have one passed in
1297 // as argument here.
1298 DCHECK(!params
.opener_suppressed
|| route_id
== MSG_ROUTING_NONE
);
1300 scoped_refptr
<SiteInstance
> site_instance
=
1301 params
.opener_suppressed
&& !is_guest
?
1302 SiteInstance::CreateForURL(GetBrowserContext(), params
.target_url
) :
1305 // A message to create a new window can only come from the active process for
1306 // this WebContentsImpl instance. If any other process sends the request,
1307 // it is invalid and the process must be terminated.
1308 if (GetRenderProcessHost()->GetID() != render_process_id
) {
1309 base::ProcessHandle process_handle
=
1310 RenderProcessHost::FromID(render_process_id
)->GetHandle();
1311 if (process_handle
!= base::kNullProcessHandle
) {
1313 base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWindow"));
1314 base::KillProcess(process_handle
, content::RESULT_CODE_KILLED
, false);
1319 // We must assign the SessionStorageNamespace before calling Init().
1321 // http://crbug.com/142685
1322 const std::string
& partition_id
=
1323 GetContentClient()->browser()->
1324 GetStoragePartitionIdForSite(GetBrowserContext(),
1325 site_instance
->GetSiteURL());
1326 StoragePartition
* partition
= BrowserContext::GetStoragePartition(
1327 GetBrowserContext(), site_instance
.get());
1328 DOMStorageContextWrapper
* dom_storage_context
=
1329 static_cast<DOMStorageContextWrapper
*>(partition
->GetDOMStorageContext());
1330 SessionStorageNamespaceImpl
* session_storage_namespace_impl
=
1331 static_cast<SessionStorageNamespaceImpl
*>(session_storage_namespace
);
1332 CHECK(session_storage_namespace_impl
->IsFromContext(dom_storage_context
));
1335 !delegate_
->ShouldCreateWebContents(this,
1337 params
.window_container_type
,
1341 session_storage_namespace
)) {
1342 if (route_id
!= MSG_ROUTING_NONE
&&
1343 !RenderViewHost::FromID(render_process_id
, route_id
)) {
1344 // If the embedder didn't create a WebContents for this route, we need to
1345 // delete the RenderView that had already been created.
1346 Send(new ViewMsg_Close(route_id
));
1348 GetRenderViewHost()->GetProcess()->ResumeRequestsForView(route_id
);
1349 GetRenderViewHost()->GetProcess()->ResumeRequestsForView(
1350 main_frame_route_id
);
1354 // Create the new web contents. This will automatically create the new
1355 // WebContentsView. In the future, we may want to create the view separately.
1356 WebContentsImpl
* new_contents
=
1357 new WebContentsImpl(GetBrowserContext(),
1358 params
.opener_suppressed
? NULL
: this);
1360 new_contents
->GetController().SetSessionStorageNamespace(
1362 session_storage_namespace
);
1363 CreateParams
create_params(GetBrowserContext(), site_instance
.get());
1364 create_params
.routing_id
= route_id
;
1365 create_params
.main_frame_routing_id
= main_frame_route_id
;
1367 create_params
.context
= view_
->GetNativeView();
1368 create_params
.initial_size
= view_
->GetContainerSize();
1370 // This makes |new_contents| act as a guest.
1371 // For more info, see comment above class BrowserPluginGuest.
1372 int instance_id
= GetBrowserPluginGuestManager()->get_next_instance_id();
1373 WebContentsImpl
* new_contents_impl
=
1374 static_cast<WebContentsImpl
*>(new_contents
);
1375 BrowserPluginGuest::CreateWithOpener(instance_id
,
1376 new_contents_impl
->opener() != NULL
,
1378 GetBrowserPluginGuest());
1380 if (params
.disposition
== NEW_BACKGROUND_TAB
)
1381 create_params
.initially_hidden
= true;
1382 new_contents
->Init(create_params
);
1384 // Save the window for later if we're not suppressing the opener (since it
1385 // will be shown immediately).
1386 if (!params
.opener_suppressed
) {
1388 WebContentsViewPort
* new_view
= new_contents
->view_
.get();
1390 // TODO(brettw): It seems bogus that we have to call this function on the
1391 // newly created object and give it one of its own member variables.
1392 new_view
->CreateViewForWidget(new_contents
->GetRenderViewHost());
1394 // Save the created window associated with the route so we can show it
1396 DCHECK_NE(MSG_ROUTING_NONE
, route_id
);
1397 pending_contents_
[route_id
] = new_contents
;
1398 AddDestructionObserver(new_contents
);
1402 delegate_
->WebContentsCreated(
1403 this, params
.opener_render_frame_id
, params
.frame_name
,
1404 params
.target_url
, new_contents
);
1407 if (params
.opener_suppressed
) {
1408 // When the opener is suppressed, the original renderer cannot access the
1409 // new window. As a result, we need to show and navigate the window here.
1410 bool was_blocked
= false;
1412 gfx::Rect initial_pos
;
1413 delegate_
->AddNewContents(
1414 this, new_contents
, params
.disposition
, initial_pos
,
1415 params
.user_gesture
, &was_blocked
);
1418 OpenURLParams
open_params(params
.target_url
,
1421 PAGE_TRANSITION_LINK
,
1422 true /* is_renderer_initiated */);
1423 open_params
.user_gesture
= params
.user_gesture
;
1424 new_contents
->OpenURL(open_params
);
1429 void WebContentsImpl::CreateNewWidget(int render_process_id
,
1431 blink::WebPopupType popup_type
) {
1432 CreateNewWidget(render_process_id
, route_id
, false, popup_type
);
1435 void WebContentsImpl::CreateNewFullscreenWidget(int render_process_id
,
1437 CreateNewWidget(render_process_id
, route_id
, true, blink::WebPopupTypeNone
);
1440 void WebContentsImpl::CreateNewWidget(int render_process_id
,
1443 blink::WebPopupType popup_type
) {
1444 RenderProcessHost
* process
= GetRenderProcessHost();
1445 // A message to create a new widget can only come from the active process for
1446 // this WebContentsImpl instance. If any other process sends the request,
1447 // it is invalid and the process must be terminated.
1448 if (process
->GetID() != render_process_id
) {
1449 base::ProcessHandle process_handle
=
1450 RenderProcessHost::FromID(render_process_id
)->GetHandle();
1451 if (process_handle
!= base::kNullProcessHandle
) {
1453 base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWidget"));
1454 base::KillProcess(process_handle
, content::RESULT_CODE_KILLED
, false);
1459 RenderWidgetHostImpl
* widget_host
=
1460 new RenderWidgetHostImpl(this, process
, route_id
, IsHidden());
1461 created_widgets_
.insert(widget_host
);
1463 RenderWidgetHostViewPort
* widget_view
= RenderWidgetHostViewPort::FromRWHV(
1464 view_
->CreateViewForPopupWidget(widget_host
));
1467 if (!is_fullscreen
) {
1468 // Popups should not get activated.
1469 widget_view
->SetPopupType(popup_type
);
1471 // Save the created widget associated with the route so we can show it later.
1472 pending_widget_views_
[route_id
] = widget_view
;
1474 #if defined(OS_MACOSX)
1475 // A RenderWidgetHostViewMac has lifetime scoped to the view. We'll retain it
1476 // to allow it to survive the trip without being hosted.
1477 base::mac::NSObjectRetain(widget_view
->GetNativeView());
1481 void WebContentsImpl::ShowCreatedWindow(int route_id
,
1482 WindowOpenDisposition disposition
,
1483 const gfx::Rect
& initial_pos
,
1484 bool user_gesture
) {
1485 WebContentsImpl
* contents
= GetCreatedWindow(route_id
);
1487 WebContentsDelegate
* delegate
= GetDelegate();
1489 delegate
->AddNewContents(
1490 this, contents
, disposition
, initial_pos
, user_gesture
, NULL
);
1495 void WebContentsImpl::ShowCreatedWidget(int route_id
,
1496 const gfx::Rect
& initial_pos
) {
1497 ShowCreatedWidget(route_id
, false, initial_pos
);
1500 void WebContentsImpl::ShowCreatedFullscreenWidget(int route_id
) {
1501 ShowCreatedWidget(route_id
, true, gfx::Rect());
1504 void WebContentsImpl::ShowCreatedWidget(int route_id
,
1506 const gfx::Rect
& initial_pos
) {
1507 RenderWidgetHostViewPort
* widget_host_view
=
1508 RenderWidgetHostViewPort::FromRWHV(GetCreatedWidget(route_id
));
1509 if (!widget_host_view
)
1511 if (is_fullscreen
) {
1512 DCHECK_EQ(MSG_ROUTING_NONE
, fullscreen_widget_routing_id_
);
1513 fullscreen_widget_routing_id_
= route_id
;
1514 if (delegate_
&& delegate_
->EmbedsFullscreenWidget()) {
1515 widget_host_view
->InitAsChild(GetRenderWidgetHostView()->GetNativeView());
1516 delegate_
->ToggleFullscreenModeForTab(this, true);
1518 widget_host_view
->InitAsFullscreen(GetRenderWidgetHostViewPort());
1520 FOR_EACH_OBSERVER(WebContentsObserver
,
1522 DidShowFullscreenWidget(route_id
));
1523 if (!widget_host_view
->HasFocus())
1524 widget_host_view
->Focus();
1526 widget_host_view
->InitAsPopup(GetRenderWidgetHostViewPort(), initial_pos
);
1529 RenderWidgetHostImpl
* render_widget_host_impl
=
1530 RenderWidgetHostImpl::From(widget_host_view
->GetRenderWidgetHost());
1531 render_widget_host_impl
->Init();
1532 // Only allow privileged mouse lock for fullscreen render widget, which is
1533 // used to implement Pepper Flash fullscreen.
1534 render_widget_host_impl
->set_allow_privileged_mouse_lock(is_fullscreen
);
1536 #if defined(OS_MACOSX)
1537 // A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's
1538 // properly embedded (or purposefully ignored) we can release the retain we
1539 // took in CreateNewWidget().
1540 base::mac::NSObjectRelease(widget_host_view
->GetNativeView());
1544 WebContentsImpl
* WebContentsImpl::GetCreatedWindow(int route_id
) {
1545 PendingContents::iterator iter
= pending_contents_
.find(route_id
);
1547 // Certain systems can block the creation of new windows. If we didn't succeed
1548 // in creating one, just return NULL.
1549 if (iter
== pending_contents_
.end()) {
1553 WebContentsImpl
* new_contents
= iter
->second
;
1554 pending_contents_
.erase(route_id
);
1555 RemoveDestructionObserver(new_contents
);
1557 // Don't initialize the guest WebContents immediately.
1558 if (new_contents
->GetRenderProcessHost()->IsGuest())
1559 return new_contents
;
1561 if (!new_contents
->GetRenderProcessHost()->HasConnection() ||
1562 !new_contents
->GetRenderViewHost()->GetView())
1565 // TODO(brettw): It seems bogus to reach into here and initialize the host.
1566 static_cast<RenderViewHostImpl
*>(new_contents
->GetRenderViewHost())->Init();
1567 return new_contents
;
1570 RenderWidgetHostView
* WebContentsImpl::GetCreatedWidget(int route_id
) {
1571 PendingWidgetViews::iterator iter
= pending_widget_views_
.find(route_id
);
1572 if (iter
== pending_widget_views_
.end()) {
1577 RenderWidgetHostView
* widget_host_view
= iter
->second
;
1578 pending_widget_views_
.erase(route_id
);
1580 RenderWidgetHost
* widget_host
= widget_host_view
->GetRenderWidgetHost();
1581 if (!widget_host
->GetProcess()->HasConnection()) {
1582 // The view has gone away or the renderer crashed. Nothing to do.
1586 return widget_host_view
;
1589 void WebContentsImpl::RequestMediaAccessPermission(
1590 const MediaStreamRequest
& request
,
1591 const MediaResponseCallback
& callback
) {
1593 delegate_
->RequestMediaAccessPermission(this, request
, callback
);
1595 callback
.Run(MediaStreamDevices(),
1596 MEDIA_DEVICE_INVALID_STATE
,
1597 scoped_ptr
<MediaStreamUI
>());
1601 SessionStorageNamespace
* WebContentsImpl::GetSessionStorageNamespace(
1602 SiteInstance
* instance
) {
1603 return controller_
.GetSessionStorageNamespace(instance
);
1606 FrameTree
* WebContentsImpl::GetFrameTree() {
1607 return &frame_tree_
;
1610 void WebContentsImpl::AccessibilityEventReceived(
1611 const std::vector
<AXEventNotificationDetails
>& details
) {
1613 WebContentsObserver
, observers_
, AccessibilityEventReceived(details
));
1616 void WebContentsImpl::OnShowValidationMessage(
1617 const gfx::Rect
& anchor_in_root_view
,
1618 const base::string16
& main_text
,
1619 const base::string16
& sub_text
) {
1621 delegate_
->ShowValidationMessage(
1622 this, anchor_in_root_view
, main_text
, sub_text
);
1625 void WebContentsImpl::OnHideValidationMessage() {
1627 delegate_
->HideValidationMessage(this);
1630 void WebContentsImpl::OnMoveValidationMessage(
1631 const gfx::Rect
& anchor_in_root_view
) {
1633 delegate_
->MoveValidationMessage(this, anchor_in_root_view
);
1636 void WebContentsImpl::DidSendScreenRects(RenderWidgetHostImpl
* rwh
) {
1637 if (browser_plugin_embedder_
)
1638 browser_plugin_embedder_
->DidSendScreenRects();
1641 void WebContentsImpl::UpdatePreferredSize(const gfx::Size
& pref_size
) {
1642 const gfx::Size old_size
= GetPreferredSize();
1643 preferred_size_
= pref_size
;
1644 OnPreferredSizeChanged(old_size
);
1647 void WebContentsImpl::ResizeDueToAutoResize(const gfx::Size
& new_size
) {
1649 delegate_
->ResizeDueToAutoResize(this, new_size
);
1652 WebContents
* WebContentsImpl::OpenURL(const OpenURLParams
& params
) {
1656 WebContents
* new_contents
= delegate_
->OpenURLFromTab(this, params
);
1657 return new_contents
;
1660 bool WebContentsImpl::Send(IPC::Message
* message
) {
1661 if (!GetRenderViewHost()) {
1666 return GetRenderViewHost()->Send(message
);
1669 bool WebContentsImpl::NavigateToPendingEntry(
1670 NavigationController::ReloadType reload_type
) {
1671 FrameTreeNode
* node
= frame_tree_
.root();
1673 // If we are using --site-per-process, we should navigate in the FrameTreeNode
1674 // specified in the pending entry.
1675 NavigationEntryImpl
* pending_entry
=
1676 NavigationEntryImpl::FromNavigationEntry(controller_
.GetPendingEntry());
1677 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess
) &&
1678 pending_entry
->frame_tree_node_id() != -1) {
1679 node
= frame_tree_
.FindByID(pending_entry
->frame_tree_node_id());
1682 return node
->navigator()->NavigateToPendingEntry(
1683 node
->current_frame_host(), reload_type
);
1686 void WebContentsImpl::RenderFrameForInterstitialPageCreated(
1687 RenderFrameHost
* render_frame_host
) {
1688 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
1689 RenderFrameForInterstitialPageCreated(render_frame_host
));
1692 void WebContentsImpl::AttachInterstitialPage(
1693 InterstitialPageImpl
* interstitial_page
) {
1694 DCHECK(interstitial_page
);
1695 GetRenderManager()->set_interstitial_page(interstitial_page
);
1697 // Cancel any visible dialogs so that they don't interfere with the
1699 if (dialog_manager_
)
1700 dialog_manager_
->CancelActiveAndPendingDialogs(this);
1702 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
1703 DidAttachInterstitialPage());
1706 void WebContentsImpl::DetachInterstitialPage() {
1707 if (GetInterstitialPage())
1708 GetRenderManager()->remove_interstitial_page();
1709 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
1710 DidDetachInterstitialPage());
1713 void WebContentsImpl::SetHistoryLengthAndPrune(
1714 const SiteInstance
* site_instance
,
1716 int32 minimum_page_id
) {
1717 // SetHistoryLengthAndPrune doesn't work when there are pending cross-site
1718 // navigations. Callers should ensure that this is the case.
1719 if (GetRenderManager()->pending_render_view_host()) {
1723 RenderViewHostImpl
* rvh
= GetRenderViewHostImpl();
1728 if (site_instance
&& rvh
->GetSiteInstance() != site_instance
) {
1732 Send(new ViewMsg_SetHistoryLengthAndPrune(GetRoutingID(),
1737 void WebContentsImpl::FocusThroughTabTraversal(bool reverse
) {
1738 if (ShowingInterstitialPage()) {
1739 GetRenderManager()->interstitial_page()->FocusThroughTabTraversal(reverse
);
1742 GetRenderViewHostImpl()->SetInitialFocus(reverse
);
1745 bool WebContentsImpl::ShowingInterstitialPage() const {
1746 return GetRenderManager()->interstitial_page() != NULL
;
1749 InterstitialPage
* WebContentsImpl::GetInterstitialPage() const {
1750 return GetRenderManager()->interstitial_page();
1753 bool WebContentsImpl::IsSavable() {
1754 // WebKit creates Document object when MIME type is application/xhtml+xml,
1755 // so we also support this MIME type.
1756 return contents_mime_type_
== "text/html" ||
1757 contents_mime_type_
== "text/xml" ||
1758 contents_mime_type_
== "application/xhtml+xml" ||
1759 contents_mime_type_
== "text/plain" ||
1760 contents_mime_type_
== "text/css" ||
1761 net::IsSupportedJavascriptMimeType(contents_mime_type_
.c_str());
1764 void WebContentsImpl::OnSavePage() {
1765 // If we can not save the page, try to download it.
1767 RecordDownloadSource(INITIATED_BY_SAVE_PACKAGE_ON_NON_HTML
);
1768 SaveFrame(GetURL(), Referrer());
1774 // Create the save package and possibly prompt the user for the name to save
1775 // the page as. The user prompt is an asynchronous operation that runs on
1777 save_package_
= new SavePackage(this);
1778 save_package_
->GetSaveInfo();
1781 // Used in automated testing to bypass prompting the user for file names.
1782 // Instead, the names and paths are hard coded rather than running them through
1783 // file name sanitation and extension / mime checking.
1784 bool WebContentsImpl::SavePage(const base::FilePath
& main_file
,
1785 const base::FilePath
& dir_path
,
1786 SavePageType save_type
) {
1787 // Stop the page from navigating.
1790 save_package_
= new SavePackage(this, save_type
, main_file
, dir_path
);
1791 return save_package_
->Init(SavePackageDownloadCreatedCallback());
1794 void WebContentsImpl::SaveFrame(const GURL
& url
,
1795 const Referrer
& referrer
) {
1796 if (!GetURL().is_valid())
1798 bool is_main_frame
= (url
== GetURL());
1800 DownloadManager
* dlm
=
1801 BrowserContext::GetDownloadManager(GetBrowserContext());
1805 if (is_main_frame
) {
1806 const NavigationEntry
* entry
= controller_
.GetLastCommittedEntry();
1808 post_id
= entry
->GetPostID();
1810 scoped_ptr
<DownloadUrlParameters
> params(
1811 DownloadUrlParameters::FromWebContents(this, url
));
1812 params
->set_referrer(referrer
);
1813 params
->set_post_id(post_id
);
1814 params
->set_prefer_cache(true);
1816 params
->set_method("POST");
1817 params
->set_prompt(true);
1818 dlm
->DownloadUrl(params
.Pass());
1821 void WebContentsImpl::GenerateMHTML(
1822 const base::FilePath
& file
,
1823 const base::Callback
<void(int64
)>& callback
) {
1824 MHTMLGenerationManager::GetInstance()->SaveMHTML(this, file
, callback
);
1827 // TODO(nasko): Rename this method to IsVisibleEntry.
1828 bool WebContentsImpl::IsActiveEntry(int32 page_id
) {
1829 NavigationEntryImpl
* visible_entry
=
1830 NavigationEntryImpl::FromNavigationEntry(controller_
.GetVisibleEntry());
1831 return (visible_entry
!= NULL
&&
1832 visible_entry
->site_instance() == GetSiteInstance() &&
1833 visible_entry
->GetPageID() == page_id
);
1836 const std::string
& WebContentsImpl::GetContentsMimeType() const {
1837 return contents_mime_type_
;
1840 bool WebContentsImpl::WillNotifyDisconnection() const {
1841 return notify_disconnection_
;
1844 void WebContentsImpl::SetOverrideEncoding(const std::string
& encoding
) {
1845 SetEncoding(encoding
);
1846 Send(new ViewMsg_SetPageEncoding(GetRoutingID(), encoding
));
1849 void WebContentsImpl::ResetOverrideEncoding() {
1851 Send(new ViewMsg_ResetPageEncodingToDefault(GetRoutingID()));
1854 RendererPreferences
* WebContentsImpl::GetMutableRendererPrefs() {
1855 return &renderer_preferences_
;
1858 void WebContentsImpl::Close() {
1859 Close(GetRenderViewHost());
1862 void WebContentsImpl::DragSourceEndedAt(int client_x
, int client_y
,
1863 int screen_x
, int screen_y
, blink::WebDragOperation operation
) {
1864 if (browser_plugin_embedder_
.get())
1865 browser_plugin_embedder_
->DragSourceEndedAt(client_x
, client_y
,
1866 screen_x
, screen_y
, operation
);
1867 if (GetRenderViewHost())
1868 GetRenderViewHostImpl()->DragSourceEndedAt(client_x
, client_y
,
1869 screen_x
, screen_y
, operation
);
1872 void WebContentsImpl::DragSourceMovedTo(int client_x
, int client_y
,
1873 int screen_x
, int screen_y
) {
1874 if (browser_plugin_embedder_
.get())
1875 browser_plugin_embedder_
->DragSourceMovedTo(client_x
, client_y
,
1876 screen_x
, screen_y
);
1877 if (GetRenderViewHost())
1878 GetRenderViewHostImpl()->DragSourceMovedTo(client_x
, client_y
,
1879 screen_x
, screen_y
);
1882 void WebContentsImpl::DidGetResourceResponseStart(
1883 const ResourceRequestDetails
& details
) {
1884 controller_
.ssl_manager()->DidStartResourceResponse(details
);
1886 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
1887 DidGetResourceResponseStart(details
));
1889 // TODO(avi): Remove. http://crbug.com/170921
1890 NotificationService::current()->Notify(
1891 NOTIFICATION_RESOURCE_RESPONSE_STARTED
,
1892 Source
<WebContents
>(this),
1893 Details
<const ResourceRequestDetails
>(&details
));
1896 void WebContentsImpl::DidGetRedirectForResourceRequest(
1897 RenderViewHost
* render_view_host
,
1898 const ResourceRedirectDetails
& details
) {
1899 controller_
.ssl_manager()->DidReceiveResourceRedirect(details
);
1902 WebContentsObserver
,
1904 DidGetRedirectForResourceRequest(render_view_host
, details
));
1906 // TODO(avi): Remove. http://crbug.com/170921
1907 NotificationService::current()->Notify(
1908 NOTIFICATION_RESOURCE_RECEIVED_REDIRECT
,
1909 Source
<WebContents
>(this),
1910 Details
<const ResourceRedirectDetails
>(&details
));
1913 void WebContentsImpl::SystemDragEnded() {
1914 if (GetRenderViewHost())
1915 GetRenderViewHostImpl()->DragSourceSystemDragEnded();
1917 delegate_
->DragEnded();
1918 if (browser_plugin_embedder_
.get())
1919 browser_plugin_embedder_
->SystemDragEnded();
1922 void WebContentsImpl::UserGestureDone() {
1926 void WebContentsImpl::SetClosedByUserGesture(bool value
) {
1927 closed_by_user_gesture_
= value
;
1930 bool WebContentsImpl::GetClosedByUserGesture() const {
1931 return closed_by_user_gesture_
;
1934 double WebContentsImpl::GetZoomLevel() const {
1935 HostZoomMapImpl
* zoom_map
= static_cast<HostZoomMapImpl
*>(
1936 HostZoomMap::GetForBrowserContext(GetBrowserContext()));
1941 if (temporary_zoom_settings_
) {
1942 zoom_level
= zoom_map
->GetTemporaryZoomLevel(
1943 GetRenderProcessHost()->GetID(), GetRenderViewHost()->GetRoutingID());
1946 NavigationEntry
* entry
= GetController().GetLastCommittedEntry();
1947 // Since zoom map is updated using rewritten URL, use rewritten URL
1948 // to get the zoom level.
1949 url
= entry
? entry
->GetURL() : GURL::EmptyGURL();
1950 zoom_level
= zoom_map
->GetZoomLevelForHostAndScheme(url
.scheme(),
1951 net::GetHostOrSpecFromURL(url
));
1956 int WebContentsImpl::GetZoomPercent(bool* enable_increment
,
1957 bool* enable_decrement
) const {
1958 *enable_decrement
= *enable_increment
= false;
1959 // Calculate the zoom percent from the factor. Round up to the nearest whole
1961 int percent
= static_cast<int>(
1962 ZoomLevelToZoomFactor(GetZoomLevel()) * 100 + 0.5);
1963 *enable_decrement
= percent
> minimum_zoom_percent_
;
1964 *enable_increment
= percent
< maximum_zoom_percent_
;
1968 void WebContentsImpl::ViewSource() {
1972 NavigationEntry
* entry
= GetController().GetLastCommittedEntry();
1976 delegate_
->ViewSourceForTab(this, entry
->GetURL());
1979 void WebContentsImpl::ViewFrameSource(const GURL
& url
,
1980 const PageState
& page_state
) {
1984 delegate_
->ViewSourceForFrame(this, url
, page_state
);
1987 int WebContentsImpl::GetMinimumZoomPercent() const {
1988 return minimum_zoom_percent_
;
1991 int WebContentsImpl::GetMaximumZoomPercent() const {
1992 return maximum_zoom_percent_
;
1995 gfx::Size
WebContentsImpl::GetPreferredSize() const {
1996 return capturer_count_
== 0 ? preferred_size_
: preferred_size_for_capture_
;
1999 bool WebContentsImpl::GotResponseToLockMouseRequest(bool allowed
) {
2000 return GetRenderViewHost() ?
2001 GetRenderViewHostImpl()->GotResponseToLockMouseRequest(allowed
) : false;
2004 bool WebContentsImpl::HasOpener() const {
2005 return opener_
!= NULL
;
2008 void WebContentsImpl::DidChooseColorInColorChooser(SkColor color
) {
2009 Send(new ViewMsg_DidChooseColorResponse(
2010 GetRoutingID(), color_chooser_identifier_
, color
));
2013 void WebContentsImpl::DidEndColorChooser() {
2014 Send(new ViewMsg_DidEndColorChooser(GetRoutingID(),
2015 color_chooser_identifier_
));
2016 color_chooser_
.reset();
2017 color_chooser_identifier_
= 0;
2020 int WebContentsImpl::DownloadImage(const GURL
& url
,
2022 uint32_t max_bitmap_size
,
2023 const ImageDownloadCallback
& callback
) {
2024 RenderViewHost
* host
= GetRenderViewHost();
2025 int id
= StartDownload(host
, url
, is_favicon
, max_bitmap_size
);
2026 image_download_map_
[id
] = callback
;
2030 bool WebContentsImpl::IsSubframe() const {
2031 return is_subframe_
;
2034 void WebContentsImpl::SetZoomLevel(double level
) {
2035 Send(new ViewMsg_SetZoomLevel(GetRoutingID(), level
));
2036 BrowserPluginEmbedder
* embedder
= GetBrowserPluginEmbedder();
2038 embedder
->SetZoomLevel(level
);
2041 void WebContentsImpl::Find(int request_id
,
2042 const base::string16
& search_text
,
2043 const blink::WebFindOptions
& options
) {
2044 Send(new ViewMsg_Find(GetRoutingID(), request_id
, search_text
, options
));
2047 void WebContentsImpl::StopFinding(StopFindAction action
) {
2048 Send(new ViewMsg_StopFinding(GetRoutingID(), action
));
2051 bool WebContentsImpl::FocusLocationBarByDefault() {
2052 NavigationEntry
* entry
= controller_
.GetVisibleEntry();
2053 if (entry
&& entry
->GetURL() == GURL(kAboutBlankURL
))
2055 return delegate_
&& delegate_
->ShouldFocusLocationBarByDefault(this);
2058 void WebContentsImpl::SetFocusToLocationBar(bool select_all
) {
2060 delegate_
->SetFocusToLocationBar(select_all
);
2063 void WebContentsImpl::DidStartProvisionalLoad(
2064 RenderFrameHostImpl
* render_frame_host
,
2065 int parent_routing_id
,
2066 const GURL
& validated_url
,
2068 bool is_iframe_srcdoc
) {
2069 bool is_main_frame
= render_frame_host
->frame_tree_node()->IsMainFrame();
2071 DidChangeLoadProgress(0);
2073 // Notify observers about the start of the provisional load.
2074 int render_frame_id
= render_frame_host
->GetRoutingID();
2075 RenderViewHost
* render_view_host
= render_frame_host
->render_view_host();
2076 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2077 DidStartProvisionalLoadForFrame(
2078 render_frame_id
, parent_routing_id
, is_main_frame
,
2079 validated_url
, is_error_page
, is_iframe_srcdoc
,
2082 if (is_main_frame
) {
2084 WebContentsObserver
,
2086 ProvisionalChangeToMainFrameUrl(validated_url
,
2087 render_frame_host
));
2091 void WebContentsImpl::DidFailProvisionalLoadWithError(
2092 RenderFrameHostImpl
* render_frame_host
,
2093 const FrameHostMsg_DidFailProvisionalLoadWithError_Params
& params
) {
2094 GURL
validated_url(params
.url
);
2095 int render_frame_id
= render_frame_host
->GetRoutingID();
2096 bool is_main_frame
= render_frame_host
->frame_tree_node()->IsMainFrame();
2097 RenderViewHost
* render_view_host
= render_frame_host
->render_view_host();
2099 WebContentsObserver
,
2101 DidFailProvisionalLoad(render_frame_id
,
2102 params
.frame_unique_name
,
2106 params
.error_description
,
2110 void WebContentsImpl::DidFailLoadWithError(
2111 RenderFrameHostImpl
* render_frame_host
,
2114 const base::string16
& error_description
) {
2115 int render_frame_id
= render_frame_host
->GetRoutingID();
2116 bool is_main_frame
= render_frame_host
->frame_tree_node()->IsMainFrame();
2117 RenderViewHost
* render_view_host
= render_frame_host
->render_view_host();
2118 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2119 DidFailLoad(render_frame_id
, url
, is_main_frame
, error_code
,
2120 error_description
, render_view_host
));
2123 void WebContentsImpl::NotifyChangedNavigationState(
2124 InvalidateTypes changed_flags
) {
2125 NotifyNavigationStateChanged(changed_flags
);
2128 void WebContentsImpl::AboutToNavigateRenderFrame(
2129 RenderFrameHostImpl
* render_frame_host
) {
2130 // Notify observers that we will navigate in this RenderView.
2131 RenderViewHost
* render_view_host
= render_frame_host
->render_view_host();
2133 WebContentsObserver
,
2135 AboutToNavigateRenderView(render_view_host
));
2138 void WebContentsImpl::DidStartNavigationToPendingEntry(
2139 RenderFrameHostImpl
* render_frame_host
,
2141 NavigationController::ReloadType reload_type
) {
2142 // Notify observers about navigation.
2144 WebContentsObserver
,
2146 DidStartNavigationToPendingEntry(url
, reload_type
));
2149 void WebContentsImpl::RequestOpenURL(RenderFrameHostImpl
* render_frame_host
,
2150 const OpenURLParams
& params
) {
2151 int source_render_frame_id
= render_frame_host
->GetRoutingID();
2152 WebContents
* new_contents
= OpenURL(params
);
2155 // Notify observers.
2156 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2157 DidOpenRequestedURL(new_contents
,
2162 source_render_frame_id
));
2166 void WebContentsImpl::DidRedirectProvisionalLoad(
2167 RenderFrameHostImpl
* render_frame_host
,
2168 const GURL
& validated_target_url
) {
2169 // Notify observers about the provisional change in the main frame URL.
2171 WebContentsObserver
,
2173 ProvisionalChangeToMainFrameUrl(validated_target_url
,
2174 render_frame_host
));
2177 void WebContentsImpl::DidCommitProvisionalLoad(
2178 RenderFrameHostImpl
* render_frame_host
,
2179 const base::string16
& frame_unique_name
,
2182 PageTransition transition_type
) {
2183 int render_frame_id
= render_frame_host
->GetRoutingID();
2184 RenderViewHost
* render_view_host
= render_frame_host
->render_view_host();
2185 // Notify observers about the commit of the provisional load.
2187 WebContentsObserver
,
2189 DidCommitProvisionalLoadForFrame(render_frame_id
,
2197 void WebContentsImpl::DidNavigateMainFramePostCommit(
2198 const LoadCommittedDetails
& details
,
2199 const FrameHostMsg_DidCommitProvisionalLoad_Params
& params
) {
2200 if (details
.is_navigation_to_different_page()) {
2201 // Clear the status bubble. This is a workaround for a bug where WebKit
2202 // doesn't let us know that the cursor left an element during a
2203 // transition (this is also why the mouse cursor remains as a hand after
2204 // clicking on a link); see bugs 1184641 and 980803. We don't want to
2205 // clear the bubble when a user navigates to a named anchor in the same
2207 UpdateTargetURL(details
.entry
->GetPageID(), GURL());
2210 if (!details
.is_in_page
) {
2211 // Once the main frame is navigated, we're no longer considered to have
2212 // displayed insecure content.
2213 displayed_insecure_content_
= false;
2214 SSLManager::NotifySSLInternalStateChanged(
2215 GetController().GetBrowserContext());
2218 // Notify observers about navigation.
2219 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2220 DidNavigateMainFrame(details
, params
));
2223 delegate_
->DidNavigateMainFramePostCommit(this);
2224 view_
->SetOverscrollControllerEnabled(delegate_
->CanOverscrollContent());
2228 void WebContentsImpl::DidNavigateAnyFramePostCommit(
2229 RenderFrameHostImpl
* render_frame_host
,
2230 const LoadCommittedDetails
& details
,
2231 const FrameHostMsg_DidCommitProvisionalLoad_Params
& params
) {
2232 // If we navigate off the page, close all JavaScript dialogs.
2233 if (dialog_manager_
&& !details
.is_in_page
)
2234 dialog_manager_
->CancelActiveAndPendingDialogs(this);
2236 // Notify observers about navigation.
2237 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2238 DidNavigateAnyFrame(details
, params
));
2241 void WebContentsImpl::SetMainFrameMimeType(const std::string
& mime_type
) {
2242 contents_mime_type_
= mime_type
;
2245 bool WebContentsImpl::CanOverscrollContent() {
2247 return delegate_
->CanOverscrollContent();
2252 void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
2254 const std::string
& security_info
,
2255 const std::string
& http_method
,
2256 const std::string
& mime_type
,
2257 ResourceType::Type resource_type
) {
2258 base::StatsCounter
cache("WebKit.CacheHit");
2261 // Send out a notification that we loaded a resource from our memory cache.
2263 net::CertStatus cert_status
= 0;
2264 int security_bits
= -1;
2265 int connection_status
= 0;
2266 SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids
;
2267 DeserializeSecurityInfo(security_info
, &cert_id
, &cert_status
,
2268 &security_bits
, &connection_status
,
2269 &signed_certificate_timestamp_ids
);
2270 // TODO(alcutter,eranm): Pass signed_certificate_timestamp_ids into details
2271 LoadFromMemoryCacheDetails
details(
2272 url
, GetRenderProcessHost()->GetID(), cert_id
, cert_status
, http_method
,
2273 mime_type
, resource_type
);
2275 controller_
.ssl_manager()->DidLoadFromMemoryCache(details
);
2277 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2278 DidLoadResourceFromMemoryCache(details
));
2280 if (url
.is_valid() && url
.SchemeIsHTTPOrHTTPS()) {
2281 scoped_refptr
<net::URLRequestContextGetter
> request_context(
2282 resource_type
== ResourceType::MEDIA
?
2283 GetBrowserContext()->GetMediaRequestContextForRenderProcess(
2284 GetRenderProcessHost()->GetID()) :
2285 GetBrowserContext()->GetRequestContextForRenderProcess(
2286 GetRenderProcessHost()->GetID()));
2287 BrowserThread::PostTask(
2290 base::Bind(&NotifyCacheOnIO
, request_context
, url
, http_method
));
2294 void WebContentsImpl::OnDidDisplayInsecureContent() {
2295 RecordAction(base::UserMetricsAction("SSL.DisplayedInsecureContent"));
2296 displayed_insecure_content_
= true;
2297 SSLManager::NotifySSLInternalStateChanged(
2298 GetController().GetBrowserContext());
2301 void WebContentsImpl::OnDidRunInsecureContent(
2302 const std::string
& security_origin
, const GURL
& target_url
) {
2303 LOG(WARNING
) << security_origin
<< " ran insecure content from "
2304 << target_url
.possibly_invalid_spec();
2305 RecordAction(base::UserMetricsAction("SSL.RanInsecureContent"));
2306 if (EndsWith(security_origin
, kDotGoogleDotCom
, false))
2307 RecordAction(base::UserMetricsAction("SSL.RanInsecureContentGoogle"));
2308 controller_
.ssl_manager()->DidRunInsecureContent(security_origin
);
2309 displayed_insecure_content_
= true;
2310 SSLManager::NotifySSLInternalStateChanged(
2311 GetController().GetBrowserContext());
2314 void WebContentsImpl::OnDocumentLoadedInFrame() {
2315 CHECK(render_frame_message_source_
);
2316 CHECK(!render_view_message_source_
);
2317 RenderFrameHostImpl
* rfh
=
2318 static_cast<RenderFrameHostImpl
*>(render_frame_message_source_
);
2320 int render_frame_id
= rfh
->GetRoutingID();
2321 RenderViewHost
* render_view_host
= rfh
->render_view_host();
2322 FOR_EACH_OBSERVER(WebContentsObserver
,
2324 DocumentLoadedInFrame(render_frame_id
, render_view_host
));
2327 void WebContentsImpl::OnDidFinishLoad(
2329 if (!render_frame_message_source_
) {
2330 RecordAction(base::UserMetricsAction("BadMessageTerminate_RVD2"));
2331 GetRenderProcessHost()->ReceivedBadMessage();
2335 GURL
validated_url(url
);
2336 RenderProcessHost
* render_process_host
=
2337 render_frame_message_source_
->GetProcess();
2338 render_process_host
->FilterURL(false, &validated_url
);
2340 RenderFrameHostImpl
* rfh
=
2341 static_cast<RenderFrameHostImpl
*>(render_frame_message_source_
);
2342 int render_frame_id
= rfh
->GetRoutingID();
2343 RenderViewHost
* render_view_host
= rfh
->render_view_host();
2344 bool is_main_frame
= rfh
->frame_tree_node()->IsMainFrame();
2345 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2346 DidFinishLoad(render_frame_id
, validated_url
,
2347 is_main_frame
, render_view_host
));
2350 void WebContentsImpl::OnGoToEntryAtOffset(int offset
) {
2351 if (!delegate_
|| delegate_
->OnGoToEntryOffset(offset
))
2352 controller_
.GoToOffset(offset
);
2355 void WebContentsImpl::OnUpdateZoomLimits(int minimum_percent
,
2356 int maximum_percent
,
2358 minimum_zoom_percent_
= minimum_percent
;
2359 maximum_zoom_percent_
= maximum_percent
;
2360 temporary_zoom_settings_
= !remember
;
2363 void WebContentsImpl::OnEnumerateDirectory(int request_id
,
2364 const base::FilePath
& path
) {
2368 ChildProcessSecurityPolicyImpl
* policy
=
2369 ChildProcessSecurityPolicyImpl::GetInstance();
2370 if (policy
->CanReadFile(GetRenderProcessHost()->GetID(), path
))
2371 delegate_
->EnumerateDirectory(this, request_id
, path
);
2374 void WebContentsImpl::OnRegisterProtocolHandler(const std::string
& protocol
,
2376 const base::string16
& title
,
2377 bool user_gesture
) {
2381 ChildProcessSecurityPolicyImpl
* policy
=
2382 ChildProcessSecurityPolicyImpl::GetInstance();
2383 if (policy
->IsPseudoScheme(protocol
))
2386 delegate_
->RegisterProtocolHandler(this, protocol
, url
, title
, user_gesture
);
2389 void WebContentsImpl::OnFindReply(int request_id
,
2390 int number_of_matches
,
2391 const gfx::Rect
& selection_rect
,
2392 int active_match_ordinal
,
2393 bool final_update
) {
2395 delegate_
->FindReply(this, request_id
, number_of_matches
, selection_rect
,
2396 active_match_ordinal
, final_update
);
2400 #if defined(OS_ANDROID)
2401 void WebContentsImpl::OnFindMatchRectsReply(
2403 const std::vector
<gfx::RectF
>& rects
,
2404 const gfx::RectF
& active_rect
) {
2406 delegate_
->FindMatchRectsReply(this, version
, rects
, active_rect
);
2409 void WebContentsImpl::OnOpenDateTimeDialog(
2410 const ViewHostMsg_DateTimeDialogValue_Params
& value
) {
2411 date_time_chooser_
->ShowDialog(ContentViewCore::FromWebContents(this),
2412 GetRenderViewHost(),
2421 void WebContentsImpl::OnJavaBridgeGetChannelHandle(IPC::Message
* reply_msg
) {
2422 java_bridge_dispatcher_host_manager_
->OnGetChannelHandle(
2423 render_frame_message_source_
, reply_msg
);
2428 void WebContentsImpl::OnPepperPluginHung(int plugin_child_id
,
2429 const base::FilePath
& path
,
2431 UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1);
2433 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2434 PluginHungStatusChanged(plugin_child_id
, path
, is_hung
));
2437 void WebContentsImpl::OnPluginCrashed(const base::FilePath
& plugin_path
,
2438 base::ProcessId plugin_pid
) {
2439 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2440 PluginCrashed(plugin_path
, plugin_pid
));
2443 void WebContentsImpl::OnDomOperationResponse(const std::string
& json_string
,
2444 int automation_id
) {
2445 DomOperationNotificationDetails
details(json_string
, automation_id
);
2446 NotificationService::current()->Notify(
2447 NOTIFICATION_DOM_OPERATION_RESPONSE
,
2448 Source
<WebContents
>(this),
2449 Details
<DomOperationNotificationDetails
>(&details
));
2452 void WebContentsImpl::OnAppCacheAccessed(const GURL
& manifest_url
,
2453 bool blocked_by_policy
) {
2454 // Notify observers about navigation.
2455 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2456 AppCacheAccessed(manifest_url
, blocked_by_policy
));
2459 void WebContentsImpl::OnOpenColorChooser(
2460 int color_chooser_id
,
2462 const std::vector
<ColorSuggestion
>& suggestions
) {
2463 ColorChooser
* new_color_chooser
=
2464 delegate_
->OpenColorChooser(this, color
, suggestions
);
2465 if (!new_color_chooser
)
2468 color_chooser_
->End();
2469 color_chooser_
.reset(new_color_chooser
);
2470 color_chooser_identifier_
= color_chooser_id
;
2473 void WebContentsImpl::OnEndColorChooser(int color_chooser_id
) {
2474 if (color_chooser_
&&
2475 color_chooser_id
== color_chooser_identifier_
)
2476 color_chooser_
->End();
2479 void WebContentsImpl::OnSetSelectedColorInColorChooser(int color_chooser_id
,
2481 if (color_chooser_
&&
2482 color_chooser_id
== color_chooser_identifier_
)
2483 color_chooser_
->SetSelectedColor(color
);
2486 // This exists for render views that don't have a WebUI, but do have WebUI
2487 // bindings enabled.
2488 void WebContentsImpl::OnWebUISend(const GURL
& source_url
,
2489 const std::string
& name
,
2490 const base::ListValue
& args
) {
2492 delegate_
->WebUISend(this, source_url
, name
, args
);
2495 void WebContentsImpl::OnRequestPpapiBrokerPermission(
2498 const base::FilePath
& plugin_path
) {
2500 OnPpapiBrokerPermissionResult(routing_id
, false);
2504 if (!delegate_
->RequestPpapiBrokerPermission(
2505 this, url
, plugin_path
,
2506 base::Bind(&WebContentsImpl::OnPpapiBrokerPermissionResult
,
2507 base::Unretained(this), routing_id
))) {
2509 OnPpapiBrokerPermissionResult(routing_id
, false);
2513 void WebContentsImpl::OnPpapiBrokerPermissionResult(int routing_id
,
2515 Send(new ViewMsg_PpapiBrokerPermissionResult(routing_id
, result
));
2518 void WebContentsImpl::OnBrowserPluginMessage(const IPC::Message
& message
) {
2519 // This creates a BrowserPluginEmbedder, which handles all the BrowserPlugin
2520 // specific messages for this WebContents. This means that any message from
2521 // a BrowserPlugin prior to this will be ignored.
2522 // For more info, see comment above classes BrowserPluginEmbedder and
2523 // BrowserPluginGuest.
2524 CHECK(!browser_plugin_embedder_
.get());
2525 browser_plugin_embedder_
.reset(BrowserPluginEmbedder::Create(this));
2526 browser_plugin_embedder_
->OnMessageReceived(message
);
2529 void WebContentsImpl::OnDidDownloadImage(
2531 int http_status_code
,
2532 const GURL
& image_url
,
2533 const std::vector
<SkBitmap
>& bitmaps
,
2534 const std::vector
<gfx::Size
>& original_bitmap_sizes
) {
2535 if (bitmaps
.size() != original_bitmap_sizes
.size())
2538 ImageDownloadMap::iterator iter
= image_download_map_
.find(id
);
2539 if (iter
== image_download_map_
.end()) {
2540 // Currently WebContents notifies us of ANY downloads so that it is
2541 // possible to get here.
2544 if (!iter
->second
.is_null()) {
2546 id
, http_status_code
, image_url
, bitmaps
, original_bitmap_sizes
);
2548 image_download_map_
.erase(id
);
2551 void WebContentsImpl::OnUpdateFaviconURL(
2553 const std::vector
<FaviconURL
>& candidates
) {
2554 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2555 DidUpdateFaviconURL(page_id
, candidates
));
2558 void WebContentsImpl::OnMediaPlayingNotification(int64 player_cookie
,
2561 // Chrome OS does its own detection of audio and video.
2562 #if !defined(OS_CHROMEOS)
2563 scoped_ptr
<PowerSaveBlocker
> blocker
;
2565 blocker
= PowerSaveBlocker::Create(
2566 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep
, "Playing video");
2567 #if defined(OS_ANDROID)
2568 static_cast<PowerSaveBlockerImpl
*>(blocker
.get())
2569 ->InitDisplaySleepBlocker(GetView()->GetNativeView());
2571 } else if (has_audio
) {
2572 blocker
= PowerSaveBlocker::Create(
2573 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension
, "Playing audio");
2577 power_save_blockers_
[render_view_message_source_
][player_cookie
] =
2580 #endif // !defined(OS_CHROMEOS)
2583 void WebContentsImpl::OnMediaPausedNotification(int64 player_cookie
) {
2584 // Chrome OS does its own detection of audio and video.
2585 #if !defined(OS_CHROMEOS)
2586 delete power_save_blockers_
[render_view_message_source_
][player_cookie
];
2587 power_save_blockers_
[render_view_message_source_
].erase(player_cookie
);
2588 #endif // !defined(OS_CHROMEOS)
2591 void WebContentsImpl::OnFirstVisuallyNonEmptyPaint(int32 page_id
) {
2592 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2593 DidFirstVisuallyNonEmptyPaint(page_id
));
2596 void WebContentsImpl::DidChangeVisibleSSLState() {
2597 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2598 DidChangeVisibleSSLState());
2601 void WebContentsImpl::NotifyBeforeFormRepostWarningShow() {
2602 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2603 BeforeFormRepostWarningShow());
2607 void WebContentsImpl::ActivateAndShowRepostFormWarningDialog() {
2610 delegate_
->ShowRepostFormWarningDialog(this);
2613 // Notifies the RenderWidgetHost instance about the fact that the page is
2614 // loading, or done loading.
2615 void WebContentsImpl::SetIsLoading(RenderViewHost
* render_view_host
,
2617 bool to_different_document
,
2618 LoadNotificationDetails
* details
) {
2619 if (is_loading
== is_loading_
)
2623 load_state_
= net::LoadStateWithParam(net::LOAD_STATE_IDLE
,
2625 load_state_host_
.clear();
2627 upload_position_
= 0;
2630 GetRenderManager()->SetIsLoading(is_loading
);
2632 is_loading_
= is_loading
;
2633 waiting_for_response_
= is_loading
;
2636 delegate_
->LoadingStateChanged(this, to_different_document
);
2637 NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD
);
2639 std::string url
= (details
? details
->url
.possibly_invalid_spec() : "NULL");
2641 TRACE_EVENT_ASYNC_BEGIN1("browser", "WebContentsImpl Loading", this,
2643 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2644 DidStartLoading(render_view_host
));
2646 TRACE_EVENT_ASYNC_END1("browser", "WebContentsImpl Loading", this,
2648 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2649 DidStopLoading(render_view_host
));
2652 // TODO(avi): Remove. http://crbug.com/170921
2653 int type
= is_loading
? NOTIFICATION_LOAD_START
: NOTIFICATION_LOAD_STOP
;
2654 NotificationDetails det
= NotificationService::NoDetails();
2656 det
= Details
<LoadNotificationDetails
>(details
);
2657 NotificationService::current()->Notify(
2658 type
, Source
<NavigationController
>(&controller_
), det
);
2661 void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost
* rvh
) {
2662 // If we are creating a RVH for a restored controller, then we need to make
2663 // sure the RenderView starts with a next_page_id_ larger than the number
2664 // of restored entries. This must be called before the RenderView starts
2665 // navigating (to avoid a race between the browser updating max_page_id and
2666 // the renderer updating next_page_id_). Because of this, we only call this
2667 // from CreateRenderView and allow that to notify the RenderView for us.
2668 int max_restored_page_id
= controller_
.GetMaxRestoredPageID();
2669 if (max_restored_page_id
>
2670 GetMaxPageIDForSiteInstance(rvh
->GetSiteInstance()))
2671 UpdateMaxPageIDForSiteInstance(rvh
->GetSiteInstance(),
2672 max_restored_page_id
);
2675 bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl
* entry
,
2676 const base::string16
& title
) {
2677 // For file URLs without a title, use the pathname instead. In the case of a
2678 // synthesized title, we don't want the update to count toward the "one set
2679 // per page of the title to history."
2680 base::string16 final_title
;
2682 if (entry
&& entry
->GetURL().SchemeIsFile() && title
.empty()) {
2683 final_title
= base::UTF8ToUTF16(entry
->GetURL().ExtractFileName());
2684 explicit_set
= false; // Don't count synthetic titles toward the set limit.
2686 base::TrimWhitespace(title
, base::TRIM_ALL
, &final_title
);
2687 explicit_set
= true;
2690 // If a page is created via window.open and never navigated,
2691 // there will be no navigation entry. In this situation,
2692 // |page_title_when_no_navigation_entry_| will be used for page title.
2694 if (final_title
== entry
->GetTitle())
2695 return false; // Nothing changed, don't bother.
2697 entry
->SetTitle(final_title
);
2699 if (page_title_when_no_navigation_entry_
== final_title
)
2700 return false; // Nothing changed, don't bother.
2702 page_title_when_no_navigation_entry_
= final_title
;
2705 // Lastly, set the title for the view.
2706 view_
->SetPageTitle(final_title
);
2708 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2709 TitleWasSet(entry
, explicit_set
));
2711 // TODO(avi): Remove. http://crbug.com/170921
2712 std::pair
<NavigationEntry
*, bool> details
=
2713 std::make_pair(entry
, explicit_set
);
2714 NotificationService::current()->Notify(
2715 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED
,
2716 Source
<WebContents
>(this),
2717 Details
<std::pair
<NavigationEntry
*, bool> >(&details
));
2722 void WebContentsImpl::NotifySwapped(RenderViewHost
* old_host
,
2723 RenderViewHost
* new_host
) {
2724 // After sending out a swap notification, we need to send a disconnect
2725 // notification so that clients that pick up a pointer to |this| can NULL the
2726 // pointer. See Bug 1230284.
2727 notify_disconnection_
= true;
2728 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2729 RenderViewHostChanged(old_host
, new_host
));
2731 // TODO(avi): Remove. http://crbug.com/170921
2732 std::pair
<RenderViewHost
*, RenderViewHost
*> details
=
2733 std::make_pair(old_host
, new_host
);
2734 NotificationService::current()->Notify(
2735 NOTIFICATION_RENDER_VIEW_HOST_CHANGED
,
2736 Source
<WebContents
>(this),
2737 Details
<std::pair
<RenderViewHost
*, RenderViewHost
*> >(&details
));
2739 // Ensure that the associated embedder gets cleared after a RenderViewHost
2740 // gets swapped, so we don't reuse the same embedder next time a
2741 // RenderViewHost is attached to this WebContents.
2742 RemoveBrowserPluginEmbedder();
2745 // TODO(avi): Remove this entire function because this notification is already
2746 // covered by two observer functions. http://crbug.com/170921
2747 void WebContentsImpl::NotifyDisconnected() {
2748 if (!notify_disconnection_
)
2751 notify_disconnection_
= false;
2752 NotificationService::current()->Notify(
2753 NOTIFICATION_WEB_CONTENTS_DISCONNECTED
,
2754 Source
<WebContents
>(this),
2755 NotificationService::NoDetails());
2758 void WebContentsImpl::NotifyNavigationEntryCommitted(
2759 const LoadCommittedDetails
& load_details
) {
2761 WebContentsObserver
, observers_
, NavigationEntryCommitted(load_details
));
2764 bool WebContentsImpl::OnMessageReceived(RenderFrameHost
* render_frame_host
,
2765 const IPC::Message
& message
) {
2766 return OnMessageReceived(NULL
, render_frame_host
, message
);
2769 void WebContentsImpl::RenderFrameCreated(RenderFrameHost
* render_frame_host
) {
2770 // Note this is only for subframes, the notification for the main frame
2771 // happens in RenderViewCreated.
2772 FOR_EACH_OBSERVER(WebContentsObserver
,
2774 RenderFrameCreated(render_frame_host
));
2777 void WebContentsImpl::RenderFrameDeleted(RenderFrameHost
* render_frame_host
) {
2778 FOR_EACH_OBSERVER(WebContentsObserver
,
2780 RenderFrameDeleted(render_frame_host
));
2783 void WebContentsImpl::WorkerCrashed(RenderFrameHost
* render_frame_host
) {
2785 delegate_
->WorkerCrashed(this);
2788 void WebContentsImpl::ShowContextMenu(RenderFrameHost
* render_frame_host
,
2789 const ContextMenuParams
& params
) {
2790 // Allow WebContentsDelegates to handle the context menu operation first.
2791 if (delegate_
&& delegate_
->HandleContextMenu(params
))
2794 render_view_host_delegate_view_
->ShowContextMenu(render_frame_host
, params
);
2797 WebContents
* WebContentsImpl::GetAsWebContents() {
2801 RenderViewHostDelegateView
* WebContentsImpl::GetDelegateView() {
2802 return render_view_host_delegate_view_
;
2805 RendererPreferences
WebContentsImpl::GetRendererPrefs(
2806 BrowserContext
* browser_context
) const {
2807 return renderer_preferences_
;
2810 gfx::Rect
WebContentsImpl::GetRootWindowResizerRect() const {
2812 return delegate_
->GetRootWindowResizerRect();
2816 void WebContentsImpl::RemoveBrowserPluginEmbedder() {
2817 if (browser_plugin_embedder_
)
2818 browser_plugin_embedder_
.reset();
2821 void WebContentsImpl::RenderViewCreated(RenderViewHost
* render_view_host
) {
2822 // Don't send notifications if we are just creating a swapped-out RVH for
2823 // the opener chain. These won't be used for view-source or WebUI, so it's
2824 // ok to return early.
2825 if (static_cast<RenderViewHostImpl
*>(render_view_host
)->IsSwappedOut())
2829 view_
->SetOverscrollControllerEnabled(delegate_
->CanOverscrollContent());
2831 NotificationService::current()->Notify(
2832 NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED
,
2833 Source
<WebContents
>(this),
2834 Details
<RenderViewHost
>(render_view_host
));
2836 // When we're creating views, we're still doing initial setup, so we always
2837 // use the pending Web UI rather than any possibly existing committed one.
2838 if (GetRenderManager()->pending_web_ui())
2839 GetRenderManager()->pending_web_ui()->RenderViewCreated(render_view_host
);
2841 NavigationEntry
* entry
= controller_
.GetPendingEntry();
2842 if (entry
&& entry
->IsViewSourceMode()) {
2843 // Put the renderer in view source mode.
2844 render_view_host
->Send(
2845 new ViewMsg_EnableViewSourceMode(render_view_host
->GetRoutingID()));
2848 view_
->RenderViewCreated(render_view_host
);
2851 WebContentsObserver
, observers_
, RenderViewCreated(render_view_host
));
2853 // We tell the observers now instead of when the main RenderFrameHostImpl is
2854 // constructed because otherwise it would be too early (i.e. IPCs sent to the
2855 // frame would be dropped because it's not created yet).
2856 RenderFrameHost
* main_frame
= render_view_host
->GetMainFrame();
2858 WebContentsObserver
, observers_
, RenderFrameCreated(main_frame
));
2861 void WebContentsImpl::RenderViewReady(RenderViewHost
* rvh
) {
2862 if (rvh
!= GetRenderViewHost()) {
2863 // Don't notify the world, since this came from a renderer in the
2868 notify_disconnection_
= true;
2869 // TODO(avi): Remove. http://crbug.com/170921
2870 NotificationService::current()->Notify(
2871 NOTIFICATION_WEB_CONTENTS_CONNECTED
,
2872 Source
<WebContents
>(this),
2873 NotificationService::NoDetails());
2875 bool was_crashed
= IsCrashed();
2876 SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING
, 0);
2878 // Restore the focus to the tab (otherwise the focus will be on the top
2880 if (was_crashed
&& !FocusLocationBarByDefault() &&
2881 (!delegate_
|| delegate_
->ShouldFocusPageAfterCrash())) {
2885 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, RenderViewReady());
2888 void WebContentsImpl::RenderViewTerminated(RenderViewHost
* rvh
,
2889 base::TerminationStatus status
,
2891 if (rvh
!= GetRenderViewHost()) {
2892 // The pending page's RenderViewHost is gone.
2896 // Ensure fullscreen mode is exited in the |delegate_| since a crashed
2897 // renderer may not have made a clean exit.
2898 if (IsFullscreenForCurrentTab())
2899 ToggleFullscreenMode(false);
2901 // Cancel any visible dialogs so they are not left dangling over the sad tab.
2902 if (dialog_manager_
)
2903 dialog_manager_
->CancelActiveAndPendingDialogs(this);
2905 ClearPowerSaveBlockers(rvh
);
2906 SetIsLoading(rvh
, false, true, NULL
);
2907 NotifyDisconnected();
2908 SetIsCrashed(status
, error_code
);
2909 GetView()->OnTabCrashed(GetCrashedStatus(), crashed_error_code_
);
2911 FOR_EACH_OBSERVER(WebContentsObserver
,
2913 RenderProcessGone(GetCrashedStatus()));
2916 void WebContentsImpl::RenderViewDeleted(RenderViewHost
* rvh
) {
2917 ClearPowerSaveBlockers(rvh
);
2918 GetRenderManager()->RenderViewDeleted(rvh
);
2919 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, RenderViewDeleted(rvh
));
2922 void WebContentsImpl::UpdateState(RenderViewHost
* rvh
,
2924 const PageState
& page_state
) {
2925 // Ensure that this state update comes from either the active RVH or one of
2926 // the swapped out RVHs. We don't expect to hear from any other RVHs.
2927 // TODO(nasko): This should go through RenderFrameHost.
2928 // TODO(creis): We can't update state for cross-process subframes until we
2929 // have FrameNavigationEntries. Once we do, this should be a DCHECK.
2930 if (rvh
!= GetRenderViewHost() &&
2931 !GetRenderManager()->IsRVHOnSwappedOutList(
2932 static_cast<RenderViewHostImpl
*>(rvh
)))
2935 // We must be prepared to handle state updates for any page, these occur
2936 // when the user is scrolling and entering form data, as well as when we're
2937 // leaving a page, in which case our state may have already been moved to
2938 // the next page. The navigation controller will look up the appropriate
2939 // NavigationEntry and update it when it is notified via the delegate.
2941 int entry_index
= controller_
.GetEntryIndexWithPageID(
2942 rvh
->GetSiteInstance(), page_id
);
2943 if (entry_index
< 0)
2945 NavigationEntry
* entry
= controller_
.GetEntryAtIndex(entry_index
);
2947 if (page_state
== entry
->GetPageState())
2948 return; // Nothing to update.
2949 entry
->SetPageState(page_state
);
2950 controller_
.NotifyEntryChanged(entry
, entry_index
);
2953 void WebContentsImpl::UpdateTitle(RenderViewHost
* rvh
,
2955 const base::string16
& title
,
2956 base::i18n::TextDirection title_direction
) {
2957 // If we have a title, that's a pretty good indication that we've started
2958 // getting useful data.
2959 SetNotWaitingForResponse();
2961 // Try to find the navigation entry, which might not be the current one.
2962 // For example, it might be from a pending RVH for the pending entry.
2963 NavigationEntryImpl
* entry
= controller_
.GetEntryWithPageID(
2964 rvh
->GetSiteInstance(), page_id
);
2966 // We can handle title updates when we don't have an entry in
2967 // UpdateTitleForEntry, but only if the update is from the current RVH.
2968 if (!entry
&& rvh
!= GetRenderViewHost())
2971 // TODO(evan): make use of title_direction.
2972 // http://code.google.com/p/chromium/issues/detail?id=27094
2973 if (!UpdateTitleForEntry(entry
, title
))
2976 // Broadcast notifications when the UI should be updated.
2977 if (entry
== controller_
.GetEntryAtOffset(0))
2978 NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE
);
2981 void WebContentsImpl::UpdateEncoding(RenderViewHost
* render_view_host
,
2982 const std::string
& encoding
) {
2983 SetEncoding(encoding
);
2986 void WebContentsImpl::UpdateTargetURL(int32 page_id
, const GURL
& url
) {
2988 delegate_
->UpdateTargetURL(this, page_id
, url
);
2991 void WebContentsImpl::Close(RenderViewHost
* rvh
) {
2992 #if defined(OS_MACOSX)
2993 // The UI may be in an event-tracking loop, such as between the
2994 // mouse-down and mouse-up in text selection or a button click.
2995 // Defer the close until after tracking is complete, so that we
2996 // don't free objects out from under the UI.
2997 // TODO(shess): This could get more fine-grained. For instance,
2998 // closing a tab in another window while selecting text in the
2999 // current window's Omnibox should be just fine.
3000 if (view_
->IsEventTracking()) {
3001 view_
->CloseTabAfterEventTracking();
3006 // Ignore this if it comes from a RenderViewHost that we aren't showing.
3007 if (delegate_
&& rvh
== GetRenderViewHost())
3008 delegate_
->CloseContents(this);
3011 void WebContentsImpl::SwappedOut(RenderFrameHost
* rfh
) {
3012 // TODO(creis): Handle subframes that go fullscreen.
3013 if (rfh
->GetRenderViewHost() == GetRenderViewHost()) {
3014 // Exit fullscreen mode before the current RVH is swapped out. For numerous
3015 // cases, there is no guarantee the renderer would/could initiate an exit.
3016 // Example: http://crbug.com/347232
3017 if (IsFullscreenForCurrentTab()) {
3018 rfh
->GetRenderViewHost()->ExitFullscreen();
3019 DCHECK(!IsFullscreenForCurrentTab());
3023 delegate_
->SwappedOut(this);
3027 void WebContentsImpl::RequestMove(const gfx::Rect
& new_bounds
) {
3028 if (delegate_
&& delegate_
->IsPopupOrPanel(this))
3029 delegate_
->MoveContents(this, new_bounds
);
3032 void WebContentsImpl::DidStartLoading(RenderFrameHost
* render_frame_host
,
3033 bool to_different_document
) {
3034 SetIsLoading(render_frame_host
->GetRenderViewHost(), true,
3035 to_different_document
, NULL
);
3038 void WebContentsImpl::DidStopLoading(RenderFrameHost
* render_frame_host
) {
3039 scoped_ptr
<LoadNotificationDetails
> details
;
3041 // Use the last committed entry rather than the active one, in case a
3042 // pending entry has been created.
3043 NavigationEntry
* entry
= controller_
.GetLastCommittedEntry();
3044 Navigator
* navigator
= frame_tree_
.root()->navigator();
3046 // An entry may not exist for a stop when loading an initial blank page or
3047 // if an iframe injected by script into a blank page finishes loading.
3049 base::TimeDelta elapsed
=
3050 base::TimeTicks::Now() - navigator
->GetCurrentLoadStart();
3052 details
.reset(new LoadNotificationDetails(
3053 entry
->GetVirtualURL(),
3054 entry
->GetTransitionType(),
3057 controller_
.GetCurrentEntryIndex()));
3060 SetIsLoading(render_frame_host
->GetRenderViewHost(), false, true,
3064 void WebContentsImpl::DidCancelLoading() {
3065 controller_
.DiscardNonCommittedEntries();
3067 // Update the URL display.
3068 NotifyNavigationStateChanged(INVALIDATE_TYPE_URL
);
3071 void WebContentsImpl::DidChangeLoadProgress(double progress
) {
3073 delegate_
->LoadProgressChanged(this, progress
);
3076 void WebContentsImpl::DidDisownOpener(RenderViewHost
* rvh
) {
3078 // Clear our opener so that future cross-process navigations don't have an
3080 RemoveDestructionObserver(opener_
);
3084 // Notify all swapped out RenderViewHosts for this tab. This is important
3085 // in case we go back to them, or if another window in those processes tries
3086 // to access window.opener.
3087 GetRenderManager()->DidDisownOpener(rvh
);
3090 void WebContentsImpl::DidAccessInitialDocument() {
3091 // Update the URL display.
3092 NotifyNavigationStateChanged(content::INVALIDATE_TYPE_URL
);
3095 void WebContentsImpl::DocumentAvailableInMainFrame(
3096 RenderViewHost
* render_view_host
) {
3097 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3098 DocumentAvailableInMainFrame());
3101 void WebContentsImpl::DocumentOnLoadCompletedInMainFrame(
3102 RenderViewHost
* render_view_host
,
3104 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3105 DocumentOnLoadCompletedInMainFrame(page_id
));
3107 // TODO(avi): Remove. http://crbug.com/170921
3108 NotificationService::current()->Notify(
3109 NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME
,
3110 Source
<WebContents
>(this),
3111 Details
<int>(&page_id
));
3114 void WebContentsImpl::RouteCloseEvent(RenderViewHost
* rvh
) {
3115 // Tell the active RenderViewHost to run unload handlers and close, as long
3116 // as the request came from a RenderViewHost in the same BrowsingInstance.
3117 // In most cases, we receive this from a swapped out RenderViewHost.
3118 // It is possible to receive it from one that has just been swapped in,
3119 // in which case we might as well deliver the message anyway.
3120 if (rvh
->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()))
3121 GetRenderViewHost()->ClosePage();
3124 void WebContentsImpl::RouteMessageEvent(
3125 RenderViewHost
* rvh
,
3126 const ViewMsg_PostMessage_Params
& params
) {
3127 // Only deliver the message to the active RenderViewHost if the request
3128 // came from a RenderViewHost in the same BrowsingInstance or if this
3129 // WebContents is dedicated to a browser plugin guest.
3130 // Note: This check means that an embedder could theoretically receive a
3131 // postMessage from anyone (not just its own guests). However, this is
3132 // probably not a risk for apps since other pages won't have references
3134 if (!rvh
->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()) &&
3135 !GetBrowserPluginGuest() && !GetBrowserPluginEmbedder())
3138 ViewMsg_PostMessage_Params
new_params(params
);
3140 if (!params
.message_port_ids
.empty()) {
3141 MessagePortMessageFilter
* message_port_message_filter
=
3142 static_cast<RenderProcessHostImpl
*>(GetRenderProcessHost())
3143 ->message_port_message_filter();
3144 std::vector
<int> new_routing_ids(params
.message_port_ids
.size());
3145 for (size_t i
= 0; i
< params
.message_port_ids
.size(); ++i
) {
3146 new_routing_ids
[i
] = message_port_message_filter
->GetNextRoutingID();
3147 MessagePortService::GetInstance()->UpdateMessagePort(
3148 params
.message_port_ids
[i
],
3149 message_port_message_filter
,
3150 new_routing_ids
[i
]);
3152 new_params
.new_routing_ids
= new_routing_ids
;
3155 // If there is a source_routing_id, translate it to the routing ID for
3156 // the equivalent swapped out RVH in the target process. If we need
3157 // to create a swapped out RVH for the source tab, we create its opener
3158 // chain as well, since those will also be accessible to the target page.
3159 if (new_params
.source_routing_id
!= MSG_ROUTING_NONE
) {
3160 // Try to look up the WebContents for the source page.
3161 WebContentsImpl
* source_contents
= NULL
;
3162 RenderViewHostImpl
* source_rvh
= RenderViewHostImpl::FromID(
3163 rvh
->GetProcess()->GetID(), params
.source_routing_id
);
3165 source_contents
= static_cast<WebContentsImpl
*>(
3166 source_rvh
->GetDelegate()->GetAsWebContents());
3169 if (source_contents
) {
3170 if (GetBrowserPluginGuest()) {
3171 // We create a swapped out RenderView for the embedder in the guest's
3172 // render process but we intentionally do not expose the embedder's
3173 // opener chain to it.
3174 new_params
.source_routing_id
=
3175 source_contents
->CreateSwappedOutRenderView(GetSiteInstance());
3177 new_params
.source_routing_id
=
3178 source_contents
->CreateOpenerRenderViews(GetSiteInstance());
3181 // We couldn't find it, so don't pass a source frame.
3182 new_params
.source_routing_id
= MSG_ROUTING_NONE
;
3186 // In most cases, we receive this from a swapped out RenderViewHost.
3187 // It is possible to receive it from one that has just been swapped in,
3188 // in which case we might as well deliver the message anyway.
3189 Send(new ViewMsg_PostMessageEvent(GetRoutingID(), new_params
));
3192 void WebContentsImpl::RunJavaScriptMessage(
3193 RenderViewHost
* rvh
,
3194 const base::string16
& message
,
3195 const base::string16
& default_prompt
,
3196 const GURL
& frame_url
,
3197 JavaScriptMessageType javascript_message_type
,
3198 IPC::Message
* reply_msg
,
3199 bool* did_suppress_message
) {
3200 // Suppress JavaScript dialogs when requested. Also suppress messages when
3201 // showing an interstitial as it's shown over the previous page and we don't
3202 // want the hidden page's dialogs to interfere with the interstitial.
3203 bool suppress_this_message
=
3204 static_cast<RenderViewHostImpl
*>(rvh
)->IsSwappedOut() ||
3205 ShowingInterstitialPage() ||
3207 delegate_
->ShouldSuppressDialogs() ||
3208 !delegate_
->GetJavaScriptDialogManager();
3210 if (!suppress_this_message
) {
3211 std::string accept_lang
= GetContentClient()->browser()->
3212 GetAcceptLangs(GetBrowserContext());
3213 dialog_manager_
= delegate_
->GetJavaScriptDialogManager();
3214 dialog_manager_
->RunJavaScriptDialog(
3216 frame_url
.GetOrigin(),
3218 javascript_message_type
,
3221 base::Bind(&WebContentsImpl::OnDialogClosed
,
3222 base::Unretained(this),
3225 &suppress_this_message
);
3228 *did_suppress_message
= suppress_this_message
;
3230 if (suppress_this_message
) {
3231 // If we are suppressing messages, just reply as if the user immediately
3232 // pressed "Cancel".
3233 OnDialogClosed(rvh
, reply_msg
, false, base::string16());
3236 // OnDialogClosed (two lines up) may have caused deletion of this object (see
3237 // http://crbug.com/288961 ). The only safe thing to do here is return.
3240 void WebContentsImpl::RunBeforeUnloadConfirm(RenderViewHost
* rvh
,
3241 const base::string16
& message
,
3243 IPC::Message
* reply_msg
) {
3244 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(rvh
);
3246 delegate_
->WillRunBeforeUnloadConfirm();
3248 bool suppress_this_message
=
3249 rvhi
->rvh_state() != RenderViewHostImpl::STATE_DEFAULT
||
3251 delegate_
->ShouldSuppressDialogs() ||
3252 !delegate_
->GetJavaScriptDialogManager();
3253 if (suppress_this_message
) {
3254 // The reply must be sent to the RVH that sent the request.
3255 rvhi
->JavaScriptDialogClosed(reply_msg
, true, base::string16());
3259 is_showing_before_unload_dialog_
= true;
3260 dialog_manager_
= delegate_
->GetJavaScriptDialogManager();
3261 dialog_manager_
->RunBeforeUnloadDialog(
3262 this, message
, is_reload
,
3263 base::Bind(&WebContentsImpl::OnDialogClosed
, base::Unretained(this), rvh
,
3267 bool WebContentsImpl::AddMessageToConsole(int32 level
,
3268 const base::string16
& message
,
3270 const base::string16
& source_id
) {
3273 return delegate_
->AddMessageToConsole(this, level
, message
, line_no
,
3277 WebPreferences
WebContentsImpl::GetWebkitPrefs() {
3278 // We want to base the page config off of the actual URL, rather than the
3280 // TODO(nasko): Investigate how to remove the GetActiveEntry usage here,
3281 // as it is deprecated and can be out of sync with GetRenderViewHost().
3282 GURL url
= controller_
.GetActiveEntry()
3283 ? controller_
.GetActiveEntry()->GetURL() : GURL::EmptyGURL();
3285 return GetRenderManager()->current_host()->GetWebkitPrefs(url
);
3288 int WebContentsImpl::CreateSwappedOutRenderView(
3289 SiteInstance
* instance
) {
3290 return GetRenderManager()->CreateRenderFrame(instance
, MSG_ROUTING_NONE
,
3294 void WebContentsImpl::OnUserGesture() {
3295 // Notify observers.
3296 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, DidGetUserGesture());
3298 ResourceDispatcherHostImpl
* rdh
= ResourceDispatcherHostImpl::Get();
3299 if (rdh
) // NULL in unittests.
3300 rdh
->OnUserGesture(this);
3303 void WebContentsImpl::OnIgnoredUIEvent() {
3304 // Notify observers.
3305 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, DidGetIgnoredUIEvent());
3308 void WebContentsImpl::RendererUnresponsive(RenderViewHost
* rvh
,
3309 bool is_during_beforeunload
,
3310 bool is_during_unload
) {
3311 // Don't show hung renderer dialog for a swapped out RVH.
3312 if (rvh
!= GetRenderViewHost())
3315 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(rvh
);
3317 // Ignore renderer unresponsive event if debugger is attached to the tab
3318 // since the event may be a result of the renderer sitting on a breakpoint.
3319 // See http://crbug.com/65458
3320 if (DevToolsAgentHost::IsDebuggerAttached(this))
3323 if (is_during_beforeunload
|| is_during_unload
) {
3324 // Hang occurred while firing the beforeunload/unload handler.
3325 // Pretend the handler fired so tab closing continues as if it had.
3326 rvhi
->set_sudden_termination_allowed(true);
3328 if (!GetRenderManager()->ShouldCloseTabOnUnresponsiveRenderer())
3331 // If the tab hangs in the beforeunload/unload handler there's really
3332 // nothing we can do to recover. If the hang is in the beforeunload handler,
3333 // pretend the beforeunload listeners have all fired and allow the delegate
3334 // to continue closing; the user will not have the option of cancelling the
3335 // close. Otherwise, pretend the unload listeners have all fired and close
3338 if (is_during_beforeunload
) {
3339 delegate_
->BeforeUnloadFired(this, true, &close
);
3346 if (!GetRenderViewHostImpl() || !GetRenderViewHostImpl()->IsRenderViewLive())
3350 delegate_
->RendererUnresponsive(this);
3353 void WebContentsImpl::RendererResponsive(RenderViewHost
* render_view_host
) {
3355 delegate_
->RendererResponsive(this);
3358 void WebContentsImpl::LoadStateChanged(
3360 const net::LoadStateWithParam
& load_state
,
3361 uint64 upload_position
,
3362 uint64 upload_size
) {
3363 load_state_
= load_state
;
3364 upload_position_
= upload_position
;
3365 upload_size_
= upload_size
;
3366 load_state_host_
= net::IDNToUnicode(url
.host(),
3367 GetContentClient()->browser()->GetAcceptLangs(
3368 GetBrowserContext()));
3369 if (load_state_
.state
== net::LOAD_STATE_READING_RESPONSE
)
3370 SetNotWaitingForResponse();
3372 NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD
| INVALIDATE_TYPE_TAB
);
3376 void WebContentsImpl::BeforeUnloadFiredFromRenderManager(
3377 bool proceed
, const base::TimeTicks
& proceed_time
,
3378 bool* proceed_to_fire_unload
) {
3379 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3380 BeforeUnloadFired(proceed_time
));
3382 delegate_
->BeforeUnloadFired(this, proceed
, proceed_to_fire_unload
);
3383 // Note: |this| might be deleted at this point.
3386 void WebContentsImpl::RenderProcessGoneFromRenderManager(
3387 RenderViewHost
* render_view_host
) {
3388 DCHECK(crashed_status_
!= base::TERMINATION_STATUS_STILL_RUNNING
);
3389 RenderViewTerminated(render_view_host
, crashed_status_
, crashed_error_code_
);
3392 void WebContentsImpl::UpdateRenderViewSizeForRenderManager() {
3393 // TODO(brettw) this is a hack. See WebContentsView::SizeContents.
3394 gfx::Size size
= GetSizeForNewRenderView();
3395 // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be
3396 // here during container initialization and normal window size will be set
3397 // later. In case of tab duplication this resizing to 0x0 prevents setting
3398 // normal size later so just ignore it.
3399 if (!size
.IsEmpty())
3400 view_
->SizeContents(size
);
3403 void WebContentsImpl::CancelModalDialogsForRenderManager() {
3404 // We need to cancel modal dialogs when doing a process swap, since the load
3405 // deferrer would prevent us from swapping out.
3406 if (dialog_manager_
)
3407 dialog_manager_
->CancelActiveAndPendingDialogs(this);
3410 void WebContentsImpl::NotifySwappedFromRenderManager(RenderViewHost
* old_host
,
3411 RenderViewHost
* new_host
) {
3412 NotifySwapped(old_host
, new_host
);
3414 // Make sure the visible RVH reflects the new delegate's preferences.
3416 view_
->SetOverscrollControllerEnabled(delegate_
->CanOverscrollContent());
3418 view_
->RenderViewSwappedIn(new_host
);
3421 int WebContentsImpl::CreateOpenerRenderViewsForRenderManager(
3422 SiteInstance
* instance
) {
3424 return MSG_ROUTING_NONE
;
3426 // Recursively create RenderViews for anything else in the opener chain.
3427 return opener_
->CreateOpenerRenderViews(instance
);
3430 int WebContentsImpl::CreateOpenerRenderViews(SiteInstance
* instance
) {
3431 int opener_route_id
= MSG_ROUTING_NONE
;
3433 // If this tab has an opener, ensure it has a RenderView in the given
3434 // SiteInstance as well.
3436 opener_route_id
= opener_
->CreateOpenerRenderViews(instance
);
3438 // If any of the renderers (current, pending, or swapped out) for this
3439 // WebContents has the same SiteInstance, use it.
3440 if (GetRenderManager()->current_host()->GetSiteInstance() == instance
)
3441 return GetRenderManager()->current_host()->GetRoutingID();
3443 if (GetRenderManager()->pending_render_view_host() &&
3444 GetRenderManager()->pending_render_view_host()->GetSiteInstance() ==
3446 return GetRenderManager()->pending_render_view_host()->GetRoutingID();
3448 RenderViewHostImpl
* rvh
= GetRenderManager()->GetSwappedOutRenderViewHost(
3451 return rvh
->GetRoutingID();
3453 // Create a swapped out RenderView in the given SiteInstance if none exists,
3454 // setting its opener to the given route_id. Return the new view's route_id.
3455 return GetRenderManager()->CreateRenderFrame(instance
, opener_route_id
,
3459 NavigationControllerImpl
& WebContentsImpl::GetControllerForRenderManager() {
3460 return GetController();
3463 WebUIImpl
* WebContentsImpl::CreateWebUIForRenderManager(const GURL
& url
) {
3464 return static_cast<WebUIImpl
*>(CreateWebUI(url
));
3468 WebContentsImpl::GetLastCommittedNavigationEntryForRenderManager() {
3469 return controller_
.GetLastCommittedEntry();
3472 bool WebContentsImpl::CreateRenderViewForRenderManager(
3473 RenderViewHost
* render_view_host
,
3474 int opener_route_id
,
3475 CrossProcessFrameConnector
* frame_connector
) {
3476 TRACE_EVENT0("browser", "WebContentsImpl::CreateRenderViewForRenderManager");
3477 // Can be NULL during tests.
3478 RenderWidgetHostView
* rwh_view
;
3479 // TODO(kenrb): RenderWidgetHostViewChildFrame special casing is temporary
3480 // until RenderWidgetHost is attached to RenderFrameHost. We need to special
3481 // case this because RWH is still a base class of RenderViewHost, and child
3482 // frame RWHVs are unique in that they do not have their own WebContents.
3483 if (frame_connector
) {
3484 RenderWidgetHostViewChildFrame
* rwh_view_child
=
3485 new RenderWidgetHostViewChildFrame(render_view_host
);
3486 frame_connector
->set_view(rwh_view_child
);
3487 rwh_view
= rwh_view_child
;
3489 rwh_view
= view_
->CreateViewForWidget(render_view_host
);
3492 // Now that the RenderView has been created, we need to tell it its size.
3494 rwh_view
->SetSize(GetSizeForNewRenderView());
3496 // Make sure we use the correct starting page_id in the new RenderView.
3497 UpdateMaxPageIDIfNecessary(render_view_host
);
3499 GetMaxPageIDForSiteInstance(render_view_host
->GetSiteInstance());
3501 if (!static_cast<RenderViewHostImpl
*>(
3502 render_view_host
)->CreateRenderView(base::string16(),
3508 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
3509 // Force a ViewMsg_Resize to be sent, needed to make plugins show up on
3510 // linux. See crbug.com/83941.
3512 if (RenderWidgetHost
* render_widget_host
= rwh_view
->GetRenderWidgetHost())
3513 render_widget_host
->WasResized();
3520 #if defined(OS_ANDROID)
3521 base::android::ScopedJavaLocalRef
<jobject
>
3522 WebContentsImpl::GetJavaWebContents() {
3523 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
3525 WebContentsAndroid
* web_contents_android
=
3526 static_cast<WebContentsAndroid
*>(GetUserData(kWebContentsAndroidKey
));
3527 if (!web_contents_android
) {
3528 web_contents_android
= new WebContentsAndroid(this);
3529 SetUserData(kWebContentsAndroidKey
, web_contents_android
);
3531 return web_contents_android
->GetJavaObject();
3534 bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() {
3535 return CreateRenderViewForRenderManager(GetRenderViewHost(),
3541 void WebContentsImpl::OnDialogClosed(RenderViewHost
* rvh
,
3542 IPC::Message
* reply_msg
,
3544 const base::string16
& user_input
) {
3545 if (is_showing_before_unload_dialog_
&& !success
) {
3546 // If a beforeunload dialog is canceled, we need to stop the throbber from
3547 // spinning, since we forced it to start spinning in Navigate.
3548 DidStopLoading(rvh
->GetMainFrame());
3549 controller_
.DiscardNonCommittedEntries();
3551 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3552 BeforeUnloadDialogCancelled());
3554 is_showing_before_unload_dialog_
= false;
3555 static_cast<RenderViewHostImpl
*>(
3556 rvh
)->JavaScriptDialogClosed(reply_msg
, success
, user_input
);
3559 void WebContentsImpl::SetEncoding(const std::string
& encoding
) {
3560 encoding_
= GetContentClient()->browser()->
3561 GetCanonicalEncodingNameByAliasName(encoding
);
3564 void WebContentsImpl::CreateViewAndSetSizeForRVH(RenderViewHost
* rvh
) {
3565 RenderWidgetHostView
* rwh_view
= view_
->CreateViewForWidget(rvh
);
3566 // Can be NULL during tests.
3568 rwh_view
->SetSize(GetView()->GetContainerSize());
3571 bool WebContentsImpl::IsHidden() {
3572 return capturer_count_
== 0 && !should_normally_be_visible_
;
3575 RenderFrameHostManager
* WebContentsImpl::GetRenderManager() const {
3576 return frame_tree_
.root()->render_manager();
3579 RenderViewHostImpl
* WebContentsImpl::GetRenderViewHostImpl() {
3580 return static_cast<RenderViewHostImpl
*>(GetRenderViewHost());
3583 BrowserPluginGuest
* WebContentsImpl::GetBrowserPluginGuest() const {
3584 return browser_plugin_guest_
.get();
3587 void WebContentsImpl::SetBrowserPluginGuest(BrowserPluginGuest
* guest
) {
3588 CHECK(!browser_plugin_guest_
);
3589 browser_plugin_guest_
.reset(guest
);
3592 BrowserPluginEmbedder
* WebContentsImpl::GetBrowserPluginEmbedder() const {
3593 return browser_plugin_embedder_
.get();
3596 BrowserPluginGuestManager
*
3597 WebContentsImpl::GetBrowserPluginGuestManager() const {
3598 return static_cast<BrowserPluginGuestManager
*>(
3599 GetBrowserContext()->GetUserData(
3600 browser_plugin::kBrowserPluginGuestManagerKeyName
));
3603 void WebContentsImpl::ClearPowerSaveBlockers(
3604 RenderViewHost
* render_view_host
) {
3605 STLDeleteValues(&power_save_blockers_
[render_view_host
]);
3606 power_save_blockers_
.erase(render_view_host
);
3609 void WebContentsImpl::ClearAllPowerSaveBlockers() {
3610 for (PowerSaveBlockerMap::iterator
i(power_save_blockers_
.begin());
3611 i
!= power_save_blockers_
.end(); ++i
)
3612 STLDeleteValues(&power_save_blockers_
[i
->first
]);
3613 power_save_blockers_
.clear();
3616 gfx::Size
WebContentsImpl::GetSizeForNewRenderView() const {
3619 size
= delegate_
->GetSizeForNewRenderView(this);
3621 size
= view_
->GetContainerSize();
3625 void WebContentsImpl::OnFrameRemoved(
3626 RenderViewHostImpl
* render_view_host
,
3627 int frame_routing_id
) {
3628 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3629 FrameDetached(render_view_host
, frame_routing_id
));
3632 void WebContentsImpl::OnPreferredSizeChanged(const gfx::Size
& old_size
) {
3635 const gfx::Size new_size
= GetPreferredSize();
3636 if (new_size
!= old_size
)
3637 delegate_
->UpdatePreferredSize(this, new_size
);
3640 } // namespace content