web_contents_impl.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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/debug/trace_event.h" 11#include "base/lazy_instance.h" 12#include "base/logging.h" 13#include "base/metrics/histogram.h" 14#include "base/metrics/stats_counters.h" 15#include "base/process/process.h" 16#include "base/strings/string16.h" 17#include "base/strings/string_number_conversions.h" 18#include "base/strings/string_util.h" 19#include "base/strings/utf_string_conversions.h" 20#include "base/time/time.h" 21#include "content/browser/accessibility/accessibility_mode_helper.h" 22#include "content/browser/accessibility/browser_accessibility_state_impl.h" 23#include "content/browser/browser_plugin/browser_plugin_embedder.h" 24#include "content/browser/browser_plugin/browser_plugin_guest.h" 25#include "content/browser/child_process_security_policy_impl.h" 26#include "content/browser/devtools/render_view_devtools_agent_host.h" 27#include "content/browser/dom_storage/dom_storage_context_wrapper.h" 28#include "content/browser/dom_storage/session_storage_namespace_impl.h" 29#include "content/browser/download/download_stats.h" 30#include "content/browser/download/mhtml_generation_manager.h" 31#include "content/browser/download/save_package.h" 32#include "content/browser/frame_host/cross_process_frame_connector.h" 33#include "content/browser/frame_host/interstitial_page_impl.h" 34#include "content/browser/frame_host/navigation_entry_impl.h" 35#include "content/browser/frame_host/navigator_impl.h" 36#include "content/browser/frame_host/render_frame_host_impl.h" 37#include "content/browser/frame_host/render_widget_host_view_child_frame.h" 38#include "content/browser/geolocation/geolocation_dispatcher_host.h" 39#include "content/browser/host_zoom_map_impl.h" 40#include "content/browser/loader/resource_dispatcher_host_impl.h" 41#include "content/browser/media/midi_dispatcher_host.h" 42#include "content/browser/message_port_message_filter.h" 43#include "content/browser/message_port_service.h" 44#include "content/browser/power_save_blocker_impl.h" 45#include "content/browser/renderer_host/render_process_host_impl.h" 46#include "content/browser/renderer_host/render_view_host_delegate_view.h" 47#include "content/browser/renderer_host/render_view_host_impl.h" 48#include "content/browser/renderer_host/render_widget_host_impl.h" 49#include "content/browser/renderer_host/render_widget_host_view_base.h" 50#include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h" 51#include "content/browser/site_instance_impl.h" 52#include "content/browser/web_contents/web_contents_view_guest.h" 53#include "content/browser/webui/generic_handler.h" 54#include "content/browser/webui/web_ui_controller_factory_registry.h" 55#include "content/browser/webui/web_ui_impl.h" 56#include "content/common/browser_plugin/browser_plugin_constants.h" 57#include "content/common/browser_plugin/browser_plugin_messages.h" 58#include "content/common/frame_messages.h" 59#include "content/common/image_messages.h" 60#include "content/common/input_messages.h" 61#include "content/common/ssl_status_serialization.h" 62#include "content/common/view_messages.h" 63#include "content/public/browser/ax_event_notification_details.h" 64#include "content/public/browser/browser_context.h" 65#include "content/public/browser/browser_plugin_guest_manager.h" 66#include "content/public/browser/content_browser_client.h" 67#include "content/public/browser/devtools_agent_host.h" 68#include "content/public/browser/download_manager.h" 69#include "content/public/browser/download_url_parameters.h" 70#include "content/public/browser/invalidate_type.h" 71#include "content/public/browser/javascript_dialog_manager.h" 72#include "content/public/browser/load_from_memory_cache_details.h" 73#include "content/public/browser/load_notification_details.h" 74#include "content/public/browser/navigation_details.h" 75#include "content/public/browser/notification_details.h" 76#include "content/public/browser/notification_service.h" 77#include "content/public/browser/render_widget_host_iterator.h" 78#include "content/public/browser/resource_request_details.h" 79#include "content/public/browser/storage_partition.h" 80#include "content/public/browser/user_metrics.h" 81#include "content/public/browser/web_contents_delegate.h" 82#include "content/public/browser/web_contents_observer.h" 83#include "content/public/common/bindings_policy.h" 84#include "content/public/common/content_constants.h" 85#include "content/public/common/content_switches.h" 86#include "content/public/common/page_zoom.h" 87#include "content/public/common/result_codes.h" 88#include "content/public/common/url_constants.h" 89#include "content/public/common/url_utils.h" 90#include "content/public/common/web_preferences.h" 91#include "net/base/mime_util.h" 92#include "net/base/net_util.h" 93#include "net/http/http_cache.h" 94#include "net/http/http_transaction_factory.h" 95#include "net/url_request/url_request_context.h" 96#include "net/url_request/url_request_context_getter.h" 97#include "ui/base/layout.h" 98#include "ui/gfx/display.h" 99#include "ui/gfx/screen.h" 100#include "ui/gl/gl_switches.h" 101 102#if defined(OS_ANDROID) 103#include "content/browser/android/content_view_core_impl.h" 104#include "content/browser/android/date_time_chooser_android.h" 105#include "content/browser/media/android/browser_media_player_manager.h" 106#include "content/browser/web_contents/web_contents_android.h" 107#include "content/public/browser/android/content_view_core.h" 108#endif 109 110#if defined(OS_MACOSX) 111#include "base/mac/foundation_util.h" 112#endif 113 114// Cross-Site Navigations 115// 116// If a WebContentsImpl is told to navigate to a different web site (as 117// determined by SiteInstance), it will replace its current RenderViewHost with 118// a new RenderViewHost dedicated to the new SiteInstance. This works as 119// follows: 120// 121// - RVHM::Navigate determines whether the destination is cross-site, and if so, 122// it creates a pending_render_view_host_. 123// - The pending RVH is "suspended," so that no navigation messages are sent to 124// its renderer until the beforeunload JavaScript handler has a chance to 125// run in the current RVH. 126// - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton) 127// that it has a pending cross-site request. We will check this on the IO 128// thread when deciding how to handle the response. 129// - The current RVH runs its beforeunload handler. If it returns false, we 130// cancel all the pending logic. Otherwise we allow the pending RVH to send 131// the navigation request to its renderer. 132// - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the 133// main resource load on the pending RVH. It creates a 134// CrossSiteResourceHandler to check whether a process swap is needed when 135// the request is ready to commit. 136// - When RDH receives a response, the BufferedResourceHandler determines 137// whether it is a download. If so, it sends a message to the new renderer 138// causing it to cancel the request, and the download proceeds. For now, the 139// pending RVH remains until the next DidNavigate event for this 140// WebContentsImpl. This isn't ideal, but it doesn't affect any functionality. 141// - After RDH receives a response and determines that it is safe and not a 142// download, the CrossSiteResourceHandler checks whether a process swap is 143// needed (either because CrossSiteRequestManager has state for it or because 144// a transfer was needed for a redirect). 145// - If so, CrossSiteResourceHandler pauses the response to first run the old 146// page's unload handler. It does this by asynchronously calling the 147// OnCrossSiteResponse method of RenderFrameHostManager on the UI thread, 148// which sends a SwapOut message to the current RVH. 149// - Once the unload handler is finished, RVHM::SwappedOut checks if a transfer 150// to a new process is needed, based on the stored pending_nav_params_. (This 151// is independent of whether we started out with a cross-process navigation.) 152// - If not, it just tells the ResourceDispatcherHost to resume the response 153// to its current RenderViewHost. 154// - If so, it cancels the current pending RenderViewHost and sets up a new 155// navigation using RequestTransferURL. When the transferred request 156// arrives in the ResourceDispatcherHost, we transfer the response and 157// resume it. 158// - The pending renderer sends a FrameNavigate message that invokes the 159// DidNavigate method. This replaces the current RVH with the 160// pending RVH. 161// - The previous renderer is kept swapped out in RenderFrameHostManager in case 162// the user goes back. The process only stays live if another tab is using 163// it, but if so, the existing frame relationships will be maintained. 164 165namespace content { 166namespace { 167 168const int kMinimumDelayBetweenLoadingUpdatesMS = 100; 169 170// This matches what Blink's ProgressTracker has traditionally used for a 171// minimum progress value. 172const double kMinimumLoadingProgress = 0.1; 173 174const char kDotGoogleDotCom[] = ".google.com"; 175 176#if defined(OS_ANDROID) 177const char kWebContentsAndroidKey[] = "web_contents_android"; 178#endif // OS_ANDROID 179 180base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> > 181g_created_callbacks = LAZY_INSTANCE_INITIALIZER; 182 183static int StartDownload(content::RenderFrameHost* rfh, 184 const GURL& url, 185 bool is_favicon, 186 uint32_t max_bitmap_size) { 187 static int g_next_image_download_id = 0; 188 rfh->Send(new ImageMsg_DownloadImage(rfh->GetRoutingID(), 189 ++g_next_image_download_id, 190 url, 191 is_favicon, 192 max_bitmap_size)); 193 return g_next_image_download_id; 194} 195 196void NotifyCacheOnIO( 197 scoped_refptr<net::URLRequestContextGetter> request_context, 198 const GURL& url, 199 const std::string& http_method) { 200 request_context->GetURLRequestContext()->http_transaction_factory()-> 201 GetCache()->OnExternalCacheHit(url, http_method); 202} 203 204// Helper function for retrieving all the sites in a frame tree. 205bool CollectSites(BrowserContext* context, 206 std::set<GURL>* sites, 207 FrameTreeNode* node) { 208 sites->insert(SiteInstance::GetSiteForURL(context, node->current_url())); 209 return true; 210} 211 212bool ForEachFrameInternal( 213 const base::Callback<void(RenderFrameHost*)>& on_frame, 214 FrameTreeNode* node) { 215 on_frame.Run(node->current_frame_host()); 216 return true; 217} 218 219bool ForEachPendingFrameInternal( 220 const base::Callback<void(RenderFrameHost*)>& on_frame, 221 FrameTreeNode* node) { 222 RenderFrameHost* pending_frame_host = 223 node->render_manager()->pending_frame_host(); 224 if (pending_frame_host) 225 on_frame.Run(pending_frame_host); 226 return true; 227} 228 229void SendToAllFramesInternal(IPC::Message* message, RenderFrameHost* rfh) { 230 IPC::Message* message_copy = new IPC::Message(*message); 231 message_copy->set_routing_id(rfh->GetRoutingID()); 232 rfh->Send(message_copy); 233} 234 235void AddRenderWidgetHostViewToSet(std::set<RenderWidgetHostView*>* set, 236 RenderFrameHost* rfh) { 237 RenderWidgetHostView* rwhv = static_cast<RenderFrameHostImpl*>(rfh) 238 ->frame_tree_node() 239 ->render_manager() 240 ->GetRenderWidgetHostView(); 241 set->insert(rwhv); 242} 243 244void SetAccessibilityModeOnFrame(AccessibilityMode mode, 245 RenderFrameHost* frame_host) { 246 static_cast<RenderFrameHostImpl*>(frame_host)->SetAccessibilityMode(mode); 247} 248 249} // namespace 250 251WebContents* WebContents::Create(const WebContents::CreateParams& params) { 252 return WebContentsImpl::CreateWithOpener( 253 params, static_cast<WebContentsImpl*>(params.opener)); 254} 255 256WebContents* WebContents::CreateWithSessionStorage( 257 const WebContents::CreateParams& params, 258 const SessionStorageNamespaceMap& session_storage_namespace_map) { 259 WebContentsImpl* new_contents = new WebContentsImpl( 260 params.browser_context, NULL); 261 262 for (SessionStorageNamespaceMap::const_iterator it = 263 session_storage_namespace_map.begin(); 264 it != session_storage_namespace_map.end(); 265 ++it) { 266 new_contents->GetController() 267 .SetSessionStorageNamespace(it->first, it->second.get()); 268 } 269 270 new_contents->Init(params); 271 return new_contents; 272} 273 274void WebContentsImpl::AddCreatedCallback(const CreatedCallback& callback) { 275 g_created_callbacks.Get().push_back(callback); 276} 277 278void WebContentsImpl::RemoveCreatedCallback(const CreatedCallback& callback) { 279 for (size_t i = 0; i < g_created_callbacks.Get().size(); ++i) { 280 if (g_created_callbacks.Get().at(i).Equals(callback)) { 281 g_created_callbacks.Get().erase(g_created_callbacks.Get().begin() + i); 282 return; 283 } 284 } 285} 286 287WebContents* WebContents::FromRenderViewHost(const RenderViewHost* rvh) { 288 return rvh->GetDelegate()->GetAsWebContents(); 289} 290 291WebContents* WebContents::FromRenderFrameHost(RenderFrameHost* rfh) { 292 RenderFrameHostImpl* rfh_impl = static_cast<RenderFrameHostImpl*>(rfh); 293 if (!rfh_impl) 294 return NULL; 295 return rfh_impl->delegate()->GetAsWebContents(); 296} 297 298// WebContentsImpl::DestructionObserver ---------------------------------------- 299 300class WebContentsImpl::DestructionObserver : public WebContentsObserver { 301 public: 302 DestructionObserver(WebContentsImpl* owner, WebContents* watched_contents) 303 : WebContentsObserver(watched_contents), 304 owner_(owner) { 305 } 306 307 // WebContentsObserver: 308 virtual void WebContentsDestroyed() OVERRIDE { 309 owner_->OnWebContentsDestroyed( 310 static_cast<WebContentsImpl*>(web_contents())); 311 } 312 313 private: 314 WebContentsImpl* owner_; 315 316 DISALLOW_COPY_AND_ASSIGN(DestructionObserver); 317}; 318 319WebContentsImpl::ColorChooserInfo::ColorChooserInfo(int render_process_id, 320 int render_frame_id, 321 ColorChooser* chooser, 322 int identifier) 323 : render_process_id(render_process_id), 324 render_frame_id(render_frame_id), 325 chooser(chooser), 326 identifier(identifier) { 327} 328 329WebContentsImpl::ColorChooserInfo::~ColorChooserInfo() { 330} 331 332// WebContentsImpl ------------------------------------------------------------- 333 334WebContentsImpl::WebContentsImpl( 335 BrowserContext* browser_context, 336 WebContentsImpl* opener) 337 : delegate_(NULL), 338 controller_(this, browser_context), 339 render_view_host_delegate_view_(NULL), 340 opener_(opener), 341 created_with_opener_(!!opener), 342#if defined(OS_WIN) 343 accessible_parent_(NULL), 344#endif 345 frame_tree_(new NavigatorImpl(&controller_, this), 346 this, this, this, this), 347 is_loading_(false), 348 is_load_to_different_document_(false), 349 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING), 350 crashed_error_code_(0), 351 waiting_for_response_(false), 352 load_state_(net::LOAD_STATE_IDLE, base::string16()), 353 loading_total_progress_(0.0), 354 loading_weak_factory_(this), 355 loading_frames_in_progress_(0), 356 upload_size_(0), 357 upload_position_(0), 358 displayed_insecure_content_(false), 359 has_accessed_initial_document_(false), 360 capturer_count_(0), 361 should_normally_be_visible_(true), 362 is_being_destroyed_(false), 363 notify_disconnection_(false), 364 dialog_manager_(NULL), 365 is_showing_before_unload_dialog_(false), 366 last_active_time_(base::TimeTicks::Now()), 367 closed_by_user_gesture_(false), 368 minimum_zoom_percent_(static_cast<int>(kMinimumZoomFactor * 100)), 369 maximum_zoom_percent_(static_cast<int>(kMaximumZoomFactor * 100)), 370 totalPinchGestureAmount_(0), 371 currentPinchZoomStepDelta_(0), 372 render_view_message_source_(NULL), 373 fullscreen_widget_routing_id_(MSG_ROUTING_NONE), 374 fullscreen_widget_had_focus_at_shutdown_(false), 375 is_subframe_(false), 376 touch_emulation_enabled_(false), 377 last_dialog_suppressed_(false), 378 accessibility_mode_( 379 BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode()) { 380 for (size_t i = 0; i < g_created_callbacks.Get().size(); i++) 381 g_created_callbacks.Get().at(i).Run(this); 382 frame_tree_.SetFrameRemoveListener( 383 base::Bind(&WebContentsImpl::OnFrameRemoved, 384 base::Unretained(this))); 385} 386 387WebContentsImpl::~WebContentsImpl() { 388 is_being_destroyed_ = true; 389 390 // Delete all RFH pending shutdown, which will lead the corresponding RVH to 391 // shutdown and be deleted as well. 392 frame_tree_.ForEach( 393 base::Bind(&RenderFrameHostManager::ClearRFHsPendingShutdown)); 394 395 ClearAllPowerSaveBlockers(); 396 397 for (std::set<RenderWidgetHostImpl*>::iterator iter = 398 created_widgets_.begin(); iter != created_widgets_.end(); ++iter) { 399 (*iter)->DetachDelegate(); 400 } 401 created_widgets_.clear(); 402 403 // Clear out any JavaScript state. 404 if (dialog_manager_) 405 dialog_manager_->WebContentsDestroyed(this); 406 407 if (color_chooser_info_.get()) 408 color_chooser_info_->chooser->End(); 409 410 NotifyDisconnected(); 411 412 // Notify any observer that have a reference on this WebContents. 413 NotificationService::current()->Notify( 414 NOTIFICATION_WEB_CONTENTS_DESTROYED, 415 Source<WebContents>(this), 416 NotificationService::NoDetails()); 417 418 // Destroy all frame tree nodes except for the root; this notifies observers. 419 frame_tree_.ResetForMainFrameSwap(); 420 GetRenderManager()->ResetProxyHosts(); 421 422 // Manually call the observer methods for the root frame tree node. 423 RenderFrameHostManager* root = GetRenderManager(); 424 if (root->pending_frame_host()) { 425 FOR_EACH_OBSERVER(WebContentsObserver, 426 observers_, 427 RenderFrameDeleted(root->pending_frame_host())); 428 } 429 FOR_EACH_OBSERVER(WebContentsObserver, 430 observers_, 431 RenderFrameDeleted(root->current_frame_host())); 432 433 if (root->pending_render_view_host()) { 434 FOR_EACH_OBSERVER(WebContentsObserver, 435 observers_, 436 RenderViewDeleted(root->pending_render_view_host())); 437 } 438 439 FOR_EACH_OBSERVER(WebContentsObserver, 440 observers_, 441 RenderViewDeleted(root->current_host())); 442 443 FOR_EACH_OBSERVER(WebContentsObserver, 444 observers_, 445 WebContentsDestroyed()); 446 447 FOR_EACH_OBSERVER(WebContentsObserver, 448 observers_, 449 ResetWebContents()); 450 451 SetDelegate(NULL); 452 453 STLDeleteContainerPairSecondPointers(destruction_observers_.begin(), 454 destruction_observers_.end()); 455} 456 457WebContentsImpl* WebContentsImpl::CreateWithOpener( 458 const WebContents::CreateParams& params, 459 WebContentsImpl* opener) { 460 TRACE_EVENT0("browser", "WebContentsImpl::CreateWithOpener"); 461 WebContentsImpl* new_contents = new WebContentsImpl( 462 params.browser_context, params.opener_suppressed ? NULL : opener); 463 464 if (params.guest_delegate) { 465 // This makes |new_contents| act as a guest. 466 // For more info, see comment above class BrowserPluginGuest. 467 BrowserPluginGuest::Create(params.guest_delegate->GetGuestInstanceID(), 468 new_contents, 469 params.guest_delegate); 470 // We are instantiating a WebContents for browser plugin. Set its subframe 471 // bit to true. 472 new_contents->is_subframe_ = true; 473 } 474 new_contents->Init(params); 475 return new_contents; 476} 477 478// static 479std::vector<WebContentsImpl*> WebContentsImpl::GetAllWebContents() { 480 std::vector<WebContentsImpl*> result; 481 scoped_ptr<RenderWidgetHostIterator> widgets( 482 RenderWidgetHostImpl::GetRenderWidgetHosts()); 483 std::set<WebContentsImpl*> web_contents_set; 484 while (RenderWidgetHost* rwh = widgets->GetNextHost()) { 485 if (!rwh->IsRenderView()) 486 continue; 487 RenderViewHost* rvh = RenderViewHost::From(rwh); 488 if (!rvh) 489 continue; 490 WebContents* web_contents = WebContents::FromRenderViewHost(rvh); 491 if (!web_contents) 492 continue; 493 WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents); 494 if (web_contents_set.find(wci) == web_contents_set.end()) { 495 web_contents_set.insert(wci); 496 result.push_back(wci); 497 } 498 } 499 return result; 500} 501 502RenderFrameHostManager* WebContentsImpl::GetRenderManagerForTesting() { 503 return GetRenderManager(); 504} 505 506bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host, 507 const IPC::Message& message) { 508 return OnMessageReceived(render_view_host, NULL, message); 509} 510 511bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host, 512 RenderFrameHost* render_frame_host, 513 const IPC::Message& message) { 514 DCHECK(render_view_host || render_frame_host); 515 if (GetWebUI() && 516 static_cast<WebUIImpl*>(GetWebUI())->OnMessageReceived(message)) { 517 return true; 518 } 519 520 ObserverListBase<WebContentsObserver>::Iterator it(observers_); 521 WebContentsObserver* observer; 522 if (render_frame_host) { 523 while ((observer = it.GetNext()) != NULL) 524 if (observer->OnMessageReceived(message, render_frame_host)) 525 return true; 526 } else { 527 while ((observer = it.GetNext()) != NULL) 528 if (observer->OnMessageReceived(message)) 529 return true; 530 } 531 532 // Message handlers should be aware of which 533 // RenderViewHost/RenderFrameHost sent the message, which is temporarily 534 // stored in render_(view|frame)_message_source_. 535 if (render_frame_host) { 536 if (RenderViewDevToolsAgentHost::DispatchIPCMessage( 537 render_frame_host->GetRenderViewHost(), message)) 538 return true; 539 render_frame_message_source_ = render_frame_host; 540 } else { 541 if (RenderViewDevToolsAgentHost::DispatchIPCMessage( 542 render_view_host, message)) 543 return true; 544 render_view_message_source_ = render_view_host; 545 } 546 547 bool handled = true; 548 IPC_BEGIN_MESSAGE_MAP(WebContentsImpl, message) 549 IPC_MESSAGE_HANDLER(FrameHostMsg_PepperPluginHung, OnPepperPluginHung) 550 IPC_MESSAGE_HANDLER(FrameHostMsg_PluginCrashed, OnPluginCrashed) 551 IPC_MESSAGE_HANDLER(FrameHostMsg_DomOperationResponse, 552 OnDomOperationResponse) 553 IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeThemeColor, 554 OnThemeColorChanged) 555 IPC_MESSAGE_HANDLER(FrameHostMsg_DidDetectXSS, OnDidDetectXSS) 556 IPC_MESSAGE_HANDLER(FrameHostMsg_DidFinishDocumentLoad, 557 OnDocumentLoadedInFrame) 558 IPC_MESSAGE_HANDLER(FrameHostMsg_DidFinishLoad, OnDidFinishLoad) 559 IPC_MESSAGE_HANDLER(FrameHostMsg_DidStartLoading, OnDidStartLoading) 560 IPC_MESSAGE_HANDLER(FrameHostMsg_DidStopLoading, OnDidStopLoading) 561 IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeLoadProgress, 562 OnDidChangeLoadProgress) 563 IPC_MESSAGE_HANDLER(FrameHostMsg_OpenColorChooser, OnOpenColorChooser) 564 IPC_MESSAGE_HANDLER(FrameHostMsg_EndColorChooser, OnEndColorChooser) 565 IPC_MESSAGE_HANDLER(FrameHostMsg_SetSelectedColorInColorChooser, 566 OnSetSelectedColorInColorChooser) 567 IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPlayingNotification, 568 OnMediaPlayingNotification) 569 IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPausedNotification, 570 OnMediaPausedNotification) 571 IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache, 572 OnDidLoadResourceFromMemoryCache) 573 IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent, 574 OnDidDisplayInsecureContent) 575 IPC_MESSAGE_HANDLER(ViewHostMsg_DidRunInsecureContent, 576 OnDidRunInsecureContent) 577 IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset, OnGoToEntryAtOffset) 578 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits, OnUpdateZoomLimits) 579 IPC_MESSAGE_HANDLER(ViewHostMsg_EnumerateDirectory, OnEnumerateDirectory) 580 IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler, 581 OnRegisterProtocolHandler) 582 IPC_MESSAGE_HANDLER(ViewHostMsg_UnregisterProtocolHandler, 583 OnUnregisterProtocolHandler) 584 IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnFindReply) 585 IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed, OnAppCacheAccessed) 586 IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnWebUISend) 587 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission, 588 OnRequestPpapiBrokerPermission) 589 IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_Attach, 590 OnBrowserPluginMessage(message)) 591 IPC_MESSAGE_HANDLER(ImageHostMsg_DidDownloadImage, OnDidDownloadImage) 592 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFaviconURL, OnUpdateFaviconURL) 593 IPC_MESSAGE_HANDLER(ViewHostMsg_DidFirstVisuallyNonEmptyPaint, 594 OnFirstVisuallyNonEmptyPaint) 595 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowValidationMessage, 596 OnShowValidationMessage) 597 IPC_MESSAGE_HANDLER(ViewHostMsg_HideValidationMessage, 598 OnHideValidationMessage) 599 IPC_MESSAGE_HANDLER(ViewHostMsg_MoveValidationMessage, 600 OnMoveValidationMessage) 601#if defined(OS_ANDROID) 602 IPC_MESSAGE_HANDLER(ViewHostMsg_FindMatchRects_Reply, 603 OnFindMatchRectsReply) 604 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog, 605 OnOpenDateTimeDialog) 606#endif 607 IPC_MESSAGE_UNHANDLED(handled = false) 608 IPC_END_MESSAGE_MAP() 609 render_view_message_source_ = NULL; 610 render_frame_message_source_ = NULL; 611 612 return handled; 613} 614 615void WebContentsImpl::RunFileChooser( 616 RenderViewHost* render_view_host, 617 const FileChooserParams& params) { 618 if (delegate_) 619 delegate_->RunFileChooser(this, params); 620} 621 622NavigationControllerImpl& WebContentsImpl::GetController() { 623 return controller_; 624} 625 626const NavigationControllerImpl& WebContentsImpl::GetController() const { 627 return controller_; 628} 629 630BrowserContext* WebContentsImpl::GetBrowserContext() const { 631 return controller_.GetBrowserContext(); 632} 633 634const GURL& WebContentsImpl::GetURL() const { 635 // We may not have a navigation entry yet. 636 NavigationEntry* entry = controller_.GetVisibleEntry(); 637 return entry ? entry->GetVirtualURL() : GURL::EmptyGURL(); 638} 639 640const GURL& WebContentsImpl::GetVisibleURL() const { 641 // We may not have a navigation entry yet. 642 NavigationEntry* entry = controller_.GetVisibleEntry(); 643 return entry ? entry->GetVirtualURL() : GURL::EmptyGURL(); 644} 645 646const GURL& WebContentsImpl::GetLastCommittedURL() const { 647 // We may not have a navigation entry yet. 648 NavigationEntry* entry = controller_.GetLastCommittedEntry(); 649 return entry ? entry->GetVirtualURL() : GURL::EmptyGURL(); 650} 651 652WebContentsDelegate* WebContentsImpl::GetDelegate() { 653 return delegate_; 654} 655 656void WebContentsImpl::SetDelegate(WebContentsDelegate* delegate) { 657 // TODO(cbentzel): remove this debugging code? 658 if (delegate == delegate_) 659 return; 660 if (delegate_) 661 delegate_->Detach(this); 662 delegate_ = delegate; 663 if (delegate_) { 664 delegate_->Attach(this); 665 // Ensure the visible RVH reflects the new delegate's preferences. 666 if (view_) 667 view_->SetOverscrollControllerEnabled(CanOverscrollContent()); 668 } 669} 670 671RenderProcessHost* WebContentsImpl::GetRenderProcessHost() const { 672 RenderViewHostImpl* host = GetRenderManager()->current_host(); 673 return host ? host->GetProcess() : NULL; 674} 675 676RenderFrameHost* WebContentsImpl::GetMainFrame() { 677 return frame_tree_.root()->current_frame_host(); 678} 679 680RenderFrameHost* WebContentsImpl::GetFocusedFrame() { 681 if (!frame_tree_.GetFocusedFrame()) 682 return NULL; 683 return frame_tree_.GetFocusedFrame()->current_frame_host(); 684} 685 686void WebContentsImpl::ForEachFrame( 687 const base::Callback<void(RenderFrameHost*)>& on_frame) { 688 frame_tree_.ForEach(base::Bind(&ForEachFrameInternal, on_frame)); 689} 690 691void WebContentsImpl::SendToAllFrames(IPC::Message* message) { 692 ForEachFrame(base::Bind(&SendToAllFramesInternal, message)); 693 delete message; 694} 695 696RenderViewHost* WebContentsImpl::GetRenderViewHost() const { 697 return GetRenderManager()->current_host(); 698} 699 700int WebContentsImpl::GetRoutingID() const { 701 if (!GetRenderViewHost()) 702 return MSG_ROUTING_NONE; 703 704 return GetRenderViewHost()->GetRoutingID(); 705} 706 707int WebContentsImpl::GetFullscreenWidgetRoutingID() const { 708 return fullscreen_widget_routing_id_; 709} 710 711RenderWidgetHostView* WebContentsImpl::GetRenderWidgetHostView() const { 712 return GetRenderManager()->GetRenderWidgetHostView(); 713} 714 715RenderWidgetHostView* WebContentsImpl::GetFullscreenRenderWidgetHostView() 716 const { 717 RenderWidgetHost* const widget_host = 718 RenderWidgetHostImpl::FromID(GetRenderProcessHost()->GetID(), 719 GetFullscreenWidgetRoutingID()); 720 return widget_host ? widget_host->GetView() : NULL; 721} 722 723WebContentsView* WebContentsImpl::GetView() const { 724 return view_.get(); 725} 726 727void WebContentsImpl::SetAccessibilityMode(AccessibilityMode mode) { 728 if (mode == accessibility_mode_) 729 return; 730 731 accessibility_mode_ = mode; 732 frame_tree_.ForEach( 733 base::Bind(&ForEachFrameInternal, 734 base::Bind(&SetAccessibilityModeOnFrame, mode))); 735 frame_tree_.ForEach( 736 base::Bind(&ForEachPendingFrameInternal, 737 base::Bind(&SetAccessibilityModeOnFrame, mode))); 738} 739 740void WebContentsImpl::AddAccessibilityMode(AccessibilityMode mode) { 741 SetAccessibilityMode( 742 content::AddAccessibilityModeTo(accessibility_mode_, mode)); 743} 744 745void WebContentsImpl::RemoveAccessibilityMode(AccessibilityMode mode) { 746 SetAccessibilityMode( 747 content::RemoveAccessibilityModeFrom(accessibility_mode_, mode)); 748} 749 750WebUI* WebContentsImpl::CreateWebUI(const GURL& url) { 751 WebUIImpl* web_ui = new WebUIImpl(this); 752 WebUIController* controller = WebUIControllerFactoryRegistry::GetInstance()-> 753 CreateWebUIControllerForURL(web_ui, url); 754 if (controller) { 755 web_ui->AddMessageHandler(new GenericHandler()); 756 web_ui->SetController(controller); 757 return web_ui; 758 } 759 760 delete web_ui; 761 return NULL; 762} 763 764WebUI* WebContentsImpl::GetWebUI() const { 765 return GetRenderManager()->web_ui() ? GetRenderManager()->web_ui() 766 : GetRenderManager()->pending_web_ui(); 767} 768 769WebUI* WebContentsImpl::GetCommittedWebUI() const { 770 return GetRenderManager()->web_ui(); 771} 772 773void WebContentsImpl::SetUserAgentOverride(const std::string& override) { 774 if (GetUserAgentOverride() == override) 775 return; 776 777 renderer_preferences_.user_agent_override = override; 778 779 // Send the new override string to the renderer. 780 RenderViewHost* host = GetRenderViewHost(); 781 if (host) 782 host->SyncRendererPrefs(); 783 784 // Reload the page if a load is currently in progress to avoid having 785 // different parts of the page loaded using different user agents. 786 NavigationEntry* entry = controller_.GetVisibleEntry(); 787 if (is_loading_ && entry != NULL && entry->GetIsOverridingUserAgent()) 788 controller_.ReloadIgnoringCache(true); 789 790 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 791 UserAgentOverrideSet(override)); 792} 793 794const std::string& WebContentsImpl::GetUserAgentOverride() const { 795 return renderer_preferences_.user_agent_override; 796} 797 798void WebContentsImpl::EnableTreeOnlyAccessibilityMode() { 799 AddAccessibilityMode(AccessibilityModeTreeOnly); 800} 801 802bool WebContentsImpl::IsTreeOnlyAccessibilityModeForTesting() const { 803 return accessibility_mode_ == AccessibilityModeTreeOnly; 804} 805 806bool WebContentsImpl::IsFullAccessibilityModeForTesting() const { 807 return accessibility_mode_ == AccessibilityModeComplete; 808} 809 810#if defined(OS_WIN) 811void WebContentsImpl::SetParentNativeViewAccessible( 812gfx::NativeViewAccessible accessible_parent) { 813 accessible_parent_ = accessible_parent; 814 RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame()); 815 if (rfh) 816 rfh->SetParentNativeViewAccessible(accessible_parent); 817} 818#endif 819 820const base::string16& WebContentsImpl::GetTitle() const { 821 // Transient entries take precedence. They are used for interstitial pages 822 // that are shown on top of existing pages. 823 NavigationEntry* entry = controller_.GetTransientEntry(); 824 std::string accept_languages = 825 GetContentClient()->browser()->GetAcceptLangs( 826 GetBrowserContext()); 827 if (entry) { 828 return entry->GetTitleForDisplay(accept_languages); 829 } 830 WebUI* our_web_ui = GetRenderManager()->pending_web_ui() ? 831 GetRenderManager()->pending_web_ui() : GetRenderManager()->web_ui(); 832 if (our_web_ui) { 833 // Don't override the title in view source mode. 834 entry = controller_.GetVisibleEntry(); 835 if (!(entry && entry->IsViewSourceMode())) { 836 // Give the Web UI the chance to override our title. 837 const base::string16& title = our_web_ui->GetOverriddenTitle(); 838 if (!title.empty()) 839 return title; 840 } 841 } 842 843 // We use the title for the last committed entry rather than a pending 844 // navigation entry. For example, when the user types in a URL, we want to 845 // keep the old page's title until the new load has committed and we get a new 846 // title. 847 entry = controller_.GetLastCommittedEntry(); 848 849 // We make an exception for initial navigations. 850 if (controller_.IsInitialNavigation()) { 851 // We only want to use the title from the visible entry in one of two cases: 852 // 1. There's already a committed entry for an initial navigation, in which 853 // case we are doing a history navigation in a new tab (e.g., Ctrl+Back). 854 // 2. The pending entry has been explicitly assigned a title to display. 855 // 856 // If there's no last committed entry and no assigned title, we should fall 857 // back to |page_title_when_no_navigation_entry_| rather than showing the 858 // URL. 859 if (entry || 860 (controller_.GetVisibleEntry() && 861 !controller_.GetVisibleEntry()->GetTitle().empty())) { 862 entry = controller_.GetVisibleEntry(); 863 } 864 } 865 866 if (entry) { 867 return entry->GetTitleForDisplay(accept_languages); 868 } 869 870 // |page_title_when_no_navigation_entry_| is finally used 871 // if no title cannot be retrieved. 872 return page_title_when_no_navigation_entry_; 873} 874 875int32 WebContentsImpl::GetMaxPageID() { 876 return GetMaxPageIDForSiteInstance(GetSiteInstance()); 877} 878 879int32 WebContentsImpl::GetMaxPageIDForSiteInstance( 880 SiteInstance* site_instance) { 881 if (max_page_ids_.find(site_instance->GetId()) == max_page_ids_.end()) 882 max_page_ids_[site_instance->GetId()] = -1; 883 884 return max_page_ids_[site_instance->GetId()]; 885} 886 887void WebContentsImpl::UpdateMaxPageID(int32 page_id) { 888 UpdateMaxPageIDForSiteInstance(GetSiteInstance(), page_id); 889} 890 891void WebContentsImpl::UpdateMaxPageIDForSiteInstance( 892 SiteInstance* site_instance, int32 page_id) { 893 if (GetMaxPageIDForSiteInstance(site_instance) < page_id) 894 max_page_ids_[site_instance->GetId()] = page_id; 895} 896 897void WebContentsImpl::CopyMaxPageIDsFrom(WebContents* web_contents) { 898 WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents); 899 max_page_ids_ = contents->max_page_ids_; 900} 901 902SiteInstance* WebContentsImpl::GetSiteInstance() const { 903 return GetRenderManager()->current_host()->GetSiteInstance(); 904} 905 906SiteInstance* WebContentsImpl::GetPendingSiteInstance() const { 907 RenderViewHost* dest_rvh = GetRenderManager()->pending_render_view_host() ? 908 GetRenderManager()->pending_render_view_host() : 909 GetRenderManager()->current_host(); 910 return dest_rvh->GetSiteInstance(); 911} 912 913bool WebContentsImpl::IsLoading() const { 914 return is_loading_; 915} 916 917bool WebContentsImpl::IsLoadingToDifferentDocument() const { 918 return is_loading_ && is_load_to_different_document_; 919} 920 921bool WebContentsImpl::IsWaitingForResponse() const { 922 return waiting_for_response_ && is_load_to_different_document_; 923} 924 925const net::LoadStateWithParam& WebContentsImpl::GetLoadState() const { 926 return load_state_; 927} 928 929const base::string16& WebContentsImpl::GetLoadStateHost() const { 930 return load_state_host_; 931} 932 933uint64 WebContentsImpl::GetUploadSize() const { 934 return upload_size_; 935} 936 937uint64 WebContentsImpl::GetUploadPosition() const { 938 return upload_position_; 939} 940 941std::set<GURL> WebContentsImpl::GetSitesInTab() const { 942 std::set<GURL> sites; 943 frame_tree_.ForEach(base::Bind(&CollectSites, 944 base::Unretained(GetBrowserContext()), 945 base::Unretained(&sites))); 946 return sites; 947} 948 949const std::string& WebContentsImpl::GetEncoding() const { 950 return canonical_encoding_; 951} 952 953bool WebContentsImpl::DisplayedInsecureContent() const { 954 return displayed_insecure_content_; 955} 956 957void WebContentsImpl::IncrementCapturerCount(const gfx::Size& capture_size) { 958 DCHECK(!is_being_destroyed_); 959 ++capturer_count_; 960 DVLOG(1) << "There are now " << capturer_count_ 961 << " capturing(s) of WebContentsImpl@" << this; 962 963 // Note: This provides a hint to upstream code to size the views optimally 964 // for quality (e.g., to avoid scaling). 965 if (!capture_size.IsEmpty() && preferred_size_for_capture_.IsEmpty()) { 966 preferred_size_for_capture_ = capture_size; 967 OnPreferredSizeChanged(preferred_size_); 968 } 969} 970 971void WebContentsImpl::DecrementCapturerCount() { 972 --capturer_count_; 973 DVLOG(1) << "There are now " << capturer_count_ 974 << " capturing(s) of WebContentsImpl@" << this; 975 DCHECK_LE(0, capturer_count_); 976 977 if (is_being_destroyed_) 978 return; 979 980 if (capturer_count_ == 0) { 981 const gfx::Size old_size = preferred_size_for_capture_; 982 preferred_size_for_capture_ = gfx::Size(); 983 OnPreferredSizeChanged(old_size); 984 } 985 986 if (IsHidden()) { 987 DVLOG(1) << "Executing delayed WasHidden()."; 988 WasHidden(); 989 } 990} 991 992int WebContentsImpl::GetCapturerCount() const { 993 return capturer_count_; 994} 995 996bool WebContentsImpl::IsCrashed() const { 997 return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED || 998 crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION || 999 crashed_status_ == base::TERMINATION_STATUS_PROCESS_WAS_KILLED); 1000} 1001 1002void WebContentsImpl::SetIsCrashed(base::TerminationStatus status, 1003 int error_code) { 1004 if (status == crashed_status_) 1005 return; 1006 1007 crashed_status_ = status; 1008 crashed_error_code_ = error_code; 1009 NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB); 1010} 1011 1012base::TerminationStatus WebContentsImpl::GetCrashedStatus() const { 1013 return crashed_status_; 1014} 1015 1016bool WebContentsImpl::IsBeingDestroyed() const { 1017 return is_being_destroyed_; 1018} 1019 1020void WebContentsImpl::NotifyNavigationStateChanged(unsigned changed_flags) { 1021 if (delegate_) 1022 delegate_->NavigationStateChanged(this, changed_flags); 1023} 1024 1025base::TimeTicks WebContentsImpl::GetLastActiveTime() const { 1026 return last_active_time_; 1027} 1028 1029void WebContentsImpl::WasShown() { 1030 controller_.SetActive(true); 1031 1032 std::set<RenderWidgetHostView*> widgets = GetRenderWidgetHostViewsInTree(); 1033 for (std::set<RenderWidgetHostView*>::iterator iter = widgets.begin(); 1034 iter != widgets.end(); 1035 iter++) { 1036 if (*iter) { 1037 (*iter)->Show(); 1038#if defined(OS_MACOSX) 1039 (*iter)->SetActive(true); 1040#endif 1041 } 1042 } 1043 1044 last_active_time_ = base::TimeTicks::Now(); 1045 1046 // The resize rect might have changed while this was inactive -- send the new 1047 // one to make sure it's up to date. 1048 RenderViewHostImpl* rvh = 1049 static_cast<RenderViewHostImpl*>(GetRenderViewHost()); 1050 if (rvh) { 1051 rvh->ResizeRectChanged(GetRootWindowResizerRect()); 1052 } 1053 1054 FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasShown()); 1055 1056 should_normally_be_visible_ = true; 1057} 1058 1059void WebContentsImpl::WasHidden() { 1060 // If there are entities capturing screenshots or video (e.g., mirroring), 1061 // don't activate the "disable rendering" optimization. 1062 if (capturer_count_ == 0) { 1063 // |GetRenderViewHost()| can be NULL if the user middle clicks a link to 1064 // open a tab in the background, then closes the tab before selecting it. 1065 // This is because closing the tab calls WebContentsImpl::Destroy(), which 1066 // removes the |GetRenderViewHost()|; then when we actually destroy the 1067 // window, OnWindowPosChanged() notices and calls WasHidden() (which 1068 // calls us). 1069 std::set<RenderWidgetHostView*> widgets = GetRenderWidgetHostViewsInTree(); 1070 for (std::set<RenderWidgetHostView*>::iterator iter = widgets.begin(); 1071 iter != widgets.end(); 1072 iter++) { 1073 if (*iter) 1074 (*iter)->Hide(); 1075 } 1076 } 1077 1078 FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasHidden()); 1079 1080 should_normally_be_visible_ = false; 1081} 1082 1083bool WebContentsImpl::NeedToFireBeforeUnload() { 1084 // TODO(creis): Should we fire even for interstitial pages? 1085 return WillNotifyDisconnection() && 1086 !ShowingInterstitialPage() && 1087 !static_cast<RenderViewHostImpl*>( 1088 GetRenderViewHost())->SuddenTerminationAllowed(); 1089} 1090 1091void WebContentsImpl::DispatchBeforeUnload(bool for_cross_site_transition) { 1092 static_cast<RenderFrameHostImpl*>(GetMainFrame())->DispatchBeforeUnload( 1093 for_cross_site_transition); 1094} 1095 1096void WebContentsImpl::Stop() { 1097 GetRenderManager()->Stop(); 1098 FOR_EACH_OBSERVER(WebContentsObserver, observers_, NavigationStopped()); 1099} 1100 1101WebContents* WebContentsImpl::Clone() { 1102 // We use our current SiteInstance since the cloned entry will use it anyway. 1103 // We pass our own opener so that the cloned page can access it if it was 1104 // before. 1105 CreateParams create_params(GetBrowserContext(), GetSiteInstance()); 1106 create_params.initial_size = GetContainerBounds().size(); 1107 WebContentsImpl* tc = CreateWithOpener(create_params, opener_); 1108 tc->GetController().CopyStateFrom(controller_); 1109 FOR_EACH_OBSERVER(WebContentsObserver, 1110 observers_, 1111 DidCloneToNewWebContents(this, tc)); 1112 return tc; 1113} 1114 1115void WebContentsImpl::Observe(int type, 1116 const NotificationSource& source, 1117 const NotificationDetails& details) { 1118 switch (type) { 1119 case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED: { 1120 RenderWidgetHost* host = Source<RenderWidgetHost>(source).ptr(); 1121 RenderWidgetHostView* view = host->GetView(); 1122 if (view == GetFullscreenRenderWidgetHostView()) { 1123 // We cannot just call view_->RestoreFocus() here. On some platforms, 1124 // attempting to focus the currently-invisible WebContentsView will be 1125 // flat-out ignored. Therefore, this boolean is used to track whether 1126 // we will request focus after the fullscreen widget has been 1127 // destroyed. 1128 fullscreen_widget_had_focus_at_shutdown_ = (view && view->HasFocus()); 1129 } else { 1130 for (PendingWidgetViews::iterator i = pending_widget_views_.begin(); 1131 i != pending_widget_views_.end(); ++i) { 1132 if (host->GetView() == i->second) { 1133 pending_widget_views_.erase(i); 1134 break; 1135 } 1136 } 1137 } 1138 break; 1139 } 1140 default: 1141 NOTREACHED(); 1142 } 1143} 1144 1145WebContents* WebContentsImpl::GetWebContents() { 1146 return this; 1147} 1148 1149void WebContentsImpl::Init(const WebContents::CreateParams& params) { 1150 // This is set before initializing the render manager since 1151 // RenderFrameHostManager::Init calls back into us via its delegate to ask if 1152 // it should be hidden. 1153 should_normally_be_visible_ = !params.initially_hidden; 1154 1155 GetRenderManager()->Init( 1156 params.browser_context, params.site_instance, params.routing_id, 1157 params.main_frame_routing_id); 1158 1159 WebContentsViewDelegate* delegate = 1160 GetContentClient()->browser()->GetWebContentsViewDelegate(this); 1161 1162 if (browser_plugin_guest_) { 1163 scoped_ptr<WebContentsView> platform_view(CreateWebContentsView( 1164 this, delegate, &render_view_host_delegate_view_)); 1165 1166 WebContentsViewGuest* rv = new WebContentsViewGuest( 1167 this, browser_plugin_guest_.get(), platform_view.Pass(), 1168 render_view_host_delegate_view_); 1169 render_view_host_delegate_view_ = rv; 1170 view_.reset(rv); 1171 } else { 1172 // Regular WebContentsView. 1173 view_.reset(CreateWebContentsView( 1174 this, delegate, &render_view_host_delegate_view_)); 1175 } 1176 CHECK(render_view_host_delegate_view_); 1177 CHECK(view_.get()); 1178 1179 gfx::Size initial_size = params.initial_size; 1180 view_->CreateView(initial_size, params.context); 1181 1182 // Listen for whether our opener gets destroyed. 1183 if (opener_) 1184 AddDestructionObserver(opener_); 1185 1186 registrar_.Add(this, 1187 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, 1188 NotificationService::AllBrowserContextsAndSources()); 1189 1190 geolocation_dispatcher_host_.reset(new GeolocationDispatcherHost(this)); 1191 midi_dispatcher_host_.reset(new MidiDispatcherHost(this)); 1192 1193 screen_orientation_dispatcher_host_.reset( 1194 new ScreenOrientationDispatcherHost(this)); 1195 1196#if defined(OS_ANDROID) 1197 date_time_chooser_.reset(new DateTimeChooserAndroid()); 1198#endif 1199} 1200 1201void WebContentsImpl::OnWebContentsDestroyed(WebContentsImpl* web_contents) { 1202 RemoveDestructionObserver(web_contents); 1203 1204 // Clear the opener if it has been closed. 1205 if (web_contents == opener_) { 1206 opener_ = NULL; 1207 return; 1208 } 1209 // Clear a pending contents that has been closed before being shown. 1210 for (PendingContents::iterator iter = pending_contents_.begin(); 1211 iter != pending_contents_.end(); 1212 ++iter) { 1213 if (iter->second != web_contents) 1214 continue; 1215 pending_contents_.erase(iter); 1216 return; 1217 } 1218 NOTREACHED(); 1219} 1220 1221void WebContentsImpl::AddDestructionObserver(WebContentsImpl* web_contents) { 1222 if (!ContainsKey(destruction_observers_, web_contents)) { 1223 destruction_observers_[web_contents] = 1224 new DestructionObserver(this, web_contents); 1225 } 1226} 1227 1228void WebContentsImpl::RemoveDestructionObserver(WebContentsImpl* web_contents) { 1229 DestructionObservers::iterator iter = 1230 destruction_observers_.find(web_contents); 1231 if (iter != destruction_observers_.end()) { 1232 delete destruction_observers_[web_contents]; 1233 destruction_observers_.erase(iter); 1234 } 1235} 1236 1237void WebContentsImpl::AddObserver(WebContentsObserver* observer) { 1238 observers_.AddObserver(observer); 1239} 1240 1241void WebContentsImpl::RemoveObserver(WebContentsObserver* observer) { 1242 observers_.RemoveObserver(observer); 1243} 1244 1245std::set<RenderWidgetHostView*> 1246WebContentsImpl::GetRenderWidgetHostViewsInTree() { 1247 std::set<RenderWidgetHostView*> set; 1248 if (ShowingInterstitialPage()) { 1249 set.insert(GetRenderWidgetHostView()); 1250 } else { 1251 ForEachFrame( 1252 base::Bind(&AddRenderWidgetHostViewToSet, base::Unretained(&set))); 1253 } 1254 return set; 1255} 1256 1257void WebContentsImpl::Activate() { 1258 if (delegate_) 1259 delegate_->ActivateContents(this); 1260} 1261 1262void WebContentsImpl::Deactivate() { 1263 if (delegate_) 1264 delegate_->DeactivateContents(this); 1265} 1266 1267void WebContentsImpl::LostCapture() { 1268 if (delegate_) 1269 delegate_->LostCapture(); 1270} 1271 1272void WebContentsImpl::RenderWidgetDeleted( 1273 RenderWidgetHostImpl* render_widget_host) { 1274 if (is_being_destroyed_) { 1275 // |created_widgets_| might have been destroyed. 1276 return; 1277 } 1278 1279 std::set<RenderWidgetHostImpl*>::iterator iter = 1280 created_widgets_.find(render_widget_host); 1281 if (iter != created_widgets_.end()) 1282 created_widgets_.erase(iter); 1283 1284 if (render_widget_host && 1285 render_widget_host->GetRoutingID() == fullscreen_widget_routing_id_) { 1286 if (delegate_ && delegate_->EmbedsFullscreenWidget()) 1287 delegate_->ToggleFullscreenModeForTab(this, false); 1288 FOR_EACH_OBSERVER(WebContentsObserver, 1289 observers_, 1290 DidDestroyFullscreenWidget( 1291 fullscreen_widget_routing_id_)); 1292 fullscreen_widget_routing_id_ = MSG_ROUTING_NONE; 1293 if (fullscreen_widget_had_focus_at_shutdown_) 1294 view_->RestoreFocus(); 1295 } 1296} 1297 1298bool WebContentsImpl::PreHandleKeyboardEvent( 1299 const NativeWebKeyboardEvent& event, 1300 bool* is_keyboard_shortcut) { 1301 return delegate_ && 1302 delegate_->PreHandleKeyboardEvent(this, event, is_keyboard_shortcut); 1303} 1304 1305void WebContentsImpl::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { 1306 if (delegate_) 1307 delegate_->HandleKeyboardEvent(this, event); 1308} 1309 1310bool WebContentsImpl::HandleWheelEvent( 1311 const blink::WebMouseWheelEvent& event) { 1312#if !defined(OS_MACOSX) 1313 // On platforms other than Mac, control+mousewheel changes zoom. On Mac, this 1314 // isn't done for two reasons: 1315 // -the OS already has a gesture to do this through pinch-zoom 1316 // -if a user starts an inertial scroll, let's go, and presses control 1317 // (i.e. control+tab) then the OS's buffered scroll events will come in 1318 // with control key set which isn't what the user wants 1319 if (delegate_ && 1320 event.wheelTicksY && 1321 (event.modifiers & blink::WebInputEvent::ControlKey) && 1322 // Avoid adjusting the zoom in response to two-finger-scrolling touchpad 1323 // gestures, which are regrettably easy to trigger accidentally. 1324 !event.hasPreciseScrollingDeltas) { 1325 delegate_->ContentsZoomChange(event.wheelTicksY > 0); 1326 return true; 1327 } 1328#endif 1329 return false; 1330} 1331 1332bool WebContentsImpl::PreHandleGestureEvent( 1333 const blink::WebGestureEvent& event) { 1334 return delegate_ && delegate_->PreHandleGestureEvent(this, event); 1335} 1336 1337bool WebContentsImpl::HandleGestureEvent( 1338 const blink::WebGestureEvent& event) { 1339 // Some platforms (eg. Mac) send GesturePinch events for trackpad pinch-zoom. 1340 // Use them to implement browser zoom, as for HandleWheelEvent above. 1341 if (event.type == blink::WebInputEvent::GesturePinchUpdate && 1342 event.sourceDevice == blink::WebGestureDeviceTouchpad) { 1343 // The scale difference necessary to trigger a zoom action. Derived from 1344 // experimentation to find a value that feels reasonable. 1345 const float kZoomStepValue = 0.6f; 1346 1347 // Find the (absolute) thresholds on either side of the current zoom factor, 1348 // then convert those to actual numbers to trigger a zoom in or out. 1349 // This logic deliberately makes the range around the starting zoom value 1350 // for the gesture twice as large as the other ranges (i.e., the notches are 1351 // at ..., -3*step, -2*step, -step, step, 2*step, 3*step, ... but not at 0) 1352 // so that it's easier to get back to your starting point than it is to 1353 // overshoot. 1354 float nextStep = (abs(currentPinchZoomStepDelta_) + 1) * kZoomStepValue; 1355 float backStep = abs(currentPinchZoomStepDelta_) * kZoomStepValue; 1356 float zoomInThreshold = (currentPinchZoomStepDelta_ >= 0) ? nextStep 1357 : -backStep; 1358 float zoomOutThreshold = (currentPinchZoomStepDelta_ <= 0) ? -nextStep 1359 : backStep; 1360 1361 totalPinchGestureAmount_ += (event.data.pinchUpdate.scale - 1.0); 1362 if (totalPinchGestureAmount_ > zoomInThreshold) { 1363 currentPinchZoomStepDelta_++; 1364 if (delegate_) 1365 delegate_->ContentsZoomChange(true); 1366 } else if (totalPinchGestureAmount_ < zoomOutThreshold) { 1367 currentPinchZoomStepDelta_--; 1368 if (delegate_) 1369 delegate_->ContentsZoomChange(false); 1370 } 1371 return true; 1372 } 1373 1374 return false; 1375} 1376 1377void WebContentsImpl::HandleMouseDown() { 1378 if (delegate_) 1379 delegate_->HandleMouseDown(); 1380} 1381 1382void WebContentsImpl::HandleMouseUp() { 1383 if (delegate_) 1384 delegate_->HandleMouseUp(); 1385} 1386 1387void WebContentsImpl::HandlePointerActivate() { 1388 if (delegate_) 1389 delegate_->HandlePointerActivate(); 1390} 1391 1392void WebContentsImpl::HandleGestureBegin() { 1393 if (delegate_) 1394 delegate_->HandleGestureBegin(); 1395} 1396 1397void WebContentsImpl::HandleGestureEnd() { 1398 if (delegate_) 1399 delegate_->HandleGestureEnd(); 1400} 1401 1402void WebContentsImpl::ToggleFullscreenMode(bool enter_fullscreen) { 1403 // This method is being called to enter or leave renderer-initiated fullscreen 1404 // mode. Either way, make sure any existing fullscreen widget is shut down 1405 // first. 1406 RenderWidgetHostView* const widget_view = GetFullscreenRenderWidgetHostView(); 1407 if (widget_view) 1408 RenderWidgetHostImpl::From(widget_view->GetRenderWidgetHost())->Shutdown(); 1409 1410 if (delegate_) 1411 delegate_->ToggleFullscreenModeForTab(this, enter_fullscreen); 1412 1413 FOR_EACH_OBSERVER(WebContentsObserver, 1414 observers_, 1415 DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab())); 1416} 1417 1418bool WebContentsImpl::IsFullscreenForCurrentTab() const { 1419 return delegate_ ? delegate_->IsFullscreenForTabOrPending(this) : false; 1420} 1421 1422void WebContentsImpl::RequestToLockMouse(bool user_gesture, 1423 bool last_unlocked_by_target) { 1424 if (delegate_) { 1425 delegate_->RequestToLockMouse(this, user_gesture, last_unlocked_by_target); 1426 } else { 1427 GotResponseToLockMouseRequest(false); 1428 } 1429} 1430 1431void WebContentsImpl::LostMouseLock() { 1432 if (delegate_) 1433 delegate_->LostMouseLock(); 1434} 1435 1436void WebContentsImpl::CreateNewWindow( 1437 int render_process_id, 1438 int route_id, 1439 int main_frame_route_id, 1440 const ViewHostMsg_CreateWindow_Params& params, 1441 SessionStorageNamespace* session_storage_namespace) { 1442 // We usually create the new window in the same BrowsingInstance (group of 1443 // script-related windows), by passing in the current SiteInstance. However, 1444 // if the opener is being suppressed (in a non-guest), we create a new 1445 // SiteInstance in its own BrowsingInstance. 1446 bool is_guest = BrowserPluginGuest::IsGuest(this); 1447 1448 // If the opener is to be suppressed, the new window can be in any process. 1449 // Since routing ids are process specific, we must not have one passed in 1450 // as argument here. 1451 DCHECK(!params.opener_suppressed || route_id == MSG_ROUTING_NONE); 1452 1453 scoped_refptr<SiteInstance> site_instance = 1454 params.opener_suppressed && !is_guest ? 1455 SiteInstance::CreateForURL(GetBrowserContext(), params.target_url) : 1456 GetSiteInstance(); 1457 1458 // A message to create a new window can only come from the active process for 1459 // this WebContentsImpl instance. If any other process sends the request, 1460 // it is invalid and the process must be terminated. 1461 if (GetRenderProcessHost()->GetID() != render_process_id) { 1462 base::ProcessHandle process_handle = 1463 RenderProcessHost::FromID(render_process_id)->GetHandle(); 1464 if (process_handle != base::kNullProcessHandle) { 1465 RecordAction( 1466 base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWindow")); 1467 base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false); 1468 } 1469 return; 1470 } 1471 1472 // We must assign the SessionStorageNamespace before calling Init(). 1473 // 1474 // http://crbug.com/142685 1475 const std::string& partition_id = 1476 GetContentClient()->browser()-> 1477 GetStoragePartitionIdForSite(GetBrowserContext(), 1478 site_instance->GetSiteURL()); 1479 StoragePartition* partition = BrowserContext::GetStoragePartition( 1480 GetBrowserContext(), site_instance.get()); 1481 DOMStorageContextWrapper* dom_storage_context = 1482 static_cast<DOMStorageContextWrapper*>(partition->GetDOMStorageContext()); 1483 SessionStorageNamespaceImpl* session_storage_namespace_impl = 1484 static_cast<SessionStorageNamespaceImpl*>(session_storage_namespace); 1485 CHECK(session_storage_namespace_impl->IsFromContext(dom_storage_context)); 1486 1487 if (delegate_ && 1488 !delegate_->ShouldCreateWebContents(this, 1489 route_id, 1490 params.window_container_type, 1491 params.frame_name, 1492 params.target_url, 1493 partition_id, 1494 session_storage_namespace)) { 1495 if (route_id != MSG_ROUTING_NONE && 1496 !RenderViewHost::FromID(render_process_id, route_id)) { 1497 // If the embedder didn't create a WebContents for this route, we need to 1498 // delete the RenderView that had already been created. 1499 Send(new ViewMsg_Close(route_id)); 1500 } 1501 GetRenderViewHost()->GetProcess()->ResumeRequestsForView(route_id); 1502 GetRenderViewHost()->GetProcess()->ResumeRequestsForView( 1503 main_frame_route_id); 1504 return; 1505 } 1506 1507 // Create the new web contents. This will automatically create the new 1508 // WebContentsView. In the future, we may want to create the view separately. 1509 CreateParams create_params(GetBrowserContext(), site_instance.get()); 1510 create_params.routing_id = route_id; 1511 create_params.main_frame_routing_id = main_frame_route_id; 1512 create_params.opener = this; 1513 create_params.opener_suppressed = params.opener_suppressed; 1514 if (params.disposition == NEW_BACKGROUND_TAB) 1515 create_params.initially_hidden = true; 1516 1517 WebContentsImpl* new_contents = NULL; 1518 if (!is_guest) { 1519 create_params.context = view_->GetNativeView(); 1520 create_params.initial_size = GetContainerBounds().size(); 1521 new_contents = static_cast<WebContentsImpl*>( 1522 WebContents::Create(create_params)); 1523 } else { 1524 new_contents = GetBrowserPluginGuest()->CreateNewGuestWindow(create_params); 1525 } 1526 new_contents->GetController().SetSessionStorageNamespace( 1527 partition_id, 1528 session_storage_namespace); 1529 new_contents->RenderViewCreated(new_contents->GetRenderViewHost()); 1530 1531 // Save the window for later if we're not suppressing the opener (since it 1532 // will be shown immediately). 1533 if (!params.opener_suppressed) { 1534 if (!is_guest) { 1535 WebContentsView* new_view = new_contents->view_.get(); 1536 1537 // TODO(brettw): It seems bogus that we have to call this function on the 1538 // newly created object and give it one of its own member variables. 1539 new_view->CreateViewForWidget(new_contents->GetRenderViewHost()); 1540 } 1541 // Save the created window associated with the route so we can show it 1542 // later. 1543 DCHECK_NE(MSG_ROUTING_NONE, route_id); 1544 pending_contents_[route_id] = new_contents; 1545 AddDestructionObserver(new_contents); 1546 } 1547 1548 if (delegate_) { 1549 delegate_->WebContentsCreated( 1550 this, params.opener_render_frame_id, params.frame_name, 1551 params.target_url, new_contents); 1552 } 1553 1554 if (params.opener_suppressed) { 1555 // When the opener is suppressed, the original renderer cannot access the 1556 // new window. As a result, we need to show and navigate the window here. 1557 bool was_blocked = false; 1558 if (delegate_) { 1559 gfx::Rect initial_pos; 1560 delegate_->AddNewContents( 1561 this, new_contents, params.disposition, initial_pos, 1562 params.user_gesture, &was_blocked); 1563 } 1564 if (!was_blocked) { 1565 OpenURLParams open_params(params.target_url, 1566 Referrer(), 1567 CURRENT_TAB, 1568 PAGE_TRANSITION_LINK, 1569 true /* is_renderer_initiated */); 1570 open_params.user_gesture = params.user_gesture; 1571 new_contents->OpenURL(open_params); 1572 } 1573 } 1574} 1575 1576void WebContentsImpl::CreateNewWidget(int render_process_id, 1577 int route_id, 1578 blink::WebPopupType popup_type) { 1579 CreateNewWidget(render_process_id, route_id, false, popup_type); 1580} 1581 1582void WebContentsImpl::CreateNewFullscreenWidget(int render_process_id, 1583 int route_id) { 1584 CreateNewWidget(render_process_id, route_id, true, blink::WebPopupTypeNone); 1585} 1586 1587void WebContentsImpl::CreateNewWidget(int render_process_id, 1588 int route_id, 1589 bool is_fullscreen, 1590 blink::WebPopupType popup_type) { 1591 RenderProcessHost* process = GetRenderProcessHost(); 1592 // A message to create a new widget can only come from the active process for 1593 // this WebContentsImpl instance. If any other process sends the request, 1594 // it is invalid and the process must be terminated. 1595 if (process->GetID() != render_process_id) { 1596 base::ProcessHandle process_handle = 1597 RenderProcessHost::FromID(render_process_id)->GetHandle(); 1598 if (process_handle != base::kNullProcessHandle) { 1599 RecordAction( 1600 base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWidget")); 1601 base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false); 1602 } 1603 return; 1604 } 1605 1606 RenderWidgetHostImpl* widget_host = 1607 new RenderWidgetHostImpl(this, process, route_id, IsHidden()); 1608 created_widgets_.insert(widget_host); 1609 1610 RenderWidgetHostViewBase* widget_view = 1611 static_cast<RenderWidgetHostViewBase*>( 1612 view_->CreateViewForPopupWidget(widget_host)); 1613 if (!widget_view) 1614 return; 1615 if (!is_fullscreen) { 1616 // Popups should not get activated. 1617 widget_view->SetPopupType(popup_type); 1618 } 1619 // Save the created widget associated with the route so we can show it later. 1620 pending_widget_views_[route_id] = widget_view; 1621 1622#if defined(OS_MACOSX) 1623 // A RenderWidgetHostViewMac has lifetime scoped to the view. We'll retain it 1624 // to allow it to survive the trip without being hosted. 1625 base::mac::NSObjectRetain(widget_view->GetNativeView()); 1626#endif 1627} 1628 1629void WebContentsImpl::ShowCreatedWindow(int route_id, 1630 WindowOpenDisposition disposition, 1631 const gfx::Rect& initial_pos, 1632 bool user_gesture) { 1633 WebContentsImpl* contents = GetCreatedWindow(route_id); 1634 if (contents) { 1635 WebContentsDelegate* delegate = GetDelegate(); 1636 if (delegate) { 1637 delegate->AddNewContents( 1638 this, contents, disposition, initial_pos, user_gesture, NULL); 1639 } 1640 } 1641} 1642 1643void WebContentsImpl::ShowCreatedWidget(int route_id, 1644 const gfx::Rect& initial_pos) { 1645 ShowCreatedWidget(route_id, false, initial_pos); 1646} 1647 1648void WebContentsImpl::ShowCreatedFullscreenWidget(int route_id) { 1649 ShowCreatedWidget(route_id, true, gfx::Rect()); 1650} 1651 1652void WebContentsImpl::ShowCreatedWidget(int route_id, 1653 bool is_fullscreen, 1654 const gfx::Rect& initial_pos) { 1655 RenderWidgetHostViewBase* widget_host_view = 1656 static_cast<RenderWidgetHostViewBase*>(GetCreatedWidget(route_id)); 1657 if (!widget_host_view) 1658 return; 1659 1660 RenderWidgetHostView* view = NULL; 1661 BrowserPluginGuest* guest = GetBrowserPluginGuest(); 1662 if (guest && guest->embedder_web_contents()) { 1663 view = guest->embedder_web_contents()->GetRenderWidgetHostView(); 1664 } else { 1665 view = GetRenderWidgetHostView(); 1666 } 1667 1668 if (is_fullscreen) { 1669 DCHECK_EQ(MSG_ROUTING_NONE, fullscreen_widget_routing_id_); 1670 view_->StoreFocus(); 1671 fullscreen_widget_routing_id_ = route_id; 1672 if (delegate_ && delegate_->EmbedsFullscreenWidget()) { 1673 widget_host_view->InitAsChild(GetRenderWidgetHostView()->GetNativeView()); 1674 delegate_->ToggleFullscreenModeForTab(this, true); 1675 } else { 1676 widget_host_view->InitAsFullscreen(view); 1677 } 1678 FOR_EACH_OBSERVER(WebContentsObserver, 1679 observers_, 1680 DidShowFullscreenWidget(route_id)); 1681 if (!widget_host_view->HasFocus()) 1682 widget_host_view->Focus(); 1683 } else { 1684 widget_host_view->InitAsPopup(view, initial_pos); 1685 } 1686 1687 RenderWidgetHostImpl* render_widget_host_impl = 1688 RenderWidgetHostImpl::From(widget_host_view->GetRenderWidgetHost()); 1689 render_widget_host_impl->Init(); 1690 // Only allow privileged mouse lock for fullscreen render widget, which is 1691 // used to implement Pepper Flash fullscreen. 1692 render_widget_host_impl->set_allow_privileged_mouse_lock(is_fullscreen); 1693 1694#if defined(OS_MACOSX) 1695 // A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's 1696 // properly embedded (or purposefully ignored) we can release the retain we 1697 // took in CreateNewWidget(). 1698 base::mac::NSObjectRelease(widget_host_view->GetNativeView()); 1699#endif 1700} 1701 1702WebContentsImpl* WebContentsImpl::GetCreatedWindow(int route_id) { 1703 PendingContents::iterator iter = pending_contents_.find(route_id); 1704 1705 // Certain systems can block the creation of new windows. If we didn't succeed 1706 // in creating one, just return NULL. 1707 if (iter == pending_contents_.end()) { 1708 return NULL; 1709 } 1710 1711 WebContentsImpl* new_contents = iter->second; 1712 pending_contents_.erase(route_id); 1713 RemoveDestructionObserver(new_contents); 1714 1715 // Don't initialize the guest WebContents immediately. 1716 if (BrowserPluginGuest::IsGuest(new_contents)) 1717 return new_contents; 1718 1719 if (!new_contents->GetRenderProcessHost()->HasConnection() || 1720 !new_contents->GetRenderViewHost()->GetView()) 1721 return NULL; 1722 1723 // TODO(brettw): It seems bogus to reach into here and initialize the host. 1724 static_cast<RenderViewHostImpl*>(new_contents->GetRenderViewHost())->Init(); 1725 return new_contents; 1726} 1727 1728RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int route_id) { 1729 PendingWidgetViews::iterator iter = pending_widget_views_.find(route_id); 1730 if (iter == pending_widget_views_.end()) { 1731 DCHECK(false); 1732 return NULL; 1733 } 1734 1735 RenderWidgetHostView* widget_host_view = iter->second; 1736 pending_widget_views_.erase(route_id); 1737 1738 RenderWidgetHost* widget_host = widget_host_view->GetRenderWidgetHost(); 1739 if (!widget_host->GetProcess()->HasConnection()) { 1740 // The view has gone away or the renderer crashed. Nothing to do. 1741 return NULL; 1742 } 1743 1744 return widget_host_view; 1745} 1746 1747void WebContentsImpl::RequestMediaAccessPermission( 1748 const MediaStreamRequest& request, 1749 const MediaResponseCallback& callback) { 1750 if (delegate_) { 1751 delegate_->RequestMediaAccessPermission(this, request, callback); 1752 } else { 1753 callback.Run(MediaStreamDevices(), 1754 MEDIA_DEVICE_INVALID_STATE, 1755 scoped_ptr<MediaStreamUI>()); 1756 } 1757} 1758 1759SessionStorageNamespace* WebContentsImpl::GetSessionStorageNamespace( 1760 SiteInstance* instance) { 1761 return controller_.GetSessionStorageNamespace(instance); 1762} 1763 1764SessionStorageNamespaceMap WebContentsImpl::GetSessionStorageNamespaceMap() { 1765 return controller_.GetSessionStorageNamespaceMap(); 1766} 1767 1768FrameTree* WebContentsImpl::GetFrameTree() { 1769 return &frame_tree_; 1770} 1771 1772AccessibilityMode WebContentsImpl::GetAccessibilityMode() const { 1773 return accessibility_mode_; 1774} 1775 1776void WebContentsImpl::AccessibilityEventReceived( 1777 const std::vector<AXEventNotificationDetails>& details) { 1778 FOR_EACH_OBSERVER( 1779 WebContentsObserver, observers_, AccessibilityEventReceived(details)); 1780} 1781 1782void WebContentsImpl::OnShowValidationMessage( 1783 const gfx::Rect& anchor_in_root_view, 1784 const base::string16& main_text, 1785 const base::string16& sub_text) { 1786 if (delegate_) 1787 delegate_->ShowValidationMessage( 1788 this, anchor_in_root_view, main_text, sub_text); 1789} 1790 1791void WebContentsImpl::OnHideValidationMessage() { 1792 if (delegate_) 1793 delegate_->HideValidationMessage(this); 1794} 1795 1796void WebContentsImpl::OnMoveValidationMessage( 1797 const gfx::Rect& anchor_in_root_view) { 1798 if (delegate_) 1799 delegate_->MoveValidationMessage(this, anchor_in_root_view); 1800} 1801 1802void WebContentsImpl::DidSendScreenRects(RenderWidgetHostImpl* rwh) { 1803 if (browser_plugin_embedder_) 1804 browser_plugin_embedder_->DidSendScreenRects(); 1805} 1806 1807void WebContentsImpl::OnTouchEmulationEnabled(bool enabled) { 1808 touch_emulation_enabled_ = enabled; 1809 if (view_) 1810 view_->SetOverscrollControllerEnabled(CanOverscrollContent()); 1811} 1812 1813BrowserAccessibilityManager* 1814 WebContentsImpl::GetRootBrowserAccessibilityManager() { 1815 RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame()); 1816 return rfh ? rfh->browser_accessibility_manager() : NULL; 1817} 1818 1819BrowserAccessibilityManager* 1820 WebContentsImpl::GetOrCreateRootBrowserAccessibilityManager() { 1821 RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame()); 1822 return rfh ? rfh->GetOrCreateBrowserAccessibilityManager() : NULL; 1823} 1824 1825void WebContentsImpl::UpdatePreferredSize(const gfx::Size& pref_size) { 1826 const gfx::Size old_size = GetPreferredSize(); 1827 preferred_size_ = pref_size; 1828 OnPreferredSizeChanged(old_size); 1829} 1830 1831void WebContentsImpl::ResizeDueToAutoResize(const gfx::Size& new_size) { 1832 if (delegate_) 1833 delegate_->ResizeDueToAutoResize(this, new_size); 1834} 1835 1836WebContents* WebContentsImpl::OpenURL(const OpenURLParams& params) { 1837 if (!delegate_) 1838 return NULL; 1839 1840 WebContents* new_contents = delegate_->OpenURLFromTab(this, params); 1841 return new_contents; 1842} 1843 1844bool WebContentsImpl::Send(IPC::Message* message) { 1845 if (!GetRenderViewHost()) { 1846 delete message; 1847 return false; 1848 } 1849 1850 return GetRenderViewHost()->Send(message); 1851} 1852 1853bool WebContentsImpl::NavigateToPendingEntry( 1854 NavigationController::ReloadType reload_type) { 1855 FrameTreeNode* node = frame_tree_.root(); 1856 1857 // If we are using --site-per-process, we should navigate in the FrameTreeNode 1858 // specified in the pending entry. 1859 NavigationEntryImpl* pending_entry = 1860 NavigationEntryImpl::FromNavigationEntry(controller_.GetPendingEntry()); 1861 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) && 1862 pending_entry->frame_tree_node_id() != -1) { 1863 node = frame_tree_.FindByID(pending_entry->frame_tree_node_id()); 1864 } 1865 1866 return node->navigator()->NavigateToPendingEntry( 1867 node->current_frame_host(), reload_type); 1868} 1869 1870void WebContentsImpl::RenderFrameForInterstitialPageCreated( 1871 RenderFrameHost* render_frame_host) { 1872 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 1873 RenderFrameForInterstitialPageCreated(render_frame_host)); 1874} 1875 1876void WebContentsImpl::AttachInterstitialPage( 1877 InterstitialPageImpl* interstitial_page) { 1878 DCHECK(interstitial_page); 1879 GetRenderManager()->set_interstitial_page(interstitial_page); 1880 1881 // Cancel any visible dialogs so that they don't interfere with the 1882 // interstitial. 1883 if (dialog_manager_) 1884 dialog_manager_->CancelActiveAndPendingDialogs(this); 1885 1886 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 1887 DidAttachInterstitialPage()); 1888} 1889 1890void WebContentsImpl::DetachInterstitialPage() { 1891 if (ShowingInterstitialPage()) 1892 GetRenderManager()->remove_interstitial_page(); 1893 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 1894 DidDetachInterstitialPage()); 1895} 1896 1897void WebContentsImpl::SetHistoryLengthAndPrune( 1898 const SiteInstance* site_instance, 1899 int history_length, 1900 int32 minimum_page_id) { 1901 // SetHistoryLengthAndPrune doesn't work when there are pending cross-site 1902 // navigations. Callers should ensure that this is the case. 1903 if (GetRenderManager()->pending_render_view_host()) { 1904 NOTREACHED(); 1905 return; 1906 } 1907 RenderViewHostImpl* rvh = GetRenderViewHostImpl(); 1908 if (!rvh) { 1909 NOTREACHED(); 1910 return; 1911 } 1912 if (site_instance && rvh->GetSiteInstance() != site_instance) { 1913 NOTREACHED(); 1914 return; 1915 } 1916 Send(new ViewMsg_SetHistoryLengthAndPrune(GetRoutingID(), 1917 history_length, 1918 minimum_page_id)); 1919} 1920 1921void WebContentsImpl::ReloadFocusedFrame(bool ignore_cache) { 1922 RenderFrameHost* focused_frame = GetFocusedFrame(); 1923 if (!focused_frame) 1924 return; 1925 1926 focused_frame->Send(new FrameMsg_Reload( 1927 focused_frame->GetRoutingID(), ignore_cache)); 1928} 1929 1930void WebContentsImpl::Undo() { 1931 RenderFrameHost* focused_frame = GetFocusedFrame(); 1932 if (!focused_frame) 1933 return; 1934 1935 focused_frame->Send(new InputMsg_Undo(focused_frame->GetRoutingID())); 1936 RecordAction(base::UserMetricsAction("Undo")); 1937} 1938 1939void WebContentsImpl::Redo() { 1940 RenderFrameHost* focused_frame = GetFocusedFrame(); 1941 if (!focused_frame) 1942 return; 1943 focused_frame->Send(new InputMsg_Redo(focused_frame->GetRoutingID())); 1944 RecordAction(base::UserMetricsAction("Redo")); 1945} 1946 1947void WebContentsImpl::Cut() { 1948 RenderFrameHost* focused_frame = GetFocusedFrame(); 1949 if (!focused_frame) 1950 return; 1951 1952 focused_frame->Send(new InputMsg_Cut(focused_frame->GetRoutingID())); 1953 RecordAction(base::UserMetricsAction("Cut")); 1954} 1955 1956void WebContentsImpl::Copy() { 1957 RenderFrameHost* focused_frame = GetFocusedFrame(); 1958 if (!focused_frame) 1959 return; 1960 1961 focused_frame->Send(new InputMsg_Copy(focused_frame->GetRoutingID())); 1962 RecordAction(base::UserMetricsAction("Copy")); 1963} 1964 1965void WebContentsImpl::CopyToFindPboard() { 1966#if defined(OS_MACOSX) 1967 RenderFrameHost* focused_frame = GetFocusedFrame(); 1968 if (!focused_frame) 1969 return; 1970 1971 // Windows/Linux don't have the concept of a find pasteboard. 1972 focused_frame->Send( 1973 new InputMsg_CopyToFindPboard(focused_frame->GetRoutingID())); 1974 RecordAction(base::UserMetricsAction("CopyToFindPboard")); 1975#endif 1976} 1977 1978void WebContentsImpl::Paste() { 1979 RenderFrameHost* focused_frame = GetFocusedFrame(); 1980 if (!focused_frame) 1981 return; 1982 1983 focused_frame->Send(new InputMsg_Paste(focused_frame->GetRoutingID())); 1984 RecordAction(base::UserMetricsAction("Paste")); 1985} 1986 1987void WebContentsImpl::PasteAndMatchStyle() { 1988 RenderFrameHost* focused_frame = GetFocusedFrame(); 1989 if (!focused_frame) 1990 return; 1991 1992 focused_frame->Send(new InputMsg_PasteAndMatchStyle( 1993 focused_frame->GetRoutingID())); 1994 RecordAction(base::UserMetricsAction("PasteAndMatchStyle")); 1995} 1996 1997void WebContentsImpl::Delete() { 1998 RenderFrameHost* focused_frame = GetFocusedFrame(); 1999 if (!focused_frame) 2000 return; 2001 2002 focused_frame->Send(new InputMsg_Delete(focused_frame->GetRoutingID())); 2003 RecordAction(base::UserMetricsAction("DeleteSelection")); 2004} 2005 2006void WebContentsImpl::SelectAll() { 2007 RenderFrameHost* focused_frame = GetFocusedFrame(); 2008 if (!focused_frame) 2009 return; 2010 2011 focused_frame->Send(new InputMsg_SelectAll(focused_frame->GetRoutingID())); 2012 RecordAction(base::UserMetricsAction("SelectAll")); 2013} 2014 2015void WebContentsImpl::Unselect() { 2016 RenderFrameHost* focused_frame = GetFocusedFrame(); 2017 if (!focused_frame) 2018 return; 2019 2020 focused_frame->Send(new InputMsg_Unselect(focused_frame->GetRoutingID())); 2021 RecordAction(base::UserMetricsAction("Unselect")); 2022} 2023 2024void WebContentsImpl::Replace(const base::string16& word) { 2025 RenderFrameHost* focused_frame = GetFocusedFrame(); 2026 if (!focused_frame) 2027 return; 2028 2029 focused_frame->Send(new InputMsg_Replace( 2030 focused_frame->GetRoutingID(), word)); 2031} 2032 2033void WebContentsImpl::ReplaceMisspelling(const base::string16& word) { 2034 RenderFrameHost* focused_frame = GetFocusedFrame(); 2035 if (!focused_frame) 2036 return; 2037 2038 focused_frame->Send(new InputMsg_ReplaceMisspelling( 2039 focused_frame->GetRoutingID(), word)); 2040} 2041 2042void WebContentsImpl::NotifyContextMenuClosed( 2043 const CustomContextMenuContext& context) { 2044 RenderFrameHost* focused_frame = GetFocusedFrame(); 2045 if (!focused_frame) 2046 return; 2047 2048 focused_frame->Send(new FrameMsg_ContextMenuClosed( 2049 focused_frame->GetRoutingID(), context)); 2050} 2051 2052void WebContentsImpl::ExecuteCustomContextMenuCommand( 2053 int action, const CustomContextMenuContext& context) { 2054 RenderFrameHost* focused_frame = GetFocusedFrame(); 2055 if (!focused_frame) 2056 return; 2057 2058 focused_frame->Send(new FrameMsg_CustomContextMenuAction( 2059 focused_frame->GetRoutingID(), context, action)); 2060} 2061 2062gfx::NativeView WebContentsImpl::GetNativeView() { 2063 return view_->GetNativeView(); 2064} 2065 2066gfx::NativeView WebContentsImpl::GetContentNativeView() { 2067 return view_->GetContentNativeView(); 2068} 2069 2070gfx::NativeWindow WebContentsImpl::GetTopLevelNativeWindow() { 2071 return view_->GetTopLevelNativeWindow(); 2072} 2073 2074gfx::Rect WebContentsImpl::GetViewBounds() { 2075 return view_->GetViewBounds(); 2076} 2077 2078gfx::Rect WebContentsImpl::GetContainerBounds() { 2079 gfx::Rect rv; 2080 view_->GetContainerBounds(&rv); 2081 return rv; 2082} 2083 2084DropData* WebContentsImpl::GetDropData() { 2085 return view_->GetDropData(); 2086} 2087 2088void WebContentsImpl::Focus() { 2089 RenderWidgetHostView* const fullscreen_view = 2090 GetFullscreenRenderWidgetHostView(); 2091 if (fullscreen_view) 2092 fullscreen_view->Focus(); 2093 else 2094 view_->Focus(); 2095} 2096 2097void WebContentsImpl::SetInitialFocus() { 2098 RenderWidgetHostView* const fullscreen_view = 2099 GetFullscreenRenderWidgetHostView(); 2100 if (fullscreen_view) 2101 fullscreen_view->Focus(); 2102 else 2103 view_->SetInitialFocus(); 2104} 2105 2106void WebContentsImpl::StoreFocus() { 2107 if (!GetFullscreenRenderWidgetHostView()) 2108 view_->StoreFocus(); 2109} 2110 2111void WebContentsImpl::RestoreFocus() { 2112 RenderWidgetHostView* const fullscreen_view = 2113 GetFullscreenRenderWidgetHostView(); 2114 if (fullscreen_view) 2115 fullscreen_view->Focus(); 2116 else 2117 view_->RestoreFocus(); 2118} 2119 2120void WebContentsImpl::FocusThroughTabTraversal(bool reverse) { 2121 if (ShowingInterstitialPage()) { 2122 GetRenderManager()->interstitial_page()->FocusThroughTabTraversal(reverse); 2123 return; 2124 } 2125 RenderWidgetHostView* const fullscreen_view = 2126 GetFullscreenRenderWidgetHostView(); 2127 if (fullscreen_view) { 2128 fullscreen_view->Focus(); 2129 return; 2130 } 2131 GetRenderViewHostImpl()->SetInitialFocus(reverse); 2132} 2133 2134bool WebContentsImpl::ShowingInterstitialPage() const { 2135 return GetRenderManager()->interstitial_page() != NULL; 2136} 2137 2138InterstitialPage* WebContentsImpl::GetInterstitialPage() const { 2139 return GetRenderManager()->interstitial_page(); 2140} 2141 2142bool WebContentsImpl::IsSavable() { 2143 // WebKit creates Document object when MIME type is application/xhtml+xml, 2144 // so we also support this MIME type. 2145 return contents_mime_type_ == "text/html" || 2146 contents_mime_type_ == "text/xml" || 2147 contents_mime_type_ == "application/xhtml+xml" || 2148 contents_mime_type_ == "text/plain" || 2149 contents_mime_type_ == "text/css" || 2150 net::IsSupportedJavascriptMimeType(contents_mime_type_.c_str()); 2151} 2152 2153void WebContentsImpl::OnSavePage() { 2154 // If we can not save the page, try to download it. 2155 if (!IsSavable()) { 2156 RecordDownloadSource(INITIATED_BY_SAVE_PACKAGE_ON_NON_HTML); 2157 SaveFrame(GetURL(), Referrer()); 2158 return; 2159 } 2160 2161 Stop(); 2162 2163 // Create the save package and possibly prompt the user for the name to save 2164 // the page as. The user prompt is an asynchronous operation that runs on 2165 // another thread. 2166 save_package_ = new SavePackage(this); 2167 save_package_->GetSaveInfo(); 2168} 2169 2170// Used in automated testing to bypass prompting the user for file names. 2171// Instead, the names and paths are hard coded rather than running them through 2172// file name sanitation and extension / mime checking. 2173bool WebContentsImpl::SavePage(const base::FilePath& main_file, 2174 const base::FilePath& dir_path, 2175 SavePageType save_type) { 2176 // Stop the page from navigating. 2177 Stop(); 2178 2179 save_package_ = new SavePackage(this, save_type, main_file, dir_path); 2180 return save_package_->Init(SavePackageDownloadCreatedCallback()); 2181} 2182 2183void WebContentsImpl::SaveFrame(const GURL& url, 2184 const Referrer& referrer) { 2185 if (!GetURL().is_valid()) 2186 return; 2187 bool is_main_frame = (url == GetURL()); 2188 2189 DownloadManager* dlm = 2190 BrowserContext::GetDownloadManager(GetBrowserContext()); 2191 if (!dlm) 2192 return; 2193 int64 post_id = -1; 2194 if (is_main_frame) { 2195 const NavigationEntry* entry = controller_.GetLastCommittedEntry(); 2196 if (entry) 2197 post_id = entry->GetPostID(); 2198 } 2199 scoped_ptr<DownloadUrlParameters> params( 2200 DownloadUrlParameters::FromWebContents(this, url)); 2201 params->set_referrer(referrer); 2202 params->set_post_id(post_id); 2203 params->set_prefer_cache(true); 2204 if (post_id >= 0) 2205 params->set_method("POST"); 2206 params->set_prompt(true); 2207 dlm->DownloadUrl(params.Pass()); 2208} 2209 2210void WebContentsImpl::GenerateMHTML( 2211 const base::FilePath& file, 2212 const base::Callback<void(int64)>& callback) { 2213 MHTMLGenerationManager::GetInstance()->SaveMHTML(this, file, callback); 2214} 2215 2216const std::string& WebContentsImpl::GetContentsMimeType() const { 2217 return contents_mime_type_; 2218} 2219 2220bool WebContentsImpl::WillNotifyDisconnection() const { 2221 return notify_disconnection_; 2222} 2223 2224void WebContentsImpl::SetOverrideEncoding(const std::string& encoding) { 2225 SetEncoding(encoding); 2226 Send(new ViewMsg_SetPageEncoding(GetRoutingID(), encoding)); 2227} 2228 2229void WebContentsImpl::ResetOverrideEncoding() { 2230 canonical_encoding_.clear(); 2231 Send(new ViewMsg_ResetPageEncodingToDefault(GetRoutingID())); 2232} 2233 2234RendererPreferences* WebContentsImpl::GetMutableRendererPrefs() { 2235 return &renderer_preferences_; 2236} 2237 2238void WebContentsImpl::Close() { 2239 Close(GetRenderViewHost()); 2240} 2241 2242void WebContentsImpl::DragSourceEndedAt(int client_x, int client_y, 2243 int screen_x, int screen_y, blink::WebDragOperation operation) { 2244 if (browser_plugin_embedder_.get()) 2245 browser_plugin_embedder_->DragSourceEndedAt(client_x, client_y, 2246 screen_x, screen_y, operation); 2247 if (GetRenderViewHost()) 2248 GetRenderViewHostImpl()->DragSourceEndedAt(client_x, client_y, 2249 screen_x, screen_y, operation); 2250} 2251 2252void WebContentsImpl::DidGetResourceResponseStart( 2253 const ResourceRequestDetails& details) { 2254 controller_.ssl_manager()->DidStartResourceResponse(details); 2255 2256 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2257 DidGetResourceResponseStart(details)); 2258 2259 // TODO(avi): Remove. http://crbug.com/170921 2260 NotificationService::current()->Notify( 2261 NOTIFICATION_RESOURCE_RESPONSE_STARTED, 2262 Source<WebContents>(this), 2263 Details<const ResourceRequestDetails>(&details)); 2264} 2265 2266void WebContentsImpl::DidGetRedirectForResourceRequest( 2267 RenderViewHost* render_view_host, 2268 const ResourceRedirectDetails& details) { 2269 controller_.ssl_manager()->DidReceiveResourceRedirect(details); 2270 2271 FOR_EACH_OBSERVER( 2272 WebContentsObserver, 2273 observers_, 2274 DidGetRedirectForResourceRequest(render_view_host, details)); 2275 2276 // TODO(avi): Remove. http://crbug.com/170921 2277 NotificationService::current()->Notify( 2278 NOTIFICATION_RESOURCE_RECEIVED_REDIRECT, 2279 Source<WebContents>(this), 2280 Details<const ResourceRedirectDetails>(&details)); 2281} 2282 2283void WebContentsImpl::SystemDragEnded() { 2284 if (GetRenderViewHost()) 2285 GetRenderViewHostImpl()->DragSourceSystemDragEnded(); 2286 if (delegate_) 2287 delegate_->DragEnded(); 2288 if (browser_plugin_embedder_.get()) 2289 browser_plugin_embedder_->SystemDragEnded(); 2290} 2291 2292void WebContentsImpl::UserGestureDone() { 2293 OnUserGesture(); 2294} 2295 2296void WebContentsImpl::SetClosedByUserGesture(bool value) { 2297 closed_by_user_gesture_ = value; 2298} 2299 2300bool WebContentsImpl::GetClosedByUserGesture() const { 2301 return closed_by_user_gesture_; 2302} 2303 2304void WebContentsImpl::ViewSource() { 2305 if (!delegate_) 2306 return; 2307 2308 NavigationEntry* entry = GetController().GetLastCommittedEntry(); 2309 if (!entry) 2310 return; 2311 2312 delegate_->ViewSourceForTab(this, entry->GetURL()); 2313} 2314 2315void WebContentsImpl::ViewFrameSource(const GURL& url, 2316 const PageState& page_state) { 2317 if (!delegate_) 2318 return; 2319 2320 delegate_->ViewSourceForFrame(this, url, page_state); 2321} 2322 2323int WebContentsImpl::GetMinimumZoomPercent() const { 2324 return minimum_zoom_percent_; 2325} 2326 2327int WebContentsImpl::GetMaximumZoomPercent() const { 2328 return maximum_zoom_percent_; 2329} 2330 2331gfx::Size WebContentsImpl::GetPreferredSize() const { 2332 return capturer_count_ == 0 ? preferred_size_ : preferred_size_for_capture_; 2333} 2334 2335bool WebContentsImpl::GotResponseToLockMouseRequest(bool allowed) { 2336 if (GetBrowserPluginGuest()) 2337 return GetBrowserPluginGuest()->LockMouse(allowed); 2338 2339 return GetRenderViewHost() ? 2340 GetRenderViewHostImpl()->GotResponseToLockMouseRequest(allowed) : false; 2341} 2342 2343bool WebContentsImpl::HasOpener() const { 2344 return opener_ != NULL; 2345} 2346 2347void WebContentsImpl::DidChooseColorInColorChooser(SkColor color) { 2348 if (!color_chooser_info_.get()) 2349 return; 2350 RenderFrameHost* rfh = RenderFrameHost::FromID( 2351 color_chooser_info_->render_process_id, 2352 color_chooser_info_->render_frame_id); 2353 if (!rfh) 2354 return; 2355 2356 rfh->Send(new FrameMsg_DidChooseColorResponse( 2357 rfh->GetRoutingID(), color_chooser_info_->identifier, color)); 2358} 2359 2360void WebContentsImpl::DidEndColorChooser() { 2361 if (!color_chooser_info_.get()) 2362 return; 2363 RenderFrameHost* rfh = RenderFrameHost::FromID( 2364 color_chooser_info_->render_process_id, 2365 color_chooser_info_->render_frame_id); 2366 if (!rfh) 2367 return; 2368 2369 rfh->Send(new FrameMsg_DidEndColorChooser( 2370 rfh->GetRoutingID(), color_chooser_info_->identifier)); 2371 color_chooser_info_.reset(); 2372} 2373 2374int WebContentsImpl::DownloadImage(const GURL& url, 2375 bool is_favicon, 2376 uint32_t max_bitmap_size, 2377 const ImageDownloadCallback& callback) { 2378 int id = StartDownload(GetMainFrame(), url, is_favicon, max_bitmap_size); 2379 image_download_map_[id] = callback; 2380 return id; 2381} 2382 2383bool WebContentsImpl::IsSubframe() const { 2384 return is_subframe_; 2385} 2386 2387void WebContentsImpl::Find(int request_id, 2388 const base::string16& search_text, 2389 const blink::WebFindOptions& options) { 2390 Send(new ViewMsg_Find(GetRoutingID(), request_id, search_text, options)); 2391} 2392 2393void WebContentsImpl::StopFinding(StopFindAction action) { 2394 Send(new ViewMsg_StopFinding(GetRoutingID(), action)); 2395} 2396 2397void WebContentsImpl::InsertCSS(const std::string& css) { 2398 GetMainFrame()->Send(new FrameMsg_CSSInsertRequest( 2399 GetMainFrame()->GetRoutingID(), css)); 2400} 2401 2402bool WebContentsImpl::FocusLocationBarByDefault() { 2403 NavigationEntry* entry = controller_.GetVisibleEntry(); 2404 if (entry && entry->GetURL() == GURL(url::kAboutBlankURL)) 2405 return true; 2406 return delegate_ && delegate_->ShouldFocusLocationBarByDefault(this); 2407} 2408 2409void WebContentsImpl::SetFocusToLocationBar(bool select_all) { 2410 if (delegate_) 2411 delegate_->SetFocusToLocationBar(select_all); 2412} 2413 2414void WebContentsImpl::DidStartProvisionalLoad( 2415 RenderFrameHostImpl* render_frame_host, 2416 const GURL& validated_url, 2417 bool is_error_page, 2418 bool is_iframe_srcdoc) { 2419 // Notify observers about the start of the provisional load. 2420 FOR_EACH_OBSERVER( 2421 WebContentsObserver, 2422 observers_, 2423 DidStartProvisionalLoadForFrame( 2424 render_frame_host, validated_url, is_error_page, is_iframe_srcdoc)); 2425 2426 if (!render_frame_host->GetParent()) { 2427 FOR_EACH_OBSERVER( 2428 WebContentsObserver, 2429 observers_, 2430 ProvisionalChangeToMainFrameUrl(validated_url, 2431 render_frame_host)); 2432 } 2433} 2434 2435void WebContentsImpl::DidFailProvisionalLoadWithError( 2436 RenderFrameHostImpl* render_frame_host, 2437 const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) { 2438 GURL validated_url(params.url); 2439 FOR_EACH_OBSERVER(WebContentsObserver, 2440 observers_, 2441 DidFailProvisionalLoad(render_frame_host, 2442 validated_url, 2443 params.error_code, 2444 params.error_description)); 2445} 2446 2447void WebContentsImpl::DidFailLoadWithError( 2448 RenderFrameHostImpl* render_frame_host, 2449 const GURL& url, 2450 int error_code, 2451 const base::string16& error_description) { 2452 FOR_EACH_OBSERVER( 2453 WebContentsObserver, 2454 observers_, 2455 DidFailLoad(render_frame_host, url, error_code, error_description)); 2456} 2457 2458void WebContentsImpl::NotifyChangedNavigationState( 2459 InvalidateTypes changed_flags) { 2460 NotifyNavigationStateChanged(changed_flags); 2461} 2462 2463void WebContentsImpl::AboutToNavigateRenderFrame( 2464 RenderFrameHostImpl* render_frame_host) { 2465 // Notify observers that we will navigate in this RenderView. 2466 RenderViewHost* render_view_host = render_frame_host->render_view_host(); 2467 FOR_EACH_OBSERVER( 2468 WebContentsObserver, 2469 observers_, 2470 AboutToNavigateRenderView(render_view_host)); 2471} 2472 2473void WebContentsImpl::DidStartNavigationToPendingEntry( 2474 RenderFrameHostImpl* render_frame_host, 2475 const GURL& url, 2476 NavigationController::ReloadType reload_type) { 2477 // Notify observers about navigation. 2478 FOR_EACH_OBSERVER( 2479 WebContentsObserver, 2480 observers_, 2481 DidStartNavigationToPendingEntry(url, reload_type)); 2482} 2483 2484void WebContentsImpl::RequestOpenURL(RenderFrameHostImpl* render_frame_host, 2485 const OpenURLParams& params) { 2486 int source_render_frame_id = render_frame_host->GetRoutingID(); 2487 WebContents* new_contents = OpenURL(params); 2488 2489 if (new_contents) { 2490 // Notify observers. 2491 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2492 DidOpenRequestedURL(new_contents, 2493 params.url, 2494 params.referrer, 2495 params.disposition, 2496 params.transition, 2497 source_render_frame_id)); 2498 } 2499} 2500 2501bool WebContentsImpl::ShouldPreserveAbortedURLs() { 2502 if (!delegate_) 2503 return false; 2504 return delegate_->ShouldPreserveAbortedURLs(this); 2505} 2506 2507void WebContentsImpl::DidRedirectProvisionalLoad( 2508 RenderFrameHostImpl* render_frame_host, 2509 const GURL& validated_target_url) { 2510 // Notify observers about the provisional change in the main frame URL. 2511 FOR_EACH_OBSERVER( 2512 WebContentsObserver, 2513 observers_, 2514 ProvisionalChangeToMainFrameUrl(validated_target_url, 2515 render_frame_host)); 2516} 2517 2518void WebContentsImpl::DidCommitProvisionalLoad( 2519 RenderFrameHostImpl* render_frame_host, 2520 const GURL& url, 2521 PageTransition transition_type) { 2522 // Notify observers about the commit of the provisional load. 2523 FOR_EACH_OBSERVER(WebContentsObserver, 2524 observers_, 2525 DidCommitProvisionalLoadForFrame( 2526 render_frame_host, url, transition_type)); 2527} 2528 2529void WebContentsImpl::DidNavigateMainFramePreCommit( 2530 bool navigation_is_within_page) { 2531 // Ensure fullscreen mode is exited before committing the navigation to a 2532 // different page. The next page will not start out assuming it is in 2533 // fullscreen mode. 2534 if (navigation_is_within_page) { 2535 // No page change? Then, the renderer and browser can remain in fullscreen. 2536 return; 2537 } 2538 if (IsFullscreenForCurrentTab()) 2539 GetRenderViewHost()->ExitFullscreen(); 2540 DCHECK(!IsFullscreenForCurrentTab()); 2541} 2542 2543void WebContentsImpl::DidNavigateMainFramePostCommit( 2544 const LoadCommittedDetails& details, 2545 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { 2546 if (details.is_navigation_to_different_page()) { 2547 // Clear the status bubble. This is a workaround for a bug where WebKit 2548 // doesn't let us know that the cursor left an element during a 2549 // transition (this is also why the mouse cursor remains as a hand after 2550 // clicking on a link); see bugs 1184641 and 980803. We don't want to 2551 // clear the bubble when a user navigates to a named anchor in the same 2552 // page. 2553 UpdateTargetURL(details.entry->GetPageID(), GURL()); 2554 } 2555 2556 if (!details.is_in_page) { 2557 // Once the main frame is navigated, we're no longer considered to have 2558 // displayed insecure content. 2559 displayed_insecure_content_ = false; 2560 SSLManager::NotifySSLInternalStateChanged( 2561 GetController().GetBrowserContext()); 2562 } 2563 2564 // Notify observers about navigation. 2565 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2566 DidNavigateMainFrame(details, params)); 2567 2568 if (delegate_) 2569 delegate_->DidNavigateMainFramePostCommit(this); 2570 view_->SetOverscrollControllerEnabled(CanOverscrollContent()); 2571} 2572 2573void WebContentsImpl::DidNavigateAnyFramePostCommit( 2574 RenderFrameHostImpl* render_frame_host, 2575 const LoadCommittedDetails& details, 2576 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { 2577 // Now that something has committed, we don't need to track whether the 2578 // initial page has been accessed. 2579 has_accessed_initial_document_ = false; 2580 2581 // If we navigate off the page, close all JavaScript dialogs. 2582 if (dialog_manager_ && !details.is_in_page) 2583 dialog_manager_->CancelActiveAndPendingDialogs(this); 2584 2585 // Notify observers about navigation. 2586 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2587 DidNavigateAnyFrame(details, params)); 2588} 2589 2590void WebContentsImpl::SetMainFrameMimeType(const std::string& mime_type) { 2591 contents_mime_type_ = mime_type; 2592} 2593 2594bool WebContentsImpl::CanOverscrollContent() const { 2595 // Disable overscroll when touch emulation is on. See crbug.com/369938. 2596 if (touch_emulation_enabled_) 2597 return false; 2598 2599 if (delegate_) 2600 return delegate_->CanOverscrollContent(); 2601 2602 return false; 2603} 2604 2605void WebContentsImpl::OnThemeColorChanged(SkColor theme_color) { 2606 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2607 DidChangeThemeColor(theme_color)); 2608} 2609 2610void WebContentsImpl::OnDidLoadResourceFromMemoryCache( 2611 const GURL& url, 2612 const std::string& security_info, 2613 const std::string& http_method, 2614 const std::string& mime_type, 2615 ResourceType::Type resource_type) { 2616 base::StatsCounter cache("WebKit.CacheHit"); 2617 cache.Increment(); 2618 2619 // Send out a notification that we loaded a resource from our memory cache. 2620 int cert_id = 0; 2621 net::CertStatus cert_status = 0; 2622 int security_bits = -1; 2623 int connection_status = 0; 2624 SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids; 2625 DeserializeSecurityInfo(security_info, &cert_id, &cert_status, 2626 &security_bits, &connection_status, 2627 &signed_certificate_timestamp_ids); 2628 // TODO(alcutter,eranm): Pass signed_certificate_timestamp_ids into details 2629 LoadFromMemoryCacheDetails details( 2630 url, GetRenderProcessHost()->GetID(), cert_id, cert_status, http_method, 2631 mime_type, resource_type); 2632 2633 controller_.ssl_manager()->DidLoadFromMemoryCache(details); 2634 2635 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2636 DidLoadResourceFromMemoryCache(details)); 2637 2638 if (url.is_valid() && url.SchemeIsHTTPOrHTTPS()) { 2639 scoped_refptr<net::URLRequestContextGetter> request_context( 2640 resource_type == ResourceType::MEDIA ? 2641 GetBrowserContext()->GetMediaRequestContextForRenderProcess( 2642 GetRenderProcessHost()->GetID()) : 2643 GetBrowserContext()->GetRequestContextForRenderProcess( 2644 GetRenderProcessHost()->GetID())); 2645 BrowserThread::PostTask( 2646 BrowserThread::IO, 2647 FROM_HERE, 2648 base::Bind(&NotifyCacheOnIO, request_context, url, http_method)); 2649 } 2650} 2651 2652void WebContentsImpl::OnDidDisplayInsecureContent() { 2653 RecordAction(base::UserMetricsAction("SSL.DisplayedInsecureContent")); 2654 displayed_insecure_content_ = true; 2655 SSLManager::NotifySSLInternalStateChanged( 2656 GetController().GetBrowserContext()); 2657} 2658 2659void WebContentsImpl::OnDidRunInsecureContent( 2660 const std::string& security_origin, const GURL& target_url) { 2661 LOG(WARNING) << security_origin << " ran insecure content from " 2662 << target_url.possibly_invalid_spec(); 2663 RecordAction(base::UserMetricsAction("SSL.RanInsecureContent")); 2664 if (EndsWith(security_origin, kDotGoogleDotCom, false)) 2665 RecordAction(base::UserMetricsAction("SSL.RanInsecureContentGoogle")); 2666 controller_.ssl_manager()->DidRunInsecureContent(security_origin); 2667 displayed_insecure_content_ = true; 2668 SSLManager::NotifySSLInternalStateChanged( 2669 GetController().GetBrowserContext()); 2670} 2671 2672 2673void WebContentsImpl::OnDidDetectXSS(int32 page_id, 2674 const GURL& url, 2675 bool blocked_entire_page) { 2676 if (!blocked_entire_page) 2677 return; 2678 2679 int entry_index = controller_.GetEntryIndexWithPageID( 2680 GetRenderViewHost()->GetSiteInstance(), page_id); 2681 if (entry_index < 0) 2682 return; 2683 2684 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( 2685 controller_.GetEntryAtIndex(entry_index)); 2686 if (!entry) 2687 return; 2688 2689 entry->set_xss_detected(true); 2690} 2691 2692void WebContentsImpl::OnDocumentLoadedInFrame() { 2693 CHECK(render_frame_message_source_); 2694 CHECK(!render_view_message_source_); 2695 RenderFrameHostImpl* rfh = 2696 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2697 FOR_EACH_OBSERVER( 2698 WebContentsObserver, observers_, DocumentLoadedInFrame(rfh)); 2699} 2700 2701void WebContentsImpl::OnDidFinishLoad( 2702 const GURL& url) { 2703 if (!render_frame_message_source_) { 2704 RecordAction(base::UserMetricsAction("BadMessageTerminate_RVD2")); 2705 GetRenderProcessHost()->ReceivedBadMessage(); 2706 return; 2707 } 2708 2709 GURL validated_url(url); 2710 RenderProcessHost* render_process_host = 2711 render_frame_message_source_->GetProcess(); 2712 render_process_host->FilterURL(false, &validated_url); 2713 2714 RenderFrameHostImpl* rfh = 2715 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2716 FOR_EACH_OBSERVER( 2717 WebContentsObserver, observers_, DidFinishLoad(rfh, validated_url)); 2718} 2719 2720void WebContentsImpl::OnDidStartLoading(bool to_different_document) { 2721 RenderFrameHostImpl* rfh = 2722 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2723 int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id(); 2724 2725 // It is possible to get multiple calls to OnDidStartLoading that don't have 2726 // corresponding calls to OnDidStopLoading: 2727 // - With "swappedout://" URLs, this happens when a RenderView gets swapped 2728 // out for a cross-process navigation, and it turns into a placeholder for 2729 // one being rendered in a different process. 2730 // - Also, there might be more than one RenderFrameHost sharing the same 2731 // FrameTreeNode (and thus sharing its ID) each sending a start. 2732 // - But in the future, once clamy@ moves navigation network requests to the 2733 // browser process, there's a good chance that callbacks about starting and 2734 // stopping will all be handled by the browser. When that happens, there 2735 // should no longer be a start/stop call imbalance. TODO(avi): When this 2736 // future arrives, update this code to not allow this case. 2737 DCHECK_GE(loading_frames_in_progress_, 0); 2738 if (loading_progresses_.find(render_frame_id) == loading_progresses_.end()) { 2739 if (loading_frames_in_progress_ == 0) 2740 DidStartLoading(rfh, to_different_document); 2741 ++loading_frames_in_progress_; 2742 } 2743 2744 loading_progresses_[render_frame_id] = kMinimumLoadingProgress; 2745 SendLoadProgressChanged(); 2746} 2747 2748void WebContentsImpl::OnDidStopLoading() { 2749 RenderFrameHostImpl* rfh = 2750 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2751 int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id(); 2752 2753 if (loading_progresses_.find(render_frame_id) != loading_progresses_.end()) { 2754 // Load stopped while we were still tracking load. Make sure we update 2755 // progress based on this frame's completion. 2756 loading_progresses_[render_frame_id] = 1.0; 2757 SendLoadProgressChanged(); 2758 // Then we clean-up our states. 2759 if (loading_total_progress_ == 1.0) 2760 ResetLoadProgressState(); 2761 } 2762 2763 // TODO(japhet): This should be a DCHECK, but the pdf plugin sometimes 2764 // calls DidStopLoading() without a matching DidStartLoading(). 2765 if (loading_frames_in_progress_ == 0) 2766 return; 2767 --loading_frames_in_progress_; 2768 if (loading_frames_in_progress_ == 0) 2769 DidStopLoading(rfh); 2770} 2771 2772void WebContentsImpl::OnDidChangeLoadProgress(double load_progress) { 2773 RenderFrameHostImpl* rfh = 2774 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2775 int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id(); 2776 2777 loading_progresses_[render_frame_id] = load_progress; 2778 2779 // We notify progress change immediately for the first and last updates. 2780 // Also, since the message loop may be pretty busy when a page is loaded, it 2781 // might not execute a posted task in a timely manner so we make sure to 2782 // immediately send progress report if enough time has passed. 2783 base::TimeDelta min_delay = 2784 base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenLoadingUpdatesMS); 2785 if (load_progress == 1.0 || loading_last_progress_update_.is_null() || 2786 base::TimeTicks::Now() - loading_last_progress_update_ > min_delay) { 2787 // If there is a pending task to send progress, it is now obsolete. 2788 loading_weak_factory_.InvalidateWeakPtrs(); 2789 SendLoadProgressChanged(); 2790 if (loading_total_progress_ == 1.0) 2791 ResetLoadProgressState(); 2792 return; 2793 } 2794 2795 if (loading_weak_factory_.HasWeakPtrs()) 2796 return; 2797 2798 base::MessageLoop::current()->PostDelayedTask( 2799 FROM_HERE, 2800 base::Bind(&WebContentsImpl::SendLoadProgressChanged, 2801 loading_weak_factory_.GetWeakPtr()), 2802 min_delay); 2803} 2804 2805void WebContentsImpl::OnGoToEntryAtOffset(int offset) { 2806 if (!delegate_ || delegate_->OnGoToEntryOffset(offset)) 2807 controller_.GoToOffset(offset); 2808} 2809 2810void WebContentsImpl::OnUpdateZoomLimits(int minimum_percent, 2811 int maximum_percent) { 2812 minimum_zoom_percent_ = minimum_percent; 2813 maximum_zoom_percent_ = maximum_percent; 2814} 2815 2816void WebContentsImpl::OnEnumerateDirectory(int request_id, 2817 const base::FilePath& path) { 2818 if (!delegate_) 2819 return; 2820 2821 ChildProcessSecurityPolicyImpl* policy = 2822 ChildProcessSecurityPolicyImpl::GetInstance(); 2823 if (policy->CanReadFile(GetRenderProcessHost()->GetID(), path)) 2824 delegate_->EnumerateDirectory(this, request_id, path); 2825} 2826 2827void WebContentsImpl::OnRegisterProtocolHandler(const std::string& protocol, 2828 const GURL& url, 2829 const base::string16& title, 2830 bool user_gesture) { 2831 if (!delegate_) 2832 return; 2833 2834 ChildProcessSecurityPolicyImpl* policy = 2835 ChildProcessSecurityPolicyImpl::GetInstance(); 2836 if (policy->IsPseudoScheme(protocol)) 2837 return; 2838 2839 delegate_->RegisterProtocolHandler(this, protocol, url, user_gesture); 2840} 2841 2842void WebContentsImpl::OnUnregisterProtocolHandler(const std::string& protocol, 2843 const GURL& url, 2844 bool user_gesture) { 2845 if (!delegate_) 2846 return; 2847 2848 ChildProcessSecurityPolicyImpl* policy = 2849 ChildProcessSecurityPolicyImpl::GetInstance(); 2850 if (policy->IsPseudoScheme(protocol)) 2851 return; 2852 2853 delegate_->UnregisterProtocolHandler(this, protocol, url, user_gesture); 2854} 2855 2856void WebContentsImpl::OnFindReply(int request_id, 2857 int number_of_matches, 2858 const gfx::Rect& selection_rect, 2859 int active_match_ordinal, 2860 bool final_update) { 2861 if (delegate_) { 2862 delegate_->FindReply(this, request_id, number_of_matches, selection_rect, 2863 active_match_ordinal, final_update); 2864 } 2865} 2866 2867#if defined(OS_ANDROID) 2868void WebContentsImpl::OnFindMatchRectsReply( 2869 int version, 2870 const std::vector<gfx::RectF>& rects, 2871 const gfx::RectF& active_rect) { 2872 if (delegate_) 2873 delegate_->FindMatchRectsReply(this, version, rects, active_rect); 2874} 2875 2876void WebContentsImpl::OnOpenDateTimeDialog( 2877 const ViewHostMsg_DateTimeDialogValue_Params& value) { 2878 date_time_chooser_->ShowDialog(ContentViewCore::FromWebContents(this), 2879 GetRenderViewHost(), 2880 value.dialog_type, 2881 value.dialog_value, 2882 value.minimum, 2883 value.maximum, 2884 value.step, 2885 value.suggestions); 2886} 2887 2888#endif 2889 2890void WebContentsImpl::OnPepperPluginHung(int plugin_child_id, 2891 const base::FilePath& path, 2892 bool is_hung) { 2893 UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1); 2894 2895 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2896 PluginHungStatusChanged(plugin_child_id, path, is_hung)); 2897} 2898 2899void WebContentsImpl::OnPluginCrashed(const base::FilePath& plugin_path, 2900 base::ProcessId plugin_pid) { 2901 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2902 PluginCrashed(plugin_path, plugin_pid)); 2903} 2904 2905void WebContentsImpl::OnDomOperationResponse(const std::string& json_string, 2906 int automation_id) { 2907 DomOperationNotificationDetails details(json_string, automation_id); 2908 NotificationService::current()->Notify( 2909 NOTIFICATION_DOM_OPERATION_RESPONSE, 2910 Source<WebContents>(this), 2911 Details<DomOperationNotificationDetails>(&details)); 2912} 2913 2914void WebContentsImpl::OnAppCacheAccessed(const GURL& manifest_url, 2915 bool blocked_by_policy) { 2916 // Notify observers about navigation. 2917 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2918 AppCacheAccessed(manifest_url, blocked_by_policy)); 2919} 2920 2921void WebContentsImpl::OnOpenColorChooser( 2922 int color_chooser_id, 2923 SkColor color, 2924 const std::vector<ColorSuggestion>& suggestions) { 2925 ColorChooser* new_color_chooser = delegate_ ? 2926 delegate_->OpenColorChooser(this, color, suggestions) : 2927 NULL; 2928 if (!new_color_chooser) 2929 return; 2930 if (color_chooser_info_.get()) 2931 color_chooser_info_->chooser->End(); 2932 2933 color_chooser_info_.reset(new ColorChooserInfo( 2934 render_frame_message_source_->GetProcess()->GetID(), 2935 render_frame_message_source_->GetRoutingID(), 2936 new_color_chooser, 2937 color_chooser_id)); 2938} 2939 2940void WebContentsImpl::OnEndColorChooser(int color_chooser_id) { 2941 if (color_chooser_info_ && 2942 color_chooser_id == color_chooser_info_->identifier) 2943 color_chooser_info_->chooser->End(); 2944} 2945 2946void WebContentsImpl::OnSetSelectedColorInColorChooser(int color_chooser_id, 2947 SkColor color) { 2948 if (color_chooser_info_ && 2949 color_chooser_id == color_chooser_info_->identifier) 2950 color_chooser_info_->chooser->SetSelectedColor(color); 2951} 2952 2953// This exists for render views that don't have a WebUI, but do have WebUI 2954// bindings enabled. 2955void WebContentsImpl::OnWebUISend(const GURL& source_url, 2956 const std::string& name, 2957 const base::ListValue& args) { 2958 if (delegate_) 2959 delegate_->WebUISend(this, source_url, name, args); 2960} 2961 2962void WebContentsImpl::OnRequestPpapiBrokerPermission( 2963 int routing_id, 2964 const GURL& url, 2965 const base::FilePath& plugin_path) { 2966 if (!delegate_) { 2967 OnPpapiBrokerPermissionResult(routing_id, false); 2968 return; 2969 } 2970 2971 if (!delegate_->RequestPpapiBrokerPermission( 2972 this, url, plugin_path, 2973 base::Bind(&WebContentsImpl::OnPpapiBrokerPermissionResult, 2974 base::Unretained(this), routing_id))) { 2975 NOTIMPLEMENTED(); 2976 OnPpapiBrokerPermissionResult(routing_id, false); 2977 } 2978} 2979 2980void WebContentsImpl::OnPpapiBrokerPermissionResult(int routing_id, 2981 bool result) { 2982 Send(new ViewMsg_PpapiBrokerPermissionResult(routing_id, result)); 2983} 2984 2985void WebContentsImpl::OnBrowserPluginMessage(const IPC::Message& message) { 2986 // This creates a BrowserPluginEmbedder, which handles all the BrowserPlugin 2987 // specific messages for this WebContents. This means that any message from 2988 // a BrowserPlugin prior to this will be ignored. 2989 // For more info, see comment above classes BrowserPluginEmbedder and 2990 // BrowserPluginGuest. 2991 CHECK(!browser_plugin_embedder_.get()); 2992 browser_plugin_embedder_.reset(BrowserPluginEmbedder::Create(this)); 2993 browser_plugin_embedder_->OnMessageReceived(message); 2994} 2995 2996void WebContentsImpl::OnDidDownloadImage( 2997 int id, 2998 int http_status_code, 2999 const GURL& image_url, 3000 const std::vector<SkBitmap>& bitmaps, 3001 const std::vector<gfx::Size>& original_bitmap_sizes) { 3002 if (bitmaps.size() != original_bitmap_sizes.size()) 3003 return; 3004 3005 ImageDownloadMap::iterator iter = image_download_map_.find(id); 3006 if (iter == image_download_map_.end()) { 3007 // Currently WebContents notifies us of ANY downloads so that it is 3008 // possible to get here. 3009 return; 3010 } 3011 if (!iter->second.is_null()) { 3012 iter->second.Run( 3013 id, http_status_code, image_url, bitmaps, original_bitmap_sizes); 3014 } 3015 image_download_map_.erase(id); 3016} 3017 3018void WebContentsImpl::OnUpdateFaviconURL( 3019 const std::vector<FaviconURL>& candidates) { 3020 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3021 DidUpdateFaviconURL(candidates)); 3022} 3023 3024void WebContentsImpl::OnMediaPlayingNotification(int64 player_cookie, 3025 bool has_video, 3026 bool has_audio) { 3027// Chrome OS does its own detection of audio and video. 3028#if !defined(OS_CHROMEOS) 3029 scoped_ptr<PowerSaveBlocker> blocker; 3030 if (has_video) { 3031 blocker = PowerSaveBlocker::Create( 3032 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, "Playing video"); 3033#if defined(OS_ANDROID) 3034 static_cast<PowerSaveBlockerImpl*>(blocker.get()) 3035 ->InitDisplaySleepBlocker(GetView()->GetNativeView()); 3036#endif 3037 } else if (has_audio) { 3038 blocker = PowerSaveBlocker::Create( 3039 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, "Playing audio"); 3040 } 3041 3042 if (blocker) { 3043 power_save_blockers_[render_frame_message_source_][player_cookie] = 3044 blocker.release(); 3045 } 3046#endif // !defined(OS_CHROMEOS) 3047} 3048 3049void WebContentsImpl::OnMediaPausedNotification(int64 player_cookie) { 3050 // Chrome OS does its own detection of audio and video. 3051#if !defined(OS_CHROMEOS) 3052 delete power_save_blockers_[render_frame_message_source_][player_cookie]; 3053 power_save_blockers_[render_frame_message_source_].erase(player_cookie); 3054#endif // !defined(OS_CHROMEOS) 3055} 3056 3057void WebContentsImpl::OnFirstVisuallyNonEmptyPaint() { 3058 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3059 DidFirstVisuallyNonEmptyPaint()); 3060} 3061 3062void WebContentsImpl::DidChangeVisibleSSLState() { 3063 if (delegate_) 3064 delegate_->VisibleSSLStateChanged(this); 3065} 3066 3067void WebContentsImpl::NotifyBeforeFormRepostWarningShow() { 3068 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3069 BeforeFormRepostWarningShow()); 3070} 3071 3072 3073void WebContentsImpl::ActivateAndShowRepostFormWarningDialog() { 3074 Activate(); 3075 if (delegate_) 3076 delegate_->ShowRepostFormWarningDialog(this); 3077} 3078 3079bool WebContentsImpl::HasAccessedInitialDocument() { 3080 return has_accessed_initial_document_; 3081} 3082 3083// Notifies the RenderWidgetHost instance about the fact that the page is 3084// loading, or done loading. 3085void WebContentsImpl::SetIsLoading(RenderViewHost* render_view_host, 3086 bool is_loading, 3087 bool to_different_document, 3088 LoadNotificationDetails* details) { 3089 if (is_loading == is_loading_) 3090 return; 3091 3092 if (!is_loading) { 3093 load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE, 3094 base::string16()); 3095 load_state_host_.clear(); 3096 upload_size_ = 0; 3097 upload_position_ = 0; 3098 } 3099 3100 GetRenderManager()->SetIsLoading(is_loading); 3101 3102 is_loading_ = is_loading; 3103 waiting_for_response_ = is_loading; 3104 is_load_to_different_document_ = to_different_document; 3105 3106 if (delegate_) 3107 delegate_->LoadingStateChanged(this, to_different_document); 3108 NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD); 3109 3110 std::string url = (details ? details->url.possibly_invalid_spec() : "NULL"); 3111 if (is_loading) { 3112 TRACE_EVENT_ASYNC_BEGIN1("browser", "WebContentsImpl Loading", this, 3113 "URL", url); 3114 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3115 DidStartLoading(render_view_host)); 3116 } else { 3117 TRACE_EVENT_ASYNC_END1("browser", "WebContentsImpl Loading", this, 3118 "URL", url); 3119 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3120 DidStopLoading(render_view_host)); 3121 } 3122 3123 // TODO(avi): Remove. http://crbug.com/170921 3124 int type = is_loading ? NOTIFICATION_LOAD_START : NOTIFICATION_LOAD_STOP; 3125 NotificationDetails det = NotificationService::NoDetails(); 3126 if (details) 3127 det = Details<LoadNotificationDetails>(details); 3128 NotificationService::current()->Notify( 3129 type, Source<NavigationController>(&controller_), det); 3130} 3131 3132void WebContentsImpl::SelectRange(const gfx::Point& start, 3133 const gfx::Point& end) { 3134 RenderFrameHost* focused_frame = GetFocusedFrame(); 3135 if (!focused_frame) 3136 return; 3137 3138 focused_frame->Send( 3139 new InputMsg_SelectRange(focused_frame->GetRoutingID(), start, end)); 3140} 3141 3142void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) { 3143 // If we are creating a RVH for a restored controller, then we need to make 3144 // sure the RenderView starts with a next_page_id_ larger than the number 3145 // of restored entries. This must be called before the RenderView starts 3146 // navigating (to avoid a race between the browser updating max_page_id and 3147 // the renderer updating next_page_id_). Because of this, we only call this 3148 // from CreateRenderView and allow that to notify the RenderView for us. 3149 int max_restored_page_id = controller_.GetMaxRestoredPageID(); 3150 if (max_restored_page_id > 3151 GetMaxPageIDForSiteInstance(rvh->GetSiteInstance())) 3152 UpdateMaxPageIDForSiteInstance(rvh->GetSiteInstance(), 3153 max_restored_page_id); 3154} 3155 3156bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl* entry, 3157 const base::string16& title) { 3158 // For file URLs without a title, use the pathname instead. In the case of a 3159 // synthesized title, we don't want the update to count toward the "one set 3160 // per page of the title to history." 3161 base::string16 final_title; 3162 bool explicit_set; 3163 if (entry && entry->GetURL().SchemeIsFile() && title.empty()) { 3164 final_title = base::UTF8ToUTF16(entry->GetURL().ExtractFileName()); 3165 explicit_set = false; // Don't count synthetic titles toward the set limit. 3166 } else { 3167 base::TrimWhitespace(title, base::TRIM_ALL, &final_title); 3168 explicit_set = true; 3169 } 3170 3171 // If a page is created via window.open and never navigated, 3172 // there will be no navigation entry. In this situation, 3173 // |page_title_when_no_navigation_entry_| will be used for page title. 3174 if (entry) { 3175 if (final_title == entry->GetTitle()) 3176 return false; // Nothing changed, don't bother. 3177 3178 entry->SetTitle(final_title); 3179 } else { 3180 if (page_title_when_no_navigation_entry_ == final_title) 3181 return false; // Nothing changed, don't bother. 3182 3183 page_title_when_no_navigation_entry_ = final_title; 3184 } 3185 3186 // Lastly, set the title for the view. 3187 view_->SetPageTitle(final_title); 3188 3189 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3190 TitleWasSet(entry, explicit_set)); 3191 3192 // TODO(avi): Remove. http://crbug.com/170921 3193 std::pair<NavigationEntry*, bool> details = 3194 std::make_pair(entry, explicit_set); 3195 NotificationService::current()->Notify( 3196 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, 3197 Source<WebContents>(this), 3198 Details<std::pair<NavigationEntry*, bool> >(&details)); 3199 3200 return true; 3201} 3202 3203void WebContentsImpl::SendLoadProgressChanged() { 3204 loading_last_progress_update_ = base::TimeTicks::Now(); 3205 double progress = 0.0; 3206 int frame_count = 0; 3207 3208 for (LoadingProgressMap::iterator it = loading_progresses_.begin(); 3209 it != loading_progresses_.end(); 3210 ++it) { 3211 progress += it->second; 3212 ++frame_count; 3213 } 3214 if (frame_count == 0) 3215 return; 3216 progress /= frame_count; 3217 DCHECK(progress <= 1.0); 3218 3219 if (progress <= loading_total_progress_) 3220 return; 3221 loading_total_progress_ = progress; 3222 3223 if (delegate_) 3224 delegate_->LoadProgressChanged(this, progress); 3225} 3226 3227void WebContentsImpl::ResetLoadProgressState() { 3228 loading_progresses_.clear(); 3229 loading_total_progress_ = 0.0; 3230 loading_weak_factory_.InvalidateWeakPtrs(); 3231 loading_last_progress_update_ = base::TimeTicks(); 3232} 3233 3234void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host, 3235 RenderViewHost* new_host) { 3236 // After sending out a swap notification, we need to send a disconnect 3237 // notification so that clients that pick up a pointer to |this| can NULL the 3238 // pointer. See Bug 1230284. 3239 notify_disconnection_ = true; 3240 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3241 RenderViewHostChanged(old_host, new_host)); 3242 3243 // TODO(avi): Remove. http://crbug.com/170921 3244 std::pair<RenderViewHost*, RenderViewHost*> details = 3245 std::make_pair(old_host, new_host); 3246 NotificationService::current()->Notify( 3247 NOTIFICATION_RENDER_VIEW_HOST_CHANGED, 3248 Source<WebContents>(this), 3249 Details<std::pair<RenderViewHost*, RenderViewHost*> >(&details)); 3250 3251 // Ensure that the associated embedder gets cleared after a RenderViewHost 3252 // gets swapped, so we don't reuse the same embedder next time a 3253 // RenderViewHost is attached to this WebContents. 3254 RemoveBrowserPluginEmbedder(); 3255} 3256 3257void WebContentsImpl::NotifyFrameSwapped(RenderFrameHost* old_host, 3258 RenderFrameHost* new_host) { 3259 FOR_EACH_OBSERVER(WebContentsObserver, 3260 observers_, 3261 RenderFrameHostChanged(old_host, new_host)); 3262} 3263 3264// TODO(avi): Remove this entire function because this notification is already 3265// covered by two observer functions. http://crbug.com/170921 3266void WebContentsImpl::NotifyDisconnected() { 3267 if (!notify_disconnection_) 3268 return; 3269 3270 notify_disconnection_ = false; 3271 NotificationService::current()->Notify( 3272 NOTIFICATION_WEB_CONTENTS_DISCONNECTED, 3273 Source<WebContents>(this), 3274 NotificationService::NoDetails()); 3275} 3276 3277void WebContentsImpl::NotifyNavigationEntryCommitted( 3278 const LoadCommittedDetails& load_details) { 3279 FOR_EACH_OBSERVER( 3280 WebContentsObserver, observers_, NavigationEntryCommitted(load_details)); 3281} 3282 3283bool WebContentsImpl::OnMessageReceived(RenderFrameHost* render_frame_host, 3284 const IPC::Message& message) { 3285 return OnMessageReceived(NULL, render_frame_host, message); 3286} 3287 3288const GURL& WebContentsImpl::GetMainFrameLastCommittedURL() const { 3289 return GetLastCommittedURL(); 3290} 3291 3292void WebContentsImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) { 3293 // Note this is only for subframes, the notification for the main frame 3294 // happens in RenderViewCreated. 3295 FOR_EACH_OBSERVER(WebContentsObserver, 3296 observers_, 3297 RenderFrameCreated(render_frame_host)); 3298 SetAccessibilityModeOnFrame(accessibility_mode_, render_frame_host); 3299} 3300 3301void WebContentsImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) { 3302 ClearPowerSaveBlockers(render_frame_host); 3303 FOR_EACH_OBSERVER(WebContentsObserver, 3304 observers_, 3305 RenderFrameDeleted(render_frame_host)); 3306} 3307 3308void WebContentsImpl::WorkerCrashed(RenderFrameHost* render_frame_host) { 3309 if (delegate_) 3310 delegate_->WorkerCrashed(this); 3311} 3312 3313void WebContentsImpl::ShowContextMenu(RenderFrameHost* render_frame_host, 3314 const ContextMenuParams& params) { 3315 ContextMenuParams context_menu_params(params); 3316 // Allow WebContentsDelegates to handle the context menu operation first. 3317 if (GetBrowserPluginGuest()) { 3318 WebContentsViewGuest* view_guest = 3319 static_cast<WebContentsViewGuest*>(GetView()); 3320 context_menu_params = view_guest->ConvertContextMenuParams(params); 3321 } 3322 if (delegate_ && delegate_->HandleContextMenu(context_menu_params)) 3323 return; 3324 3325 render_view_host_delegate_view_->ShowContextMenu(render_frame_host, 3326 context_menu_params); 3327} 3328 3329void WebContentsImpl::RunJavaScriptMessage( 3330 RenderFrameHost* render_frame_host, 3331 const base::string16& message, 3332 const base::string16& default_prompt, 3333 const GURL& frame_url, 3334 JavaScriptMessageType javascript_message_type, 3335 IPC::Message* reply_msg) { 3336 // Suppress JavaScript dialogs when requested. Also suppress messages when 3337 // showing an interstitial as it's shown over the previous page and we don't 3338 // want the hidden page's dialogs to interfere with the interstitial. 3339 bool suppress_this_message = 3340 static_cast<RenderViewHostImpl*>(render_frame_host->GetRenderViewHost())-> 3341 IsSwappedOut() || 3342 ShowingInterstitialPage() || 3343 !delegate_ || 3344 delegate_->ShouldSuppressDialogs() || 3345 !delegate_->GetJavaScriptDialogManager(); 3346 3347 if (!suppress_this_message) { 3348 std::string accept_lang = GetContentClient()->browser()-> 3349 GetAcceptLangs(GetBrowserContext()); 3350 dialog_manager_ = delegate_->GetJavaScriptDialogManager(); 3351 dialog_manager_->RunJavaScriptDialog( 3352 this, 3353 frame_url.GetOrigin(), 3354 accept_lang, 3355 javascript_message_type, 3356 message, 3357 default_prompt, 3358 base::Bind(&WebContentsImpl::OnDialogClosed, 3359 base::Unretained(this), 3360 render_frame_host->GetProcess()->GetID(), 3361 render_frame_host->GetRoutingID(), 3362 reply_msg, 3363 false), 3364 &suppress_this_message); 3365 } 3366 3367 if (suppress_this_message) { 3368 // If we are suppressing messages, just reply as if the user immediately 3369 // pressed "Cancel", passing true to |dialog_was_suppressed|. 3370 OnDialogClosed(render_frame_host->GetProcess()->GetID(), 3371 render_frame_host->GetRoutingID(), reply_msg, 3372 true, false, base::string16()); 3373 } 3374 3375 // OnDialogClosed (two lines up) may have caused deletion of this object (see 3376 // http://crbug.com/288961 ). The only safe thing to do here is return. 3377} 3378 3379void WebContentsImpl::RunBeforeUnloadConfirm( 3380 RenderFrameHost* render_frame_host, 3381 const base::string16& message, 3382 bool is_reload, 3383 IPC::Message* reply_msg) { 3384 RenderFrameHostImpl* rfhi = 3385 static_cast<RenderFrameHostImpl*>(render_frame_host); 3386 RenderViewHostImpl* rvhi = 3387 static_cast<RenderViewHostImpl*>(render_frame_host->GetRenderViewHost()); 3388 if (delegate_) 3389 delegate_->WillRunBeforeUnloadConfirm(); 3390 3391 bool suppress_this_message = 3392 rvhi->rvh_state() != RenderViewHostImpl::STATE_DEFAULT || 3393 !delegate_ || 3394 delegate_->ShouldSuppressDialogs() || 3395 !delegate_->GetJavaScriptDialogManager(); 3396 if (suppress_this_message) { 3397 rfhi->JavaScriptDialogClosed(reply_msg, true, base::string16(), true); 3398 return; 3399 } 3400 3401 is_showing_before_unload_dialog_ = true; 3402 dialog_manager_ = delegate_->GetJavaScriptDialogManager(); 3403 dialog_manager_->RunBeforeUnloadDialog( 3404 this, message, is_reload, 3405 base::Bind(&WebContentsImpl::OnDialogClosed, base::Unretained(this), 3406 render_frame_host->GetProcess()->GetID(), 3407 render_frame_host->GetRoutingID(), reply_msg, 3408 false)); 3409} 3410 3411WebContents* WebContentsImpl::GetAsWebContents() { 3412 return this; 3413} 3414 3415bool WebContentsImpl::IsNeverVisible() { 3416 if (!delegate_) 3417 return false; 3418 return delegate_->IsNeverVisible(this); 3419} 3420 3421#if defined(OS_WIN) 3422gfx::NativeViewAccessible WebContentsImpl::GetParentNativeViewAccessible() { 3423 return accessible_parent_; 3424} 3425#endif 3426 3427RenderViewHostDelegateView* WebContentsImpl::GetDelegateView() { 3428 return render_view_host_delegate_view_; 3429} 3430 3431RendererPreferences WebContentsImpl::GetRendererPrefs( 3432 BrowserContext* browser_context) const { 3433 return renderer_preferences_; 3434} 3435 3436gfx::Rect WebContentsImpl::GetRootWindowResizerRect() const { 3437 if (delegate_) 3438 return delegate_->GetRootWindowResizerRect(); 3439 return gfx::Rect(); 3440} 3441 3442void WebContentsImpl::RemoveBrowserPluginEmbedder() { 3443 if (browser_plugin_embedder_) 3444 browser_plugin_embedder_.reset(); 3445} 3446 3447void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) { 3448 // Don't send notifications if we are just creating a swapped-out RVH for 3449 // the opener chain. These won't be used for view-source or WebUI, so it's 3450 // ok to return early. 3451 if (static_cast<RenderViewHostImpl*>(render_view_host)->IsSwappedOut()) 3452 return; 3453 3454 if (delegate_) 3455 view_->SetOverscrollControllerEnabled(CanOverscrollContent()); 3456 3457 NotificationService::current()->Notify( 3458 NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED, 3459 Source<WebContents>(this), 3460 Details<RenderViewHost>(render_view_host)); 3461 3462 // When we're creating views, we're still doing initial setup, so we always 3463 // use the pending Web UI rather than any possibly existing committed one. 3464 if (GetRenderManager()->pending_web_ui()) 3465 GetRenderManager()->pending_web_ui()->RenderViewCreated(render_view_host); 3466 3467 NavigationEntry* entry = controller_.GetPendingEntry(); 3468 if (entry && entry->IsViewSourceMode()) { 3469 // Put the renderer in view source mode. 3470 render_view_host->Send( 3471 new ViewMsg_EnableViewSourceMode(render_view_host->GetRoutingID())); 3472 } 3473 3474 view_->RenderViewCreated(render_view_host); 3475 3476 FOR_EACH_OBSERVER( 3477 WebContentsObserver, observers_, RenderViewCreated(render_view_host)); 3478 3479 // We tell the observers now instead of when the main RenderFrameHostImpl is 3480 // constructed because otherwise it would be too early (i.e. IPCs sent to the 3481 // frame would be dropped because it's not created yet). 3482 RenderFrameHost* main_frame = render_view_host->GetMainFrame(); 3483 FOR_EACH_OBSERVER( 3484 WebContentsObserver, observers_, RenderFrameCreated(main_frame)); 3485 SetAccessibilityModeOnFrame(accessibility_mode_, main_frame); 3486} 3487 3488void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) { 3489 if (rvh != GetRenderViewHost()) { 3490 // Don't notify the world, since this came from a renderer in the 3491 // background. 3492 return; 3493 } 3494 3495 notify_disconnection_ = true; 3496 // TODO(avi): Remove. http://crbug.com/170921 3497 NotificationService::current()->Notify( 3498 NOTIFICATION_WEB_CONTENTS_CONNECTED, 3499 Source<WebContents>(this), 3500 NotificationService::NoDetails()); 3501 3502 bool was_crashed = IsCrashed(); 3503 SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING, 0); 3504 3505 // Restore the focus to the tab (otherwise the focus will be on the top 3506 // window). 3507 if (was_crashed && !FocusLocationBarByDefault() && 3508 (!delegate_ || delegate_->ShouldFocusPageAfterCrash())) { 3509 view_->Focus(); 3510 } 3511 3512 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewReady()); 3513} 3514 3515void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh, 3516 base::TerminationStatus status, 3517 int error_code) { 3518 if (rvh != GetRenderViewHost()) { 3519 // The pending page's RenderViewHost is gone. 3520 return; 3521 } 3522 3523 // Ensure fullscreen mode is exited in the |delegate_| since a crashed 3524 // renderer may not have made a clean exit. 3525 if (IsFullscreenForCurrentTab()) 3526 ToggleFullscreenMode(false); 3527 3528 // Cancel any visible dialogs so they are not left dangling over the sad tab. 3529 if (dialog_manager_) 3530 dialog_manager_->CancelActiveAndPendingDialogs(this); 3531 3532 if (delegate_) 3533 delegate_->HideValidationMessage(this); 3534 3535 SetIsLoading(rvh, false, true, NULL); 3536 NotifyDisconnected(); 3537 SetIsCrashed(status, error_code); 3538 3539 // Reset the loading progress. TODO(avi): What does it mean to have a 3540 // "renderer crash" when there is more than one renderer process serving a 3541 // webpage? Once this function is called at a more granular frame level, we 3542 // probably will need to more granularly reset the state here. 3543 ResetLoadProgressState(); 3544 loading_frames_in_progress_ = 0; 3545 3546 FOR_EACH_OBSERVER(WebContentsObserver, 3547 observers_, 3548 RenderProcessGone(GetCrashedStatus())); 3549} 3550 3551void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) { 3552 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh)); 3553} 3554 3555void WebContentsImpl::UpdateState(RenderViewHost* rvh, 3556 int32 page_id, 3557 const PageState& page_state) { 3558 // Ensure that this state update comes from either the active RVH or one of 3559 // the swapped out RVHs. We don't expect to hear from any other RVHs. 3560 // TODO(nasko): This should go through RenderFrameHost. 3561 // TODO(creis): We can't update state for cross-process subframes until we 3562 // have FrameNavigationEntries. Once we do, this should be a DCHECK. 3563 if (rvh != GetRenderViewHost() && 3564 !GetRenderManager()->IsRVHOnSwappedOutList( 3565 static_cast<RenderViewHostImpl*>(rvh))) 3566 return; 3567 3568 // We must be prepared to handle state updates for any page, these occur 3569 // when the user is scrolling and entering form data, as well as when we're 3570 // leaving a page, in which case our state may have already been moved to 3571 // the next page. The navigation controller will look up the appropriate 3572 // NavigationEntry and update it when it is notified via the delegate. 3573 3574 int entry_index = controller_.GetEntryIndexWithPageID( 3575 rvh->GetSiteInstance(), page_id); 3576 if (entry_index < 0) 3577 return; 3578 NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index); 3579 3580 if (page_state == entry->GetPageState()) 3581 return; // Nothing to update. 3582 entry->SetPageState(page_state); 3583 controller_.NotifyEntryChanged(entry, entry_index); 3584} 3585 3586void WebContentsImpl::UpdateTargetURL(int32 page_id, const GURL& url) { 3587 if (delegate_) 3588 delegate_->UpdateTargetURL(this, page_id, url); 3589} 3590 3591void WebContentsImpl::Close(RenderViewHost* rvh) { 3592#if defined(OS_MACOSX) 3593 // The UI may be in an event-tracking loop, such as between the 3594 // mouse-down and mouse-up in text selection or a button click. 3595 // Defer the close until after tracking is complete, so that we 3596 // don't free objects out from under the UI. 3597 // TODO(shess): This could get more fine-grained. For instance, 3598 // closing a tab in another window while selecting text in the 3599 // current window's Omnibox should be just fine. 3600 if (view_->IsEventTracking()) { 3601 view_->CloseTabAfterEventTracking(); 3602 return; 3603 } 3604#endif 3605 3606 // Ignore this if it comes from a RenderViewHost that we aren't showing. 3607 if (delegate_ && rvh == GetRenderViewHost()) 3608 delegate_->CloseContents(this); 3609} 3610 3611void WebContentsImpl::SwappedOut(RenderFrameHost* rfh) { 3612 if (delegate_ && rfh->GetRenderViewHost() == GetRenderViewHost()) 3613 delegate_->SwappedOut(this); 3614} 3615 3616void WebContentsImpl::DidDeferAfterResponseStarted() { 3617#if defined(OS_ANDROID) 3618 ContentViewCoreImpl::FromWebContents(this)->DidDeferAfterResponseStarted(); 3619#endif 3620} 3621 3622bool WebContentsImpl::WillHandleDeferAfterResponseStarted() { 3623#if defined(OS_ANDROID) 3624 return ContentViewCoreImpl::FromWebContents(this)-> 3625 WillHandleDeferAfterResponseStarted(); 3626#else 3627 return false; 3628#endif 3629} 3630 3631void WebContentsImpl::RequestMove(const gfx::Rect& new_bounds) { 3632 if (delegate_ && delegate_->IsPopupOrPanel(this)) 3633 delegate_->MoveContents(this, new_bounds); 3634} 3635 3636void WebContentsImpl::DidStartLoading(RenderFrameHost* render_frame_host, 3637 bool to_different_document) { 3638 SetIsLoading(render_frame_host->GetRenderViewHost(), true, 3639 to_different_document, NULL); 3640} 3641 3642void WebContentsImpl::DidStopLoading(RenderFrameHost* render_frame_host) { 3643 scoped_ptr<LoadNotificationDetails> details; 3644 3645 // Use the last committed entry rather than the active one, in case a 3646 // pending entry has been created. 3647 NavigationEntry* entry = controller_.GetLastCommittedEntry(); 3648 Navigator* navigator = frame_tree_.root()->navigator(); 3649 3650 // An entry may not exist for a stop when loading an initial blank page or 3651 // if an iframe injected by script into a blank page finishes loading. 3652 if (entry) { 3653 base::TimeDelta elapsed = 3654 base::TimeTicks::Now() - navigator->GetCurrentLoadStart(); 3655 3656 details.reset(new LoadNotificationDetails( 3657 entry->GetVirtualURL(), 3658 entry->GetTransitionType(), 3659 elapsed, 3660 &controller_, 3661 controller_.GetCurrentEntryIndex())); 3662 } 3663 3664 SetIsLoading(render_frame_host->GetRenderViewHost(), false, true, 3665 details.get()); 3666} 3667 3668void WebContentsImpl::DidCancelLoading() { 3669 controller_.DiscardNonCommittedEntries(); 3670 3671 // Update the URL display. 3672 NotifyNavigationStateChanged(INVALIDATE_TYPE_URL); 3673} 3674 3675void WebContentsImpl::DidAccessInitialDocument() { 3676 has_accessed_initial_document_ = true; 3677 3678 // We may have left a failed browser-initiated navigation in the address bar 3679 // to let the user edit it and try again. Clear it now that content might 3680 // show up underneath it. 3681 if (!IsLoading() && controller_.GetPendingEntry()) 3682 controller_.DiscardPendingEntry(); 3683 3684 // Update the URL display. 3685 NotifyNavigationStateChanged(content::INVALIDATE_TYPE_URL); 3686} 3687 3688void WebContentsImpl::DidDisownOpener(RenderFrameHost* render_frame_host) { 3689 if (opener_) { 3690 // Clear our opener so that future cross-process navigations don't have an 3691 // opener assigned. 3692 RemoveDestructionObserver(opener_); 3693 opener_ = NULL; 3694 } 3695 3696 // Notify all swapped out RenderViewHosts for this tab. This is important 3697 // in case we go back to them, or if another window in those processes tries 3698 // to access window.opener. 3699 GetRenderManager()->DidDisownOpener(render_frame_host->GetRenderViewHost()); 3700} 3701 3702void WebContentsImpl::DocumentOnLoadCompleted( 3703 RenderFrameHost* render_frame_host) { 3704 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3705 DocumentOnLoadCompletedInMainFrame()); 3706 3707 // TODO(avi): Remove. http://crbug.com/170921 3708 NotificationService::current()->Notify( 3709 NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, 3710 Source<WebContents>(this), 3711 NotificationService::NoDetails()); 3712} 3713 3714void WebContentsImpl::UpdateTitle(RenderFrameHost* render_frame_host, 3715 int32 page_id, 3716 const base::string16& title, 3717 base::i18n::TextDirection title_direction) { 3718 RenderViewHost* rvh = render_frame_host->GetRenderViewHost(); 3719 3720 // If we have a title, that's a pretty good indication that we've started 3721 // getting useful data. 3722 SetNotWaitingForResponse(); 3723 3724 // Try to find the navigation entry, which might not be the current one. 3725 // For example, it might be from a pending RVH for the pending entry. 3726 NavigationEntryImpl* entry = controller_.GetEntryWithPageID( 3727 rvh->GetSiteInstance(), page_id); 3728 3729 // We can handle title updates when we don't have an entry in 3730 // UpdateTitleForEntry, but only if the update is from the current RVH. 3731 // TODO(avi): Change to make decisions based on the RenderFrameHost. 3732 if (!entry && rvh != GetRenderViewHost()) 3733 return; 3734 3735 // TODO(evan): make use of title_direction. 3736 // http://code.google.com/p/chromium/issues/detail?id=27094 3737 if (!UpdateTitleForEntry(entry, title)) 3738 return; 3739 3740 // Broadcast notifications when the UI should be updated. 3741 if (entry == controller_.GetEntryAtOffset(0)) 3742 NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE); 3743} 3744 3745void WebContentsImpl::UpdateEncoding(RenderFrameHost* render_frame_host, 3746 const std::string& encoding) { 3747 SetEncoding(encoding); 3748} 3749 3750void WebContentsImpl::DocumentAvailableInMainFrame( 3751 RenderViewHost* render_view_host) { 3752 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3753 DocumentAvailableInMainFrame()); 3754} 3755void WebContentsImpl::RouteCloseEvent(RenderViewHost* rvh) { 3756 // Tell the active RenderViewHost to run unload handlers and close, as long 3757 // as the request came from a RenderViewHost in the same BrowsingInstance. 3758 // In most cases, we receive this from a swapped out RenderViewHost. 3759 // It is possible to receive it from one that has just been swapped in, 3760 // in which case we might as well deliver the message anyway. 3761 if (rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance())) 3762 GetRenderViewHost()->ClosePage(); 3763} 3764 3765void WebContentsImpl::RouteMessageEvent( 3766 RenderViewHost* rvh, 3767 const ViewMsg_PostMessage_Params& params) { 3768 // Only deliver the message to the active RenderViewHost if the request 3769 // came from a RenderViewHost in the same BrowsingInstance or if this 3770 // WebContents is dedicated to a browser plugin guest. 3771 // Note: This check means that an embedder could theoretically receive a 3772 // postMessage from anyone (not just its own guests). However, this is 3773 // probably not a risk for apps since other pages won't have references 3774 // to App windows. 3775 if (!rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()) && 3776 !GetBrowserPluginGuest() && !GetBrowserPluginEmbedder()) 3777 return; 3778 3779 ViewMsg_PostMessage_Params new_params(params); 3780 3781 if (!params.message_port_ids.empty()) { 3782 MessagePortMessageFilter* message_port_message_filter = 3783 static_cast<RenderProcessHostImpl*>(GetRenderProcessHost()) 3784 ->message_port_message_filter(); 3785 message_port_message_filter->UpdateMessagePortsWithNewRoutes( 3786 params.message_port_ids, 3787 &new_params.new_routing_ids); 3788 } 3789 3790 // If there is a source_routing_id, translate it to the routing ID for 3791 // the equivalent swapped out RVH in the target process. If we need 3792 // to create a swapped out RVH for the source tab, we create its opener 3793 // chain as well, since those will also be accessible to the target page. 3794 if (new_params.source_routing_id != MSG_ROUTING_NONE) { 3795 // Try to look up the WebContents for the source page. 3796 WebContentsImpl* source_contents = NULL; 3797 RenderViewHostImpl* source_rvh = RenderViewHostImpl::FromID( 3798 rvh->GetProcess()->GetID(), params.source_routing_id); 3799 if (source_rvh) { 3800 source_contents = static_cast<WebContentsImpl*>( 3801 source_rvh->GetDelegate()->GetAsWebContents()); 3802 } 3803 3804 if (source_contents) { 3805 if (GetBrowserPluginGuest()) { 3806 // We create a swapped out RenderView for the embedder in the guest's 3807 // render process but we intentionally do not expose the embedder's 3808 // opener chain to it. 3809 new_params.source_routing_id = 3810 source_contents->CreateSwappedOutRenderView(GetSiteInstance()); 3811 } else { 3812 new_params.source_routing_id = 3813 source_contents->CreateOpenerRenderViews(GetSiteInstance()); 3814 } 3815 } else { 3816 // We couldn't find it, so don't pass a source frame. 3817 new_params.source_routing_id = MSG_ROUTING_NONE; 3818 } 3819 } 3820 3821 // In most cases, we receive this from a swapped out RenderViewHost. 3822 // It is possible to receive it from one that has just been swapped in, 3823 // in which case we might as well deliver the message anyway. 3824 Send(new ViewMsg_PostMessageEvent(GetRoutingID(), new_params)); 3825} 3826 3827bool WebContentsImpl::AddMessageToConsole(int32 level, 3828 const base::string16& message, 3829 int32 line_no, 3830 const base::string16& source_id) { 3831 if (!delegate_) 3832 return false; 3833 return delegate_->AddMessageToConsole(this, level, message, line_no, 3834 source_id); 3835} 3836 3837WebPreferences WebContentsImpl::GetWebkitPrefs() { 3838 // We want to base the page config off of the actual URL, rather than the 3839 // virtual URL. 3840 // TODO(nasko): Investigate how to remove the GetActiveEntry usage here, 3841 // as it is deprecated and can be out of sync with GetRenderViewHost(). 3842 GURL url = controller_.GetActiveEntry() 3843 ? controller_.GetActiveEntry()->GetURL() : GURL::EmptyGURL(); 3844 3845 return GetRenderManager()->current_host()->GetWebkitPrefs(url); 3846} 3847 3848int WebContentsImpl::CreateSwappedOutRenderView( 3849 SiteInstance* instance) { 3850 return GetRenderManager()->CreateRenderFrame(instance, MSG_ROUTING_NONE, 3851 true, true); 3852} 3853 3854void WebContentsImpl::OnUserGesture() { 3855 // Notify observers. 3856 FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetUserGesture()); 3857 3858 ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get(); 3859 if (rdh) // NULL in unittests. 3860 rdh->OnUserGesture(this); 3861} 3862 3863void WebContentsImpl::OnIgnoredUIEvent() { 3864 // Notify observers. 3865 FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetIgnoredUIEvent()); 3866} 3867 3868void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh, 3869 bool is_during_beforeunload, 3870 bool is_during_unload) { 3871 // Don't show hung renderer dialog for a swapped out RVH. 3872 if (rvh != GetRenderViewHost()) 3873 return; 3874 3875 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh); 3876 3877 // Ignore renderer unresponsive event if debugger is attached to the tab 3878 // since the event may be a result of the renderer sitting on a breakpoint. 3879 // See http://crbug.com/65458 3880 if (DevToolsAgentHost::IsDebuggerAttached(this)) 3881 return; 3882 3883 if (is_during_beforeunload || is_during_unload) { 3884 // Hang occurred while firing the beforeunload/unload handler. 3885 // Pretend the handler fired so tab closing continues as if it had. 3886 rvhi->set_sudden_termination_allowed(true); 3887 3888 if (!GetRenderManager()->ShouldCloseTabOnUnresponsiveRenderer()) 3889 return; 3890 3891 // If the tab hangs in the beforeunload/unload handler there's really 3892 // nothing we can do to recover. If the hang is in the beforeunload handler, 3893 // pretend the beforeunload listeners have all fired and allow the delegate 3894 // to continue closing; the user will not have the option of cancelling the 3895 // close. Otherwise, pretend the unload listeners have all fired and close 3896 // the tab. 3897 bool close = true; 3898 if (is_during_beforeunload && delegate_) { 3899 delegate_->BeforeUnloadFired(this, true, &close); 3900 } 3901 if (close) 3902 Close(rvh); 3903 return; 3904 } 3905 3906 if (!GetRenderViewHostImpl() || !GetRenderViewHostImpl()->IsRenderViewLive()) 3907 return; 3908 3909 if (delegate_) 3910 delegate_->RendererUnresponsive(this); 3911} 3912 3913void WebContentsImpl::RendererResponsive(RenderViewHost* render_view_host) { 3914 if (delegate_) 3915 delegate_->RendererResponsive(this); 3916} 3917 3918void WebContentsImpl::LoadStateChanged( 3919 const GURL& url, 3920 const net::LoadStateWithParam& load_state, 3921 uint64 upload_position, 3922 uint64 upload_size) { 3923 load_state_ = load_state; 3924 upload_position_ = upload_position; 3925 upload_size_ = upload_size; 3926 load_state_host_ = net::IDNToUnicode(url.host(), 3927 GetContentClient()->browser()->GetAcceptLangs( 3928 GetBrowserContext())); 3929 if (load_state_.state == net::LOAD_STATE_READING_RESPONSE) 3930 SetNotWaitingForResponse(); 3931 if (IsLoading()) { 3932 NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD | INVALIDATE_TYPE_TAB); 3933 } 3934} 3935 3936void WebContentsImpl::BeforeUnloadFiredFromRenderManager( 3937 bool proceed, const base::TimeTicks& proceed_time, 3938 bool* proceed_to_fire_unload) { 3939 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3940 BeforeUnloadFired(proceed_time)); 3941 if (delegate_) 3942 delegate_->BeforeUnloadFired(this, proceed, proceed_to_fire_unload); 3943 // Note: |this| might be deleted at this point. 3944} 3945 3946void WebContentsImpl::RenderProcessGoneFromRenderManager( 3947 RenderViewHost* render_view_host) { 3948 DCHECK(crashed_status_ != base::TERMINATION_STATUS_STILL_RUNNING); 3949 RenderViewTerminated(render_view_host, crashed_status_, crashed_error_code_); 3950} 3951 3952void WebContentsImpl::UpdateRenderViewSizeForRenderManager() { 3953 // TODO(brettw) this is a hack. See WebContentsView::SizeContents. 3954 gfx::Size size = GetSizeForNewRenderView(); 3955 // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be 3956 // here during container initialization and normal window size will be set 3957 // later. In case of tab duplication this resizing to 0x0 prevents setting 3958 // normal size later so just ignore it. 3959 if (!size.IsEmpty()) 3960 view_->SizeContents(size); 3961} 3962 3963void WebContentsImpl::CancelModalDialogsForRenderManager() { 3964 // We need to cancel modal dialogs when doing a process swap, since the load 3965 // deferrer would prevent us from swapping out. 3966 if (dialog_manager_) 3967 dialog_manager_->CancelActiveAndPendingDialogs(this); 3968} 3969 3970void WebContentsImpl::NotifySwappedFromRenderManager(RenderFrameHost* old_host, 3971 RenderFrameHost* new_host, 3972 bool is_main_frame) { 3973 if (is_main_frame) { 3974 NotifyViewSwapped(old_host ? old_host->GetRenderViewHost() : NULL, 3975 new_host->GetRenderViewHost()); 3976 3977 // Make sure the visible RVH reflects the new delegate's preferences. 3978 if (delegate_) 3979 view_->SetOverscrollControllerEnabled(CanOverscrollContent()); 3980 3981 view_->RenderViewSwappedIn(new_host->GetRenderViewHost()); 3982 } 3983 3984 NotifyFrameSwapped(old_host, new_host); 3985} 3986 3987int WebContentsImpl::CreateOpenerRenderViewsForRenderManager( 3988 SiteInstance* instance) { 3989 if (!opener_) 3990 return MSG_ROUTING_NONE; 3991 3992 // Recursively create RenderViews for anything else in the opener chain. 3993 return opener_->CreateOpenerRenderViews(instance); 3994} 3995 3996int WebContentsImpl::CreateOpenerRenderViews(SiteInstance* instance) { 3997 int opener_route_id = MSG_ROUTING_NONE; 3998 3999 // If this tab has an opener, ensure it has a RenderView in the given 4000 // SiteInstance as well. 4001 if (opener_) 4002 opener_route_id = opener_->CreateOpenerRenderViews(instance); 4003 4004 // If any of the renderers (current, pending, or swapped out) for this 4005 // WebContents has the same SiteInstance, use it. 4006 if (GetRenderManager()->current_host()->GetSiteInstance() == instance) 4007 return GetRenderManager()->current_host()->GetRoutingID(); 4008 4009 if (GetRenderManager()->pending_render_view_host() && 4010 GetRenderManager()->pending_render_view_host()->GetSiteInstance() == 4011 instance) 4012 return GetRenderManager()->pending_render_view_host()->GetRoutingID(); 4013 4014 RenderViewHostImpl* rvh = GetRenderManager()->GetSwappedOutRenderViewHost( 4015 instance); 4016 if (rvh) 4017 return rvh->GetRoutingID(); 4018 4019 // Create a swapped out RenderView in the given SiteInstance if none exists, 4020 // setting its opener to the given route_id. Return the new view's route_id. 4021 return GetRenderManager()->CreateRenderFrame(instance, opener_route_id, 4022 true, true); 4023} 4024 4025NavigationControllerImpl& WebContentsImpl::GetControllerForRenderManager() { 4026 return GetController(); 4027} 4028 4029WebUIImpl* WebContentsImpl::CreateWebUIForRenderManager(const GURL& url) { 4030 return static_cast<WebUIImpl*>(CreateWebUI(url)); 4031} 4032 4033NavigationEntry* 4034 WebContentsImpl::GetLastCommittedNavigationEntryForRenderManager() { 4035 return controller_.GetLastCommittedEntry(); 4036} 4037 4038bool WebContentsImpl::CreateRenderViewForRenderManager( 4039 RenderViewHost* render_view_host, 4040 int opener_route_id, 4041 int proxy_routing_id, 4042 bool for_main_frame) { 4043 TRACE_EVENT0("browser", "WebContentsImpl::CreateRenderViewForRenderManager"); 4044 // Can be NULL during tests. 4045 RenderWidgetHostViewBase* rwh_view; 4046 // TODO(kenrb): RenderWidgetHostViewChildFrame special casing is temporary 4047 // until RenderWidgetHost is attached to RenderFrameHost. We need to special 4048 // case this because RWH is still a base class of RenderViewHost, and child 4049 // frame RWHVs are unique in that they do not have their own WebContents. 4050 if (!for_main_frame) { 4051 RenderWidgetHostViewChildFrame* rwh_view_child = 4052 new RenderWidgetHostViewChildFrame(render_view_host); 4053 rwh_view = rwh_view_child; 4054 } else { 4055 rwh_view = view_->CreateViewForWidget(render_view_host); 4056 } 4057 4058 // Now that the RenderView has been created, we need to tell it its size. 4059 if (rwh_view) 4060 rwh_view->SetSize(GetSizeForNewRenderView()); 4061 4062 // Make sure we use the correct starting page_id in the new RenderView. 4063 UpdateMaxPageIDIfNecessary(render_view_host); 4064 int32 max_page_id = 4065 GetMaxPageIDForSiteInstance(render_view_host->GetSiteInstance()); 4066 4067 if (!static_cast<RenderViewHostImpl*>( 4068 render_view_host)->CreateRenderView(base::string16(), 4069 opener_route_id, 4070 proxy_routing_id, 4071 max_page_id, 4072 created_with_opener_)) { 4073 return false; 4074 } 4075 4076#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 4077 // Force a ViewMsg_Resize to be sent, needed to make plugins show up on 4078 // linux. See crbug.com/83941. 4079 if (rwh_view) { 4080 if (RenderWidgetHost* render_widget_host = rwh_view->GetRenderWidgetHost()) 4081 render_widget_host->WasResized(); 4082 } 4083#endif 4084 4085 return true; 4086} 4087 4088#if defined(OS_ANDROID) 4089 4090base::android::ScopedJavaLocalRef<jobject> 4091WebContentsImpl::GetJavaWebContents() { 4092 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 4093 4094 WebContentsAndroid* web_contents_android = 4095 static_cast<WebContentsAndroid*>(GetUserData(kWebContentsAndroidKey)); 4096 if (!web_contents_android) { 4097 web_contents_android = new WebContentsAndroid(this); 4098 SetUserData(kWebContentsAndroidKey, web_contents_android); 4099 } 4100 return web_contents_android->GetJavaObject(); 4101} 4102 4103bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() { 4104 return CreateRenderViewForRenderManager(GetRenderViewHost(), 4105 MSG_ROUTING_NONE, 4106 MSG_ROUTING_NONE, 4107 true); 4108} 4109 4110#elif defined(OS_MACOSX) 4111 4112void WebContentsImpl::SetAllowOverlappingViews(bool overlapping) { 4113 view_->SetAllowOverlappingViews(overlapping); 4114} 4115 4116bool WebContentsImpl::GetAllowOverlappingViews() { 4117 return view_->GetAllowOverlappingViews(); 4118} 4119 4120void WebContentsImpl::SetAllowOtherViews(bool allow) { 4121 view_->SetAllowOtherViews(allow); 4122} 4123 4124bool WebContentsImpl::GetAllowOtherViews() { 4125 return view_->GetAllowOtherViews(); 4126} 4127 4128#endif 4129 4130void WebContentsImpl::OnDialogClosed(int render_process_id, 4131 int render_frame_id, 4132 IPC::Message* reply_msg, 4133 bool dialog_was_suppressed, 4134 bool success, 4135 const base::string16& user_input) { 4136 RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(render_process_id, 4137 render_frame_id); 4138 last_dialog_suppressed_ = dialog_was_suppressed; 4139 4140 if (is_showing_before_unload_dialog_ && !success) { 4141 // If a beforeunload dialog is canceled, we need to stop the throbber from 4142 // spinning, since we forced it to start spinning in Navigate. 4143 if (rfh) 4144 DidStopLoading(rfh); 4145 controller_.DiscardNonCommittedEntries(); 4146 4147 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 4148 BeforeUnloadDialogCancelled()); 4149 } 4150 4151 is_showing_before_unload_dialog_ = false; 4152 if (rfh) { 4153 rfh->JavaScriptDialogClosed(reply_msg, success, user_input, 4154 dialog_was_suppressed); 4155 } else { 4156 // Don't leak the sync IPC reply if the RFH or process is gone. 4157 delete reply_msg; 4158 } 4159} 4160 4161void WebContentsImpl::SetEncoding(const std::string& encoding) { 4162 if (encoding == last_reported_encoding_) 4163 return; 4164 last_reported_encoding_ = encoding; 4165 4166 canonical_encoding_ = GetContentClient()->browser()-> 4167 GetCanonicalEncodingNameByAliasName(encoding); 4168} 4169 4170void WebContentsImpl::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) { 4171 RenderWidgetHostViewBase* rwh_view = view_->CreateViewForWidget(rvh); 4172 // Can be NULL during tests. 4173 if (rwh_view) 4174 rwh_view->SetSize(GetContainerBounds().size()); 4175} 4176 4177bool WebContentsImpl::IsHidden() { 4178 return capturer_count_ == 0 && !should_normally_be_visible_; 4179} 4180 4181RenderFrameHostManager* WebContentsImpl::GetRenderManager() const { 4182 return frame_tree_.root()->render_manager(); 4183} 4184 4185RenderViewHostImpl* WebContentsImpl::GetRenderViewHostImpl() { 4186 return static_cast<RenderViewHostImpl*>(GetRenderViewHost()); 4187} 4188 4189BrowserPluginGuest* WebContentsImpl::GetBrowserPluginGuest() const { 4190 return browser_plugin_guest_.get(); 4191} 4192 4193void WebContentsImpl::SetBrowserPluginGuest(BrowserPluginGuest* guest) { 4194 CHECK(!browser_plugin_guest_); 4195 browser_plugin_guest_.reset(guest); 4196} 4197 4198BrowserPluginEmbedder* WebContentsImpl::GetBrowserPluginEmbedder() const { 4199 return browser_plugin_embedder_.get(); 4200} 4201 4202void WebContentsImpl::ClearPowerSaveBlockers( 4203 RenderFrameHost* render_frame_host) { 4204 STLDeleteValues(&power_save_blockers_[render_frame_host]); 4205 power_save_blockers_.erase(render_frame_host); 4206} 4207 4208void WebContentsImpl::ClearAllPowerSaveBlockers() { 4209 for (PowerSaveBlockerMap::iterator i(power_save_blockers_.begin()); 4210 i != power_save_blockers_.end(); ++i) 4211 STLDeleteValues(&power_save_blockers_[i->first]); 4212 power_save_blockers_.clear(); 4213} 4214 4215gfx::Size WebContentsImpl::GetSizeForNewRenderView() { 4216 gfx::Size size; 4217 if (delegate_) 4218 size = delegate_->GetSizeForNewRenderView(this); 4219 if (size.IsEmpty()) 4220 size = GetContainerBounds().size(); 4221 return size; 4222} 4223 4224void WebContentsImpl::OnFrameRemoved(RenderFrameHost* render_frame_host) { 4225 FOR_EACH_OBSERVER( 4226 WebContentsObserver, observers_, FrameDetached(render_frame_host)); 4227} 4228 4229void WebContentsImpl::OnPreferredSizeChanged(const gfx::Size& old_size) { 4230 if (!delegate_) 4231 return; 4232 const gfx::Size new_size = GetPreferredSize(); 4233 if (new_size != old_size) 4234 delegate_->UpdatePreferredSize(this, new_size); 4235} 4236 4237void WebContentsImpl::ResumeResponseDeferredAtStart() { 4238 FrameTreeNode* node = frame_tree_.root(); 4239 node->render_manager()->ResumeResponseDeferredAtStart(); 4240} 4241 4242} // namespace content 4243