Index: content/browser/web_contents/render_view_host_manager.cc |
=================================================================== |
--- content/browser/web_contents/render_view_host_manager.cc (revision 140789) |
+++ content/browser/web_contents/render_view_host_manager.cc (working copy) |
@@ -8,7 +8,6 @@ |
#include "base/command_line.h" |
#include "base/logging.h" |
-#include "content/browser/child_process_security_policy_impl.h" |
#include "content/browser/debugger/devtools_manager_impl.h" |
#include "content/browser/renderer_host/render_view_host_factory.h" |
#include "content/browser/renderer_host/render_view_host_impl.h" |
@@ -24,7 +23,6 @@ |
#include "content/public/browser/web_contents_view.h" |
#include "content/public/browser/web_ui_controller.h" |
#include "content/public/browser/web_ui_controller_factory.h" |
-#include "content/public/common/bindings_policy.h" |
#include "content/public/common/content_switches.h" |
#include "content/public/common/url_constants.h" |
@@ -360,63 +358,51 @@ |
return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab); |
} |
-bool RenderViewHostManager::ShouldSwapBrowsingInstanceForNavigation( |
- const NavigationEntry* current_entry, |
+bool RenderViewHostManager::ShouldSwapProcessesForNavigation( |
+ const NavigationEntry* curr_entry, |
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). Any time we return true, |
- // the new_entry will be rendered in a new SiteInstance AND BrowsingInstance. |
+ // 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 current_entry, check the current RVH's |
+ // 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 = current_entry ? current_entry->GetURL() : |
+ const GURL& current_url = (curr_entry) ? curr_entry->GetURL() : |
render_view_host_->GetSiteInstance()->GetSite(); |
- const GURL& new_url = new_entry->GetURL(); |
content::BrowserContext* browser_context = |
delegate_->GetControllerForRenderManager().GetBrowserContext(); |
const WebUIControllerFactory* web_ui_factory = |
content::GetContentClient()->browser()->GetWebUIControllerFactory(); |
if (web_ui_factory) { |
- int enabled_bindings = render_view_host_->GetEnabledBindings(); |
- |
- // Check if we're currently in a WebUI RenderViewHost, based on either URL |
- // or bindings. |
- if (enabled_bindings & content::BINDINGS_POLICY_WEB_UI || |
- web_ui_factory->UseWebUIForURL(browser_context, current_url)) { |
- // If so, force a swap if destination not an acceptable URL for Web UI. |
+ if (web_ui_factory->UseWebUIForURL(browser_context, current_url)) { |
+ // Force swap if it's not an acceptable URL for Web UI. |
// Here, data URLs are never allowed. |
- if (!web_ui_factory->IsURLAcceptableForWebUI(browser_context, new_url, |
- false)) |
+ if (!web_ui_factory->IsURLAcceptableForWebUI(browser_context, |
+ new_entry->GetURL(), false)) |
return true; |
} else { |
- // Force a swap if it's a Web UI URL. |
- if (web_ui_factory->UseWebUIForURL(browser_context, new_url)) |
+ // Force swap if it's a Web UI URL. |
+ if (web_ui_factory->UseWebUIForURL(browser_context, new_entry->GetURL())) |
return true; |
} |
} |
- // Also let the embedder decide if a BrowsingInstance swap is required. |
- if (content::GetContentClient()->browser()-> |
- ShouldSwapBrowsingInstanceForNavigation(browser_context, |
- current_url, new_url)) { |
+ if (content::GetContentClient()->browser()->ShouldSwapProcessesForNavigation( |
+ curr_entry ? curr_entry->GetURL() : GURL(), new_entry->GetURL())) { |
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 BrowsingInstance switch. |
- if (current_entry && |
- current_entry->IsViewSourceMode() != new_entry->IsViewSourceMode()) { |
+ // it as a new navigation). So require a view switch. |
+ if (curr_entry->IsViewSourceMode() != new_entry->IsViewSourceMode()) |
return true; |
- } |
return false; |
} |
@@ -437,37 +423,28 @@ |
SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry( |
const NavigationEntryImpl& entry, |
- SiteInstance* curr_instance, |
- bool force_swap) { |
- // Determine which SiteInstance to use for navigating to |entry|. |
+ SiteInstance* curr_instance) { |
+ // NOTE: This is only called when ShouldTransitionCrossSite is true. |
+ |
const GURL& dest_url = entry.GetURL(); |
NavigationControllerImpl& controller = |
delegate_->GetControllerForRenderManager(); |
content::BrowserContext* browser_context = controller.GetBrowserContext(); |
- // If a swap is required, we need to force the SiteInstance AND |
- // BrowsingInstance 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. |
- if (force_swap) { |
- // We shouldn't be forcing a swap if an entry already has a SiteInstance. |
- DCHECK(!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(); |
// (UGLY) HEURISTIC, process-per-site only: |
+ // |
// If this navigation is generated, then it probably corresponds to a search |
// query. Given that search results typically lead to users navigating to |
// other sites, we don't really want to use the search engine hostname to |
// determine the site instance for this navigation. |
+ // |
// NOTE: This can be removed once we have a way to transition between |
// RenderViews in response to a link click. |
+ // |
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerSite) && |
entry.GetTransitionType() == content::PAGE_TRANSITION_GENERATED) |
return curr_instance; |
@@ -510,7 +487,7 @@ |
return curr_site_instance; |
} |
- // Otherwise, only create a new SiteInstance for a cross-site navigation. |
+ // Otherwise, only create a new SiteInstance for 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 |
@@ -551,16 +528,25 @@ |
// 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) && |
- !curr_site_instance->HasWrongProcessForURL(dest_url)) { |
+ !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); |
} |
- |
- // Otherwise 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( |
@@ -614,14 +600,8 @@ |
int opener_route_id) { |
// If the pending navigation is to a WebUI, tell the RenderView about any |
// bindings it will need enabled. |
- if (pending_web_ui()) { |
+ if (pending_web_ui()) |
render_view_host->AllowBindings(pending_web_ui()->GetBindings()); |
- } else { |
- // Ensure that we don't create an unprivileged view in a WebUI-enabled |
- // process. |
- CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( |
- render_view_host->GetProcess()->GetID())); |
- } |
return delegate_->CreateRenderViewForRenderManager(render_view_host, |
opener_route_id); |
@@ -727,40 +707,30 @@ |
RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate( |
const NavigationEntryImpl& entry) { |
- // If we are currently navigating cross-process, we want to get back to normal |
- // and then navigate as usual. |
+ // If we are cross-navigating, then we want to get back to normal and navigate |
+ // as usual. |
if (cross_navigation_pending_) { |
if (pending_render_view_host_) |
CancelPending(); |
cross_navigation_pending_ = false; |
} |
- // 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. |
+ // 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(); |
- SiteInstance* new_instance = curr_instance; |
- // Determine if we need a new BrowsingInstance for this entry. If true, |
- // this implies it will get a new SiteInstance (and likely process), and |
- // that other tabs in the current BrowsingInstance will be unable to script |
- // it. This is used for cases that require a process swap even in the |
- // process-per-tab model, such as WebUI pages. |
+ // 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 content::NavigationEntry* curr_entry = |
delegate_->GetLastCommittedNavigationEntryForRenderManager(); |
- bool force_swap = ShouldSwapBrowsingInstanceForNavigation(curr_entry, |
- &entry); |
+ bool force_swap = ShouldSwapProcessesForNavigation(curr_entry, &entry); |
if (ShouldTransitionCrossSite() || force_swap) |
- new_instance = GetSiteInstanceForEntry(entry, curr_instance, force_swap); |
+ new_instance = GetSiteInstanceForEntry(entry, curr_instance); |
- // 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 (new_instance != curr_instance) { |
- // New SiteInstance: create a pending RVH to navigate. |
+ if (new_instance != curr_instance || force_swap) { |
+ // New SiteInstance. |
DCHECK(!cross_navigation_pending_); |
// This will possibly create (set to NULL) a Web UI object for the pending |
@@ -831,29 +801,30 @@ |
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(curr_entry, &entry)) { |
- pending_web_ui_.reset(); |
- pending_and_current_web_ui_ = web_ui_->AsWeakPtr(); |
} else { |
- pending_and_current_web_ui_.reset(); |
- pending_web_ui_.reset( |
- delegate_->CreateWebUIForRenderManager(entry.GetURL())); |
- } |
+ if (ShouldReuseWebUI(curr_entry, &entry)) { |
+ pending_web_ui_.reset(); |
+ pending_and_current_web_ui_ = web_ui_->AsWeakPtr(); |
+ } else { |
+ pending_and_current_web_ui_.reset(); |
+ pending_web_ui_.reset( |
+ delegate_->CreateWebUIForRenderManager(entry.GetURL())); |
+ } |
- 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_; |
} |