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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/frame_host/render_view_host_manager.cc
diff --git a/content/browser/frame_host/render_view_host_manager.cc b/content/browser/frame_host/render_view_host_manager.cc
index a8473cd19969eb4c3abaf0180bae9767008847bd..91da5b1ef4a40f7423a60c1723bca4747b646ded 100644
--- a/content/browser/frame_host/render_view_host_manager.cc
+++ b/content/browser/frame_host/render_view_host_manager.cc
@@ -493,36 +493,47 @@ bool RenderViewHostManager::ShouldSwapProcessesForNavigation(
const NavigationEntryImpl* new_entry) const {
DCHECK(new_entry);
+ // If new_entry already has a SiteInstance, assume it is correct and use it.
+ if (new_entry->site_instance())
+ return false;
+
// Check for reasons to swap processes even if we are in a process model that
// doesn't usually swap (e.g., process-per-tab).
- // For security, we should transition between processes when one is a Web UI
- // page and one isn't. If there's no curr_entry, check the current RVH's
- // site, which might already be committed to a Web UI URL (such as the NTP).
- const GURL& current_url = (curr_entry) ? curr_entry->GetURL() :
- render_view_host_->GetSiteInstance()->GetSiteURL();
+ // We use the effective URL here, since that's what is used in the
+ // SiteInstance's site and when we later call IsSameWebSite. If there is no
+ // curr_entry, check the current SiteInstance's site, which might already be
+ // committed to a Web UI URL (such as the NTP).
BrowserContext* browser_context =
delegate_->GetControllerForRenderManager().GetBrowserContext();
+ const GURL& current_url = (curr_entry) ?
+ SiteInstanceImpl::GetEffectiveURL(browser_context, curr_entry->GetURL()) :
+ render_view_host_->GetSiteInstance()->GetSiteURL();
+ const GURL& new_url = SiteInstanceImpl::GetEffectiveURL(browser_context,
+ new_entry->GetURL());
+
+ // For security, we should transition between processes when one is a Web UI
+ // page and one isn't.
if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
browser_context, current_url)) {
// Force swap if it's not an acceptable URL for Web UI.
// Here, data URLs are never allowed.
if (!WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
- browser_context, new_entry->GetURL(), false)) {
+ browser_context, new_url, false)) {
return true;
}
} else {
// Force swap if it's a Web UI URL.
if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
- browser_context, new_entry->GetURL())) {
+ browser_context, new_url)) {
return true;
}
}
+ // Check with the content client as well. Important to pass current_url here,
+ // which uses the SiteInstance's site if there is no curr_entry.
if (GetContentClient()->browser()->ShouldSwapProcessesForNavigation(
- render_view_host_->GetSiteInstance(),
- curr_entry ? curr_entry->GetURL() : GURL(),
- new_entry->GetURL())) {
+ render_view_host_->GetSiteInstance(), current_url, new_url)) {
return true;
}
@@ -553,14 +564,22 @@ bool RenderViewHostManager::ShouldReuseWebUI(
SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
const NavigationEntryImpl& entry,
- SiteInstance* curr_instance) {
- // NOTE: This is only called when ShouldTransitionCrossSite is true.
-
+ SiteInstance* curr_instance,
+ bool force_browsing_instance_swap) {
+ // Determine which SiteInstance to use for navigating to |entry|.
const GURL& dest_url = entry.GetURL();
NavigationControllerImpl& controller =
delegate_->GetControllerForRenderManager();
BrowserContext* browser_context = controller.GetBrowserContext();
+ // If a swap is required, we need to force the SiteInstance AND
+ // BrowsingInstance to be different ones, using CreateForURL.
+ if (force_browsing_instance_swap) {
+ // We shouldn't be forcing a swap if an entry already has a SiteInstance.
+ CHECK(!entry.site_instance());
+ return SiteInstance::CreateForURL(browser_context, dest_url);
+ }
+
// If the entry has an instance already we should use it.
if (entry.site_instance())
return entry.site_instance();
@@ -687,22 +706,14 @@ SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
!static_cast<SiteInstanceImpl*>(curr_instance)->HasWrongProcessForURL(
dest_url)) {
return curr_instance;
- } else if (ShouldSwapProcessesForNavigation(curr_entry, &entry)) {
- // When we're swapping, we need to force the site instance AND browsing
- // instance to be different ones. This addresses special cases where we use
- // a single BrowsingInstance for all pages of a certain type (e.g., New Tab
- // Pages), keeping them in the same process. When you navigate away from
- // that page, we want to explicity ignore that BrowsingInstance and group
- // this page into the appropriate SiteInstance for its URL.
- return SiteInstance::CreateForURL(browser_context, dest_url);
- } else {
- // Start the new renderer in a new SiteInstance, but in the current
- // BrowsingInstance. It is important to immediately give this new
- // SiteInstance to a RenderViewHost (if it is different than our current
- // SiteInstance), so that it is ref counted. This will happen in
- // CreateRenderView.
- return curr_instance->GetRelatedSiteInstance(dest_url);
}
+
+ // Start the new renderer in a new SiteInstance, but in the current
+ // BrowsingInstance. It is important to immediately give this new
+ // SiteInstance to a RenderViewHost (if it is different than our current
+ // SiteInstance), so that it is ref counted. This will happen in
+ // CreateRenderView.
+ return curr_instance->GetRelatedSiteInstance(dest_url);
}
int RenderViewHostManager::CreateRenderView(
@@ -713,6 +724,10 @@ int RenderViewHostManager::CreateRenderView(
CHECK(instance);
DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden.
+ // We are creating a pending or swapped out RVH here. We should never create
+ // it in the same SiteInstance as our current RVH.
+ CHECK_NE(render_view_host_->GetSiteInstance(), instance);
+
// Check if we've already created an RVH for this SiteInstance. If so, try
// to re-use the existing one, which has already been initialized. We'll
// remove it from the list of swapped out hosts if it commits.
@@ -912,11 +927,18 @@ RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate(
const NavigationEntry* curr_entry =
delegate_->GetLastCommittedNavigationEntryForRenderManager();
bool is_guest_scheme = curr_instance->GetSiteURL().SchemeIs(kGuestScheme);
- bool force_swap = ShouldSwapProcessesForNavigation(curr_entry, &entry);
+ bool force_swap = !is_guest_scheme &&
+ ShouldSwapProcessesForNavigation(curr_entry, &entry);
if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap))
- new_instance = GetSiteInstanceForEntry(entry, curr_instance);
+ new_instance = GetSiteInstanceForEntry(entry, curr_instance, force_swap);
+
+ // If force_swap is true, we must use a different SiteInstance. If we didn't,
+ // we would have two RenderViewHosts in the same SiteInstance and the same
+ // tab, resulting in page_id conflicts for their NavigationEntries.
+ if (force_swap)
+ CHECK_NE(new_instance, curr_instance);
- if (!is_guest_scheme && (new_instance != curr_instance || force_swap)) {
+ if (new_instance != curr_instance) {
// New SiteInstance.
DCHECK(!cross_navigation_pending_);
« 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