diff options
author | creis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-06 18:17:26 +0000 |
---|---|---|
committer | creis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-06 18:17:26 +0000 |
commit | f0576397e6ce23be5819fdd25b5aae31e7906b1b (patch) | |
tree | 69a38c07933022012756380220e894b168a2e311 | |
parent | 8590c327d60a7304d339bf6e43a103b6e33710f0 (diff) | |
download | chromium_src-f0576397e6ce23be5819fdd25b5aae31e7906b1b.zip chromium_src-f0576397e6ce23be5819fdd25b5aae31e7906b1b.tar.gz chromium_src-f0576397e6ce23be5819fdd25b5aae31e7906b1b.tar.bz2 |
Revert 139933 - Clean up RenderViewHostManager swapping logic.
Reverting due to http://crbug.com/131376.
Makes the difference between swapping SiteInstances and swapping
BrowsingInstances explicit, and adds CHECKs to enforce invariants
more effectively.
BUG=123007
TEST=No functionality change.
Review URL: https://chromiumcodereview.appspot.com/9965091
TBR=creis@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10546029
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@140795 0039d316-1c4b-4281-b951-d872f2087c98
8 files changed, 113 insertions, 170 deletions
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 1d2cd1d..a4bca59 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc @@ -261,21 +261,6 @@ bool IsIsolatedAppInProcess(const GURL& site_url, return false; } -// If |url| has an extension or isolated app (not a hosted app) associated with -// it, return it. Otherwise return null. -const Extension* GetExtensionOrIsolatedApp(const GURL& url, - ExtensionService* service) { - const Extension* extension = - service->extensions()->GetExtensionOrAppByURL(ExtensionURLInfo(url)); - // Ignore hosted apps that aren't isolated apps. - if (extension && - extension->is_hosted_app() && - !extension->is_storage_isolated()) - extension = NULL; - return extension; -} - - bool CertMatchesFilter(const net::X509Certificate& cert, const base::DictionaryValue& filter) { // TODO(markusheintz): This is the minimal required filter implementation. @@ -646,29 +631,28 @@ void ChromeContentBrowserClient::SiteInstanceDeleting( site_instance->GetId())); } -bool ChromeContentBrowserClient::ShouldSwapBrowsingInstanceForNavigation( - content::BrowserContext* browser_context, +bool ChromeContentBrowserClient::ShouldSwapProcessesForNavigation( const GURL& current_url, const GURL& new_url) { - Profile* profile = Profile::FromBrowserContext(browser_context); - ExtensionService* service = profile->GetExtensionService(); - if (!service) + if (current_url.is_empty()) { + // Always choose a new process when navigating to extension URLs. The + // process grouping logic will combine all of a given extension's pages + // into the same process. + if (new_url.SchemeIs(chrome::kExtensionScheme)) + return true; + return false; + } - // We must use a new BrowsingInstance (forcing a process swap and disabling - // scripting by existing tabs) if one of the URLs is an extension and the - // other is not the exact same extension. - // - // We ignore hosted apps here so that other tabs in their BrowsingInstance can - // script them. Navigations to/from a hosted app will still trigger a - // SiteInstance swap in RenderViewHostManager. - // - // However, we do use a new BrowsingInstance for isolated apps, which should - // not be scriptable by other tabs. - const Extension* current_extension = - GetExtensionOrIsolatedApp(current_url, service); - const Extension* new_extension = GetExtensionOrIsolatedApp(new_url, service); - return current_extension != new_extension; + // Also, we must switch if one is an extension and the other is not the exact + // same extension. + if (current_url.SchemeIs(chrome::kExtensionScheme) || + new_url.SchemeIs(chrome::kExtensionScheme)) { + if (current_url.GetOrigin() != new_url.GetOrigin()) + return true; + } + + return false; } bool ChromeContentBrowserClient::ShouldSwapProcessesForRedirect( diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 974921c..b5a2153 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h @@ -53,10 +53,8 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient { content::SiteInstance* site_instance) OVERRIDE; virtual void SiteInstanceDeleting(content::SiteInstance* site_instance) OVERRIDE; - virtual bool ShouldSwapBrowsingInstanceForNavigation( - content::BrowserContext* browser_context, - const GURL& current_url, - const GURL& new_url) OVERRIDE; + virtual bool ShouldSwapProcessesForNavigation(const GURL& current_url, + const GURL& new_url) OVERRIDE; virtual bool ShouldSwapProcessesForRedirect( content::ResourceContext* resource_context, const GURL& current_url, diff --git a/content/browser/debugger/devtools_manager_unittest.cc b/content/browser/debugger/devtools_manager_unittest.cc index c6a1507..2529436 100644 --- a/content/browser/debugger/devtools_manager_unittest.cc +++ b/content/browser/debugger/devtools_manager_unittest.cc @@ -97,8 +97,7 @@ class DevToolsManagerTestBrowserClient DevToolsManagerTestBrowserClient() { } - virtual bool ShouldSwapBrowsingInstanceForNavigation( - content::BrowserContext* browser_context, + virtual bool ShouldSwapProcessesForNavigation( const GURL& current_url, const GURL& new_url) OVERRIDE { return true; diff --git a/content/browser/web_contents/render_view_host_manager.cc b/content/browser/web_contents/render_view_host_manager.cc index 3b1081a..cb7ead5 100644 --- a/content/browser/web_contents/render_view_host_manager.cc +++ b/content/browser/web_contents/render_view_host_manager.cc @@ -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 @@ bool RenderViewHostManager::ShouldTransitionCrossSite() { 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 @@ bool RenderViewHostManager::ShouldReuseWebUI( 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 @@ SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry( 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 @@ 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) && - !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 @@ bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host, 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 @@ void RenderViewHostManager::CommitPending() { 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); - - // 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); + new_instance = GetSiteInstanceForEntry(entry, 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 @@ 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(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_; } diff --git a/content/browser/web_contents/render_view_host_manager.h b/content/browser/web_contents/render_view_host_manager.h index 32d2fca..68b1704 100644 --- a/content/browser/web_contents/render_view_host_manager.h +++ b/content/browser/web_contents/render_view_host_manager.h @@ -235,30 +235,26 @@ class CONTENT_EXPORT RenderViewHostManager // switch. Can be overridden in unit tests. bool ShouldTransitionCrossSite(); - // Returns true if for the navigation from |current_entry| to |new_entry|, - // a new SiteInstance and BrowsingInstance should be created (even if we are - // in a process model that doesn't usually swap). This forces a process swap - // and severs script connections with existing tabs. Cases where this can - // happen include transitions between WebUI and regular web pages. + // Returns true if the two navigation entries are incompatible in some way + // other than site instances. Cases where this can happen include Web UI + // to regular web pages. It will cause us to swap RenderViewHosts (and hence + // RenderProcessHosts) even if the site instance would otherwise be the same. + // As part of this, we'll also force new SiteInstances and BrowsingInstances. // Either of the entries may be NULL. - bool ShouldSwapBrowsingInstanceForNavigation( - const content::NavigationEntry* current_entry, + bool ShouldSwapProcessesForNavigation( + const content::NavigationEntry* curr_entry, const content::NavigationEntryImpl* new_entry) const; - // Returns true if it is safe to reuse the current WebUI when navigating from - // |curr_entry| to |new_entry|. bool ShouldReuseWebUI( const content::NavigationEntry* curr_entry, const content::NavigationEntryImpl* new_entry) const; // Returns an appropriate SiteInstance object for the given NavigationEntry, - // possibly reusing the current SiteInstance. If --process-per-tab is used, - // this is only called when ShouldSwapBrowsingInstancesForNavigation returns - // true. + // possibly reusing the current SiteInstance. + // Never called if --process-per-tab is used. content::SiteInstance* GetSiteInstanceForEntry( const content::NavigationEntryImpl& entry, - content::SiteInstance* curr_instance, - bool force_swap); + content::SiteInstance* curr_instance); // Sets up the necessary state for a new RenderViewHost with the given opener. bool InitRenderView(content::RenderViewHost* render_view_host, diff --git a/content/browser/web_contents/render_view_host_manager_unittest.cc b/content/browser/web_contents/render_view_host_manager_unittest.cc index 25705d7..80cdca3 100644 --- a/content/browser/web_contents/render_view_host_manager_unittest.cc +++ b/content/browser/web_contents/render_view_host_manager_unittest.cc @@ -180,8 +180,7 @@ class RenderViewHostManagerTest bool ShouldSwapProcesses(RenderViewHostManager* manager, const NavigationEntryImpl* cur_entry, const NavigationEntryImpl* new_entry) const { - return manager->ShouldSwapBrowsingInstanceForNavigation(cur_entry, - new_entry); + return manager->ShouldSwapProcessesForNavigation(cur_entry, new_entry); } private: diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index db158b4..859204f 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc @@ -53,10 +53,9 @@ bool ContentBrowserClient::ShouldTryToUseExistingProcessHost( return false; } -bool ContentBrowserClient::ShouldSwapBrowsingInstanceForNavigation( - BrowserContext* browser_context, - const GURL& current_url, - const GURL& new_url) { +bool ContentBrowserClient::ShouldSwapProcessesForNavigation( + const GURL& current_url, + const GURL& new_url) { return false; } diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index 81fed12..c5965fe 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h @@ -149,13 +149,10 @@ class CONTENT_EXPORT ContentBrowserClient { virtual void SiteInstanceDeleting(SiteInstance* site_instance) {} // Returns true if for the navigation from |current_url| to |new_url|, - // a new SiteInstance and BrowsingInstance should be created (even if we are - // in a process model that doesn't usually swap). This forces a process swap - // and severs script connections with existing tabs. - virtual bool ShouldSwapBrowsingInstanceForNavigation( - BrowserContext* browser_context, - const GURL& current_url, - const GURL& new_url); + // processes should be swapped (even if we are in a process model that + // doesn't usually swap). + virtual bool ShouldSwapProcessesForNavigation(const GURL& current_url, + const GURL& new_url); // Returns true if the given navigation redirect should cause a renderer // process swap. |