web_contents_impl.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "content/browser/web_contents/web_contents_impl.h" 6 7#include <utility> 8 9#include "base/command_line.h" 10#include "base/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/base/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" 87 88#if defined(OS_ANDROID) 89#include "content/browser/android/date_time_chooser_android.h" 90#endif 91 92#if defined(OS_MACOSX) 93#include "base/mac/foundation_util.h" 94#include "ui/surface/io_surface_support_mac.h" 95#endif 96 97#if defined(ENABLE_JAVA_BRIDGE) 98#include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h" 99#endif 100 101// Cross-Site Navigations 102// 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 106// follows: 107// 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 138// pending RVH. 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. 142 143using webkit_glue::WebPreferences; 144 145namespace content { 146namespace { 147 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. 150const int kQueryStateDelay = 5000; 151 152const int kSyncWaitDelay = 40; 153 154const char kDotGoogleDotCom[] = ".google.com"; 155 156static int StartDownload(content::RenderViewHost* rvh, 157 const GURL& url, 158 bool is_favicon, 159 int image_size) { 160 static int g_next_favicon_download_id = 0; 161 rvh->Send(new IconMsg_DownloadFavicon(rvh->GetRoutingID(), 162 ++g_next_favicon_download_id, 163 url, 164 is_favicon, 165 image_size)); 166 return g_next_favicon_download_id; 167} 168 169ViewMsg_Navigate_Type::Value GetNavigationType( 170 BrowserContext* browser_context, const NavigationEntryImpl& entry, 171 NavigationController::ReloadType reload_type) { 172 switch (reload_type) { 173 case NavigationControllerImpl::RELOAD: 174 return ViewMsg_Navigate_Type::RELOAD; 175 case NavigationControllerImpl::RELOAD_IGNORING_CACHE: 176 return ViewMsg_Navigate_Type::RELOAD_IGNORING_CACHE; 177 case NavigationControllerImpl::RELOAD_ORIGINAL_REQUEST_URL: 178 return ViewMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL; 179 case NavigationControllerImpl::NO_RELOAD: 180 break; // Fall through to rest of function. 181 } 182 183 // |RenderViewImpl::PopulateStateFromPendingNavigationParams| differentiates 184 // between |RESTORE_WITH_POST| and |RESTORE|. 185 if (entry.restore_type() == 186 NavigationEntryImpl::RESTORE_LAST_SESSION_EXITED_CLEANLY) { 187 if (entry.GetHasPostData()) 188 return ViewMsg_Navigate_Type::RESTORE_WITH_POST; 189 return ViewMsg_Navigate_Type::RESTORE; 190 } 191 192 return ViewMsg_Navigate_Type::NORMAL; 193} 194 195void MakeNavigateParams(const NavigationEntryImpl& entry, 196 const NavigationControllerImpl& controller, 197 WebContentsDelegate* delegate, 198 NavigationController::ReloadType reload_type, 199 ViewMsg_Navigate_Params* params) { 200 params->page_id = entry.GetPageID(); 201 params->pending_history_list_offset = controller.GetIndexOfEntry(&entry); 202 params->current_history_list_offset = controller.GetLastCommittedEntryIndex(); 203 params->current_history_list_length = controller.GetEntryCount(); 204 if (!entry.GetBaseURLForDataURL().is_empty()) { 205 params->base_url_for_data_url = entry.GetBaseURLForDataURL(); 206 params->history_url_for_data_url = entry.GetVirtualURL(); 207 } 208 params->referrer = entry.GetReferrer(); 209 params->transition = entry.GetTransitionType(); 210 params->state = entry.GetContentState(); 211 params->navigation_type = 212 GetNavigationType(controller.GetBrowserContext(), entry, reload_type); 213 params->request_time = base::Time::Now(); 214 params->extra_headers = entry.extra_headers(); 215 params->transferred_request_child_id = 216 entry.transferred_global_request_id().child_id; 217 params->transferred_request_request_id = 218 entry.transferred_global_request_id().request_id; 219 params->is_overriding_user_agent = entry.GetIsOverridingUserAgent(); 220 // Avoid downloading when in view-source mode. 221 params->allow_download = !entry.IsViewSourceMode(); 222 params->is_post = entry.GetHasPostData(); 223 if(entry.GetBrowserInitiatedPostData()) { 224 params->browser_initiated_post_data.assign( 225 entry.GetBrowserInitiatedPostData()->front(), 226 entry.GetBrowserInitiatedPostData()->front() + 227 entry.GetBrowserInitiatedPostData()->size()); 228 229 } 230 231 if (reload_type == NavigationControllerImpl::RELOAD_ORIGINAL_REQUEST_URL && 232 entry.GetOriginalRequestURL().is_valid() && !entry.GetHasPostData()) { 233 // We may have been redirected when navigating to the current URL. 234 // Use the URL the user originally intended to visit, if it's valid and if a 235 // POST wasn't involved; the latter case avoids issues with sending data to 236 // the wrong page. 237 params->url = entry.GetOriginalRequestURL(); 238 } else { 239 params->url = entry.GetURL(); 240 } 241 242 params->can_load_local_resources = entry.GetCanLoadLocalResources(); 243 params->frame_to_navigate = entry.GetFrameToNavigate(); 244 245 if (delegate) 246 delegate->AddNavigationHeaders(params->url, ¶ms->extra_headers); 247} 248 249} // namespace 250 251WebContents* WebContents::Create(const WebContents::CreateParams& params) { 252 return WebContentsImpl::CreateWithOpener(params, NULL); 253} 254 255WebContents* WebContents::CreateWithSessionStorage( 256 const WebContents::CreateParams& params, 257 const SessionStorageNamespaceMap& session_storage_namespace_map) { 258 WebContentsImpl* new_contents = new WebContentsImpl( 259 params.browser_context, NULL); 260 261 for (SessionStorageNamespaceMap::const_iterator it = 262 session_storage_namespace_map.begin(); 263 it != session_storage_namespace_map.end(); 264 ++it) { 265 new_contents->GetController().SetSessionStorageNamespace(it->first, 266 it->second); 267 } 268 269 new_contents->Init(params); 270 return new_contents; 271} 272 273WebContents* WebContents::FromRenderViewHost(const RenderViewHost* rvh) { 274 return rvh->GetDelegate()->GetAsWebContents(); 275} 276 277// WebContentsImpl ------------------------------------------------------------- 278 279WebContentsImpl::WebContentsImpl( 280 BrowserContext* browser_context, 281 WebContentsImpl* opener) 282 : delegate_(NULL), 283 ALLOW_THIS_IN_INITIALIZER_LIST(controller_(this, browser_context)), 284 render_view_host_delegate_view_(NULL), 285 opener_(opener), 286 ALLOW_THIS_IN_INITIALIZER_LIST(render_manager_(this, this, this)), 287 is_loading_(false), 288 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING), 289 crashed_error_code_(0), 290 waiting_for_response_(false), 291 load_state_(net::LOAD_STATE_IDLE, string16()), 292 upload_size_(0), 293 upload_position_(0), 294 displayed_insecure_content_(false), 295 capturer_count_(0), 296 should_normally_be_visible_(true), 297 is_being_destroyed_(false), 298 notify_disconnection_(false), 299 dialog_manager_(NULL), 300 is_showing_before_unload_dialog_(false), 301 closed_by_user_gesture_(false), 302 minimum_zoom_percent_(static_cast<int>(kMinimumZoomFactor * 100)), 303 maximum_zoom_percent_(static_cast<int>(kMaximumZoomFactor * 100)), 304 temporary_zoom_settings_(false), 305 content_restrictions_(0), 306 color_chooser_(NULL), 307 message_source_(NULL), 308 fullscreen_widget_routing_id_(MSG_ROUTING_NONE) { 309} 310 311WebContentsImpl::~WebContentsImpl() { 312 is_being_destroyed_ = true; 313 314 for (std::set<RenderWidgetHostImpl*>::iterator iter = 315 created_widgets_.begin(); iter != created_widgets_.end(); ++iter) { 316 (*iter)->DetachDelegate(); 317 } 318 created_widgets_.clear(); 319 320 // Clear out any JavaScript state. 321 if (dialog_manager_) 322 dialog_manager_->ResetJavaScriptState(this); 323 324 if (color_chooser_) 325 color_chooser_->End(); 326 327 NotifyDisconnected(); 328 329 // Notify any observer that have a reference on this WebContents. 330 NotificationService::current()->Notify( 331 NOTIFICATION_WEB_CONTENTS_DESTROYED, 332 Source<WebContents>(this), 333 NotificationService::NoDetails()); 334 335 // TODO(brettw) this should be moved to the view. 336#if defined(OS_WIN) && !defined(USE_AURA) 337 // If we still have a window handle, destroy it. GetNativeView can return 338 // NULL if this contents was part of a window that closed. 339 if (view_->GetNativeView()) { 340 RenderViewHost* host = GetRenderViewHost(); 341 if (host && host->GetView()) 342 RenderWidgetHostViewPort::FromRWHV(host->GetView())->WillWmDestroy(); 343 } 344#endif 345 346 // OnCloseStarted isn't called in unit tests. 347 if (!close_start_time_.is_null()) { 348 base::TimeTicks now = base::TimeTicks::Now(); 349 base::TimeTicks unload_start_time = close_start_time_; 350 if (!before_unload_end_time_.is_null()) 351 unload_start_time = before_unload_end_time_; 352 UMA_HISTOGRAM_TIMES("Tab.Close", now - close_start_time_); 353 UMA_HISTOGRAM_TIMES("Tab.Close.UnloadTime", now - unload_start_time); 354 } 355 356 FOR_EACH_OBSERVER(WebContentsObserver, 357 observers_, 358 WebContentsImplDestroyed()); 359 360 SetDelegate(NULL); 361} 362 363WebContentsImpl* WebContentsImpl::CreateWithOpener( 364 const WebContents::CreateParams& params, 365 WebContentsImpl* opener) { 366 WebContentsImpl* new_contents = new WebContentsImpl( 367 params.browser_context, opener); 368 369 new_contents->Init(params); 370 return new_contents; 371} 372 373// static 374BrowserPluginGuest* WebContentsImpl::CreateGuest( 375 BrowserContext* browser_context, 376 SiteInstance* site_instance, 377 int guest_instance_id) { 378 WebContentsImpl* new_contents = new WebContentsImpl(browser_context, NULL); 379 380 // This makes |new_contents| act as a guest. 381 // For more info, see comment above class BrowserPluginGuest. 382 new_contents->browser_plugin_guest_.reset( 383 BrowserPluginGuest::Create(guest_instance_id, new_contents)); 384 385 WebContents::CreateParams create_params(browser_context, site_instance); 386 new_contents->Init(create_params); 387 388 // We are instantiating a WebContents for browser plugin. Set its subframe bit 389 // to true. 390 static_cast<RenderViewHostImpl*>( 391 new_contents->GetRenderViewHost())->set_is_subframe(true); 392 393 return new_contents->browser_plugin_guest_.get(); 394} 395 396WebPreferences WebContentsImpl::GetWebkitPrefs(RenderViewHost* rvh, 397 const GURL& url) { 398 WebPreferences prefs; 399 400 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 401 402 prefs.developer_extras_enabled = true; 403 prefs.javascript_enabled = 404 !command_line.HasSwitch(switches::kDisableJavaScript); 405 prefs.web_security_enabled = 406 !command_line.HasSwitch(switches::kDisableWebSecurity); 407 prefs.plugins_enabled = 408 !command_line.HasSwitch(switches::kDisablePlugins); 409 prefs.java_enabled = 410 !command_line.HasSwitch(switches::kDisableJava); 411 412 prefs.uses_page_cache = 413 command_line.HasSwitch(switches::kEnableFastback); 414 prefs.remote_fonts_enabled = 415 !command_line.HasSwitch(switches::kDisableRemoteFonts); 416 prefs.xss_auditor_enabled = 417 !command_line.HasSwitch(switches::kDisableXSSAuditor); 418 prefs.application_cache_enabled = 419 !command_line.HasSwitch(switches::kDisableApplicationCache); 420 421 prefs.local_storage_enabled = 422 !command_line.HasSwitch(switches::kDisableLocalStorage); 423 prefs.databases_enabled = 424 !command_line.HasSwitch(switches::kDisableDatabases); 425#if defined(OS_ANDROID) 426 prefs.webaudio_enabled = 427 command_line.HasSwitch(switches::kEnableWebAudio); 428#else 429 prefs.webaudio_enabled = 430 !command_line.HasSwitch(switches::kDisableWebAudio); 431#endif 432 433 prefs.experimental_webgl_enabled = 434 GpuProcessHost::gpu_enabled() && 435 !command_line.HasSwitch(switches::kDisable3DAPIs) && 436#if defined(OS_ANDROID) 437 command_line.HasSwitch(switches::kEnableExperimentalWebGL); 438#else 439 !command_line.HasSwitch(switches::kDisableExperimentalWebGL); 440#endif 441 442 prefs.flash_3d_enabled = 443 GpuProcessHost::gpu_enabled() && 444 !command_line.HasSwitch(switches::kDisableFlash3d); 445 prefs.flash_stage3d_enabled = 446 GpuProcessHost::gpu_enabled() && 447 !command_line.HasSwitch(switches::kDisableFlashStage3d); 448 prefs.flash_stage3d_baseline_enabled = 449 GpuProcessHost::gpu_enabled() && 450 !command_line.HasSwitch(switches::kDisableFlashStage3d); 451 452 prefs.gl_multisampling_enabled = 453 !command_line.HasSwitch(switches::kDisableGLMultisampling); 454 prefs.privileged_webgl_extensions_enabled = 455 command_line.HasSwitch(switches::kEnablePrivilegedWebGLExtensions); 456 prefs.site_specific_quirks_enabled = 457 !command_line.HasSwitch(switches::kDisableSiteSpecificQuirks); 458 prefs.allow_file_access_from_file_urls = 459 command_line.HasSwitch(switches::kAllowFileAccessFromFiles); 460 461 prefs.accelerated_compositing_for_overflow_scroll_enabled = false; 462 if (command_line.HasSwitch(switches::kEnableAcceleratedOverflowScroll)) 463 prefs.accelerated_compositing_for_overflow_scroll_enabled = true; 464 if (command_line.HasSwitch(switches::kDisableAcceleratedOverflowScroll)) 465 prefs.accelerated_compositing_for_overflow_scroll_enabled = false; 466 467 prefs.accelerated_compositing_for_scrollable_frames_enabled = 468 command_line.HasSwitch(switches::kEnableAcceleratedScrollableFrames); 469 prefs.composited_scrolling_for_frames_enabled = 470 command_line.HasSwitch(switches::kEnableCompositedScrollingForFrames); 471 prefs.show_paint_rects = 472 command_line.HasSwitch(switches::kShowPaintRects); 473 prefs.accelerated_compositing_enabled = 474 GpuProcessHost::gpu_enabled() && 475 !command_line.HasSwitch(switches::kDisableAcceleratedCompositing); 476 prefs.force_compositing_mode = 477 content::IsForceCompositingModeEnabled() && 478 !command_line.HasSwitch(switches::kDisableForceCompositingMode); 479 prefs.accelerated_2d_canvas_enabled = 480 GpuProcessHost::gpu_enabled() && 481 !command_line.HasSwitch(switches::kDisableAccelerated2dCanvas); 482 prefs.antialiased_2d_canvas_disabled = 483 command_line.HasSwitch(switches::kDisable2dCanvasAntialiasing); 484 prefs.accelerated_filters_enabled = 485 GpuProcessHost::gpu_enabled() && 486 command_line.HasSwitch(switches::kEnableAcceleratedFilters); 487 prefs.accelerated_compositing_for_3d_transforms_enabled = 488 prefs.accelerated_compositing_for_animation_enabled = 489 !command_line.HasSwitch(switches::kDisableAcceleratedLayers); 490 prefs.accelerated_compositing_for_plugins_enabled = 491 !command_line.HasSwitch(switches::kDisableAcceleratedPlugins); 492 prefs.accelerated_compositing_for_video_enabled = 493 !command_line.HasSwitch(switches::kDisableAcceleratedVideo); 494 prefs.fullscreen_enabled = 495 !command_line.HasSwitch(switches::kDisableFullScreen); 496 prefs.css_sticky_position_enabled = 497 command_line.HasSwitch(switches::kEnableExperimentalWebKitFeatures); 498 prefs.css_shaders_enabled = 499 command_line.HasSwitch(switches::kEnableCssShaders); 500 prefs.css_variables_enabled = 501 command_line.HasSwitch(switches::kEnableExperimentalWebKitFeatures); 502 prefs.css_grid_layout_enabled = 503 command_line.HasSwitch(switches::kEnableExperimentalWebKitFeatures); 504 prefs.threaded_html_parser = 505 !command_line.HasSwitch(switches::kDisableThreadedHTMLParser); 506#if defined(OS_ANDROID) 507 prefs.user_gesture_required_for_media_playback = !command_line.HasSwitch( 508 switches::kDisableGestureRequirementForMediaPlayback); 509#endif 510 511 bool touch_device_present = false; 512 touch_device_present = ui::IsTouchDevicePresent(); 513 const std::string touch_enabled_switch = 514 command_line.HasSwitch(switches::kTouchEvents) ? 515 command_line.GetSwitchValueASCII(switches::kTouchEvents) : 516 switches::kTouchEventsAuto; 517 518 if (touch_enabled_switch.empty() || 519 touch_enabled_switch == switches::kTouchEventsEnabled) { 520 prefs.touch_enabled = true; 521 } else if (touch_enabled_switch == switches::kTouchEventsAuto) { 522 prefs.touch_enabled = touch_device_present; 523 } else if (touch_enabled_switch != switches::kTouchEventsDisabled) { 524 LOG(ERROR) << "Invalid --touch-events option: " << touch_enabled_switch; 525 } 526 527 prefs.device_supports_touch = prefs.touch_enabled && touch_device_present; 528#if defined(OS_ANDROID) 529 prefs.device_supports_mouse = false; 530#endif 531 532 prefs.touch_adjustment_enabled = 533 !command_line.HasSwitch(switches::kDisableTouchAdjustment); 534 535#if defined(OS_MACOSX) || defined(OS_CHROMEOS) 536 bool default_enable_scroll_animator = true; 537#else 538 bool default_enable_scroll_animator = false; 539#endif 540 prefs.enable_scroll_animator = default_enable_scroll_animator; 541 if (command_line.HasSwitch(switches::kEnableSmoothScrolling)) 542 prefs.enable_scroll_animator = true; 543 if (command_line.HasSwitch(switches::kDisableSmoothScrolling)) 544 prefs.enable_scroll_animator = false; 545 546 prefs.visual_word_movement_enabled = 547 command_line.HasSwitch(switches::kEnableVisualWordMovement); 548 549 { // Certain GPU features might have been blacklisted. 550 GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance(); 551 DCHECK(gpu_data_manager); 552 uint32 blacklist_type = gpu_data_manager->GetBlacklistedFeatures(); 553 if (blacklist_type & GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) 554 prefs.accelerated_compositing_enabled = false; 555 if (blacklist_type & GPU_FEATURE_TYPE_WEBGL) 556 prefs.experimental_webgl_enabled = false; 557 if (blacklist_type & GPU_FEATURE_TYPE_FLASH3D) 558 prefs.flash_3d_enabled = false; 559 if (blacklist_type & GPU_FEATURE_TYPE_FLASH_STAGE3D) { 560 prefs.flash_stage3d_enabled = false; 561 prefs.flash_stage3d_baseline_enabled = false; 562 } 563 if (blacklist_type & GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE) 564 prefs.flash_stage3d_baseline_enabled = false; 565 if (blacklist_type & GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS) 566 prefs.accelerated_2d_canvas_enabled = false; 567 if (blacklist_type & GPU_FEATURE_TYPE_MULTISAMPLING) 568 prefs.gl_multisampling_enabled = false; 569 if (blacklist_type & GPU_FEATURE_TYPE_3D_CSS) { 570 prefs.accelerated_compositing_for_3d_transforms_enabled = false; 571 prefs.accelerated_compositing_for_animation_enabled = false; 572 } 573 if (blacklist_type & GPU_FEATURE_TYPE_ACCELERATED_VIDEO) 574 prefs.accelerated_compositing_for_video_enabled = false; 575 576 // Accelerated video and animation are slower than regular when using a 577 // software 3d rasterizer. 3D CSS may also be too slow to be worthwhile. 578 if (gpu_data_manager->ShouldUseSoftwareRendering()) { 579 prefs.accelerated_compositing_for_video_enabled = false; 580 prefs.accelerated_compositing_for_animation_enabled = false; 581 prefs.accelerated_compositing_for_3d_transforms_enabled = false; 582 prefs.accelerated_compositing_for_plugins_enabled = false; 583 } 584 } 585 586 if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( 587 rvh->GetProcess()->GetID())) { 588 prefs.loads_images_automatically = true; 589 prefs.javascript_enabled = true; 590 } 591 592 prefs.is_online = !net::NetworkChangeNotifier::IsOffline(); 593 594 // Force accelerated compositing and 2d canvas off for chrome: and about: 595 // pages (unless it's specifically allowed). 596 if ((url.SchemeIs(chrome::kChromeUIScheme) || 597 (url.SchemeIs(chrome::kAboutScheme) && 598 url.spec() != chrome::kAboutBlankURL)) && 599 !command_line.HasSwitch(switches::kAllowWebUICompositing)) { 600 prefs.accelerated_compositing_enabled = false; 601 prefs.accelerated_2d_canvas_enabled = false; 602 } 603 604 prefs.apply_default_device_scale_factor_in_compositor = true; 605 prefs.apply_page_scale_factor_in_compositor = true; 606 607 prefs.fixed_position_creates_stacking_context = !command_line.HasSwitch( 608 switches::kDisableFixedPositionCreatesStackingContext); 609 610#if defined(OS_CHROMEOS) 611 prefs.gesture_tap_highlight_enabled = !command_line.HasSwitch( 612 switches::kDisableGestureTapHighlight); 613#else 614 prefs.gesture_tap_highlight_enabled = command_line.HasSwitch( 615 switches::kEnableGestureTapHighlight); 616#endif 617 618 prefs.number_of_cpu_cores = base::SysInfo::NumberOfProcessors(); 619 620 prefs.viewport_enabled = command_line.HasSwitch(switches::kEnableViewport); 621 622 prefs.deferred_image_decoding_enabled = 623 command_line.HasSwitch(switches::kEnableDeferredImageDecoding) || 624 cc::switches::IsImplSidePaintingEnabled(); 625 626 GetContentClient()->browser()->OverrideWebkitPrefs(rvh, url, &prefs); 627 628 // Disable compositing in guests until we have compositing path implemented 629 // for guests. 630 bool guest_compositing_enabled = !command_line.HasSwitch( 631 switches::kDisableBrowserPluginCompositing); 632 if (rvh->GetProcess()->IsGuest() && !guest_compositing_enabled) { 633 prefs.force_compositing_mode = false; 634 prefs.accelerated_compositing_enabled = false; 635 } 636 637 return prefs; 638} 639 640RenderViewHostManager* WebContentsImpl::GetRenderManagerForTesting() { 641 return &render_manager_; 642} 643 644bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host, 645 const IPC::Message& message) { 646 if (GetWebUI() && 647 static_cast<WebUIImpl*>(GetWebUI())->OnMessageReceived(message)) { 648 return true; 649 } 650 651 ObserverListBase<WebContentsObserver>::Iterator it(observers_); 652 WebContentsObserver* observer; 653 while ((observer = it.GetNext()) != NULL) 654 if (observer->OnMessageReceived(message)) 655 return true; 656 657 // Message handlers should be aware of which RenderViewHost sent the 658 // message, which is temporarily stored in message_source_. 659 message_source_ = render_view_host; 660 bool handled = true; 661 bool message_is_ok = true; 662 IPC_BEGIN_MESSAGE_MAP_EX(WebContentsImpl, message, message_is_ok) 663 IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache, 664 OnDidLoadResourceFromMemoryCache) 665 IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent, 666 OnDidDisplayInsecureContent) 667 IPC_MESSAGE_HANDLER(ViewHostMsg_DidRunInsecureContent, 668 OnDidRunInsecureContent) 669 IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentLoadedInFrame, 670 OnDocumentLoadedInFrame) 671 IPC_MESSAGE_HANDLER(ViewHostMsg_DidFinishLoad, OnDidFinishLoad) 672 IPC_MESSAGE_HANDLER(ViewHostMsg_DidFailLoadWithError, 673 OnDidFailLoadWithError) 674 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateContentRestrictions, 675 OnUpdateContentRestrictions) 676 IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset, OnGoToEntryAtOffset) 677 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits, OnUpdateZoomLimits) 678 IPC_MESSAGE_HANDLER(ViewHostMsg_SaveURLAs, OnSaveURL) 679 IPC_MESSAGE_HANDLER(ViewHostMsg_EnumerateDirectory, OnEnumerateDirectory) 680 IPC_MESSAGE_HANDLER(ViewHostMsg_JSOutOfMemory, OnJSOutOfMemory) 681 IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler, 682 OnRegisterProtocolHandler) 683 IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnFindReply) 684 IPC_MESSAGE_HANDLER(ViewHostMsg_CrashedPlugin, OnCrashedPlugin) 685 IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed, OnAppCacheAccessed) 686 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenColorChooser, OnOpenColorChooser) 687 IPC_MESSAGE_HANDLER(ViewHostMsg_EndColorChooser, OnEndColorChooser) 688 IPC_MESSAGE_HANDLER(ViewHostMsg_SetSelectedColorInColorChooser, 689 OnSetSelectedColorInColorChooser) 690 IPC_MESSAGE_HANDLER(ViewHostMsg_PepperPluginHung, OnPepperPluginHung) 691 IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnWebUISend) 692 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission, 693 OnRequestPpapiBrokerPermission) 694 IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_AllocateInstanceID, 695 OnBrowserPluginMessage(message)) 696 IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_Attach, 697 OnBrowserPluginMessage(message)) 698 IPC_MESSAGE_HANDLER(IconHostMsg_DidDownloadFavicon, OnDidDownloadFavicon) 699 IPC_MESSAGE_HANDLER(IconHostMsg_UpdateFaviconURL, OnUpdateFaviconURL) 700#if defined(OS_ANDROID) 701 IPC_MESSAGE_HANDLER(ViewHostMsg_FindMatchRects_Reply, 702 OnFindMatchRectsReply) 703 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog, 704 OnOpenDateTimeDialog) 705#endif 706 IPC_MESSAGE_HANDLER(ViewHostMsg_FrameDetached, OnFrameDetached) 707 IPC_MESSAGE_UNHANDLED(handled = false) 708 IPC_END_MESSAGE_MAP_EX() 709 message_source_ = NULL; 710 711 if (!message_is_ok) { 712 RecordAction(UserMetricsAction("BadMessageTerminate_RVD")); 713 GetRenderProcessHost()->ReceivedBadMessage(); 714 } 715 716 return handled; 717} 718 719void WebContentsImpl::RunFileChooser( 720 RenderViewHost* render_view_host, 721 const FileChooserParams& params) { 722 if (delegate_) 723 delegate_->RunFileChooser(this, params); 724} 725 726NavigationControllerImpl& WebContentsImpl::GetController() { 727 return controller_; 728} 729 730const NavigationControllerImpl& WebContentsImpl::GetController() const { 731 return controller_; 732} 733 734BrowserContext* WebContentsImpl::GetBrowserContext() const { 735 return controller_.GetBrowserContext(); 736} 737 738const GURL& WebContentsImpl::GetURL() const { 739 // We may not have a navigation entry yet 740 NavigationEntry* entry = controller_.GetActiveEntry(); 741 return entry ? entry->GetVirtualURL() : GURL::EmptyGURL(); 742} 743 744WebContentsDelegate* WebContentsImpl::GetDelegate() { 745 return delegate_; 746} 747 748void WebContentsImpl::SetDelegate(WebContentsDelegate* delegate) { 749 // TODO(cbentzel): remove this debugging code? 750 if (delegate == delegate_) 751 return; 752 if (delegate_) 753 delegate_->Detach(this); 754 delegate_ = delegate; 755 if (delegate_) { 756 delegate_->Attach(this); 757 // Ensure the visible RVH reflects the new delegate's preferences. 758 if (view_) 759 view_->SetOverscrollControllerEnabled(delegate->CanOverscrollContent()); 760 } 761} 762 763RenderProcessHost* WebContentsImpl::GetRenderProcessHost() const { 764 RenderViewHostImpl* host = render_manager_.current_host(); 765 return host ? host->GetProcess() : NULL; 766} 767 768RenderViewHost* WebContentsImpl::GetRenderViewHost() const { 769 return render_manager_.current_host(); 770} 771 772void WebContentsImpl::GetRenderViewHostAtPosition( 773 int x, 774 int y, 775 const base::Callback<void(RenderViewHost*, int, int)>& callback) { 776 BrowserPluginEmbedder* embedder = GetBrowserPluginEmbedder(); 777 if (embedder) 778 embedder->GetRenderViewHostAtPosition(x, y, callback); 779 else 780 callback.Run(GetRenderViewHost(), x, y); 781} 782 783WebContents* WebContentsImpl::GetEmbedderWebContents() const { 784 BrowserPluginGuest* guest = GetBrowserPluginGuest(); 785 if (guest) 786 return guest->embedder_web_contents(); 787 return NULL; 788} 789 790int WebContentsImpl::GetEmbeddedInstanceID() const { 791 BrowserPluginGuest* guest = GetBrowserPluginGuest(); 792 if (guest) 793 return guest->instance_id(); 794 return 0; 795} 796 797int WebContentsImpl::GetRoutingID() const { 798 if (!GetRenderViewHost()) 799 return MSG_ROUTING_NONE; 800 801 return GetRenderViewHost()->GetRoutingID(); 802} 803 804int WebContentsImpl::GetFullscreenWidgetRoutingID() const { 805 return fullscreen_widget_routing_id_; 806} 807 808RenderWidgetHostView* WebContentsImpl::GetRenderWidgetHostView() const { 809 return render_manager_.GetRenderWidgetHostView(); 810} 811 812RenderWidgetHostViewPort* WebContentsImpl::GetRenderWidgetHostViewPort() const { 813 BrowserPluginGuest* guest = GetBrowserPluginGuest(); 814 if (guest && guest->embedder_web_contents()) { 815 return guest->embedder_web_contents()->GetRenderWidgetHostViewPort(); 816 } 817 return RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView()); 818} 819 820WebContentsView* WebContentsImpl::GetView() const { 821 return view_.get(); 822} 823 824WebUI* WebContentsImpl::CreateWebUI(const GURL& url) { 825 WebUIImpl* web_ui = new WebUIImpl(this); 826 WebUIController* controller = WebUIControllerFactoryRegistry::GetInstance()-> 827 CreateWebUIControllerForURL(web_ui, url); 828 if (controller) { 829 web_ui->AddMessageHandler(new GenericHandler()); 830 web_ui->SetController(controller); 831 return web_ui; 832 } 833 834 delete web_ui; 835 return NULL; 836} 837 838WebUI* WebContentsImpl::GetWebUI() const { 839 return render_manager_.web_ui() ? render_manager_.web_ui() 840 : render_manager_.pending_web_ui(); 841} 842 843WebUI* WebContentsImpl::GetCommittedWebUI() const { 844 return render_manager_.web_ui(); 845} 846 847void WebContentsImpl::SetUserAgentOverride(const std::string& override) { 848 if (GetUserAgentOverride() == override) 849 return; 850 851 renderer_preferences_.user_agent_override = override; 852 853 // Send the new override string to the renderer. 854 RenderViewHost* host = GetRenderViewHost(); 855 if (host) 856 host->SyncRendererPrefs(); 857 858 // Reload the page if a load is currently in progress to avoid having 859 // different parts of the page loaded using different user agents. 860 NavigationEntry* entry = controller_.GetActiveEntry(); 861 if (is_loading_ && entry != NULL && entry->GetIsOverridingUserAgent()) 862 controller_.ReloadIgnoringCache(true); 863 864 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 865 UserAgentOverrideSet(override)); 866} 867 868const std::string& WebContentsImpl::GetUserAgentOverride() const { 869 return renderer_preferences_.user_agent_override; 870} 871 872const string16& WebContentsImpl::GetTitle() const { 873 // Transient entries take precedence. They are used for interstitial pages 874 // that are shown on top of existing pages. 875 NavigationEntry* entry = controller_.GetTransientEntry(); 876 std::string accept_languages = 877 GetContentClient()->browser()->GetAcceptLangs( 878 GetBrowserContext()); 879 if (entry) { 880 return entry->GetTitleForDisplay(accept_languages); 881 } 882 WebUI* our_web_ui = render_manager_.pending_web_ui() ? 883 render_manager_.pending_web_ui() : render_manager_.web_ui(); 884 if (our_web_ui) { 885 // Don't override the title in view source mode. 886 entry = controller_.GetActiveEntry(); 887 if (!(entry && entry->IsViewSourceMode())) { 888 // Give the Web UI the chance to override our title. 889 const string16& title = our_web_ui->GetOverriddenTitle(); 890 if (!title.empty()) 891 return title; 892 } 893 } 894 895 // We use the title for the last committed entry rather than a pending 896 // navigation entry. For example, when the user types in a URL, we want to 897 // keep the old page's title until the new load has committed and we get a new 898 // title. 899 entry = controller_.GetLastCommittedEntry(); 900 if (entry) { 901 return entry->GetTitleForDisplay(accept_languages); 902 } 903 904 // |page_title_when_no_navigation_entry_| is finally used 905 // if no title cannot be retrieved. 906 return page_title_when_no_navigation_entry_; 907} 908 909int32 WebContentsImpl::GetMaxPageID() { 910 return GetMaxPageIDForSiteInstance(GetSiteInstance()); 911} 912 913int32 WebContentsImpl::GetMaxPageIDForSiteInstance( 914 SiteInstance* site_instance) { 915 if (max_page_ids_.find(site_instance->GetId()) == max_page_ids_.end()) 916 max_page_ids_[site_instance->GetId()] = -1; 917 918 return max_page_ids_[site_instance->GetId()]; 919} 920 921void WebContentsImpl::UpdateMaxPageID(int32 page_id) { 922 UpdateMaxPageIDForSiteInstance(GetSiteInstance(), page_id); 923} 924 925void WebContentsImpl::UpdateMaxPageIDForSiteInstance( 926 SiteInstance* site_instance, int32 page_id) { 927 if (GetMaxPageIDForSiteInstance(site_instance) < page_id) 928 max_page_ids_[site_instance->GetId()] = page_id; 929} 930 931void WebContentsImpl::CopyMaxPageIDsFrom(WebContentsImpl* web_contents) { 932 max_page_ids_ = web_contents->max_page_ids_; 933} 934 935SiteInstance* WebContentsImpl::GetSiteInstance() const { 936 return render_manager_.current_host()->GetSiteInstance(); 937} 938 939SiteInstance* WebContentsImpl::GetPendingSiteInstance() const { 940 RenderViewHost* dest_rvh = render_manager_.pending_render_view_host() ? 941 render_manager_.pending_render_view_host() : 942 render_manager_.current_host(); 943 return dest_rvh->GetSiteInstance(); 944} 945 946bool WebContentsImpl::IsLoading() const { 947 return is_loading_; 948} 949 950bool WebContentsImpl::IsWaitingForResponse() const { 951 return waiting_for_response_; 952} 953 954const net::LoadStateWithParam& WebContentsImpl::GetLoadState() const { 955 return load_state_; 956} 957 958const string16& WebContentsImpl::GetLoadStateHost() const { 959 return load_state_host_; 960} 961 962uint64 WebContentsImpl::GetUploadSize() const { 963 return upload_size_; 964} 965 966uint64 WebContentsImpl::GetUploadPosition() const { 967 return upload_position_; 968} 969 970const std::string& WebContentsImpl::GetEncoding() const { 971 return encoding_; 972} 973 974bool WebContentsImpl::DisplayedInsecureContent() const { 975 return displayed_insecure_content_; 976} 977 978void WebContentsImpl::IncrementCapturerCount() { 979 DCHECK(!is_being_destroyed_); 980 ++capturer_count_; 981 DVLOG(1) << "There are now " << capturer_count_ 982 << " capturing(s) of WebContentsImpl@" << this; 983} 984 985void WebContentsImpl::DecrementCapturerCount() { 986 --capturer_count_; 987 DVLOG(1) << "There are now " << capturer_count_ 988 << " capturing(s) of WebContentsImpl@" << this; 989 DCHECK_LE(0, capturer_count_); 990 991 if (is_being_destroyed_) 992 return; 993 994 // While capturer_count_ was greater than zero, the WasHidden() calls to RWHV 995 // were being prevented. If there are no more capturers, make the call now. 996 if (capturer_count_ == 0 && !should_normally_be_visible_) { 997 DVLOG(1) << "Executing delayed WasHidden()."; 998 WasHidden(); 999 } 1000} 1001 1002bool WebContentsImpl::IsCrashed() const { 1003 return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED || 1004 crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION || 1005 crashed_status_ == base::TERMINATION_STATUS_PROCESS_WAS_KILLED); 1006} 1007 1008void WebContentsImpl::SetIsCrashed(base::TerminationStatus status, 1009 int error_code) { 1010 if (status == crashed_status_) 1011 return; 1012 1013 crashed_status_ = status; 1014 crashed_error_code_ = error_code; 1015 NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB); 1016} 1017 1018base::TerminationStatus WebContentsImpl::GetCrashedStatus() const { 1019 return crashed_status_; 1020} 1021 1022bool WebContentsImpl::IsBeingDestroyed() const { 1023 return is_being_destroyed_; 1024} 1025 1026void WebContentsImpl::NotifyNavigationStateChanged(unsigned changed_flags) { 1027 if (delegate_) 1028 delegate_->NavigationStateChanged(this, changed_flags); 1029} 1030 1031base::TimeTicks WebContentsImpl::GetLastSelectedTime() const { 1032 return last_selected_time_; 1033} 1034 1035void WebContentsImpl::WasShown() { 1036 controller_.SetActive(true); 1037 RenderWidgetHostViewPort* rwhv = 1038 RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView()); 1039 if (rwhv) { 1040 rwhv->WasShown(); 1041#if defined(OS_MACOSX) 1042 rwhv->SetActive(true); 1043#endif 1044 } 1045 1046 last_selected_time_ = base::TimeTicks::Now(); 1047 1048 FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasShown()); 1049 1050 // The resize rect might have changed while this was inactive -- send the new 1051 // one to make sure it's up to date. 1052 RenderViewHostImpl* rvh = 1053 static_cast<RenderViewHostImpl*>(GetRenderViewHost()); 1054 if (rvh) { 1055 rvh->ResizeRectChanged(GetRootWindowResizerRect()); 1056 } 1057 1058 should_normally_be_visible_ = true; 1059 NotificationService::current()->Notify( 1060 NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED, 1061 Source<WebContents>(this), 1062 Details<const bool>(&should_normally_be_visible_)); 1063} 1064 1065void WebContentsImpl::WasHidden() { 1066 // If there are entities capturing screenshots or video (e.g., mirroring), 1067 // don't activate the "disable rendering" optimization. 1068 if (capturer_count_ == 0) { 1069 // |GetRenderViewHost()| can be NULL if the user middle clicks a link to 1070 // open a tab in the background, then closes the tab before selecting it. 1071 // This is because closing the tab calls WebContentsImpl::Destroy(), which 1072 // removes the |GetRenderViewHost()|; then when we actually destroy the 1073 // window, OnWindowPosChanged() notices and calls WasHidden() (which 1074 // calls us). 1075 RenderWidgetHostViewPort* rwhv = 1076 RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView()); 1077 if (rwhv) 1078 rwhv->WasHidden(); 1079 } 1080 1081 should_normally_be_visible_ = false; 1082 NotificationService::current()->Notify( 1083 NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED, 1084 Source<WebContents>(this), 1085 Details<const bool>(&should_normally_be_visible_)); 1086} 1087 1088bool WebContentsImpl::NeedToFireBeforeUnload() { 1089 // TODO(creis): Should we fire even for interstitial pages? 1090 return WillNotifyDisconnection() && 1091 !ShowingInterstitialPage() && 1092 !static_cast<RenderViewHostImpl*>( 1093 GetRenderViewHost())->SuddenTerminationAllowed(); 1094} 1095 1096void WebContentsImpl::Stop() { 1097 render_manager_.Stop(); 1098 FOR_EACH_OBSERVER(WebContentsObserver, observers_, StopNavigation()); 1099} 1100 1101WebContents* WebContentsImpl::Clone() { 1102 // We use our current SiteInstance since the cloned entry will use it anyway. 1103 // We pass our own opener so that the cloned page can access it if it was 1104 // before. 1105 CreateParams create_params(GetBrowserContext(), GetSiteInstance()); 1106 create_params.initial_size = view_->GetContainerSize(); 1107 WebContentsImpl* tc = CreateWithOpener(create_params, opener_); 1108 tc->GetController().CopyStateFrom(controller_); 1109 FOR_EACH_OBSERVER(WebContentsObserver, 1110 observers_, 1111 DidCloneToNewWebContents(this, tc)); 1112 return tc; 1113} 1114 1115void WebContentsImpl::Observe(int type, 1116 const NotificationSource& source, 1117 const NotificationDetails& details) { 1118 switch (type) { 1119 case NOTIFICATION_WEB_CONTENTS_DESTROYED: 1120 OnWebContentsDestroyed(Source<WebContents>(source).ptr()); 1121 break; 1122 case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED: { 1123 RenderWidgetHost* host = Source<RenderWidgetHost>(source).ptr(); 1124 for (PendingWidgetViews::iterator i = pending_widget_views_.begin(); 1125 i != pending_widget_views_.end(); ++i) { 1126 if (host->GetView() == i->second) { 1127 pending_widget_views_.erase(i); 1128 break; 1129 } 1130 } 1131 break; 1132 } 1133 default: 1134 NOTREACHED(); 1135 } 1136} 1137 1138void WebContentsImpl::Init(const WebContents::CreateParams& params) { 1139 render_manager_.Init( 1140 params.browser_context, params.site_instance, params.routing_id); 1141 1142 view_.reset(GetContentClient()->browser()-> 1143 OverrideCreateWebContentsView(this, &render_view_host_delegate_view_)); 1144 if (view_.get()) { 1145 CHECK(render_view_host_delegate_view_); 1146 } else { 1147 WebContentsViewDelegate* delegate = 1148 GetContentClient()->browser()->GetWebContentsViewDelegate(this); 1149 1150 if (browser_plugin_guest_.get()) { 1151 WebContentsViewPort* platform_view = CreateWebContentsView( 1152 this, delegate, &render_view_host_delegate_view_); 1153 1154 WebContentsViewGuest* rv = new WebContentsViewGuest( 1155 this, browser_plugin_guest_.get(), platform_view); 1156 render_view_host_delegate_view_ = rv; 1157 view_.reset(rv); 1158 } else { 1159 // Regular WebContentsView. 1160 view_.reset(CreateWebContentsView( 1161 this, delegate, &render_view_host_delegate_view_)); 1162 } 1163 CHECK(render_view_host_delegate_view_); 1164 } 1165 CHECK(view_.get()); 1166 1167 gfx::Size initial_size = params.initial_size; 1168 view_->CreateView(initial_size, params.context); 1169 1170 // Listen for whether our opener gets destroyed. 1171 if (opener_) { 1172 registrar_.Add(this, NOTIFICATION_WEB_CONTENTS_DESTROYED, 1173 Source<WebContents>(opener_)); 1174 } 1175 1176 registrar_.Add(this, 1177 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, 1178 NotificationService::AllBrowserContextsAndSources()); 1179#if defined(ENABLE_JAVA_BRIDGE) 1180 java_bridge_dispatcher_host_manager_.reset( 1181 new JavaBridgeDispatcherHostManager(this)); 1182#endif 1183 1184#if defined(OS_ANDROID) 1185 date_time_chooser_.reset(new DateTimeChooserAndroid()); 1186#endif 1187} 1188 1189void WebContentsImpl::OnWebContentsDestroyed(WebContents* web_contents) { 1190 // Clear the opener if it has been closed. 1191 if (web_contents == opener_) { 1192 registrar_.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED, 1193 Source<WebContents>(opener_)); 1194 opener_ = NULL; 1195 return; 1196 } 1197 // Clear a pending contents that has been closed before being shown. 1198 for (PendingContents::iterator iter = pending_contents_.begin(); 1199 iter != pending_contents_.end(); 1200 ++iter) { 1201 if (iter->second != web_contents) 1202 continue; 1203 pending_contents_.erase(iter); 1204 registrar_.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED, 1205 Source<WebContents>(web_contents)); 1206 return; 1207 } 1208 NOTREACHED(); 1209} 1210 1211void WebContentsImpl::AddObserver(WebContentsObserver* observer) { 1212 observers_.AddObserver(observer); 1213} 1214 1215void WebContentsImpl::RemoveObserver(WebContentsObserver* observer) { 1216 observers_.RemoveObserver(observer); 1217} 1218 1219void WebContentsImpl::Activate() { 1220 if (delegate_) 1221 delegate_->ActivateContents(this); 1222} 1223 1224void WebContentsImpl::Deactivate() { 1225 if (delegate_) 1226 delegate_->DeactivateContents(this); 1227} 1228 1229void WebContentsImpl::LostCapture() { 1230 if (delegate_) 1231 delegate_->LostCapture(); 1232} 1233 1234void WebContentsImpl::RenderWidgetDeleted( 1235 RenderWidgetHostImpl* render_widget_host) { 1236 if (is_being_destroyed_) { 1237 // |created_widgets_| might have been destroyed. 1238 return; 1239 } 1240 1241 std::set<RenderWidgetHostImpl*>::iterator iter = 1242 created_widgets_.find(render_widget_host); 1243 if (iter != created_widgets_.end()) 1244 created_widgets_.erase(iter); 1245 1246 if (render_widget_host && 1247 render_widget_host->GetRoutingID() == fullscreen_widget_routing_id_) { 1248 FOR_EACH_OBSERVER(WebContentsObserver, 1249 observers_, 1250 DidDestroyFullscreenWidget( 1251 fullscreen_widget_routing_id_)); 1252 fullscreen_widget_routing_id_ = MSG_ROUTING_NONE; 1253 } 1254} 1255 1256bool WebContentsImpl::PreHandleKeyboardEvent( 1257 const NativeWebKeyboardEvent& event, 1258 bool* is_keyboard_shortcut) { 1259 return delegate_ && 1260 delegate_->PreHandleKeyboardEvent(this, event, is_keyboard_shortcut); 1261} 1262 1263void WebContentsImpl::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { 1264 if (delegate_) 1265 delegate_->HandleKeyboardEvent(this, event); 1266} 1267 1268bool WebContentsImpl::PreHandleWheelEvent( 1269 const WebKit::WebMouseWheelEvent& event) { 1270 if (delegate_ && 1271 event.wheelTicksY && 1272 (event.modifiers & WebKit::WebInputEvent::ControlKey)) { 1273 delegate_->ContentsZoomChange(event.wheelTicksY > 0); 1274 return true; 1275 } 1276 1277 return false; 1278} 1279 1280void WebContentsImpl::HandleMouseDown() { 1281 if (delegate_) 1282 delegate_->HandleMouseDown(); 1283} 1284 1285void WebContentsImpl::HandleMouseUp() { 1286 if (delegate_) 1287 delegate_->HandleMouseUp(); 1288} 1289 1290void WebContentsImpl::HandlePointerActivate() { 1291 if (delegate_) 1292 delegate_->HandlePointerActivate(); 1293} 1294 1295void WebContentsImpl::HandleGestureBegin() { 1296 if (delegate_) 1297 delegate_->HandleGestureBegin(); 1298} 1299 1300void WebContentsImpl::HandleGestureEnd() { 1301 if (delegate_) 1302 delegate_->HandleGestureEnd(); 1303} 1304 1305void WebContentsImpl::ToggleFullscreenMode(bool enter_fullscreen) { 1306 if (delegate_) 1307 delegate_->ToggleFullscreenModeForTab(this, enter_fullscreen); 1308} 1309 1310bool WebContentsImpl::IsFullscreenForCurrentTab() const { 1311 return delegate_ ? delegate_->IsFullscreenForTabOrPending(this) : false; 1312} 1313 1314void WebContentsImpl::RequestToLockMouse(bool user_gesture, 1315 bool last_unlocked_by_target) { 1316 if (delegate_) { 1317 delegate_->RequestToLockMouse(this, user_gesture, last_unlocked_by_target); 1318 } else { 1319 GotResponseToLockMouseRequest(false); 1320 } 1321} 1322 1323void WebContentsImpl::LostMouseLock() { 1324 if (delegate_) 1325 delegate_->LostMouseLock(); 1326} 1327 1328void WebContentsImpl::CreateNewWindow( 1329 int route_id, 1330 const ViewHostMsg_CreateWindow_Params& params, 1331 SessionStorageNamespace* session_storage_namespace) { 1332 if (delegate_ && !delegate_->ShouldCreateWebContents( 1333 this, route_id, params.window_container_type, params.frame_name, 1334 params.target_url)) { 1335 GetRenderViewHost()->GetProcess()->ResumeRequestsForView(route_id); 1336 return; 1337 } 1338 1339 // We usually create the new window in the same BrowsingInstance (group of 1340 // script-related windows), by passing in the current SiteInstance. However, 1341 // if the opener is being suppressed (in a non-guest), we create a new 1342 // SiteInstance in its own BrowsingInstance. 1343 bool is_guest = GetRenderProcessHost()->IsGuest(); 1344 1345 scoped_refptr<SiteInstance> site_instance = 1346 params.opener_suppressed && !is_guest ? 1347 SiteInstance::CreateForURL(GetBrowserContext(), params.target_url) : 1348 GetSiteInstance(); 1349 1350 // Create the new web contents. This will automatically create the new 1351 // WebContentsView. In the future, we may want to create the view separately. 1352 WebContentsImpl* new_contents = 1353 new WebContentsImpl(GetBrowserContext(), 1354 params.opener_suppressed ? NULL : this); 1355 1356 // We must assign the SessionStorageNamespace before calling Init(). 1357 // 1358 // http://crbug.com/142685 1359 const std::string& partition_id = 1360 GetContentClient()->browser()-> 1361 GetStoragePartitionIdForSite(GetBrowserContext(), 1362 site_instance->GetSiteURL()); 1363 StoragePartition* partition = 1364 BrowserContext::GetStoragePartition(GetBrowserContext(), 1365 site_instance); 1366 DOMStorageContextImpl* dom_storage_context = 1367 static_cast<DOMStorageContextImpl*>(partition->GetDOMStorageContext()); 1368 SessionStorageNamespaceImpl* session_storage_namespace_impl = 1369 static_cast<SessionStorageNamespaceImpl*>(session_storage_namespace); 1370 CHECK(session_storage_namespace_impl->IsFromContext(dom_storage_context)); 1371 new_contents->GetController().SetSessionStorageNamespace( 1372 partition_id, 1373 session_storage_namespace); 1374 CreateParams create_params(GetBrowserContext(), site_instance); 1375 create_params.routing_id = route_id; 1376 if (!is_guest) { 1377 create_params.context = view_->GetNativeView(); 1378 create_params.initial_size = view_->GetContainerSize(); 1379 } else { 1380 // This makes |new_contents| act as a guest. 1381 // For more info, see comment above class BrowserPluginGuest. 1382 int instance_id = GetBrowserPluginGuestManager()->get_next_instance_id(); 1383 WebContentsImpl* new_contents_impl = 1384 static_cast<WebContentsImpl*>(new_contents); 1385 new_contents_impl->browser_plugin_guest_.reset( 1386 BrowserPluginGuest::Create(instance_id, new_contents_impl)); 1387 } 1388 new_contents->Init(create_params); 1389 1390 // Save the window for later if we're not suppressing the opener (since it 1391 // will be shown immediately) and if it's not a guest (since we separately 1392 // track when to show guests). 1393 if (!params.opener_suppressed && !is_guest) { 1394 WebContentsViewPort* new_view = new_contents->view_.get(); 1395 1396 // TODO(brettw): It seems bogus that we have to call this function on the 1397 // newly created object and give it one of its own member variables. 1398 new_view->CreateViewForWidget(new_contents->GetRenderViewHost()); 1399 1400 // Save the created window associated with the route so we can show it 1401 // later. 1402 DCHECK_NE(MSG_ROUTING_NONE, route_id); 1403 pending_contents_[route_id] = new_contents; 1404 registrar_.Add(this, NOTIFICATION_WEB_CONTENTS_DESTROYED, 1405 Source<WebContents>(new_contents)); 1406 } 1407 1408 if (delegate_) { 1409 delegate_->WebContentsCreated( 1410 this, params.opener_frame_id, params.frame_name, 1411 params.target_url, new_contents); 1412 } 1413 1414 if (params.opener_suppressed) { 1415 // When the opener is suppressed, the original renderer cannot access the 1416 // new window. As a result, we need to show and navigate the window here. 1417 bool was_blocked = false; 1418 if (delegate_) { 1419 gfx::Rect initial_pos; 1420 delegate_->AddNewContents( 1421 this, new_contents, params.disposition, initial_pos, 1422 params.user_gesture, &was_blocked); 1423 } 1424 if (!was_blocked) { 1425 OpenURLParams open_params(params.target_url, 1426 Referrer(), 1427 CURRENT_TAB, 1428 PAGE_TRANSITION_LINK, 1429 true /* is_renderer_initiated */); 1430 new_contents->OpenURL(open_params); 1431 } 1432 } 1433} 1434 1435void WebContentsImpl::CreateNewWidget(int route_id, 1436 WebKit::WebPopupType popup_type) { 1437 CreateNewWidget(route_id, false, popup_type); 1438} 1439 1440void WebContentsImpl::CreateNewFullscreenWidget(int route_id) { 1441 CreateNewWidget(route_id, true, WebKit::WebPopupTypeNone); 1442} 1443 1444void WebContentsImpl::CreateNewWidget(int route_id, 1445 bool is_fullscreen, 1446 WebKit::WebPopupType popup_type) { 1447 RenderProcessHost* process = GetRenderProcessHost(); 1448 RenderWidgetHostImpl* widget_host = 1449 new RenderWidgetHostImpl(this, process, route_id); 1450 created_widgets_.insert(widget_host); 1451 1452 RenderWidgetHostViewPort* widget_view = RenderWidgetHostViewPort::FromRWHV( 1453 view_->CreateViewForPopupWidget(widget_host)); 1454 if (!widget_view) 1455 return; 1456 if (!is_fullscreen) { 1457 // Popups should not get activated. 1458 widget_view->SetPopupType(popup_type); 1459 } 1460 // Save the created widget associated with the route so we can show it later. 1461 pending_widget_views_[route_id] = widget_view; 1462 1463#if defined(OS_MACOSX) 1464 // A RenderWidgetHostViewMac has lifetime scoped to the view. We'll retain it 1465 // to allow it to survive the trip without being hosted. 1466 base::mac::NSObjectRetain(widget_view->GetNativeView()); 1467#endif 1468} 1469 1470void WebContentsImpl::ShowCreatedWindow(int route_id, 1471 WindowOpenDisposition disposition, 1472 const gfx::Rect& initial_pos, 1473 bool user_gesture) { 1474 WebContentsImpl* contents = GetCreatedWindow(route_id); 1475 if (contents) { 1476 WebContentsDelegate* delegate = GetDelegate(); 1477 if (delegate) { 1478 delegate->AddNewContents( 1479 this, contents, disposition, initial_pos, user_gesture, NULL); 1480 } 1481 } 1482} 1483 1484void WebContentsImpl::ShowCreatedWidget(int route_id, 1485 const gfx::Rect& initial_pos) { 1486 ShowCreatedWidget(route_id, false, initial_pos); 1487} 1488 1489void WebContentsImpl::ShowCreatedFullscreenWidget(int route_id) { 1490 ShowCreatedWidget(route_id, true, gfx::Rect()); 1491 1492 DCHECK_EQ(MSG_ROUTING_NONE, fullscreen_widget_routing_id_); 1493 fullscreen_widget_routing_id_ = route_id; 1494 FOR_EACH_OBSERVER(WebContentsObserver, 1495 observers_, 1496 DidShowFullscreenWidget(route_id)); 1497} 1498 1499void WebContentsImpl::ShowCreatedWidget(int route_id, 1500 bool is_fullscreen, 1501 const gfx::Rect& initial_pos) { 1502 if (delegate_) 1503 delegate_->RenderWidgetShowing(); 1504 1505 RenderWidgetHostViewPort* widget_host_view = 1506 RenderWidgetHostViewPort::FromRWHV(GetCreatedWidget(route_id)); 1507 if (!widget_host_view) 1508 return; 1509 if (is_fullscreen) 1510 widget_host_view->InitAsFullscreen(GetRenderWidgetHostViewPort()); 1511 else 1512 widget_host_view->InitAsPopup(GetRenderWidgetHostViewPort(), initial_pos); 1513 1514 RenderWidgetHostImpl* render_widget_host_impl = 1515 RenderWidgetHostImpl::From(widget_host_view->GetRenderWidgetHost()); 1516 render_widget_host_impl->Init(); 1517 // Only allow privileged mouse lock for fullscreen render widget, which is 1518 // used to implement Pepper Flash fullscreen. 1519 render_widget_host_impl->set_allow_privileged_mouse_lock(is_fullscreen); 1520 1521#if defined(OS_MACOSX) 1522 // A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's 1523 // properly embedded (or purposefully ignored) we can release the retain we 1524 // took in CreateNewWidget(). 1525 base::mac::NSObjectRelease(widget_host_view->GetNativeView()); 1526#endif 1527} 1528 1529WebContentsImpl* WebContentsImpl::GetCreatedWindow(int route_id) { 1530 PendingContents::iterator iter = pending_contents_.find(route_id); 1531 1532 // Certain systems can block the creation of new windows. If we didn't succeed 1533 // in creating one, just return NULL. 1534 if (iter == pending_contents_.end()) { 1535 return NULL; 1536 } 1537 1538 WebContentsImpl* new_contents = iter->second; 1539 pending_contents_.erase(route_id); 1540 registrar_.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED, 1541 Source<WebContents>(new_contents)); 1542 1543 if (!new_contents->GetRenderProcessHost()->HasConnection() || 1544 !new_contents->GetRenderViewHost()->GetView()) 1545 return NULL; 1546 1547 // TODO(brettw): It seems bogus to reach into here and initialize the host. 1548 static_cast<RenderViewHostImpl*>(new_contents->GetRenderViewHost())->Init(); 1549 return new_contents; 1550} 1551 1552RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int route_id) { 1553 PendingWidgetViews::iterator iter = pending_widget_views_.find(route_id); 1554 if (iter == pending_widget_views_.end()) { 1555 DCHECK(false); 1556 return NULL; 1557 } 1558 1559 RenderWidgetHostView* widget_host_view = iter->second; 1560 pending_widget_views_.erase(route_id); 1561 1562 RenderWidgetHost* widget_host = widget_host_view->GetRenderWidgetHost(); 1563 if (!widget_host->GetProcess()->HasConnection()) { 1564 // The view has gone away or the renderer crashed. Nothing to do. 1565 return NULL; 1566 } 1567 1568 return widget_host_view; 1569} 1570 1571void WebContentsImpl::ShowContextMenu( 1572 const ContextMenuParams& params, 1573 ContextMenuSourceType type) { 1574 // Allow WebContentsDelegates to handle the context menu operation first. 1575 if (delegate_ && delegate_->HandleContextMenu(params)) 1576 return; 1577 1578 render_view_host_delegate_view_->ShowContextMenu(params, type); 1579} 1580 1581void WebContentsImpl::RequestMediaAccessPermission( 1582 const MediaStreamRequest& request, 1583 const MediaResponseCallback& callback) { 1584 if (delegate_) 1585 delegate_->RequestMediaAccessPermission(this, request, callback); 1586 else 1587 callback.Run(MediaStreamDevices()); 1588} 1589 1590void WebContentsImpl::UpdatePreferredSize(const gfx::Size& pref_size) { 1591 preferred_size_ = pref_size; 1592 if (delegate_) 1593 delegate_->UpdatePreferredSize(this, pref_size); 1594} 1595 1596void WebContentsImpl::ResizeDueToAutoResize(const gfx::Size& new_size) { 1597 if (delegate_) 1598 delegate_->ResizeDueToAutoResize(this, new_size); 1599} 1600 1601WebContents* WebContentsImpl::OpenURL(const OpenURLParams& params) { 1602 if (!delegate_) 1603 return NULL; 1604 1605 WebContents* new_contents = delegate_->OpenURLFromTab(this, params); 1606 return new_contents; 1607} 1608 1609bool WebContentsImpl::Send(IPC::Message* message) { 1610 if (!GetRenderViewHost()) { 1611 delete message; 1612 return false; 1613 } 1614 1615 return GetRenderViewHost()->Send(message); 1616} 1617 1618bool WebContentsImpl::NavigateToPendingEntry( 1619 NavigationController::ReloadType reload_type) { 1620 return NavigateToEntry( 1621 *NavigationEntryImpl::FromNavigationEntry(controller_.GetPendingEntry()), 1622 reload_type); 1623} 1624 1625void WebContentsImpl::RenderViewForInterstitialPageCreated( 1626 RenderViewHost* render_view_host) { 1627 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 1628 RenderViewForInterstitialPageCreated(render_view_host)); 1629} 1630 1631void WebContentsImpl::AttachInterstitialPage( 1632 InterstitialPageImpl* interstitial_page) { 1633 DCHECK(interstitial_page); 1634 render_manager_.set_interstitial_page(interstitial_page); 1635 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 1636 DidAttachInterstitialPage()); 1637} 1638 1639void WebContentsImpl::DetachInterstitialPage() { 1640 if (GetInterstitialPage()) 1641 render_manager_.remove_interstitial_page(); 1642 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 1643 DidDetachInterstitialPage()); 1644} 1645 1646bool WebContentsImpl::NavigateToEntry( 1647 const NavigationEntryImpl& entry, 1648 NavigationController::ReloadType reload_type) { 1649 // The renderer will reject IPC messages with URLs longer than 1650 // this limit, so don't attempt to navigate with a longer URL. 1651 if (entry.GetURL().spec().size() > kMaxURLChars) 1652 return false; 1653 1654 RenderViewHostImpl* dest_render_view_host = 1655 static_cast<RenderViewHostImpl*>(render_manager_.Navigate(entry)); 1656 if (!dest_render_view_host) 1657 return false; // Unable to create the desired render view host. 1658 1659 // For security, we should never send non-Web-UI URLs to a Web UI renderer. 1660 // Double check that here. 1661 int enabled_bindings = dest_render_view_host->GetEnabledBindings(); 1662 bool data_urls_allowed = delegate_ && delegate_->CanLoadDataURLsInWebUI(); 1663 bool is_allowed_in_web_ui_renderer = 1664 WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI( 1665 GetBrowserContext(), entry.GetURL(), data_urls_allowed); 1666 if ((enabled_bindings & BINDINGS_POLICY_WEB_UI) && 1667 !is_allowed_in_web_ui_renderer) { 1668 // Log the URL to help us diagnose any future failures of this CHECK. 1669 GetContentClient()->SetActiveURL(entry.GetURL()); 1670 CHECK(0); 1671 } 1672 1673 // Notify observers that we will navigate in this RV. 1674 FOR_EACH_OBSERVER(WebContentsObserver, 1675 observers_, 1676 AboutToNavigateRenderView(dest_render_view_host)); 1677 1678 // Used for page load time metrics. 1679 current_load_start_ = base::TimeTicks::Now(); 1680 1681 // Navigate in the desired RenderViewHost. 1682 ViewMsg_Navigate_Params navigate_params; 1683 MakeNavigateParams(entry, controller_, delegate_, reload_type, 1684 &navigate_params); 1685 dest_render_view_host->Navigate(navigate_params); 1686 1687 if (entry.GetPageID() == -1) { 1688 // HACK!! This code suppresses javascript: URLs from being added to 1689 // session history, which is what we want to do for javascript: URLs that 1690 // do not generate content. What we really need is a message from the 1691 // renderer telling us that a new page was not created. The same message 1692 // could be used for mailto: URLs and the like. 1693 if (entry.GetURL().SchemeIs(chrome::kJavaScriptScheme)) 1694 return false; 1695 } 1696 1697 // Notify observers about navigation. 1698 FOR_EACH_OBSERVER(WebContentsObserver, 1699 observers_, 1700 NavigateToPendingEntry(entry.GetURL(), reload_type)); 1701 1702 if (delegate_) 1703 delegate_->DidNavigateToPendingEntry(this); 1704 1705 return true; 1706} 1707 1708void WebContentsImpl::SetHistoryLengthAndPrune( 1709 const SiteInstance* site_instance, 1710 int history_length, 1711 int32 minimum_page_id) { 1712 // SetHistoryLengthAndPrune doesn't work when there are pending cross-site 1713 // navigations. Callers should ensure that this is the case. 1714 if (render_manager_.pending_render_view_host()) { 1715 NOTREACHED(); 1716 return; 1717 } 1718 RenderViewHostImpl* rvh = GetRenderViewHostImpl(); 1719 if (!rvh) { 1720 NOTREACHED(); 1721 return; 1722 } 1723 if (site_instance && rvh->GetSiteInstance() != site_instance) { 1724 NOTREACHED(); 1725 return; 1726 } 1727 Send(new ViewMsg_SetHistoryLengthAndPrune(GetRoutingID(), 1728 history_length, 1729 minimum_page_id)); 1730} 1731 1732void WebContentsImpl::FocusThroughTabTraversal(bool reverse) { 1733 if (ShowingInterstitialPage()) { 1734 render_manager_.interstitial_page()->FocusThroughTabTraversal(reverse); 1735 return; 1736 } 1737 GetRenderViewHostImpl()->SetInitialFocus(reverse); 1738} 1739 1740bool WebContentsImpl::ShowingInterstitialPage() const { 1741 return render_manager_.interstitial_page() != NULL; 1742} 1743 1744InterstitialPage* WebContentsImpl::GetInterstitialPage() const { 1745 return render_manager_.interstitial_page(); 1746} 1747 1748bool WebContentsImpl::IsSavable() { 1749 // WebKit creates Document object when MIME type is application/xhtml+xml, 1750 // so we also support this MIME type. 1751 return contents_mime_type_ == "text/html" || 1752 contents_mime_type_ == "text/xml" || 1753 contents_mime_type_ == "application/xhtml+xml" || 1754 contents_mime_type_ == "text/plain" || 1755 contents_mime_type_ == "text/css" || 1756 net::IsSupportedJavascriptMimeType(contents_mime_type_.c_str()); 1757} 1758 1759void WebContentsImpl::OnSavePage() { 1760 // If we can not save the page, try to download it. 1761 if (!IsSavable()) { 1762 RecordDownloadSource(INITIATED_BY_SAVE_PACKAGE_ON_NON_HTML); 1763 SaveURL(GetURL(), Referrer(), true); 1764 return; 1765 } 1766 1767 Stop(); 1768 1769 // Create the save package and possibly prompt the user for the name to save 1770 // the page as. The user prompt is an asynchronous operation that runs on 1771 // another thread. 1772 save_package_ = new SavePackage(this); 1773 save_package_->GetSaveInfo(); 1774} 1775 1776// Used in automated testing to bypass prompting the user for file names. 1777// Instead, the names and paths are hard coded rather than running them through 1778// file name sanitation and extension / mime checking. 1779bool WebContentsImpl::SavePage(const base::FilePath& main_file, 1780 const base::FilePath& dir_path, 1781 SavePageType save_type) { 1782 // Stop the page from navigating. 1783 Stop(); 1784 1785 save_package_ = new SavePackage(this, save_type, main_file, dir_path); 1786 return save_package_->Init(SavePackageDownloadCreatedCallback()); 1787} 1788 1789void WebContentsImpl::GenerateMHTML( 1790 const base::FilePath& file, 1791 const base::Callback<void(const base::FilePath&, int64)>& callback) { 1792 MHTMLGenerationManager::GetInstance()->GenerateMHTML(this, file, callback); 1793} 1794 1795bool WebContentsImpl::IsActiveEntry(int32 page_id) { 1796 NavigationEntryImpl* active_entry = 1797 NavigationEntryImpl::FromNavigationEntry(controller_.GetActiveEntry()); 1798 return (active_entry != NULL && 1799 active_entry->site_instance() == GetSiteInstance() && 1800 active_entry->GetPageID() == page_id); 1801} 1802 1803const std::string& WebContentsImpl::GetContentsMimeType() const { 1804 return contents_mime_type_; 1805} 1806 1807bool WebContentsImpl::WillNotifyDisconnection() const { 1808 return notify_disconnection_; 1809} 1810 1811void WebContentsImpl::SetOverrideEncoding(const std::string& encoding) { 1812 SetEncoding(encoding); 1813 Send(new ViewMsg_SetPageEncoding(GetRoutingID(), encoding)); 1814} 1815 1816void WebContentsImpl::ResetOverrideEncoding() { 1817 encoding_.clear(); 1818 Send(new ViewMsg_ResetPageEncodingToDefault(GetRoutingID())); 1819} 1820 1821RendererPreferences* WebContentsImpl::GetMutableRendererPrefs() { 1822 return &renderer_preferences_; 1823} 1824 1825void WebContentsImpl::SetNewTabStartTime(const base::TimeTicks& time) { 1826 new_tab_start_time_ = time; 1827} 1828 1829base::TimeTicks WebContentsImpl::GetNewTabStartTime() const { 1830 return new_tab_start_time_; 1831} 1832 1833void WebContentsImpl::Close() { 1834 Close(GetRenderViewHost()); 1835} 1836 1837void WebContentsImpl::OnCloseStarted() { 1838 if (close_start_time_.is_null()) 1839 close_start_time_ = base::TimeTicks::Now(); 1840} 1841 1842void WebContentsImpl::SystemDragEnded() { 1843 if (GetRenderViewHost()) 1844 GetRenderViewHostImpl()->DragSourceSystemDragEnded(); 1845 if (delegate_) 1846 delegate_->DragEnded(); 1847} 1848 1849void WebContentsImpl::UserGestureDone() { 1850 OnUserGesture(); 1851} 1852 1853void WebContentsImpl::SetClosedByUserGesture(bool value) { 1854 closed_by_user_gesture_ = value; 1855} 1856 1857bool WebContentsImpl::GetClosedByUserGesture() const { 1858 return closed_by_user_gesture_; 1859} 1860 1861double WebContentsImpl::GetZoomLevel() const { 1862 HostZoomMapImpl* zoom_map = static_cast<HostZoomMapImpl*>( 1863 HostZoomMap::GetForBrowserContext(GetBrowserContext())); 1864 if (!zoom_map) 1865 return 0; 1866 1867 double zoom_level; 1868 if (temporary_zoom_settings_) { 1869 zoom_level = zoom_map->GetTemporaryZoomLevel( 1870 GetRenderProcessHost()->GetID(), GetRenderViewHost()->GetRoutingID()); 1871 } else { 1872 GURL url; 1873 NavigationEntry* active_entry = GetController().GetActiveEntry(); 1874 // Since zoom map is updated using rewritten URL, use rewritten URL 1875 // to get the zoom level. 1876 url = active_entry ? active_entry->GetURL() : GURL::EmptyGURL(); 1877 zoom_level = zoom_map->GetZoomLevelForHostAndScheme(url.scheme(), 1878 net::GetHostOrSpecFromURL(url)); 1879 } 1880 return zoom_level; 1881} 1882 1883int WebContentsImpl::GetZoomPercent(bool* enable_increment, 1884 bool* enable_decrement) const { 1885 *enable_decrement = *enable_increment = false; 1886 // Calculate the zoom percent from the factor. Round up to the nearest whole 1887 // number. 1888 int percent = static_cast<int>( 1889 WebKit::WebView::zoomLevelToZoomFactor(GetZoomLevel()) * 100 + 0.5); 1890 *enable_decrement = percent > minimum_zoom_percent_; 1891 *enable_increment = percent < maximum_zoom_percent_; 1892 return percent; 1893} 1894 1895void WebContentsImpl::ViewSource() { 1896 if (!delegate_) 1897 return; 1898 1899 NavigationEntry* active_entry = GetController().GetActiveEntry(); 1900 if (!active_entry) 1901 return; 1902 1903 delegate_->ViewSourceForTab(this, active_entry->GetURL()); 1904} 1905 1906void WebContentsImpl::ViewFrameSource(const GURL& url, 1907 const std::string& content_state) { 1908 if (!delegate_) 1909 return; 1910 1911 delegate_->ViewSourceForFrame(this, url, content_state); 1912} 1913 1914int WebContentsImpl::GetMinimumZoomPercent() const { 1915 return minimum_zoom_percent_; 1916} 1917 1918int WebContentsImpl::GetMaximumZoomPercent() const { 1919 return maximum_zoom_percent_; 1920} 1921 1922gfx::Size WebContentsImpl::GetPreferredSize() const { 1923 return preferred_size_; 1924} 1925 1926int WebContentsImpl::GetContentRestrictions() const { 1927 return content_restrictions_; 1928} 1929 1930WebUI* WebContentsImpl::GetWebUIForCurrentState() { 1931 // When there is a pending navigation entry, we want to use the pending WebUI 1932 // that goes along with it to control the basic flags. For example, we want to 1933 // show the pending URL in the URL bar, so we want the display_url flag to 1934 // be from the pending entry. 1935 // 1936 // The confusion comes because there are multiple possibilities for the 1937 // initial load in a tab as a side effect of the way the RenderViewHostManager 1938 // works. 1939 // 1940 // - For the very first tab the load looks "normal". The new tab Web UI is 1941 // the pending one, and we want it to apply here. 1942 // 1943 // - For subsequent new tabs, they'll get a new SiteInstance which will then 1944 // get switched to the one previously associated with the new tab pages. 1945 // This switching will cause the manager to commit the RVH/WebUI. So we'll 1946 // have a committed Web UI in this case. 1947 // 1948 // This condition handles all of these cases: 1949 // 1950 // - First load in first tab: no committed nav entry + pending nav entry + 1951 // pending dom ui: 1952 // -> Use pending Web UI if any. 1953 // 1954 // - First load in second tab: no committed nav entry + pending nav entry + 1955 // no pending Web UI: 1956 // -> Use the committed Web UI if any. 1957 // 1958 // - Second navigation in any tab: committed nav entry + pending nav entry: 1959 // -> Use pending Web UI if any. 1960 // 1961 // - Normal state with no load: committed nav entry + no pending nav entry: 1962 // -> Use committed Web UI. 1963 if (controller_.GetPendingEntry() && 1964 (controller_.GetLastCommittedEntry() || 1965 render_manager_.pending_web_ui())) 1966 return render_manager_.pending_web_ui(); 1967 return render_manager_.web_ui(); 1968} 1969 1970bool WebContentsImpl::GotResponseToLockMouseRequest(bool allowed) { 1971 return GetRenderViewHost() ? 1972 GetRenderViewHostImpl()->GotResponseToLockMouseRequest(allowed) : false; 1973} 1974 1975bool WebContentsImpl::HasOpener() const { 1976 return opener_ != NULL; 1977} 1978 1979void WebContentsImpl::DidChooseColorInColorChooser(int color_chooser_id, 1980 SkColor color) { 1981 Send(new ViewMsg_DidChooseColorResponse( 1982 GetRoutingID(), color_chooser_id, color)); 1983} 1984 1985void WebContentsImpl::DidEndColorChooser(int color_chooser_id) { 1986 Send(new ViewMsg_DidEndColorChooser(GetRoutingID(), color_chooser_id)); 1987 if (delegate_) 1988 delegate_->DidEndColorChooser(); 1989 color_chooser_ = NULL; 1990} 1991 1992int WebContentsImpl::DownloadFavicon(const GURL& url, 1993 bool is_favicon, 1994 int image_size, 1995 const FaviconDownloadCallback& callback) { 1996 RenderViewHost* host = GetRenderViewHost(); 1997 int id = StartDownload(host, url, is_favicon, image_size); 1998 favicon_download_map_[id] = callback; 1999 return id; 2000} 2001 2002bool WebContentsImpl::FocusLocationBarByDefault() { 2003 WebUI* web_ui = GetWebUIForCurrentState(); 2004 if (web_ui) 2005 return web_ui->ShouldFocusLocationBarByDefault(); 2006 NavigationEntry* entry = controller_.GetActiveEntry(); 2007 if (entry && entry->GetURL() == GURL(chrome::kAboutBlankURL)) 2008 return true; 2009 return delegate_ && delegate_->ShouldFocusLocationBarByDefault(this); 2010} 2011 2012void WebContentsImpl::SetFocusToLocationBar(bool select_all) { 2013 if (delegate_) 2014 delegate_->SetFocusToLocationBar(select_all); 2015} 2016 2017void WebContentsImpl::DidStartProvisionalLoadForFrame( 2018 RenderViewHost* render_view_host, 2019 int64 frame_id, 2020 int64 parent_frame_id, 2021 bool is_main_frame, 2022 const GURL& url) { 2023 bool is_error_page = (url.spec() == kUnreachableWebDataURL); 2024 bool is_iframe_srcdoc = (url.spec() == chrome::kAboutSrcDocURL); 2025 GURL validated_url(url); 2026 RenderProcessHost* render_process_host = 2027 render_view_host->GetProcess(); 2028 RenderViewHost::FilterURL(render_process_host, false, &validated_url); 2029 2030 if (is_main_frame) 2031 DidChangeLoadProgress(0); 2032 2033 // Notify observers about the start of the provisional load. 2034 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2035 DidStartProvisionalLoadForFrame(frame_id, parent_frame_id, 2036 is_main_frame, validated_url, is_error_page, 2037 is_iframe_srcdoc, render_view_host)); 2038 2039 if (is_main_frame) { 2040 // Notify observers about the provisional change in the main frame URL. 2041 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2042 ProvisionalChangeToMainFrameUrl(validated_url, 2043 render_view_host)); 2044 } 2045} 2046 2047void WebContentsImpl::DidRedirectProvisionalLoad( 2048 RenderViewHost* render_view_host, 2049 int32 page_id, 2050 const GURL& source_url, 2051 const GURL& target_url) { 2052 // TODO(creis): Remove this method and have the pre-rendering code listen to 2053 // the ResourceDispatcherHost's RESOURCE_RECEIVED_REDIRECT notification 2054 // instead. See http://crbug.com/78512. 2055 GURL validated_source_url(source_url); 2056 GURL validated_target_url(target_url); 2057 RenderProcessHost* render_process_host = 2058 render_view_host->GetProcess(); 2059 RenderViewHost::FilterURL(render_process_host, false, &validated_source_url); 2060 RenderViewHost::FilterURL(render_process_host, false, &validated_target_url); 2061 NavigationEntry* entry; 2062 if (page_id == -1) { 2063 entry = controller_.GetPendingEntry(); 2064 } else { 2065 entry = controller_.GetEntryWithPageID(render_view_host->GetSiteInstance(), 2066 page_id); 2067 } 2068 if (!entry || entry->GetURL() != validated_source_url) 2069 return; 2070 2071 // Notify observers about the provisional change in the main frame URL. 2072 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2073 ProvisionalChangeToMainFrameUrl(validated_target_url, 2074 render_view_host)); 2075} 2076 2077void WebContentsImpl::DidFailProvisionalLoadWithError( 2078 RenderViewHost* render_view_host, 2079 const ViewHostMsg_DidFailProvisionalLoadWithError_Params& params) { 2080 VLOG(1) << "Failed Provisional Load: " << params.url.possibly_invalid_spec() 2081 << ", error_code: " << params.error_code 2082 << ", error_description: " << params.error_description 2083 << ", is_main_frame: " << params.is_main_frame 2084 << ", showing_repost_interstitial: " << 2085 params.showing_repost_interstitial 2086 << ", frame_id: " << params.frame_id; 2087 GURL validated_url(params.url); 2088 RenderProcessHost* render_process_host = 2089 render_view_host->GetProcess(); 2090 RenderViewHost::FilterURL(render_process_host, false, &validated_url); 2091 2092 if (net::ERR_ABORTED == params.error_code) { 2093 // EVIL HACK ALERT! Ignore failed loads when we're showing interstitials. 2094 // This means that the interstitial won't be torn down properly, which is 2095 // bad. But if we have an interstitial, go back to another tab type, and 2096 // then load the same interstitial again, we could end up getting the first 2097 // interstitial's "failed" message (as a result of the cancel) when we're on 2098 // the second one. 2099 // 2100 // We can't tell this apart, so we think we're tearing down the current page 2101 // which will cause a crash later one. There is also some code in 2102 // RenderViewHostManager::RendererAbortedProvisionalLoad that is commented 2103 // out because of this problem. 2104 // 2105 // http://code.google.com/p/chromium/issues/detail?id=2855 2106 // Because this will not tear down the interstitial properly, if "back" is 2107 // back to another tab type, the interstitial will still be somewhat alive 2108 // in the previous tab type. If you navigate somewhere that activates the 2109 // tab with the interstitial again, you'll see a flash before the new load 2110 // commits of the interstitial page. 2111 if (ShowingInterstitialPage()) { 2112 LOG(WARNING) << "Discarding message during interstitial."; 2113 return; 2114 } 2115 2116 // Do not clear the pending entry if one exists, so that the user's typed 2117 // URL is not lost when a navigation fails or is aborted. We'll allow 2118 // the view to clear the pending entry and typed URL if the user requests. 2119 2120 render_manager_.RendererAbortedProvisionalLoad(render_view_host); 2121 } 2122 2123 FOR_EACH_OBSERVER(WebContentsObserver, 2124 observers_, 2125 DidFailProvisionalLoad(params.frame_id, 2126 params.is_main_frame, 2127 validated_url, 2128 params.error_code, 2129 params.error_description, 2130 render_view_host)); 2131} 2132 2133void WebContentsImpl::OnDidLoadResourceFromMemoryCache( 2134 const GURL& url, 2135 const std::string& security_info, 2136 const std::string& http_method, 2137 const std::string& mime_type, 2138 ResourceType::Type resource_type) { 2139 base::StatsCounter cache("WebKit.CacheHit"); 2140 cache.Increment(); 2141 2142 // Send out a notification that we loaded a resource from our memory cache. 2143 int cert_id = 0; 2144 net::CertStatus cert_status = 0; 2145 int security_bits = -1; 2146 int connection_status = 0; 2147 DeserializeSecurityInfo(security_info, &cert_id, &cert_status, 2148 &security_bits, &connection_status); 2149 LoadFromMemoryCacheDetails details( 2150 url, GetRenderProcessHost()->GetID(), cert_id, cert_status, http_method, 2151 mime_type, resource_type); 2152 2153 NotificationService::current()->Notify( 2154 NOTIFICATION_LOAD_FROM_MEMORY_CACHE, 2155 Source<NavigationController>(&controller_), 2156 Details<LoadFromMemoryCacheDetails>(&details)); 2157} 2158 2159void WebContentsImpl::OnDidDisplayInsecureContent() { 2160 RecordAction(UserMetricsAction("SSL.DisplayedInsecureContent")); 2161 displayed_insecure_content_ = true; 2162 SSLManager::NotifySSLInternalStateChanged( 2163 GetController().GetBrowserContext()); 2164} 2165 2166void WebContentsImpl::OnDidRunInsecureContent( 2167 const std::string& security_origin, const GURL& target_url) { 2168 LOG(INFO) << security_origin << " ran insecure content from " 2169 << target_url.possibly_invalid_spec(); 2170 RecordAction(UserMetricsAction("SSL.RanInsecureContent")); 2171 if (EndsWith(security_origin, kDotGoogleDotCom, false)) 2172 RecordAction(UserMetricsAction("SSL.RanInsecureContentGoogle")); 2173 controller_.ssl_manager()->DidRunInsecureContent(security_origin); 2174 displayed_insecure_content_ = true; 2175 SSLManager::NotifySSLInternalStateChanged( 2176 GetController().GetBrowserContext()); 2177} 2178 2179void WebContentsImpl::OnDocumentLoadedInFrame(int64 frame_id) { 2180 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2181 DocumentLoadedInFrame(frame_id, message_source_)); 2182} 2183 2184void WebContentsImpl::OnDidFinishLoad( 2185 int64 frame_id, 2186 const GURL& url, 2187 bool is_main_frame) { 2188 GURL validated_url(url); 2189 RenderProcessHost* render_process_host = message_source_->GetProcess(); 2190 RenderViewHost::FilterURL(render_process_host, false, &validated_url); 2191 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2192 DidFinishLoad(frame_id, validated_url, is_main_frame, 2193 message_source_)); 2194} 2195 2196void WebContentsImpl::OnDidFailLoadWithError( 2197 int64 frame_id, 2198 const GURL& url, 2199 bool is_main_frame, 2200 int error_code, 2201 const string16& error_description) { 2202 GURL validated_url(url); 2203 RenderProcessHost* render_process_host = message_source_->GetProcess(); 2204 RenderViewHost::FilterURL(render_process_host, false, &validated_url); 2205 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2206 DidFailLoad(frame_id, validated_url, is_main_frame, 2207 error_code, error_description, 2208 message_source_)); 2209} 2210 2211void WebContentsImpl::OnUpdateContentRestrictions(int restrictions) { 2212 content_restrictions_ = restrictions; 2213 if (delegate_) 2214 delegate_->ContentRestrictionsChanged(this); 2215} 2216 2217void WebContentsImpl::OnGoToEntryAtOffset(int offset) { 2218 if (!delegate_ || delegate_->OnGoToEntryOffset(offset)) { 2219 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( 2220 controller_.GetEntryAtOffset(offset)); 2221 if (!entry) 2222 return; 2223 // Note that we don't call NavigationController::GotToOffset() as we don't 2224 // want to create a pending navigation entry (it might end up lingering 2225 // http://crbug.com/51680). 2226 entry->SetTransitionType( 2227 PageTransitionFromInt( 2228 entry->GetTransitionType() | 2229 PAGE_TRANSITION_FORWARD_BACK)); 2230 NavigateToEntry(*entry, NavigationControllerImpl::NO_RELOAD); 2231 2232 // If the entry is being restored and doesn't have a SiteInstance yet, fill 2233 // it in now that we know. This allows us to find the entry when it commits. 2234 if (!entry->site_instance() && 2235 entry->restore_type() != NavigationEntryImpl::RESTORE_NONE) { 2236 entry->set_site_instance( 2237 static_cast<SiteInstanceImpl*>(GetPendingSiteInstance())); 2238 } 2239 } 2240} 2241 2242void WebContentsImpl::OnUpdateZoomLimits(int minimum_percent, 2243 int maximum_percent, 2244 bool remember) { 2245 minimum_zoom_percent_ = minimum_percent; 2246 maximum_zoom_percent_ = maximum_percent; 2247 temporary_zoom_settings_ = !remember; 2248} 2249 2250void WebContentsImpl::OnSaveURL(const GURL& url, 2251 const Referrer& referrer) { 2252 RecordDownloadSource(INITIATED_BY_PEPPER_SAVE); 2253 // Check if the URL to save matches the URL of the main frame. Since this 2254 // message originates from Pepper plugins, it may not be the case if the 2255 // plugin is an embedded element. 2256 GURL main_frame_url = GetURL(); 2257 if (!main_frame_url.is_valid()) 2258 return; 2259 bool is_main_frame = (url == main_frame_url); 2260 SaveURL(url, referrer, is_main_frame); 2261} 2262 2263void WebContentsImpl::OnEnumerateDirectory(int request_id, 2264 const base::FilePath& path) { 2265 if (!delegate_) 2266 return; 2267 2268 ChildProcessSecurityPolicyImpl* policy = 2269 ChildProcessSecurityPolicyImpl::GetInstance(); 2270 if (policy->CanReadDirectory(GetRenderProcessHost()->GetID(), path)) 2271 delegate_->EnumerateDirectory(this, request_id, path); 2272} 2273 2274void WebContentsImpl::OnJSOutOfMemory() { 2275 if (delegate_) 2276 delegate_->JSOutOfMemory(this); 2277} 2278 2279void WebContentsImpl::OnRegisterProtocolHandler(const std::string& protocol, 2280 const GURL& url, 2281 const string16& title, 2282 bool user_gesture) { 2283 if (!delegate_) 2284 return; 2285 2286 ChildProcessSecurityPolicyImpl* policy = 2287 ChildProcessSecurityPolicyImpl::GetInstance(); 2288 if (policy->IsPseudoScheme(protocol) || policy->IsDisabledScheme(protocol)) 2289 return; 2290 delegate_->RegisterProtocolHandler(this, protocol, url, title, user_gesture); 2291} 2292 2293void WebContentsImpl::OnFindReply(int request_id, 2294 int number_of_matches, 2295 const gfx::Rect& selection_rect, 2296 int active_match_ordinal, 2297 bool final_update) { 2298 if (delegate_) { 2299 delegate_->FindReply(this, request_id, number_of_matches, selection_rect, 2300 active_match_ordinal, final_update); 2301 } 2302} 2303 2304#if defined(OS_ANDROID) 2305void WebContentsImpl::OnFindMatchRectsReply( 2306 int version, 2307 const std::vector<gfx::RectF>& rects, 2308 const gfx::RectF& active_rect) { 2309 if (delegate_) 2310 delegate_->FindMatchRectsReply(this, version, rects, active_rect); 2311} 2312 2313void WebContentsImpl::OnOpenDateTimeDialog( 2314 const ViewHostMsg_DateTimeDialogValue_Params& value) { 2315 date_time_chooser_->ShowDialog( 2316 view_->GetContentNativeView(), GetRenderViewHost(), value.dialog_type, 2317 value.year, value.month, value.day, value.hour, 2318 value.minute, value.second); 2319} 2320 2321#endif 2322 2323void WebContentsImpl::OnCrashedPlugin(const base::FilePath& plugin_path, 2324 base::ProcessId plugin_pid) { 2325 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2326 PluginCrashed(plugin_path, plugin_pid)); 2327} 2328 2329void WebContentsImpl::OnAppCacheAccessed(const GURL& manifest_url, 2330 bool blocked_by_policy) { 2331 // Notify observers about navigation. 2332 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2333 AppCacheAccessed(manifest_url, blocked_by_policy)); 2334} 2335 2336void WebContentsImpl::OnOpenColorChooser(int color_chooser_id, 2337 SkColor color) { 2338 color_chooser_ = delegate_ ? 2339 delegate_->OpenColorChooser(this, color_chooser_id, color) : NULL; 2340} 2341 2342void WebContentsImpl::OnEndColorChooser(int color_chooser_id) { 2343 if (color_chooser_ && 2344 color_chooser_id == color_chooser_->identifier()) 2345 color_chooser_->End(); 2346} 2347 2348void WebContentsImpl::OnSetSelectedColorInColorChooser(int color_chooser_id, 2349 SkColor color) { 2350 if (color_chooser_ && 2351 color_chooser_id == color_chooser_->identifier()) 2352 color_chooser_->SetSelectedColor(color); 2353} 2354 2355void WebContentsImpl::OnPepperPluginHung(int plugin_child_id, 2356 const base::FilePath& path, 2357 bool is_hung) { 2358 UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1); 2359 2360 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2361 PluginHungStatusChanged(plugin_child_id, path, is_hung)); 2362} 2363 2364// This exists for render views that don't have a WebUI, but do have WebUI 2365// bindings enabled. 2366void WebContentsImpl::OnWebUISend(const GURL& source_url, 2367 const std::string& name, 2368 const base::ListValue& args) { 2369 if (delegate_) 2370 delegate_->WebUISend(this, source_url, name, args); 2371} 2372 2373void WebContentsImpl::OnRequestPpapiBrokerPermission( 2374 int request_id, 2375 const GURL& url, 2376 const base::FilePath& plugin_path) { 2377 if (!delegate_) { 2378 OnPpapiBrokerPermissionResult(request_id, false); 2379 return; 2380 } 2381 2382 if (!delegate_->RequestPpapiBrokerPermission( 2383 this, url, plugin_path, 2384 base::Bind(&WebContentsImpl::OnPpapiBrokerPermissionResult, 2385 base::Unretained(this), request_id))) { 2386 NOTIMPLEMENTED(); 2387 OnPpapiBrokerPermissionResult(request_id, false); 2388 } 2389} 2390 2391void WebContentsImpl::OnPpapiBrokerPermissionResult(int request_id, 2392 bool result) { 2393 RenderViewHostImpl* rvh = GetRenderViewHostImpl(); 2394 rvh->Send(new ViewMsg_PpapiBrokerPermissionResult(rvh->GetRoutingID(), 2395 request_id, 2396 result)); 2397} 2398 2399void WebContentsImpl::OnBrowserPluginMessage(const IPC::Message& message) { 2400 // This creates a BrowserPluginEmbedder, which handles all the BrowserPlugin 2401 // specific messages for this WebContents. This means that any message from 2402 // a BrowserPlugin prior to this will be ignored. 2403 // For more info, see comment above classes BrowserPluginEmbedder and 2404 // BrowserPluginGuest. 2405 CHECK(!browser_plugin_embedder_.get()); 2406 browser_plugin_embedder_.reset(BrowserPluginEmbedder::Create(this)); 2407 browser_plugin_embedder_->OnMessageReceived(message); 2408} 2409 2410void WebContentsImpl::OnDidDownloadFavicon( 2411 int id, 2412 const GURL& image_url, 2413 int requested_size, 2414 const std::vector<SkBitmap>& bitmaps) { 2415 FaviconDownloadMap::iterator iter = favicon_download_map_.find(id); 2416 if (iter == favicon_download_map_.end()) { 2417 // Currently WebContents notifies us of ANY downloads so that it is 2418 // possible to get here. 2419 return; 2420 } 2421 if (!iter->second.is_null()) { 2422 iter->second.Run(id, image_url, requested_size, bitmaps); 2423 } 2424 favicon_download_map_.erase(id); 2425} 2426 2427void WebContentsImpl::OnUpdateFaviconURL( 2428 int32 page_id, 2429 const std::vector<FaviconURL>& candidates) { 2430 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2431 DidUpdateFaviconURL(page_id, candidates)); 2432} 2433 2434void WebContentsImpl::OnFrameDetached(int64 frame_id) { 2435 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2436 FrameDetached(message_source_, frame_id)); 2437} 2438 2439void WebContentsImpl::DidChangeVisibleSSLState() { 2440 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2441 DidChangeVisibleSSLState()); 2442} 2443 2444void WebContentsImpl::NotifyBeforeFormRepostWarningShow() { 2445 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2446 BeforeFormRepostWarningShow()); 2447} 2448 2449// Notifies the RenderWidgetHost instance about the fact that the page is 2450// loading, or done loading and calls the base implementation. 2451void WebContentsImpl::SetIsLoading(bool is_loading, 2452 LoadNotificationDetails* details) { 2453 if (is_loading == is_loading_) 2454 return; 2455 2456 if (!is_loading) { 2457 load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE, string16()); 2458 load_state_host_.clear(); 2459 upload_size_ = 0; 2460 upload_position_ = 0; 2461 } 2462 2463 render_manager_.SetIsLoading(is_loading); 2464 2465 is_loading_ = is_loading; 2466 waiting_for_response_ = is_loading; 2467 2468 if (delegate_) 2469 delegate_->LoadingStateChanged(this); 2470 NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD); 2471 2472 if (is_loading) 2473 TRACE_EVENT_ASYNC_BEGIN0("browser", "WebContentsImpl Loading", this); 2474 else 2475 TRACE_EVENT_ASYNC_END0("browser", "WebContentsImpl Loading", this); 2476 int type = is_loading ? NOTIFICATION_LOAD_START : NOTIFICATION_LOAD_STOP; 2477 NotificationDetails det = NotificationService::NoDetails(); 2478 if (details) 2479 det = Details<LoadNotificationDetails>(details); 2480 NotificationService::current()->Notify( 2481 type, Source<NavigationController>(&controller_), det); 2482} 2483 2484void WebContentsImpl::DidNavigateMainFramePostCommit( 2485 const LoadCommittedDetails& details, 2486 const ViewHostMsg_FrameNavigate_Params& params) { 2487 if (details.is_navigation_to_different_page()) { 2488 // Clear the status bubble. This is a workaround for a bug where WebKit 2489 // doesn't let us know that the cursor left an element during a 2490 // transition (this is also why the mouse cursor remains as a hand after 2491 // clicking on a link); see bugs 1184641 and 980803. We don't want to 2492 // clear the bubble when a user navigates to a named anchor in the same 2493 // page. 2494 UpdateTargetURL(details.entry->GetPageID(), GURL()); 2495 } 2496 2497 if (!details.is_in_page) { 2498 // Once the main frame is navigated, we're no longer considered to have 2499 // displayed insecure content. 2500 displayed_insecure_content_ = false; 2501 } 2502 2503 // Notify observers about navigation. 2504 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2505 DidNavigateMainFrame(details, params)); 2506} 2507 2508void WebContentsImpl::DidNavigateAnyFramePostCommit( 2509 RenderViewHost* render_view_host, 2510 const LoadCommittedDetails& details, 2511 const ViewHostMsg_FrameNavigate_Params& params) { 2512 // If we navigate off the page, reset JavaScript state. This does nothing 2513 // to prevent a malicious script from spamming messages, since the script 2514 // could just reload the page to stop blocking. 2515 if (dialog_manager_ && !details.is_in_page) { 2516 dialog_manager_->ResetJavaScriptState(this); 2517 dialog_manager_ = NULL; 2518 } 2519 2520 // Notify observers about navigation. 2521 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2522 DidNavigateAnyFrame(details, params)); 2523} 2524 2525void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) { 2526 // If we are creating a RVH for a restored controller, then we need to make 2527 // sure the RenderView starts with a next_page_id_ larger than the number 2528 // of restored entries. This must be called before the RenderView starts 2529 // navigating (to avoid a race between the browser updating max_page_id and 2530 // the renderer updating next_page_id_). Because of this, we only call this 2531 // from CreateRenderView and allow that to notify the RenderView for us. 2532 int max_restored_page_id = controller_.GetMaxRestoredPageID(); 2533 if (max_restored_page_id > 2534 GetMaxPageIDForSiteInstance(rvh->GetSiteInstance())) 2535 UpdateMaxPageIDForSiteInstance(rvh->GetSiteInstance(), 2536 max_restored_page_id); 2537} 2538 2539bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl* entry, 2540 const string16& title) { 2541 // For file URLs without a title, use the pathname instead. In the case of a 2542 // synthesized title, we don't want the update to count toward the "one set 2543 // per page of the title to history." 2544 string16 final_title; 2545 bool explicit_set; 2546 if (entry && entry->GetURL().SchemeIsFile() && title.empty()) { 2547 final_title = UTF8ToUTF16(entry->GetURL().ExtractFileName()); 2548 explicit_set = false; // Don't count synthetic titles toward the set limit. 2549 } else { 2550 TrimWhitespace(title, TRIM_ALL, &final_title); 2551 explicit_set = true; 2552 } 2553 2554 // If a page is created via window.open and never navigated, 2555 // there will be no navigation entry. In this situation, 2556 // |page_title_when_no_navigation_entry_| will be used for page title. 2557 if (entry) { 2558 if (final_title == entry->GetTitle()) 2559 return false; // Nothing changed, don't bother. 2560 2561 entry->SetTitle(final_title); 2562 } else { 2563 if (page_title_when_no_navigation_entry_ == final_title) 2564 return false; // Nothing changed, don't bother. 2565 2566 page_title_when_no_navigation_entry_ = final_title; 2567 } 2568 2569 // Lastly, set the title for the view. 2570 view_->SetPageTitle(final_title); 2571 2572 std::pair<NavigationEntry*, bool> details = 2573 std::make_pair(entry, explicit_set); 2574 2575 NotificationService::current()->Notify( 2576 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, 2577 Source<WebContents>(this), 2578 Details<std::pair<NavigationEntry*, bool> >(&details)); 2579 2580 return true; 2581} 2582 2583void WebContentsImpl::NotifySwapped(RenderViewHost* old_render_view_host) { 2584 // After sending out a swap notification, we need to send a disconnect 2585 // notification so that clients that pick up a pointer to |this| can NULL the 2586 // pointer. See Bug 1230284. 2587 notify_disconnection_ = true; 2588 NotificationService::current()->Notify( 2589 NOTIFICATION_WEB_CONTENTS_SWAPPED, 2590 Source<WebContents>(this), 2591 Details<RenderViewHost>(old_render_view_host)); 2592 2593 // Ensure that the associated embedder gets cleared after a RenderViewHost 2594 // gets swapped, so we don't reuse the same embedder next time a 2595 // RenderViewHost is attached to this WebContents. 2596 RemoveBrowserPluginEmbedder(); 2597} 2598 2599void WebContentsImpl::NotifyConnected() { 2600 notify_disconnection_ = true; 2601 NotificationService::current()->Notify( 2602 NOTIFICATION_WEB_CONTENTS_CONNECTED, 2603 Source<WebContents>(this), 2604 NotificationService::NoDetails()); 2605} 2606 2607void WebContentsImpl::NotifyDisconnected() { 2608 if (!notify_disconnection_) 2609 return; 2610 2611 notify_disconnection_ = false; 2612 NotificationService::current()->Notify( 2613 NOTIFICATION_WEB_CONTENTS_DISCONNECTED, 2614 Source<WebContents>(this), 2615 NotificationService::NoDetails()); 2616} 2617 2618RenderViewHostDelegateView* WebContentsImpl::GetDelegateView() { 2619 return render_view_host_delegate_view_; 2620} 2621 2622RenderViewHostDelegate::RendererManagement* 2623WebContentsImpl::GetRendererManagementDelegate() { 2624 return &render_manager_; 2625} 2626 2627RendererPreferences WebContentsImpl::GetRendererPrefs( 2628 BrowserContext* browser_context) const { 2629 return renderer_preferences_; 2630} 2631 2632WebContents* WebContentsImpl::GetAsWebContents() { 2633 return this; 2634} 2635 2636gfx::Rect WebContentsImpl::GetRootWindowResizerRect() const { 2637 if (delegate_) 2638 return delegate_->GetRootWindowResizerRect(); 2639 return gfx::Rect(); 2640} 2641 2642void WebContentsImpl::RemoveBrowserPluginEmbedder() { 2643 if (browser_plugin_embedder_.get()) 2644 browser_plugin_embedder_.reset(); 2645} 2646 2647void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) { 2648 // Don't send notifications if we are just creating a swapped-out RVH for 2649 // the opener chain. These won't be used for view-source or WebUI, so it's 2650 // ok to return early. 2651 if (static_cast<RenderViewHostImpl*>(render_view_host)->is_swapped_out()) 2652 return; 2653 2654 if (delegate_) 2655 view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent()); 2656 2657 NotificationService::current()->Notify( 2658 NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED, 2659 Source<WebContents>(this), 2660 Details<RenderViewHost>(render_view_host)); 2661 NavigationEntry* entry = controller_.GetActiveEntry(); 2662 if (!entry) 2663 return; 2664 2665 // When we're creating views, we're still doing initial setup, so we always 2666 // use the pending Web UI rather than any possibly existing committed one. 2667 if (render_manager_.pending_web_ui()) 2668 render_manager_.pending_web_ui()->RenderViewCreated(render_view_host); 2669 2670 if (entry->IsViewSourceMode()) { 2671 // Put the renderer in view source mode. 2672 render_view_host->Send( 2673 new ViewMsg_EnableViewSourceMode(render_view_host->GetRoutingID())); 2674 } 2675 2676 view_->RenderViewCreated(render_view_host); 2677 2678 FOR_EACH_OBSERVER( 2679 WebContentsObserver, observers_, RenderViewCreated(render_view_host)); 2680} 2681 2682void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) { 2683 if (rvh != GetRenderViewHost()) { 2684 // Don't notify the world, since this came from a renderer in the 2685 // background. 2686 return; 2687 } 2688 2689 NotifyConnected(); 2690 bool was_crashed = IsCrashed(); 2691 SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING, 0); 2692 2693 // Restore the focus to the tab (otherwise the focus will be on the top 2694 // window). 2695 if (was_crashed && !FocusLocationBarByDefault() && 2696 (!delegate_ || delegate_->ShouldFocusPageAfterCrash())) { 2697 view_->Focus(); 2698 } 2699 2700 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewReady()); 2701} 2702 2703void WebContentsImpl::RenderViewGone(RenderViewHost* rvh, 2704 base::TerminationStatus status, 2705 int error_code) { 2706 if (rvh != GetRenderViewHost()) { 2707 // The pending page's RenderViewHost is gone. 2708 return; 2709 } 2710 2711 SetIsLoading(false, NULL); 2712 NotifyDisconnected(); 2713 SetIsCrashed(status, error_code); 2714 GetView()->OnTabCrashed(GetCrashedStatus(), crashed_error_code_); 2715 2716 FOR_EACH_OBSERVER(WebContentsObserver, 2717 observers_, 2718 RenderViewGone(GetCrashedStatus())); 2719} 2720 2721void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) { 2722 render_manager_.RenderViewDeleted(rvh); 2723 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh)); 2724} 2725 2726void WebContentsImpl::DidNavigate( 2727 RenderViewHost* rvh, 2728 const ViewHostMsg_FrameNavigate_Params& params) { 2729 if (PageTransitionIsMainFrame(params.transition)) { 2730 // When overscroll navigation gesture is enabled, a screenshot of the page 2731 // in its current state is taken so that it can be used during the 2732 // nav-gesture. It is necessary to take the screenshot here, before calling 2733 // RenderViewHostManager::DidNavigateMainFrame, because that can change 2734 // WebContents::GetRenderViewHost to return the new host, instead of the one 2735 // that may have just been swapped out. 2736 if (delegate_ && delegate_->CanOverscrollContent()) 2737 controller_.TakeScreenshot(); 2738 2739 render_manager_.DidNavigateMainFrame(rvh); 2740 } 2741 2742 // Update the site of the SiteInstance if it doesn't have one yet, unless 2743 // this is for about:blank. In that case, the SiteInstance can still be 2744 // considered unused until a navigation to a real page. 2745 if (!static_cast<SiteInstanceImpl*>(GetSiteInstance())->HasSite() && 2746 params.url != GURL(chrome::kAboutBlankURL)) { 2747 static_cast<SiteInstanceImpl*>(GetSiteInstance())->SetSite(params.url); 2748 } 2749 2750 // Need to update MIME type here because it's referred to in 2751 // UpdateNavigationCommands() called by RendererDidNavigate() to 2752 // determine whether or not to enable the encoding menu. 2753 // It's updated only for the main frame. For a subframe, 2754 // RenderView::UpdateURL does not set params.contents_mime_type. 2755 // (see http://code.google.com/p/chromium/issues/detail?id=2929 ) 2756 // TODO(jungshik): Add a test for the encoding menu to avoid 2757 // regressing it again. 2758 if (PageTransitionIsMainFrame(params.transition)) 2759 contents_mime_type_ = params.contents_mime_type; 2760 2761 LoadCommittedDetails details; 2762 bool did_navigate = controller_.RendererDidNavigate(params, &details); 2763 2764 // Send notification about committed provisional loads. This notification is 2765 // different from the NAV_ENTRY_COMMITTED notification which doesn't include 2766 // the actual URL navigated to and isn't sent for AUTO_SUBFRAME navigations. 2767 if (details.type != NAVIGATION_TYPE_NAV_IGNORE) { 2768 // For AUTO_SUBFRAME navigations, an event for the main frame is generated 2769 // that is not recorded in the navigation history. For the purpose of 2770 // tracking navigation events, we treat this event as a sub frame navigation 2771 // event. 2772 bool is_main_frame = did_navigate ? details.is_main_frame : false; 2773 PageTransition transition_type = params.transition; 2774 // Whether or not a page transition was triggered by going backward or 2775 // forward in the history is only stored in the navigation controller's 2776 // entry list. 2777 if (did_navigate && 2778 (controller_.GetActiveEntry()->GetTransitionType() & 2779 PAGE_TRANSITION_FORWARD_BACK)) { 2780 transition_type = PageTransitionFromInt( 2781 params.transition | PAGE_TRANSITION_FORWARD_BACK); 2782 } 2783 // Notify observers about the commit of the provisional load. 2784 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2785 DidCommitProvisionalLoadForFrame(params.frame_id, 2786 is_main_frame, params.url, transition_type, rvh)); 2787 } 2788 2789 if (!did_navigate) 2790 return; // No navigation happened. 2791 2792 // DO NOT ADD MORE STUFF TO THIS FUNCTION! Your component should either listen 2793 // for the appropriate notification (best) or you can add it to 2794 // DidNavigateMainFramePostCommit / DidNavigateAnyFramePostCommit (only if 2795 // necessary, please). 2796 2797 // Run post-commit tasks. 2798 if (details.is_main_frame) { 2799 DidNavigateMainFramePostCommit(details, params); 2800 if (delegate_) { 2801 delegate_->DidNavigateMainFramePostCommit(this); 2802 view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent()); 2803 } 2804 } 2805 DidNavigateAnyFramePostCommit(rvh, details, params); 2806} 2807 2808void WebContentsImpl::UpdateState(RenderViewHost* rvh, 2809 int32 page_id, 2810 const std::string& state) { 2811 // Ensure that this state update comes from either the active RVH or one of 2812 // the swapped out RVHs. We don't expect to hear from any other RVHs. 2813 DCHECK(rvh == GetRenderViewHost() || render_manager_.IsSwappedOut(rvh)); 2814 2815 // We must be prepared to handle state updates for any page, these occur 2816 // when the user is scrolling and entering form data, as well as when we're 2817 // leaving a page, in which case our state may have already been moved to 2818 // the next page. The navigation controller will look up the appropriate 2819 // NavigationEntry and update it when it is notified via the delegate. 2820 2821 int entry_index = controller_.GetEntryIndexWithPageID( 2822 rvh->GetSiteInstance(), page_id); 2823 if (entry_index < 0) 2824 return; 2825 NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index); 2826 2827 if (state == entry->GetContentState()) 2828 return; // Nothing to update. 2829 entry->SetContentState(state); 2830 controller_.NotifyEntryChanged(entry, entry_index); 2831} 2832 2833void WebContentsImpl::UpdateTitle(RenderViewHost* rvh, 2834 int32 page_id, 2835 const string16& title, 2836 base::i18n::TextDirection title_direction) { 2837 // If we have a title, that's a pretty good indication that we've started 2838 // getting useful data. 2839 SetNotWaitingForResponse(); 2840 2841 // Try to find the navigation entry, which might not be the current one. 2842 // For example, it might be from a pending RVH for the pending entry. 2843 NavigationEntryImpl* entry = controller_.GetEntryWithPageID( 2844 rvh->GetSiteInstance(), page_id); 2845 2846 // We can handle title updates when we don't have an entry in 2847 // UpdateTitleForEntry, but only if the update is from the current RVH. 2848 if (!entry && rvh != GetRenderViewHost()) 2849 return; 2850 2851 // TODO(evan): make use of title_direction. 2852 // http://code.google.com/p/chromium/issues/detail?id=27094 2853 if (!UpdateTitleForEntry(entry, title)) 2854 return; 2855 2856 // Broadcast notifications when the UI should be updated. 2857 if (entry == controller_.GetEntryAtOffset(0)) 2858 NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE); 2859} 2860 2861void WebContentsImpl::UpdateEncoding(RenderViewHost* render_view_host, 2862 const std::string& encoding) { 2863 SetEncoding(encoding); 2864} 2865 2866void WebContentsImpl::UpdateTargetURL(int32 page_id, const GURL& url) { 2867 if (delegate_) 2868 delegate_->UpdateTargetURL(this, page_id, url); 2869} 2870 2871void WebContentsImpl::Close(RenderViewHost* rvh) { 2872#if defined(OS_MACOSX) 2873 // The UI may be in an event-tracking loop, such as between the 2874 // mouse-down and mouse-up in text selection or a button click. 2875 // Defer the close until after tracking is complete, so that we 2876 // don't free objects out from under the UI. 2877 // TODO(shess): This could get more fine-grained. For instance, 2878 // closing a tab in another window while selecting text in the 2879 // current window's Omnibox should be just fine. 2880 if (view_->IsEventTracking()) { 2881 view_->CloseTabAfterEventTracking(); 2882 return; 2883 } 2884#endif 2885 2886 // Ignore this if it comes from a RenderViewHost that we aren't showing. 2887 if (delegate_ && rvh == GetRenderViewHost()) 2888 delegate_->CloseContents(this); 2889} 2890 2891void WebContentsImpl::SwappedOut(RenderViewHost* rvh) { 2892 if (delegate_ && rvh == GetRenderViewHost()) 2893 delegate_->SwappedOut(this); 2894} 2895 2896void WebContentsImpl::RequestMove(const gfx::Rect& new_bounds) { 2897 if (delegate_ && delegate_->IsPopupOrPanel(this)) 2898 delegate_->MoveContents(this, new_bounds); 2899} 2900 2901void WebContentsImpl::DidStartLoading(RenderViewHost* render_view_host) { 2902 SetIsLoading(true, NULL); 2903 2904 if (delegate_ && content_restrictions_) 2905 OnUpdateContentRestrictions(0); 2906 2907 // Notify observers about navigation. 2908 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2909 DidStartLoading(render_view_host)); 2910} 2911 2912void WebContentsImpl::DidStopLoading(RenderViewHost* render_view_host) { 2913 scoped_ptr<LoadNotificationDetails> details; 2914 2915 NavigationEntry* entry = controller_.GetActiveEntry(); 2916 // An entry may not exist for a stop when loading an initial blank page or 2917 // if an iframe injected by script into a blank page finishes loading. 2918 if (entry) { 2919 base::TimeDelta elapsed = base::TimeTicks::Now() - current_load_start_; 2920 2921 details.reset(new LoadNotificationDetails( 2922 entry->GetVirtualURL(), 2923 entry->GetTransitionType(), 2924 elapsed, 2925 &controller_, 2926 controller_.GetCurrentEntryIndex())); 2927 } 2928 2929 SetIsLoading(false, details.get()); 2930 2931 // Notify observers about navigation. 2932 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2933 DidStopLoading(render_view_host)); 2934} 2935 2936void WebContentsImpl::DidCancelLoading() { 2937 controller_.DiscardNonCommittedEntries(); 2938 2939 // Update the URL display. 2940 NotifyNavigationStateChanged(INVALIDATE_TYPE_URL); 2941} 2942 2943void WebContentsImpl::DidChangeLoadProgress(double progress) { 2944#if defined(OS_ANDROID) 2945 if (delegate_) 2946 delegate_->LoadProgressChanged(this, progress); 2947#endif 2948} 2949 2950void WebContentsImpl::DidDisownOpener(RenderViewHost* rvh) { 2951 // Clear our opener so that future cross-process navigations don't have an 2952 // opener assigned. 2953 registrar_.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED, 2954 Source<WebContents>(opener_)); 2955 opener_ = NULL; 2956 2957 // Notify all swapped out RenderViewHosts for this tab. This is important 2958 // in case we go back to them, or if another window in those processes tries 2959 // to access window.opener. 2960 render_manager_.DidDisownOpener(rvh); 2961} 2962 2963void WebContentsImpl::DidUpdateFrameTree(RenderViewHost* rvh) { 2964 render_manager_.DidUpdateFrameTree(rvh); 2965} 2966 2967void WebContentsImpl::DocumentAvailableInMainFrame( 2968 RenderViewHost* render_view_host) { 2969 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2970 DocumentAvailableInMainFrame()); 2971} 2972 2973void WebContentsImpl::DocumentOnLoadCompletedInMainFrame( 2974 RenderViewHost* render_view_host, 2975 int32 page_id) { 2976 NotificationService::current()->Notify( 2977 NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, 2978 Source<WebContents>(this), 2979 Details<int>(&page_id)); 2980} 2981 2982void WebContentsImpl::RequestOpenURL(RenderViewHost* rvh, 2983 const GURL& url, 2984 const Referrer& referrer, 2985 WindowOpenDisposition disposition, 2986 int64 source_frame_id, 2987 bool is_cross_site_redirect) { 2988 // If this came from a swapped out RenderViewHost, we only allow the request 2989 // if we are still in the same BrowsingInstance. 2990 if (static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out() && 2991 !rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance())) { 2992 return; 2993 } 2994 2995 // Delegate to RequestTransferURL because this is just the generic 2996 // case where |old_request_id| is empty. 2997 RequestTransferURL(url, referrer, disposition, source_frame_id, 2998 GlobalRequestID(), is_cross_site_redirect); 2999} 3000 3001void WebContentsImpl::RequestTransferURL( 3002 const GURL& url, 3003 const Referrer& referrer, 3004 WindowOpenDisposition disposition, 3005 int64 source_frame_id, 3006 const GlobalRequestID& old_request_id, 3007 bool is_cross_site_redirect) { 3008 WebContents* new_contents = NULL; 3009 PageTransition transition_type = PAGE_TRANSITION_LINK; 3010 if (render_manager_.web_ui()) { 3011 // When we're a Web UI, it will provide a page transition type for us (this 3012 // is so the new tab page can specify AUTO_BOOKMARK for automatically 3013 // generated suggestions). 3014 // 3015 // Note also that we hide the referrer for Web UI pages. We don't really 3016 // want web sites to see a referrer of "chrome://blah" (and some 3017 // chrome: URLs might have search terms or other stuff we don't want to 3018 // send to the site), so we send no referrer. 3019 OpenURLParams params(url, Referrer(), source_frame_id, disposition, 3020 render_manager_.web_ui()->GetLinkTransitionType(), 3021 false /* is_renderer_initiated */); 3022 params.transferred_global_request_id = old_request_id; 3023 new_contents = OpenURL(params); 3024 transition_type = render_manager_.web_ui()->GetLinkTransitionType(); 3025 } else { 3026 OpenURLParams params(url, referrer, source_frame_id, disposition, 3027 PAGE_TRANSITION_LINK, true /* is_renderer_initiated */); 3028 params.transferred_global_request_id = old_request_id; 3029 params.is_cross_site_redirect = is_cross_site_redirect; 3030 new_contents = OpenURL(params); 3031 } 3032 if (new_contents) { 3033 // Notify observers. 3034 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3035 DidOpenRequestedURL(new_contents, 3036 url, 3037 referrer, 3038 disposition, 3039 transition_type, 3040 source_frame_id)); 3041 } 3042} 3043 3044void WebContentsImpl::RouteCloseEvent(RenderViewHost* rvh) { 3045 // Tell the active RenderViewHost to run unload handlers and close, as long 3046 // as the request came from a RenderViewHost in the same BrowsingInstance. 3047 // In most cases, we receive this from a swapped out RenderViewHost. 3048 // It is possible to receive it from one that has just been swapped in, 3049 // in which case we might as well deliver the message anyway. 3050 if (rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance())) 3051 GetRenderViewHost()->ClosePage(); 3052} 3053 3054void WebContentsImpl::RouteMessageEvent( 3055 RenderViewHost* rvh, 3056 const ViewMsg_PostMessage_Params& params) { 3057 // Only deliver the message to the active RenderViewHost if the request 3058 // came from a RenderViewHost in the same BrowsingInstance or if this 3059 // WebContents is dedicated to a browser plugin guest. 3060 // Note: This check means that an embedder could theoretically receive a 3061 // postMessage from anyone (not just its own guests). However, this is 3062 // probably not a risk for apps since other pages won't have references 3063 // to App windows. 3064 if (!rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()) && 3065 !GetBrowserPluginGuest() && !GetBrowserPluginEmbedder()) 3066 return; 3067 3068 ViewMsg_PostMessage_Params new_params(params); 3069 3070 // If the renderer has changed while the post message is being routed, 3071 // drop the message, as it will not be delivered to the right target. 3072 // TODO(nasko): Check for process ID and target frame id mismatch, once 3073 // http://crbug.com/153701 is fixed. 3074 3075 // If there is a source_routing_id, translate it to the routing ID for 3076 // the equivalent swapped out RVH in the target process. If we need 3077 // to create a swapped out RVH for the source tab, we create its opener 3078 // chain as well, since those will also be accessible to the target page. 3079 if (new_params.source_routing_id != MSG_ROUTING_NONE) { 3080 // Try to look up the WebContents for the source page. 3081 WebContentsImpl* source_contents = NULL; 3082 RenderViewHostImpl* source_rvh = RenderViewHostImpl::FromID( 3083 rvh->GetProcess()->GetID(), params.source_routing_id); 3084 if (source_rvh) { 3085 source_contents = static_cast<WebContentsImpl*>( 3086 source_rvh->GetDelegate()->GetAsWebContents()); 3087 } 3088 3089 if (source_contents) { 3090 if (GetBrowserPluginGuest()) { 3091 // We create a swapped out RenderView for the embedder in the guest's 3092 // render process but we intentionally do not expose the embedder's 3093 // opener chain to it. 3094 new_params.source_routing_id = 3095 source_contents->CreateSwappedOutRenderView(GetSiteInstance()); 3096 } else { 3097 new_params.source_routing_id = 3098 source_contents->CreateOpenerRenderViews(GetSiteInstance()); 3099 } 3100 } else { 3101 // We couldn't find it, so don't pass a source frame. 3102 new_params.source_routing_id = MSG_ROUTING_NONE; 3103 } 3104 } 3105 3106 // In most cases, we receive this from a swapped out RenderViewHost. 3107 // It is possible to receive it from one that has just been swapped in, 3108 // in which case we might as well deliver the message anyway. 3109 Send(new ViewMsg_PostMessageEvent(GetRoutingID(), new_params)); 3110} 3111 3112void WebContentsImpl::RunJavaScriptMessage( 3113 RenderViewHost* rvh, 3114 const string16& message, 3115 const string16& default_prompt, 3116 const GURL& frame_url, 3117 JavaScriptMessageType javascript_message_type, 3118 IPC::Message* reply_msg, 3119 bool* did_suppress_message) { 3120 // Suppress JavaScript dialogs when requested. Also suppress messages when 3121 // showing an interstitial as it's shown over the previous page and we don't 3122 // want the hidden page's dialogs to interfere with the interstitial. 3123 bool suppress_this_message = 3124 static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out() || 3125 ShowingInterstitialPage() || 3126 !delegate_ || 3127 delegate_->ShouldSuppressDialogs() || 3128 !delegate_->GetJavaScriptDialogManager(); 3129 3130 if (!suppress_this_message) { 3131 std::string accept_lang = GetContentClient()->browser()-> 3132 GetAcceptLangs(GetBrowserContext()); 3133 dialog_manager_ = delegate_->GetJavaScriptDialogManager(); 3134 dialog_manager_->RunJavaScriptDialog( 3135 this, 3136 frame_url.GetOrigin(), 3137 accept_lang, 3138 javascript_message_type, 3139 message, 3140 default_prompt, 3141 base::Bind(&WebContentsImpl::OnDialogClosed, 3142 base::Unretained(this), 3143 rvh, 3144 reply_msg), 3145 &suppress_this_message); 3146 } 3147 3148 if (suppress_this_message) { 3149 // If we are suppressing messages, just reply as if the user immediately 3150 // pressed "Cancel". 3151 OnDialogClosed(rvh, reply_msg, false, string16()); 3152 } 3153 3154 *did_suppress_message = suppress_this_message; 3155} 3156 3157void WebContentsImpl::RunBeforeUnloadConfirm(RenderViewHost* rvh, 3158 const string16& message, 3159 bool is_reload, 3160 IPC::Message* reply_msg) { 3161 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh); 3162 if (delegate_) 3163 delegate_->WillRunBeforeUnloadConfirm(); 3164 3165 bool suppress_this_message = 3166 rvhi->is_swapped_out() || 3167 !delegate_ || 3168 delegate_->ShouldSuppressDialogs() || 3169 !delegate_->GetJavaScriptDialogManager(); 3170 if (suppress_this_message) { 3171 // The reply must be sent to the RVH that sent the request. 3172 rvhi->JavaScriptDialogClosed(reply_msg, true, string16()); 3173 return; 3174 } 3175 3176 is_showing_before_unload_dialog_ = true; 3177 dialog_manager_ = delegate_->GetJavaScriptDialogManager(); 3178 dialog_manager_->RunBeforeUnloadDialog( 3179 this, message, is_reload, 3180 base::Bind(&WebContentsImpl::OnDialogClosed, base::Unretained(this), rvh, 3181 reply_msg)); 3182} 3183 3184bool WebContentsImpl::AddMessageToConsole(int32 level, 3185 const string16& message, 3186 int32 line_no, 3187 const string16& source_id) { 3188 if (!delegate_) 3189 return false; 3190 return delegate_->AddMessageToConsole(this, level, message, line_no, 3191 source_id); 3192} 3193 3194WebPreferences WebContentsImpl::GetWebkitPrefs() { 3195 // We want to base the page config off of the real URL, rather than the 3196 // display URL. 3197 GURL url = controller_.GetActiveEntry() 3198 ? controller_.GetActiveEntry()->GetURL() : GURL::EmptyGURL(); 3199 return GetWebkitPrefs(GetRenderViewHost(), url); 3200} 3201 3202int WebContentsImpl::CreateSwappedOutRenderView( 3203 SiteInstance* instance) { 3204 return render_manager_.CreateRenderView(instance, MSG_ROUTING_NONE, true); 3205} 3206 3207void WebContentsImpl::OnUserGesture() { 3208 // Notify observers. 3209 FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetUserGesture()); 3210 3211 ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get(); 3212 if (rdh) // NULL in unittests. 3213 rdh->OnUserGesture(this); 3214} 3215 3216void WebContentsImpl::OnIgnoredUIEvent() { 3217 // Notify observers. 3218 FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetIgnoredUIEvent()); 3219} 3220 3221void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh, 3222 bool is_during_unload) { 3223 // Don't show hung renderer dialog for a swapped out RVH. 3224 if (rvh != GetRenderViewHost()) 3225 return; 3226 3227 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh); 3228 3229 // Ignore renderer unresponsive event if debugger is attached to the tab 3230 // since the event may be a result of the renderer sitting on a breakpoint. 3231 // See http://crbug.com/65458 3232 if (DevToolsAgentHost::IsDebuggerAttached(this)) 3233 return; 3234 3235 if (is_during_unload) { 3236 // Hang occurred while firing the beforeunload/unload handler. 3237 // Pretend the handler fired so tab closing continues as if it had. 3238 rvhi->set_sudden_termination_allowed(true); 3239 3240 if (!render_manager_.ShouldCloseTabOnUnresponsiveRenderer()) 3241 return; 3242 3243 // If the tab hangs in the beforeunload/unload handler there's really 3244 // nothing we can do to recover. Pretend the unload listeners have 3245 // all fired and close the tab. If the hang is in the beforeunload handler 3246 // then the user will not have the option of cancelling the close. 3247 Close(rvh); 3248 return; 3249 } 3250 3251 if (!GetRenderViewHostImpl() || !GetRenderViewHostImpl()->IsRenderViewLive()) 3252 return; 3253 3254 if (delegate_) 3255 delegate_->RendererUnresponsive(this); 3256} 3257 3258void WebContentsImpl::RendererResponsive(RenderViewHost* render_view_host) { 3259 if (delegate_) 3260 delegate_->RendererResponsive(this); 3261} 3262 3263void WebContentsImpl::LoadStateChanged( 3264 const GURL& url, 3265 const net::LoadStateWithParam& load_state, 3266 uint64 upload_position, 3267 uint64 upload_size) { 3268 load_state_ = load_state; 3269 upload_position_ = upload_position; 3270 upload_size_ = upload_size; 3271 load_state_host_ = net::IDNToUnicode(url.host(), 3272 GetContentClient()->browser()->GetAcceptLangs( 3273 GetBrowserContext())); 3274 if (load_state_.state == net::LOAD_STATE_READING_RESPONSE) 3275 SetNotWaitingForResponse(); 3276 if (IsLoading()) { 3277 NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD | INVALIDATE_TYPE_TAB); 3278 } 3279} 3280 3281void WebContentsImpl::WorkerCrashed() { 3282 if (delegate_) 3283 delegate_->WorkerCrashed(this); 3284} 3285 3286void WebContentsImpl::BeforeUnloadFiredFromRenderManager( 3287 bool proceed, const base::TimeTicks& proceed_time, 3288 bool* proceed_to_fire_unload) { 3289 before_unload_end_time_ = proceed_time; 3290 if (delegate_) 3291 delegate_->BeforeUnloadFired(this, proceed, proceed_to_fire_unload); 3292} 3293 3294void WebContentsImpl::RenderViewGoneFromRenderManager( 3295 RenderViewHost* render_view_host) { 3296 DCHECK(crashed_status_ != base::TERMINATION_STATUS_STILL_RUNNING); 3297 RenderViewGone(render_view_host, crashed_status_, crashed_error_code_); 3298} 3299 3300void WebContentsImpl::UpdateRenderViewSizeForRenderManager() { 3301 // TODO(brettw) this is a hack. See WebContentsView::SizeContents. 3302 gfx::Size size = view_->GetContainerSize(); 3303 // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be 3304 // here during container initialization and normal window size will be set 3305 // later. In case of tab duplication this resizing to 0x0 prevents setting 3306 // normal size later so just ignore it. 3307 if (!size.IsEmpty()) 3308 view_->SizeContents(size); 3309} 3310 3311void WebContentsImpl::NotifySwappedFromRenderManager(RenderViewHost* rvh) { 3312 NotifySwapped(rvh); 3313 3314 // Make sure the visible RVH reflects the new delegate's preferences. 3315 if (delegate_) 3316 view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent()); 3317 3318 view_->RenderViewSwappedIn(render_manager_.current_host()); 3319} 3320 3321int WebContentsImpl::CreateOpenerRenderViewsForRenderManager( 3322 SiteInstance* instance) { 3323 if (!opener_) 3324 return MSG_ROUTING_NONE; 3325 3326 // Recursively create RenderViews for anything else in the opener chain. 3327 return opener_->CreateOpenerRenderViews(instance); 3328} 3329 3330int WebContentsImpl::CreateOpenerRenderViews(SiteInstance* instance) { 3331 int opener_route_id = MSG_ROUTING_NONE; 3332 3333 // If this tab has an opener, ensure it has a RenderView in the given 3334 // SiteInstance as well. 3335 if (opener_) 3336 opener_route_id = opener_->CreateOpenerRenderViews(instance); 3337 3338 // If any of the renderers (current, pending, or swapped out) for this 3339 // WebContents has the same SiteInstance, use it. 3340 if (render_manager_.current_host()->GetSiteInstance() == instance) 3341 return render_manager_.current_host()->GetRoutingID(); 3342 3343 if (render_manager_.pending_render_view_host() && 3344 render_manager_.pending_render_view_host()->GetSiteInstance() == instance) 3345 return render_manager_.pending_render_view_host()->GetRoutingID(); 3346 3347 RenderViewHostImpl* rvh = render_manager_.GetSwappedOutRenderViewHost( 3348 instance); 3349 if (rvh) 3350 return rvh->GetRoutingID(); 3351 3352 // Create a swapped out RenderView in the given SiteInstance if none exists, 3353 // setting its opener to the given route_id. Return the new view's route_id. 3354 return render_manager_.CreateRenderView(instance, opener_route_id, true); 3355} 3356 3357NavigationControllerImpl& WebContentsImpl::GetControllerForRenderManager() { 3358 return GetController(); 3359} 3360 3361WebUIImpl* WebContentsImpl::CreateWebUIForRenderManager(const GURL& url) { 3362 return static_cast<WebUIImpl*>(CreateWebUI(url)); 3363} 3364 3365NavigationEntry* 3366 WebContentsImpl::GetLastCommittedNavigationEntryForRenderManager() { 3367 return controller_.GetLastCommittedEntry(); 3368} 3369 3370bool WebContentsImpl::CreateRenderViewForRenderManager( 3371 RenderViewHost* render_view_host, int opener_route_id) { 3372 // Can be NULL during tests. 3373 RenderWidgetHostView* rwh_view = view_->CreateViewForWidget(render_view_host); 3374 3375 // Now that the RenderView has been created, we need to tell it its size. 3376 if (rwh_view) 3377 rwh_view->SetSize(view_->GetContainerSize()); 3378 3379 // Make sure we use the correct starting page_id in the new RenderView. 3380 UpdateMaxPageIDIfNecessary(render_view_host); 3381 int32 max_page_id = 3382 GetMaxPageIDForSiteInstance(render_view_host->GetSiteInstance()); 3383 3384 if (!static_cast<RenderViewHostImpl*>( 3385 render_view_host)->CreateRenderView(string16(), 3386 opener_route_id, 3387 max_page_id)) { 3388 return false; 3389 } 3390 3391#if defined(OS_LINUX) || defined(OS_OPENBSD) 3392 // Force a ViewMsg_Resize to be sent, needed to make plugins show up on 3393 // linux. See crbug.com/83941. 3394 if (rwh_view) { 3395 if (RenderWidgetHost* render_widget_host = rwh_view->GetRenderWidgetHost()) 3396 render_widget_host->WasResized(); 3397 } 3398#endif 3399 3400 return true; 3401} 3402 3403void WebContentsImpl::OnDialogClosed(RenderViewHost* rvh, 3404 IPC::Message* reply_msg, 3405 bool success, 3406 const string16& user_input) { 3407 if (is_showing_before_unload_dialog_ && !success) { 3408 // If a beforeunload dialog is canceled, we need to stop the throbber from 3409 // spinning, since we forced it to start spinning in Navigate. 3410 DidStopLoading(rvh); 3411 controller_.DiscardNonCommittedEntries(); 3412 3413 close_start_time_ = base::TimeTicks(); 3414 before_unload_end_time_ = base::TimeTicks(); 3415 } 3416 is_showing_before_unload_dialog_ = false; 3417 static_cast<RenderViewHostImpl*>( 3418 rvh)->JavaScriptDialogClosed(reply_msg, success, user_input); 3419} 3420 3421void WebContentsImpl::SetEncoding(const std::string& encoding) { 3422 encoding_ = GetContentClient()->browser()-> 3423 GetCanonicalEncodingNameByAliasName(encoding); 3424} 3425 3426void WebContentsImpl::SaveURL(const GURL& url, 3427 const Referrer& referrer, 3428 bool is_main_frame) { 3429 DownloadManager* dlm = 3430 BrowserContext::GetDownloadManager(GetBrowserContext()); 3431 if (!dlm) 3432 return; 3433 int64 post_id = -1; 3434 if (is_main_frame) { 3435 const NavigationEntry* entry = controller_.GetActiveEntry(); 3436 if (entry) 3437 post_id = entry->GetPostID(); 3438 } 3439 scoped_ptr<DownloadUrlParameters> params( 3440 DownloadUrlParameters::FromWebContents(this, url)); 3441 params->set_referrer(referrer); 3442 params->set_post_id(post_id); 3443 params->set_prefer_cache(true); 3444 if (post_id >= 0) 3445 params->set_method("POST"); 3446 params->set_prompt(true); 3447 dlm->DownloadUrl(params.Pass()); 3448} 3449 3450void WebContentsImpl::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) { 3451 RenderWidgetHostView* rwh_view = view_->CreateViewForWidget(rvh); 3452 // Can be NULL during tests. 3453 if (rwh_view) 3454 rwh_view->SetSize(GetView()->GetContainerSize()); 3455} 3456 3457RenderViewHostImpl* WebContentsImpl::GetRenderViewHostImpl() { 3458 return static_cast<RenderViewHostImpl*>(GetRenderViewHost()); 3459} 3460 3461BrowserPluginGuest* WebContentsImpl::GetBrowserPluginGuest() const { 3462 return browser_plugin_guest_.get(); 3463} 3464 3465BrowserPluginEmbedder* WebContentsImpl::GetBrowserPluginEmbedder() const { 3466 return browser_plugin_embedder_.get(); 3467} 3468 3469BrowserPluginGuestManager* 3470 WebContentsImpl::GetBrowserPluginGuestManager() const { 3471 return static_cast<BrowserPluginGuestManager*>( 3472 GetBrowserContext()->GetUserData( 3473 browser_plugin::kBrowserPluginGuestManagerKeyName)); 3474} 3475 3476} // namespace content 3477