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/accessibility/accessibility_mode_helper.h"
22 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
23 #include "content/browser/browser_plugin/browser_plugin_embedder.h"
24 #include "content/browser/browser_plugin/browser_plugin_guest.h"
25 #include "content/browser/child_process_security_policy_impl.h"
26 #include "content/browser/devtools/render_view_devtools_agent_host.h"
27 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
28 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
29 #include "content/browser/download/download_stats.h"
30 #include "content/browser/download/mhtml_generation_manager.h"
31 #include "content/browser/download/save_package.h"
32 #include "content/browser/frame_host/cross_process_frame_connector.h"
33 #include "content/browser/frame_host/interstitial_page_impl.h"
34 #include "content/browser/frame_host/navigation_entry_impl.h"
35 #include "content/browser/frame_host/navigator_impl.h"
36 #include "content/browser/frame_host/render_frame_host_impl.h"
37 #include "content/browser/frame_host/render_widget_host_view_child_frame.h"
38 #include "content/browser/geolocation/geolocation_dispatcher_host.h"
39 #include "content/browser/host_zoom_map_impl.h"
40 #include "content/browser/loader/resource_dispatcher_host_impl.h"
41 #include "content/browser/media/audio_stream_monitor.h"
42 #include "content/browser/media/midi_dispatcher_host.h"
43 #include "content/browser/message_port_message_filter.h"
44 #include "content/browser/message_port_service.h"
45 #include "content/browser/power_save_blocker_impl.h"
46 #include "content/browser/renderer_host/render_process_host_impl.h"
47 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
48 #include "content/browser/renderer_host/render_view_host_impl.h"
49 #include "content/browser/renderer_host/render_widget_host_impl.h"
50 #include "content/browser/renderer_host/render_widget_host_view_base.h"
51 #include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
52 #include "content/browser/site_instance_impl.h"
53 #include "content/browser/web_contents/web_contents_view_guest.h"
54 #include "content/browser/webui/generic_handler.h"
55 #include "content/browser/webui/web_ui_controller_factory_registry.h"
56 #include "content/browser/webui/web_ui_impl.h"
57 #include "content/common/browser_plugin/browser_plugin_constants.h"
58 #include "content/common/browser_plugin/browser_plugin_messages.h"
59 #include "content/common/frame_messages.h"
60 #include "content/common/image_messages.h"
61 #include "content/common/input_messages.h"
62 #include "content/common/ssl_status_serialization.h"
63 #include "content/common/view_messages.h"
64 #include "content/public/browser/ax_event_notification_details.h"
65 #include "content/public/browser/browser_context.h"
66 #include "content/public/browser/browser_plugin_guest_manager.h"
67 #include "content/public/browser/content_browser_client.h"
68 #include "content/public/browser/devtools_agent_host.h"
69 #include "content/public/browser/download_manager.h"
70 #include "content/public/browser/download_url_parameters.h"
71 #include "content/public/browser/invalidate_type.h"
72 #include "content/public/browser/javascript_dialog_manager.h"
73 #include "content/public/browser/load_from_memory_cache_details.h"
74 #include "content/public/browser/load_notification_details.h"
75 #include "content/public/browser/navigation_details.h"
76 #include "content/public/browser/notification_details.h"
77 #include "content/public/browser/notification_service.h"
78 #include "content/public/browser/render_widget_host_iterator.h"
79 #include "content/public/browser/resource_request_details.h"
80 #include "content/public/browser/storage_partition.h"
81 #include "content/public/browser/user_metrics.h"
82 #include "content/public/browser/web_contents_delegate.h"
83 #include "content/public/browser/web_contents_observer.h"
84 #include "content/public/common/bindings_policy.h"
85 #include "content/public/common/content_constants.h"
86 #include "content/public/common/content_switches.h"
87 #include "content/public/common/page_zoom.h"
88 #include "content/public/common/result_codes.h"
89 #include "content/public/common/url_constants.h"
90 #include "content/public/common/url_utils.h"
91 #include "content/public/common/web_preferences.h"
92 #include "net/base/mime_util.h"
93 #include "net/base/net_util.h"
94 #include "net/http/http_cache.h"
95 #include "net/http/http_transaction_factory.h"
96 #include "net/url_request/url_request_context.h"
97 #include "net/url_request/url_request_context_getter.h"
98 #include "ui/base/layout.h"
99 #include "ui/gfx/display.h"
100 #include "ui/gfx/screen.h"
101 #include "ui/gl/gl_switches.h"
103 #if defined(OS_ANDROID)
104 #include "content/browser/android/content_view_core_impl.h"
105 #include "content/browser/android/date_time_chooser_android.h"
106 #include "content/browser/media/android/browser_media_player_manager.h"
107 #include "content/browser/web_contents/web_contents_android.h"
108 #include "content/public/browser/android/content_view_core.h"
111 #if defined(OS_MACOSX)
112 #include "base/mac/foundation_util.h"
115 // Cross-Site Navigations
117 // If a WebContentsImpl is told to navigate to a different web site (as
118 // determined by SiteInstance), it will replace its current RenderViewHost with
119 // a new RenderViewHost dedicated to the new SiteInstance. This works as
122 // - RVHM::Navigate determines whether the destination is cross-site, and if so,
123 // it creates a pending_render_view_host_.
124 // - The pending RVH is "suspended," so that no navigation messages are sent to
125 // its renderer until the beforeunload JavaScript handler has a chance to
126 // run in the current RVH.
127 // - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton)
128 // that it has a pending cross-site request. We will check this on the IO
129 // thread when deciding how to handle the response.
130 // - The current RVH runs its beforeunload handler. If it returns false, we
131 // cancel all the pending logic. Otherwise we allow the pending RVH to send
132 // the navigation request to its renderer.
133 // - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the
134 // main resource load on the pending RVH. It creates a
135 // CrossSiteResourceHandler to check whether a process swap is needed when
136 // the request is ready to commit.
137 // - When RDH receives a response, the BufferedResourceHandler determines
138 // whether it is a download. If so, it sends a message to the new renderer
139 // causing it to cancel the request, and the download proceeds. For now, the
140 // pending RVH remains until the next DidNavigate event for this
141 // WebContentsImpl. This isn't ideal, but it doesn't affect any functionality.
142 // - After RDH receives a response and determines that it is safe and not a
143 // download, the CrossSiteResourceHandler checks whether a process swap is
144 // needed (either because CrossSiteRequestManager has state for it or because
145 // a transfer was needed for a redirect).
146 // - If so, CrossSiteResourceHandler pauses the response to first run the old
147 // page's unload handler. It does this by asynchronously calling the
148 // OnCrossSiteResponse method of RenderFrameHostManager on the UI thread,
149 // which sends a SwapOut message to the current RVH.
150 // - Once the unload handler is finished, RVHM::SwappedOut checks if a transfer
151 // to a new process is needed, based on the stored pending_nav_params_. (This
152 // is independent of whether we started out with a cross-process navigation.)
153 // - If not, it just tells the ResourceDispatcherHost to resume the response
154 // to its current RenderViewHost.
155 // - If so, it cancels the current pending RenderViewHost and sets up a new
156 // navigation using RequestTransferURL. When the transferred request
157 // arrives in the ResourceDispatcherHost, we transfer the response and
159 // - The pending renderer sends a FrameNavigate message that invokes the
160 // DidNavigate method. This replaces the current RVH with the
162 // - The previous renderer is kept swapped out in RenderFrameHostManager in case
163 // the user goes back. The process only stays live if another tab is using
164 // it, but if so, the existing frame relationships will be maintained.
169 const int kMinimumDelayBetweenLoadingUpdatesMS
= 100;
171 // This matches what Blink's ProgressTracker has traditionally used for a
172 // minimum progress value.
173 const double kMinimumLoadingProgress
= 0.1;
175 const char kDotGoogleDotCom
[] = ".google.com";
177 #if defined(OS_ANDROID)
178 const char kWebContentsAndroidKey
[] = "web_contents_android";
181 base::LazyInstance
<std::vector
<WebContentsImpl::CreatedCallback
> >
182 g_created_callbacks
= LAZY_INSTANCE_INITIALIZER
;
184 static int StartDownload(RenderFrameHost
* rfh
,
187 uint32_t max_bitmap_size
) {
188 static int g_next_image_download_id
= 0;
189 rfh
->Send(new ImageMsg_DownloadImage(rfh
->GetRoutingID(),
190 ++g_next_image_download_id
,
194 return g_next_image_download_id
;
197 void NotifyCacheOnIO(
198 scoped_refptr
<net::URLRequestContextGetter
> request_context
,
200 const std::string
& http_method
) {
201 request_context
->GetURLRequestContext()->http_transaction_factory()->
202 GetCache()->OnExternalCacheHit(url
, http_method
);
205 // Helper function for retrieving all the sites in a frame tree.
206 bool CollectSites(BrowserContext
* context
,
207 std::set
<GURL
>* sites
,
208 FrameTreeNode
* node
) {
209 sites
->insert(SiteInstance::GetSiteForURL(context
, node
->current_url()));
213 bool ForEachFrameInternal(
214 const base::Callback
<void(RenderFrameHost
*)>& on_frame
,
215 FrameTreeNode
* node
) {
216 on_frame
.Run(node
->current_frame_host());
220 bool ForEachPendingFrameInternal(
221 const base::Callback
<void(RenderFrameHost
*)>& on_frame
,
222 FrameTreeNode
* node
) {
223 RenderFrameHost
* pending_frame_host
=
224 node
->render_manager()->pending_frame_host();
225 if (pending_frame_host
)
226 on_frame
.Run(pending_frame_host
);
230 void SendToAllFramesInternal(IPC::Message
* message
, RenderFrameHost
* rfh
) {
231 IPC::Message
* message_copy
= new IPC::Message(*message
);
232 message_copy
->set_routing_id(rfh
->GetRoutingID());
233 rfh
->Send(message_copy
);
236 void AddRenderWidgetHostViewToSet(std::set
<RenderWidgetHostView
*>* set
,
237 RenderFrameHost
* rfh
) {
238 RenderWidgetHostView
* rwhv
= static_cast<RenderFrameHostImpl
*>(rfh
)
241 ->GetRenderWidgetHostView();
245 void SetAccessibilityModeOnFrame(AccessibilityMode mode
,
246 RenderFrameHost
* frame_host
) {
247 static_cast<RenderFrameHostImpl
*>(frame_host
)->SetAccessibilityMode(mode
);
252 WebContents
* WebContents::Create(const WebContents::CreateParams
& params
) {
253 return WebContentsImpl::CreateWithOpener(
254 params
, static_cast<WebContentsImpl
*>(params
.opener
));
257 WebContents
* WebContents::CreateWithSessionStorage(
258 const WebContents::CreateParams
& params
,
259 const SessionStorageNamespaceMap
& session_storage_namespace_map
) {
260 WebContentsImpl
* new_contents
= new WebContentsImpl(
261 params
.browser_context
, NULL
);
263 for (SessionStorageNamespaceMap::const_iterator it
=
264 session_storage_namespace_map
.begin();
265 it
!= session_storage_namespace_map
.end();
267 new_contents
->GetController()
268 .SetSessionStorageNamespace(it
->first
, it
->second
.get());
271 new_contents
->Init(params
);
275 void WebContentsImpl::AddCreatedCallback(const CreatedCallback
& callback
) {
276 g_created_callbacks
.Get().push_back(callback
);
279 void WebContentsImpl::RemoveCreatedCallback(const CreatedCallback
& callback
) {
280 for (size_t i
= 0; i
< g_created_callbacks
.Get().size(); ++i
) {
281 if (g_created_callbacks
.Get().at(i
).Equals(callback
)) {
282 g_created_callbacks
.Get().erase(g_created_callbacks
.Get().begin() + i
);
288 WebContents
* WebContents::FromRenderViewHost(const RenderViewHost
* rvh
) {
289 return rvh
->GetDelegate()->GetAsWebContents();
292 WebContents
* WebContents::FromRenderFrameHost(RenderFrameHost
* rfh
) {
293 RenderFrameHostImpl
* rfh_impl
= static_cast<RenderFrameHostImpl
*>(rfh
);
296 return rfh_impl
->delegate()->GetAsWebContents();
299 // WebContentsImpl::DestructionObserver ----------------------------------------
301 class WebContentsImpl::DestructionObserver
: public WebContentsObserver
{
303 DestructionObserver(WebContentsImpl
* owner
, WebContents
* watched_contents
)
304 : WebContentsObserver(watched_contents
),
308 // WebContentsObserver:
309 virtual void WebContentsDestroyed() OVERRIDE
{
310 owner_
->OnWebContentsDestroyed(
311 static_cast<WebContentsImpl
*>(web_contents()));
315 WebContentsImpl
* owner_
;
317 DISALLOW_COPY_AND_ASSIGN(DestructionObserver
);
320 WebContentsImpl::ColorChooserInfo::ColorChooserInfo(int render_process_id
,
322 ColorChooser
* chooser
,
324 : render_process_id(render_process_id
),
325 render_frame_id(render_frame_id
),
327 identifier(identifier
) {
330 WebContentsImpl::ColorChooserInfo::~ColorChooserInfo() {
333 // WebContentsImpl -------------------------------------------------------------
335 WebContentsImpl::WebContentsImpl(
336 BrowserContext
* browser_context
,
337 WebContentsImpl
* opener
)
339 controller_(this, browser_context
),
340 render_view_host_delegate_view_(NULL
),
342 created_with_opener_(!!opener
),
344 accessible_parent_(NULL
),
346 frame_tree_(new NavigatorImpl(&controller_
, this),
347 this, this, this, this),
349 is_load_to_different_document_(false),
350 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING
),
351 crashed_error_code_(0),
352 waiting_for_response_(false),
353 load_state_(net::LOAD_STATE_IDLE
, base::string16()),
354 loading_total_progress_(0.0),
355 loading_weak_factory_(this),
356 loading_frames_in_progress_(0),
359 displayed_insecure_content_(false),
360 has_accessed_initial_document_(false),
362 should_normally_be_visible_(true),
363 is_being_destroyed_(false),
364 notify_disconnection_(false),
365 dialog_manager_(NULL
),
366 is_showing_before_unload_dialog_(false),
367 last_active_time_(base::TimeTicks::Now()),
368 closed_by_user_gesture_(false),
369 minimum_zoom_percent_(static_cast<int>(kMinimumZoomFactor
* 100)),
370 maximum_zoom_percent_(static_cast<int>(kMaximumZoomFactor
* 100)),
371 totalPinchGestureAmount_(0),
372 currentPinchZoomStepDelta_(0),
373 render_view_message_source_(NULL
),
374 fullscreen_widget_routing_id_(MSG_ROUTING_NONE
),
375 fullscreen_widget_had_focus_at_shutdown_(false),
377 force_disable_overscroll_content_(false),
378 last_dialog_suppressed_(false),
380 BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode()),
381 audio_stream_monitor_(this) {
382 for (size_t i
= 0; i
< g_created_callbacks
.Get().size(); i
++)
383 g_created_callbacks
.Get().at(i
).Run(this);
384 frame_tree_
.SetFrameRemoveListener(
385 base::Bind(&WebContentsImpl::OnFrameRemoved
,
386 base::Unretained(this)));
389 WebContentsImpl::~WebContentsImpl() {
390 is_being_destroyed_
= true;
392 // Delete all RFH pending shutdown, which will lead the corresponding RVH to
393 // shutdown and be deleted as well.
395 base::Bind(&RenderFrameHostManager::ClearRFHsPendingShutdown
));
397 ClearAllPowerSaveBlockers();
399 for (std::set
<RenderWidgetHostImpl
*>::iterator iter
=
400 created_widgets_
.begin(); iter
!= created_widgets_
.end(); ++iter
) {
401 (*iter
)->DetachDelegate();
403 created_widgets_
.clear();
405 // Clear out any JavaScript state.
407 dialog_manager_
->WebContentsDestroyed(this);
409 if (color_chooser_info_
.get())
410 color_chooser_info_
->chooser
->End();
412 NotifyDisconnected();
414 // Notify any observer that have a reference on this WebContents.
415 NotificationService::current()->Notify(
416 NOTIFICATION_WEB_CONTENTS_DESTROYED
,
417 Source
<WebContents
>(this),
418 NotificationService::NoDetails());
420 // Destroy all frame tree nodes except for the root; this notifies observers.
421 frame_tree_
.ResetForMainFrameSwap();
422 GetRenderManager()->ResetProxyHosts();
424 // Manually call the observer methods for the root frame tree node.
425 RenderFrameHostManager
* root
= GetRenderManager();
426 if (root
->pending_frame_host()) {
427 FOR_EACH_OBSERVER(WebContentsObserver
,
429 RenderFrameDeleted(root
->pending_frame_host()));
431 FOR_EACH_OBSERVER(WebContentsObserver
,
433 RenderFrameDeleted(root
->current_frame_host()));
435 if (root
->pending_render_view_host()) {
436 FOR_EACH_OBSERVER(WebContentsObserver
,
438 RenderViewDeleted(root
->pending_render_view_host()));
441 FOR_EACH_OBSERVER(WebContentsObserver
,
443 RenderViewDeleted(root
->current_host()));
445 FOR_EACH_OBSERVER(WebContentsObserver
,
447 WebContentsDestroyed());
449 FOR_EACH_OBSERVER(WebContentsObserver
,
455 STLDeleteContainerPairSecondPointers(destruction_observers_
.begin(),
456 destruction_observers_
.end());
459 WebContentsImpl
* WebContentsImpl::CreateWithOpener(
460 const WebContents::CreateParams
& params
,
461 WebContentsImpl
* opener
) {
462 TRACE_EVENT0("browser", "WebContentsImpl::CreateWithOpener");
463 WebContentsImpl
* new_contents
= new WebContentsImpl(
464 params
.browser_context
, params
.opener_suppressed
? NULL
: opener
);
466 if (params
.guest_delegate
) {
467 // This makes |new_contents| act as a guest.
468 // For more info, see comment above class BrowserPluginGuest.
469 BrowserPluginGuest::Create(new_contents
, params
.guest_delegate
);
470 // We are instantiating a WebContents for browser plugin. Set its subframe
472 new_contents
->is_subframe_
= true;
474 new_contents
->Init(params
);
479 std::vector
<WebContentsImpl
*> WebContentsImpl::GetAllWebContents() {
480 std::vector
<WebContentsImpl
*> result
;
481 scoped_ptr
<RenderWidgetHostIterator
> widgets(
482 RenderWidgetHostImpl::GetRenderWidgetHosts());
483 std::set
<WebContentsImpl
*> web_contents_set
;
484 while (RenderWidgetHost
* rwh
= widgets
->GetNextHost()) {
485 if (!rwh
->IsRenderView())
487 RenderViewHost
* rvh
= RenderViewHost::From(rwh
);
490 WebContents
* web_contents
= WebContents::FromRenderViewHost(rvh
);
493 WebContentsImpl
* wci
= static_cast<WebContentsImpl
*>(web_contents
);
494 if (web_contents_set
.find(wci
) == web_contents_set
.end()) {
495 web_contents_set
.insert(wci
);
496 result
.push_back(wci
);
502 RenderFrameHostManager
* WebContentsImpl::GetRenderManagerForTesting() {
503 return GetRenderManager();
506 bool WebContentsImpl::OnMessageReceived(RenderViewHost
* render_view_host
,
507 const IPC::Message
& message
) {
508 return OnMessageReceived(render_view_host
, NULL
, message
);
511 bool WebContentsImpl::OnMessageReceived(RenderViewHost
* render_view_host
,
512 RenderFrameHost
* render_frame_host
,
513 const IPC::Message
& message
) {
514 DCHECK(render_view_host
|| render_frame_host
);
516 static_cast<WebUIImpl
*>(GetWebUI())->OnMessageReceived(message
)) {
520 ObserverListBase
<WebContentsObserver
>::Iterator
it(observers_
);
521 WebContentsObserver
* observer
;
522 if (render_frame_host
) {
523 while ((observer
= it
.GetNext()) != NULL
)
524 if (observer
->OnMessageReceived(message
, render_frame_host
))
527 while ((observer
= it
.GetNext()) != NULL
)
528 if (observer
->OnMessageReceived(message
))
532 // Message handlers should be aware of which
533 // RenderViewHost/RenderFrameHost sent the message, which is temporarily
534 // stored in render_(view|frame)_message_source_.
535 if (render_frame_host
)
536 render_frame_message_source_
= render_frame_host
;
538 render_view_message_source_
= render_view_host
;
541 IPC_BEGIN_MESSAGE_MAP(WebContentsImpl
, message
)
542 IPC_MESSAGE_HANDLER(FrameHostMsg_PepperPluginHung
, OnPepperPluginHung
)
543 IPC_MESSAGE_HANDLER(FrameHostMsg_PluginCrashed
, OnPluginCrashed
)
544 IPC_MESSAGE_HANDLER(FrameHostMsg_DomOperationResponse
,
545 OnDomOperationResponse
)
546 IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeThemeColor
,
548 IPC_MESSAGE_HANDLER(FrameHostMsg_DidFinishDocumentLoad
,
549 OnDocumentLoadedInFrame
)
550 IPC_MESSAGE_HANDLER(FrameHostMsg_DidFinishLoad
, OnDidFinishLoad
)
551 IPC_MESSAGE_HANDLER(FrameHostMsg_DidStartLoading
, OnDidStartLoading
)
552 IPC_MESSAGE_HANDLER(FrameHostMsg_DidStopLoading
, OnDidStopLoading
)
553 IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeLoadProgress
,
554 OnDidChangeLoadProgress
)
555 IPC_MESSAGE_HANDLER(FrameHostMsg_OpenColorChooser
, OnOpenColorChooser
)
556 IPC_MESSAGE_HANDLER(FrameHostMsg_EndColorChooser
, OnEndColorChooser
)
557 IPC_MESSAGE_HANDLER(FrameHostMsg_SetSelectedColorInColorChooser
,
558 OnSetSelectedColorInColorChooser
)
559 IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPlayingNotification
,
560 OnMediaPlayingNotification
)
561 IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPausedNotification
,
562 OnMediaPausedNotification
)
563 IPC_MESSAGE_HANDLER(FrameHostMsg_DidFirstVisuallyNonEmptyPaint
,
564 OnFirstVisuallyNonEmptyPaint
)
565 IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache
,
566 OnDidLoadResourceFromMemoryCache
)
567 IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent
,
568 OnDidDisplayInsecureContent
)
569 IPC_MESSAGE_HANDLER(ViewHostMsg_DidRunInsecureContent
,
570 OnDidRunInsecureContent
)
571 IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset
, OnGoToEntryAtOffset
)
572 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits
, OnUpdateZoomLimits
)
573 IPC_MESSAGE_HANDLER(ViewHostMsg_EnumerateDirectory
, OnEnumerateDirectory
)
574 IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler
,
575 OnRegisterProtocolHandler
)
576 IPC_MESSAGE_HANDLER(ViewHostMsg_UnregisterProtocolHandler
,
577 OnUnregisterProtocolHandler
)
578 IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply
, OnFindReply
)
579 IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed
, OnAppCacheAccessed
)
580 IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend
, OnWebUISend
)
581 #if defined(ENABLE_PLUGINS)
582 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission
,
583 OnRequestPpapiBrokerPermission
)
584 IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_Attach
,
585 OnBrowserPluginMessage(message
))
587 IPC_MESSAGE_HANDLER(ImageHostMsg_DidDownloadImage
, OnDidDownloadImage
)
588 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFaviconURL
, OnUpdateFaviconURL
)
589 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowValidationMessage
,
590 OnShowValidationMessage
)
591 IPC_MESSAGE_HANDLER(ViewHostMsg_HideValidationMessage
,
592 OnHideValidationMessage
)
593 IPC_MESSAGE_HANDLER(ViewHostMsg_MoveValidationMessage
,
594 OnMoveValidationMessage
)
595 #if defined(OS_ANDROID)
596 IPC_MESSAGE_HANDLER(ViewHostMsg_FindMatchRects_Reply
,
597 OnFindMatchRectsReply
)
598 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog
,
599 OnOpenDateTimeDialog
)
601 IPC_MESSAGE_UNHANDLED(handled
= false)
602 IPC_END_MESSAGE_MAP()
603 render_view_message_source_
= NULL
;
604 render_frame_message_source_
= NULL
;
609 void WebContentsImpl::RunFileChooser(
610 RenderViewHost
* render_view_host
,
611 const FileChooserParams
& params
) {
613 delegate_
->RunFileChooser(this, params
);
616 NavigationControllerImpl
& WebContentsImpl::GetController() {
620 const NavigationControllerImpl
& WebContentsImpl::GetController() const {
624 BrowserContext
* WebContentsImpl::GetBrowserContext() const {
625 return controller_
.GetBrowserContext();
628 const GURL
& WebContentsImpl::GetURL() const {
629 // We may not have a navigation entry yet.
630 NavigationEntry
* entry
= controller_
.GetVisibleEntry();
631 return entry
? entry
->GetVirtualURL() : GURL::EmptyGURL();
634 const GURL
& WebContentsImpl::GetVisibleURL() const {
635 // We may not have a navigation entry yet.
636 NavigationEntry
* entry
= controller_
.GetVisibleEntry();
637 return entry
? entry
->GetVirtualURL() : GURL::EmptyGURL();
640 const GURL
& WebContentsImpl::GetLastCommittedURL() const {
641 // We may not have a navigation entry yet.
642 NavigationEntry
* entry
= controller_
.GetLastCommittedEntry();
643 return entry
? entry
->GetVirtualURL() : GURL::EmptyGURL();
646 WebContentsDelegate
* WebContentsImpl::GetDelegate() {
650 void WebContentsImpl::SetDelegate(WebContentsDelegate
* delegate
) {
651 // TODO(cbentzel): remove this debugging code?
652 if (delegate
== delegate_
)
655 delegate_
->Detach(this);
656 delegate_
= delegate
;
658 delegate_
->Attach(this);
659 // Ensure the visible RVH reflects the new delegate's preferences.
661 view_
->SetOverscrollControllerEnabled(CanOverscrollContent());
665 RenderProcessHost
* WebContentsImpl::GetRenderProcessHost() const {
666 RenderViewHostImpl
* host
= GetRenderManager()->current_host();
667 return host
? host
->GetProcess() : NULL
;
670 RenderFrameHost
* WebContentsImpl::GetMainFrame() {
671 return frame_tree_
.root()->current_frame_host();
674 RenderFrameHost
* WebContentsImpl::GetFocusedFrame() {
675 if (!frame_tree_
.GetFocusedFrame())
677 return frame_tree_
.GetFocusedFrame()->current_frame_host();
680 void WebContentsImpl::ForEachFrame(
681 const base::Callback
<void(RenderFrameHost
*)>& on_frame
) {
682 frame_tree_
.ForEach(base::Bind(&ForEachFrameInternal
, on_frame
));
685 void WebContentsImpl::SendToAllFrames(IPC::Message
* message
) {
686 ForEachFrame(base::Bind(&SendToAllFramesInternal
, message
));
690 RenderViewHost
* WebContentsImpl::GetRenderViewHost() const {
691 return GetRenderManager()->current_host();
694 int WebContentsImpl::GetRoutingID() const {
695 if (!GetRenderViewHost())
696 return MSG_ROUTING_NONE
;
698 return GetRenderViewHost()->GetRoutingID();
701 int WebContentsImpl::GetFullscreenWidgetRoutingID() const {
702 return fullscreen_widget_routing_id_
;
705 RenderWidgetHostView
* WebContentsImpl::GetRenderWidgetHostView() const {
706 return GetRenderManager()->GetRenderWidgetHostView();
709 RenderWidgetHostView
* WebContentsImpl::GetFullscreenRenderWidgetHostView()
711 RenderWidgetHost
* const widget_host
=
712 RenderWidgetHostImpl::FromID(GetRenderProcessHost()->GetID(),
713 GetFullscreenWidgetRoutingID());
714 return widget_host
? widget_host
->GetView() : NULL
;
717 WebContentsView
* WebContentsImpl::GetView() const {
721 void WebContentsImpl::SetAccessibilityMode(AccessibilityMode mode
) {
722 if (mode
== accessibility_mode_
)
725 accessibility_mode_
= mode
;
727 base::Bind(&ForEachFrameInternal
,
728 base::Bind(&SetAccessibilityModeOnFrame
, mode
)));
730 base::Bind(&ForEachPendingFrameInternal
,
731 base::Bind(&SetAccessibilityModeOnFrame
, mode
)));
734 void WebContentsImpl::AddAccessibilityMode(AccessibilityMode mode
) {
735 SetAccessibilityMode(AddAccessibilityModeTo(accessibility_mode_
, mode
));
738 void WebContentsImpl::RemoveAccessibilityMode(AccessibilityMode mode
) {
739 SetAccessibilityMode(RemoveAccessibilityModeFrom(accessibility_mode_
, mode
));
742 WebUI
* WebContentsImpl::CreateWebUI(const GURL
& url
) {
743 WebUIImpl
* web_ui
= new WebUIImpl(this);
744 WebUIController
* controller
= WebUIControllerFactoryRegistry::GetInstance()->
745 CreateWebUIControllerForURL(web_ui
, url
);
747 web_ui
->AddMessageHandler(new GenericHandler());
748 web_ui
->SetController(controller
);
756 WebUI
* WebContentsImpl::GetWebUI() const {
757 return GetRenderManager()->web_ui() ? GetRenderManager()->web_ui()
758 : GetRenderManager()->pending_web_ui();
761 WebUI
* WebContentsImpl::GetCommittedWebUI() const {
762 return GetRenderManager()->web_ui();
765 void WebContentsImpl::SetUserAgentOverride(const std::string
& override
) {
766 if (GetUserAgentOverride() == override
)
769 renderer_preferences_
.user_agent_override
= override
;
771 // Send the new override string to the renderer.
772 RenderViewHost
* host
= GetRenderViewHost();
774 host
->SyncRendererPrefs();
776 // Reload the page if a load is currently in progress to avoid having
777 // different parts of the page loaded using different user agents.
778 NavigationEntry
* entry
= controller_
.GetVisibleEntry();
779 if (is_loading_
&& entry
!= NULL
&& entry
->GetIsOverridingUserAgent())
780 controller_
.ReloadIgnoringCache(true);
782 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
783 UserAgentOverrideSet(override
));
786 const std::string
& WebContentsImpl::GetUserAgentOverride() const {
787 return renderer_preferences_
.user_agent_override
;
790 void WebContentsImpl::EnableTreeOnlyAccessibilityMode() {
791 AddAccessibilityMode(AccessibilityModeTreeOnly
);
794 bool WebContentsImpl::IsTreeOnlyAccessibilityModeForTesting() const {
795 return accessibility_mode_
== AccessibilityModeTreeOnly
;
798 bool WebContentsImpl::IsFullAccessibilityModeForTesting() const {
799 return accessibility_mode_
== AccessibilityModeComplete
;
803 void WebContentsImpl::SetParentNativeViewAccessible(
804 gfx::NativeViewAccessible accessible_parent
) {
805 accessible_parent_
= accessible_parent
;
806 RenderFrameHostImpl
* rfh
= static_cast<RenderFrameHostImpl
*>(GetMainFrame());
808 rfh
->SetParentNativeViewAccessible(accessible_parent
);
812 const base::string16
& WebContentsImpl::GetTitle() const {
813 // Transient entries take precedence. They are used for interstitial pages
814 // that are shown on top of existing pages.
815 NavigationEntry
* entry
= controller_
.GetTransientEntry();
816 std::string accept_languages
=
817 GetContentClient()->browser()->GetAcceptLangs(
818 GetBrowserContext());
820 return entry
->GetTitleForDisplay(accept_languages
);
822 WebUI
* our_web_ui
= GetRenderManager()->pending_web_ui() ?
823 GetRenderManager()->pending_web_ui() : GetRenderManager()->web_ui();
825 // Don't override the title in view source mode.
826 entry
= controller_
.GetVisibleEntry();
827 if (!(entry
&& entry
->IsViewSourceMode())) {
828 // Give the Web UI the chance to override our title.
829 const base::string16
& title
= our_web_ui
->GetOverriddenTitle();
835 // We use the title for the last committed entry rather than a pending
836 // navigation entry. For example, when the user types in a URL, we want to
837 // keep the old page's title until the new load has committed and we get a new
839 entry
= controller_
.GetLastCommittedEntry();
841 // We make an exception for initial navigations.
842 if (controller_
.IsInitialNavigation()) {
843 // We only want to use the title from the visible entry in one of two cases:
844 // 1. There's already a committed entry for an initial navigation, in which
845 // case we are doing a history navigation in a new tab (e.g., Ctrl+Back).
846 // 2. The pending entry has been explicitly assigned a title to display.
848 // If there's no last committed entry and no assigned title, we should fall
849 // back to |page_title_when_no_navigation_entry_| rather than showing the
852 (controller_
.GetVisibleEntry() &&
853 !controller_
.GetVisibleEntry()->GetTitle().empty())) {
854 entry
= controller_
.GetVisibleEntry();
859 return entry
->GetTitleForDisplay(accept_languages
);
862 // |page_title_when_no_navigation_entry_| is finally used
863 // if no title cannot be retrieved.
864 return page_title_when_no_navigation_entry_
;
867 int32
WebContentsImpl::GetMaxPageID() {
868 return GetMaxPageIDForSiteInstance(GetSiteInstance());
871 int32
WebContentsImpl::GetMaxPageIDForSiteInstance(
872 SiteInstance
* site_instance
) {
873 if (max_page_ids_
.find(site_instance
->GetId()) == max_page_ids_
.end())
874 max_page_ids_
[site_instance
->GetId()] = -1;
876 return max_page_ids_
[site_instance
->GetId()];
879 void WebContentsImpl::UpdateMaxPageID(int32 page_id
) {
880 UpdateMaxPageIDForSiteInstance(GetSiteInstance(), page_id
);
883 void WebContentsImpl::UpdateMaxPageIDForSiteInstance(
884 SiteInstance
* site_instance
, int32 page_id
) {
885 if (GetMaxPageIDForSiteInstance(site_instance
) < page_id
)
886 max_page_ids_
[site_instance
->GetId()] = page_id
;
889 void WebContentsImpl::CopyMaxPageIDsFrom(WebContents
* web_contents
) {
890 WebContentsImpl
* contents
= static_cast<WebContentsImpl
*>(web_contents
);
891 max_page_ids_
= contents
->max_page_ids_
;
894 SiteInstance
* WebContentsImpl::GetSiteInstance() const {
895 return GetRenderManager()->current_host()->GetSiteInstance();
898 SiteInstance
* WebContentsImpl::GetPendingSiteInstance() const {
899 RenderViewHost
* dest_rvh
= GetRenderManager()->pending_render_view_host() ?
900 GetRenderManager()->pending_render_view_host() :
901 GetRenderManager()->current_host();
902 return dest_rvh
->GetSiteInstance();
905 bool WebContentsImpl::IsLoading() const {
909 bool WebContentsImpl::IsLoadingToDifferentDocument() const {
910 return is_loading_
&& is_load_to_different_document_
;
913 bool WebContentsImpl::IsWaitingForResponse() const {
914 return waiting_for_response_
&& is_load_to_different_document_
;
917 const net::LoadStateWithParam
& WebContentsImpl::GetLoadState() const {
921 const base::string16
& WebContentsImpl::GetLoadStateHost() const {
922 return load_state_host_
;
925 uint64
WebContentsImpl::GetUploadSize() const {
929 uint64
WebContentsImpl::GetUploadPosition() const {
930 return upload_position_
;
933 std::set
<GURL
> WebContentsImpl::GetSitesInTab() const {
934 std::set
<GURL
> sites
;
935 frame_tree_
.ForEach(base::Bind(&CollectSites
,
936 base::Unretained(GetBrowserContext()),
937 base::Unretained(&sites
)));
941 const std::string
& WebContentsImpl::GetEncoding() const {
942 return canonical_encoding_
;
945 bool WebContentsImpl::DisplayedInsecureContent() const {
946 return displayed_insecure_content_
;
949 void WebContentsImpl::IncrementCapturerCount(const gfx::Size
& capture_size
) {
950 DCHECK(!is_being_destroyed_
);
952 DVLOG(1) << "There are now " << capturer_count_
953 << " capturing(s) of WebContentsImpl@" << this;
955 // Note: This provides a hint to upstream code to size the views optimally
956 // for quality (e.g., to avoid scaling).
957 if (!capture_size
.IsEmpty() && preferred_size_for_capture_
.IsEmpty()) {
958 preferred_size_for_capture_
= capture_size
;
959 OnPreferredSizeChanged(preferred_size_
);
963 void WebContentsImpl::DecrementCapturerCount() {
965 DVLOG(1) << "There are now " << capturer_count_
966 << " capturing(s) of WebContentsImpl@" << this;
967 DCHECK_LE(0, capturer_count_
);
969 if (is_being_destroyed_
)
972 if (capturer_count_
== 0) {
973 const gfx::Size old_size
= preferred_size_for_capture_
;
974 preferred_size_for_capture_
= gfx::Size();
975 OnPreferredSizeChanged(old_size
);
979 DVLOG(1) << "Executing delayed WasHidden().";
984 int WebContentsImpl::GetCapturerCount() const {
985 return capturer_count_
;
988 bool WebContentsImpl::IsCrashed() const {
989 return (crashed_status_
== base::TERMINATION_STATUS_PROCESS_CRASHED
||
990 crashed_status_
== base::TERMINATION_STATUS_ABNORMAL_TERMINATION
||
991 crashed_status_
== base::TERMINATION_STATUS_PROCESS_WAS_KILLED
);
994 void WebContentsImpl::SetIsCrashed(base::TerminationStatus status
,
996 if (status
== crashed_status_
)
999 crashed_status_
= status
;
1000 crashed_error_code_
= error_code
;
1001 NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB
);
1004 base::TerminationStatus
WebContentsImpl::GetCrashedStatus() const {
1005 return crashed_status_
;
1008 bool WebContentsImpl::IsBeingDestroyed() const {
1009 return is_being_destroyed_
;
1012 void WebContentsImpl::NotifyNavigationStateChanged(
1013 InvalidateTypes changed_flags
) {
1014 // Create and release the audio power save blocker depending on whether the
1015 // tab is actively producing audio or not.
1016 if (changed_flags
== INVALIDATE_TYPE_TAB
&&
1017 AudioStreamMonitor::monitoring_available()) {
1018 if (WasRecentlyAudible()) {
1019 if (!audio_power_save_blocker_
)
1020 CreateAudioPowerSaveBlocker();
1022 audio_power_save_blocker_
.reset();
1027 delegate_
->NavigationStateChanged(this, changed_flags
);
1030 base::TimeTicks
WebContentsImpl::GetLastActiveTime() const {
1031 return last_active_time_
;
1034 void WebContentsImpl::WasShown() {
1035 controller_
.SetActive(true);
1037 std::set
<RenderWidgetHostView
*> widgets
= GetRenderWidgetHostViewsInTree();
1038 for (std::set
<RenderWidgetHostView
*>::iterator iter
= widgets
.begin();
1039 iter
!= widgets
.end();
1043 #if defined(OS_MACOSX)
1044 (*iter
)->SetActive(true);
1049 last_active_time_
= base::TimeTicks::Now();
1051 // The resize rect might have changed while this was inactive -- send the new
1052 // one to make sure it's up to date.
1053 RenderViewHostImpl
* rvh
=
1054 static_cast<RenderViewHostImpl
*>(GetRenderViewHost());
1056 rvh
->ResizeRectChanged(GetRootWindowResizerRect());
1059 // Restore power save blocker if there are active video players running.
1060 if (!active_video_players_
.empty() && !video_power_save_blocker_
)
1061 CreateVideoPowerSaveBlocker();
1063 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, WasShown());
1065 should_normally_be_visible_
= true;
1068 void WebContentsImpl::WasHidden() {
1069 // If there are entities capturing screenshots or video (e.g., mirroring),
1070 // don't activate the "disable rendering" optimization.
1071 if (capturer_count_
== 0) {
1072 // |GetRenderViewHost()| can be NULL if the user middle clicks a link to
1073 // open a tab in the background, then closes the tab before selecting it.
1074 // This is because closing the tab calls WebContentsImpl::Destroy(), which
1075 // removes the |GetRenderViewHost()|; then when we actually destroy the
1076 // window, OnWindowPosChanged() notices and calls WasHidden() (which
1078 std::set
<RenderWidgetHostView
*> widgets
= GetRenderWidgetHostViewsInTree();
1079 for (std::set
<RenderWidgetHostView
*>::iterator iter
= widgets
.begin();
1080 iter
!= widgets
.end();
1086 // Release any video power save blockers held as video is not visible.
1087 video_power_save_blocker_
.reset();
1090 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, WasHidden());
1092 should_normally_be_visible_
= false;
1095 bool WebContentsImpl::NeedToFireBeforeUnload() {
1096 // TODO(creis): Should we fire even for interstitial pages?
1097 return WillNotifyDisconnection() &&
1098 !ShowingInterstitialPage() &&
1099 !static_cast<RenderViewHostImpl
*>(
1100 GetRenderViewHost())->SuddenTerminationAllowed();
1103 void WebContentsImpl::DispatchBeforeUnload(bool for_cross_site_transition
) {
1104 static_cast<RenderFrameHostImpl
*>(GetMainFrame())->DispatchBeforeUnload(
1105 for_cross_site_transition
);
1108 void WebContentsImpl::Stop() {
1109 GetRenderManager()->Stop();
1110 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, NavigationStopped());
1113 WebContents
* WebContentsImpl::Clone() {
1114 // We use our current SiteInstance since the cloned entry will use it anyway.
1115 // We pass our own opener so that the cloned page can access it if it was
1117 CreateParams
create_params(GetBrowserContext(), GetSiteInstance());
1118 create_params
.initial_size
= GetContainerBounds().size();
1119 WebContentsImpl
* tc
= CreateWithOpener(create_params
, opener_
);
1120 tc
->GetController().CopyStateFrom(controller_
);
1121 FOR_EACH_OBSERVER(WebContentsObserver
,
1123 DidCloneToNewWebContents(this, tc
));
1127 void WebContentsImpl::Observe(int type
,
1128 const NotificationSource
& source
,
1129 const NotificationDetails
& details
) {
1131 case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED
: {
1132 RenderWidgetHost
* host
= Source
<RenderWidgetHost
>(source
).ptr();
1133 RenderWidgetHostView
* view
= host
->GetView();
1134 if (view
== GetFullscreenRenderWidgetHostView()) {
1135 // We cannot just call view_->RestoreFocus() here. On some platforms,
1136 // attempting to focus the currently-invisible WebContentsView will be
1137 // flat-out ignored. Therefore, this boolean is used to track whether
1138 // we will request focus after the fullscreen widget has been
1140 fullscreen_widget_had_focus_at_shutdown_
= (view
&& view
->HasFocus());
1142 for (PendingWidgetViews::iterator i
= pending_widget_views_
.begin();
1143 i
!= pending_widget_views_
.end(); ++i
) {
1144 if (host
->GetView() == i
->second
) {
1145 pending_widget_views_
.erase(i
);
1157 WebContents
* WebContentsImpl::GetWebContents() {
1161 void WebContentsImpl::Init(const WebContents::CreateParams
& params
) {
1162 // This is set before initializing the render manager since
1163 // RenderFrameHostManager::Init calls back into us via its delegate to ask if
1164 // it should be hidden.
1165 should_normally_be_visible_
= !params
.initially_hidden
;
1167 GetRenderManager()->Init(
1168 params
.browser_context
, params
.site_instance
, params
.routing_id
,
1169 params
.main_frame_routing_id
);
1171 WebContentsViewDelegate
* delegate
=
1172 GetContentClient()->browser()->GetWebContentsViewDelegate(this);
1174 if (browser_plugin_guest_
) {
1175 scoped_ptr
<WebContentsView
> platform_view(CreateWebContentsView(
1176 this, delegate
, &render_view_host_delegate_view_
));
1178 WebContentsViewGuest
* rv
= new WebContentsViewGuest(
1179 this, browser_plugin_guest_
.get(), platform_view
.Pass(),
1180 render_view_host_delegate_view_
);
1181 render_view_host_delegate_view_
= rv
;
1184 // Regular WebContentsView.
1185 view_
.reset(CreateWebContentsView(
1186 this, delegate
, &render_view_host_delegate_view_
));
1188 CHECK(render_view_host_delegate_view_
);
1191 gfx::Size initial_size
= params
.initial_size
;
1192 view_
->CreateView(initial_size
, params
.context
);
1194 // Listen for whether our opener gets destroyed.
1196 AddDestructionObserver(opener_
);
1198 registrar_
.Add(this,
1199 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED
,
1200 NotificationService::AllBrowserContextsAndSources());
1202 geolocation_dispatcher_host_
.reset(new GeolocationDispatcherHost(this));
1203 midi_dispatcher_host_
.reset(new MidiDispatcherHost(this));
1205 screen_orientation_dispatcher_host_
.reset(
1206 new ScreenOrientationDispatcherHost(this));
1208 #if defined(OS_ANDROID)
1209 date_time_chooser_
.reset(new DateTimeChooserAndroid());
1213 void WebContentsImpl::OnWebContentsDestroyed(WebContentsImpl
* web_contents
) {
1214 RemoveDestructionObserver(web_contents
);
1216 // Clear the opener if it has been closed.
1217 if (web_contents
== opener_
) {
1221 // Clear a pending contents that has been closed before being shown.
1222 for (PendingContents::iterator iter
= pending_contents_
.begin();
1223 iter
!= pending_contents_
.end();
1225 if (iter
->second
!= web_contents
)
1227 pending_contents_
.erase(iter
);
1233 void WebContentsImpl::AddDestructionObserver(WebContentsImpl
* web_contents
) {
1234 if (!ContainsKey(destruction_observers_
, web_contents
)) {
1235 destruction_observers_
[web_contents
] =
1236 new DestructionObserver(this, web_contents
);
1240 void WebContentsImpl::RemoveDestructionObserver(WebContentsImpl
* web_contents
) {
1241 DestructionObservers::iterator iter
=
1242 destruction_observers_
.find(web_contents
);
1243 if (iter
!= destruction_observers_
.end()) {
1244 delete destruction_observers_
[web_contents
];
1245 destruction_observers_
.erase(iter
);
1249 void WebContentsImpl::AddObserver(WebContentsObserver
* observer
) {
1250 observers_
.AddObserver(observer
);
1253 void WebContentsImpl::RemoveObserver(WebContentsObserver
* observer
) {
1254 observers_
.RemoveObserver(observer
);
1257 std::set
<RenderWidgetHostView
*>
1258 WebContentsImpl::GetRenderWidgetHostViewsInTree() {
1259 std::set
<RenderWidgetHostView
*> set
;
1260 if (ShowingInterstitialPage()) {
1261 set
.insert(GetRenderWidgetHostView());
1264 base::Bind(&AddRenderWidgetHostViewToSet
, base::Unretained(&set
)));
1269 void WebContentsImpl::Activate() {
1271 delegate_
->ActivateContents(this);
1274 void WebContentsImpl::Deactivate() {
1276 delegate_
->DeactivateContents(this);
1279 void WebContentsImpl::LostCapture() {
1281 delegate_
->LostCapture();
1284 void WebContentsImpl::RenderWidgetDeleted(
1285 RenderWidgetHostImpl
* render_widget_host
) {
1286 if (is_being_destroyed_
) {
1287 // |created_widgets_| might have been destroyed.
1291 std::set
<RenderWidgetHostImpl
*>::iterator iter
=
1292 created_widgets_
.find(render_widget_host
);
1293 if (iter
!= created_widgets_
.end())
1294 created_widgets_
.erase(iter
);
1296 if (render_widget_host
&&
1297 render_widget_host
->GetRoutingID() == fullscreen_widget_routing_id_
) {
1298 if (delegate_
&& delegate_
->EmbedsFullscreenWidget())
1299 delegate_
->ToggleFullscreenModeForTab(this, false);
1300 FOR_EACH_OBSERVER(WebContentsObserver
,
1302 DidDestroyFullscreenWidget(
1303 fullscreen_widget_routing_id_
));
1304 fullscreen_widget_routing_id_
= MSG_ROUTING_NONE
;
1305 if (fullscreen_widget_had_focus_at_shutdown_
)
1306 view_
->RestoreFocus();
1310 bool WebContentsImpl::PreHandleKeyboardEvent(
1311 const NativeWebKeyboardEvent
& event
,
1312 bool* is_keyboard_shortcut
) {
1314 delegate_
->PreHandleKeyboardEvent(this, event
, is_keyboard_shortcut
);
1317 void WebContentsImpl::HandleKeyboardEvent(const NativeWebKeyboardEvent
& event
) {
1318 if (browser_plugin_embedder_
&&
1319 browser_plugin_embedder_
->HandleKeyboardEvent(event
)) {
1323 delegate_
->HandleKeyboardEvent(this, event
);
1326 bool WebContentsImpl::HandleWheelEvent(
1327 const blink::WebMouseWheelEvent
& event
) {
1328 #if !defined(OS_MACOSX)
1329 // On platforms other than Mac, control+mousewheel changes zoom. On Mac, this
1330 // isn't done for two reasons:
1331 // -the OS already has a gesture to do this through pinch-zoom
1332 // -if a user starts an inertial scroll, let's go, and presses control
1333 // (i.e. control+tab) then the OS's buffered scroll events will come in
1334 // with control key set which isn't what the user wants
1336 event
.wheelTicksY
&&
1337 (event
.modifiers
& blink::WebInputEvent::ControlKey
) &&
1338 // Avoid adjusting the zoom in response to two-finger-scrolling touchpad
1339 // gestures, which are regrettably easy to trigger accidentally.
1340 !event
.hasPreciseScrollingDeltas
) {
1341 delegate_
->ContentsZoomChange(event
.wheelTicksY
> 0);
1348 bool WebContentsImpl::PreHandleGestureEvent(
1349 const blink::WebGestureEvent
& event
) {
1350 return delegate_
&& delegate_
->PreHandleGestureEvent(this, event
);
1353 bool WebContentsImpl::HandleGestureEvent(
1354 const blink::WebGestureEvent
& event
) {
1355 // Some platforms (eg. Mac) send GesturePinch events for trackpad pinch-zoom.
1356 // Use them to implement browser zoom, as for HandleWheelEvent above.
1357 if (event
.type
== blink::WebInputEvent::GesturePinchUpdate
&&
1358 event
.sourceDevice
== blink::WebGestureDeviceTouchpad
) {
1359 // The scale difference necessary to trigger a zoom action. Derived from
1360 // experimentation to find a value that feels reasonable.
1361 const float kZoomStepValue
= 0.6f
;
1363 // Find the (absolute) thresholds on either side of the current zoom factor,
1364 // then convert those to actual numbers to trigger a zoom in or out.
1365 // This logic deliberately makes the range around the starting zoom value
1366 // for the gesture twice as large as the other ranges (i.e., the notches are
1367 // at ..., -3*step, -2*step, -step, step, 2*step, 3*step, ... but not at 0)
1368 // so that it's easier to get back to your starting point than it is to
1370 float nextStep
= (abs(currentPinchZoomStepDelta_
) + 1) * kZoomStepValue
;
1371 float backStep
= abs(currentPinchZoomStepDelta_
) * kZoomStepValue
;
1372 float zoomInThreshold
= (currentPinchZoomStepDelta_
>= 0) ? nextStep
1374 float zoomOutThreshold
= (currentPinchZoomStepDelta_
<= 0) ? -nextStep
1377 totalPinchGestureAmount_
+= (event
.data
.pinchUpdate
.scale
- 1.0);
1378 if (totalPinchGestureAmount_
> zoomInThreshold
) {
1379 currentPinchZoomStepDelta_
++;
1381 delegate_
->ContentsZoomChange(true);
1382 } else if (totalPinchGestureAmount_
< zoomOutThreshold
) {
1383 currentPinchZoomStepDelta_
--;
1385 delegate_
->ContentsZoomChange(false);
1393 void WebContentsImpl::HandleMouseDown() {
1395 delegate_
->HandleMouseDown();
1398 void WebContentsImpl::HandleMouseUp() {
1400 delegate_
->HandleMouseUp();
1403 void WebContentsImpl::HandlePointerActivate() {
1405 delegate_
->HandlePointerActivate();
1408 void WebContentsImpl::HandleGestureBegin() {
1410 delegate_
->HandleGestureBegin();
1413 void WebContentsImpl::HandleGestureEnd() {
1415 delegate_
->HandleGestureEnd();
1418 void WebContentsImpl::ToggleFullscreenMode(bool enter_fullscreen
) {
1419 // This method is being called to enter or leave renderer-initiated fullscreen
1420 // mode. Either way, make sure any existing fullscreen widget is shut down
1422 RenderWidgetHostView
* const widget_view
= GetFullscreenRenderWidgetHostView();
1424 RenderWidgetHostImpl::From(widget_view
->GetRenderWidgetHost())->Shutdown();
1427 delegate_
->ToggleFullscreenModeForTab(this, enter_fullscreen
);
1429 FOR_EACH_OBSERVER(WebContentsObserver
,
1431 DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab()));
1434 bool WebContentsImpl::IsFullscreenForCurrentTab() const {
1435 return delegate_
? delegate_
->IsFullscreenForTabOrPending(this) : false;
1438 void WebContentsImpl::RequestToLockMouse(bool user_gesture
,
1439 bool last_unlocked_by_target
) {
1441 delegate_
->RequestToLockMouse(this, user_gesture
, last_unlocked_by_target
);
1443 GotResponseToLockMouseRequest(false);
1447 void WebContentsImpl::LostMouseLock() {
1449 delegate_
->LostMouseLock();
1452 void WebContentsImpl::CreateNewWindow(
1453 int render_process_id
,
1455 int main_frame_route_id
,
1456 const ViewHostMsg_CreateWindow_Params
& params
,
1457 SessionStorageNamespace
* session_storage_namespace
) {
1458 // We usually create the new window in the same BrowsingInstance (group of
1459 // script-related windows), by passing in the current SiteInstance. However,
1460 // if the opener is being suppressed (in a non-guest), we create a new
1461 // SiteInstance in its own BrowsingInstance.
1462 bool is_guest
= BrowserPluginGuest::IsGuest(this);
1464 // If the opener is to be suppressed, the new window can be in any process.
1465 // Since routing ids are process specific, we must not have one passed in
1466 // as argument here.
1467 DCHECK(!params
.opener_suppressed
|| route_id
== MSG_ROUTING_NONE
);
1469 scoped_refptr
<SiteInstance
> site_instance
=
1470 params
.opener_suppressed
&& !is_guest
?
1471 SiteInstance::CreateForURL(GetBrowserContext(), params
.target_url
) :
1474 // A message to create a new window can only come from the active process for
1475 // this WebContentsImpl instance. If any other process sends the request,
1476 // it is invalid and the process must be terminated.
1477 if (GetRenderProcessHost()->GetID() != render_process_id
) {
1478 base::ProcessHandle process_handle
=
1479 RenderProcessHost::FromID(render_process_id
)->GetHandle();
1480 if (process_handle
!= base::kNullProcessHandle
) {
1482 base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWindow"));
1483 base::KillProcess(process_handle
, RESULT_CODE_KILLED
, false);
1488 // We must assign the SessionStorageNamespace before calling Init().
1490 // http://crbug.com/142685
1491 const std::string
& partition_id
=
1492 GetContentClient()->browser()->
1493 GetStoragePartitionIdForSite(GetBrowserContext(),
1494 site_instance
->GetSiteURL());
1495 StoragePartition
* partition
= BrowserContext::GetStoragePartition(
1496 GetBrowserContext(), site_instance
.get());
1497 DOMStorageContextWrapper
* dom_storage_context
=
1498 static_cast<DOMStorageContextWrapper
*>(partition
->GetDOMStorageContext());
1499 SessionStorageNamespaceImpl
* session_storage_namespace_impl
=
1500 static_cast<SessionStorageNamespaceImpl
*>(session_storage_namespace
);
1501 CHECK(session_storage_namespace_impl
->IsFromContext(dom_storage_context
));
1504 !delegate_
->ShouldCreateWebContents(this,
1506 params
.window_container_type
,
1510 session_storage_namespace
)) {
1511 if (route_id
!= MSG_ROUTING_NONE
&&
1512 !RenderViewHost::FromID(render_process_id
, route_id
)) {
1513 // If the embedder didn't create a WebContents for this route, we need to
1514 // delete the RenderView that had already been created.
1515 Send(new ViewMsg_Close(route_id
));
1517 GetRenderViewHost()->GetProcess()->ResumeRequestsForView(route_id
);
1518 GetRenderViewHost()->GetProcess()->ResumeRequestsForView(
1519 main_frame_route_id
);
1523 // Create the new web contents. This will automatically create the new
1524 // WebContentsView. In the future, we may want to create the view separately.
1525 CreateParams
create_params(GetBrowserContext(), site_instance
.get());
1526 create_params
.routing_id
= route_id
;
1527 create_params
.main_frame_routing_id
= main_frame_route_id
;
1528 create_params
.opener
= this;
1529 create_params
.opener_suppressed
= params
.opener_suppressed
;
1530 if (params
.disposition
== NEW_BACKGROUND_TAB
)
1531 create_params
.initially_hidden
= true;
1533 WebContentsImpl
* new_contents
= NULL
;
1535 create_params
.context
= view_
->GetNativeView();
1536 create_params
.initial_size
= GetContainerBounds().size();
1537 new_contents
= static_cast<WebContentsImpl
*>(
1538 WebContents::Create(create_params
));
1540 new_contents
= GetBrowserPluginGuest()->CreateNewGuestWindow(create_params
);
1542 new_contents
->GetController().SetSessionStorageNamespace(
1544 session_storage_namespace
);
1545 new_contents
->RenderViewCreated(new_contents
->GetRenderViewHost());
1547 // Save the window for later if we're not suppressing the opener (since it
1548 // will be shown immediately).
1549 if (!params
.opener_suppressed
) {
1551 WebContentsView
* new_view
= new_contents
->view_
.get();
1553 // TODO(brettw): It seems bogus that we have to call this function on the
1554 // newly created object and give it one of its own member variables.
1555 new_view
->CreateViewForWidget(new_contents
->GetRenderViewHost());
1557 // Save the created window associated with the route so we can show it
1559 DCHECK_NE(MSG_ROUTING_NONE
, route_id
);
1560 pending_contents_
[route_id
] = new_contents
;
1561 AddDestructionObserver(new_contents
);
1565 delegate_
->WebContentsCreated(
1566 this, params
.opener_render_frame_id
, params
.frame_name
,
1567 params
.target_url
, new_contents
);
1570 if (params
.opener_suppressed
) {
1571 // When the opener is suppressed, the original renderer cannot access the
1572 // new window. As a result, we need to show and navigate the window here.
1573 bool was_blocked
= false;
1575 gfx::Rect initial_pos
;
1576 delegate_
->AddNewContents(
1577 this, new_contents
, params
.disposition
, initial_pos
,
1578 params
.user_gesture
, &was_blocked
);
1581 OpenURLParams
open_params(params
.target_url
,
1584 PAGE_TRANSITION_LINK
,
1585 true /* is_renderer_initiated */);
1586 open_params
.user_gesture
= params
.user_gesture
;
1587 new_contents
->OpenURL(open_params
);
1592 void WebContentsImpl::CreateNewWidget(int render_process_id
,
1594 blink::WebPopupType popup_type
) {
1595 CreateNewWidget(render_process_id
, route_id
, false, popup_type
);
1598 void WebContentsImpl::CreateNewFullscreenWidget(int render_process_id
,
1600 CreateNewWidget(render_process_id
, route_id
, true, blink::WebPopupTypeNone
);
1603 void WebContentsImpl::CreateNewWidget(int render_process_id
,
1606 blink::WebPopupType popup_type
) {
1607 RenderProcessHost
* process
= GetRenderProcessHost();
1608 // A message to create a new widget can only come from the active process for
1609 // this WebContentsImpl instance. If any other process sends the request,
1610 // it is invalid and the process must be terminated.
1611 if (process
->GetID() != render_process_id
) {
1612 base::ProcessHandle process_handle
=
1613 RenderProcessHost::FromID(render_process_id
)->GetHandle();
1614 if (process_handle
!= base::kNullProcessHandle
) {
1616 base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWidget"));
1617 base::KillProcess(process_handle
, RESULT_CODE_KILLED
, false);
1622 RenderWidgetHostImpl
* widget_host
=
1623 new RenderWidgetHostImpl(this, process
, route_id
, IsHidden());
1624 created_widgets_
.insert(widget_host
);
1626 RenderWidgetHostViewBase
* widget_view
=
1627 static_cast<RenderWidgetHostViewBase
*>(
1628 view_
->CreateViewForPopupWidget(widget_host
));
1631 if (!is_fullscreen
) {
1632 // Popups should not get activated.
1633 widget_view
->SetPopupType(popup_type
);
1635 // Save the created widget associated with the route so we can show it later.
1636 pending_widget_views_
[route_id
] = widget_view
;
1638 #if defined(OS_MACOSX)
1639 // A RenderWidgetHostViewMac has lifetime scoped to the view. We'll retain it
1640 // to allow it to survive the trip without being hosted.
1641 base::mac::NSObjectRetain(widget_view
->GetNativeView());
1645 void WebContentsImpl::ShowCreatedWindow(int route_id
,
1646 WindowOpenDisposition disposition
,
1647 const gfx::Rect
& initial_pos
,
1648 bool user_gesture
) {
1649 WebContentsImpl
* contents
= GetCreatedWindow(route_id
);
1651 WebContentsDelegate
* delegate
= GetDelegate();
1653 delegate
->AddNewContents(
1654 this, contents
, disposition
, initial_pos
, user_gesture
, NULL
);
1659 void WebContentsImpl::ShowCreatedWidget(int route_id
,
1660 const gfx::Rect
& initial_pos
) {
1661 ShowCreatedWidget(route_id
, false, initial_pos
);
1664 void WebContentsImpl::ShowCreatedFullscreenWidget(int route_id
) {
1665 ShowCreatedWidget(route_id
, true, gfx::Rect());
1668 void WebContentsImpl::ShowCreatedWidget(int route_id
,
1670 const gfx::Rect
& initial_pos
) {
1671 RenderWidgetHostViewBase
* widget_host_view
=
1672 static_cast<RenderWidgetHostViewBase
*>(GetCreatedWidget(route_id
));
1673 if (!widget_host_view
)
1676 RenderWidgetHostView
* view
= NULL
;
1677 BrowserPluginGuest
* guest
= GetBrowserPluginGuest();
1678 if (guest
&& guest
->embedder_web_contents()) {
1679 view
= guest
->embedder_web_contents()->GetRenderWidgetHostView();
1681 view
= GetRenderWidgetHostView();
1684 if (is_fullscreen
) {
1685 DCHECK_EQ(MSG_ROUTING_NONE
, fullscreen_widget_routing_id_
);
1686 view_
->StoreFocus();
1687 fullscreen_widget_routing_id_
= route_id
;
1688 if (delegate_
&& delegate_
->EmbedsFullscreenWidget()) {
1689 widget_host_view
->InitAsChild(GetRenderWidgetHostView()->GetNativeView());
1690 delegate_
->ToggleFullscreenModeForTab(this, true);
1692 widget_host_view
->InitAsFullscreen(view
);
1694 FOR_EACH_OBSERVER(WebContentsObserver
,
1696 DidShowFullscreenWidget(route_id
));
1697 if (!widget_host_view
->HasFocus())
1698 widget_host_view
->Focus();
1700 widget_host_view
->InitAsPopup(view
, initial_pos
);
1703 RenderWidgetHostImpl
* render_widget_host_impl
=
1704 RenderWidgetHostImpl::From(widget_host_view
->GetRenderWidgetHost());
1705 render_widget_host_impl
->Init();
1706 // Only allow privileged mouse lock for fullscreen render widget, which is
1707 // used to implement Pepper Flash fullscreen.
1708 render_widget_host_impl
->set_allow_privileged_mouse_lock(is_fullscreen
);
1710 #if defined(OS_MACOSX)
1711 // A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's
1712 // properly embedded (or purposefully ignored) we can release the retain we
1713 // took in CreateNewWidget().
1714 base::mac::NSObjectRelease(widget_host_view
->GetNativeView());
1718 WebContentsImpl
* WebContentsImpl::GetCreatedWindow(int route_id
) {
1719 PendingContents::iterator iter
= pending_contents_
.find(route_id
);
1721 // Certain systems can block the creation of new windows. If we didn't succeed
1722 // in creating one, just return NULL.
1723 if (iter
== pending_contents_
.end()) {
1727 WebContentsImpl
* new_contents
= iter
->second
;
1728 pending_contents_
.erase(route_id
);
1729 RemoveDestructionObserver(new_contents
);
1731 // Don't initialize the guest WebContents immediately.
1732 if (BrowserPluginGuest::IsGuest(new_contents
))
1733 return new_contents
;
1735 if (!new_contents
->GetRenderProcessHost()->HasConnection() ||
1736 !new_contents
->GetRenderViewHost()->GetView())
1739 // TODO(brettw): It seems bogus to reach into here and initialize the host.
1740 static_cast<RenderViewHostImpl
*>(new_contents
->GetRenderViewHost())->Init();
1741 return new_contents
;
1744 RenderWidgetHostView
* WebContentsImpl::GetCreatedWidget(int route_id
) {
1745 PendingWidgetViews::iterator iter
= pending_widget_views_
.find(route_id
);
1746 if (iter
== pending_widget_views_
.end()) {
1751 RenderWidgetHostView
* widget_host_view
= iter
->second
;
1752 pending_widget_views_
.erase(route_id
);
1754 RenderWidgetHost
* widget_host
= widget_host_view
->GetRenderWidgetHost();
1755 if (!widget_host
->GetProcess()->HasConnection()) {
1756 // The view has gone away or the renderer crashed. Nothing to do.
1760 return widget_host_view
;
1763 void WebContentsImpl::RequestMediaAccessPermission(
1764 const MediaStreamRequest
& request
,
1765 const MediaResponseCallback
& callback
) {
1767 delegate_
->RequestMediaAccessPermission(this, request
, callback
);
1769 callback
.Run(MediaStreamDevices(),
1770 MEDIA_DEVICE_INVALID_STATE
,
1771 scoped_ptr
<MediaStreamUI
>());
1775 SessionStorageNamespace
* WebContentsImpl::GetSessionStorageNamespace(
1776 SiteInstance
* instance
) {
1777 return controller_
.GetSessionStorageNamespace(instance
);
1780 SessionStorageNamespaceMap
WebContentsImpl::GetSessionStorageNamespaceMap() {
1781 return controller_
.GetSessionStorageNamespaceMap();
1784 FrameTree
* WebContentsImpl::GetFrameTree() {
1785 return &frame_tree_
;
1788 AccessibilityMode
WebContentsImpl::GetAccessibilityMode() const {
1789 return accessibility_mode_
;
1792 void WebContentsImpl::AccessibilityEventReceived(
1793 const std::vector
<AXEventNotificationDetails
>& details
) {
1795 WebContentsObserver
, observers_
, AccessibilityEventReceived(details
));
1798 void WebContentsImpl::OnShowValidationMessage(
1799 const gfx::Rect
& anchor_in_root_view
,
1800 const base::string16
& main_text
,
1801 const base::string16
& sub_text
) {
1803 delegate_
->ShowValidationMessage(
1804 this, anchor_in_root_view
, main_text
, sub_text
);
1807 void WebContentsImpl::OnHideValidationMessage() {
1809 delegate_
->HideValidationMessage(this);
1812 void WebContentsImpl::OnMoveValidationMessage(
1813 const gfx::Rect
& anchor_in_root_view
) {
1815 delegate_
->MoveValidationMessage(this, anchor_in_root_view
);
1818 void WebContentsImpl::DidSendScreenRects(RenderWidgetHostImpl
* rwh
) {
1819 if (browser_plugin_embedder_
)
1820 browser_plugin_embedder_
->DidSendScreenRects();
1823 BrowserAccessibilityManager
*
1824 WebContentsImpl::GetRootBrowserAccessibilityManager() {
1825 RenderFrameHostImpl
* rfh
= static_cast<RenderFrameHostImpl
*>(GetMainFrame());
1826 return rfh
? rfh
->browser_accessibility_manager() : NULL
;
1829 BrowserAccessibilityManager
*
1830 WebContentsImpl::GetOrCreateRootBrowserAccessibilityManager() {
1831 RenderFrameHostImpl
* rfh
= static_cast<RenderFrameHostImpl
*>(GetMainFrame());
1832 return rfh
? rfh
->GetOrCreateBrowserAccessibilityManager() : NULL
;
1835 void WebContentsImpl::UpdatePreferredSize(const gfx::Size
& pref_size
) {
1836 const gfx::Size old_size
= GetPreferredSize();
1837 preferred_size_
= pref_size
;
1838 OnPreferredSizeChanged(old_size
);
1841 void WebContentsImpl::ResizeDueToAutoResize(const gfx::Size
& new_size
) {
1843 delegate_
->ResizeDueToAutoResize(this, new_size
);
1846 WebContents
* WebContentsImpl::OpenURL(const OpenURLParams
& params
) {
1850 WebContents
* new_contents
= delegate_
->OpenURLFromTab(this, params
);
1851 return new_contents
;
1854 bool WebContentsImpl::Send(IPC::Message
* message
) {
1855 if (!GetRenderViewHost()) {
1860 return GetRenderViewHost()->Send(message
);
1863 bool WebContentsImpl::NavigateToPendingEntry(
1864 NavigationController::ReloadType reload_type
) {
1865 FrameTreeNode
* node
= frame_tree_
.root();
1867 // If we are using --site-per-process, we should navigate in the FrameTreeNode
1868 // specified in the pending entry.
1869 NavigationEntryImpl
* pending_entry
=
1870 NavigationEntryImpl::FromNavigationEntry(controller_
.GetPendingEntry());
1871 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess
) &&
1872 pending_entry
->frame_tree_node_id() != -1) {
1873 node
= frame_tree_
.FindByID(pending_entry
->frame_tree_node_id());
1876 return node
->navigator()->NavigateToPendingEntry(
1877 node
->current_frame_host(), reload_type
);
1880 void WebContentsImpl::RenderFrameForInterstitialPageCreated(
1881 RenderFrameHost
* render_frame_host
) {
1882 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
1883 RenderFrameForInterstitialPageCreated(render_frame_host
));
1886 void WebContentsImpl::AttachInterstitialPage(
1887 InterstitialPageImpl
* interstitial_page
) {
1888 DCHECK(interstitial_page
);
1889 GetRenderManager()->set_interstitial_page(interstitial_page
);
1891 // Cancel any visible dialogs so that they don't interfere with the
1893 if (dialog_manager_
)
1894 dialog_manager_
->CancelActiveAndPendingDialogs(this);
1896 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
1897 DidAttachInterstitialPage());
1900 void WebContentsImpl::DetachInterstitialPage() {
1901 if (ShowingInterstitialPage())
1902 GetRenderManager()->remove_interstitial_page();
1903 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
1904 DidDetachInterstitialPage());
1907 void WebContentsImpl::SetHistoryLengthAndPrune(
1908 const SiteInstance
* site_instance
,
1910 int32 minimum_page_id
) {
1911 // SetHistoryLengthAndPrune doesn't work when there are pending cross-site
1912 // navigations. Callers should ensure that this is the case.
1913 if (GetRenderManager()->pending_render_view_host()) {
1917 RenderViewHostImpl
* rvh
= GetRenderViewHostImpl();
1922 if (site_instance
&& rvh
->GetSiteInstance() != site_instance
) {
1926 Send(new ViewMsg_SetHistoryLengthAndPrune(GetRoutingID(),
1931 void WebContentsImpl::ReloadFocusedFrame(bool ignore_cache
) {
1932 RenderFrameHost
* focused_frame
= GetFocusedFrame();
1936 focused_frame
->Send(new FrameMsg_Reload(
1937 focused_frame
->GetRoutingID(), ignore_cache
));
1940 void WebContentsImpl::Undo() {
1941 RenderFrameHost
* focused_frame
= GetFocusedFrame();
1945 focused_frame
->Send(new InputMsg_Undo(focused_frame
->GetRoutingID()));
1946 RecordAction(base::UserMetricsAction("Undo"));
1949 void WebContentsImpl::Redo() {
1950 RenderFrameHost
* focused_frame
= GetFocusedFrame();
1953 focused_frame
->Send(new InputMsg_Redo(focused_frame
->GetRoutingID()));
1954 RecordAction(base::UserMetricsAction("Redo"));
1957 void WebContentsImpl::Cut() {
1958 RenderFrameHost
* focused_frame
= GetFocusedFrame();
1962 focused_frame
->Send(new InputMsg_Cut(focused_frame
->GetRoutingID()));
1963 RecordAction(base::UserMetricsAction("Cut"));
1966 void WebContentsImpl::Copy() {
1967 RenderFrameHost
* focused_frame
= GetFocusedFrame();
1971 focused_frame
->Send(new InputMsg_Copy(focused_frame
->GetRoutingID()));
1972 RecordAction(base::UserMetricsAction("Copy"));
1975 void WebContentsImpl::CopyToFindPboard() {
1976 #if defined(OS_MACOSX)
1977 RenderFrameHost
* focused_frame
= GetFocusedFrame();
1981 // Windows/Linux don't have the concept of a find pasteboard.
1982 focused_frame
->Send(
1983 new InputMsg_CopyToFindPboard(focused_frame
->GetRoutingID()));
1984 RecordAction(base::UserMetricsAction("CopyToFindPboard"));
1988 void WebContentsImpl::Paste() {
1989 RenderFrameHost
* focused_frame
= GetFocusedFrame();
1993 focused_frame
->Send(new InputMsg_Paste(focused_frame
->GetRoutingID()));
1994 RecordAction(base::UserMetricsAction("Paste"));
1997 void WebContentsImpl::PasteAndMatchStyle() {
1998 RenderFrameHost
* focused_frame
= GetFocusedFrame();
2002 focused_frame
->Send(new InputMsg_PasteAndMatchStyle(
2003 focused_frame
->GetRoutingID()));
2004 RecordAction(base::UserMetricsAction("PasteAndMatchStyle"));
2007 void WebContentsImpl::Delete() {
2008 RenderFrameHost
* focused_frame
= GetFocusedFrame();
2012 focused_frame
->Send(new InputMsg_Delete(focused_frame
->GetRoutingID()));
2013 RecordAction(base::UserMetricsAction("DeleteSelection"));
2016 void WebContentsImpl::SelectAll() {
2017 RenderFrameHost
* focused_frame
= GetFocusedFrame();
2021 focused_frame
->Send(new InputMsg_SelectAll(focused_frame
->GetRoutingID()));
2022 RecordAction(base::UserMetricsAction("SelectAll"));
2025 void WebContentsImpl::Unselect() {
2026 RenderFrameHost
* focused_frame
= GetFocusedFrame();
2030 focused_frame
->Send(new InputMsg_Unselect(focused_frame
->GetRoutingID()));
2031 RecordAction(base::UserMetricsAction("Unselect"));
2034 void WebContentsImpl::Replace(const base::string16
& word
) {
2035 RenderFrameHost
* focused_frame
= GetFocusedFrame();
2039 focused_frame
->Send(new InputMsg_Replace(
2040 focused_frame
->GetRoutingID(), word
));
2043 void WebContentsImpl::ReplaceMisspelling(const base::string16
& word
) {
2044 RenderFrameHost
* focused_frame
= GetFocusedFrame();
2048 focused_frame
->Send(new InputMsg_ReplaceMisspelling(
2049 focused_frame
->GetRoutingID(), word
));
2052 void WebContentsImpl::NotifyContextMenuClosed(
2053 const CustomContextMenuContext
& context
) {
2054 RenderFrameHost
* focused_frame
= GetFocusedFrame();
2058 focused_frame
->Send(new FrameMsg_ContextMenuClosed(
2059 focused_frame
->GetRoutingID(), context
));
2062 void WebContentsImpl::ExecuteCustomContextMenuCommand(
2063 int action
, const CustomContextMenuContext
& context
) {
2064 RenderFrameHost
* focused_frame
= GetFocusedFrame();
2068 focused_frame
->Send(new FrameMsg_CustomContextMenuAction(
2069 focused_frame
->GetRoutingID(), context
, action
));
2072 gfx::NativeView
WebContentsImpl::GetNativeView() {
2073 return view_
->GetNativeView();
2076 gfx::NativeView
WebContentsImpl::GetContentNativeView() {
2077 return view_
->GetContentNativeView();
2080 gfx::NativeWindow
WebContentsImpl::GetTopLevelNativeWindow() {
2081 return view_
->GetTopLevelNativeWindow();
2084 gfx::Rect
WebContentsImpl::GetViewBounds() {
2085 return view_
->GetViewBounds();
2088 gfx::Rect
WebContentsImpl::GetContainerBounds() {
2090 view_
->GetContainerBounds(&rv
);
2094 DropData
* WebContentsImpl::GetDropData() {
2095 return view_
->GetDropData();
2098 void WebContentsImpl::Focus() {
2099 RenderWidgetHostView
* const fullscreen_view
=
2100 GetFullscreenRenderWidgetHostView();
2101 if (fullscreen_view
)
2102 fullscreen_view
->Focus();
2107 void WebContentsImpl::SetInitialFocus() {
2108 RenderWidgetHostView
* const fullscreen_view
=
2109 GetFullscreenRenderWidgetHostView();
2110 if (fullscreen_view
)
2111 fullscreen_view
->Focus();
2113 view_
->SetInitialFocus();
2116 void WebContentsImpl::StoreFocus() {
2117 if (!GetFullscreenRenderWidgetHostView())
2118 view_
->StoreFocus();
2121 void WebContentsImpl::RestoreFocus() {
2122 RenderWidgetHostView
* const fullscreen_view
=
2123 GetFullscreenRenderWidgetHostView();
2124 if (fullscreen_view
)
2125 fullscreen_view
->Focus();
2127 view_
->RestoreFocus();
2130 void WebContentsImpl::FocusThroughTabTraversal(bool reverse
) {
2131 if (ShowingInterstitialPage()) {
2132 GetRenderManager()->interstitial_page()->FocusThroughTabTraversal(reverse
);
2135 RenderWidgetHostView
* const fullscreen_view
=
2136 GetFullscreenRenderWidgetHostView();
2137 if (fullscreen_view
) {
2138 fullscreen_view
->Focus();
2141 GetRenderViewHostImpl()->SetInitialFocus(reverse
);
2144 bool WebContentsImpl::ShowingInterstitialPage() const {
2145 return GetRenderManager()->interstitial_page() != NULL
;
2148 InterstitialPage
* WebContentsImpl::GetInterstitialPage() const {
2149 return GetRenderManager()->interstitial_page();
2152 bool WebContentsImpl::IsSavable() {
2153 // WebKit creates Document object when MIME type is application/xhtml+xml,
2154 // so we also support this MIME type.
2155 return contents_mime_type_
== "text/html" ||
2156 contents_mime_type_
== "text/xml" ||
2157 contents_mime_type_
== "application/xhtml+xml" ||
2158 contents_mime_type_
== "text/plain" ||
2159 contents_mime_type_
== "text/css" ||
2160 net::IsSupportedJavascriptMimeType(contents_mime_type_
.c_str());
2163 void WebContentsImpl::OnSavePage() {
2164 // If we can not save the page, try to download it.
2166 RecordDownloadSource(INITIATED_BY_SAVE_PACKAGE_ON_NON_HTML
);
2167 SaveFrame(GetURL(), Referrer());
2173 // Create the save package and possibly prompt the user for the name to save
2174 // the page as. The user prompt is an asynchronous operation that runs on
2176 save_package_
= new SavePackage(this);
2177 save_package_
->GetSaveInfo();
2180 // Used in automated testing to bypass prompting the user for file names.
2181 // Instead, the names and paths are hard coded rather than running them through
2182 // file name sanitation and extension / mime checking.
2183 bool WebContentsImpl::SavePage(const base::FilePath
& main_file
,
2184 const base::FilePath
& dir_path
,
2185 SavePageType save_type
) {
2186 // Stop the page from navigating.
2189 save_package_
= new SavePackage(this, save_type
, main_file
, dir_path
);
2190 return save_package_
->Init(SavePackageDownloadCreatedCallback());
2193 void WebContentsImpl::SaveFrame(const GURL
& url
,
2194 const Referrer
& referrer
) {
2195 if (!GetURL().is_valid())
2197 bool is_main_frame
= (url
== GetURL());
2199 DownloadManager
* dlm
=
2200 BrowserContext::GetDownloadManager(GetBrowserContext());
2204 if (is_main_frame
) {
2205 const NavigationEntry
* entry
= controller_
.GetLastCommittedEntry();
2207 post_id
= entry
->GetPostID();
2209 scoped_ptr
<DownloadUrlParameters
> params(
2210 DownloadUrlParameters::FromWebContents(this, url
));
2211 params
->set_referrer(referrer
);
2212 params
->set_post_id(post_id
);
2213 params
->set_prefer_cache(true);
2215 params
->set_method("POST");
2216 params
->set_prompt(true);
2217 dlm
->DownloadUrl(params
.Pass());
2220 void WebContentsImpl::GenerateMHTML(
2221 const base::FilePath
& file
,
2222 const base::Callback
<void(int64
)>& callback
) {
2223 MHTMLGenerationManager::GetInstance()->SaveMHTML(this, file
, callback
);
2226 const std::string
& WebContentsImpl::GetContentsMimeType() const {
2227 return contents_mime_type_
;
2230 bool WebContentsImpl::WillNotifyDisconnection() const {
2231 return notify_disconnection_
;
2234 void WebContentsImpl::SetOverrideEncoding(const std::string
& encoding
) {
2235 SetEncoding(encoding
);
2236 Send(new ViewMsg_SetPageEncoding(GetRoutingID(), encoding
));
2239 void WebContentsImpl::ResetOverrideEncoding() {
2240 canonical_encoding_
.clear();
2241 Send(new ViewMsg_ResetPageEncodingToDefault(GetRoutingID()));
2244 RendererPreferences
* WebContentsImpl::GetMutableRendererPrefs() {
2245 return &renderer_preferences_
;
2248 void WebContentsImpl::Close() {
2249 Close(GetRenderViewHost());
2252 void WebContentsImpl::DragSourceEndedAt(int client_x
, int client_y
,
2253 int screen_x
, int screen_y
, blink::WebDragOperation operation
) {
2254 if (browser_plugin_embedder_
.get())
2255 browser_plugin_embedder_
->DragSourceEndedAt(client_x
, client_y
,
2256 screen_x
, screen_y
, operation
);
2257 if (GetRenderViewHost())
2258 GetRenderViewHostImpl()->DragSourceEndedAt(client_x
, client_y
,
2259 screen_x
, screen_y
, operation
);
2262 void WebContentsImpl::DidGetResourceResponseStart(
2263 const ResourceRequestDetails
& details
) {
2264 controller_
.ssl_manager()->DidStartResourceResponse(details
);
2266 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2267 DidGetResourceResponseStart(details
));
2269 // TODO(avi): Remove. http://crbug.com/170921
2270 NotificationService::current()->Notify(
2271 NOTIFICATION_RESOURCE_RESPONSE_STARTED
,
2272 Source
<WebContents
>(this),
2273 Details
<const ResourceRequestDetails
>(&details
));
2276 void WebContentsImpl::DidGetRedirectForResourceRequest(
2277 RenderViewHost
* render_view_host
,
2278 const ResourceRedirectDetails
& details
) {
2279 controller_
.ssl_manager()->DidReceiveResourceRedirect(details
);
2282 WebContentsObserver
,
2284 DidGetRedirectForResourceRequest(render_view_host
, details
));
2286 // TODO(avi): Remove. http://crbug.com/170921
2287 NotificationService::current()->Notify(
2288 NOTIFICATION_RESOURCE_RECEIVED_REDIRECT
,
2289 Source
<WebContents
>(this),
2290 Details
<const ResourceRedirectDetails
>(&details
));
2293 void WebContentsImpl::SystemDragEnded() {
2294 if (GetRenderViewHost())
2295 GetRenderViewHostImpl()->DragSourceSystemDragEnded();
2297 delegate_
->DragEnded();
2298 if (browser_plugin_embedder_
.get())
2299 browser_plugin_embedder_
->SystemDragEnded();
2302 void WebContentsImpl::UserGestureDone() {
2306 void WebContentsImpl::SetClosedByUserGesture(bool value
) {
2307 closed_by_user_gesture_
= value
;
2310 bool WebContentsImpl::GetClosedByUserGesture() const {
2311 return closed_by_user_gesture_
;
2314 void WebContentsImpl::ViewSource() {
2318 NavigationEntry
* entry
= GetController().GetLastCommittedEntry();
2322 delegate_
->ViewSourceForTab(this, entry
->GetURL());
2325 void WebContentsImpl::ViewFrameSource(const GURL
& url
,
2326 const PageState
& page_state
) {
2330 delegate_
->ViewSourceForFrame(this, url
, page_state
);
2333 int WebContentsImpl::GetMinimumZoomPercent() const {
2334 return minimum_zoom_percent_
;
2337 int WebContentsImpl::GetMaximumZoomPercent() const {
2338 return maximum_zoom_percent_
;
2341 gfx::Size
WebContentsImpl::GetPreferredSize() const {
2342 return capturer_count_
== 0 ? preferred_size_
: preferred_size_for_capture_
;
2345 bool WebContentsImpl::GotResponseToLockMouseRequest(bool allowed
) {
2346 if (GetBrowserPluginGuest())
2347 return GetBrowserPluginGuest()->LockMouse(allowed
);
2349 return GetRenderViewHost() ?
2350 GetRenderViewHostImpl()->GotResponseToLockMouseRequest(allowed
) : false;
2353 bool WebContentsImpl::HasOpener() const {
2354 return opener_
!= NULL
;
2357 void WebContentsImpl::DidChooseColorInColorChooser(SkColor color
) {
2358 if (!color_chooser_info_
.get())
2360 RenderFrameHost
* rfh
= RenderFrameHost::FromID(
2361 color_chooser_info_
->render_process_id
,
2362 color_chooser_info_
->render_frame_id
);
2366 rfh
->Send(new FrameMsg_DidChooseColorResponse(
2367 rfh
->GetRoutingID(), color_chooser_info_
->identifier
, color
));
2370 void WebContentsImpl::DidEndColorChooser() {
2371 if (!color_chooser_info_
.get())
2373 RenderFrameHost
* rfh
= RenderFrameHost::FromID(
2374 color_chooser_info_
->render_process_id
,
2375 color_chooser_info_
->render_frame_id
);
2379 rfh
->Send(new FrameMsg_DidEndColorChooser(
2380 rfh
->GetRoutingID(), color_chooser_info_
->identifier
));
2381 color_chooser_info_
.reset();
2384 int WebContentsImpl::DownloadImage(const GURL
& url
,
2386 uint32_t max_bitmap_size
,
2387 const ImageDownloadCallback
& callback
) {
2388 int id
= StartDownload(GetMainFrame(), url
, is_favicon
, max_bitmap_size
);
2389 image_download_map_
[id
] = callback
;
2393 bool WebContentsImpl::IsSubframe() const {
2394 return is_subframe_
;
2397 void WebContentsImpl::Find(int request_id
,
2398 const base::string16
& search_text
,
2399 const blink::WebFindOptions
& options
) {
2400 Send(new ViewMsg_Find(GetRoutingID(), request_id
, search_text
, options
));
2403 void WebContentsImpl::StopFinding(StopFindAction action
) {
2404 Send(new ViewMsg_StopFinding(GetRoutingID(), action
));
2407 void WebContentsImpl::InsertCSS(const std::string
& css
) {
2408 GetMainFrame()->Send(new FrameMsg_CSSInsertRequest(
2409 GetMainFrame()->GetRoutingID(), css
));
2412 bool WebContentsImpl::WasRecentlyAudible() {
2413 return audio_stream_monitor_
.WasRecentlyAudible();
2416 bool WebContentsImpl::FocusLocationBarByDefault() {
2417 NavigationEntry
* entry
= controller_
.GetVisibleEntry();
2418 if (entry
&& entry
->GetURL() == GURL(url::kAboutBlankURL
))
2420 return delegate_
&& delegate_
->ShouldFocusLocationBarByDefault(this);
2423 void WebContentsImpl::SetFocusToLocationBar(bool select_all
) {
2425 delegate_
->SetFocusToLocationBar(select_all
);
2428 void WebContentsImpl::DidStartProvisionalLoad(
2429 RenderFrameHostImpl
* render_frame_host
,
2430 const GURL
& validated_url
,
2432 bool is_iframe_srcdoc
) {
2433 // Notify observers about the start of the provisional load.
2435 WebContentsObserver
,
2437 DidStartProvisionalLoadForFrame(
2438 render_frame_host
, validated_url
, is_error_page
, is_iframe_srcdoc
));
2440 if (!render_frame_host
->GetParent()) {
2442 WebContentsObserver
,
2444 ProvisionalChangeToMainFrameUrl(validated_url
,
2445 render_frame_host
));
2449 void WebContentsImpl::DidStartNavigationTransition(
2450 RenderFrameHostImpl
* render_frame_host
) {
2451 #if defined(OS_ANDROID)
2452 int render_frame_id
= render_frame_host
->GetRoutingID();
2453 GetWebContentsAndroid()->DidStartNavigationTransitionForFrame(
2458 void WebContentsImpl::DidFailProvisionalLoadWithError(
2459 RenderFrameHostImpl
* render_frame_host
,
2460 const FrameHostMsg_DidFailProvisionalLoadWithError_Params
& params
) {
2461 GURL
validated_url(params
.url
);
2462 FOR_EACH_OBSERVER(WebContentsObserver
,
2464 DidFailProvisionalLoad(render_frame_host
,
2467 params
.error_description
));
2470 void WebContentsImpl::DidFailLoadWithError(
2471 RenderFrameHostImpl
* render_frame_host
,
2474 const base::string16
& error_description
) {
2476 WebContentsObserver
,
2478 DidFailLoad(render_frame_host
, url
, error_code
, error_description
));
2481 void WebContentsImpl::NotifyChangedNavigationState(
2482 InvalidateTypes changed_flags
) {
2483 NotifyNavigationStateChanged(changed_flags
);
2486 void WebContentsImpl::AboutToNavigateRenderFrame(
2487 RenderFrameHostImpl
* render_frame_host
) {
2488 // Notify observers that we will navigate in this RenderView.
2489 RenderViewHost
* render_view_host
= render_frame_host
->render_view_host();
2491 WebContentsObserver
,
2493 AboutToNavigateRenderView(render_view_host
));
2496 void WebContentsImpl::DidStartNavigationToPendingEntry(
2497 RenderFrameHostImpl
* render_frame_host
,
2499 NavigationController::ReloadType reload_type
) {
2500 // Notify observers about navigation.
2502 WebContentsObserver
,
2504 DidStartNavigationToPendingEntry(url
, reload_type
));
2507 void WebContentsImpl::RequestOpenURL(RenderFrameHostImpl
* render_frame_host
,
2508 const OpenURLParams
& params
) {
2509 int source_render_frame_id
= render_frame_host
->GetRoutingID();
2510 WebContents
* new_contents
= OpenURL(params
);
2513 // Notify observers.
2514 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2515 DidOpenRequestedURL(new_contents
,
2520 source_render_frame_id
));
2524 bool WebContentsImpl::ShouldPreserveAbortedURLs() {
2527 return delegate_
->ShouldPreserveAbortedURLs(this);
2530 void WebContentsImpl::DidRedirectProvisionalLoad(
2531 RenderFrameHostImpl
* render_frame_host
,
2532 const GURL
& validated_target_url
) {
2533 // Notify observers about the provisional change in the main frame URL.
2535 WebContentsObserver
,
2537 ProvisionalChangeToMainFrameUrl(validated_target_url
,
2538 render_frame_host
));
2541 void WebContentsImpl::DidCommitProvisionalLoad(
2542 RenderFrameHostImpl
* render_frame_host
,
2544 PageTransition transition_type
) {
2545 // Notify observers about the commit of the provisional load.
2546 FOR_EACH_OBSERVER(WebContentsObserver
,
2548 DidCommitProvisionalLoadForFrame(
2549 render_frame_host
, url
, transition_type
));
2552 void WebContentsImpl::DidNavigateMainFramePreCommit(
2553 bool navigation_is_within_page
) {
2554 // Ensure fullscreen mode is exited before committing the navigation to a
2555 // different page. The next page will not start out assuming it is in
2557 if (navigation_is_within_page
) {
2558 // No page change? Then, the renderer and browser can remain in fullscreen.
2561 if (IsFullscreenForCurrentTab())
2562 GetRenderViewHost()->ExitFullscreen();
2563 DCHECK(!IsFullscreenForCurrentTab());
2566 void WebContentsImpl::DidNavigateMainFramePostCommit(
2567 const LoadCommittedDetails
& details
,
2568 const FrameHostMsg_DidCommitProvisionalLoad_Params
& params
) {
2569 if (details
.is_navigation_to_different_page()) {
2570 // Clear the status bubble. This is a workaround for a bug where WebKit
2571 // doesn't let us know that the cursor left an element during a
2572 // transition (this is also why the mouse cursor remains as a hand after
2573 // clicking on a link); see bugs 1184641 and 980803. We don't want to
2574 // clear the bubble when a user navigates to a named anchor in the same
2576 UpdateTargetURL(details
.entry
->GetPageID(), GURL());
2579 if (!details
.is_in_page
) {
2580 // Once the main frame is navigated, we're no longer considered to have
2581 // displayed insecure content.
2582 displayed_insecure_content_
= false;
2583 SSLManager::NotifySSLInternalStateChanged(
2584 GetController().GetBrowserContext());
2587 // Notify observers about navigation.
2588 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2589 DidNavigateMainFrame(details
, params
));
2592 delegate_
->DidNavigateMainFramePostCommit(this);
2593 view_
->SetOverscrollControllerEnabled(CanOverscrollContent());
2596 void WebContentsImpl::DidNavigateAnyFramePostCommit(
2597 RenderFrameHostImpl
* render_frame_host
,
2598 const LoadCommittedDetails
& details
,
2599 const FrameHostMsg_DidCommitProvisionalLoad_Params
& params
) {
2600 // Now that something has committed, we don't need to track whether the
2601 // initial page has been accessed.
2602 has_accessed_initial_document_
= false;
2604 // If we navigate off the page, close all JavaScript dialogs.
2605 if (dialog_manager_
&& !details
.is_in_page
)
2606 dialog_manager_
->CancelActiveAndPendingDialogs(this);
2608 // Notify observers about navigation.
2609 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2610 DidNavigateAnyFrame(details
, params
));
2613 void WebContentsImpl::SetMainFrameMimeType(const std::string
& mime_type
) {
2614 contents_mime_type_
= mime_type
;
2617 bool WebContentsImpl::CanOverscrollContent() const {
2618 // Disable overscroll when touch emulation is on. See crbug.com/369938.
2619 if (force_disable_overscroll_content_
)
2623 return delegate_
->CanOverscrollContent();
2628 void WebContentsImpl::OnThemeColorChanged(SkColor theme_color
) {
2629 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2630 DidChangeThemeColor(theme_color
));
2633 void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
2635 const std::string
& security_info
,
2636 const std::string
& http_method
,
2637 const std::string
& mime_type
,
2638 ResourceType resource_type
) {
2639 base::StatsCounter
cache("WebKit.CacheHit");
2642 // Send out a notification that we loaded a resource from our memory cache.
2644 net::CertStatus cert_status
= 0;
2645 int security_bits
= -1;
2646 int connection_status
= 0;
2647 SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids
;
2648 DeserializeSecurityInfo(security_info
, &cert_id
, &cert_status
,
2649 &security_bits
, &connection_status
,
2650 &signed_certificate_timestamp_ids
);
2651 // TODO(alcutter,eranm): Pass signed_certificate_timestamp_ids into details
2652 LoadFromMemoryCacheDetails
details(
2653 url
, GetRenderProcessHost()->GetID(), cert_id
, cert_status
, http_method
,
2654 mime_type
, resource_type
);
2656 controller_
.ssl_manager()->DidLoadFromMemoryCache(details
);
2658 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2659 DidLoadResourceFromMemoryCache(details
));
2661 if (url
.is_valid() && url
.SchemeIsHTTPOrHTTPS()) {
2662 scoped_refptr
<net::URLRequestContextGetter
> request_context(
2663 resource_type
== RESOURCE_TYPE_MEDIA
?
2664 GetBrowserContext()->GetMediaRequestContextForRenderProcess(
2665 GetRenderProcessHost()->GetID()) :
2666 GetBrowserContext()->GetRequestContextForRenderProcess(
2667 GetRenderProcessHost()->GetID()));
2668 BrowserThread::PostTask(
2671 base::Bind(&NotifyCacheOnIO
, request_context
, url
, http_method
));
2675 void WebContentsImpl::OnDidDisplayInsecureContent() {
2676 RecordAction(base::UserMetricsAction("SSL.DisplayedInsecureContent"));
2677 displayed_insecure_content_
= true;
2678 SSLManager::NotifySSLInternalStateChanged(
2679 GetController().GetBrowserContext());
2682 void WebContentsImpl::OnDidRunInsecureContent(
2683 const std::string
& security_origin
, const GURL
& target_url
) {
2684 LOG(WARNING
) << security_origin
<< " ran insecure content from "
2685 << target_url
.possibly_invalid_spec();
2686 RecordAction(base::UserMetricsAction("SSL.RanInsecureContent"));
2687 if (EndsWith(security_origin
, kDotGoogleDotCom
, false))
2688 RecordAction(base::UserMetricsAction("SSL.RanInsecureContentGoogle"));
2689 controller_
.ssl_manager()->DidRunInsecureContent(security_origin
);
2690 displayed_insecure_content_
= true;
2691 SSLManager::NotifySSLInternalStateChanged(
2692 GetController().GetBrowserContext());
2695 void WebContentsImpl::OnDocumentLoadedInFrame() {
2696 CHECK(render_frame_message_source_
);
2697 CHECK(!render_view_message_source_
);
2698 RenderFrameHostImpl
* rfh
=
2699 static_cast<RenderFrameHostImpl
*>(render_frame_message_source_
);
2701 WebContentsObserver
, observers_
, DocumentLoadedInFrame(rfh
));
2704 void WebContentsImpl::OnDidFinishLoad(
2706 if (!render_frame_message_source_
) {
2707 RecordAction(base::UserMetricsAction("BadMessageTerminate_RVD2"));
2708 GetRenderProcessHost()->ReceivedBadMessage();
2712 GURL
validated_url(url
);
2713 RenderProcessHost
* render_process_host
=
2714 render_frame_message_source_
->GetProcess();
2715 render_process_host
->FilterURL(false, &validated_url
);
2717 RenderFrameHostImpl
* rfh
=
2718 static_cast<RenderFrameHostImpl
*>(render_frame_message_source_
);
2720 WebContentsObserver
, observers_
, DidFinishLoad(rfh
, validated_url
));
2723 void WebContentsImpl::OnDidStartLoading(bool to_different_document
) {
2724 RenderFrameHostImpl
* rfh
=
2725 static_cast<RenderFrameHostImpl
*>(render_frame_message_source_
);
2726 int64 render_frame_id
= rfh
->frame_tree_node()->frame_tree_node_id();
2728 // It is possible to get multiple calls to OnDidStartLoading that don't have
2729 // corresponding calls to OnDidStopLoading:
2730 // - With "swappedout://" URLs, this happens when a RenderView gets swapped
2731 // out for a cross-process navigation, and it turns into a placeholder for
2732 // one being rendered in a different process.
2733 // - Also, there might be more than one RenderFrameHost sharing the same
2734 // FrameTreeNode (and thus sharing its ID) each sending a start.
2735 // - But in the future, once clamy@ moves navigation network requests to the
2736 // browser process, there's a good chance that callbacks about starting and
2737 // stopping will all be handled by the browser. When that happens, there
2738 // should no longer be a start/stop call imbalance. TODO(avi): When this
2739 // future arrives, update this code to not allow this case.
2740 DCHECK_GE(loading_frames_in_progress_
, 0);
2741 if (loading_progresses_
.find(render_frame_id
) == loading_progresses_
.end()) {
2742 if (loading_frames_in_progress_
== 0)
2743 DidStartLoading(rfh
, to_different_document
);
2744 ++loading_frames_in_progress_
;
2747 loading_progresses_
[render_frame_id
] = kMinimumLoadingProgress
;
2748 SendLoadProgressChanged();
2751 void WebContentsImpl::OnDidStopLoading() {
2752 RenderFrameHostImpl
* rfh
=
2753 static_cast<RenderFrameHostImpl
*>(render_frame_message_source_
);
2754 int64 render_frame_id
= rfh
->frame_tree_node()->frame_tree_node_id();
2756 if (loading_progresses_
.find(render_frame_id
) != loading_progresses_
.end()) {
2757 // Load stopped while we were still tracking load. Make sure we update
2758 // progress based on this frame's completion.
2759 loading_progresses_
[render_frame_id
] = 1.0;
2760 SendLoadProgressChanged();
2761 // Then we clean-up our states.
2762 if (loading_total_progress_
== 1.0)
2763 ResetLoadProgressState();
2766 // TODO(japhet): This should be a DCHECK, but the pdf plugin sometimes
2767 // calls DidStopLoading() without a matching DidStartLoading().
2768 if (loading_frames_in_progress_
== 0)
2770 --loading_frames_in_progress_
;
2771 if (loading_frames_in_progress_
== 0)
2772 DidStopLoading(rfh
);
2775 void WebContentsImpl::OnDidChangeLoadProgress(double load_progress
) {
2776 RenderFrameHostImpl
* rfh
=
2777 static_cast<RenderFrameHostImpl
*>(render_frame_message_source_
);
2778 int64 render_frame_id
= rfh
->frame_tree_node()->frame_tree_node_id();
2780 loading_progresses_
[render_frame_id
] = load_progress
;
2782 // We notify progress change immediately for the first and last updates.
2783 // Also, since the message loop may be pretty busy when a page is loaded, it
2784 // might not execute a posted task in a timely manner so we make sure to
2785 // immediately send progress report if enough time has passed.
2786 base::TimeDelta min_delay
=
2787 base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenLoadingUpdatesMS
);
2788 if (load_progress
== 1.0 || loading_last_progress_update_
.is_null() ||
2789 base::TimeTicks::Now() - loading_last_progress_update_
> min_delay
) {
2790 // If there is a pending task to send progress, it is now obsolete.
2791 loading_weak_factory_
.InvalidateWeakPtrs();
2792 SendLoadProgressChanged();
2793 if (loading_total_progress_
== 1.0)
2794 ResetLoadProgressState();
2798 if (loading_weak_factory_
.HasWeakPtrs())
2801 base::MessageLoop::current()->PostDelayedTask(
2803 base::Bind(&WebContentsImpl::SendLoadProgressChanged
,
2804 loading_weak_factory_
.GetWeakPtr()),
2808 void WebContentsImpl::OnGoToEntryAtOffset(int offset
) {
2809 if (!delegate_
|| delegate_
->OnGoToEntryOffset(offset
))
2810 controller_
.GoToOffset(offset
);
2813 void WebContentsImpl::OnUpdateZoomLimits(int minimum_percent
,
2814 int maximum_percent
) {
2815 minimum_zoom_percent_
= minimum_percent
;
2816 maximum_zoom_percent_
= maximum_percent
;
2819 void WebContentsImpl::OnEnumerateDirectory(int request_id
,
2820 const base::FilePath
& path
) {
2824 ChildProcessSecurityPolicyImpl
* policy
=
2825 ChildProcessSecurityPolicyImpl::GetInstance();
2826 if (policy
->CanReadFile(GetRenderProcessHost()->GetID(), path
))
2827 delegate_
->EnumerateDirectory(this, request_id
, path
);
2830 void WebContentsImpl::OnRegisterProtocolHandler(const std::string
& protocol
,
2832 const base::string16
& title
,
2833 bool user_gesture
) {
2837 ChildProcessSecurityPolicyImpl
* policy
=
2838 ChildProcessSecurityPolicyImpl::GetInstance();
2839 if (policy
->IsPseudoScheme(protocol
))
2842 delegate_
->RegisterProtocolHandler(this, protocol
, url
, user_gesture
);
2845 void WebContentsImpl::OnUnregisterProtocolHandler(const std::string
& protocol
,
2847 bool user_gesture
) {
2851 ChildProcessSecurityPolicyImpl
* policy
=
2852 ChildProcessSecurityPolicyImpl::GetInstance();
2853 if (policy
->IsPseudoScheme(protocol
))
2856 delegate_
->UnregisterProtocolHandler(this, protocol
, url
, user_gesture
);
2859 void WebContentsImpl::OnFindReply(int request_id
,
2860 int number_of_matches
,
2861 const gfx::Rect
& selection_rect
,
2862 int active_match_ordinal
,
2863 bool final_update
) {
2865 delegate_
->FindReply(this, request_id
, number_of_matches
, selection_rect
,
2866 active_match_ordinal
, final_update
);
2870 #if defined(OS_ANDROID)
2871 void WebContentsImpl::OnFindMatchRectsReply(
2873 const std::vector
<gfx::RectF
>& rects
,
2874 const gfx::RectF
& active_rect
) {
2876 delegate_
->FindMatchRectsReply(this, version
, rects
, active_rect
);
2879 void WebContentsImpl::OnOpenDateTimeDialog(
2880 const ViewHostMsg_DateTimeDialogValue_Params
& value
) {
2881 date_time_chooser_
->ShowDialog(ContentViewCore::FromWebContents(this),
2882 GetRenderViewHost(),
2893 void WebContentsImpl::OnPepperPluginHung(int plugin_child_id
,
2894 const base::FilePath
& path
,
2896 UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1);
2898 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2899 PluginHungStatusChanged(plugin_child_id
, path
, is_hung
));
2902 void WebContentsImpl::OnPluginCrashed(const base::FilePath
& plugin_path
,
2903 base::ProcessId plugin_pid
) {
2904 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2905 PluginCrashed(plugin_path
, plugin_pid
));
2908 void WebContentsImpl::OnDomOperationResponse(const std::string
& json_string
,
2909 int automation_id
) {
2910 DomOperationNotificationDetails
details(json_string
, automation_id
);
2911 NotificationService::current()->Notify(
2912 NOTIFICATION_DOM_OPERATION_RESPONSE
,
2913 Source
<WebContents
>(this),
2914 Details
<DomOperationNotificationDetails
>(&details
));
2917 void WebContentsImpl::OnAppCacheAccessed(const GURL
& manifest_url
,
2918 bool blocked_by_policy
) {
2919 // Notify observers about navigation.
2920 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2921 AppCacheAccessed(manifest_url
, blocked_by_policy
));
2924 void WebContentsImpl::OnOpenColorChooser(
2925 int color_chooser_id
,
2927 const std::vector
<ColorSuggestion
>& suggestions
) {
2928 ColorChooser
* new_color_chooser
= delegate_
?
2929 delegate_
->OpenColorChooser(this, color
, suggestions
) :
2931 if (!new_color_chooser
)
2933 if (color_chooser_info_
.get())
2934 color_chooser_info_
->chooser
->End();
2936 color_chooser_info_
.reset(new ColorChooserInfo(
2937 render_frame_message_source_
->GetProcess()->GetID(),
2938 render_frame_message_source_
->GetRoutingID(),
2943 void WebContentsImpl::OnEndColorChooser(int color_chooser_id
) {
2944 if (color_chooser_info_
&&
2945 color_chooser_id
== color_chooser_info_
->identifier
)
2946 color_chooser_info_
->chooser
->End();
2949 void WebContentsImpl::OnSetSelectedColorInColorChooser(int color_chooser_id
,
2951 if (color_chooser_info_
&&
2952 color_chooser_id
== color_chooser_info_
->identifier
)
2953 color_chooser_info_
->chooser
->SetSelectedColor(color
);
2956 // This exists for render views that don't have a WebUI, but do have WebUI
2957 // bindings enabled.
2958 void WebContentsImpl::OnWebUISend(const GURL
& source_url
,
2959 const std::string
& name
,
2960 const base::ListValue
& args
) {
2962 delegate_
->WebUISend(this, source_url
, name
, args
);
2965 #if defined(ENABLE_PLUGINS)
2966 void WebContentsImpl::OnRequestPpapiBrokerPermission(
2969 const base::FilePath
& plugin_path
) {
2971 OnPpapiBrokerPermissionResult(routing_id
, false);
2975 if (!delegate_
->RequestPpapiBrokerPermission(
2976 this, url
, plugin_path
,
2977 base::Bind(&WebContentsImpl::OnPpapiBrokerPermissionResult
,
2978 base::Unretained(this), routing_id
))) {
2980 OnPpapiBrokerPermissionResult(routing_id
, false);
2984 void WebContentsImpl::OnPpapiBrokerPermissionResult(int routing_id
,
2986 Send(new ViewMsg_PpapiBrokerPermissionResult(routing_id
, result
));
2989 void WebContentsImpl::OnBrowserPluginMessage(const IPC::Message
& message
) {
2990 // This creates a BrowserPluginEmbedder, which handles all the BrowserPlugin
2991 // specific messages for this WebContents. This means that any message from
2992 // a BrowserPlugin prior to this will be ignored.
2993 // For more info, see comment above classes BrowserPluginEmbedder and
2994 // BrowserPluginGuest.
2995 CHECK(!browser_plugin_embedder_
.get());
2996 browser_plugin_embedder_
.reset(BrowserPluginEmbedder::Create(this));
2997 browser_plugin_embedder_
->OnMessageReceived(message
);
3001 void WebContentsImpl::OnDidDownloadImage(
3003 int http_status_code
,
3004 const GURL
& image_url
,
3005 const std::vector
<SkBitmap
>& bitmaps
,
3006 const std::vector
<gfx::Size
>& original_bitmap_sizes
) {
3007 if (bitmaps
.size() != original_bitmap_sizes
.size())
3010 ImageDownloadMap::iterator iter
= image_download_map_
.find(id
);
3011 if (iter
== image_download_map_
.end()) {
3012 // Currently WebContents notifies us of ANY downloads so that it is
3013 // possible to get here.
3016 if (!iter
->second
.is_null()) {
3018 id
, http_status_code
, image_url
, bitmaps
, original_bitmap_sizes
);
3020 image_download_map_
.erase(id
);
3023 void WebContentsImpl::OnUpdateFaviconURL(
3024 const std::vector
<FaviconURL
>& candidates
) {
3025 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3026 DidUpdateFaviconURL(candidates
));
3029 void WebContentsImpl::CreateAudioPowerSaveBlocker() {
3030 // ChromeOS has its own way of handling power save blocks for media.
3031 #if !defined(OS_CHROMEOS)
3032 DCHECK(!audio_power_save_blocker_
);
3033 audio_power_save_blocker_
= PowerSaveBlocker::Create(
3034 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension
, "Playing Audio");
3038 void WebContentsImpl::CreateVideoPowerSaveBlocker() {
3039 // ChromeOS has its own way of handling power save blocks for media.
3040 #if !defined(OS_CHROMEOS)
3041 DCHECK(!video_power_save_blocker_
);
3042 DCHECK(!active_video_players_
.empty());
3043 video_power_save_blocker_
= PowerSaveBlocker::Create(
3044 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep
, "Playing Video");
3045 #if defined(OS_ANDROID)
3046 static_cast<PowerSaveBlockerImpl
*>(video_power_save_blocker_
.get())
3047 ->InitDisplaySleepBlocker(GetView()->GetNativeView());
3052 void WebContentsImpl::MaybeReleasePowerSaveBlockers() {
3053 // If there are no more audio players and we don't have audio stream
3054 // monitoring, release the audio power save blocker here instead of during
3055 // NotifyNavigationStateChanged().
3056 if (active_audio_players_
.empty() &&
3057 !AudioStreamMonitor::monitoring_available()) {
3058 audio_power_save_blocker_
.reset();
3061 // If there are no more video players, clear the video power save blocker.
3062 if (active_video_players_
.empty())
3063 video_power_save_blocker_
.reset();
3066 void WebContentsImpl::OnMediaPlayingNotification(int64 player_cookie
,
3070 AddMediaPlayerEntry(player_cookie
, &active_audio_players_
);
3072 // If we don't have audio stream monitoring, allocate the audio power save
3073 // blocker here instead of during NotifyNavigationStateChanged().
3074 if (!audio_power_save_blocker_
&&
3075 !AudioStreamMonitor::monitoring_available()) {
3076 CreateAudioPowerSaveBlocker();
3081 AddMediaPlayerEntry(player_cookie
, &active_video_players_
);
3083 // If we're not hidden and have just created a player, create a blocker.
3084 if (!video_power_save_blocker_
&& !IsHidden())
3085 CreateVideoPowerSaveBlocker();
3089 void WebContentsImpl::OnMediaPausedNotification(int64 player_cookie
) {
3090 RemoveMediaPlayerEntry(player_cookie
, &active_audio_players_
);
3091 RemoveMediaPlayerEntry(player_cookie
, &active_video_players_
);
3092 MaybeReleasePowerSaveBlockers();
3095 void WebContentsImpl::OnFirstVisuallyNonEmptyPaint() {
3096 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3097 DidFirstVisuallyNonEmptyPaint());
3100 void WebContentsImpl::DidChangeVisibleSSLState() {
3102 delegate_
->VisibleSSLStateChanged(this);
3105 void WebContentsImpl::NotifyBeforeFormRepostWarningShow() {
3106 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3107 BeforeFormRepostWarningShow());
3110 void WebContentsImpl::ActivateAndShowRepostFormWarningDialog() {
3113 delegate_
->ShowRepostFormWarningDialog(this);
3116 bool WebContentsImpl::HasAccessedInitialDocument() {
3117 return has_accessed_initial_document_
;
3120 // Notifies the RenderWidgetHost instance about the fact that the page is
3121 // loading, or done loading.
3122 void WebContentsImpl::SetIsLoading(RenderViewHost
* render_view_host
,
3124 bool to_different_document
,
3125 LoadNotificationDetails
* details
) {
3126 if (is_loading
== is_loading_
)
3130 load_state_
= net::LoadStateWithParam(net::LOAD_STATE_IDLE
,
3132 load_state_host_
.clear();
3134 upload_position_
= 0;
3137 GetRenderManager()->SetIsLoading(is_loading
);
3139 is_loading_
= is_loading
;
3140 waiting_for_response_
= is_loading
;
3141 is_load_to_different_document_
= to_different_document
;
3144 delegate_
->LoadingStateChanged(this, to_different_document
);
3145 NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD
);
3147 std::string url
= (details
? details
->url
.possibly_invalid_spec() : "NULL");
3149 TRACE_EVENT_ASYNC_BEGIN1("browser,navigation", "WebContentsImpl Loading",
3151 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3152 DidStartLoading(render_view_host
));
3154 TRACE_EVENT_ASYNC_END1("browser,navigation", "WebContentsImpl Loading",
3156 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3157 DidStopLoading(render_view_host
));
3160 // TODO(avi): Remove. http://crbug.com/170921
3161 int type
= is_loading
? NOTIFICATION_LOAD_START
: NOTIFICATION_LOAD_STOP
;
3162 NotificationDetails det
= NotificationService::NoDetails();
3164 det
= Details
<LoadNotificationDetails
>(details
);
3165 NotificationService::current()->Notify(
3166 type
, Source
<NavigationController
>(&controller_
), det
);
3169 void WebContentsImpl::SelectRange(const gfx::Point
& start
,
3170 const gfx::Point
& end
) {
3171 RenderFrameHost
* focused_frame
= GetFocusedFrame();
3175 focused_frame
->Send(
3176 new InputMsg_SelectRange(focused_frame
->GetRoutingID(), start
, end
));
3179 void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost
* rvh
) {
3180 // If we are creating a RVH for a restored controller, then we need to make
3181 // sure the RenderView starts with a next_page_id_ larger than the number
3182 // of restored entries. This must be called before the RenderView starts
3183 // navigating (to avoid a race between the browser updating max_page_id and
3184 // the renderer updating next_page_id_). Because of this, we only call this
3185 // from CreateRenderView and allow that to notify the RenderView for us.
3186 int max_restored_page_id
= controller_
.GetMaxRestoredPageID();
3187 if (max_restored_page_id
>
3188 GetMaxPageIDForSiteInstance(rvh
->GetSiteInstance()))
3189 UpdateMaxPageIDForSiteInstance(rvh
->GetSiteInstance(),
3190 max_restored_page_id
);
3193 bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl
* entry
,
3194 const base::string16
& title
) {
3195 // For file URLs without a title, use the pathname instead. In the case of a
3196 // synthesized title, we don't want the update to count toward the "one set
3197 // per page of the title to history."
3198 base::string16 final_title
;
3200 if (entry
&& entry
->GetURL().SchemeIsFile() && title
.empty()) {
3201 final_title
= base::UTF8ToUTF16(entry
->GetURL().ExtractFileName());
3202 explicit_set
= false; // Don't count synthetic titles toward the set limit.
3204 base::TrimWhitespace(title
, base::TRIM_ALL
, &final_title
);
3205 explicit_set
= true;
3208 // If a page is created via window.open and never navigated,
3209 // there will be no navigation entry. In this situation,
3210 // |page_title_when_no_navigation_entry_| will be used for page title.
3212 if (final_title
== entry
->GetTitle())
3213 return false; // Nothing changed, don't bother.
3215 entry
->SetTitle(final_title
);
3217 if (page_title_when_no_navigation_entry_
== final_title
)
3218 return false; // Nothing changed, don't bother.
3220 page_title_when_no_navigation_entry_
= final_title
;
3223 // Lastly, set the title for the view.
3224 view_
->SetPageTitle(final_title
);
3226 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3227 TitleWasSet(entry
, explicit_set
));
3229 // TODO(avi): Remove. http://crbug.com/170921
3230 std::pair
<NavigationEntry
*, bool> details
=
3231 std::make_pair(entry
, explicit_set
);
3232 NotificationService::current()->Notify(
3233 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED
,
3234 Source
<WebContents
>(this),
3235 Details
<std::pair
<NavigationEntry
*, bool> >(&details
));
3240 void WebContentsImpl::SendLoadProgressChanged() {
3241 loading_last_progress_update_
= base::TimeTicks::Now();
3242 double progress
= 0.0;
3243 int frame_count
= 0;
3245 for (LoadingProgressMap::iterator it
= loading_progresses_
.begin();
3246 it
!= loading_progresses_
.end();
3248 progress
+= it
->second
;
3251 if (frame_count
== 0)
3253 progress
/= frame_count
;
3254 DCHECK(progress
<= 1.0);
3256 if (progress
<= loading_total_progress_
)
3258 loading_total_progress_
= progress
;
3261 delegate_
->LoadProgressChanged(this, progress
);
3264 void WebContentsImpl::ResetLoadProgressState() {
3265 loading_progresses_
.clear();
3266 loading_total_progress_
= 0.0;
3267 loading_weak_factory_
.InvalidateWeakPtrs();
3268 loading_last_progress_update_
= base::TimeTicks();
3271 void WebContentsImpl::NotifyViewSwapped(RenderViewHost
* old_host
,
3272 RenderViewHost
* new_host
) {
3273 // After sending out a swap notification, we need to send a disconnect
3274 // notification so that clients that pick up a pointer to |this| can NULL the
3275 // pointer. See Bug 1230284.
3276 notify_disconnection_
= true;
3277 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3278 RenderViewHostChanged(old_host
, new_host
));
3280 // TODO(avi): Remove. http://crbug.com/170921
3281 std::pair
<RenderViewHost
*, RenderViewHost
*> details
=
3282 std::make_pair(old_host
, new_host
);
3283 NotificationService::current()->Notify(
3284 NOTIFICATION_RENDER_VIEW_HOST_CHANGED
,
3285 Source
<WebContents
>(this),
3286 Details
<std::pair
<RenderViewHost
*, RenderViewHost
*> >(&details
));
3288 // Ensure that the associated embedder gets cleared after a RenderViewHost
3289 // gets swapped, so we don't reuse the same embedder next time a
3290 // RenderViewHost is attached to this WebContents.
3291 RemoveBrowserPluginEmbedder();
3294 void WebContentsImpl::NotifyFrameSwapped(RenderFrameHost
* old_host
,
3295 RenderFrameHost
* new_host
) {
3296 FOR_EACH_OBSERVER(WebContentsObserver
,
3298 RenderFrameHostChanged(old_host
, new_host
));
3301 // TODO(avi): Remove this entire function because this notification is already
3302 // covered by two observer functions. http://crbug.com/170921
3303 void WebContentsImpl::NotifyDisconnected() {
3304 if (!notify_disconnection_
)
3307 notify_disconnection_
= false;
3308 NotificationService::current()->Notify(
3309 NOTIFICATION_WEB_CONTENTS_DISCONNECTED
,
3310 Source
<WebContents
>(this),
3311 NotificationService::NoDetails());
3314 void WebContentsImpl::NotifyNavigationEntryCommitted(
3315 const LoadCommittedDetails
& load_details
) {
3317 WebContentsObserver
, observers_
, NavigationEntryCommitted(load_details
));
3320 bool WebContentsImpl::OnMessageReceived(RenderFrameHost
* render_frame_host
,
3321 const IPC::Message
& message
) {
3322 return OnMessageReceived(NULL
, render_frame_host
, message
);
3325 const GURL
& WebContentsImpl::GetMainFrameLastCommittedURL() const {
3326 return GetLastCommittedURL();
3329 void WebContentsImpl::RenderFrameCreated(RenderFrameHost
* render_frame_host
) {
3330 // Note this is only for subframes, the notification for the main frame
3331 // happens in RenderViewCreated.
3332 FOR_EACH_OBSERVER(WebContentsObserver
,
3334 RenderFrameCreated(render_frame_host
));
3335 SetAccessibilityModeOnFrame(accessibility_mode_
, render_frame_host
);
3338 void WebContentsImpl::RenderFrameDeleted(RenderFrameHost
* render_frame_host
) {
3339 ClearPowerSaveBlockers(render_frame_host
);
3340 FOR_EACH_OBSERVER(WebContentsObserver
,
3342 RenderFrameDeleted(render_frame_host
));
3345 void WebContentsImpl::WorkerCrashed(RenderFrameHost
* render_frame_host
) {
3347 delegate_
->WorkerCrashed(this);
3350 void WebContentsImpl::ShowContextMenu(RenderFrameHost
* render_frame_host
,
3351 const ContextMenuParams
& params
) {
3352 ContextMenuParams
context_menu_params(params
);
3353 // Allow WebContentsDelegates to handle the context menu operation first.
3354 if (GetBrowserPluginGuest()) {
3355 WebContentsViewGuest
* view_guest
=
3356 static_cast<WebContentsViewGuest
*>(GetView());
3357 context_menu_params
= view_guest
->ConvertContextMenuParams(params
);
3359 if (delegate_
&& delegate_
->HandleContextMenu(context_menu_params
))
3362 render_view_host_delegate_view_
->ShowContextMenu(render_frame_host
,
3363 context_menu_params
);
3366 void WebContentsImpl::RunJavaScriptMessage(
3367 RenderFrameHost
* render_frame_host
,
3368 const base::string16
& message
,
3369 const base::string16
& default_prompt
,
3370 const GURL
& frame_url
,
3371 JavaScriptMessageType javascript_message_type
,
3372 IPC::Message
* reply_msg
) {
3373 // Suppress JavaScript dialogs when requested. Also suppress messages when
3374 // showing an interstitial as it's shown over the previous page and we don't
3375 // want the hidden page's dialogs to interfere with the interstitial.
3376 bool suppress_this_message
=
3377 static_cast<RenderViewHostImpl
*>(render_frame_host
->GetRenderViewHost())->
3379 ShowingInterstitialPage() ||
3381 delegate_
->ShouldSuppressDialogs() ||
3382 !delegate_
->GetJavaScriptDialogManager();
3384 if (!suppress_this_message
) {
3385 std::string accept_lang
= GetContentClient()->browser()->
3386 GetAcceptLangs(GetBrowserContext());
3387 dialog_manager_
= delegate_
->GetJavaScriptDialogManager();
3388 dialog_manager_
->RunJavaScriptDialog(
3390 frame_url
.GetOrigin(),
3392 javascript_message_type
,
3395 base::Bind(&WebContentsImpl::OnDialogClosed
,
3396 base::Unretained(this),
3397 render_frame_host
->GetProcess()->GetID(),
3398 render_frame_host
->GetRoutingID(),
3401 &suppress_this_message
);
3404 if (suppress_this_message
) {
3405 // If we are suppressing messages, just reply as if the user immediately
3406 // pressed "Cancel", passing true to |dialog_was_suppressed|.
3407 OnDialogClosed(render_frame_host
->GetProcess()->GetID(),
3408 render_frame_host
->GetRoutingID(), reply_msg
,
3409 true, false, base::string16());
3412 // OnDialogClosed (two lines up) may have caused deletion of this object (see
3413 // http://crbug.com/288961 ). The only safe thing to do here is return.
3416 void WebContentsImpl::RunBeforeUnloadConfirm(
3417 RenderFrameHost
* render_frame_host
,
3418 const base::string16
& message
,
3420 IPC::Message
* reply_msg
) {
3421 RenderFrameHostImpl
* rfhi
=
3422 static_cast<RenderFrameHostImpl
*>(render_frame_host
);
3423 RenderViewHostImpl
* rvhi
=
3424 static_cast<RenderViewHostImpl
*>(render_frame_host
->GetRenderViewHost());
3426 delegate_
->WillRunBeforeUnloadConfirm();
3428 bool suppress_this_message
=
3429 rvhi
->rvh_state() != RenderViewHostImpl::STATE_DEFAULT
||
3431 delegate_
->ShouldSuppressDialogs() ||
3432 !delegate_
->GetJavaScriptDialogManager();
3433 if (suppress_this_message
) {
3434 rfhi
->JavaScriptDialogClosed(reply_msg
, true, base::string16(), true);
3438 is_showing_before_unload_dialog_
= true;
3439 dialog_manager_
= delegate_
->GetJavaScriptDialogManager();
3440 dialog_manager_
->RunBeforeUnloadDialog(
3441 this, message
, is_reload
,
3442 base::Bind(&WebContentsImpl::OnDialogClosed
, base::Unretained(this),
3443 render_frame_host
->GetProcess()->GetID(),
3444 render_frame_host
->GetRoutingID(), reply_msg
,
3448 WebContents
* WebContentsImpl::GetAsWebContents() {
3452 bool WebContentsImpl::IsNeverVisible() {
3455 return delegate_
->IsNeverVisible(this);
3459 gfx::NativeViewAccessible
WebContentsImpl::GetParentNativeViewAccessible() {
3460 return accessible_parent_
;
3464 RenderViewHostDelegateView
* WebContentsImpl::GetDelegateView() {
3465 return render_view_host_delegate_view_
;
3468 RendererPreferences
WebContentsImpl::GetRendererPrefs(
3469 BrowserContext
* browser_context
) const {
3470 return renderer_preferences_
;
3473 gfx::Rect
WebContentsImpl::GetRootWindowResizerRect() const {
3475 return delegate_
->GetRootWindowResizerRect();
3479 void WebContentsImpl::RemoveBrowserPluginEmbedder() {
3480 if (browser_plugin_embedder_
)
3481 browser_plugin_embedder_
.reset();
3484 void WebContentsImpl::RenderViewCreated(RenderViewHost
* render_view_host
) {
3485 // Don't send notifications if we are just creating a swapped-out RVH for
3486 // the opener chain. These won't be used for view-source or WebUI, so it's
3487 // ok to return early.
3488 if (static_cast<RenderViewHostImpl
*>(render_view_host
)->IsSwappedOut())
3492 view_
->SetOverscrollControllerEnabled(CanOverscrollContent());
3494 NotificationService::current()->Notify(
3495 NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED
,
3496 Source
<WebContents
>(this),
3497 Details
<RenderViewHost
>(render_view_host
));
3499 // When we're creating views, we're still doing initial setup, so we always
3500 // use the pending Web UI rather than any possibly existing committed one.
3501 if (GetRenderManager()->pending_web_ui())
3502 GetRenderManager()->pending_web_ui()->RenderViewCreated(render_view_host
);
3504 NavigationEntry
* entry
= controller_
.GetPendingEntry();
3505 if (entry
&& entry
->IsViewSourceMode()) {
3506 // Put the renderer in view source mode.
3507 render_view_host
->Send(
3508 new ViewMsg_EnableViewSourceMode(render_view_host
->GetRoutingID()));
3511 view_
->RenderViewCreated(render_view_host
);
3514 WebContentsObserver
, observers_
, RenderViewCreated(render_view_host
));
3516 // We tell the observers now instead of when the main RenderFrameHostImpl is
3517 // constructed because otherwise it would be too early (i.e. IPCs sent to the
3518 // frame would be dropped because it's not created yet).
3519 RenderFrameHost
* main_frame
= render_view_host
->GetMainFrame();
3521 WebContentsObserver
, observers_
, RenderFrameCreated(main_frame
));
3522 SetAccessibilityModeOnFrame(accessibility_mode_
, main_frame
);
3525 void WebContentsImpl::RenderViewReady(RenderViewHost
* rvh
) {
3526 if (rvh
!= GetRenderViewHost()) {
3527 // Don't notify the world, since this came from a renderer in the
3532 notify_disconnection_
= true;
3533 // TODO(avi): Remove. http://crbug.com/170921
3534 NotificationService::current()->Notify(
3535 NOTIFICATION_WEB_CONTENTS_CONNECTED
,
3536 Source
<WebContents
>(this),
3537 NotificationService::NoDetails());
3539 bool was_crashed
= IsCrashed();
3540 SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING
, 0);
3542 // Restore the focus to the tab (otherwise the focus will be on the top
3544 if (was_crashed
&& !FocusLocationBarByDefault() &&
3545 (!delegate_
|| delegate_
->ShouldFocusPageAfterCrash())) {
3549 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, RenderViewReady());
3552 void WebContentsImpl::RenderViewTerminated(RenderViewHost
* rvh
,
3553 base::TerminationStatus status
,
3555 if (rvh
!= GetRenderViewHost()) {
3556 // The pending page's RenderViewHost is gone.
3560 // Ensure fullscreen mode is exited in the |delegate_| since a crashed
3561 // renderer may not have made a clean exit.
3562 if (IsFullscreenForCurrentTab())
3563 ToggleFullscreenMode(false);
3565 // Cancel any visible dialogs so they are not left dangling over the sad tab.
3566 if (dialog_manager_
)
3567 dialog_manager_
->CancelActiveAndPendingDialogs(this);
3570 delegate_
->HideValidationMessage(this);
3572 SetIsLoading(rvh
, false, true, NULL
);
3573 NotifyDisconnected();
3574 SetIsCrashed(status
, error_code
);
3576 // Reset the loading progress. TODO(avi): What does it mean to have a
3577 // "renderer crash" when there is more than one renderer process serving a
3578 // webpage? Once this function is called at a more granular frame level, we
3579 // probably will need to more granularly reset the state here.
3580 ResetLoadProgressState();
3581 loading_frames_in_progress_
= 0;
3583 FOR_EACH_OBSERVER(WebContentsObserver
,
3585 RenderProcessGone(GetCrashedStatus()));
3588 void WebContentsImpl::RenderViewDeleted(RenderViewHost
* rvh
) {
3589 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, RenderViewDeleted(rvh
));
3592 void WebContentsImpl::UpdateState(RenderViewHost
* rvh
,
3594 const PageState
& page_state
) {
3595 // Ensure that this state update comes from either the active RVH or one of
3596 // the swapped out RVHs. We don't expect to hear from any other RVHs.
3597 // TODO(nasko): This should go through RenderFrameHost.
3598 // TODO(creis): We can't update state for cross-process subframes until we
3599 // have FrameNavigationEntries. Once we do, this should be a DCHECK.
3600 if (rvh
!= GetRenderViewHost() &&
3601 !GetRenderManager()->IsRVHOnSwappedOutList(
3602 static_cast<RenderViewHostImpl
*>(rvh
)))
3605 // We must be prepared to handle state updates for any page, these occur
3606 // when the user is scrolling and entering form data, as well as when we're
3607 // leaving a page, in which case our state may have already been moved to
3608 // the next page. The navigation controller will look up the appropriate
3609 // NavigationEntry and update it when it is notified via the delegate.
3611 int entry_index
= controller_
.GetEntryIndexWithPageID(
3612 rvh
->GetSiteInstance(), page_id
);
3613 if (entry_index
< 0)
3615 NavigationEntry
* entry
= controller_
.GetEntryAtIndex(entry_index
);
3617 if (page_state
== entry
->GetPageState())
3618 return; // Nothing to update.
3619 entry
->SetPageState(page_state
);
3620 controller_
.NotifyEntryChanged(entry
, entry_index
);
3623 void WebContentsImpl::UpdateTargetURL(int32 page_id
, const GURL
& url
) {
3625 delegate_
->UpdateTargetURL(this, page_id
, url
);
3628 void WebContentsImpl::Close(RenderViewHost
* rvh
) {
3629 #if defined(OS_MACOSX)
3630 // The UI may be in an event-tracking loop, such as between the
3631 // mouse-down and mouse-up in text selection or a button click.
3632 // Defer the close until after tracking is complete, so that we
3633 // don't free objects out from under the UI.
3634 // TODO(shess): This could get more fine-grained. For instance,
3635 // closing a tab in another window while selecting text in the
3636 // current window's Omnibox should be just fine.
3637 if (view_
->IsEventTracking()) {
3638 view_
->CloseTabAfterEventTracking();
3643 // Ignore this if it comes from a RenderViewHost that we aren't showing.
3644 if (delegate_
&& rvh
== GetRenderViewHost())
3645 delegate_
->CloseContents(this);
3648 void WebContentsImpl::SwappedOut(RenderFrameHost
* rfh
) {
3649 if (delegate_
&& rfh
->GetRenderViewHost() == GetRenderViewHost())
3650 delegate_
->SwappedOut(this);
3653 void WebContentsImpl::DidDeferAfterResponseStarted(
3654 const TransitionLayerData
& transition_data
) {
3655 #if defined(OS_ANDROID)
3656 GetWebContentsAndroid()->DidDeferAfterResponseStarted(transition_data
);
3660 bool WebContentsImpl::WillHandleDeferAfterResponseStarted() {
3661 #if defined(OS_ANDROID)
3662 return GetWebContentsAndroid()->WillHandleDeferAfterResponseStarted();
3668 void WebContentsImpl::RequestMove(const gfx::Rect
& new_bounds
) {
3669 if (delegate_
&& delegate_
->IsPopupOrPanel(this))
3670 delegate_
->MoveContents(this, new_bounds
);
3673 void WebContentsImpl::DidStartLoading(RenderFrameHost
* render_frame_host
,
3674 bool to_different_document
) {
3675 SetIsLoading(render_frame_host
->GetRenderViewHost(), true,
3676 to_different_document
, NULL
);
3679 void WebContentsImpl::DidStopLoading(RenderFrameHost
* render_frame_host
) {
3680 scoped_ptr
<LoadNotificationDetails
> details
;
3682 // Use the last committed entry rather than the active one, in case a
3683 // pending entry has been created.
3684 NavigationEntry
* entry
= controller_
.GetLastCommittedEntry();
3685 Navigator
* navigator
= frame_tree_
.root()->navigator();
3687 // An entry may not exist for a stop when loading an initial blank page or
3688 // if an iframe injected by script into a blank page finishes loading.
3690 base::TimeDelta elapsed
=
3691 base::TimeTicks::Now() - navigator
->GetCurrentLoadStart();
3693 details
.reset(new LoadNotificationDetails(
3694 entry
->GetVirtualURL(),
3695 entry
->GetTransitionType(),
3698 controller_
.GetCurrentEntryIndex()));
3701 SetIsLoading(render_frame_host
->GetRenderViewHost(), false, true,
3705 void WebContentsImpl::DidCancelLoading() {
3706 controller_
.DiscardNonCommittedEntries();
3708 // Update the URL display.
3709 NotifyNavigationStateChanged(INVALIDATE_TYPE_URL
);
3712 void WebContentsImpl::DidAccessInitialDocument() {
3713 has_accessed_initial_document_
= true;
3715 // We may have left a failed browser-initiated navigation in the address bar
3716 // to let the user edit it and try again. Clear it now that content might
3717 // show up underneath it.
3718 if (!IsLoading() && controller_
.GetPendingEntry())
3719 controller_
.DiscardPendingEntry();
3721 // Update the URL display.
3722 NotifyNavigationStateChanged(INVALIDATE_TYPE_URL
);
3725 void WebContentsImpl::DidDisownOpener(RenderFrameHost
* render_frame_host
) {
3726 // No action is necessary if the opener has already been cleared.
3730 // Clear our opener so that future cross-process navigations don't have an
3732 RemoveDestructionObserver(opener_
);
3735 // Notify all swapped out RenderViewHosts for this tab. This is important
3736 // in case we go back to them, or if another window in those processes tries
3737 // to access window.opener.
3738 GetRenderManager()->DidDisownOpener(render_frame_host
);
3741 void WebContentsImpl::DocumentOnLoadCompleted(
3742 RenderFrameHost
* render_frame_host
) {
3743 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3744 DocumentOnLoadCompletedInMainFrame());
3746 // TODO(avi): Remove. http://crbug.com/170921
3747 NotificationService::current()->Notify(
3748 NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME
,
3749 Source
<WebContents
>(this),
3750 NotificationService::NoDetails());
3753 void WebContentsImpl::UpdateTitle(RenderFrameHost
* render_frame_host
,
3755 const base::string16
& title
,
3756 base::i18n::TextDirection title_direction
) {
3757 RenderViewHost
* rvh
= render_frame_host
->GetRenderViewHost();
3759 // If we have a title, that's a pretty good indication that we've started
3760 // getting useful data.
3761 SetNotWaitingForResponse();
3763 // Try to find the navigation entry, which might not be the current one.
3764 // For example, it might be from a pending RVH for the pending entry.
3765 NavigationEntryImpl
* entry
= controller_
.GetEntryWithPageID(
3766 rvh
->GetSiteInstance(), page_id
);
3768 // We can handle title updates when we don't have an entry in
3769 // UpdateTitleForEntry, but only if the update is from the current RVH.
3770 // TODO(avi): Change to make decisions based on the RenderFrameHost.
3771 if (!entry
&& rvh
!= GetRenderViewHost())
3774 // TODO(evan): make use of title_direction.
3775 // http://code.google.com/p/chromium/issues/detail?id=27094
3776 if (!UpdateTitleForEntry(entry
, title
))
3779 // Broadcast notifications when the UI should be updated.
3780 if (entry
== controller_
.GetEntryAtOffset(0))
3781 NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE
);
3784 void WebContentsImpl::UpdateEncoding(RenderFrameHost
* render_frame_host
,
3785 const std::string
& encoding
) {
3786 SetEncoding(encoding
);
3789 void WebContentsImpl::DocumentAvailableInMainFrame(
3790 RenderViewHost
* render_view_host
) {
3791 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3792 DocumentAvailableInMainFrame());
3794 void WebContentsImpl::RouteCloseEvent(RenderViewHost
* rvh
) {
3795 // Tell the active RenderViewHost to run unload handlers and close, as long
3796 // as the request came from a RenderViewHost in the same BrowsingInstance.
3797 // In most cases, we receive this from a swapped out RenderViewHost.
3798 // It is possible to receive it from one that has just been swapped in,
3799 // in which case we might as well deliver the message anyway.
3800 if (rvh
->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()))
3801 GetRenderViewHost()->ClosePage();
3804 void WebContentsImpl::RouteMessageEvent(
3805 RenderViewHost
* rvh
,
3806 const ViewMsg_PostMessage_Params
& params
) {
3807 // Only deliver the message to the active RenderViewHost if the request
3808 // came from a RenderViewHost in the same BrowsingInstance or if this
3809 // WebContents is dedicated to a browser plugin guest.
3810 // Note: This check means that an embedder could theoretically receive a
3811 // postMessage from anyone (not just its own guests). However, this is
3812 // probably not a risk for apps since other pages won't have references
3814 if (!rvh
->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()) &&
3815 !GetBrowserPluginGuest() && !GetBrowserPluginEmbedder())
3818 ViewMsg_PostMessage_Params
new_params(params
);
3820 if (!params
.message_port_ids
.empty()) {
3821 MessagePortMessageFilter
* message_port_message_filter
=
3822 static_cast<RenderProcessHostImpl
*>(GetRenderProcessHost())
3823 ->message_port_message_filter();
3824 message_port_message_filter
->UpdateMessagePortsWithNewRoutes(
3825 params
.message_port_ids
,
3826 &new_params
.new_routing_ids
);
3829 // If there is a source_routing_id, translate it to the routing ID for
3830 // the equivalent swapped out RVH in the target process. If we need
3831 // to create a swapped out RVH for the source tab, we create its opener
3832 // chain as well, since those will also be accessible to the target page.
3833 if (new_params
.source_routing_id
!= MSG_ROUTING_NONE
) {
3834 // Try to look up the WebContents for the source page.
3835 WebContentsImpl
* source_contents
= NULL
;
3836 RenderViewHostImpl
* source_rvh
= RenderViewHostImpl::FromID(
3837 rvh
->GetProcess()->GetID(), params
.source_routing_id
);
3839 source_contents
= static_cast<WebContentsImpl
*>(
3840 source_rvh
->GetDelegate()->GetAsWebContents());
3843 if (source_contents
) {
3844 if (GetBrowserPluginGuest()) {
3845 // We create a swapped out RenderView for the embedder in the guest's
3846 // render process but we intentionally do not expose the embedder's
3847 // opener chain to it.
3848 new_params
.source_routing_id
=
3849 source_contents
->CreateSwappedOutRenderView(GetSiteInstance());
3851 new_params
.source_routing_id
=
3852 source_contents
->CreateOpenerRenderViews(GetSiteInstance());
3855 // We couldn't find it, so don't pass a source frame.
3856 new_params
.source_routing_id
= MSG_ROUTING_NONE
;
3860 // In most cases, we receive this from a swapped out RenderViewHost.
3861 // It is possible to receive it from one that has just been swapped in,
3862 // in which case we might as well deliver the message anyway.
3863 Send(new ViewMsg_PostMessageEvent(GetRoutingID(), new_params
));
3866 bool WebContentsImpl::AddMessageToConsole(int32 level
,
3867 const base::string16
& message
,
3869 const base::string16
& source_id
) {
3872 return delegate_
->AddMessageToConsole(this, level
, message
, line_no
,
3876 WebPreferences
WebContentsImpl::ComputeWebkitPrefs() {
3877 // We want to base the page config off of the actual URL, rather than the
3879 // TODO(nasko): Investigate how to remove the GetActiveEntry usage here,
3880 // as it is deprecated and can be out of sync with GetRenderViewHost().
3881 GURL url
= controller_
.GetActiveEntry()
3882 ? controller_
.GetActiveEntry()->GetURL() : GURL::EmptyGURL();
3884 return GetRenderManager()->current_host()->ComputeWebkitPrefs(url
);
3887 int WebContentsImpl::CreateSwappedOutRenderView(
3888 SiteInstance
* instance
) {
3889 return GetRenderManager()->CreateRenderFrame(
3890 instance
, MSG_ROUTING_NONE
, true, true, true);
3893 void WebContentsImpl::OnUserGesture() {
3894 // Notify observers.
3895 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, DidGetUserGesture());
3897 ResourceDispatcherHostImpl
* rdh
= ResourceDispatcherHostImpl::Get();
3898 if (rdh
) // NULL in unittests.
3899 rdh
->OnUserGesture(this);
3902 void WebContentsImpl::OnIgnoredUIEvent() {
3903 // Notify observers.
3904 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, DidGetIgnoredUIEvent());
3907 void WebContentsImpl::RendererUnresponsive(RenderViewHost
* rvh
,
3908 bool is_during_beforeunload
,
3909 bool is_during_unload
) {
3910 // Don't show hung renderer dialog for a swapped out RVH.
3911 if (rvh
!= GetRenderViewHost())
3914 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(rvh
);
3916 // Ignore renderer unresponsive event if debugger is attached to the tab
3917 // since the event may be a result of the renderer sitting on a breakpoint.
3918 // See http://crbug.com/65458
3919 if (DevToolsAgentHost::IsDebuggerAttached(this))
3922 if (is_during_beforeunload
|| is_during_unload
) {
3923 // Hang occurred while firing the beforeunload/unload handler.
3924 // Pretend the handler fired so tab closing continues as if it had.
3925 rvhi
->set_sudden_termination_allowed(true);
3927 if (!GetRenderManager()->ShouldCloseTabOnUnresponsiveRenderer())
3930 // If the tab hangs in the beforeunload/unload handler there's really
3931 // nothing we can do to recover. If the hang is in the beforeunload handler,
3932 // pretend the beforeunload listeners have all fired and allow the delegate
3933 // to continue closing; the user will not have the option of cancelling the
3934 // close. Otherwise, pretend the unload listeners have all fired and close
3937 if (is_during_beforeunload
&& delegate_
) {
3938 delegate_
->BeforeUnloadFired(this, true, &close
);
3945 if (!GetRenderViewHostImpl() || !GetRenderViewHostImpl()->IsRenderViewLive())
3949 delegate_
->RendererUnresponsive(this);
3952 void WebContentsImpl::RendererResponsive(RenderViewHost
* render_view_host
) {
3954 delegate_
->RendererResponsive(this);
3957 void WebContentsImpl::LoadStateChanged(
3959 const net::LoadStateWithParam
& load_state
,
3960 uint64 upload_position
,
3961 uint64 upload_size
) {
3962 load_state_
= load_state
;
3963 upload_position_
= upload_position
;
3964 upload_size_
= upload_size
;
3965 load_state_host_
= net::IDNToUnicode(url
.host(),
3966 GetContentClient()->browser()->GetAcceptLangs(
3967 GetBrowserContext()));
3968 if (load_state_
.state
== net::LOAD_STATE_READING_RESPONSE
)
3969 SetNotWaitingForResponse();
3971 NotifyNavigationStateChanged(static_cast<InvalidateTypes
>(
3972 INVALIDATE_TYPE_LOAD
| INVALIDATE_TYPE_TAB
));
3976 void WebContentsImpl::BeforeUnloadFiredFromRenderManager(
3977 bool proceed
, const base::TimeTicks
& proceed_time
,
3978 bool* proceed_to_fire_unload
) {
3979 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3980 BeforeUnloadFired(proceed_time
));
3982 delegate_
->BeforeUnloadFired(this, proceed
, proceed_to_fire_unload
);
3983 // Note: |this| might be deleted at this point.
3986 void WebContentsImpl::RenderProcessGoneFromRenderManager(
3987 RenderViewHost
* render_view_host
) {
3988 DCHECK(crashed_status_
!= base::TERMINATION_STATUS_STILL_RUNNING
);
3989 RenderViewTerminated(render_view_host
, crashed_status_
, crashed_error_code_
);
3992 void WebContentsImpl::UpdateRenderViewSizeForRenderManager() {
3993 // TODO(brettw) this is a hack. See WebContentsView::SizeContents.
3994 gfx::Size size
= GetSizeForNewRenderView();
3995 // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be
3996 // here during container initialization and normal window size will be set
3997 // later. In case of tab duplication this resizing to 0x0 prevents setting
3998 // normal size later so just ignore it.
3999 if (!size
.IsEmpty())
4000 view_
->SizeContents(size
);
4003 void WebContentsImpl::CancelModalDialogsForRenderManager() {
4004 // We need to cancel modal dialogs when doing a process swap, since the load
4005 // deferrer would prevent us from swapping out.
4006 if (dialog_manager_
)
4007 dialog_manager_
->CancelActiveAndPendingDialogs(this);
4010 void WebContentsImpl::NotifySwappedFromRenderManager(RenderFrameHost
* old_host
,
4011 RenderFrameHost
* new_host
,
4012 bool is_main_frame
) {
4013 if (is_main_frame
) {
4014 NotifyViewSwapped(old_host
? old_host
->GetRenderViewHost() : NULL
,
4015 new_host
->GetRenderViewHost());
4017 // Make sure the visible RVH reflects the new delegate's preferences.
4019 view_
->SetOverscrollControllerEnabled(CanOverscrollContent());
4021 view_
->RenderViewSwappedIn(new_host
->GetRenderViewHost());
4024 NotifyFrameSwapped(old_host
, new_host
);
4027 int WebContentsImpl::CreateOpenerRenderViewsForRenderManager(
4028 SiteInstance
* instance
) {
4030 return MSG_ROUTING_NONE
;
4032 // Recursively create RenderViews for anything else in the opener chain.
4033 return opener_
->CreateOpenerRenderViews(instance
);
4036 int WebContentsImpl::CreateOpenerRenderViews(SiteInstance
* instance
) {
4037 int opener_route_id
= MSG_ROUTING_NONE
;
4039 // If this tab has an opener, ensure it has a RenderView in the given
4040 // SiteInstance as well.
4042 opener_route_id
= opener_
->CreateOpenerRenderViews(instance
);
4044 // If any of the renderers (current, pending, or swapped out) for this
4045 // WebContents has the same SiteInstance, use it.
4046 if (GetRenderManager()->current_host()->GetSiteInstance() == instance
)
4047 return GetRenderManager()->current_host()->GetRoutingID();
4049 if (GetRenderManager()->pending_render_view_host() &&
4050 GetRenderManager()->pending_render_view_host()->GetSiteInstance() ==
4052 return GetRenderManager()->pending_render_view_host()->GetRoutingID();
4054 RenderViewHostImpl
* rvh
= GetRenderManager()->GetSwappedOutRenderViewHost(
4057 return rvh
->GetRoutingID();
4059 // Create a swapped out RenderView in the given SiteInstance if none exists,
4060 // setting its opener to the given route_id. Return the new view's route_id.
4061 return GetRenderManager()->CreateRenderFrame(
4062 instance
, opener_route_id
, true, true, true);
4065 NavigationControllerImpl
& WebContentsImpl::GetControllerForRenderManager() {
4066 return GetController();
4069 WebUIImpl
* WebContentsImpl::CreateWebUIForRenderManager(const GURL
& url
) {
4070 return static_cast<WebUIImpl
*>(CreateWebUI(url
));
4074 WebContentsImpl::GetLastCommittedNavigationEntryForRenderManager() {
4075 return controller_
.GetLastCommittedEntry();
4078 bool WebContentsImpl::CreateRenderViewForRenderManager(
4079 RenderViewHost
* render_view_host
,
4080 int opener_route_id
,
4081 int proxy_routing_id
,
4082 bool for_main_frame_navigation
) {
4083 TRACE_EVENT0("browser,navigation",
4084 "WebContentsImpl::CreateRenderViewForRenderManager");
4085 // Can be NULL during tests.
4086 RenderWidgetHostViewBase
* rwh_view
;
4087 // TODO(kenrb): RenderWidgetHostViewChildFrame special casing is temporary
4088 // until RenderWidgetHost is attached to RenderFrameHost. We need to special
4089 // case this because RWH is still a base class of RenderViewHost, and child
4090 // frame RWHVs are unique in that they do not have their own WebContents.
4091 if (!for_main_frame_navigation
) {
4092 RenderWidgetHostViewChildFrame
* rwh_view_child
=
4093 new RenderWidgetHostViewChildFrame(render_view_host
);
4094 rwh_view
= rwh_view_child
;
4096 rwh_view
= view_
->CreateViewForWidget(render_view_host
);
4099 // Now that the RenderView has been created, we need to tell it its size.
4101 rwh_view
->SetSize(GetSizeForNewRenderView());
4103 // Make sure we use the correct starting page_id in the new RenderView.
4104 UpdateMaxPageIDIfNecessary(render_view_host
);
4106 GetMaxPageIDForSiteInstance(render_view_host
->GetSiteInstance());
4108 if (!static_cast<RenderViewHostImpl
*>(
4109 render_view_host
)->CreateRenderView(base::string16(),
4113 created_with_opener_
)) {
4117 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
4118 // Force a ViewMsg_Resize to be sent, needed to make plugins show up on
4119 // linux. See crbug.com/83941.
4121 if (RenderWidgetHost
* render_widget_host
= rwh_view
->GetRenderWidgetHost())
4122 render_widget_host
->WasResized();
4129 bool WebContentsImpl::CreateRenderFrameForRenderManager(
4130 RenderFrameHost
* render_frame_host
,
4131 int parent_routing_id
) {
4132 TRACE_EVENT0("browser,navigation",
4133 "WebContentsImpl::CreateRenderFrameForRenderManager");
4135 RenderFrameHostImpl
* rfh
=
4136 static_cast<RenderFrameHostImpl
*>(render_frame_host
);
4137 if (!rfh
->CreateRenderFrame(parent_routing_id
))
4140 // TODO(nasko): When RenderWidgetHost is owned by RenderFrameHost, the passed
4141 // RenderFrameHost will have to be associated with the appropriate
4142 // RenderWidgetHostView or a new one should be created here.
4147 #if defined(OS_ANDROID)
4149 base::android::ScopedJavaLocalRef
<jobject
>
4150 WebContentsImpl::GetJavaWebContents() {
4151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
4152 return GetWebContentsAndroid()->GetJavaObject();
4155 WebContentsAndroid
* WebContentsImpl::GetWebContentsAndroid() {
4156 WebContentsAndroid
* web_contents_android
=
4157 static_cast<WebContentsAndroid
*>(GetUserData(kWebContentsAndroidKey
));
4158 if (!web_contents_android
) {
4159 web_contents_android
= new WebContentsAndroid(this);
4160 SetUserData(kWebContentsAndroidKey
, web_contents_android
);
4162 return web_contents_android
;
4165 bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() {
4166 return CreateRenderViewForRenderManager(GetRenderViewHost(),
4172 #elif defined(OS_MACOSX)
4174 void WebContentsImpl::SetAllowOtherViews(bool allow
) {
4175 view_
->SetAllowOtherViews(allow
);
4178 bool WebContentsImpl::GetAllowOtherViews() {
4179 return view_
->GetAllowOtherViews();
4184 void WebContentsImpl::OnDialogClosed(int render_process_id
,
4185 int render_frame_id
,
4186 IPC::Message
* reply_msg
,
4187 bool dialog_was_suppressed
,
4189 const base::string16
& user_input
) {
4190 RenderFrameHostImpl
* rfh
= RenderFrameHostImpl::FromID(render_process_id
,
4192 last_dialog_suppressed_
= dialog_was_suppressed
;
4194 if (is_showing_before_unload_dialog_
&& !success
) {
4195 // If a beforeunload dialog is canceled, we need to stop the throbber from
4196 // spinning, since we forced it to start spinning in Navigate.
4198 DidStopLoading(rfh
);
4199 controller_
.DiscardNonCommittedEntries();
4201 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
4202 BeforeUnloadDialogCancelled());
4205 is_showing_before_unload_dialog_
= false;
4207 rfh
->JavaScriptDialogClosed(reply_msg
, success
, user_input
,
4208 dialog_was_suppressed
);
4210 // Don't leak the sync IPC reply if the RFH or process is gone.
4215 void WebContentsImpl::SetEncoding(const std::string
& encoding
) {
4216 if (encoding
== last_reported_encoding_
)
4218 last_reported_encoding_
= encoding
;
4220 canonical_encoding_
= GetContentClient()->browser()->
4221 GetCanonicalEncodingNameByAliasName(encoding
);
4224 void WebContentsImpl::CreateViewAndSetSizeForRVH(RenderViewHost
* rvh
) {
4225 RenderWidgetHostViewBase
* rwh_view
= view_
->CreateViewForWidget(rvh
);
4226 // Can be NULL during tests.
4228 rwh_view
->SetSize(GetContainerBounds().size());
4231 bool WebContentsImpl::IsHidden() {
4232 return capturer_count_
== 0 && !should_normally_be_visible_
;
4235 RenderFrameHostManager
* WebContentsImpl::GetRenderManager() const {
4236 return frame_tree_
.root()->render_manager();
4239 RenderViewHostImpl
* WebContentsImpl::GetRenderViewHostImpl() {
4240 return static_cast<RenderViewHostImpl
*>(GetRenderViewHost());
4243 BrowserPluginGuest
* WebContentsImpl::GetBrowserPluginGuest() const {
4244 return browser_plugin_guest_
.get();
4247 void WebContentsImpl::SetBrowserPluginGuest(BrowserPluginGuest
* guest
) {
4248 CHECK(!browser_plugin_guest_
);
4249 browser_plugin_guest_
.reset(guest
);
4252 BrowserPluginEmbedder
* WebContentsImpl::GetBrowserPluginEmbedder() const {
4253 return browser_plugin_embedder_
.get();
4256 void WebContentsImpl::ClearPowerSaveBlockers(
4257 RenderFrameHost
* render_frame_host
) {
4258 RemoveAllMediaPlayerEntries(render_frame_host
, &active_audio_players_
);
4259 RemoveAllMediaPlayerEntries(render_frame_host
, &active_video_players_
);
4260 MaybeReleasePowerSaveBlockers();
4263 void WebContentsImpl::ClearAllPowerSaveBlockers() {
4264 active_audio_players_
.clear();
4265 active_video_players_
.clear();
4266 audio_power_save_blocker_
.reset();
4267 video_power_save_blocker_
.reset();
4270 gfx::Size
WebContentsImpl::GetSizeForNewRenderView() {
4273 size
= delegate_
->GetSizeForNewRenderView(this);
4275 size
= GetContainerBounds().size();
4279 void WebContentsImpl::OnFrameRemoved(RenderFrameHost
* render_frame_host
) {
4281 WebContentsObserver
, observers_
, FrameDetached(render_frame_host
));
4284 void WebContentsImpl::OnPreferredSizeChanged(const gfx::Size
& old_size
) {
4287 const gfx::Size new_size
= GetPreferredSize();
4288 if (new_size
!= old_size
)
4289 delegate_
->UpdatePreferredSize(this, new_size
);
4292 void WebContentsImpl::AddMediaPlayerEntry(int64 player_cookie
,
4293 ActiveMediaPlayerMap
* player_map
) {
4294 const uintptr_t key
=
4295 reinterpret_cast<uintptr_t>(render_frame_message_source_
);
4296 DCHECK(std::find((*player_map
)[key
].begin(),
4297 (*player_map
)[key
].end(),
4298 player_cookie
) == (*player_map
)[key
].end());
4299 (*player_map
)[key
].push_back(player_cookie
);
4302 void WebContentsImpl::RemoveMediaPlayerEntry(int64 player_cookie
,
4303 ActiveMediaPlayerMap
* player_map
) {
4304 const uintptr_t key
=
4305 reinterpret_cast<uintptr_t>(render_frame_message_source_
);
4306 ActiveMediaPlayerMap::iterator it
= player_map
->find(key
);
4307 if (it
== player_map
->end())
4310 // Remove the player.
4311 PlayerList::iterator player_it
=
4312 std::find(it
->second
.begin(), it
->second
.end(), player_cookie
);
4313 if (player_it
!= it
->second
.end())
4314 it
->second
.erase(player_it
);
4316 // If there are no players left, remove the map entry.
4317 if (it
->second
.empty())
4318 player_map
->erase(it
);
4321 void WebContentsImpl::RemoveAllMediaPlayerEntries(
4322 RenderFrameHost
* render_frame_host
,
4323 ActiveMediaPlayerMap
* player_map
) {
4324 ActiveMediaPlayerMap::iterator it
=
4325 player_map
->find(reinterpret_cast<uintptr_t>(render_frame_host
));
4326 if (it
== player_map
->end())
4328 player_map
->erase(it
);
4331 void WebContentsImpl::ResumeResponseDeferredAtStart() {
4332 FrameTreeNode
* node
= frame_tree_
.root();
4333 node
->render_manager()->ResumeResponseDeferredAtStart();
4336 void WebContentsImpl::SetForceDisableOverscrollContent(bool force_disable
) {
4337 force_disable_overscroll_content_
= force_disable
;
4339 view_
->SetOverscrollControllerEnabled(CanOverscrollContent());
4342 } // namespace content