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/metrics/histogram.h"
11 #include "base/metrics/stats_counters.h"
12 #include "base/string16.h"
13 #include "base/string_number_conversions.h"
14 #include "base/string_util.h"
15 #include "base/sys_info.h"
16 #include "base/time.h"
17 #include "base/utf_string_conversions.h"
18 #include "cc/switches.h"
19 #include "content/browser/browser_plugin/browser_plugin_embedder.h"
20 #include "content/browser/browser_plugin/browser_plugin_guest.h"
21 #include "content/browser/browser_plugin/browser_plugin_guest_manager.h"
22 #include "content/browser/child_process_security_policy_impl.h"
23 #include "content/browser/devtools/devtools_manager_impl.h"
24 #include "content/browser/dom_storage/dom_storage_context_impl.h"
25 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
26 #include "content/browser/download/download_stats.h"
27 #include "content/browser/download/mhtml_generation_manager.h"
28 #include "content/browser/download/save_package.h"
29 #include "content/browser/gpu/gpu_data_manager_impl.h"
30 #include "content/browser/gpu/gpu_process_host.h"
31 #include "content/browser/host_zoom_map_impl.h"
32 #include "content/browser/loader/resource_dispatcher_host_impl.h"
33 #include "content/browser/renderer_host/render_process_host_impl.h"
34 #include "content/browser/renderer_host/render_view_host_impl.h"
35 #include "content/browser/renderer_host/render_widget_host_impl.h"
36 #include "content/browser/site_instance_impl.h"
37 #include "content/browser/web_contents/interstitial_page_impl.h"
38 #include "content/browser/web_contents/navigation_entry_impl.h"
39 #include "content/browser/web_contents/web_contents_view_guest.h"
40 #include "content/browser/webui/generic_handler.h"
41 #include "content/browser/webui/web_ui_controller_factory_registry.h"
42 #include "content/browser/webui/web_ui_impl.h"
43 #include "content/common/browser_plugin/browser_plugin_constants.h"
44 #include "content/common/browser_plugin/browser_plugin_messages.h"
45 #include "content/common/icon_messages.h"
46 #include "content/common/ssl_status_serialization.h"
47 #include "content/common/view_messages.h"
48 #include "content/port/browser/render_view_host_delegate_view.h"
49 #include "content/port/browser/render_widget_host_view_port.h"
50 #include "content/public/browser/browser_context.h"
51 #include "content/public/browser/color_chooser.h"
52 #include "content/public/browser/compositor_util.h"
53 #include "content/public/browser/content_browser_client.h"
54 #include "content/public/browser/devtools_agent_host.h"
55 #include "content/public/browser/download_manager.h"
56 #include "content/public/browser/download_url_parameters.h"
57 #include "content/public/browser/invalidate_type.h"
58 #include "content/public/browser/javascript_dialog_manager.h"
59 #include "content/public/browser/load_from_memory_cache_details.h"
60 #include "content/public/browser/load_notification_details.h"
61 #include "content/public/browser/navigation_details.h"
62 #include "content/public/browser/notification_details.h"
63 #include "content/public/browser/notification_service.h"
64 #include "content/public/browser/resource_request_details.h"
65 #include "content/public/browser/storage_partition.h"
66 #include "content/public/browser/user_metrics.h"
67 #include "content/public/browser/web_contents_delegate.h"
68 #include "content/public/browser/web_contents_observer.h"
69 #include "content/public/browser/web_contents_view.h"
70 #include "content/public/common/bindings_policy.h"
71 #include "content/public/common/content_constants.h"
72 #include "content/public/common/content_restriction.h"
73 #include "content/public/common/content_switches.h"
74 #include "content/public/common/url_constants.h"
75 #include "net/base/mime_util.h"
76 #include "net/base/net_util.h"
77 #include "net/base/network_change_notifier.h"
78 #include "net/url_request/url_request_context_getter.h"
79 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
80 #include "ui/base/layout.h"
81 #include "ui/base/touch/touch_device.h"
82 #include "ui/base/ui_base_switches.h"
83 #include "ui/gfx/display.h"
84 #include "ui/gfx/screen.h"
85 #include "ui/gl/gl_switches.h"
86 #include "webkit/glue/webpreferences.h"
88 #if defined(OS_ANDROID)
89 #include "content/browser/android/date_time_chooser_android.h"
92 #if defined(OS_MACOSX)
93 #include "base/mac/foundation_util.h"
94 #include "ui/surface/io_surface_support_mac.h"
97 #if defined(ENABLE_JAVA_BRIDGE)
98 #include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
101 // Cross-Site Navigations
103 // If a WebContentsImpl is told to navigate to a different web site (as
104 // determined by SiteInstance), it will replace its current RenderViewHost with
105 // a new RenderViewHost dedicated to the new SiteInstance. This works as
108 // - Navigate determines whether the destination is cross-site, and if so,
109 // it creates a pending_render_view_host_.
110 // - The pending RVH is "suspended," so that no navigation messages are sent to
111 // its renderer until the onbeforeunload JavaScript handler has a chance to
112 // run in the current RVH.
113 // - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton)
114 // that it has a pending cross-site request. ResourceDispatcherHost will
115 // check for this when the response arrives.
116 // - The current RVH runs its onbeforeunload handler. If it returns false, we
117 // cancel all the pending logic. Otherwise we allow the pending RVH to send
118 // the navigation request to its renderer.
119 // - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the
120 // main resource load on the pending RVH. It checks CrossSiteRequestManager
121 // to see that it is a cross-site request, and installs a
122 // CrossSiteResourceHandler.
123 // - When RDH receives a response, the BufferedResourceHandler determines
124 // whether it is a download. If so, it sends a message to the new renderer
125 // causing it to cancel the request, and the download proceeds. For now, the
126 // pending RVH remains until the next DidNavigate event for this
127 // WebContentsImpl. This isn't ideal, but it doesn't affect any functionality.
128 // - After RDH receives a response and determines that it is safe and not a
129 // download, it pauses the response to first run the old page's onunload
130 // handler. It does this by asynchronously calling the OnCrossSiteResponse
131 // method of WebContentsImpl on the UI thread, which sends a SwapOut message
132 // to the current RVH.
133 // - Once the onunload handler is finished, a SwapOut_ACK message is sent to
134 // the ResourceDispatcherHost, who unpauses the response. Data is then sent
135 // to the pending RVH.
136 // - The pending renderer sends a FrameNavigate message that invokes the
137 // DidNavigate method. This replaces the current RVH with the
139 // - The previous renderer is kept swapped out in RenderViewHostManager in case
140 // the user goes back. The process only stays live if another tab is using
141 // it, but if so, the existing frame relationships will be maintained.
143 using webkit_glue::WebPreferences
;
148 // Amount of time we wait between when a key event is received and the renderer
149 // is queried for its state and pushed to the NavigationEntry.
150 const int kQueryStateDelay
= 5000;
152 const int kSyncWaitDelay
= 40;
154 const char kDotGoogleDotCom
[] = ".google.com";
156 static int StartDownload(content::RenderViewHost
* rvh
,
159 static int g_next_favicon_download_id
= 0;
160 rvh
->Send(new IconMsg_DownloadFavicon(rvh
->GetRoutingID(),
161 ++g_next_favicon_download_id
,
164 return g_next_favicon_download_id
;
167 ViewMsg_Navigate_Type::Value
GetNavigationType(
168 BrowserContext
* browser_context
, const NavigationEntryImpl
& entry
,
169 NavigationController::ReloadType reload_type
) {
170 switch (reload_type
) {
171 case NavigationControllerImpl::RELOAD
:
172 return ViewMsg_Navigate_Type::RELOAD
;
173 case NavigationControllerImpl::RELOAD_IGNORING_CACHE
:
174 return ViewMsg_Navigate_Type::RELOAD_IGNORING_CACHE
;
175 case NavigationControllerImpl::RELOAD_ORIGINAL_REQUEST_URL
:
176 return ViewMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL
;
177 case NavigationControllerImpl::NO_RELOAD
:
178 break; // Fall through to rest of function.
181 // |RenderViewImpl::PopulateStateFromPendingNavigationParams| differentiates
182 // between |RESTORE_WITH_POST| and |RESTORE|.
183 if (entry
.restore_type() ==
184 NavigationEntryImpl::RESTORE_LAST_SESSION_EXITED_CLEANLY
) {
185 if (entry
.GetHasPostData())
186 return ViewMsg_Navigate_Type::RESTORE_WITH_POST
;
187 return ViewMsg_Navigate_Type::RESTORE
;
190 return ViewMsg_Navigate_Type::NORMAL
;
193 void MakeNavigateParams(const NavigationEntryImpl
& entry
,
194 const NavigationControllerImpl
& controller
,
195 WebContentsDelegate
* delegate
,
196 NavigationController::ReloadType reload_type
,
197 ViewMsg_Navigate_Params
* params
) {
198 params
->page_id
= entry
.GetPageID();
199 params
->pending_history_list_offset
= controller
.GetIndexOfEntry(&entry
);
200 params
->current_history_list_offset
= controller
.GetLastCommittedEntryIndex();
201 params
->current_history_list_length
= controller
.GetEntryCount();
202 if (!entry
.GetBaseURLForDataURL().is_empty()) {
203 params
->base_url_for_data_url
= entry
.GetBaseURLForDataURL();
204 params
->history_url_for_data_url
= entry
.GetVirtualURL();
206 params
->referrer
= entry
.GetReferrer();
207 params
->transition
= entry
.GetTransitionType();
208 params
->state
= entry
.GetContentState();
209 params
->navigation_type
=
210 GetNavigationType(controller
.GetBrowserContext(), entry
, reload_type
);
211 params
->request_time
= base::Time::Now();
212 params
->extra_headers
= entry
.extra_headers();
213 params
->transferred_request_child_id
=
214 entry
.transferred_global_request_id().child_id
;
215 params
->transferred_request_request_id
=
216 entry
.transferred_global_request_id().request_id
;
217 params
->is_overriding_user_agent
= entry
.GetIsOverridingUserAgent();
218 // Avoid downloading when in view-source mode.
219 params
->allow_download
= !entry
.IsViewSourceMode();
220 params
->is_post
= entry
.GetHasPostData();
221 if(entry
.GetBrowserInitiatedPostData()) {
222 params
->browser_initiated_post_data
.assign(
223 entry
.GetBrowserInitiatedPostData()->front(),
224 entry
.GetBrowserInitiatedPostData()->front() +
225 entry
.GetBrowserInitiatedPostData()->size());
229 if (reload_type
== NavigationControllerImpl::RELOAD_ORIGINAL_REQUEST_URL
&&
230 entry
.GetOriginalRequestURL().is_valid() && !entry
.GetHasPostData()) {
231 // We may have been redirected when navigating to the current URL.
232 // Use the URL the user originally intended to visit, if it's valid and if a
233 // POST wasn't involved; the latter case avoids issues with sending data to
235 params
->url
= entry
.GetOriginalRequestURL();
237 params
->url
= entry
.GetURL();
240 params
->can_load_local_resources
= entry
.GetCanLoadLocalResources();
241 params
->frame_to_navigate
= entry
.GetFrameToNavigate();
244 delegate
->AddNavigationHeaders(params
->url
, ¶ms
->extra_headers
);
249 WebContents
* WebContents::Create(const WebContents::CreateParams
& params
) {
250 return WebContentsImpl::CreateWithOpener(params
, NULL
);
253 WebContents
* WebContents::CreateWithSessionStorage(
254 const WebContents::CreateParams
& params
,
255 const SessionStorageNamespaceMap
& session_storage_namespace_map
) {
256 WebContentsImpl
* new_contents
= new WebContentsImpl(
257 params
.browser_context
, NULL
);
259 for (SessionStorageNamespaceMap::const_iterator it
=
260 session_storage_namespace_map
.begin();
261 it
!= session_storage_namespace_map
.end();
263 new_contents
->GetController().SetSessionStorageNamespace(it
->first
,
267 new_contents
->Init(params
);
271 WebContents
* WebContents::FromRenderViewHost(const RenderViewHost
* rvh
) {
272 return rvh
->GetDelegate()->GetAsWebContents();
275 // WebContentsImpl -------------------------------------------------------------
277 WebContentsImpl::WebContentsImpl(
278 BrowserContext
* browser_context
,
279 WebContentsImpl
* opener
)
281 ALLOW_THIS_IN_INITIALIZER_LIST(controller_(this, browser_context
)),
282 render_view_host_delegate_view_(NULL
),
284 ALLOW_THIS_IN_INITIALIZER_LIST(render_manager_(this, this, this)),
286 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING
),
287 crashed_error_code_(0),
288 waiting_for_response_(false),
289 load_state_(net::LOAD_STATE_IDLE
, string16()),
292 displayed_insecure_content_(false),
294 should_normally_be_visible_(true),
295 is_being_destroyed_(false),
296 notify_disconnection_(false),
297 dialog_manager_(NULL
),
298 is_showing_before_unload_dialog_(false),
299 opener_web_ui_type_(WebUI::kNoWebUI
),
300 closed_by_user_gesture_(false),
301 minimum_zoom_percent_(static_cast<int>(kMinimumZoomFactor
* 100)),
302 maximum_zoom_percent_(static_cast<int>(kMaximumZoomFactor
* 100)),
303 temporary_zoom_settings_(false),
304 content_restrictions_(0),
305 color_chooser_(NULL
),
306 message_source_(NULL
),
307 fullscreen_widget_routing_id_(MSG_ROUTING_NONE
) {
310 WebContentsImpl::~WebContentsImpl() {
311 is_being_destroyed_
= true;
313 for (std::set
<RenderWidgetHostImpl
*>::iterator iter
=
314 created_widgets_
.begin(); iter
!= created_widgets_
.end(); ++iter
) {
315 (*iter
)->DetachDelegate();
317 created_widgets_
.clear();
319 // Clear out any JavaScript state.
321 dialog_manager_
->ResetJavaScriptState(this);
324 color_chooser_
->End();
326 NotifyDisconnected();
328 // Notify any observer that have a reference on this WebContents.
329 NotificationService::current()->Notify(
330 NOTIFICATION_WEB_CONTENTS_DESTROYED
,
331 Source
<WebContents
>(this),
332 NotificationService::NoDetails());
334 // TODO(brettw) this should be moved to the view.
335 #if defined(OS_WIN) && !defined(USE_AURA)
336 // If we still have a window handle, destroy it. GetNativeView can return
337 // NULL if this contents was part of a window that closed.
338 if (view_
->GetNativeView()) {
339 RenderViewHost
* host
= GetRenderViewHost();
340 if (host
&& host
->GetView())
341 RenderWidgetHostViewPort::FromRWHV(host
->GetView())->WillWmDestroy();
345 // OnCloseStarted isn't called in unit tests.
346 if (!close_start_time_
.is_null()) {
347 base::TimeTicks now
= base::TimeTicks::Now();
348 base::TimeTicks unload_start_time
= close_start_time_
;
349 if (!before_unload_end_time_
.is_null())
350 unload_start_time
= before_unload_end_time_
;
351 UMA_HISTOGRAM_TIMES("Tab.Close", now
- close_start_time_
);
352 UMA_HISTOGRAM_TIMES("Tab.Close.UnloadTime", now
- unload_start_time
);
355 FOR_EACH_OBSERVER(WebContentsObserver
,
357 WebContentsImplDestroyed());
362 WebContentsImpl
* WebContentsImpl::CreateWithOpener(
363 const WebContents::CreateParams
& params
,
364 WebContentsImpl
* opener
) {
365 WebContentsImpl
* new_contents
= new WebContentsImpl(
366 params
.browser_context
, opener
);
368 new_contents
->Init(params
);
373 BrowserPluginGuest
* WebContentsImpl::CreateGuest(
374 BrowserContext
* browser_context
,
375 SiteInstance
* site_instance
,
377 WebContentsImpl
* opener_web_contents
,
378 int guest_instance_id
,
379 const BrowserPluginHostMsg_CreateGuest_Params
& params
) {
381 WebContentsImpl
* new_contents
= new WebContentsImpl(browser_context
,
382 opener_web_contents
);
384 // This makes |new_contents| act as a guest.
385 // For more info, see comment above class BrowserPluginGuest.
386 new_contents
->browser_plugin_guest_
.reset(
387 BrowserPluginGuest::Create(
392 WebContents::CreateParams
create_params(browser_context
, site_instance
);
393 create_params
.routing_id
= routing_id
;
394 new_contents
->Init(create_params
);
396 // We are instantiating a WebContents for browser plugin. Set its subframe bit
398 static_cast<RenderViewHostImpl
*>(
399 new_contents
->GetRenderViewHost())->set_is_subframe(true);
401 return new_contents
->browser_plugin_guest_
.get();
404 WebPreferences
WebContentsImpl::GetWebkitPrefs(RenderViewHost
* rvh
,
406 WebPreferences prefs
;
408 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
410 prefs
.developer_extras_enabled
= true;
411 prefs
.javascript_enabled
=
412 !command_line
.HasSwitch(switches::kDisableJavaScript
);
413 prefs
.web_security_enabled
=
414 !command_line
.HasSwitch(switches::kDisableWebSecurity
);
415 prefs
.plugins_enabled
=
416 !command_line
.HasSwitch(switches::kDisablePlugins
);
418 !command_line
.HasSwitch(switches::kDisableJava
);
420 prefs
.uses_page_cache
=
421 command_line
.HasSwitch(switches::kEnableFastback
);
422 prefs
.remote_fonts_enabled
=
423 !command_line
.HasSwitch(switches::kDisableRemoteFonts
);
424 prefs
.xss_auditor_enabled
=
425 !command_line
.HasSwitch(switches::kDisableXSSAuditor
);
426 prefs
.application_cache_enabled
=
427 !command_line
.HasSwitch(switches::kDisableApplicationCache
);
429 prefs
.local_storage_enabled
=
430 !command_line
.HasSwitch(switches::kDisableLocalStorage
);
431 prefs
.databases_enabled
=
432 !command_line
.HasSwitch(switches::kDisableDatabases
);
433 #if defined(OS_ANDROID)
434 prefs
.webaudio_enabled
=
435 command_line
.HasSwitch(switches::kEnableWebAudio
);
437 prefs
.webaudio_enabled
=
438 !command_line
.HasSwitch(switches::kDisableWebAudio
);
441 prefs
.experimental_webgl_enabled
=
442 GpuProcessHost::gpu_enabled() &&
443 !command_line
.HasSwitch(switches::kDisable3DAPIs
) &&
444 #if defined(OS_ANDROID)
445 command_line
.HasSwitch(switches::kEnableExperimentalWebGL
);
447 !command_line
.HasSwitch(switches::kDisableExperimentalWebGL
);
450 prefs
.flash_3d_enabled
=
451 GpuProcessHost::gpu_enabled() &&
452 !command_line
.HasSwitch(switches::kDisableFlash3d
);
453 prefs
.flash_stage3d_enabled
=
454 GpuProcessHost::gpu_enabled() &&
455 !command_line
.HasSwitch(switches::kDisableFlashStage3d
);
456 prefs
.flash_stage3d_baseline_enabled
=
457 GpuProcessHost::gpu_enabled() &&
458 !command_line
.HasSwitch(switches::kDisableFlashStage3d
);
460 prefs
.gl_multisampling_enabled
=
461 !command_line
.HasSwitch(switches::kDisableGLMultisampling
);
462 prefs
.privileged_webgl_extensions_enabled
=
463 command_line
.HasSwitch(switches::kEnablePrivilegedWebGLExtensions
);
464 prefs
.site_specific_quirks_enabled
=
465 !command_line
.HasSwitch(switches::kDisableSiteSpecificQuirks
);
466 prefs
.allow_file_access_from_file_urls
=
467 command_line
.HasSwitch(switches::kAllowFileAccessFromFiles
);
469 prefs
.accelerated_compositing_for_overflow_scroll_enabled
= false;
470 if (command_line
.HasSwitch(switches::kEnableAcceleratedOverflowScroll
))
471 prefs
.accelerated_compositing_for_overflow_scroll_enabled
= true;
472 if (command_line
.HasSwitch(switches::kDisableAcceleratedOverflowScroll
))
473 prefs
.accelerated_compositing_for_overflow_scroll_enabled
= false;
475 prefs
.accelerated_compositing_for_scrollable_frames_enabled
=
476 command_line
.HasSwitch(switches::kEnableAcceleratedScrollableFrames
);
477 prefs
.composited_scrolling_for_frames_enabled
=
478 command_line
.HasSwitch(switches::kEnableCompositedScrollingForFrames
);
479 prefs
.show_paint_rects
=
480 command_line
.HasSwitch(switches::kShowPaintRects
);
481 prefs
.accelerated_compositing_enabled
=
482 GpuProcessHost::gpu_enabled() &&
483 !command_line
.HasSwitch(switches::kDisableAcceleratedCompositing
);
484 prefs
.force_compositing_mode
=
485 content::IsForceCompositingModeEnabled() &&
486 !command_line
.HasSwitch(switches::kDisableForceCompositingMode
);
487 prefs
.accelerated_2d_canvas_enabled
=
488 GpuProcessHost::gpu_enabled() &&
489 !command_line
.HasSwitch(switches::kDisableAccelerated2dCanvas
);
490 prefs
.deferred_2d_canvas_enabled
=
491 !command_line
.HasSwitch(switches::kDisableDeferred2dCanvas
);
492 prefs
.antialiased_2d_canvas_disabled
=
493 command_line
.HasSwitch(switches::kDisable2dCanvasAntialiasing
);
494 prefs
.accelerated_filters_enabled
=
495 GpuProcessHost::gpu_enabled() &&
496 command_line
.HasSwitch(switches::kEnableAcceleratedFilters
);
497 prefs
.accelerated_compositing_for_3d_transforms_enabled
=
498 prefs
.accelerated_compositing_for_animation_enabled
=
499 !command_line
.HasSwitch(switches::kDisableAcceleratedLayers
);
500 prefs
.accelerated_compositing_for_plugins_enabled
=
501 !command_line
.HasSwitch(switches::kDisableAcceleratedPlugins
);
502 prefs
.accelerated_compositing_for_video_enabled
=
503 !command_line
.HasSwitch(switches::kDisableAcceleratedVideo
);
504 prefs
.fullscreen_enabled
=
505 !command_line
.HasSwitch(switches::kDisableFullScreen
);
506 prefs
.css_sticky_position_enabled
=
507 command_line
.HasSwitch(switches::kEnableExperimentalWebKitFeatures
);
508 prefs
.css_shaders_enabled
=
509 command_line
.HasSwitch(switches::kEnableCssShaders
);
510 prefs
.css_variables_enabled
=
511 command_line
.HasSwitch(switches::kEnableExperimentalWebKitFeatures
);
512 prefs
.css_grid_layout_enabled
=
513 command_line
.HasSwitch(switches::kEnableExperimentalWebKitFeatures
);
514 prefs
.threaded_html_parser
=
515 !command_line
.HasSwitch(switches::kDisableThreadedHTMLParser
);
516 #if defined(OS_ANDROID)
517 prefs
.user_gesture_required_for_media_playback
= !command_line
.HasSwitch(
518 switches::kDisableGestureRequirementForMediaPlayback
);
521 bool touch_device_present
= false;
522 touch_device_present
= ui::IsTouchDevicePresent();
523 const std::string touch_enabled_switch
=
524 command_line
.HasSwitch(switches::kTouchEvents
) ?
525 command_line
.GetSwitchValueASCII(switches::kTouchEvents
) :
526 switches::kTouchEventsAuto
;
528 if (touch_enabled_switch
.empty() ||
529 touch_enabled_switch
== switches::kTouchEventsEnabled
) {
530 prefs
.touch_enabled
= true;
531 } else if (touch_enabled_switch
== switches::kTouchEventsAuto
) {
532 prefs
.touch_enabled
= touch_device_present
;
533 } else if (touch_enabled_switch
!= switches::kTouchEventsDisabled
) {
534 LOG(ERROR
) << "Invalid --touch-events option: " << touch_enabled_switch
;
537 prefs
.device_supports_touch
= prefs
.touch_enabled
&& touch_device_present
;
538 #if defined(OS_ANDROID)
539 prefs
.device_supports_mouse
= false;
542 prefs
.touch_adjustment_enabled
=
543 !command_line
.HasSwitch(switches::kDisableTouchAdjustment
);
545 #if defined(OS_MACOSX) || defined(OS_CHROMEOS)
546 bool default_enable_scroll_animator
= true;
548 bool default_enable_scroll_animator
= false;
550 prefs
.enable_scroll_animator
= default_enable_scroll_animator
;
551 if (command_line
.HasSwitch(switches::kEnableSmoothScrolling
))
552 prefs
.enable_scroll_animator
= true;
553 if (command_line
.HasSwitch(switches::kDisableSmoothScrolling
))
554 prefs
.enable_scroll_animator
= false;
556 prefs
.visual_word_movement_enabled
=
557 command_line
.HasSwitch(switches::kEnableVisualWordMovement
);
559 { // Certain GPU features might have been blacklisted.
560 GpuDataManagerImpl
* gpu_data_manager
= GpuDataManagerImpl::GetInstance();
561 DCHECK(gpu_data_manager
);
562 uint32 blacklist_type
= gpu_data_manager
->GetBlacklistedFeatures();
563 if (blacklist_type
& GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING
)
564 prefs
.accelerated_compositing_enabled
= false;
565 if (blacklist_type
& GPU_FEATURE_TYPE_WEBGL
)
566 prefs
.experimental_webgl_enabled
= false;
567 if (blacklist_type
& GPU_FEATURE_TYPE_FLASH3D
)
568 prefs
.flash_3d_enabled
= false;
569 if (blacklist_type
& GPU_FEATURE_TYPE_FLASH_STAGE3D
) {
570 prefs
.flash_stage3d_enabled
= false;
571 prefs
.flash_stage3d_baseline_enabled
= false;
573 if (blacklist_type
& GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE
)
574 prefs
.flash_stage3d_baseline_enabled
= false;
575 if (blacklist_type
& GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS
)
576 prefs
.accelerated_2d_canvas_enabled
= false;
577 if (blacklist_type
& GPU_FEATURE_TYPE_MULTISAMPLING
)
578 prefs
.gl_multisampling_enabled
= false;
579 if (blacklist_type
& GPU_FEATURE_TYPE_3D_CSS
) {
580 prefs
.accelerated_compositing_for_3d_transforms_enabled
= false;
581 prefs
.accelerated_compositing_for_animation_enabled
= false;
583 if (blacklist_type
& GPU_FEATURE_TYPE_ACCELERATED_VIDEO
)
584 prefs
.accelerated_compositing_for_video_enabled
= false;
586 // Accelerated video and animation are slower than regular when using a
587 // software 3d rasterizer. 3D CSS may also be too slow to be worthwhile.
588 if (gpu_data_manager
->ShouldUseSoftwareRendering()) {
589 prefs
.accelerated_compositing_for_video_enabled
= false;
590 prefs
.accelerated_compositing_for_animation_enabled
= false;
591 prefs
.accelerated_compositing_for_3d_transforms_enabled
= false;
592 prefs
.accelerated_compositing_for_plugins_enabled
= false;
596 if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
597 rvh
->GetProcess()->GetID())) {
598 prefs
.loads_images_automatically
= true;
599 prefs
.javascript_enabled
= true;
602 prefs
.is_online
= !net::NetworkChangeNotifier::IsOffline();
604 // Force accelerated compositing and 2d canvas off for chrome: and about:
605 // pages (unless it's specifically allowed).
606 if ((url
.SchemeIs(chrome::kChromeUIScheme
) ||
607 (url
.SchemeIs(chrome::kAboutScheme
) &&
608 url
.spec() != chrome::kAboutBlankURL
)) &&
609 !command_line
.HasSwitch(switches::kAllowWebUICompositing
)) {
610 prefs
.accelerated_compositing_enabled
= false;
611 prefs
.accelerated_2d_canvas_enabled
= false;
614 prefs
.apply_default_device_scale_factor_in_compositor
= true;
615 prefs
.apply_page_scale_factor_in_compositor
= true;
617 prefs
.fixed_position_creates_stacking_context
= !command_line
.HasSwitch(
618 switches::kDisableFixedPositionCreatesStackingContext
);
620 #if defined(OS_CHROMEOS)
621 prefs
.gesture_tap_highlight_enabled
= !command_line
.HasSwitch(
622 switches::kDisableGestureTapHighlight
);
624 prefs
.gesture_tap_highlight_enabled
= command_line
.HasSwitch(
625 switches::kEnableGestureTapHighlight
);
628 prefs
.number_of_cpu_cores
= base::SysInfo::NumberOfProcessors();
630 prefs
.viewport_enabled
= command_line
.HasSwitch(switches::kEnableViewport
);
632 prefs
.deferred_image_decoding_enabled
=
633 command_line
.HasSwitch(switches::kEnableDeferredImageDecoding
) ||
634 cc::switches::IsImplSidePaintingEnabled();
636 GetContentClient()->browser()->OverrideWebkitPrefs(rvh
, url
, &prefs
);
638 // Disable compositing in guests until we have compositing path implemented
640 bool guest_compositing_enabled
= !command_line
.HasSwitch(
641 switches::kDisableBrowserPluginCompositing
);
642 if (rvh
->GetProcess()->IsGuest() && !guest_compositing_enabled
) {
643 prefs
.force_compositing_mode
= false;
644 prefs
.accelerated_compositing_enabled
= false;
647 #if defined(OS_LINUX) && !defined(USE_AURA)
648 // Temporary fix for Linux non-Aura capturing. http://crbug.com/174957
649 WebContentsImpl
* web_contents
=
650 static_cast<WebContentsImpl
*>(WebContents::FromRenderViewHost(rvh
));
651 if (web_contents
&& web_contents
->capturer_count_
> 0) {
652 prefs
.accelerated_compositing_enabled
= false;
659 RenderViewHostManager
* WebContentsImpl::GetRenderManagerForTesting() {
660 return &render_manager_
;
663 bool WebContentsImpl::OnMessageReceived(RenderViewHost
* render_view_host
,
664 const IPC::Message
& message
) {
666 static_cast<WebUIImpl
*>(GetWebUI())->OnMessageReceived(message
)) {
670 ObserverListBase
<WebContentsObserver
>::Iterator
it(observers_
);
671 WebContentsObserver
* observer
;
672 while ((observer
= it
.GetNext()) != NULL
)
673 if (observer
->OnMessageReceived(message
))
676 // Message handlers should be aware of which RenderViewHost sent the
677 // message, which is temporarily stored in message_source_.
678 message_source_
= render_view_host
;
680 bool message_is_ok
= true;
681 IPC_BEGIN_MESSAGE_MAP_EX(WebContentsImpl
, message
, message_is_ok
)
682 IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache
,
683 OnDidLoadResourceFromMemoryCache
)
684 IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent
,
685 OnDidDisplayInsecureContent
)
686 IPC_MESSAGE_HANDLER(ViewHostMsg_DidRunInsecureContent
,
687 OnDidRunInsecureContent
)
688 IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentLoadedInFrame
,
689 OnDocumentLoadedInFrame
)
690 IPC_MESSAGE_HANDLER(ViewHostMsg_DidFinishLoad
, OnDidFinishLoad
)
691 IPC_MESSAGE_HANDLER(ViewHostMsg_DidFailLoadWithError
,
692 OnDidFailLoadWithError
)
693 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateContentRestrictions
,
694 OnUpdateContentRestrictions
)
695 IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset
, OnGoToEntryAtOffset
)
696 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits
, OnUpdateZoomLimits
)
697 IPC_MESSAGE_HANDLER(ViewHostMsg_SaveURLAs
, OnSaveURL
)
698 IPC_MESSAGE_HANDLER(ViewHostMsg_EnumerateDirectory
, OnEnumerateDirectory
)
699 IPC_MESSAGE_HANDLER(ViewHostMsg_JSOutOfMemory
, OnJSOutOfMemory
)
700 IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler
,
701 OnRegisterProtocolHandler
)
702 IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply
, OnFindReply
)
703 IPC_MESSAGE_HANDLER(ViewHostMsg_CrashedPlugin
, OnCrashedPlugin
)
704 IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed
, OnAppCacheAccessed
)
705 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenColorChooser
, OnOpenColorChooser
)
706 IPC_MESSAGE_HANDLER(ViewHostMsg_EndColorChooser
, OnEndColorChooser
)
707 IPC_MESSAGE_HANDLER(ViewHostMsg_SetSelectedColorInColorChooser
,
708 OnSetSelectedColorInColorChooser
)
709 IPC_MESSAGE_HANDLER(ViewHostMsg_PepperPluginHung
, OnPepperPluginHung
)
710 IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend
, OnWebUISend
)
711 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission
,
712 OnRequestPpapiBrokerPermission
)
713 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_AllocateInstanceID
,
714 OnBrowserPluginAllocateInstanceID
)
715 IPC_MESSAGE_HANDLER(IconHostMsg_DidDownloadFavicon
, OnDidDownloadFavicon
)
716 IPC_MESSAGE_HANDLER(IconHostMsg_UpdateFaviconURL
, OnUpdateFaviconURL
)
717 #if defined(OS_ANDROID)
718 IPC_MESSAGE_HANDLER(ViewHostMsg_FindMatchRects_Reply
,
719 OnFindMatchRectsReply
)
720 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog
,
721 OnOpenDateTimeDialog
)
723 IPC_MESSAGE_HANDLER(ViewHostMsg_FrameDetached
, OnFrameDetached
)
724 IPC_MESSAGE_UNHANDLED(handled
= false)
725 IPC_END_MESSAGE_MAP_EX()
726 message_source_
= NULL
;
728 if (!message_is_ok
) {
729 RecordAction(UserMetricsAction("BadMessageTerminate_RVD"));
730 GetRenderProcessHost()->ReceivedBadMessage();
736 void WebContentsImpl::RunFileChooser(
737 RenderViewHost
* render_view_host
,
738 const FileChooserParams
& params
) {
740 delegate_
->RunFileChooser(this, params
);
743 NavigationControllerImpl
& WebContentsImpl::GetController() {
747 const NavigationControllerImpl
& WebContentsImpl::GetController() const {
751 BrowserContext
* WebContentsImpl::GetBrowserContext() const {
752 return controller_
.GetBrowserContext();
755 const GURL
& WebContentsImpl::GetURL() const {
756 // We may not have a navigation entry yet
757 NavigationEntry
* entry
= controller_
.GetActiveEntry();
758 return entry
? entry
->GetVirtualURL() : GURL::EmptyGURL();
761 WebContentsDelegate
* WebContentsImpl::GetDelegate() {
765 void WebContentsImpl::SetDelegate(WebContentsDelegate
* delegate
) {
766 // TODO(cbentzel): remove this debugging code?
767 if (delegate
== delegate_
)
770 delegate_
->Detach(this);
771 delegate_
= delegate
;
773 delegate_
->Attach(this);
774 // Ensure the visible RVH reflects the new delegate's preferences.
775 RenderViewHostImpl
* host
= render_manager_
.current_host();
777 host
->SetOverscrollControllerEnabled(delegate
->CanOverscrollContent());
781 RenderProcessHost
* WebContentsImpl::GetRenderProcessHost() const {
782 RenderViewHostImpl
* host
= render_manager_
.current_host();
783 return host
? host
->GetProcess() : NULL
;
786 RenderViewHost
* WebContentsImpl::GetRenderViewHost() const {
787 return render_manager_
.current_host();
790 void WebContentsImpl::GetRenderViewHostAtPosition(
793 const base::Callback
<void(RenderViewHost
*, int, int)>& callback
) {
794 BrowserPluginEmbedder
* embedder
= GetBrowserPluginEmbedder();
796 embedder
->GetRenderViewHostAtPosition(x
, y
, callback
);
798 callback
.Run(GetRenderViewHost(), x
, y
);
801 WebContents
* WebContentsImpl::GetEmbedderWebContents() const {
802 BrowserPluginGuest
* guest
= GetBrowserPluginGuest();
804 return guest
->embedder_web_contents();
808 int WebContentsImpl::GetEmbeddedInstanceID() const {
809 BrowserPluginGuest
* guest
= GetBrowserPluginGuest();
811 return guest
->instance_id();
815 int WebContentsImpl::GetRoutingID() const {
816 if (!GetRenderViewHost())
817 return MSG_ROUTING_NONE
;
819 return GetRenderViewHost()->GetRoutingID();
822 int WebContentsImpl::GetFullscreenWidgetRoutingID() const {
823 return fullscreen_widget_routing_id_
;
826 RenderWidgetHostView
* WebContentsImpl::GetRenderWidgetHostView() const {
827 return render_manager_
.GetRenderWidgetHostView();
830 RenderWidgetHostViewPort
* WebContentsImpl::GetRenderWidgetHostViewPort() const {
831 BrowserPluginGuest
* guest
= GetBrowserPluginGuest();
832 if (guest
&& guest
->embedder_web_contents()) {
833 return guest
->embedder_web_contents()->GetRenderWidgetHostViewPort();
835 return RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
838 WebContentsView
* WebContentsImpl::GetView() const {
842 WebUI
* WebContentsImpl::CreateWebUI(const GURL
& url
) {
843 WebUIImpl
* web_ui
= new WebUIImpl(this);
844 WebUIController
* controller
= WebUIControllerFactoryRegistry::GetInstance()->
845 CreateWebUIControllerForURL(web_ui
, url
);
847 web_ui
->AddMessageHandler(new GenericHandler());
848 web_ui
->SetController(controller
);
856 WebUI
* WebContentsImpl::GetWebUI() const {
857 return render_manager_
.web_ui() ? render_manager_
.web_ui()
858 : render_manager_
.pending_web_ui();
861 WebUI
* WebContentsImpl::GetCommittedWebUI() const {
862 return render_manager_
.web_ui();
865 void WebContentsImpl::SetUserAgentOverride(const std::string
& override
) {
866 if (GetUserAgentOverride() == override
)
869 renderer_preferences_
.user_agent_override
= override
;
871 // Send the new override string to the renderer.
872 RenderViewHost
* host
= GetRenderViewHost();
874 host
->SyncRendererPrefs();
876 // Reload the page if a load is currently in progress to avoid having
877 // different parts of the page loaded using different user agents.
878 NavigationEntry
* entry
= controller_
.GetActiveEntry();
879 if (is_loading_
&& entry
!= NULL
&& entry
->GetIsOverridingUserAgent())
880 controller_
.ReloadIgnoringCache(true);
882 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
883 UserAgentOverrideSet(override
));
886 const std::string
& WebContentsImpl::GetUserAgentOverride() const {
887 return renderer_preferences_
.user_agent_override
;
890 const string16
& WebContentsImpl::GetTitle() const {
891 // Transient entries take precedence. They are used for interstitial pages
892 // that are shown on top of existing pages.
893 NavigationEntry
* entry
= controller_
.GetTransientEntry();
894 std::string accept_languages
=
895 GetContentClient()->browser()->GetAcceptLangs(
896 GetBrowserContext());
898 return entry
->GetTitleForDisplay(accept_languages
);
900 WebUI
* our_web_ui
= render_manager_
.pending_web_ui() ?
901 render_manager_
.pending_web_ui() : render_manager_
.web_ui();
903 // Don't override the title in view source mode.
904 entry
= controller_
.GetActiveEntry();
905 if (!(entry
&& entry
->IsViewSourceMode())) {
906 // Give the Web UI the chance to override our title.
907 const string16
& title
= our_web_ui
->GetOverriddenTitle();
913 // We use the title for the last committed entry rather than a pending
914 // navigation entry. For example, when the user types in a URL, we want to
915 // keep the old page's title until the new load has committed and we get a new
917 entry
= controller_
.GetLastCommittedEntry();
919 return entry
->GetTitleForDisplay(accept_languages
);
922 // |page_title_when_no_navigation_entry_| is finally used
923 // if no title cannot be retrieved.
924 return page_title_when_no_navigation_entry_
;
927 int32
WebContentsImpl::GetMaxPageID() {
928 return GetMaxPageIDForSiteInstance(GetSiteInstance());
931 int32
WebContentsImpl::GetMaxPageIDForSiteInstance(
932 SiteInstance
* site_instance
) {
933 if (max_page_ids_
.find(site_instance
->GetId()) == max_page_ids_
.end())
934 max_page_ids_
[site_instance
->GetId()] = -1;
936 return max_page_ids_
[site_instance
->GetId()];
939 void WebContentsImpl::UpdateMaxPageID(int32 page_id
) {
940 UpdateMaxPageIDForSiteInstance(GetSiteInstance(), page_id
);
943 void WebContentsImpl::UpdateMaxPageIDForSiteInstance(
944 SiteInstance
* site_instance
, int32 page_id
) {
945 if (GetMaxPageIDForSiteInstance(site_instance
) < page_id
)
946 max_page_ids_
[site_instance
->GetId()] = page_id
;
949 void WebContentsImpl::CopyMaxPageIDsFrom(WebContentsImpl
* web_contents
) {
950 max_page_ids_
= web_contents
->max_page_ids_
;
953 SiteInstance
* WebContentsImpl::GetSiteInstance() const {
954 return render_manager_
.current_host()->GetSiteInstance();
957 SiteInstance
* WebContentsImpl::GetPendingSiteInstance() const {
958 RenderViewHost
* dest_rvh
= render_manager_
.pending_render_view_host() ?
959 render_manager_
.pending_render_view_host() :
960 render_manager_
.current_host();
961 return dest_rvh
->GetSiteInstance();
964 bool WebContentsImpl::IsLoading() const {
968 bool WebContentsImpl::IsWaitingForResponse() const {
969 return waiting_for_response_
;
972 const net::LoadStateWithParam
& WebContentsImpl::GetLoadState() const {
976 const string16
& WebContentsImpl::GetLoadStateHost() const {
977 return load_state_host_
;
980 uint64
WebContentsImpl::GetUploadSize() const {
984 uint64
WebContentsImpl::GetUploadPosition() const {
985 return upload_position_
;
988 const std::string
& WebContentsImpl::GetEncoding() const {
992 bool WebContentsImpl::DisplayedInsecureContent() const {
993 return displayed_insecure_content_
;
996 void WebContentsImpl::IncrementCapturerCount() {
997 DCHECK(!is_being_destroyed_
);
999 DVLOG(1) << "There are now " << capturer_count_
1000 << " capturing(s) of WebContentsImpl@" << this;
1002 #if defined(OS_LINUX) && !defined(USE_AURA)
1003 // Temporary fix for Linux non-Aura capturing. http://crbug.com/174957
1004 if (capturer_count_
== 1) {
1005 // Force a WebkitPreferences reload to disable compositing for snapshots.
1006 RenderViewHost
* rvh
= GetRenderViewHost();
1008 rvh
->UpdateWebkitPreferences(rvh
->GetWebkitPreferences());
1013 void WebContentsImpl::DecrementCapturerCount() {
1015 DVLOG(1) << "There are now " << capturer_count_
1016 << " capturing(s) of WebContentsImpl@" << this;
1017 DCHECK_LE(0, capturer_count_
);
1019 if (is_being_destroyed_
)
1022 #if defined(OS_LINUX) && !defined(USE_AURA)
1023 // Temporary fix for Linux non-Aura capturing. http://crbug.com/174957
1024 if (capturer_count_
== 0) {
1025 // Force a WebkitPreferences reload to re-enable compositing.
1026 RenderViewHost
* rvh
= GetRenderViewHost();
1028 rvh
->UpdateWebkitPreferences(rvh
->GetWebkitPreferences());
1032 // While capturer_count_ was greater than zero, the WasHidden() calls to RWHV
1033 // were being prevented. If there are no more capturers, make the call now.
1034 if (capturer_count_
== 0 && !should_normally_be_visible_
) {
1035 DVLOG(1) << "Executing delayed WasHidden().";
1040 bool WebContentsImpl::IsCrashed() const {
1041 return (crashed_status_
== base::TERMINATION_STATUS_PROCESS_CRASHED
||
1042 crashed_status_
== base::TERMINATION_STATUS_ABNORMAL_TERMINATION
||
1043 crashed_status_
== base::TERMINATION_STATUS_PROCESS_WAS_KILLED
);
1046 void WebContentsImpl::SetIsCrashed(base::TerminationStatus status
,
1048 if (status
== crashed_status_
)
1051 crashed_status_
= status
;
1052 crashed_error_code_
= error_code
;
1053 NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB
);
1056 base::TerminationStatus
WebContentsImpl::GetCrashedStatus() const {
1057 return crashed_status_
;
1060 bool WebContentsImpl::IsBeingDestroyed() const {
1061 return is_being_destroyed_
;
1064 void WebContentsImpl::NotifyNavigationStateChanged(unsigned changed_flags
) {
1066 delegate_
->NavigationStateChanged(this, changed_flags
);
1069 base::TimeTicks
WebContentsImpl::GetLastSelectedTime() const {
1070 return last_selected_time_
;
1073 void WebContentsImpl::WasShown() {
1074 controller_
.SetActive(true);
1075 RenderWidgetHostViewPort
* rwhv
=
1076 RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
1079 #if defined(OS_MACOSX)
1080 rwhv
->SetActive(true);
1084 last_selected_time_
= base::TimeTicks::Now();
1086 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, WasShown());
1088 // The resize rect might have changed while this was inactive -- send the new
1089 // one to make sure it's up to date.
1090 RenderViewHostImpl
* rvh
=
1091 static_cast<RenderViewHostImpl
*>(GetRenderViewHost());
1093 rvh
->ResizeRectChanged(GetRootWindowResizerRect());
1096 should_normally_be_visible_
= true;
1097 NotificationService::current()->Notify(
1098 NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED
,
1099 Source
<WebContents
>(this),
1100 Details
<const bool>(&should_normally_be_visible_
));
1103 void WebContentsImpl::WasHidden() {
1104 // If there are entities capturing screenshots or video (e.g., mirroring),
1105 // don't activate the "disable rendering" optimization.
1106 if (capturer_count_
== 0) {
1107 // |GetRenderViewHost()| can be NULL if the user middle clicks a link to
1108 // open a tab in the background, then closes the tab before selecting it.
1109 // This is because closing the tab calls WebContentsImpl::Destroy(), which
1110 // removes the |GetRenderViewHost()|; then when we actually destroy the
1111 // window, OnWindowPosChanged() notices and calls WasHidden() (which
1113 RenderWidgetHostViewPort
* rwhv
=
1114 RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
1119 should_normally_be_visible_
= false;
1120 NotificationService::current()->Notify(
1121 NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED
,
1122 Source
<WebContents
>(this),
1123 Details
<const bool>(&should_normally_be_visible_
));
1126 bool WebContentsImpl::NeedToFireBeforeUnload() {
1127 // TODO(creis): Should we fire even for interstitial pages?
1128 return WillNotifyDisconnection() &&
1129 !ShowingInterstitialPage() &&
1130 !static_cast<RenderViewHostImpl
*>(
1131 GetRenderViewHost())->SuddenTerminationAllowed();
1134 void WebContentsImpl::Stop() {
1135 render_manager_
.Stop();
1136 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, StopNavigation());
1139 WebContents
* WebContentsImpl::Clone() {
1140 // We use our current SiteInstance since the cloned entry will use it anyway.
1141 // We pass our own opener so that the cloned page can access it if it was
1143 CreateParams
create_params(GetBrowserContext(), GetSiteInstance());
1144 create_params
.initial_size
= view_
->GetContainerSize();
1145 WebContentsImpl
* tc
= CreateWithOpener(create_params
, opener_
);
1146 tc
->GetController().CopyStateFrom(controller_
);
1147 FOR_EACH_OBSERVER(WebContentsObserver
,
1149 DidCloneToNewWebContents(this, tc
));
1153 void WebContentsImpl::Observe(int type
,
1154 const NotificationSource
& source
,
1155 const NotificationDetails
& details
) {
1157 case NOTIFICATION_WEB_CONTENTS_DESTROYED
:
1158 OnWebContentsDestroyed(Source
<WebContents
>(source
).ptr());
1160 case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED
: {
1161 RenderWidgetHost
* host
= Source
<RenderWidgetHost
>(source
).ptr();
1162 for (PendingWidgetViews::iterator i
= pending_widget_views_
.begin();
1163 i
!= pending_widget_views_
.end(); ++i
) {
1164 if (host
->GetView() == i
->second
) {
1165 pending_widget_views_
.erase(i
);
1176 void WebContentsImpl::Init(const WebContents::CreateParams
& params
) {
1177 render_manager_
.Init(
1178 params
.browser_context
, params
.site_instance
, params
.routing_id
);
1180 view_
.reset(GetContentClient()->browser()->
1181 OverrideCreateWebContentsView(this, &render_view_host_delegate_view_
));
1183 CHECK(render_view_host_delegate_view_
);
1185 WebContentsViewDelegate
* delegate
=
1186 GetContentClient()->browser()->GetWebContentsViewDelegate(this);
1188 if (browser_plugin_guest_
.get()) {
1189 WebContentsViewPort
* platform_view
= CreateWebContentsView(
1190 this, delegate
, &render_view_host_delegate_view_
);
1192 WebContentsViewGuest
* rv
= new WebContentsViewGuest(
1193 this, browser_plugin_guest_
.get(), platform_view
);
1194 render_view_host_delegate_view_
= rv
;
1197 // Regular WebContentsView.
1198 view_
.reset(CreateWebContentsView(
1199 this, delegate
, &render_view_host_delegate_view_
));
1201 CHECK(render_view_host_delegate_view_
);
1205 gfx::Size initial_size
= params
.initial_size
;
1206 view_
->CreateView(initial_size
, params
.context
);
1208 // Listen for whether our opener gets destroyed.
1210 registrar_
.Add(this, NOTIFICATION_WEB_CONTENTS_DESTROYED
,
1211 Source
<WebContents
>(opener_
));
1214 registrar_
.Add(this,
1215 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED
,
1216 NotificationService::AllBrowserContextsAndSources());
1217 #if defined(ENABLE_JAVA_BRIDGE)
1218 java_bridge_dispatcher_host_manager_
.reset(
1219 new JavaBridgeDispatcherHostManager(this));
1222 #if defined(OS_ANDROID)
1223 date_time_chooser_
.reset(new DateTimeChooserAndroid());
1227 void WebContentsImpl::OnWebContentsDestroyed(WebContents
* web_contents
) {
1228 // Clear the opener if it has been closed.
1229 if (web_contents
== opener_
) {
1230 registrar_
.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED
,
1231 Source
<WebContents
>(opener_
));
1235 // Clear a pending contents that has been closed before being shown.
1236 for (PendingContents::iterator iter
= pending_contents_
.begin();
1237 iter
!= pending_contents_
.end();
1239 if (iter
->second
!= web_contents
)
1241 pending_contents_
.erase(iter
);
1242 registrar_
.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED
,
1243 Source
<WebContents
>(web_contents
));
1249 void WebContentsImpl::AddObserver(WebContentsObserver
* observer
) {
1250 observers_
.AddObserver(observer
);
1253 void WebContentsImpl::RemoveObserver(WebContentsObserver
* observer
) {
1254 observers_
.RemoveObserver(observer
);
1257 void WebContentsImpl::Activate() {
1259 delegate_
->ActivateContents(this);
1262 void WebContentsImpl::Deactivate() {
1264 delegate_
->DeactivateContents(this);
1267 void WebContentsImpl::LostCapture() {
1269 delegate_
->LostCapture();
1272 void WebContentsImpl::RenderWidgetDeleted(
1273 RenderWidgetHostImpl
* render_widget_host
) {
1274 if (is_being_destroyed_
) {
1275 // |created_widgets_| might have been destroyed.
1279 std::set
<RenderWidgetHostImpl
*>::iterator iter
=
1280 created_widgets_
.find(render_widget_host
);
1281 if (iter
!= created_widgets_
.end())
1282 created_widgets_
.erase(iter
);
1284 if (render_widget_host
&&
1285 render_widget_host
->GetRoutingID() == fullscreen_widget_routing_id_
) {
1286 FOR_EACH_OBSERVER(WebContentsObserver
,
1288 DidDestroyFullscreenWidget(
1289 fullscreen_widget_routing_id_
));
1290 fullscreen_widget_routing_id_
= MSG_ROUTING_NONE
;
1294 bool WebContentsImpl::PreHandleKeyboardEvent(
1295 const NativeWebKeyboardEvent
& event
,
1296 bool* is_keyboard_shortcut
) {
1298 delegate_
->PreHandleKeyboardEvent(this, event
, is_keyboard_shortcut
);
1301 void WebContentsImpl::HandleKeyboardEvent(const NativeWebKeyboardEvent
& event
) {
1303 delegate_
->HandleKeyboardEvent(this, event
);
1306 bool WebContentsImpl::PreHandleWheelEvent(
1307 const WebKit::WebMouseWheelEvent
& event
) {
1309 event
.wheelTicksY
&&
1310 (event
.modifiers
& WebKit::WebInputEvent::ControlKey
)) {
1311 delegate_
->ContentsZoomChange(event
.wheelTicksY
> 0);
1318 void WebContentsImpl::HandleMouseDown() {
1320 delegate_
->HandleMouseDown();
1323 void WebContentsImpl::HandleMouseUp() {
1325 delegate_
->HandleMouseUp();
1328 void WebContentsImpl::HandlePointerActivate() {
1330 delegate_
->HandlePointerActivate();
1333 void WebContentsImpl::HandleGestureBegin() {
1335 delegate_
->HandleGestureBegin();
1338 void WebContentsImpl::HandleGestureEnd() {
1340 delegate_
->HandleGestureEnd();
1343 void WebContentsImpl::ToggleFullscreenMode(bool enter_fullscreen
) {
1345 delegate_
->ToggleFullscreenModeForTab(this, enter_fullscreen
);
1348 bool WebContentsImpl::IsFullscreenForCurrentTab() const {
1349 return delegate_
? delegate_
->IsFullscreenForTabOrPending(this) : false;
1352 void WebContentsImpl::RequestToLockMouse(bool user_gesture
,
1353 bool last_unlocked_by_target
) {
1355 delegate_
->RequestToLockMouse(this, user_gesture
, last_unlocked_by_target
);
1357 GotResponseToLockMouseRequest(false);
1361 void WebContentsImpl::LostMouseLock() {
1363 delegate_
->LostMouseLock();
1366 void WebContentsImpl::CreateNewWindow(
1368 const ViewHostMsg_CreateWindow_Params
& params
,
1369 SessionStorageNamespace
* session_storage_namespace
) {
1370 if (delegate_
&& !delegate_
->ShouldCreateWebContents(
1371 this, route_id
, params
.window_container_type
, params
.frame_name
,
1372 params
.target_url
)) {
1373 GetRenderViewHost()->GetProcess()->ResumeRequestsForView(route_id
);
1377 // We usually create the new window in the same BrowsingInstance (group of
1378 // script-related windows), by passing in the current SiteInstance. However,
1379 // if the opener is being suppressed, we create a new SiteInstance in its own
1380 // BrowsingInstance.
1381 scoped_refptr
<SiteInstance
> site_instance
=
1382 params
.opener_suppressed
?
1383 SiteInstance::CreateForURL(GetBrowserContext(), params
.target_url
) :
1386 // Create the new web contents. This will automatically create the new
1387 // WebContentsView. In the future, we may want to create the view separately.
1388 WebContentsImpl
* new_contents
=
1389 new WebContentsImpl(GetBrowserContext(),
1390 params
.opener_suppressed
? NULL
: this);
1392 // We must assign the SessionStorageNamespace before calling Init().
1394 // http://crbug.com/142685
1395 const std::string
& partition_id
=
1396 GetContentClient()->browser()->
1397 GetStoragePartitionIdForSite(GetBrowserContext(),
1398 site_instance
->GetSiteURL());
1399 StoragePartition
* partition
=
1400 BrowserContext::GetStoragePartition(GetBrowserContext(),
1402 DOMStorageContextImpl
* dom_storage_context
=
1403 static_cast<DOMStorageContextImpl
*>(partition
->GetDOMStorageContext());
1404 SessionStorageNamespaceImpl
* session_storage_namespace_impl
=
1405 static_cast<SessionStorageNamespaceImpl
*>(session_storage_namespace
);
1406 CHECK(session_storage_namespace_impl
->IsFromContext(dom_storage_context
));
1407 new_contents
->GetController().SetSessionStorageNamespace(
1409 session_storage_namespace
);
1410 CreateParams
create_params(GetBrowserContext(), site_instance
);
1411 create_params
.routing_id
= route_id
;
1412 create_params
.initial_size
= view_
->GetContainerSize();
1413 create_params
.context
= view_
->GetNativeView();
1414 new_contents
->Init(create_params
);
1416 new_contents
->set_opener_web_ui_type(GetWebUITypeForCurrentState());
1418 if (!params
.opener_suppressed
) {
1419 WebContentsViewPort
* new_view
= new_contents
->view_
.get();
1421 // TODO(brettw): It seems bogus that we have to call this function on the
1422 // newly created object and give it one of its own member variables.
1423 new_view
->CreateViewForWidget(new_contents
->GetRenderViewHost());
1425 // Save the created window associated with the route so we can show it
1427 DCHECK_NE(MSG_ROUTING_NONE
, route_id
);
1428 pending_contents_
[route_id
] = new_contents
;
1429 registrar_
.Add(this, NOTIFICATION_WEB_CONTENTS_DESTROYED
,
1430 Source
<WebContents
>(new_contents
));
1434 delegate_
->WebContentsCreated(
1435 this, params
.opener_frame_id
, params
.target_url
, new_contents
);
1438 if (params
.opener_suppressed
) {
1439 // When the opener is suppressed, the original renderer cannot access the
1440 // new window. As a result, we need to show and navigate the window here.
1441 bool was_blocked
= false;
1443 gfx::Rect initial_pos
;
1444 delegate_
->AddNewContents(
1445 this, new_contents
, params
.disposition
, initial_pos
,
1446 params
.user_gesture
, &was_blocked
);
1449 OpenURLParams
open_params(params
.target_url
,
1452 PAGE_TRANSITION_LINK
,
1453 true /* is_renderer_initiated */);
1454 new_contents
->OpenURL(open_params
);
1459 void WebContentsImpl::CreateNewWidget(int route_id
,
1460 WebKit::WebPopupType popup_type
) {
1461 CreateNewWidget(route_id
, false, popup_type
);
1464 void WebContentsImpl::CreateNewFullscreenWidget(int route_id
) {
1465 CreateNewWidget(route_id
, true, WebKit::WebPopupTypeNone
);
1468 void WebContentsImpl::CreateNewWidget(int route_id
,
1470 WebKit::WebPopupType popup_type
) {
1471 RenderProcessHost
* process
= GetRenderProcessHost();
1472 RenderWidgetHostImpl
* widget_host
=
1473 new RenderWidgetHostImpl(this, process
, route_id
);
1474 created_widgets_
.insert(widget_host
);
1476 RenderWidgetHostViewPort
* widget_view
= RenderWidgetHostViewPort::FromRWHV(
1477 view_
->CreateViewForPopupWidget(widget_host
));
1480 if (!is_fullscreen
) {
1481 // Popups should not get activated.
1482 widget_view
->SetPopupType(popup_type
);
1484 // Save the created widget associated with the route so we can show it later.
1485 pending_widget_views_
[route_id
] = widget_view
;
1487 #if defined(OS_MACOSX)
1488 // A RenderWidgetHostViewMac has lifetime scoped to the view. We'll retain it
1489 // to allow it to survive the trip without being hosted.
1490 base::mac::NSObjectRetain(widget_view
->GetNativeView());
1494 void WebContentsImpl::ShowCreatedWindow(int route_id
,
1495 WindowOpenDisposition disposition
,
1496 const gfx::Rect
& initial_pos
,
1497 bool user_gesture
) {
1498 WebContentsImpl
* contents
= GetCreatedWindow(route_id
);
1500 WebContentsDelegate
* delegate
= GetDelegate();
1502 delegate
->AddNewContents(
1503 this, contents
, disposition
, initial_pos
, user_gesture
, NULL
);
1508 void WebContentsImpl::ShowCreatedWidget(int route_id
,
1509 const gfx::Rect
& initial_pos
) {
1510 ShowCreatedWidget(route_id
, false, initial_pos
);
1513 void WebContentsImpl::ShowCreatedFullscreenWidget(int route_id
) {
1514 ShowCreatedWidget(route_id
, true, gfx::Rect());
1516 DCHECK_EQ(MSG_ROUTING_NONE
, fullscreen_widget_routing_id_
);
1517 fullscreen_widget_routing_id_
= route_id
;
1518 FOR_EACH_OBSERVER(WebContentsObserver
,
1520 DidShowFullscreenWidget(route_id
));
1523 void WebContentsImpl::ShowCreatedWidget(int route_id
,
1525 const gfx::Rect
& initial_pos
) {
1527 delegate_
->RenderWidgetShowing();
1529 RenderWidgetHostViewPort
* widget_host_view
=
1530 RenderWidgetHostViewPort::FromRWHV(GetCreatedWidget(route_id
));
1531 if (!widget_host_view
)
1534 widget_host_view
->InitAsFullscreen(GetRenderWidgetHostViewPort());
1536 widget_host_view
->InitAsPopup(GetRenderWidgetHostViewPort(), initial_pos
);
1538 RenderWidgetHostImpl
* render_widget_host_impl
=
1539 RenderWidgetHostImpl::From(widget_host_view
->GetRenderWidgetHost());
1540 render_widget_host_impl
->Init();
1541 // Only allow privileged mouse lock for fullscreen render widget, which is
1542 // used to implement Pepper Flash fullscreen.
1543 render_widget_host_impl
->set_allow_privileged_mouse_lock(is_fullscreen
);
1545 #if defined(OS_MACOSX)
1546 // A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's
1547 // properly embedded (or purposefully ignored) we can release the retain we
1548 // took in CreateNewWidget().
1549 base::mac::NSObjectRelease(widget_host_view
->GetNativeView());
1553 WebContentsImpl
* WebContentsImpl::GetCreatedWindow(int route_id
) {
1554 PendingContents::iterator iter
= pending_contents_
.find(route_id
);
1556 // Certain systems can block the creation of new windows. If we didn't succeed
1557 // in creating one, just return NULL.
1558 if (iter
== pending_contents_
.end()) {
1562 WebContentsImpl
* new_contents
= iter
->second
;
1563 pending_contents_
.erase(route_id
);
1564 registrar_
.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED
,
1565 Source
<WebContents
>(new_contents
));
1567 if (!new_contents
->GetRenderProcessHost()->HasConnection() ||
1568 !new_contents
->GetRenderViewHost()->GetView())
1571 // TODO(brettw): It seems bogus to reach into here and initialize the host.
1572 static_cast<RenderViewHostImpl
*>(new_contents
->GetRenderViewHost())->Init();
1573 return new_contents
;
1576 RenderWidgetHostView
* WebContentsImpl::GetCreatedWidget(int route_id
) {
1577 PendingWidgetViews::iterator iter
= pending_widget_views_
.find(route_id
);
1578 if (iter
== pending_widget_views_
.end()) {
1583 RenderWidgetHostView
* widget_host_view
= iter
->second
;
1584 pending_widget_views_
.erase(route_id
);
1586 RenderWidgetHost
* widget_host
= widget_host_view
->GetRenderWidgetHost();
1587 if (!widget_host
->GetProcess()->HasConnection()) {
1588 // The view has gone away or the renderer crashed. Nothing to do.
1592 return widget_host_view
;
1595 void WebContentsImpl::ShowContextMenu(
1596 const ContextMenuParams
& params
,
1597 ContextMenuSourceType type
) {
1598 // Allow WebContentsDelegates to handle the context menu operation first.
1599 if (delegate_
&& delegate_
->HandleContextMenu(params
))
1602 render_view_host_delegate_view_
->ShowContextMenu(params
, type
);
1605 void WebContentsImpl::RequestMediaAccessPermission(
1606 const MediaStreamRequest
& request
,
1607 const MediaResponseCallback
& callback
) {
1609 delegate_
->RequestMediaAccessPermission(this, request
, callback
);
1611 callback
.Run(MediaStreamDevices());
1614 void WebContentsImpl::UpdatePreferredSize(const gfx::Size
& pref_size
) {
1615 preferred_size_
= pref_size
;
1617 delegate_
->UpdatePreferredSize(this, pref_size
);
1620 void WebContentsImpl::ResizeDueToAutoResize(const gfx::Size
& new_size
) {
1622 delegate_
->ResizeDueToAutoResize(this, new_size
);
1625 WebContents
* WebContentsImpl::OpenURL(const OpenURLParams
& params
) {
1629 WebContents
* new_contents
= delegate_
->OpenURLFromTab(this, params
);
1630 return new_contents
;
1633 bool WebContentsImpl::Send(IPC::Message
* message
) {
1634 if (!GetRenderViewHost()) {
1639 return GetRenderViewHost()->Send(message
);
1642 bool WebContentsImpl::NavigateToPendingEntry(
1643 NavigationController::ReloadType reload_type
) {
1644 return NavigateToEntry(
1645 *NavigationEntryImpl::FromNavigationEntry(controller_
.GetPendingEntry()),
1649 void WebContentsImpl::RenderViewForInterstitialPageCreated(
1650 RenderViewHost
* render_view_host
) {
1651 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
1652 RenderViewForInterstitialPageCreated(render_view_host
));
1655 void WebContentsImpl::AttachInterstitialPage(
1656 InterstitialPageImpl
* interstitial_page
) {
1657 DCHECK(interstitial_page
);
1658 render_manager_
.set_interstitial_page(interstitial_page
);
1659 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
1660 DidAttachInterstitialPage());
1663 void WebContentsImpl::DetachInterstitialPage() {
1664 if (GetInterstitialPage())
1665 render_manager_
.remove_interstitial_page();
1666 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
1667 DidDetachInterstitialPage());
1670 bool WebContentsImpl::NavigateToEntry(
1671 const NavigationEntryImpl
& entry
,
1672 NavigationController::ReloadType reload_type
) {
1673 // The renderer will reject IPC messages with URLs longer than
1674 // this limit, so don't attempt to navigate with a longer URL.
1675 if (entry
.GetURL().spec().size() > kMaxURLChars
)
1678 RenderViewHostImpl
* dest_render_view_host
=
1679 static_cast<RenderViewHostImpl
*>(render_manager_
.Navigate(entry
));
1680 if (!dest_render_view_host
)
1681 return false; // Unable to create the desired render view host.
1683 // For security, we should never send non-Web-UI URLs to a Web UI renderer.
1684 // Double check that here.
1685 int enabled_bindings
= dest_render_view_host
->GetEnabledBindings();
1686 bool data_urls_allowed
= delegate_
&& delegate_
->CanLoadDataURLsInWebUI();
1687 bool is_allowed_in_web_ui_renderer
=
1688 WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
1689 GetBrowserContext(), entry
.GetURL(), data_urls_allowed
);
1690 if ((enabled_bindings
& BINDINGS_POLICY_WEB_UI
) &&
1691 !is_allowed_in_web_ui_renderer
) {
1692 // Log the URL to help us diagnose any future failures of this CHECK.
1693 GetContentClient()->SetActiveURL(entry
.GetURL());
1697 // Notify observers that we will navigate in this RV.
1698 FOR_EACH_OBSERVER(WebContentsObserver
,
1700 AboutToNavigateRenderView(dest_render_view_host
));
1702 // Used for page load time metrics.
1703 current_load_start_
= base::TimeTicks::Now();
1705 // Navigate in the desired RenderViewHost.
1706 ViewMsg_Navigate_Params navigate_params
;
1707 MakeNavigateParams(entry
, controller_
, delegate_
, reload_type
,
1709 dest_render_view_host
->Navigate(navigate_params
);
1711 if (entry
.GetPageID() == -1) {
1712 // HACK!! This code suppresses javascript: URLs from being added to
1713 // session history, which is what we want to do for javascript: URLs that
1714 // do not generate content. What we really need is a message from the
1715 // renderer telling us that a new page was not created. The same message
1716 // could be used for mailto: URLs and the like.
1717 if (entry
.GetURL().SchemeIs(chrome::kJavaScriptScheme
))
1721 // Notify observers about navigation.
1722 FOR_EACH_OBSERVER(WebContentsObserver
,
1724 NavigateToPendingEntry(entry
.GetURL(), reload_type
));
1727 delegate_
->DidNavigateToPendingEntry(this);
1732 void WebContentsImpl::SetHistoryLengthAndPrune(
1733 const SiteInstance
* site_instance
,
1735 int32 minimum_page_id
) {
1736 // SetHistoryLengthAndPrune doesn't work when there are pending cross-site
1737 // navigations. Callers should ensure that this is the case.
1738 if (render_manager_
.pending_render_view_host()) {
1742 RenderViewHostImpl
* rvh
= GetRenderViewHostImpl();
1747 if (site_instance
&& rvh
->GetSiteInstance() != site_instance
) {
1751 Send(new ViewMsg_SetHistoryLengthAndPrune(GetRoutingID(),
1756 void WebContentsImpl::FocusThroughTabTraversal(bool reverse
) {
1757 if (ShowingInterstitialPage()) {
1758 render_manager_
.interstitial_page()->FocusThroughTabTraversal(reverse
);
1761 GetRenderViewHostImpl()->SetInitialFocus(reverse
);
1764 bool WebContentsImpl::ShowingInterstitialPage() const {
1765 return render_manager_
.interstitial_page() != NULL
;
1768 InterstitialPage
* WebContentsImpl::GetInterstitialPage() const {
1769 return render_manager_
.interstitial_page();
1772 bool WebContentsImpl::IsSavable() {
1773 // WebKit creates Document object when MIME type is application/xhtml+xml,
1774 // so we also support this MIME type.
1775 return contents_mime_type_
== "text/html" ||
1776 contents_mime_type_
== "text/xml" ||
1777 contents_mime_type_
== "application/xhtml+xml" ||
1778 contents_mime_type_
== "text/plain" ||
1779 contents_mime_type_
== "text/css" ||
1780 net::IsSupportedJavascriptMimeType(contents_mime_type_
.c_str());
1783 void WebContentsImpl::OnSavePage() {
1784 // If we can not save the page, try to download it.
1786 RecordDownloadSource(INITIATED_BY_SAVE_PACKAGE_ON_NON_HTML
);
1787 SaveURL(GetURL(), Referrer(), true);
1793 // Create the save package and possibly prompt the user for the name to save
1794 // the page as. The user prompt is an asynchronous operation that runs on
1796 save_package_
= new SavePackage(this);
1797 save_package_
->GetSaveInfo();
1800 // Used in automated testing to bypass prompting the user for file names.
1801 // Instead, the names and paths are hard coded rather than running them through
1802 // file name sanitation and extension / mime checking.
1803 bool WebContentsImpl::SavePage(const base::FilePath
& main_file
,
1804 const base::FilePath
& dir_path
,
1805 SavePageType save_type
) {
1806 // Stop the page from navigating.
1809 save_package_
= new SavePackage(this, save_type
, main_file
, dir_path
);
1810 return save_package_
->Init(SavePackageDownloadCreatedCallback());
1813 void WebContentsImpl::GenerateMHTML(
1814 const base::FilePath
& file
,
1815 const base::Callback
<void(const base::FilePath
&, int64
)>& callback
) {
1816 MHTMLGenerationManager::GetInstance()->GenerateMHTML(this, file
, callback
);
1819 bool WebContentsImpl::IsActiveEntry(int32 page_id
) {
1820 NavigationEntryImpl
* active_entry
=
1821 NavigationEntryImpl::FromNavigationEntry(controller_
.GetActiveEntry());
1822 return (active_entry
!= NULL
&&
1823 active_entry
->site_instance() == GetSiteInstance() &&
1824 active_entry
->GetPageID() == page_id
);
1827 const std::string
& WebContentsImpl::GetContentsMimeType() const {
1828 return contents_mime_type_
;
1831 bool WebContentsImpl::WillNotifyDisconnection() const {
1832 return notify_disconnection_
;
1835 void WebContentsImpl::SetOverrideEncoding(const std::string
& encoding
) {
1836 SetEncoding(encoding
);
1837 Send(new ViewMsg_SetPageEncoding(GetRoutingID(), encoding
));
1840 void WebContentsImpl::ResetOverrideEncoding() {
1842 Send(new ViewMsg_ResetPageEncodingToDefault(GetRoutingID()));
1845 RendererPreferences
* WebContentsImpl::GetMutableRendererPrefs() {
1846 return &renderer_preferences_
;
1849 void WebContentsImpl::SetNewTabStartTime(const base::TimeTicks
& time
) {
1850 new_tab_start_time_
= time
;
1853 base::TimeTicks
WebContentsImpl::GetNewTabStartTime() const {
1854 return new_tab_start_time_
;
1857 void WebContentsImpl::Close() {
1858 Close(GetRenderViewHost());
1861 void WebContentsImpl::OnCloseStarted() {
1862 if (close_start_time_
.is_null())
1863 close_start_time_
= base::TimeTicks::Now();
1866 bool WebContentsImpl::ShouldAcceptDragAndDrop() const {
1867 #if defined(OS_CHROMEOS)
1868 // ChromeOS panels (pop-ups) do not take drag-n-drop.
1869 // See http://crosbug.com/2413
1870 if (delegate_
&& delegate_
->IsPopupOrPanel(this))
1878 void WebContentsImpl::SystemDragEnded() {
1879 if (GetRenderViewHost())
1880 GetRenderViewHostImpl()->DragSourceSystemDragEnded();
1882 delegate_
->DragEnded();
1885 void WebContentsImpl::UserGestureDone() {
1889 void WebContentsImpl::SetClosedByUserGesture(bool value
) {
1890 closed_by_user_gesture_
= value
;
1893 bool WebContentsImpl::GetClosedByUserGesture() const {
1894 return closed_by_user_gesture_
;
1897 double WebContentsImpl::GetZoomLevel() const {
1898 HostZoomMapImpl
* zoom_map
= static_cast<HostZoomMapImpl
*>(
1899 HostZoomMap::GetForBrowserContext(GetBrowserContext()));
1904 if (temporary_zoom_settings_
) {
1905 zoom_level
= zoom_map
->GetTemporaryZoomLevel(
1906 GetRenderProcessHost()->GetID(), GetRenderViewHost()->GetRoutingID());
1909 NavigationEntry
* active_entry
= GetController().GetActiveEntry();
1910 // Since zoom map is updated using rewritten URL, use rewritten URL
1911 // to get the zoom level.
1912 url
= active_entry
? active_entry
->GetURL() : GURL::EmptyGURL();
1913 zoom_level
= zoom_map
->GetZoomLevelForHostAndScheme(url
.scheme(),
1914 net::GetHostOrSpecFromURL(url
));
1919 int WebContentsImpl::GetZoomPercent(bool* enable_increment
,
1920 bool* enable_decrement
) const {
1921 *enable_decrement
= *enable_increment
= false;
1922 // Calculate the zoom percent from the factor. Round up to the nearest whole
1924 int percent
= static_cast<int>(
1925 WebKit::WebView::zoomLevelToZoomFactor(GetZoomLevel()) * 100 + 0.5);
1926 *enable_decrement
= percent
> minimum_zoom_percent_
;
1927 *enable_increment
= percent
< maximum_zoom_percent_
;
1931 void WebContentsImpl::ViewSource() {
1935 NavigationEntry
* active_entry
= GetController().GetActiveEntry();
1939 delegate_
->ViewSourceForTab(this, active_entry
->GetURL());
1942 void WebContentsImpl::ViewFrameSource(const GURL
& url
,
1943 const std::string
& content_state
) {
1947 delegate_
->ViewSourceForFrame(this, url
, content_state
);
1950 int WebContentsImpl::GetMinimumZoomPercent() const {
1951 return minimum_zoom_percent_
;
1954 int WebContentsImpl::GetMaximumZoomPercent() const {
1955 return maximum_zoom_percent_
;
1958 gfx::Size
WebContentsImpl::GetPreferredSize() const {
1959 return preferred_size_
;
1962 int WebContentsImpl::GetContentRestrictions() const {
1963 return content_restrictions_
;
1966 WebUI::TypeID
WebContentsImpl::GetWebUITypeForCurrentState() {
1967 return WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
1968 GetBrowserContext(), GetURL());
1971 WebUI
* WebContentsImpl::GetWebUIForCurrentState() {
1972 // When there is a pending navigation entry, we want to use the pending WebUI
1973 // that goes along with it to control the basic flags. For example, we want to
1974 // show the pending URL in the URL bar, so we want the display_url flag to
1975 // be from the pending entry.
1977 // The confusion comes because there are multiple possibilities for the
1978 // initial load in a tab as a side effect of the way the RenderViewHostManager
1981 // - For the very first tab the load looks "normal". The new tab Web UI is
1982 // the pending one, and we want it to apply here.
1984 // - For subsequent new tabs, they'll get a new SiteInstance which will then
1985 // get switched to the one previously associated with the new tab pages.
1986 // This switching will cause the manager to commit the RVH/WebUI. So we'll
1987 // have a committed Web UI in this case.
1989 // This condition handles all of these cases:
1991 // - First load in first tab: no committed nav entry + pending nav entry +
1993 // -> Use pending Web UI if any.
1995 // - First load in second tab: no committed nav entry + pending nav entry +
1996 // no pending Web UI:
1997 // -> Use the committed Web UI if any.
1999 // - Second navigation in any tab: committed nav entry + pending nav entry:
2000 // -> Use pending Web UI if any.
2002 // - Normal state with no load: committed nav entry + no pending nav entry:
2003 // -> Use committed Web UI.
2004 if (controller_
.GetPendingEntry() &&
2005 (controller_
.GetLastCommittedEntry() ||
2006 render_manager_
.pending_web_ui()))
2007 return render_manager_
.pending_web_ui();
2008 return render_manager_
.web_ui();
2011 bool WebContentsImpl::GotResponseToLockMouseRequest(bool allowed
) {
2012 return GetRenderViewHost() ?
2013 GetRenderViewHostImpl()->GotResponseToLockMouseRequest(allowed
) : false;
2016 bool WebContentsImpl::HasOpener() const {
2017 return opener_
!= NULL
;
2020 void WebContentsImpl::DidChooseColorInColorChooser(int color_chooser_id
,
2022 Send(new ViewMsg_DidChooseColorResponse(
2023 GetRoutingID(), color_chooser_id
, color
));
2026 void WebContentsImpl::DidEndColorChooser(int color_chooser_id
) {
2027 Send(new ViewMsg_DidEndColorChooser(GetRoutingID(), color_chooser_id
));
2029 delegate_
->DidEndColorChooser();
2030 color_chooser_
= NULL
;
2033 int WebContentsImpl::DownloadFavicon(const GURL
& url
, int image_size
,
2034 const FaviconDownloadCallback
& callback
) {
2035 RenderViewHost
* host
= GetRenderViewHost();
2036 int id
= StartDownload(host
, url
, image_size
);
2037 favicon_download_map_
[id
] = callback
;
2041 bool WebContentsImpl::FocusLocationBarByDefault() {
2042 WebUI
* web_ui
= GetWebUIForCurrentState();
2044 return web_ui
->ShouldFocusLocationBarByDefault();
2045 NavigationEntry
* entry
= controller_
.GetActiveEntry();
2046 if (entry
&& entry
->GetURL() == GURL(chrome::kAboutBlankURL
))
2048 return delegate_
&& delegate_
->ShouldFocusLocationBarByDefault(this);
2051 void WebContentsImpl::SetFocusToLocationBar(bool select_all
) {
2053 delegate_
->SetFocusToLocationBar(select_all
);
2056 void WebContentsImpl::DidStartProvisionalLoadForFrame(
2057 RenderViewHost
* render_view_host
,
2059 int64 parent_frame_id
,
2062 bool is_error_page
= (url
.spec() == kUnreachableWebDataURL
);
2063 bool is_iframe_srcdoc
= (url
.spec() == chrome::kAboutSrcDocURL
);
2064 GURL
validated_url(url
);
2065 RenderProcessHost
* render_process_host
=
2066 render_view_host
->GetProcess();
2067 RenderViewHost::FilterURL(render_process_host
, false, &validated_url
);
2070 DidChangeLoadProgress(0);
2072 // Notify observers about the start of the provisional load.
2073 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2074 DidStartProvisionalLoadForFrame(frame_id
, parent_frame_id
,
2075 is_main_frame
, validated_url
, is_error_page
,
2076 is_iframe_srcdoc
, render_view_host
));
2078 if (is_main_frame
) {
2079 // Notify observers about the provisional change in the main frame URL.
2080 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2081 ProvisionalChangeToMainFrameUrl(validated_url
,
2086 void WebContentsImpl::DidRedirectProvisionalLoad(
2087 RenderViewHost
* render_view_host
,
2089 const GURL
& source_url
,
2090 const GURL
& target_url
) {
2091 // TODO(creis): Remove this method and have the pre-rendering code listen to
2092 // the ResourceDispatcherHost's RESOURCE_RECEIVED_REDIRECT notification
2093 // instead. See http://crbug.com/78512.
2094 GURL
validated_source_url(source_url
);
2095 GURL
validated_target_url(target_url
);
2096 RenderProcessHost
* render_process_host
=
2097 render_view_host
->GetProcess();
2098 RenderViewHost::FilterURL(render_process_host
, false, &validated_source_url
);
2099 RenderViewHost::FilterURL(render_process_host
, false, &validated_target_url
);
2100 NavigationEntry
* entry
;
2101 if (page_id
== -1) {
2102 entry
= controller_
.GetPendingEntry();
2104 entry
= controller_
.GetEntryWithPageID(render_view_host
->GetSiteInstance(),
2107 if (!entry
|| entry
->GetURL() != validated_source_url
)
2110 // Notify observers about the provisional change in the main frame URL.
2111 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2112 ProvisionalChangeToMainFrameUrl(validated_target_url
,
2116 void WebContentsImpl::DidFailProvisionalLoadWithError(
2117 RenderViewHost
* render_view_host
,
2118 const ViewHostMsg_DidFailProvisionalLoadWithError_Params
& params
) {
2119 VLOG(1) << "Failed Provisional Load: " << params
.url
.possibly_invalid_spec()
2120 << ", error_code: " << params
.error_code
2121 << ", error_description: " << params
.error_description
2122 << ", is_main_frame: " << params
.is_main_frame
2123 << ", showing_repost_interstitial: " <<
2124 params
.showing_repost_interstitial
2125 << ", frame_id: " << params
.frame_id
;
2126 GURL
validated_url(params
.url
);
2127 RenderProcessHost
* render_process_host
=
2128 render_view_host
->GetProcess();
2129 RenderViewHost::FilterURL(render_process_host
, false, &validated_url
);
2131 if (net::ERR_ABORTED
== params
.error_code
) {
2132 // EVIL HACK ALERT! Ignore failed loads when we're showing interstitials.
2133 // This means that the interstitial won't be torn down properly, which is
2134 // bad. But if we have an interstitial, go back to another tab type, and
2135 // then load the same interstitial again, we could end up getting the first
2136 // interstitial's "failed" message (as a result of the cancel) when we're on
2139 // We can't tell this apart, so we think we're tearing down the current page
2140 // which will cause a crash later one. There is also some code in
2141 // RenderViewHostManager::RendererAbortedProvisionalLoad that is commented
2142 // out because of this problem.
2144 // http://code.google.com/p/chromium/issues/detail?id=2855
2145 // Because this will not tear down the interstitial properly, if "back" is
2146 // back to another tab type, the interstitial will still be somewhat alive
2147 // in the previous tab type. If you navigate somewhere that activates the
2148 // tab with the interstitial again, you'll see a flash before the new load
2149 // commits of the interstitial page.
2150 if (ShowingInterstitialPage()) {
2151 LOG(WARNING
) << "Discarding message during interstitial.";
2155 // Do not clear the pending entry if one exists, so that the user's typed
2156 // URL is not lost when a navigation fails or is aborted. We'll allow
2157 // the view to clear the pending entry and typed URL if the user requests.
2159 render_manager_
.RendererAbortedProvisionalLoad(render_view_host
);
2162 FOR_EACH_OBSERVER(WebContentsObserver
,
2164 DidFailProvisionalLoad(params
.frame_id
,
2165 params
.is_main_frame
,
2168 params
.error_description
,
2172 void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
2174 const std::string
& security_info
,
2175 const std::string
& http_method
,
2176 const std::string
& mime_type
,
2177 ResourceType::Type resource_type
) {
2178 base::StatsCounter
cache("WebKit.CacheHit");
2181 // Send out a notification that we loaded a resource from our memory cache.
2183 net::CertStatus cert_status
= 0;
2184 int security_bits
= -1;
2185 int connection_status
= 0;
2186 DeserializeSecurityInfo(security_info
, &cert_id
, &cert_status
,
2187 &security_bits
, &connection_status
);
2188 LoadFromMemoryCacheDetails
details(
2189 url
, GetRenderProcessHost()->GetID(), cert_id
, cert_status
, http_method
,
2190 mime_type
, resource_type
);
2192 NotificationService::current()->Notify(
2193 NOTIFICATION_LOAD_FROM_MEMORY_CACHE
,
2194 Source
<NavigationController
>(&controller_
),
2195 Details
<LoadFromMemoryCacheDetails
>(&details
));
2198 void WebContentsImpl::OnDidDisplayInsecureContent() {
2199 RecordAction(UserMetricsAction("SSL.DisplayedInsecureContent"));
2200 displayed_insecure_content_
= true;
2201 SSLManager::NotifySSLInternalStateChanged(
2202 GetController().GetBrowserContext());
2205 void WebContentsImpl::OnDidRunInsecureContent(
2206 const std::string
& security_origin
, const GURL
& target_url
) {
2207 LOG(INFO
) << security_origin
<< " ran insecure content from "
2208 << target_url
.possibly_invalid_spec();
2209 RecordAction(UserMetricsAction("SSL.RanInsecureContent"));
2210 if (EndsWith(security_origin
, kDotGoogleDotCom
, false))
2211 RecordAction(UserMetricsAction("SSL.RanInsecureContentGoogle"));
2212 controller_
.ssl_manager()->DidRunInsecureContent(security_origin
);
2213 displayed_insecure_content_
= true;
2214 SSLManager::NotifySSLInternalStateChanged(
2215 GetController().GetBrowserContext());
2218 void WebContentsImpl::OnDocumentLoadedInFrame(int64 frame_id
) {
2219 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2220 DocumentLoadedInFrame(frame_id
, message_source_
));
2223 void WebContentsImpl::OnDidFinishLoad(
2226 bool is_main_frame
) {
2227 GURL
validated_url(url
);
2228 RenderProcessHost
* render_process_host
= message_source_
->GetProcess();
2229 RenderViewHost::FilterURL(render_process_host
, false, &validated_url
);
2230 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2231 DidFinishLoad(frame_id
, validated_url
, is_main_frame
,
2235 void WebContentsImpl::OnDidFailLoadWithError(
2240 const string16
& error_description
) {
2241 GURL
validated_url(url
);
2242 RenderProcessHost
* render_process_host
= message_source_
->GetProcess();
2243 RenderViewHost::FilterURL(render_process_host
, false, &validated_url
);
2244 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2245 DidFailLoad(frame_id
, validated_url
, is_main_frame
,
2246 error_code
, error_description
,
2250 void WebContentsImpl::OnUpdateContentRestrictions(int restrictions
) {
2251 content_restrictions_
= restrictions
;
2253 delegate_
->ContentRestrictionsChanged(this);
2256 void WebContentsImpl::OnGoToEntryAtOffset(int offset
) {
2257 if (!delegate_
|| delegate_
->OnGoToEntryOffset(offset
)) {
2258 NavigationEntryImpl
* entry
= NavigationEntryImpl::FromNavigationEntry(
2259 controller_
.GetEntryAtOffset(offset
));
2262 // Note that we don't call NavigationController::GotToOffset() as we don't
2263 // want to create a pending navigation entry (it might end up lingering
2264 // http://crbug.com/51680).
2265 entry
->SetTransitionType(
2266 PageTransitionFromInt(
2267 entry
->GetTransitionType() |
2268 PAGE_TRANSITION_FORWARD_BACK
));
2269 NavigateToEntry(*entry
, NavigationControllerImpl::NO_RELOAD
);
2271 // If the entry is being restored and doesn't have a SiteInstance yet, fill
2272 // it in now that we know. This allows us to find the entry when it commits.
2273 if (!entry
->site_instance() &&
2274 entry
->restore_type() != NavigationEntryImpl::RESTORE_NONE
) {
2275 entry
->set_site_instance(
2276 static_cast<SiteInstanceImpl
*>(GetPendingSiteInstance()));
2281 void WebContentsImpl::OnUpdateZoomLimits(int minimum_percent
,
2282 int maximum_percent
,
2284 minimum_zoom_percent_
= minimum_percent
;
2285 maximum_zoom_percent_
= maximum_percent
;
2286 temporary_zoom_settings_
= !remember
;
2289 void WebContentsImpl::OnSaveURL(const GURL
& url
,
2290 const Referrer
& referrer
) {
2291 RecordDownloadSource(INITIATED_BY_PEPPER_SAVE
);
2292 // Check if the URL to save matches the URL of the main frame. Since this
2293 // message originates from Pepper plugins, it may not be the case if the
2294 // plugin is an embedded element.
2295 GURL main_frame_url
= GetURL();
2296 if (!main_frame_url
.is_valid())
2298 bool is_main_frame
= (url
== main_frame_url
);
2299 SaveURL(url
, referrer
, is_main_frame
);
2302 void WebContentsImpl::OnEnumerateDirectory(int request_id
,
2303 const base::FilePath
& path
) {
2307 ChildProcessSecurityPolicyImpl
* policy
=
2308 ChildProcessSecurityPolicyImpl::GetInstance();
2309 if (policy
->CanReadDirectory(GetRenderProcessHost()->GetID(), path
))
2310 delegate_
->EnumerateDirectory(this, request_id
, path
);
2313 void WebContentsImpl::OnJSOutOfMemory() {
2315 delegate_
->JSOutOfMemory(this);
2318 void WebContentsImpl::OnRegisterProtocolHandler(const std::string
& protocol
,
2320 const string16
& title
,
2321 bool user_gesture
) {
2325 ChildProcessSecurityPolicyImpl
* policy
=
2326 ChildProcessSecurityPolicyImpl::GetInstance();
2327 if (policy
->IsPseudoScheme(protocol
) || policy
->IsDisabledScheme(protocol
))
2329 delegate_
->RegisterProtocolHandler(this, protocol
, url
, title
, user_gesture
);
2332 void WebContentsImpl::OnFindReply(int request_id
,
2333 int number_of_matches
,
2334 const gfx::Rect
& selection_rect
,
2335 int active_match_ordinal
,
2336 bool final_update
) {
2338 delegate_
->FindReply(this, request_id
, number_of_matches
, selection_rect
,
2339 active_match_ordinal
, final_update
);
2343 #if defined(OS_ANDROID)
2344 void WebContentsImpl::OnFindMatchRectsReply(
2346 const std::vector
<gfx::RectF
>& rects
,
2347 const gfx::RectF
& active_rect
) {
2349 delegate_
->FindMatchRectsReply(this, version
, rects
, active_rect
);
2352 void WebContentsImpl::OnOpenDateTimeDialog(
2353 const ViewHostMsg_DateTimeDialogValue_Params
& value
) {
2354 date_time_chooser_
->ShowDialog(
2355 view_
->GetContentNativeView(), GetRenderViewHost(), value
.dialog_type
,
2356 value
.year
, value
.month
, value
.day
, value
.hour
,
2357 value
.minute
, value
.second
);
2362 void WebContentsImpl::OnCrashedPlugin(const base::FilePath
& plugin_path
,
2363 base::ProcessId plugin_pid
) {
2364 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2365 PluginCrashed(plugin_path
, plugin_pid
));
2368 void WebContentsImpl::OnAppCacheAccessed(const GURL
& manifest_url
,
2369 bool blocked_by_policy
) {
2370 // Notify observers about navigation.
2371 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2372 AppCacheAccessed(manifest_url
, blocked_by_policy
));
2375 void WebContentsImpl::OnOpenColorChooser(int color_chooser_id
,
2377 color_chooser_
= delegate_
?
2378 delegate_
->OpenColorChooser(this, color_chooser_id
, color
) : NULL
;
2381 void WebContentsImpl::OnEndColorChooser(int color_chooser_id
) {
2382 if (color_chooser_
&&
2383 color_chooser_id
== color_chooser_
->identifier())
2384 color_chooser_
->End();
2387 void WebContentsImpl::OnSetSelectedColorInColorChooser(int color_chooser_id
,
2389 if (color_chooser_
&&
2390 color_chooser_id
== color_chooser_
->identifier())
2391 color_chooser_
->SetSelectedColor(color
);
2394 void WebContentsImpl::OnPepperPluginHung(int plugin_child_id
,
2395 const base::FilePath
& path
,
2397 UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1);
2399 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2400 PluginHungStatusChanged(plugin_child_id
, path
, is_hung
));
2403 // This exists for render views that don't have a WebUI, but do have WebUI
2404 // bindings enabled.
2405 void WebContentsImpl::OnWebUISend(const GURL
& source_url
,
2406 const std::string
& name
,
2407 const base::ListValue
& args
) {
2409 delegate_
->WebUISend(this, source_url
, name
, args
);
2412 void WebContentsImpl::OnRequestPpapiBrokerPermission(
2415 const base::FilePath
& plugin_path
) {
2417 OnPpapiBrokerPermissionResult(request_id
, false);
2421 if (!delegate_
->RequestPpapiBrokerPermission(
2422 this, url
, plugin_path
,
2423 base::Bind(&WebContentsImpl::OnPpapiBrokerPermissionResult
,
2424 base::Unretained(this), request_id
))) {
2426 OnPpapiBrokerPermissionResult(request_id
, false);
2430 void WebContentsImpl::OnPpapiBrokerPermissionResult(int request_id
,
2432 RenderViewHostImpl
* rvh
= GetRenderViewHostImpl();
2433 rvh
->Send(new ViewMsg_PpapiBrokerPermissionResult(rvh
->GetRoutingID(),
2438 void WebContentsImpl::OnBrowserPluginAllocateInstanceID(
2439 const IPC::Message
& message
, int request_id
) {
2440 // This creates a BrowserPluginEmbedder, which handles all the BrowserPlugin
2441 // specific messages for this WebContents. This means that any message from
2442 // a BrowserPlugin prior to AllocateInstanceID will be ignored.
2443 // For more info, see comment above classes BrowserPluginEmbedder and
2444 // BrowserPluginGuest.
2445 // The first BrowserPluginHostMsg_AllocateInstanceID message from this
2446 // WebContents' embedder render process is handled here. Once
2447 // BrowserPluginEmbedder is created, all subsequent BrowserPluginHostMsg_*
2448 // messages are handled in BrowserPluginEmbedder. Thus, this code will not be
2449 // executed if a BrowserPluginEmbedder exists for this WebContents.
2450 CHECK(!browser_plugin_embedder_
.get());
2451 browser_plugin_embedder_
.reset(BrowserPluginEmbedder::Create(this));
2452 browser_plugin_embedder_
->OnMessageReceived(message
);
2455 void WebContentsImpl::OnDidDownloadFavicon(
2457 const GURL
& image_url
,
2459 const std::vector
<SkBitmap
>& bitmaps
) {
2460 FaviconDownloadMap::iterator iter
= favicon_download_map_
.find(id
);
2461 if (iter
== favicon_download_map_
.end()) {
2462 // Currently WebContents notifies us of ANY downloads so that it is
2463 // possible to get here.
2466 if (!iter
->second
.is_null()) {
2467 iter
->second
.Run(id
, image_url
, requested_size
, bitmaps
);
2469 favicon_download_map_
.erase(id
);
2472 void WebContentsImpl::OnUpdateFaviconURL(
2474 const std::vector
<FaviconURL
>& candidates
) {
2475 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2476 DidUpdateFaviconURL(page_id
, candidates
));
2479 void WebContentsImpl::OnFrameDetached(int64 frame_id
) {
2480 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2481 FrameDetached(message_source_
, frame_id
));
2484 void WebContentsImpl::DidChangeVisibleSSLState() {
2485 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2486 DidChangeVisibleSSLState());
2489 void WebContentsImpl::NotifyBeforeFormRepostWarningShow() {
2490 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2491 BeforeFormRepostWarningShow());
2494 // Notifies the RenderWidgetHost instance about the fact that the page is
2495 // loading, or done loading and calls the base implementation.
2496 void WebContentsImpl::SetIsLoading(bool is_loading
,
2497 LoadNotificationDetails
* details
) {
2498 if (is_loading
== is_loading_
)
2502 load_state_
= net::LoadStateWithParam(net::LOAD_STATE_IDLE
, string16());
2503 load_state_host_
.clear();
2505 upload_position_
= 0;
2508 render_manager_
.SetIsLoading(is_loading
);
2510 is_loading_
= is_loading
;
2511 waiting_for_response_
= is_loading
;
2514 delegate_
->LoadingStateChanged(this);
2515 NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD
);
2517 int type
= is_loading
? NOTIFICATION_LOAD_START
: NOTIFICATION_LOAD_STOP
;
2518 NotificationDetails det
= NotificationService::NoDetails();
2520 det
= Details
<LoadNotificationDetails
>(details
);
2521 NotificationService::current()->Notify(
2522 type
, Source
<NavigationController
>(&controller_
), det
);
2525 void WebContentsImpl::DidNavigateMainFramePostCommit(
2526 const LoadCommittedDetails
& details
,
2527 const ViewHostMsg_FrameNavigate_Params
& params
) {
2528 if (opener_web_ui_type_
!= WebUI::kNoWebUI
) {
2529 // If this is a window.open navigation, use the same WebUI as the renderer
2530 // that opened the window, as long as both renderers have the same
2532 if (delegate_
&& opener_web_ui_type_
== GetWebUITypeForCurrentState()) {
2533 WebUIImpl
* web_ui
= CreateWebUIForRenderManager(GetURL());
2534 // web_ui might be NULL if the URL refers to a non-existent extension.
2536 render_manager_
.SetWebUIPostCommit(web_ui
);
2537 web_ui
->RenderViewCreated(GetRenderViewHost());
2540 opener_web_ui_type_
= WebUI::kNoWebUI
;
2543 if (details
.is_navigation_to_different_page()) {
2544 // Clear the status bubble. This is a workaround for a bug where WebKit
2545 // doesn't let us know that the cursor left an element during a
2546 // transition (this is also why the mouse cursor remains as a hand after
2547 // clicking on a link); see bugs 1184641 and 980803. We don't want to
2548 // clear the bubble when a user navigates to a named anchor in the same
2550 UpdateTargetURL(details
.entry
->GetPageID(), GURL());
2553 if (!details
.is_in_page
) {
2554 // Once the main frame is navigated, we're no longer considered to have
2555 // displayed insecure content.
2556 displayed_insecure_content_
= false;
2559 // Notify observers about navigation.
2560 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2561 DidNavigateMainFrame(details
, params
));
2564 void WebContentsImpl::DidNavigateAnyFramePostCommit(
2565 RenderViewHost
* render_view_host
,
2566 const LoadCommittedDetails
& details
,
2567 const ViewHostMsg_FrameNavigate_Params
& params
) {
2568 // If we navigate off the page, reset JavaScript state. This does nothing
2569 // to prevent a malicious script from spamming messages, since the script
2570 // could just reload the page to stop blocking.
2571 if (dialog_manager_
&& !details
.is_in_page
) {
2572 dialog_manager_
->ResetJavaScriptState(this);
2573 dialog_manager_
= NULL
;
2576 // Notify observers about navigation.
2577 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2578 DidNavigateAnyFrame(details
, params
));
2581 void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost
* rvh
) {
2582 // If we are creating a RVH for a restored controller, then we need to make
2583 // sure the RenderView starts with a next_page_id_ larger than the number
2584 // of restored entries. This must be called before the RenderView starts
2585 // navigating (to avoid a race between the browser updating max_page_id and
2586 // the renderer updating next_page_id_). Because of this, we only call this
2587 // from CreateRenderView and allow that to notify the RenderView for us.
2588 int max_restored_page_id
= controller_
.GetMaxRestoredPageID();
2589 if (max_restored_page_id
>
2590 GetMaxPageIDForSiteInstance(rvh
->GetSiteInstance()))
2591 UpdateMaxPageIDForSiteInstance(rvh
->GetSiteInstance(),
2592 max_restored_page_id
);
2595 bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl
* entry
,
2596 const string16
& title
) {
2597 // For file URLs without a title, use the pathname instead. In the case of a
2598 // synthesized title, we don't want the update to count toward the "one set
2599 // per page of the title to history."
2600 string16 final_title
;
2602 if (entry
&& entry
->GetURL().SchemeIsFile() && title
.empty()) {
2603 final_title
= UTF8ToUTF16(entry
->GetURL().ExtractFileName());
2604 explicit_set
= false; // Don't count synthetic titles toward the set limit.
2606 TrimWhitespace(title
, TRIM_ALL
, &final_title
);
2607 explicit_set
= true;
2610 // If a page is created via window.open and never navigated,
2611 // there will be no navigation entry. In this situation,
2612 // |page_title_when_no_navigation_entry_| will be used for page title.
2614 if (final_title
== entry
->GetTitle())
2615 return false; // Nothing changed, don't bother.
2617 entry
->SetTitle(final_title
);
2619 if (page_title_when_no_navigation_entry_
== final_title
)
2620 return false; // Nothing changed, don't bother.
2622 page_title_when_no_navigation_entry_
= final_title
;
2625 // Lastly, set the title for the view.
2626 view_
->SetPageTitle(final_title
);
2628 std::pair
<NavigationEntry
*, bool> details
=
2629 std::make_pair(entry
, explicit_set
);
2631 NotificationService::current()->Notify(
2632 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED
,
2633 Source
<WebContents
>(this),
2634 Details
<std::pair
<NavigationEntry
*, bool> >(&details
));
2639 void WebContentsImpl::NotifySwapped(RenderViewHost
* old_render_view_host
) {
2640 // After sending out a swap notification, we need to send a disconnect
2641 // notification so that clients that pick up a pointer to |this| can NULL the
2642 // pointer. See Bug 1230284.
2643 notify_disconnection_
= true;
2644 NotificationService::current()->Notify(
2645 NOTIFICATION_WEB_CONTENTS_SWAPPED
,
2646 Source
<WebContents
>(this),
2647 Details
<RenderViewHost
>(old_render_view_host
));
2649 // Ensure that the associated embedder gets cleared after a RenderViewHost
2650 // gets swapped, so we don't reuse the same embedder next time a
2651 // RenderViewHost is attached to this WebContents.
2652 RemoveBrowserPluginEmbedder();
2655 void WebContentsImpl::NotifyConnected() {
2656 notify_disconnection_
= true;
2657 NotificationService::current()->Notify(
2658 NOTIFICATION_WEB_CONTENTS_CONNECTED
,
2659 Source
<WebContents
>(this),
2660 NotificationService::NoDetails());
2663 void WebContentsImpl::NotifyDisconnected() {
2664 if (!notify_disconnection_
)
2667 notify_disconnection_
= false;
2668 NotificationService::current()->Notify(
2669 NOTIFICATION_WEB_CONTENTS_DISCONNECTED
,
2670 Source
<WebContents
>(this),
2671 NotificationService::NoDetails());
2674 RenderViewHostDelegateView
* WebContentsImpl::GetDelegateView() {
2675 return render_view_host_delegate_view_
;
2678 RenderViewHostDelegate::RendererManagement
*
2679 WebContentsImpl::GetRendererManagementDelegate() {
2680 return &render_manager_
;
2683 RendererPreferences
WebContentsImpl::GetRendererPrefs(
2684 BrowserContext
* browser_context
) const {
2685 return renderer_preferences_
;
2688 WebContents
* WebContentsImpl::GetAsWebContents() {
2692 gfx::Rect
WebContentsImpl::GetRootWindowResizerRect() const {
2694 return delegate_
->GetRootWindowResizerRect();
2698 void WebContentsImpl::RemoveBrowserPluginEmbedder() {
2699 if (browser_plugin_embedder_
.get())
2700 browser_plugin_embedder_
.reset();
2703 void WebContentsImpl::RenderViewCreated(RenderViewHost
* render_view_host
) {
2704 // Don't send notifications if we are just creating a swapped-out RVH for
2705 // the opener chain. These won't be used for view-source or WebUI, so it's
2706 // ok to return early.
2707 if (static_cast<RenderViewHostImpl
*>(render_view_host
)->is_swapped_out())
2711 static_cast<RenderViewHostImpl
*>(render_view_host
)->
2712 SetOverscrollControllerEnabled(delegate_
->CanOverscrollContent());
2715 NotificationService::current()->Notify(
2716 NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED
,
2717 Source
<WebContents
>(this),
2718 Details
<RenderViewHost
>(render_view_host
));
2719 NavigationEntry
* entry
= controller_
.GetActiveEntry();
2723 // When we're creating views, we're still doing initial setup, so we always
2724 // use the pending Web UI rather than any possibly existing committed one.
2725 if (render_manager_
.pending_web_ui())
2726 render_manager_
.pending_web_ui()->RenderViewCreated(render_view_host
);
2728 if (entry
->IsViewSourceMode()) {
2729 // Put the renderer in view source mode.
2730 render_view_host
->Send(
2731 new ViewMsg_EnableViewSourceMode(render_view_host
->GetRoutingID()));
2734 view_
->RenderViewCreated(render_view_host
);
2737 WebContentsObserver
, observers_
, RenderViewCreated(render_view_host
));
2740 void WebContentsImpl::RenderViewReady(RenderViewHost
* rvh
) {
2741 if (rvh
!= GetRenderViewHost()) {
2742 // Don't notify the world, since this came from a renderer in the
2748 bool was_crashed
= IsCrashed();
2749 SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING
, 0);
2751 // Restore the focus to the tab (otherwise the focus will be on the top
2753 if (was_crashed
&& !FocusLocationBarByDefault() &&
2754 (!delegate_
|| delegate_
->ShouldFocusPageAfterCrash())) {
2758 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, RenderViewReady());
2761 void WebContentsImpl::RenderViewGone(RenderViewHost
* rvh
,
2762 base::TerminationStatus status
,
2764 if (rvh
!= GetRenderViewHost()) {
2765 // The pending page's RenderViewHost is gone.
2769 SetIsLoading(false, NULL
);
2770 NotifyDisconnected();
2771 SetIsCrashed(status
, error_code
);
2772 GetView()->OnTabCrashed(GetCrashedStatus(), crashed_error_code_
);
2774 FOR_EACH_OBSERVER(WebContentsObserver
,
2776 RenderViewGone(GetCrashedStatus()));
2779 void WebContentsImpl::RenderViewDeleted(RenderViewHost
* rvh
) {
2780 render_manager_
.RenderViewDeleted(rvh
);
2781 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, RenderViewDeleted(rvh
));
2784 void WebContentsImpl::DidNavigate(
2785 RenderViewHost
* rvh
,
2786 const ViewHostMsg_FrameNavigate_Params
& params
) {
2787 if (PageTransitionIsMainFrame(params
.transition
)) {
2788 // When overscroll navigation gesture is enabled, a screenshot of the page
2789 // in its current state is taken so that it can be used during the
2790 // nav-gesture. It is necessary to take the screenshot here, before calling
2791 // RenderViewHostManager::DidNavigateMainFrame, because that can change
2792 // WebContents::GetRenderViewHost to return the new host, instead of the one
2793 // that may have just been swapped out.
2794 if (delegate_
&& delegate_
->CanOverscrollContent())
2795 controller_
.TakeScreenshot();
2797 render_manager_
.DidNavigateMainFrame(rvh
);
2800 // Update the site of the SiteInstance if it doesn't have one yet, unless
2801 // this is for about:blank. In that case, the SiteInstance can still be
2802 // considered unused until a navigation to a real page.
2803 if (!static_cast<SiteInstanceImpl
*>(GetSiteInstance())->HasSite() &&
2804 params
.url
!= GURL(chrome::kAboutBlankURL
)) {
2805 static_cast<SiteInstanceImpl
*>(GetSiteInstance())->SetSite(params
.url
);
2808 // Need to update MIME type here because it's referred to in
2809 // UpdateNavigationCommands() called by RendererDidNavigate() to
2810 // determine whether or not to enable the encoding menu.
2811 // It's updated only for the main frame. For a subframe,
2812 // RenderView::UpdateURL does not set params.contents_mime_type.
2813 // (see http://code.google.com/p/chromium/issues/detail?id=2929 )
2814 // TODO(jungshik): Add a test for the encoding menu to avoid
2815 // regressing it again.
2816 if (PageTransitionIsMainFrame(params
.transition
))
2817 contents_mime_type_
= params
.contents_mime_type
;
2819 LoadCommittedDetails details
;
2820 bool did_navigate
= controller_
.RendererDidNavigate(params
, &details
);
2822 // Send notification about committed provisional loads. This notification is
2823 // different from the NAV_ENTRY_COMMITTED notification which doesn't include
2824 // the actual URL navigated to and isn't sent for AUTO_SUBFRAME navigations.
2825 if (details
.type
!= NAVIGATION_TYPE_NAV_IGNORE
) {
2826 // For AUTO_SUBFRAME navigations, an event for the main frame is generated
2827 // that is not recorded in the navigation history. For the purpose of
2828 // tracking navigation events, we treat this event as a sub frame navigation
2830 bool is_main_frame
= did_navigate
? details
.is_main_frame
: false;
2831 PageTransition transition_type
= params
.transition
;
2832 // Whether or not a page transition was triggered by going backward or
2833 // forward in the history is only stored in the navigation controller's
2836 (controller_
.GetActiveEntry()->GetTransitionType() &
2837 PAGE_TRANSITION_FORWARD_BACK
)) {
2838 transition_type
= PageTransitionFromInt(
2839 params
.transition
| PAGE_TRANSITION_FORWARD_BACK
);
2841 // Notify observers about the commit of the provisional load.
2842 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2843 DidCommitProvisionalLoadForFrame(params
.frame_id
,
2844 is_main_frame
, params
.url
, transition_type
, rvh
));
2848 return; // No navigation happened.
2850 // DO NOT ADD MORE STUFF TO THIS FUNCTION! Your component should either listen
2851 // for the appropriate notification (best) or you can add it to
2852 // DidNavigateMainFramePostCommit / DidNavigateAnyFramePostCommit (only if
2853 // necessary, please).
2855 // Run post-commit tasks.
2856 if (details
.is_main_frame
) {
2857 DidNavigateMainFramePostCommit(details
, params
);
2859 delegate_
->DidNavigateMainFramePostCommit(this);
2861 DidNavigateAnyFramePostCommit(rvh
, details
, params
);
2864 void WebContentsImpl::UpdateState(RenderViewHost
* rvh
,
2866 const std::string
& state
) {
2867 // Ensure that this state update comes from either the active RVH or one of
2868 // the swapped out RVHs. We don't expect to hear from any other RVHs.
2869 DCHECK(rvh
== GetRenderViewHost() || render_manager_
.IsSwappedOut(rvh
));
2871 // We must be prepared to handle state updates for any page, these occur
2872 // when the user is scrolling and entering form data, as well as when we're
2873 // leaving a page, in which case our state may have already been moved to
2874 // the next page. The navigation controller will look up the appropriate
2875 // NavigationEntry and update it when it is notified via the delegate.
2877 int entry_index
= controller_
.GetEntryIndexWithPageID(
2878 rvh
->GetSiteInstance(), page_id
);
2879 if (entry_index
< 0)
2881 NavigationEntry
* entry
= controller_
.GetEntryAtIndex(entry_index
);
2883 if (state
== entry
->GetContentState())
2884 return; // Nothing to update.
2885 entry
->SetContentState(state
);
2886 controller_
.NotifyEntryChanged(entry
, entry_index
);
2889 void WebContentsImpl::UpdateTitle(RenderViewHost
* rvh
,
2891 const string16
& title
,
2892 base::i18n::TextDirection title_direction
) {
2893 // If we have a title, that's a pretty good indication that we've started
2894 // getting useful data.
2895 SetNotWaitingForResponse();
2897 // Try to find the navigation entry, which might not be the current one.
2898 // For example, it might be from a pending RVH for the pending entry.
2899 NavigationEntryImpl
* entry
= controller_
.GetEntryWithPageID(
2900 rvh
->GetSiteInstance(), page_id
);
2902 // We can handle title updates when we don't have an entry in
2903 // UpdateTitleForEntry, but only if the update is from the current RVH.
2904 if (!entry
&& rvh
!= GetRenderViewHost())
2907 // TODO(evan): make use of title_direction.
2908 // http://code.google.com/p/chromium/issues/detail?id=27094
2909 if (!UpdateTitleForEntry(entry
, title
))
2912 // Broadcast notifications when the UI should be updated.
2913 if (entry
== controller_
.GetEntryAtOffset(0))
2914 NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE
);
2917 void WebContentsImpl::UpdateEncoding(RenderViewHost
* render_view_host
,
2918 const std::string
& encoding
) {
2919 SetEncoding(encoding
);
2922 void WebContentsImpl::UpdateTargetURL(int32 page_id
, const GURL
& url
) {
2924 delegate_
->UpdateTargetURL(this, page_id
, url
);
2927 void WebContentsImpl::Close(RenderViewHost
* rvh
) {
2928 #if defined(OS_MACOSX)
2929 // The UI may be in an event-tracking loop, such as between the
2930 // mouse-down and mouse-up in text selection or a button click.
2931 // Defer the close until after tracking is complete, so that we
2932 // don't free objects out from under the UI.
2933 // TODO(shess): This could get more fine-grained. For instance,
2934 // closing a tab in another window while selecting text in the
2935 // current window's Omnibox should be just fine.
2936 if (view_
->IsEventTracking()) {
2937 view_
->CloseTabAfterEventTracking();
2942 // Ignore this if it comes from a RenderViewHost that we aren't showing.
2943 if (delegate_
&& rvh
== GetRenderViewHost())
2944 delegate_
->CloseContents(this);
2947 void WebContentsImpl::SwappedOut(RenderViewHost
* rvh
) {
2948 if (delegate_
&& rvh
== GetRenderViewHost())
2949 delegate_
->SwappedOut(this);
2952 void WebContentsImpl::RequestMove(const gfx::Rect
& new_bounds
) {
2953 if (delegate_
&& delegate_
->IsPopupOrPanel(this))
2954 delegate_
->MoveContents(this, new_bounds
);
2957 void WebContentsImpl::DidStartLoading(RenderViewHost
* render_view_host
) {
2958 SetIsLoading(true, NULL
);
2960 if (delegate_
&& content_restrictions_
)
2961 OnUpdateContentRestrictions(0);
2963 // Notify observers about navigation.
2964 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2965 DidStartLoading(render_view_host
));
2968 void WebContentsImpl::DidStopLoading(RenderViewHost
* render_view_host
) {
2969 scoped_ptr
<LoadNotificationDetails
> details
;
2971 NavigationEntry
* entry
= controller_
.GetActiveEntry();
2972 // An entry may not exist for a stop when loading an initial blank page or
2973 // if an iframe injected by script into a blank page finishes loading.
2975 base::TimeDelta elapsed
= base::TimeTicks::Now() - current_load_start_
;
2977 details
.reset(new LoadNotificationDetails(
2978 entry
->GetVirtualURL(),
2979 entry
->GetTransitionType(),
2982 controller_
.GetCurrentEntryIndex()));
2985 SetIsLoading(false, details
.get());
2987 // Notify observers about navigation.
2988 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
2989 DidStopLoading(render_view_host
));
2992 void WebContentsImpl::DidCancelLoading() {
2993 controller_
.DiscardNonCommittedEntries();
2995 // Update the URL display.
2996 NotifyNavigationStateChanged(INVALIDATE_TYPE_URL
);
2999 void WebContentsImpl::DidChangeLoadProgress(double progress
) {
3000 #if defined(OS_ANDROID)
3002 delegate_
->LoadProgressChanged(this, progress
);
3006 void WebContentsImpl::DidDisownOpener(RenderViewHost
* rvh
) {
3007 // Clear our opener so that future cross-process navigations don't have an
3009 registrar_
.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED
,
3010 Source
<WebContents
>(opener_
));
3013 // Notify all swapped out RenderViewHosts for this tab. This is important
3014 // in case we go back to them, or if another window in those processes tries
3015 // to access window.opener.
3016 render_manager_
.DidDisownOpener(rvh
);
3019 void WebContentsImpl::DidUpdateFrameTree(RenderViewHost
* rvh
) {
3020 render_manager_
.DidUpdateFrameTree(rvh
);
3023 void WebContentsImpl::DocumentAvailableInMainFrame(
3024 RenderViewHost
* render_view_host
) {
3025 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3026 DocumentAvailableInMainFrame());
3029 void WebContentsImpl::DocumentOnLoadCompletedInMainFrame(
3030 RenderViewHost
* render_view_host
,
3032 NotificationService::current()->Notify(
3033 NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME
,
3034 Source
<WebContents
>(this),
3035 Details
<int>(&page_id
));
3038 void WebContentsImpl::RequestOpenURL(RenderViewHost
* rvh
,
3040 const Referrer
& referrer
,
3041 WindowOpenDisposition disposition
,
3042 int64 source_frame_id
,
3043 bool is_cross_site_redirect
) {
3044 // If this came from a swapped out RenderViewHost, we only allow the request
3045 // if we are still in the same BrowsingInstance.
3046 if (static_cast<RenderViewHostImpl
*>(rvh
)->is_swapped_out() &&
3047 !rvh
->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance())) {
3051 // Delegate to RequestTransferURL because this is just the generic
3052 // case where |old_request_id| is empty.
3053 RequestTransferURL(url
, referrer
, disposition
, source_frame_id
,
3054 GlobalRequestID(), is_cross_site_redirect
);
3057 void WebContentsImpl::RequestTransferURL(
3059 const Referrer
& referrer
,
3060 WindowOpenDisposition disposition
,
3061 int64 source_frame_id
,
3062 const GlobalRequestID
& old_request_id
,
3063 bool is_cross_site_redirect
) {
3064 WebContents
* new_contents
= NULL
;
3065 PageTransition transition_type
= PAGE_TRANSITION_LINK
;
3066 if (render_manager_
.web_ui()) {
3067 // When we're a Web UI, it will provide a page transition type for us (this
3068 // is so the new tab page can specify AUTO_BOOKMARK for automatically
3069 // generated suggestions).
3071 // Note also that we hide the referrer for Web UI pages. We don't really
3072 // want web sites to see a referrer of "chrome://blah" (and some
3073 // chrome: URLs might have search terms or other stuff we don't want to
3074 // send to the site), so we send no referrer.
3075 OpenURLParams
params(url
, Referrer(), source_frame_id
, disposition
,
3076 render_manager_
.web_ui()->GetLinkTransitionType(),
3077 false /* is_renderer_initiated */);
3078 params
.transferred_global_request_id
= old_request_id
;
3079 new_contents
= OpenURL(params
);
3080 transition_type
= render_manager_
.web_ui()->GetLinkTransitionType();
3082 OpenURLParams
params(url
, referrer
, source_frame_id
, disposition
,
3083 PAGE_TRANSITION_LINK
, true /* is_renderer_initiated */);
3084 params
.transferred_global_request_id
= old_request_id
;
3085 params
.is_cross_site_redirect
= is_cross_site_redirect
;
3086 new_contents
= OpenURL(params
);
3089 // Notify observers.
3090 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
,
3091 DidOpenRequestedURL(new_contents
,
3100 void WebContentsImpl::RouteCloseEvent(RenderViewHost
* rvh
) {
3101 // Tell the active RenderViewHost to run unload handlers and close, as long
3102 // as the request came from a RenderViewHost in the same BrowsingInstance.
3103 // In most cases, we receive this from a swapped out RenderViewHost.
3104 // It is possible to receive it from one that has just been swapped in,
3105 // in which case we might as well deliver the message anyway.
3106 if (rvh
->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()))
3107 GetRenderViewHost()->ClosePage();
3110 void WebContentsImpl::RouteMessageEvent(
3111 RenderViewHost
* rvh
,
3112 const ViewMsg_PostMessage_Params
& params
) {
3113 // Only deliver the message to the active RenderViewHost if the request
3114 // came from a RenderViewHost in the same BrowsingInstance or if this
3115 // WebContents is dedicated to a browser plugin guest.
3116 // Note: This check means that an embedder could theoretically receive a
3117 // postMessage from anyone (not just its own guests). However, this is
3118 // probably not a risk for apps since other pages won't have references
3120 if (!rvh
->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()) &&
3121 !GetBrowserPluginGuest() && !GetBrowserPluginEmbedder())
3124 ViewMsg_PostMessage_Params
new_params(params
);
3126 // If the renderer has changed while the post message is being routed,
3127 // drop the message, as it will not be delivered to the right target.
3128 // TODO(nasko): Check for process ID and target frame id mismatch, once
3129 // http://crbug.com/153701 is fixed.
3131 // If there is a source_routing_id, translate it to the routing ID for
3132 // the equivalent swapped out RVH in the target process. If we need
3133 // to create a swapped out RVH for the source tab, we create its opener
3134 // chain as well, since those will also be accessible to the target page.
3135 if (new_params
.source_routing_id
!= MSG_ROUTING_NONE
) {
3136 // Try to look up the WebContents for the source page.
3137 WebContentsImpl
* source_contents
= NULL
;
3138 RenderViewHostImpl
* source_rvh
= RenderViewHostImpl::FromID(
3139 rvh
->GetProcess()->GetID(), params
.source_routing_id
);
3141 source_contents
= static_cast<WebContentsImpl
*>(
3142 source_rvh
->GetDelegate()->GetAsWebContents());
3145 if (source_contents
) {
3146 if (GetBrowserPluginGuest()) {
3147 // We create a swapped out RenderView for the embedder in the guest's
3148 // render process but we intentionally do not expose the embedder's
3149 // opener chain to it.
3150 new_params
.source_routing_id
=
3151 source_contents
->CreateSwappedOutRenderView(GetSiteInstance());
3153 new_params
.source_routing_id
=
3154 source_contents
->CreateOpenerRenderViews(GetSiteInstance());
3157 // We couldn't find it, so don't pass a source frame.
3158 new_params
.source_routing_id
= MSG_ROUTING_NONE
;
3162 // In most cases, we receive this from a swapped out RenderViewHost.
3163 // It is possible to receive it from one that has just been swapped in,
3164 // in which case we might as well deliver the message anyway.
3165 Send(new ViewMsg_PostMessageEvent(GetRoutingID(), new_params
));
3168 void WebContentsImpl::RunJavaScriptMessage(
3169 RenderViewHost
* rvh
,
3170 const string16
& message
,
3171 const string16
& default_prompt
,
3172 const GURL
& frame_url
,
3173 JavaScriptMessageType javascript_message_type
,
3174 IPC::Message
* reply_msg
,
3175 bool* did_suppress_message
) {
3176 // Suppress JavaScript dialogs when requested. Also suppress messages when
3177 // showing an interstitial as it's shown over the previous page and we don't
3178 // want the hidden page's dialogs to interfere with the interstitial.
3179 bool suppress_this_message
=
3180 static_cast<RenderViewHostImpl
*>(rvh
)->is_swapped_out() ||
3181 ShowingInterstitialPage() ||
3183 delegate_
->ShouldSuppressDialogs() ||
3184 !delegate_
->GetJavaScriptDialogManager();
3186 if (!suppress_this_message
) {
3187 std::string accept_lang
= GetContentClient()->browser()->
3188 GetAcceptLangs(GetBrowserContext());
3189 dialog_manager_
= delegate_
->GetJavaScriptDialogManager();
3190 dialog_manager_
->RunJavaScriptDialog(
3192 frame_url
.GetOrigin(),
3194 javascript_message_type
,
3197 base::Bind(&WebContentsImpl::OnDialogClosed
,
3198 base::Unretained(this),
3201 &suppress_this_message
);
3204 if (suppress_this_message
) {
3205 // If we are suppressing messages, just reply as if the user immediately
3206 // pressed "Cancel".
3207 OnDialogClosed(rvh
, reply_msg
, false, string16());
3210 *did_suppress_message
= suppress_this_message
;
3213 void WebContentsImpl::RunBeforeUnloadConfirm(RenderViewHost
* rvh
,
3214 const string16
& message
,
3216 IPC::Message
* reply_msg
) {
3217 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(rvh
);
3219 delegate_
->WillRunBeforeUnloadConfirm();
3221 bool suppress_this_message
=
3222 rvhi
->is_swapped_out() ||
3224 delegate_
->ShouldSuppressDialogs() ||
3225 !delegate_
->GetJavaScriptDialogManager();
3226 if (suppress_this_message
) {
3227 // The reply must be sent to the RVH that sent the request.
3228 rvhi
->JavaScriptDialogClosed(reply_msg
, true, string16());
3232 is_showing_before_unload_dialog_
= true;
3233 dialog_manager_
= delegate_
->GetJavaScriptDialogManager();
3234 dialog_manager_
->RunBeforeUnloadDialog(
3235 this, message
, is_reload
,
3236 base::Bind(&WebContentsImpl::OnDialogClosed
, base::Unretained(this), rvh
,
3240 bool WebContentsImpl::AddMessageToConsole(int32 level
,
3241 const string16
& message
,
3243 const string16
& source_id
) {
3246 return delegate_
->AddMessageToConsole(this, level
, message
, line_no
,
3250 WebPreferences
WebContentsImpl::GetWebkitPrefs() {
3251 // We want to base the page config off of the real URL, rather than the
3253 GURL url
= controller_
.GetActiveEntry()
3254 ? controller_
.GetActiveEntry()->GetURL() : GURL::EmptyGURL();
3255 return GetWebkitPrefs(GetRenderViewHost(), url
);
3258 int WebContentsImpl::CreateSwappedOutRenderView(
3259 SiteInstance
* instance
) {
3260 return render_manager_
.CreateRenderView(instance
, MSG_ROUTING_NONE
, true);
3263 void WebContentsImpl::OnUserGesture() {
3264 // Notify observers.
3265 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, DidGetUserGesture());
3267 ResourceDispatcherHostImpl
* rdh
= ResourceDispatcherHostImpl::Get();
3268 if (rdh
) // NULL in unittests.
3269 rdh
->OnUserGesture(this);
3272 void WebContentsImpl::OnIgnoredUIEvent() {
3273 // Notify observers.
3274 FOR_EACH_OBSERVER(WebContentsObserver
, observers_
, DidGetIgnoredUIEvent());
3277 void WebContentsImpl::RendererUnresponsive(RenderViewHost
* rvh
,
3278 bool is_during_unload
) {
3279 // Don't show hung renderer dialog for a swapped out RVH.
3280 if (rvh
!= GetRenderViewHost())
3283 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(rvh
);
3285 // Ignore renderer unresponsive event if debugger is attached to the tab
3286 // since the event may be a result of the renderer sitting on a breakpoint.
3287 // See http://crbug.com/65458
3288 if (DevToolsAgentHost::IsDebuggerAttached(this))
3291 if (is_during_unload
) {
3292 // Hang occurred while firing the beforeunload/unload handler.
3293 // Pretend the handler fired so tab closing continues as if it had.
3294 rvhi
->set_sudden_termination_allowed(true);
3296 if (!render_manager_
.ShouldCloseTabOnUnresponsiveRenderer())
3299 // If the tab hangs in the beforeunload/unload handler there's really
3300 // nothing we can do to recover. Pretend the unload listeners have
3301 // all fired and close the tab. If the hang is in the beforeunload handler
3302 // then the user will not have the option of cancelling the close.
3307 if (!GetRenderViewHostImpl() || !GetRenderViewHostImpl()->IsRenderViewLive())
3311 delegate_
->RendererUnresponsive(this);
3314 void WebContentsImpl::RendererResponsive(RenderViewHost
* render_view_host
) {
3316 delegate_
->RendererResponsive(this);
3319 void WebContentsImpl::LoadStateChanged(
3321 const net::LoadStateWithParam
& load_state
,
3322 uint64 upload_position
,
3323 uint64 upload_size
) {
3324 load_state_
= load_state
;
3325 upload_position_
= upload_position
;
3326 upload_size_
= upload_size
;
3327 load_state_host_
= net::IDNToUnicode(url
.host(),
3328 GetContentClient()->browser()->GetAcceptLangs(
3329 GetBrowserContext()));
3330 if (load_state_
.state
== net::LOAD_STATE_READING_RESPONSE
)
3331 SetNotWaitingForResponse();
3333 NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD
| INVALIDATE_TYPE_TAB
);
3337 void WebContentsImpl::WorkerCrashed() {
3339 delegate_
->WorkerCrashed(this);
3342 void WebContentsImpl::BeforeUnloadFiredFromRenderManager(
3343 bool proceed
, const base::TimeTicks
& proceed_time
,
3344 bool* proceed_to_fire_unload
) {
3345 before_unload_end_time_
= proceed_time
;
3347 delegate_
->BeforeUnloadFired(this, proceed
, proceed_to_fire_unload
);
3350 void WebContentsImpl::RenderViewGoneFromRenderManager(
3351 RenderViewHost
* render_view_host
) {
3352 DCHECK(crashed_status_
!= base::TERMINATION_STATUS_STILL_RUNNING
);
3353 RenderViewGone(render_view_host
, crashed_status_
, crashed_error_code_
);
3356 void WebContentsImpl::UpdateRenderViewSizeForRenderManager() {
3357 // TODO(brettw) this is a hack. See WebContentsView::SizeContents.
3358 gfx::Size size
= view_
->GetContainerSize();
3359 // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be
3360 // here during container initialization and normal window size will be set
3361 // later. In case of tab duplication this resizing to 0x0 prevents setting
3362 // normal size later so just ignore it.
3363 if (!size
.IsEmpty())
3364 view_
->SizeContents(size
);
3367 void WebContentsImpl::NotifySwappedFromRenderManager(RenderViewHost
* rvh
) {
3370 // Make sure the visible RVH reflects the new delegate's preferences.
3372 RenderViewHostImpl
* host
= render_manager_
.current_host();
3374 host
->SetOverscrollControllerEnabled(delegate_
->CanOverscrollContent());
3377 view_
->RenderViewSwappedIn(render_manager_
.current_host());
3380 int WebContentsImpl::CreateOpenerRenderViewsForRenderManager(
3381 SiteInstance
* instance
) {
3383 return MSG_ROUTING_NONE
;
3385 // Recursively create RenderViews for anything else in the opener chain.
3386 return opener_
->CreateOpenerRenderViews(instance
);
3389 int WebContentsImpl::CreateOpenerRenderViews(SiteInstance
* instance
) {
3390 int opener_route_id
= MSG_ROUTING_NONE
;
3392 // If this tab has an opener, ensure it has a RenderView in the given
3393 // SiteInstance as well.
3395 opener_route_id
= opener_
->CreateOpenerRenderViews(instance
);
3397 // If any of the renderers (current, pending, or swapped out) for this
3398 // WebContents has the same SiteInstance, use it.
3399 if (render_manager_
.current_host()->GetSiteInstance() == instance
)
3400 return render_manager_
.current_host()->GetRoutingID();
3402 if (render_manager_
.pending_render_view_host() &&
3403 render_manager_
.pending_render_view_host()->GetSiteInstance() == instance
)
3404 return render_manager_
.pending_render_view_host()->GetRoutingID();
3406 RenderViewHostImpl
* rvh
= render_manager_
.GetSwappedOutRenderViewHost(
3409 return rvh
->GetRoutingID();
3411 // Create a swapped out RenderView in the given SiteInstance if none exists,
3412 // setting its opener to the given route_id. Return the new view's route_id.
3413 return render_manager_
.CreateRenderView(instance
, opener_route_id
, true);
3416 NavigationControllerImpl
& WebContentsImpl::GetControllerForRenderManager() {
3417 return GetController();
3420 WebUIImpl
* WebContentsImpl::CreateWebUIForRenderManager(const GURL
& url
) {
3421 return static_cast<WebUIImpl
*>(CreateWebUI(url
));
3425 WebContentsImpl::GetLastCommittedNavigationEntryForRenderManager() {
3426 return controller_
.GetLastCommittedEntry();
3429 bool WebContentsImpl::CreateRenderViewForRenderManager(
3430 RenderViewHost
* render_view_host
, int opener_route_id
) {
3431 // Can be NULL during tests.
3432 RenderWidgetHostView
* rwh_view
= view_
->CreateViewForWidget(render_view_host
);
3434 // Now that the RenderView has been created, we need to tell it its size.
3436 rwh_view
->SetSize(view_
->GetContainerSize());
3438 // Make sure we use the correct starting page_id in the new RenderView.
3439 UpdateMaxPageIDIfNecessary(render_view_host
);
3441 GetMaxPageIDForSiteInstance(render_view_host
->GetSiteInstance());
3443 if (!static_cast<RenderViewHostImpl
*>(
3444 render_view_host
)->CreateRenderView(string16(),
3450 #if defined(OS_LINUX) || defined(OS_OPENBSD)
3451 // Force a ViewMsg_Resize to be sent, needed to make plugins show up on
3452 // linux. See crbug.com/83941.
3454 if (RenderWidgetHost
* render_widget_host
= rwh_view
->GetRenderWidgetHost())
3455 render_widget_host
->WasResized();
3462 void WebContentsImpl::OnDialogClosed(RenderViewHost
* rvh
,
3463 IPC::Message
* reply_msg
,
3465 const string16
& user_input
) {
3466 if (is_showing_before_unload_dialog_
&& !success
) {
3467 // If a beforeunload dialog is canceled, we need to stop the throbber from
3468 // spinning, since we forced it to start spinning in Navigate.
3469 DidStopLoading(rvh
);
3470 controller_
.DiscardNonCommittedEntries();
3472 close_start_time_
= base::TimeTicks();
3473 before_unload_end_time_
= base::TimeTicks();
3475 is_showing_before_unload_dialog_
= false;
3476 static_cast<RenderViewHostImpl
*>(
3477 rvh
)->JavaScriptDialogClosed(reply_msg
, success
, user_input
);
3480 void WebContentsImpl::SetEncoding(const std::string
& encoding
) {
3481 encoding_
= GetContentClient()->browser()->
3482 GetCanonicalEncodingNameByAliasName(encoding
);
3485 void WebContentsImpl::SaveURL(const GURL
& url
,
3486 const Referrer
& referrer
,
3487 bool is_main_frame
) {
3488 DownloadManager
* dlm
=
3489 BrowserContext::GetDownloadManager(GetBrowserContext());
3493 if (is_main_frame
) {
3494 const NavigationEntry
* entry
= controller_
.GetActiveEntry();
3496 post_id
= entry
->GetPostID();
3498 scoped_ptr
<DownloadUrlParameters
> params(
3499 DownloadUrlParameters::FromWebContents(this, url
));
3500 params
->set_referrer(referrer
);
3501 params
->set_post_id(post_id
);
3502 params
->set_prefer_cache(true);
3504 params
->set_method("POST");
3505 params
->set_prompt(true);
3506 dlm
->DownloadUrl(params
.Pass());
3509 void WebContentsImpl::CreateViewAndSetSizeForRVH(RenderViewHost
* rvh
) {
3510 RenderWidgetHostView
* rwh_view
= view_
->CreateViewForWidget(rvh
);
3511 // Can be NULL during tests.
3513 rwh_view
->SetSize(GetView()->GetContainerSize());
3516 RenderViewHostImpl
* WebContentsImpl::GetRenderViewHostImpl() {
3517 return static_cast<RenderViewHostImpl
*>(GetRenderViewHost());
3520 BrowserPluginGuest
* WebContentsImpl::GetBrowserPluginGuest() const {
3521 return browser_plugin_guest_
.get();
3524 BrowserPluginEmbedder
* WebContentsImpl::GetBrowserPluginEmbedder() const {
3525 return browser_plugin_embedder_
.get();
3528 BrowserPluginGuestManager
*
3529 WebContentsImpl::GetBrowserPluginGuestManager() const {
3530 return static_cast<BrowserPluginGuestManager
*>(
3531 GetBrowserContext()->GetUserData(
3532 browser_plugin::kBrowserPluginGuestManagerKeyName
));
3535 } // namespace content