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