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

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

Issue 76063007: Clean up RenderViewHostManager swapping logic. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix nits 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 71c39282a6444bee1116ffc1c10be11c04b01171..e46124b2cc653d5e6e28b015c47ca8f8e2cf2634 100644
--- a/content/browser/frame_host/render_view_host_manager.cc
+++ b/content/browser/frame_host/render_view_host_manager.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/render_view_devtools_agent_host.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/frame_host/navigation_controller_impl.h"
@@ -491,8 +492,8 @@ bool RenderViewHostManager::ShouldTransitionCrossSite() {
!CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab);
}
-bool RenderViewHostManager::ShouldSwapProcessesForNavigation(
- const NavigationEntry* curr_entry,
+bool RenderViewHostManager::ShouldSwapBrowsingInstancesForNavigation(
+ const NavigationEntry* current_entry,
const NavigationEntryImpl* new_entry) const {
DCHECK(new_entry);
@@ -501,16 +502,18 @@ bool RenderViewHostManager::ShouldSwapProcessesForNavigation(
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).
+ // doesn't usually swap (e.g., process-per-tab). Any time we return true,
+ // the new_entry will be rendered in a new SiteInstance AND BrowsingInstance.
// 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).
+ // current_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()) :
+ const GURL& current_url = (current_entry) ?
+ SiteInstanceImpl::GetEffectiveURL(browser_context,
+ current_entry->GetURL()) :
render_view_host_->GetSiteInstance()->GetSiteURL();
const GURL& new_url = SiteInstanceImpl::GetEffectiveURL(browser_context,
new_entry->GetURL());
@@ -519,14 +522,14 @@ bool RenderViewHostManager::ShouldSwapProcessesForNavigation(
// 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.
+ // If so, force a swap if destination is not an acceptable URL for Web UI.
// Here, data URLs are never allowed.
if (!WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
browser_context, new_url, false)) {
return true;
}
} else {
- // Force swap if it's a Web UI URL.
+ // Force a swap if it's a Web UI URL.
if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
browser_context, new_url)) {
return true;
@@ -534,40 +537,38 @@ bool RenderViewHostManager::ShouldSwapProcessesForNavigation(
}
// 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(
+ // which uses the SiteInstance's site if there is no current_entry.
+ if (GetContentClient()->browser()->ShouldSwapBrowsingInstancesForNavigation(
render_view_host_->GetSiteInstance(), current_url, new_url)) {
return true;
}
- if (!curr_entry)
- return false;
-
// We can't switch a RenderView between view source and non-view source mode
// without screwing up the session history sometimes (when navigating between
- // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat
- // it as a new navigation). So require a view switch.
- if (curr_entry->IsViewSourceMode() != new_entry->IsViewSourceMode())
+ // "view-source:http://foo.com/" and "http://foo.com/", Blink doesn't treat
+ // it as a new navigation). So require a BrowsingInstance switch.
+ if (current_entry &&
+ current_entry->IsViewSourceMode() != new_entry->IsViewSourceMode())
return true;
return false;
}
bool RenderViewHostManager::ShouldReuseWebUI(
- const NavigationEntry* curr_entry,
+ const NavigationEntry* current_entry,
const NavigationEntryImpl* new_entry) const {
NavigationControllerImpl& controller =
delegate_->GetControllerForRenderManager();
- return curr_entry && web_ui_.get() &&
+ return current_entry && web_ui_.get() &&
(WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
- controller.GetBrowserContext(), curr_entry->GetURL()) ==
+ controller.GetBrowserContext(), current_entry->GetURL()) ==
WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
controller.GetBrowserContext(), new_entry->GetURL()));
}
SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
const NavigationEntryImpl& entry,
- SiteInstance* curr_instance,
+ SiteInstance* current_instance,
bool force_browsing_instance_swap) {
// Determine which SiteInstance to use for navigating to |entry|.
const GURL& dest_url = entry.GetURL();
@@ -600,23 +601,23 @@ SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerSite) &&
PageTransitionCoreTypeIs(entry.GetTransitionType(),
PAGE_TRANSITION_GENERATED)) {
- return curr_instance;
+ return current_instance;
}
- SiteInstanceImpl* curr_site_instance =
- static_cast<SiteInstanceImpl*>(curr_instance);
+ 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 (!curr_site_instance->HasSite()) {
+ if (!current_site_instance->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 curr_instance has a site, because for now, we want
- // to compare against the current URL and not the SiteInstance's site. In
- // this case, there is no current URL, so comparing against the site is ok.
- // See additional comments below.)
+ // do this check if the current_instance has a site, because for now, we
+ // want to compare against the current URL and not the SiteInstance's site.
+ // In this case, there is no current URL, so comparing against the site is
+ // ok. See additional comments below.)
//
// Also, if the URL should use process-per-site mode and there is an
// existing process for the site, we should use it. We can call
@@ -625,17 +626,17 @@ SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
bool use_process_per_site =
RenderProcessHost::ShouldUseProcessPerSite(browser_context, dest_url) &&
RenderProcessHostImpl::GetProcessHostForSite(browser_context, dest_url);
- if (curr_site_instance->HasRelatedSiteInstance(dest_url) ||
+ if (current_site_instance->HasRelatedSiteInstance(dest_url) ||
use_process_per_site) {
- return curr_site_instance->GetRelatedSiteInstance(dest_url);
+ return current_site_instance->GetRelatedSiteInstance(dest_url);
}
// For extensions, Web UI URLs (such as the new tab page), and apps we do
- // not want to use the curr_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 (curr_site_instance->HasWrongProcessForURL(dest_url))
- return curr_site_instance->GetRelatedSiteInstance(dest_url);
+ // 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);
// View-source URLs must use a new SiteInstance and BrowsingInstance.
// TODO(nasko): This is the same condition as later in the function. This
@@ -660,28 +661,28 @@ SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
// we need to set the site first, otherwise after a restore none of the
// pages would share renderers in process-per-site.
if (entry.restore_type() != NavigationEntryImpl::RESTORE_NONE)
- curr_site_instance->SetSite(dest_url);
+ current_site_instance->SetSite(dest_url);
- return curr_site_instance;
+ return current_site_instance;
}
- // Otherwise, only create a new SiteInstance for cross-site navigation.
+ // Otherwise, only create a new SiteInstance for a cross-site navigation.
// TODO(creis): Once we intercept links and script-based navigations, we
// 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 = curr_instance->site();
+ // const GURL& current_url = current_instance->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.
- NavigationEntry* curr_entry = controller.GetLastCommittedEntry();
+ NavigationEntry* current_entry = controller.GetLastCommittedEntry();
if (interstitial_page_) {
// The interstitial is currently the last committed entry, but we want to
// compare against the last non-interstitial entry.
- curr_entry = controller.GetEntryAtOffset(-1);
+ current_entry = controller.GetEntryAtOffset(-1);
}
- // If there is no last non-interstitial entry (and curr_instance already
+ // If there is no last non-interstitial entry (and current_instance already
// has a site), then we must have been opened from another tab. We want
// to compare against the URL of the page that opened us, but we can't
// get to it directly. The best we can do is check against the site of
@@ -691,14 +692,14 @@ SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
// to open a new tab to an interstitial-inducing URL, and then navigates
// the page to a different same-site URL. (This seems very unlikely in
// practice.)
- const GURL& current_url = (curr_entry) ? curr_entry->GetURL() :
- curr_instance->GetSiteURL();
+ const GURL& current_url = (current_entry) ? current_entry->GetURL() :
+ current_instance->GetSiteURL();
// View-source URLs must use a new SiteInstance and BrowsingInstance.
// TODO(creis): Refactor this method so this duplicated code isn't needed.
// See http://crbug.com/123007.
- if (curr_entry &&
- curr_entry->IsViewSourceMode() != entry.IsViewSourceMode()) {
+ if (current_entry &&
+ current_entry->IsViewSourceMode() != entry.IsViewSourceMode()) {
return SiteInstance::CreateForURL(browser_context, dest_url);
}
@@ -706,9 +707,8 @@ SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
// process type is correct. (The URL may have been installed as an app since
// the last time we visited it.)
if (SiteInstance::IsSameWebSite(browser_context, current_url, dest_url) &&
- !static_cast<SiteInstanceImpl*>(curr_instance)->HasWrongProcessForURL(
- dest_url)) {
- return curr_instance;
+ !current_site_instance->HasWrongProcessForURL(dest_url)) {
+ return current_instance;
}
// Start the new renderer in a new SiteInstance, but in the current
@@ -716,7 +716,7 @@ SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
// 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);
+ return current_instance->GetRelatedSiteInstance(dest_url);
}
int RenderViewHostManager::CreateRenderView(
@@ -779,8 +779,14 @@ bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host,
int opener_route_id) {
// If the pending navigation is to a WebUI and the RenderView is not in a
// guest process, tell the RenderView about any bindings it will need enabled.
- if (pending_web_ui() && !render_view_host->GetProcess()->IsGuest())
+ if (pending_web_ui() && !render_view_host->GetProcess()->IsGuest()) {
render_view_host->AllowBindings(pending_web_ui()->GetBindings());
+ } else {
+ // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled
+ // process.
+ CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ render_view_host->GetProcess()->GetID()));
+ }
return delegate_->CreateRenderViewForRenderManager(render_view_host,
opener_route_id);
@@ -911,38 +917,43 @@ void RenderViewHostManager::ShutdownRenderViewHostsInSiteInstance(
RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate(
const NavigationEntryImpl& entry) {
- // If we are cross-navigating, then we want to get back to normal and navigate
- // as usual.
+ // If we are currently navigating cross-process, we want to get back to normal
+ // and then navigate as usual.
if (cross_navigation_pending_) {
if (pending_render_view_host_)
CancelPending();
cross_navigation_pending_ = false;
}
- // render_view_host_ will not be deleted before the end of this method, so we
- // don't have to worry about this SiteInstance's ref count dropping to zero.
- SiteInstance* curr_instance = render_view_host_->GetSiteInstance();
-
- // Determine if we need a new SiteInstance for this entry.
- // Again, new_instance won't be deleted before the end of this method, so it
- // is safe to use a normal pointer here.
- SiteInstance* new_instance = curr_instance;
- const NavigationEntry* curr_entry =
+ // render_view_host_'s SiteInstance and new_instance will not be deleted
+ // before the end of this method, so we don't have to worry about their ref
+ // counts dropping to zero.
+ SiteInstance* current_instance = render_view_host_->GetSiteInstance();
+ SiteInstance* new_instance = current_instance;
+
+ // We do not currently swap processes for navigations in webview tag guests.
+ bool is_guest_scheme = current_instance->GetSiteURL().SchemeIs(kGuestScheme);
+
+ // Determine if we need a new BrowsingInstance for this entry. If true, this
+ // implies that it will get a new SiteInstance (and likely process), and that
+ // other tabs in the current BrosingInstance will be unalbe to script it.
+ // This is used for cases that require a process swap even in the
+ // process-per-tab model, such as WebUI pages.
+ const NavigationEntry* current_entry =
delegate_->GetLastCommittedNavigationEntryForRenderManager();
- bool is_guest_scheme = curr_instance->GetSiteURL().SchemeIs(kGuestScheme);
bool force_swap = !is_guest_scheme &&
- ShouldSwapProcessesForNavigation(curr_entry, &entry);
+ ShouldSwapBrowsingInstancesForNavigation(current_entry, &entry);
if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap))
- new_instance = GetSiteInstanceForEntry(entry, curr_instance, force_swap);
+ new_instance = GetSiteInstanceForEntry(entry, current_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);
+ CHECK_NE(new_instance, current_instance);
- if (new_instance != curr_instance) {
- // New SiteInstance.
+ if (new_instance != current_instance) {
+ // New SiteInstance: create a pending RVH to navigate.
DCHECK(!cross_navigation_pending_);
// This will possibly create (set to NULL) a Web UI object for the pending
@@ -957,7 +968,7 @@ RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate(
// we are staying in the same BrowsingInstance. This allows the pending RVH
// to send cross-process script calls to its opener(s).
int opener_route_id = MSG_ROUTING_NONE;
- if (new_instance->IsRelatedSiteInstance(curr_instance)) {
+ if (new_instance->IsRelatedSiteInstance(current_instance)) {
opener_route_id =
delegate_->CreateOpenerRenderViewsForRenderManager(new_instance);
}
@@ -1028,32 +1039,31 @@ RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate(
render_view_host_->FirePageBeforeUnload(true);
return pending_render_view_host_;
+ }
+
+ // Otherwise the same SiteInstance can be used. Navigate render_view_host_.
+ DCHECK(!cross_navigation_pending_);
+ if (ShouldReuseWebUI(current_entry, &entry)) {
+ pending_web_ui_.reset();
+ pending_and_current_web_ui_ = web_ui_->AsWeakPtr();
} else {
- if (ShouldReuseWebUI(curr_entry, &entry)) {
- pending_web_ui_.reset();
- pending_and_current_web_ui_ = web_ui_->AsWeakPtr();
- } else {
- SetPendingWebUI(entry);
+ SetPendingWebUI(entry);
- // Make sure the new RenderViewHost has the right bindings.
- if (pending_web_ui() && !render_view_host_->GetProcess()->IsGuest())
- render_view_host_->AllowBindings(pending_web_ui()->GetBindings());
- }
+ // Make sure the new RenderViewHost has the right bindings.
+ if (pending_web_ui() && !render_view_host_->GetProcess()->IsGuest())
+ render_view_host_->AllowBindings(pending_web_ui()->GetBindings());
+ }
- if (pending_web_ui() && render_view_host_->IsRenderViewLive())
- pending_web_ui()->GetController()->RenderViewReused(render_view_host_);
+ if (pending_web_ui() && render_view_host_->IsRenderViewLive())
+ pending_web_ui()->GetController()->RenderViewReused(render_view_host_);
- // The renderer can exit view source mode when any error or cancellation
- // happen. We must overwrite to recover the mode.
- if (entry.IsViewSourceMode()) {
- render_view_host_->Send(
- new ViewMsg_EnableViewSourceMode(render_view_host_->GetRoutingID()));
- }
+ // The renderer can exit view source mode when any error or cancellation
+ // happen. We must overwrite to recover the mode.
+ if (entry.IsViewSourceMode()) {
+ render_view_host_->Send(
+ new ViewMsg_EnableViewSourceMode(render_view_host_->GetRoutingID()));
}
- // Same SiteInstance can be used. Navigate render_view_host_ if we are not
- // cross navigating.
- DCHECK(!cross_navigation_pending_);
return render_view_host_;
}
« 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