| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/tab_contents/render_view_host_manager.h" | 5 #include "content/browser/tab_contents/render_view_host_manager.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "content/browser/debugger/devtools_manager_impl.h" | 9 #include "content/browser/debugger/devtools_manager_impl.h" |
| 10 #include "content/browser/renderer_host/render_view_host.h" | 10 #include "content/browser/renderer_host/render_view_host.h" |
| 11 #include "content/browser/renderer_host/render_view_host_delegate.h" | 11 #include "content/browser/renderer_host/render_view_host_delegate.h" |
| 12 #include "content/browser/renderer_host/render_view_host_factory.h" | 12 #include "content/browser/renderer_host/render_view_host_factory.h" |
| 13 #include "content/browser/renderer_host/render_widget_host_view.h" | 13 #include "content/browser/renderer_host/render_widget_host_view.h" |
| 14 #include "content/browser/site_instance.h" | 14 #include "content/browser/site_instance.h" |
| 15 #include "content/browser/tab_contents/navigation_controller.h" | 15 #include "content/browser/tab_contents/navigation_controller.h" |
| 16 #include "content/browser/tab_contents/navigation_entry.h" | 16 #include "content/browser/tab_contents/navigation_entry_impl.h" |
| 17 #include "content/browser/tab_contents/tab_contents_view.h" | 17 #include "content/browser/tab_contents/tab_contents_view.h" |
| 18 #include "content/browser/webui/web_ui.h" | 18 #include "content/browser/webui/web_ui.h" |
| 19 #include "content/browser/webui/web_ui_factory.h" | 19 #include "content/browser/webui/web_ui_factory.h" |
| 20 #include "content/public/browser/notification_service.h" | 20 #include "content/public/browser/notification_service.h" |
| 21 #include "content/common/view_messages.h" | 21 #include "content/common/view_messages.h" |
| 22 #include "content/public/browser/content_browser_client.h" | 22 #include "content/public/browser/content_browser_client.h" |
| 23 #include "content/public/browser/notification_types.h" | 23 #include "content/public/browser/notification_types.h" |
| 24 #include "content/public/common/content_switches.h" | 24 #include "content/public/common/content_switches.h" |
| 25 #include "content/public/common/url_constants.h" | 25 #include "content/public/common/url_constants.h" |
| 26 | 26 |
| 27 namespace base { | 27 using content::NavigationEntry; |
| 28 class WaitableEvent; | 28 using content::NavigationEntryImpl; |
| 29 } | |
| 30 | 29 |
| 31 RenderViewHostManager::RenderViewHostManager( | 30 RenderViewHostManager::RenderViewHostManager( |
| 32 RenderViewHostDelegate* render_view_delegate, | 31 RenderViewHostDelegate* render_view_delegate, |
| 33 Delegate* delegate) | 32 Delegate* delegate) |
| 34 : delegate_(delegate), | 33 : delegate_(delegate), |
| 35 cross_navigation_pending_(false), | 34 cross_navigation_pending_(false), |
| 36 render_view_delegate_(render_view_delegate), | 35 render_view_delegate_(render_view_delegate), |
| 37 render_view_host_(NULL), | 36 render_view_host_(NULL), |
| 38 pending_render_view_host_(NULL), | 37 pending_render_view_host_(NULL), |
| 39 interstitial_page_(NULL) { | 38 interstitial_page_(NULL) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSING, | 71 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSING, |
| 73 content::NotificationService::AllSources()); | 72 content::NotificationService::AllSources()); |
| 74 } | 73 } |
| 75 | 74 |
| 76 RenderWidgetHostView* RenderViewHostManager::GetRenderWidgetHostView() const { | 75 RenderWidgetHostView* RenderViewHostManager::GetRenderWidgetHostView() const { |
| 77 if (!render_view_host_) | 76 if (!render_view_host_) |
| 78 return NULL; | 77 return NULL; |
| 79 return render_view_host_->view(); | 78 return render_view_host_->view(); |
| 80 } | 79 } |
| 81 | 80 |
| 82 RenderViewHost* RenderViewHostManager::Navigate(const NavigationEntry& entry) { | 81 RenderViewHost* RenderViewHostManager::Navigate( |
| 82 const NavigationEntryImpl& entry) { |
| 83 // Create a pending RenderViewHost. It will give us the one we should use | 83 // Create a pending RenderViewHost. It will give us the one we should use |
| 84 RenderViewHost* dest_render_view_host = UpdateRendererStateForNavigate(entry); | 84 RenderViewHost* dest_render_view_host = UpdateRendererStateForNavigate(entry); |
| 85 if (!dest_render_view_host) | 85 if (!dest_render_view_host) |
| 86 return NULL; // We weren't able to create a pending render view host. | 86 return NULL; // We weren't able to create a pending render view host. |
| 87 | 87 |
| 88 // If the current render_view_host_ isn't live, we should create it so | 88 // If the current render_view_host_ isn't live, we should create it so |
| 89 // that we don't show a sad tab while the dest_render_view_host fetches | 89 // that we don't show a sad tab while the dest_render_view_host fetches |
| 90 // its first page. (Bug 1145340) | 90 // its first page. (Bug 1145340) |
| 91 if (dest_render_view_host != render_view_host_ && | 91 if (dest_render_view_host != render_view_host_ && |
| 92 !render_view_host_->IsRenderViewLive()) { | 92 !render_view_host_->IsRenderViewLive()) { |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 } | 322 } |
| 323 } | 323 } |
| 324 | 324 |
| 325 bool RenderViewHostManager::ShouldTransitionCrossSite() { | 325 bool RenderViewHostManager::ShouldTransitionCrossSite() { |
| 326 // True if we are using process-per-site-instance (default) or | 326 // True if we are using process-per-site-instance (default) or |
| 327 // process-per-site (kProcessPerSite). | 327 // process-per-site (kProcessPerSite). |
| 328 return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab); | 328 return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab); |
| 329 } | 329 } |
| 330 | 330 |
| 331 bool RenderViewHostManager::ShouldSwapProcessesForNavigation( | 331 bool RenderViewHostManager::ShouldSwapProcessesForNavigation( |
| 332 const content::NavigationEntry* cur_entry, | 332 const NavigationEntry* cur_entry, |
| 333 const NavigationEntry* new_entry) const { | 333 const NavigationEntryImpl* new_entry) const { |
| 334 DCHECK(new_entry); | 334 DCHECK(new_entry); |
| 335 | 335 |
| 336 // Check for reasons to swap processes even if we are in a process model that | 336 // Check for reasons to swap processes even if we are in a process model that |
| 337 // doesn't usually swap (e.g., process-per-tab). | 337 // doesn't usually swap (e.g., process-per-tab). |
| 338 | 338 |
| 339 // For security, we should transition between processes when one is a Web UI | 339 // For security, we should transition between processes when one is a Web UI |
| 340 // page and one isn't. If there's no cur_entry, check the current RVH's | 340 // page and one isn't. If there's no cur_entry, check the current RVH's |
| 341 // site, which might already be committed to a Web UI URL (such as the NTP). | 341 // site, which might already be committed to a Web UI URL (such as the NTP). |
| 342 const GURL& current_url = (cur_entry) ? cur_entry->GetURL() : | 342 const GURL& current_url = (cur_entry) ? cur_entry->GetURL() : |
| 343 render_view_host_->site_instance()->site(); | 343 render_view_host_->site_instance()->site(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 367 // without screwing up the session history sometimes (when navigating between | 367 // without screwing up the session history sometimes (when navigating between |
| 368 // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat | 368 // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat |
| 369 // it as a new navigation). So require a view switch. | 369 // it as a new navigation). So require a view switch. |
| 370 if (cur_entry->IsViewSourceMode() != new_entry->IsViewSourceMode()) | 370 if (cur_entry->IsViewSourceMode() != new_entry->IsViewSourceMode()) |
| 371 return true; | 371 return true; |
| 372 | 372 |
| 373 return false; | 373 return false; |
| 374 } | 374 } |
| 375 | 375 |
| 376 SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry( | 376 SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry( |
| 377 const NavigationEntry& entry, | 377 const NavigationEntryImpl& entry, |
| 378 SiteInstance* curr_instance) { | 378 SiteInstance* curr_instance) { |
| 379 // NOTE: This is only called when ShouldTransitionCrossSite is true. | 379 // NOTE: This is only called when ShouldTransitionCrossSite is true. |
| 380 | 380 |
| 381 const GURL& dest_url = entry.GetURL(); | 381 const GURL& dest_url = entry.GetURL(); |
| 382 NavigationController& controller = delegate_->GetControllerForRenderManager(); | 382 NavigationController& controller = delegate_->GetControllerForRenderManager(); |
| 383 content::BrowserContext* browser_context = controller.browser_context(); | 383 content::BrowserContext* browser_context = controller.browser_context(); |
| 384 | 384 |
| 385 // If the entry has an instance already we should use it. | 385 // If the entry has an instance already we should use it. |
| 386 if (entry.site_instance()) | 386 if (entry.site_instance()) |
| 387 return entry.site_instance(); | 387 return entry.site_instance(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 422 return curr_instance->GetRelatedSiteInstance(dest_url); | 422 return curr_instance->GetRelatedSiteInstance(dest_url); |
| 423 | 423 |
| 424 // Normally the "site" on the SiteInstance is set lazily when the load | 424 // Normally the "site" on the SiteInstance is set lazily when the load |
| 425 // actually commits. This is to support better process sharing in case | 425 // actually commits. This is to support better process sharing in case |
| 426 // the site redirects to some other site: we want to use the destination | 426 // the site redirects to some other site: we want to use the destination |
| 427 // site in the site instance. | 427 // site in the site instance. |
| 428 // | 428 // |
| 429 // In the case of session restore, as it loads all the pages immediately | 429 // In the case of session restore, as it loads all the pages immediately |
| 430 // we need to set the site first, otherwise after a restore none of the | 430 // we need to set the site first, otherwise after a restore none of the |
| 431 // pages would share renderers in process-per-site. | 431 // pages would share renderers in process-per-site. |
| 432 if (entry.restore_type() != NavigationEntry::RESTORE_NONE) | 432 if (entry.restore_type() != NavigationEntryImpl::RESTORE_NONE) |
| 433 curr_instance->SetSite(dest_url); | 433 curr_instance->SetSite(dest_url); |
| 434 | 434 |
| 435 return curr_instance; | 435 return curr_instance; |
| 436 } | 436 } |
| 437 | 437 |
| 438 // Otherwise, only create a new SiteInstance for cross-site navigation. | 438 // Otherwise, only create a new SiteInstance for cross-site navigation. |
| 439 | 439 |
| 440 // TODO(creis): Once we intercept links and script-based navigations, we | 440 // TODO(creis): Once we intercept links and script-based navigations, we |
| 441 // will be able to enforce that all entries in a SiteInstance actually have | 441 // will be able to enforce that all entries in a SiteInstance actually have |
| 442 // the same site, and it will be safe to compare the URL against the | 442 // the same site, and it will be safe to compare the URL against the |
| 443 // SiteInstance's site, as follows: | 443 // SiteInstance's site, as follows: |
| 444 // const GURL& current_url = curr_instance->site(); | 444 // const GURL& current_url = curr_instance->site(); |
| 445 // For now, though, we're in a hybrid model where you only switch | 445 // For now, though, we're in a hybrid model where you only switch |
| 446 // SiteInstances if you type in a cross-site URL. This means we have to | 446 // SiteInstances if you type in a cross-site URL. This means we have to |
| 447 // compare the entry's URL to the last committed entry's URL. | 447 // compare the entry's URL to the last committed entry's URL. |
| 448 content::NavigationEntry* curr_entry = controller.GetLastCommittedEntry(); | 448 NavigationEntry* curr_entry = controller.GetLastCommittedEntry(); |
| 449 if (interstitial_page_) { | 449 if (interstitial_page_) { |
| 450 // The interstitial is currently the last committed entry, but we want to | 450 // The interstitial is currently the last committed entry, but we want to |
| 451 // compare against the last non-interstitial entry. | 451 // compare against the last non-interstitial entry. |
| 452 curr_entry = controller.GetEntryAtOffset(-1); | 452 curr_entry = controller.GetEntryAtOffset(-1); |
| 453 } | 453 } |
| 454 // If there is no last non-interstitial entry (and curr_instance already | 454 // If there is no last non-interstitial entry (and curr_instance already |
| 455 // has a site), then we must have been opened from another tab. We want | 455 // has a site), then we must have been opened from another tab. We want |
| 456 // to compare against the URL of the page that opened us, but we can't | 456 // to compare against the URL of the page that opened us, but we can't |
| 457 // get to it directly. The best we can do is check against the site of | 457 // get to it directly. The best we can do is check against the site of |
| 458 // the SiteInstance. This will be correct when we intercept links and | 458 // the SiteInstance. This will be correct when we intercept links and |
| (...skipping 23 matching lines...) Expand all Loading... |
| 482 // Start the new renderer in a new SiteInstance, but in the current | 482 // Start the new renderer in a new SiteInstance, but in the current |
| 483 // BrowsingInstance. It is important to immediately give this new | 483 // BrowsingInstance. It is important to immediately give this new |
| 484 // SiteInstance to a RenderViewHost (if it is different than our current | 484 // SiteInstance to a RenderViewHost (if it is different than our current |
| 485 // SiteInstance), so that it is ref counted. This will happen in | 485 // SiteInstance), so that it is ref counted. This will happen in |
| 486 // CreatePendingRenderView. | 486 // CreatePendingRenderView. |
| 487 return curr_instance->GetRelatedSiteInstance(dest_url); | 487 return curr_instance->GetRelatedSiteInstance(dest_url); |
| 488 } | 488 } |
| 489 } | 489 } |
| 490 | 490 |
| 491 bool RenderViewHostManager::CreatePendingRenderView( | 491 bool RenderViewHostManager::CreatePendingRenderView( |
| 492 const NavigationEntry& entry, SiteInstance* instance) { | 492 const NavigationEntryImpl& entry, SiteInstance* instance) { |
| 493 content::NavigationEntry* curr_entry = | 493 NavigationEntry* curr_entry = |
| 494 delegate_->GetControllerForRenderManager().GetLastCommittedEntry(); | 494 delegate_->GetControllerForRenderManager().GetLastCommittedEntry(); |
| 495 if (curr_entry) { | 495 if (curr_entry) { |
| 496 DCHECK(!curr_entry->GetContentState().empty()); | 496 DCHECK(!curr_entry->GetContentState().empty()); |
| 497 // TODO(creis): Should send a message to the RenderView to let it know | 497 // TODO(creis): Should send a message to the RenderView to let it know |
| 498 // we're about to switch away, so that it sends an UpdateState message. | 498 // we're about to switch away, so that it sends an UpdateState message. |
| 499 } | 499 } |
| 500 | 500 |
| 501 // Check if we've already created an RVH for this SiteInstance. | 501 // Check if we've already created an RVH for this SiteInstance. |
| 502 CHECK(instance); | 502 CHECK(instance); |
| 503 RenderViewHostMap::iterator iter = | 503 RenderViewHostMap::iterator iter = |
| (...skipping 20 matching lines...) Expand all Loading... |
| 524 if (success) { | 524 if (success) { |
| 525 // Don't show the view until we get a DidNavigate from it. | 525 // Don't show the view until we get a DidNavigate from it. |
| 526 pending_render_view_host_->view()->Hide(); | 526 pending_render_view_host_->view()->Hide(); |
| 527 } else { | 527 } else { |
| 528 CancelPending(); | 528 CancelPending(); |
| 529 } | 529 } |
| 530 return success; | 530 return success; |
| 531 } | 531 } |
| 532 | 532 |
| 533 bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host, | 533 bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host, |
| 534 const NavigationEntry& entry) { | 534 const NavigationEntryImpl& entry) { |
| 535 // If the pending navigation is to a WebUI, tell the RenderView about any | 535 // If the pending navigation is to a WebUI, tell the RenderView about any |
| 536 // bindings it will need enabled. | 536 // bindings it will need enabled. |
| 537 if (pending_web_ui_.get()) | 537 if (pending_web_ui_.get()) |
| 538 render_view_host->AllowBindings(pending_web_ui_->bindings()); | 538 render_view_host->AllowBindings(pending_web_ui_->bindings()); |
| 539 | 539 |
| 540 return delegate_->CreateRenderViewForRenderManager(render_view_host); | 540 return delegate_->CreateRenderViewForRenderManager(render_view_host); |
| 541 } | 541 } |
| 542 | 542 |
| 543 void RenderViewHostManager::CommitPending() { | 543 void RenderViewHostManager::CommitPending() { |
| 544 // First check whether we're going to want to focus the location bar after | 544 // First check whether we're going to want to focus the location bar after |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 } else { | 629 } else { |
| 630 old_render_view_host->Shutdown(); | 630 old_render_view_host->Shutdown(); |
| 631 } | 631 } |
| 632 | 632 |
| 633 // Let the task manager know that we've swapped RenderViewHosts, since it | 633 // Let the task manager know that we've swapped RenderViewHosts, since it |
| 634 // might need to update its process groupings. | 634 // might need to update its process groupings. |
| 635 delegate_->NotifySwappedFromRenderManager(); | 635 delegate_->NotifySwappedFromRenderManager(); |
| 636 } | 636 } |
| 637 | 637 |
| 638 RenderViewHost* RenderViewHostManager::UpdateRendererStateForNavigate( | 638 RenderViewHost* RenderViewHostManager::UpdateRendererStateForNavigate( |
| 639 const NavigationEntry& entry) { | 639 const NavigationEntryImpl& entry) { |
| 640 // If we are cross-navigating, then we want to get back to normal and navigate | 640 // If we are cross-navigating, then we want to get back to normal and navigate |
| 641 // as usual. | 641 // as usual. |
| 642 if (cross_navigation_pending_) { | 642 if (cross_navigation_pending_) { |
| 643 if (pending_render_view_host_) | 643 if (pending_render_view_host_) |
| 644 CancelPending(); | 644 CancelPending(); |
| 645 cross_navigation_pending_ = false; | 645 cross_navigation_pending_ = false; |
| 646 } | 646 } |
| 647 | 647 |
| 648 // This will possibly create (set to NULL) a Web UI object for the pending | 648 // This will possibly create (set to NULL) a Web UI object for the pending |
| 649 // page. We'll use this later to give the page special access. This must | 649 // page. We'll use this later to give the page special access. This must |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 805 } | 805 } |
| 806 } | 806 } |
| 807 | 807 |
| 808 bool RenderViewHostManager::IsSwappedOut(RenderViewHost* rvh) { | 808 bool RenderViewHostManager::IsSwappedOut(RenderViewHost* rvh) { |
| 809 if (!rvh->site_instance()) | 809 if (!rvh->site_instance()) |
| 810 return false; | 810 return false; |
| 811 | 811 |
| 812 return swapped_out_hosts_.find(rvh->site_instance()->id()) != | 812 return swapped_out_hosts_.find(rvh->site_instance()->id()) != |
| 813 swapped_out_hosts_.end(); | 813 swapped_out_hosts_.end(); |
| 814 } | 814 } |
| OLD | NEW |