Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1006)

Side by Side Diff: content/browser/frame_host/render_view_host_manager.cc

Issue 57433010: Prevent creating a swapped out RVH in the same SiteInstance as the current one. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/frame_host/render_view_host_manager.h" 5 #include "content/browser/frame_host/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/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 return 484 return
485 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) && 485 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) &&
486 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab); 486 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab);
487 } 487 }
488 488
489 bool RenderViewHostManager::ShouldSwapProcessesForNavigation( 489 bool RenderViewHostManager::ShouldSwapProcessesForNavigation(
490 const NavigationEntry* curr_entry, 490 const NavigationEntry* curr_entry,
491 const NavigationEntryImpl* new_entry) const { 491 const NavigationEntryImpl* new_entry) const {
492 DCHECK(new_entry); 492 DCHECK(new_entry);
493 493
494 // If new_entry already has a SiteInstance, assume it is correct and use it.
495 if (new_entry->site_instance())
496 return false;
497
494 // Check for reasons to swap processes even if we are in a process model that 498 // Check for reasons to swap processes even if we are in a process model that
495 // doesn't usually swap (e.g., process-per-tab). 499 // doesn't usually swap (e.g., process-per-tab).
496 500
497 // For security, we should transition between processes when one is a Web UI 501 // We use the effective URL here, since that's what is used in the
498 // page and one isn't. If there's no curr_entry, check the current RVH's 502 // SiteInstance's site and when we later call IsSameWebSite. If there is no
499 // site, which might already be committed to a Web UI URL (such as the NTP). 503 // curr_entry, check the current SiteInstance's site, which might already be
500 const GURL& current_url = (curr_entry) ? curr_entry->GetURL() : 504 // committed to a Web UI URL (such as the NTP).
501 render_view_host_->GetSiteInstance()->GetSiteURL();
502 BrowserContext* browser_context = 505 BrowserContext* browser_context =
503 delegate_->GetControllerForRenderManager().GetBrowserContext(); 506 delegate_->GetControllerForRenderManager().GetBrowserContext();
507 const GURL& current_url = (curr_entry) ?
508 SiteInstanceImpl::GetEffectiveURL(browser_context, curr_entry->GetURL()) :
509 render_view_host_->GetSiteInstance()->GetSiteURL();
510 const GURL& new_url = SiteInstanceImpl::GetEffectiveURL(browser_context,
511 new_entry->GetURL());
512
513 // For security, we should transition between processes when one is a Web UI
514 // page and one isn't.
504 if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL( 515 if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
505 browser_context, current_url)) { 516 browser_context, current_url)) {
506 // Force swap if it's not an acceptable URL for Web UI. 517 // Force swap if it's not an acceptable URL for Web UI.
507 // Here, data URLs are never allowed. 518 // Here, data URLs are never allowed.
508 if (!WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI( 519 if (!WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
509 browser_context, new_entry->GetURL(), false)) { 520 browser_context, new_url, false)) {
510 return true; 521 return true;
511 } 522 }
512 } else { 523 } else {
513 // Force swap if it's a Web UI URL. 524 // Force swap if it's a Web UI URL.
514 if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL( 525 if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
515 browser_context, new_entry->GetURL())) { 526 browser_context, new_url)) {
516 return true; 527 return true;
517 } 528 }
518 } 529 }
519 530
531 // Check with the content client as well. Important to pass current_url here,
532 // which uses the SiteInstance's site if there is no curr_entry.
520 if (GetContentClient()->browser()->ShouldSwapProcessesForNavigation( 533 if (GetContentClient()->browser()->ShouldSwapProcessesForNavigation(
521 render_view_host_->GetSiteInstance(), 534 render_view_host_->GetSiteInstance(), current_url, new_url)) {
522 curr_entry ? curr_entry->GetURL() : GURL(),
523 new_entry->GetURL())) {
524 return true; 535 return true;
525 } 536 }
526 537
527 if (!curr_entry) 538 if (!curr_entry)
528 return false; 539 return false;
529 540
530 // We can't switch a RenderView between view source and non-view source mode 541 // We can't switch a RenderView between view source and non-view source mode
531 // without screwing up the session history sometimes (when navigating between 542 // without screwing up the session history sometimes (when navigating between
532 // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat 543 // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat
533 // it as a new navigation). So require a view switch. 544 // it as a new navigation). So require a view switch.
(...skipping 10 matching lines...) Expand all
544 delegate_->GetControllerForRenderManager(); 555 delegate_->GetControllerForRenderManager();
545 return curr_entry && web_ui_.get() && 556 return curr_entry && web_ui_.get() &&
546 (WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( 557 (WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
547 controller.GetBrowserContext(), curr_entry->GetURL()) == 558 controller.GetBrowserContext(), curr_entry->GetURL()) ==
548 WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( 559 WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
549 controller.GetBrowserContext(), new_entry->GetURL())); 560 controller.GetBrowserContext(), new_entry->GetURL()));
550 } 561 }
551 562
552 SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry( 563 SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
553 const NavigationEntryImpl& entry, 564 const NavigationEntryImpl& entry,
554 SiteInstance* curr_instance) { 565 SiteInstance* curr_instance,
555 // NOTE: This is only called when ShouldTransitionCrossSite is true. 566 bool force_swap) {
556 567 // Determine which SiteInstance to use for navigating to |entry|.
557 const GURL& dest_url = entry.GetURL(); 568 const GURL& dest_url = entry.GetURL();
558 NavigationControllerImpl& controller = 569 NavigationControllerImpl& controller =
559 delegate_->GetControllerForRenderManager(); 570 delegate_->GetControllerForRenderManager();
560 BrowserContext* browser_context = controller.GetBrowserContext(); 571 BrowserContext* browser_context = controller.GetBrowserContext();
561 572
573 // If a swap is required, we need to force the SiteInstance AND
574 // BrowsingInstance to be different ones, using CreateForURL.
nasko 2013/11/05 18:41:00 Why is that? Are we guaranteed in this case that t
Charlie Reis 2013/11/05 19:13:15 Yep, that's what the poorly named ShouldSwapProces
575 if (force_swap) {
576 // We shouldn't be forcing a swap if an entry already has a SiteInstance.
577 CHECK(!entry.site_instance());
578 return SiteInstance::CreateForURL(browser_context, dest_url);
579 }
580
562 // If the entry has an instance already we should use it. 581 // If the entry has an instance already we should use it.
563 if (entry.site_instance()) 582 if (entry.site_instance())
564 return entry.site_instance(); 583 return entry.site_instance();
565 584
566 // (UGLY) HEURISTIC, process-per-site only: 585 // (UGLY) HEURISTIC, process-per-site only:
567 // 586 //
568 // If this navigation is generated, then it probably corresponds to a search 587 // If this navigation is generated, then it probably corresponds to a search
569 // query. Given that search results typically lead to users navigating to 588 // query. Given that search results typically lead to users navigating to
570 // other sites, we don't really want to use the search engine hostname to 589 // other sites, we don't really want to use the search engine hostname to
571 // determine the site instance for this navigation. 590 // determine the site instance for this navigation.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 return SiteInstance::CreateForURL(browser_context, dest_url); 697 return SiteInstance::CreateForURL(browser_context, dest_url);
679 } 698 }
680 699
681 // Use the current SiteInstance for same site navigations, as long as the 700 // Use the current SiteInstance for same site navigations, as long as the
682 // process type is correct. (The URL may have been installed as an app since 701 // process type is correct. (The URL may have been installed as an app since
683 // the last time we visited it.) 702 // the last time we visited it.)
684 if (SiteInstance::IsSameWebSite(browser_context, current_url, dest_url) && 703 if (SiteInstance::IsSameWebSite(browser_context, current_url, dest_url) &&
685 !static_cast<SiteInstanceImpl*>(curr_instance)->HasWrongProcessForURL( 704 !static_cast<SiteInstanceImpl*>(curr_instance)->HasWrongProcessForURL(
686 dest_url)) { 705 dest_url)) {
687 return curr_instance; 706 return curr_instance;
688 } else if (ShouldSwapProcessesForNavigation(curr_entry, &entry)) {
689 // When we're swapping, we need to force the site instance AND browsing
690 // instance to be different ones. This addresses special cases where we use
691 // a single BrowsingInstance for all pages of a certain type (e.g., New Tab
692 // Pages), keeping them in the same process. When you navigate away from
693 // that page, we want to explicity ignore that BrowsingInstance and group
694 // this page into the appropriate SiteInstance for its URL.
695 return SiteInstance::CreateForURL(browser_context, dest_url);
696 } else {
697 // Start the new renderer in a new SiteInstance, but in the current
698 // BrowsingInstance. It is important to immediately give this new
699 // SiteInstance to a RenderViewHost (if it is different than our current
700 // SiteInstance), so that it is ref counted. This will happen in
701 // CreateRenderView.
702 return curr_instance->GetRelatedSiteInstance(dest_url);
703 } 707 }
708
709 // Start the new renderer in a new SiteInstance, but in the current
710 // BrowsingInstance. It is important to immediately give this new
711 // SiteInstance to a RenderViewHost (if it is different than our current
712 // SiteInstance), so that it is ref counted. This will happen in
713 // CreateRenderView.
714 return curr_instance->GetRelatedSiteInstance(dest_url);
704 } 715 }
705 716
706 int RenderViewHostManager::CreateRenderView( 717 int RenderViewHostManager::CreateRenderView(
707 SiteInstance* instance, 718 SiteInstance* instance,
708 int opener_route_id, 719 int opener_route_id,
709 bool swapped_out, 720 bool swapped_out,
710 bool hidden) { 721 bool hidden) {
711 CHECK(instance); 722 CHECK(instance);
712 DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden. 723 DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden.
713 724
725 // We are creating a pending or swapped out RVH here. We should never create
726 // it in the same SiteInstance as our current RVH.
727 CHECK_NE(render_view_host_->GetSiteInstance(), instance);
728
714 // Check if we've already created an RVH for this SiteInstance. If so, try 729 // Check if we've already created an RVH for this SiteInstance. If so, try
715 // to re-use the existing one, which has already been initialized. We'll 730 // to re-use the existing one, which has already been initialized. We'll
716 // remove it from the list of swapped out hosts if it commits. 731 // remove it from the list of swapped out hosts if it commits.
717 RenderViewHostImpl* new_render_view_host = static_cast<RenderViewHostImpl*>( 732 RenderViewHostImpl* new_render_view_host = static_cast<RenderViewHostImpl*>(
718 GetSwappedOutRenderViewHost(instance)); 733 GetSwappedOutRenderViewHost(instance));
719 if (new_render_view_host) { 734 if (new_render_view_host) {
720 // Prevent the process from exiting while we're trying to use it. 735 // Prevent the process from exiting while we're trying to use it.
721 if (!swapped_out) 736 if (!swapped_out)
722 new_render_view_host->GetProcess()->AddPendingView(); 737 new_render_view_host->GetProcess()->AddPendingView();
723 } else { 738 } else {
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 // don't have to worry about this SiteInstance's ref count dropping to zero. 926 // don't have to worry about this SiteInstance's ref count dropping to zero.
912 SiteInstance* curr_instance = render_view_host_->GetSiteInstance(); 927 SiteInstance* curr_instance = render_view_host_->GetSiteInstance();
913 928
914 // Determine if we need a new SiteInstance for this entry. 929 // Determine if we need a new SiteInstance for this entry.
915 // Again, new_instance won't be deleted before the end of this method, so it 930 // Again, new_instance won't be deleted before the end of this method, so it
916 // is safe to use a normal pointer here. 931 // is safe to use a normal pointer here.
917 SiteInstance* new_instance = curr_instance; 932 SiteInstance* new_instance = curr_instance;
918 const NavigationEntry* curr_entry = 933 const NavigationEntry* curr_entry =
919 delegate_->GetLastCommittedNavigationEntryForRenderManager(); 934 delegate_->GetLastCommittedNavigationEntryForRenderManager();
920 bool is_guest_scheme = curr_instance->GetSiteURL().SchemeIs(kGuestScheme); 935 bool is_guest_scheme = curr_instance->GetSiteURL().SchemeIs(kGuestScheme);
921 bool force_swap = ShouldSwapProcessesForNavigation(curr_entry, &entry); 936 bool force_swap = !is_guest_scheme &&
937 ShouldSwapProcessesForNavigation(curr_entry, &entry);
922 if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap)) 938 if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap))
923 new_instance = GetSiteInstanceForEntry(entry, curr_instance); 939 new_instance = GetSiteInstanceForEntry(entry, curr_instance, force_swap);
924 940
925 if (!is_guest_scheme && (new_instance != curr_instance || force_swap)) { 941 // If force_swap is true, we must use a different SiteInstance. If we didn't,
942 // we would have two RenderViewHosts in the same SiteInstance and the same
943 // tab, resulting in page_id conflicts for their NavigationEntries.
944 if (force_swap)
945 CHECK_NE(new_instance, curr_instance);
946
947 if (new_instance != curr_instance) {
926 // New SiteInstance. 948 // New SiteInstance.
927 DCHECK(!cross_navigation_pending_); 949 DCHECK(!cross_navigation_pending_);
928 950
929 // This will possibly create (set to NULL) a Web UI object for the pending 951 // This will possibly create (set to NULL) a Web UI object for the pending
930 // page. We'll use this later to give the page special access. This must 952 // page. We'll use this later to give the page special access. This must
931 // happen before the new renderer is created below so it will get bindings. 953 // happen before the new renderer is created below so it will get bindings.
932 // It must also happen after the above conditional call to CancelPending(), 954 // It must also happen after the above conditional call to CancelPending(),
933 // otherwise CancelPending may clear the pending_web_ui_ and the page will 955 // otherwise CancelPending may clear the pending_web_ui_ and the page will
934 // not have its bindings set appropriately. 956 // not have its bindings set appropriately.
935 SetPendingWebUI(entry); 957 SetPendingWebUI(entry);
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
1110 RenderViewHostImpl* RenderViewHostManager::GetSwappedOutRenderViewHost( 1132 RenderViewHostImpl* RenderViewHostManager::GetSwappedOutRenderViewHost(
1111 SiteInstance* instance) { 1133 SiteInstance* instance) {
1112 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId()); 1134 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId());
1113 if (iter != swapped_out_hosts_.end()) 1135 if (iter != swapped_out_hosts_.end())
1114 return iter->second; 1136 return iter->second;
1115 1137
1116 return NULL; 1138 return NULL;
1117 } 1139 }
1118 1140
1119 } // namespace content 1141 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698