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