Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/web_contents/render_view_host_manager.h" | 5 #include "content/browser/web_contents/render_view_host_manager.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 38 using content::WebUIControllerFactory; | 38 using content::WebUIControllerFactory; |
| 39 | 39 |
| 40 RenderViewHostManager::RenderViewHostManager( | 40 RenderViewHostManager::RenderViewHostManager( |
| 41 content::RenderViewHostDelegate* render_view_delegate, | 41 content::RenderViewHostDelegate* render_view_delegate, |
| 42 Delegate* delegate) | 42 Delegate* delegate) |
| 43 : delegate_(delegate), | 43 : delegate_(delegate), |
| 44 cross_navigation_pending_(false), | 44 cross_navigation_pending_(false), |
| 45 render_view_delegate_(render_view_delegate), | 45 render_view_delegate_(render_view_delegate), |
| 46 render_view_host_(NULL), | 46 render_view_host_(NULL), |
| 47 pending_render_view_host_(NULL), | 47 pending_render_view_host_(NULL), |
| 48 pending_web_ui_(NULL), | |
| 48 interstitial_page_(NULL) { | 49 interstitial_page_(NULL) { |
| 49 } | 50 } |
| 50 | 51 |
| 51 RenderViewHostManager::~RenderViewHostManager() { | 52 RenderViewHostManager::~RenderViewHostManager() { |
| 52 if (pending_render_view_host_) | 53 if (pending_render_view_host_) |
| 53 CancelPending(); | 54 CancelPending(); |
| 54 | 55 |
| 55 // We should always have a main RenderViewHost. | 56 // We should always have a main RenderViewHost. |
| 56 RenderViewHostImpl* render_view_host = render_view_host_; | 57 RenderViewHostImpl* render_view_host = render_view_host_; |
| 57 render_view_host_ = NULL; | 58 render_view_host_ = NULL; |
| 58 render_view_host->Shutdown(); | 59 render_view_host->Shutdown(); |
| 59 | 60 |
| 60 // Shut down any swapped out RenderViewHosts. | 61 // Shut down any swapped out RenderViewHosts. |
| 61 for (RenderViewHostMap::iterator iter = swapped_out_hosts_.begin(); | 62 for (RenderViewHostMap::iterator iter = swapped_out_hosts_.begin(); |
| 62 iter != swapped_out_hosts_.end(); | 63 iter != swapped_out_hosts_.end(); |
| 63 ++iter) { | 64 ++iter) { |
| 64 iter->second->Shutdown(); | 65 iter->second->Shutdown(); |
| 65 } | 66 } |
| 67 | |
| 68 FreePendingWebUI(); | |
| 66 } | 69 } |
| 67 | 70 |
| 68 void RenderViewHostManager::Init(content::BrowserContext* browser_context, | 71 void RenderViewHostManager::Init(content::BrowserContext* browser_context, |
| 69 SiteInstance* site_instance, | 72 SiteInstance* site_instance, |
| 70 int routing_id) { | 73 int routing_id) { |
| 71 // Create a RenderViewHost, once we have an instance. It is important to | 74 // Create a RenderViewHost, once we have an instance. It is important to |
| 72 // immediately give this SiteInstance to a RenderViewHost so that it is | 75 // immediately give this SiteInstance to a RenderViewHost so that it is |
| 73 // ref counted. | 76 // ref counted. |
| 74 if (!site_instance) | 77 if (!site_instance) |
| 75 site_instance = SiteInstance::Create(browser_context); | 78 site_instance = SiteInstance::Create(browser_context); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 199 | 202 |
| 200 void RenderViewHostManager::DidNavigateMainFrame( | 203 void RenderViewHostManager::DidNavigateMainFrame( |
| 201 RenderViewHost* render_view_host) { | 204 RenderViewHost* render_view_host) { |
| 202 if (!cross_navigation_pending_) { | 205 if (!cross_navigation_pending_) { |
| 203 DCHECK(!pending_render_view_host_); | 206 DCHECK(!pending_render_view_host_); |
| 204 | 207 |
| 205 // We should only hear this from our current renderer. | 208 // We should only hear this from our current renderer. |
| 206 DCHECK(render_view_host == render_view_host_); | 209 DCHECK(render_view_host == render_view_host_); |
| 207 | 210 |
| 208 // Even when there is no pending RVH, there may be a pending Web UI. | 211 // Even when there is no pending RVH, there may be a pending Web UI. |
| 209 if (pending_web_ui_.get()) | 212 if (pending_web_ui_) |
| 210 CommitPending(); | 213 CommitPending(); |
| 211 return; | 214 return; |
| 212 } | 215 } |
| 213 | 216 |
| 214 if (render_view_host == pending_render_view_host_) { | 217 if (render_view_host == pending_render_view_host_) { |
| 215 // The pending cross-site navigation completed, so show the renderer. | 218 // The pending cross-site navigation completed, so show the renderer. |
| 216 // If it committed without sending network requests (e.g., data URLs), | 219 // If it committed without sending network requests (e.g., data URLs), |
| 217 // then we still need to swap out the old RVH first and run its unload | 220 // then we still need to swap out the old RVH first and run its unload |
| 218 // handler. OK for that to happen in the background. | 221 // handler. OK for that to happen in the background. |
| 219 if (pending_render_view_host_->GetPendingRequestId() == -1) { | 222 if (pending_render_view_host_->GetPendingRequestId() == -1) { |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 399 // We can't switch a RenderView between view source and non-view source mode | 402 // We can't switch a RenderView between view source and non-view source mode |
| 400 // without screwing up the session history sometimes (when navigating between | 403 // without screwing up the session history sometimes (when navigating between |
| 401 // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat | 404 // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat |
| 402 // it as a new navigation). So require a view switch. | 405 // it as a new navigation). So require a view switch. |
| 403 if (cur_entry->IsViewSourceMode() != new_entry->IsViewSourceMode()) | 406 if (cur_entry->IsViewSourceMode() != new_entry->IsViewSourceMode()) |
| 404 return true; | 407 return true; |
| 405 | 408 |
| 406 return false; | 409 return false; |
| 407 } | 410 } |
| 408 | 411 |
| 412 bool RenderViewHostManager::ShouldReuseWebUI( | |
| 413 const NavigationEntry* curr_entry, | |
| 414 const NavigationEntryImpl* new_entry) const { | |
| 415 NavigationControllerImpl& controller = | |
| 416 delegate_->GetControllerForRenderManager(); | |
| 417 WebUIControllerFactory* factory = | |
| 418 content::GetContentClient()->browser()->GetWebUIControllerFactory(); | |
| 419 return curr_entry && web_ui_.get() && | |
| 420 (factory->GetWebUIType(controller.GetBrowserContext(), | |
|
Dan Beam
2012/04/21 02:53:07
can you split this into multiple lines?
Evan Stade
2012/04/24 17:52:40
not easily.
| |
| 421 curr_entry->GetURL()) == | |
| 422 factory->GetWebUIType(controller.GetBrowserContext(), | |
| 423 new_entry->GetURL())); | |
| 424 } | |
| 425 | |
| 409 SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry( | 426 SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry( |
| 410 const NavigationEntryImpl& entry, | 427 const NavigationEntryImpl& entry, |
| 411 SiteInstance* curr_instance) { | 428 SiteInstance* curr_instance) { |
| 412 // NOTE: This is only called when ShouldTransitionCrossSite is true. | 429 // NOTE: This is only called when ShouldTransitionCrossSite is true. |
| 413 | 430 |
| 414 const GURL& dest_url = entry.GetURL(); | 431 const GURL& dest_url = entry.GetURL(); |
| 415 NavigationControllerImpl& controller = | 432 NavigationControllerImpl& controller = |
| 416 delegate_->GetControllerForRenderManager(); | 433 delegate_->GetControllerForRenderManager(); |
| 417 content::BrowserContext* browser_context = controller.GetBrowserContext(); | 434 content::BrowserContext* browser_context = controller.GetBrowserContext(); |
| 418 | 435 |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 574 } else { | 591 } else { |
| 575 CancelPending(); | 592 CancelPending(); |
| 576 } | 593 } |
| 577 return success; | 594 return success; |
| 578 } | 595 } |
| 579 | 596 |
| 580 bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host, | 597 bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host, |
| 581 const NavigationEntryImpl& entry) { | 598 const NavigationEntryImpl& entry) { |
| 582 // If the pending navigation is to a WebUI, tell the RenderView about any | 599 // If the pending navigation is to a WebUI, tell the RenderView about any |
| 583 // bindings it will need enabled. | 600 // bindings it will need enabled. |
| 584 if (pending_web_ui_.get()) | 601 if (pending_web_ui_) |
| 585 render_view_host->AllowBindings(pending_web_ui_->GetBindings()); | 602 render_view_host->AllowBindings(pending_web_ui_->GetBindings()); |
| 586 | 603 |
| 587 return delegate_->CreateRenderViewForRenderManager(render_view_host); | 604 return delegate_->CreateRenderViewForRenderManager(render_view_host); |
| 588 } | 605 } |
| 589 | 606 |
| 590 void RenderViewHostManager::CommitPending() { | 607 void RenderViewHostManager::CommitPending() { |
| 591 // First check whether we're going to want to focus the location bar after | 608 // First check whether we're going to want to focus the location bar after |
| 592 // this commit. We do this now because the navigation hasn't formally | 609 // this commit. We do this now because the navigation hasn't formally |
| 593 // committed yet, so if we've already cleared |pending_web_ui_| the call chain | 610 // committed yet, so if we've already cleared |pending_web_ui_| the call chain |
| 594 // this triggers won't be able to figure out what's going on. | 611 // this triggers won't be able to figure out what's going on. |
| 595 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); | 612 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); |
| 596 | 613 |
| 597 // Next commit the Web UI, if any. | 614 // Next commit the Web UI, if any. |
| 598 web_ui_.swap(pending_web_ui_); | 615 if (web_ui_.get() != pending_web_ui_) |
|
Dan Beam
2012/04/21 02:53:07
you don't really need .get() operators for scoped_
| |
| 599 if (web_ui_.get() && pending_web_ui_.get() && !pending_render_view_host_) | 616 web_ui_.reset(pending_web_ui_); |
| 600 web_ui_->GetController()->DidBecomeActiveForReusedRenderView(); | 617 pending_web_ui_ = NULL; |
| 601 pending_web_ui_.reset(); | |
| 602 | 618 |
| 603 // It's possible for the pending_render_view_host_ to be NULL when we aren't | 619 // It's possible for the pending_render_view_host_ to be NULL when we aren't |
| 604 // crossing process boundaries. If so, we just needed to handle the Web UI | 620 // crossing process boundaries. If so, we just needed to handle the Web UI |
| 605 // committing above and we're done. | 621 // committing above and we're done. |
| 606 if (!pending_render_view_host_) { | 622 if (!pending_render_view_host_) { |
| 607 if (will_focus_location_bar) | 623 if (will_focus_location_bar) |
| 608 delegate_->SetFocusToLocationBar(false); | 624 delegate_->SetFocusToLocationBar(false); |
| 609 return; | 625 return; |
| 610 } | 626 } |
| 611 | 627 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 674 } | 690 } |
| 675 swapped_out_hosts_[old_site_instance_id] = old_render_view_host; | 691 swapped_out_hosts_[old_site_instance_id] = old_render_view_host; |
| 676 } else { | 692 } else { |
| 677 old_render_view_host->Shutdown(); | 693 old_render_view_host->Shutdown(); |
| 678 } | 694 } |
| 679 | 695 |
| 680 // Let the task manager know that we've swapped RenderViewHosts, since it | 696 // Let the task manager know that we've swapped RenderViewHosts, since it |
| 681 // might need to update its process groupings. | 697 // might need to update its process groupings. |
| 682 delegate_->NotifySwappedFromRenderManager(); | 698 delegate_->NotifySwappedFromRenderManager(); |
| 683 } | 699 } |
| 684 | 700 |
|
Dan Beam
2012/04/21 02:53:07
why \n?
Evan Stade
2012/04/24 17:52:40
Done.
| |
| 701 | |
| 685 RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate( | 702 RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate( |
| 686 const NavigationEntryImpl& entry) { | 703 const NavigationEntryImpl& entry) { |
| 687 // If we are cross-navigating, then we want to get back to normal and navigate | 704 // If we are cross-navigating, then we want to get back to normal and navigate |
| 688 // as usual. | 705 // as usual. |
| 689 if (cross_navigation_pending_) { | 706 if (cross_navigation_pending_) { |
| 690 if (pending_render_view_host_) | 707 if (pending_render_view_host_) |
| 691 CancelPending(); | 708 CancelPending(); |
| 692 cross_navigation_pending_ = false; | 709 cross_navigation_pending_ = false; |
| 693 } | 710 } |
| 694 | 711 |
| 695 // This will possibly create (set to NULL) a Web UI object for the pending | |
| 696 // page. We'll use this later to give the page special access. This must | |
| 697 // happen before the new renderer is created below so it will get bindings. | |
| 698 // It must also happen after the above conditional call to CancelPending(), | |
| 699 // otherwise CancelPending may clear the pending_web_ui_ and the page will | |
| 700 // not have it's bindings set appropriately. | |
| 701 pending_web_ui_.reset(delegate_->CreateWebUIForRenderManager(entry.GetURL())); | |
| 702 | |
| 703 // render_view_host_ will not be deleted before the end of this method, so we | 712 // render_view_host_ will not be deleted before the end of this method, so we |
| 704 // don't have to worry about this SiteInstance's ref count dropping to zero. | 713 // don't have to worry about this SiteInstance's ref count dropping to zero. |
| 705 SiteInstance* curr_instance = render_view_host_->GetSiteInstance(); | 714 SiteInstance* curr_instance = render_view_host_->GetSiteInstance(); |
| 706 | 715 |
| 707 // Determine if we need a new SiteInstance for this entry. | 716 // Determine if we need a new SiteInstance for this entry. |
| 708 // Again, new_instance won't be deleted before the end of this method, so it | 717 // Again, new_instance won't be deleted before the end of this method, so it |
| 709 // is safe to use a normal pointer here. | 718 // is safe to use a normal pointer here. |
| 710 SiteInstance* new_instance = curr_instance; | 719 SiteInstance* new_instance = curr_instance; |
| 711 bool force_swap = ShouldSwapProcessesForNavigation( | 720 const content::NavigationEntry* curr_entry = |
| 712 delegate_->GetLastCommittedNavigationEntryForRenderManager(), &entry); | 721 delegate_->GetLastCommittedNavigationEntryForRenderManager(); |
| 722 bool force_swap = ShouldSwapProcessesForNavigation(curr_entry, &entry); | |
| 713 if (ShouldTransitionCrossSite() || force_swap) | 723 if (ShouldTransitionCrossSite() || force_swap) |
| 714 new_instance = GetSiteInstanceForEntry(entry, curr_instance); | 724 new_instance = GetSiteInstanceForEntry(entry, curr_instance); |
| 715 | 725 |
| 716 if (new_instance != curr_instance || force_swap) { | 726 if (new_instance != curr_instance || force_swap) { |
| 717 // New SiteInstance. | 727 // New SiteInstance. |
| 718 DCHECK(!cross_navigation_pending_); | 728 DCHECK(!cross_navigation_pending_); |
| 719 | 729 |
| 730 // This will possibly create (set to NULL) a Web UI object for the pending | |
| 731 // page. We'll use this later to give the page special access. This must | |
| 732 // happen before the new renderer is created below so it will get bindings. | |
| 733 // It must also happen after the above conditional call to CancelPending(), | |
| 734 // otherwise CancelPending may clear the pending_web_ui_ and the page will | |
| 735 // not have it's bindings set appropriately. | |
|
Dan Beam
2012/04/21 02:53:07
its
Evan Stade
2012/04/24 17:52:40
Done.
| |
| 736 pending_web_ui_ = delegate_->CreateWebUIForRenderManager(entry.GetURL()); | |
| 737 | |
| 720 // Create a pending RVH and navigate it. | 738 // Create a pending RVH and navigate it. |
| 721 bool success = CreatePendingRenderView(entry, new_instance); | 739 bool success = CreatePendingRenderView(entry, new_instance); |
| 722 if (!success) | 740 if (!success) |
| 723 return NULL; | 741 return NULL; |
| 724 | 742 |
| 725 // Check if our current RVH is live before we set up a transition. | 743 // Check if our current RVH is live before we set up a transition. |
| 726 if (!render_view_host_->IsRenderViewLive()) { | 744 if (!render_view_host_->IsRenderViewLive()) { |
| 727 if (!cross_navigation_pending_) { | 745 if (!cross_navigation_pending_) { |
| 728 // The current RVH is not live. There's no reason to sit around with a | 746 // The current RVH is not live. There's no reason to sit around with a |
| 729 // sad tab or a newly created RVH while we wait for the pending RVH to | 747 // sad tab or a newly created RVH while we wait for the pending RVH to |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 759 DCHECK(!cross_navigation_pending_); | 777 DCHECK(!cross_navigation_pending_); |
| 760 cross_navigation_pending_ = true; | 778 cross_navigation_pending_ = true; |
| 761 | 779 |
| 762 // Tell the old render view to run its onbeforeunload handler, since it | 780 // Tell the old render view to run its onbeforeunload handler, since it |
| 763 // doesn't otherwise know that the cross-site request is happening. This | 781 // doesn't otherwise know that the cross-site request is happening. This |
| 764 // will trigger a call to ShouldClosePage with the reply. | 782 // will trigger a call to ShouldClosePage with the reply. |
| 765 render_view_host_->FirePageBeforeUnload(true); | 783 render_view_host_->FirePageBeforeUnload(true); |
| 766 | 784 |
| 767 return pending_render_view_host_; | 785 return pending_render_view_host_; |
| 768 } else { | 786 } else { |
| 769 if (pending_web_ui_.get() && render_view_host_->IsRenderViewLive()) | 787 if (ShouldReuseWebUI(curr_entry, &entry)) |
| 788 pending_web_ui_ = web_ui_.get(); | |
| 789 else | |
| 790 pending_web_ui_ = delegate_->CreateWebUIForRenderManager(entry.GetURL()); | |
| 791 | |
| 792 if (pending_web_ui_ && render_view_host_->IsRenderViewLive()) | |
| 770 pending_web_ui_->GetController()->RenderViewReused(render_view_host_); | 793 pending_web_ui_->GetController()->RenderViewReused(render_view_host_); |
| 771 | 794 |
| 772 // The renderer can exit view source mode when any error or cancellation | 795 // The renderer can exit view source mode when any error or cancellation |
| 773 // happen. We must overwrite to recover the mode. | 796 // happen. We must overwrite to recover the mode. |
| 774 if (entry.IsViewSourceMode()) { | 797 if (entry.IsViewSourceMode()) { |
| 775 render_view_host_->Send( | 798 render_view_host_->Send( |
| 776 new ViewMsg_EnableViewSourceMode(render_view_host_->GetRoutingID())); | 799 new ViewMsg_EnableViewSourceMode(render_view_host_->GetRoutingID())); |
| 777 } | 800 } |
| 778 } | 801 } |
| 779 | 802 |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 803 pending_render_view_host->CancelSuspendedNavigations(); | 826 pending_render_view_host->CancelSuspendedNavigations(); |
| 804 | 827 |
| 805 // We can pass -1,-1 because there is no pending response in the | 828 // We can pass -1,-1 because there is no pending response in the |
| 806 // ResourceDispatcherHost to unpause. | 829 // ResourceDispatcherHost to unpause. |
| 807 pending_render_view_host->SwapOut(-1, -1); | 830 pending_render_view_host->SwapOut(-1, -1); |
| 808 } else { | 831 } else { |
| 809 // We won't be coming back, so shut this one down. | 832 // We won't be coming back, so shut this one down. |
| 810 pending_render_view_host->Shutdown(); | 833 pending_render_view_host->Shutdown(); |
| 811 } | 834 } |
| 812 | 835 |
| 813 pending_web_ui_.reset(); | 836 FreePendingWebUI(); |
| 814 } | 837 } |
| 815 | 838 |
| 816 void RenderViewHostManager::RenderViewDeleted(RenderViewHost* rvh) { | 839 void RenderViewHostManager::RenderViewDeleted(RenderViewHost* rvh) { |
| 817 // We are doing this in order to work around and to track a crasher | 840 // We are doing this in order to work around and to track a crasher |
| 818 // (http://crbug.com/23411) where it seems that pending_render_view_host_ is | 841 // (http://crbug.com/23411) where it seems that pending_render_view_host_ is |
| 819 // deleted (not sure from where) but not NULLed. | 842 // deleted (not sure from where) but not NULLed. |
| 820 if (rvh == pending_render_view_host_) { | 843 if (rvh == pending_render_view_host_) { |
| 821 // If you hit this NOTREACHED, please report it in the following bug | 844 // If you hit this NOTREACHED, please report it in the following bug |
| 822 // http://crbug.com/23411 Make sure to include what you were doing when it | 845 // http://crbug.com/23411 Make sure to include what you were doing when it |
| 823 // happened (navigating to a new page, closing a tab...) and if you can | 846 // happened (navigating to a new page, closing a tab...) and if you can |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 841 } | 864 } |
| 842 } | 865 } |
| 843 | 866 |
| 844 bool RenderViewHostManager::IsSwappedOut(RenderViewHost* rvh) { | 867 bool RenderViewHostManager::IsSwappedOut(RenderViewHost* rvh) { |
| 845 if (!rvh->GetSiteInstance()) | 868 if (!rvh->GetSiteInstance()) |
| 846 return false; | 869 return false; |
| 847 | 870 |
| 848 return swapped_out_hosts_.find(rvh->GetSiteInstance()->GetId()) != | 871 return swapped_out_hosts_.find(rvh->GetSiteInstance()->GetId()) != |
| 849 swapped_out_hosts_.end(); | 872 swapped_out_hosts_.end(); |
| 850 } | 873 } |
| 874 | |
| 875 void RenderViewHostManager::FreePendingWebUI() { | |
| 876 if (pending_web_ui_ && pending_web_ui_ != web_ui_.get()) | |
| 877 delete pending_web_ui_; | |
| 878 | |
| 879 pending_web_ui_ = NULL; | |
| 880 } | |
| OLD | NEW |