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

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

Powered by Google App Engine
This is Rietveld 408576698