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