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 |