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

Unified Diff: content/browser/frame_host/render_frame_host_manager.cc

Issue 967383002: PlzNavigate: Avoid duplicate SiteInstance creation during navigation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase + content-exporting SiteInstanceDescriptor. Created 5 years, 8 months 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
« no previous file with comments | « content/browser/frame_host/render_frame_host_manager.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/frame_host/render_frame_host_manager.cc
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index 86ac6e938799d59bc6f11dcbd3a0f6606efab07a..827b034cab070cd74e0f461a82664bc14abc77a4 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -743,11 +743,18 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
SiteInstance* current_site_instance = render_frame_host_->GetSiteInstance();
+ SiteInstance* candidate_site_instance =
+ speculative_render_frame_host_
+ ? speculative_render_frame_host_->GetSiteInstance()
+ : nullptr;
+
scoped_refptr<SiteInstance> dest_site_instance = GetSiteInstanceForNavigation(
request.common_params().url, request.source_site_instance(),
- request.dest_site_instance(), request.common_params().transition,
+ request.dest_site_instance(), candidate_site_instance,
+ request.common_params().transition,
request.restore_type() != NavigationEntryImpl::RESTORE_NONE,
request.is_view_source());
+
// The appropriate RenderFrameHost to commit the navigation.
RenderFrameHostImpl* navigation_rfh = nullptr;
@@ -893,6 +900,15 @@ void RenderFrameHostManager::Observe(
}
}
+RenderFrameHostManager::SiteInstanceDescriptor::SiteInstanceDescriptor(
+ BrowserContext* browser_context,
+ GURL dest_url,
+ bool related_to_current)
+ : existing_site_instance(nullptr),
+ new_is_related_to_current(related_to_current) {
+ new_site_url = SiteInstance::GetSiteForURL(browser_context, dest_url);
+}
+
// static
bool RenderFrameHostManager::ClearProxiesInSiteInstance(
int32 site_instance_id,
@@ -1025,11 +1041,11 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation(
const GURL& dest_url,
SiteInstance* source_instance,
SiteInstance* dest_instance,
+ SiteInstance* candidate_instance,
ui::PageTransition transition,
bool dest_is_restore,
bool dest_is_view_source_mode) {
SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
- SiteInstance* new_instance = current_instance;
// We do not currently swap processes for navigations in webview tag guests.
if (current_instance->GetSiteURL().SchemeIs(kGuestScheme))
@@ -1057,21 +1073,28 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation(
dest_instance,
SiteInstanceImpl::GetEffectiveURL(browser_context, dest_url),
dest_is_view_source_mode);
+ SiteInstanceDescriptor new_instance_descriptor =
+ SiteInstanceDescriptor(current_instance);
if (ShouldTransitionCrossSite() || force_swap) {
- new_instance = GetSiteInstanceForURL(
- dest_url, source_instance, current_instance, dest_instance,
- transition, dest_is_restore, dest_is_view_source_mode, force_swap);
+ new_instance_descriptor = DetermineSiteInstanceForURL(
+ dest_url, source_instance, current_instance, dest_instance, transition,
+ dest_is_restore, dest_is_view_source_mode, force_swap);
}
- // If force_swap is true, we must use a different SiteInstance. If we didn't,
- // we would have two RenderFrameHosts in the same SiteInstance and the same
- // frame, resulting in page_id conflicts for their NavigationEntries.
+ SiteInstance* new_instance =
+ ConvertToSiteInstance(new_instance_descriptor, candidate_instance);
+
+ // If |force_swap| is true, we must use a different SiteInstance than the
+ // current one. If we didn't, we would have two RenderFrameHosts in the same
+ // SiteInstance and the same frame, resulting in page_id conflicts for their
+ // NavigationEntries.
if (force_swap)
CHECK_NE(new_instance, current_instance);
return new_instance;
}
-SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
+RenderFrameHostManager::SiteInstanceDescriptor
+RenderFrameHostManager::DetermineSiteInstanceForURL(
const GURL& dest_url,
SiteInstance* source_instance,
SiteInstance* current_instance,
@@ -1080,6 +1103,8 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
bool dest_is_restore,
bool dest_is_view_source_mode,
bool force_browsing_instance_swap) {
+ SiteInstanceImpl* current_instance_impl =
+ static_cast<SiteInstanceImpl*>(current_instance);
NavigationControllerImpl& controller =
delegate_->GetControllerForRenderManager();
BrowserContext* browser_context = controller.GetBrowserContext();
@@ -1091,13 +1116,13 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
CHECK(!dest_instance->IsRelatedSiteInstance(
render_frame_host_->GetSiteInstance()));
}
- return dest_instance;
+ return SiteInstanceDescriptor(dest_instance);
}
// If a swap is required, we need to force the SiteInstance AND
// BrowsingInstance to be different ones, using CreateForURL.
if (force_browsing_instance_swap)
- return SiteInstance::CreateForURL(browser_context, dest_url);
+ return SiteInstanceDescriptor(browser_context, dest_url, false);
// (UGLY) HEURISTIC, process-per-site only:
//
@@ -1112,17 +1137,14 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kProcessPerSite) &&
ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_GENERATED)) {
- return current_instance;
+ return SiteInstanceDescriptor(current_instance_impl);
}
- SiteInstanceImpl* current_site_instance =
- static_cast<SiteInstanceImpl*>(current_instance);
-
// If we haven't used our SiteInstance (and thus RVH) yet, then we can use it
// for this entry. We won't commit the SiteInstance to this site until the
// navigation commits (in DidNavigate), unless the navigation entry was
// restored or it's a Web UI as described below.
- if (!current_site_instance->HasSite()) {
+ if (!current_instance_impl->HasSite()) {
// If we've already created a SiteInstance for our destination, we don't
// want to use this unused SiteInstance; use the existing one. (We don't
// do this check if the current_instance has a site, because for now, we
@@ -1137,30 +1159,30 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
bool use_process_per_site =
RenderProcessHost::ShouldUseProcessPerSite(browser_context, dest_url) &&
RenderProcessHostImpl::GetProcessHostForSite(browser_context, dest_url);
- if (current_site_instance->HasRelatedSiteInstance(dest_url) ||
+ if (current_instance_impl->HasRelatedSiteInstance(dest_url) ||
use_process_per_site) {
- return current_site_instance->GetRelatedSiteInstance(dest_url);
+ return SiteInstanceDescriptor(browser_context, dest_url, true);
}
// For extensions, Web UI URLs (such as the new tab page), and apps we do
- // not want to use the current_instance if it has no site, since it will
- // have a RenderProcessHost of PRIV_NORMAL. Create a new SiteInstance for
- // this URL instead (with the correct process type).
- if (current_site_instance->HasWrongProcessForURL(dest_url))
- return current_site_instance->GetRelatedSiteInstance(dest_url);
+ // not want to use the |current_instance_impl| if it has no site, since it
+ // will have a RenderProcessHost of PRIV_NORMAL. Create a new SiteInstance
+ // for this URL instead (with the correct process type).
+ if (current_instance_impl->HasWrongProcessForURL(dest_url))
+ return SiteInstanceDescriptor(browser_context, dest_url, true);
// View-source URLs must use a new SiteInstance and BrowsingInstance.
// TODO(nasko): This is the same condition as later in the function. This
// should be taken into account when refactoring this method as part of
// http://crbug.com/123007.
if (dest_is_view_source_mode)
- return SiteInstance::CreateForURL(browser_context, dest_url);
+ return SiteInstanceDescriptor(browser_context, dest_url, false);
// If we are navigating from a blank SiteInstance to a WebUI, make sure we
// create a new SiteInstance.
if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
browser_context, dest_url)) {
- return SiteInstance::CreateForURL(browser_context, dest_url);
+ return SiteInstanceDescriptor(browser_context, dest_url, false);
}
// Normally the "site" on the SiteInstance is set lazily when the load
@@ -1179,10 +1201,10 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
// See http://crbug.com/386542.
if (dest_is_restore &&
GetContentClient()->browser()->ShouldAssignSiteForURL(dest_url)) {
- current_site_instance->SetSite(dest_url);
+ current_instance_impl->SetSite(dest_url);
}
- return current_site_instance;
+ return SiteInstanceDescriptor(current_instance_impl);
}
// Otherwise, only create a new SiteInstance for a cross-site navigation.
@@ -1191,7 +1213,7 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
// will be able to enforce that all entries in a SiteInstance actually have
// the same site, and it will be safe to compare the URL against the
// SiteInstance's site, as follows:
- // const GURL& current_url = current_instance->site();
+ // const GURL& current_url = current_instance_impl->site();
// For now, though, we're in a hybrid model where you only switch
// SiteInstances if you type in a cross-site URL. This means we have to
// compare the entry's URL to the last committed entry's URL.
@@ -1210,7 +1232,7 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
if (current_entry &&
current_entry->IsViewSourceMode() != dest_is_view_source_mode &&
!IsRendererDebugURL(dest_url)) {
- return SiteInstance::CreateForURL(browser_context, dest_url);
+ return SiteInstanceDescriptor(browser_context, dest_url, false);
}
// Use the source SiteInstance in case of data URLs or about:blank pages,
@@ -1218,17 +1240,18 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
// SiteInstance.
GURL about_blank(url::kAboutBlankURL);
if (source_instance &&
- (dest_url == about_blank || dest_url.scheme() == url::kDataScheme))
- return source_instance;
+ (dest_url == about_blank || dest_url.scheme() == url::kDataScheme)) {
+ return SiteInstanceDescriptor(source_instance);
+ }
// Use the current SiteInstance for same site navigations, as long as the
// process type is correct. (The URL may have been installed as an app since
// the last time we visited it.)
const GURL& current_url =
- GetCurrentURLForSiteInstance(current_instance, current_entry);
+ GetCurrentURLForSiteInstance(current_instance_impl, current_entry);
if (SiteInstance::IsSameWebSite(browser_context, current_url, dest_url) &&
- !current_site_instance->HasWrongProcessForURL(dest_url)) {
- return current_instance;
+ !current_instance_impl->HasWrongProcessForURL(dest_url)) {
+ return SiteInstanceDescriptor(current_instance_impl);
}
// Start the new renderer in a new SiteInstance, but in the current
@@ -1236,7 +1259,36 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
// SiteInstance to a RenderViewHost (if it is different than our current
// SiteInstance), so that it is ref counted. This will happen in
// CreateRenderView.
- return current_instance->GetRelatedSiteInstance(dest_url);
+ return SiteInstanceDescriptor(browser_context, dest_url, true);
+}
+
+SiteInstance* RenderFrameHostManager::ConvertToSiteInstance(
+ const SiteInstanceDescriptor& descriptor,
+ SiteInstance* candidate_instance) {
+ SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
+
+ // Note: If the |candidate_instance| matches the descriptor, it will already
+ // be set to |descriptor.existing_site_instance|.
+ if (descriptor.existing_site_instance)
+ return descriptor.existing_site_instance;
+
+ // Note: If the |candidate_instance| matches the descriptor,
+ // GetRelatedSiteInstance will return it.
+ if (descriptor.new_is_related_to_current)
+ return current_instance->GetRelatedSiteInstance(descriptor.new_site_url);
+
+ // At this point we know an unrelated site instance must be returned. First
+ // check if the candidate matches.
+ if (candidate_instance &&
+ !current_instance->IsRelatedSiteInstance(candidate_instance) &&
+ candidate_instance->GetSiteURL() == descriptor.new_site_url) {
+ return candidate_instance;
+ }
+
+ // Otherwise return a newly created one.
+ return SiteInstance::CreateForURL(
+ delegate_->GetControllerForRenderManager().GetBrowserContext(),
+ descriptor.new_site_url);
}
const GURL& RenderFrameHostManager::GetCurrentURLForSiteInstance(
@@ -1820,7 +1872,7 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation(
- dest_url, source_instance, dest_instance, transition,
+ dest_url, source_instance, dest_instance, nullptr, transition,
dest_is_restore, dest_is_view_source_mode);
const NavigationEntry* current_entry =
« no previous file with comments | « content/browser/frame_host/render_frame_host_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698