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

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

Issue 701953006: PlzNavigate: Speculatively spawns a renderer process for navigations. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed CR comments, added simple test, other minor changes. Created 6 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_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 49b9495e32d2cb4d0da64a6b03a606afce8c3006..2086703305b9204d398449b83ec8289807e06e0b 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -69,6 +69,11 @@ RenderFrameHostManager::~RenderFrameHostManager() {
if (pending_render_frame_host_)
CancelPending();
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
+ CleanUpSpeculativeRenderFrameHost();
+ }
+
// We should always have a current RenderFrameHost except in some tests.
SetRenderFrameHost(scoped_ptr<RenderFrameHostImpl>());
@@ -307,6 +312,10 @@ void RenderFrameHostManager::OnBeforeUnloadACK(
// Current page says to cancel.
CancelPending();
cross_navigation_pending_ = false;
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
+ CleanUpSpeculativeRenderFrameHost();
+ }
}
} else {
// Non-cross site transition means closing the entire tab.
@@ -321,6 +330,10 @@ void RenderFrameHostManager::OnBeforeUnloadACK(
if (pending_render_frame_host_) {
CancelPending();
cross_navigation_pending_ = false;
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
+ CleanUpSpeculativeRenderFrameHost();
+ }
}
// This is not a cross-site navigation, the tab is being closed.
@@ -419,6 +432,16 @@ void RenderFrameHostManager::ClearNavigationTransitionData() {
void RenderFrameHostManager::DidNavigateFrame(
RenderFrameHostImpl* render_frame_host) {
+ DCHECK(render_frame_host);
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
+ if (speculative_render_frame_host_.get() == render_frame_host) {
+ CommitPending(true);
+ return;
+ }
+ CleanUpSpeculativeRenderFrameHost();
+ }
+
if (!cross_navigation_pending_) {
DCHECK(!pending_render_frame_host_);
@@ -427,13 +450,13 @@ void RenderFrameHostManager::DidNavigateFrame(
// Even when there is no pending RVH, there may be a pending Web UI.
if (pending_web_ui())
- CommitPending();
+ CommitPending(false);
return;
}
if (render_frame_host == pending_render_frame_host_) {
// The pending cross-site navigation completed, so show the renderer.
- CommitPending();
+ CommitPending(false);
cross_navigation_pending_ = false;
} else if (render_frame_host == render_frame_host_) {
// A navigation in the original page has taken place. Cancel the pending
@@ -446,6 +469,10 @@ void RenderFrameHostManager::DidNavigateFrame(
}
}
+void RenderFrameHostManager::CancelNavigation() {
+ CleanUpSpeculativeRenderFrameHost();
+}
+
void RenderFrameHostManager::DidDisownOpener(
RenderFrameHost* render_frame_host) {
// Notify all RenderFrameHosts but the one that notified us. This is necessary
@@ -559,6 +586,30 @@ void RenderFrameHostManager::SwapOutOldFrame(
}
}
+void RenderFrameHostManager::RecycleRenderFrameHost(
+ scoped_ptr<RenderFrameHostImpl> render_frame_host) {
+ // TODO(carlosk): this code is very similar to what can be found in
+ // SwapOutOldFrame and we should see that these are unified at some point.
+
+ // If the SiteInstance for the pending RFH is being used by others, don't
+ // delete the RFH, just swap it out and it can be reused at a later point.
+ SiteInstanceImpl* site_instance = render_frame_host->GetSiteInstance();
+ if (site_instance->HasSite() && site_instance->active_frame_count() > 1) {
+ // Any currently suspended navigations are no longer needed.
+ render_frame_host->CancelSuspendedNavigations();
+
+ RenderFrameProxyHost* proxy =
+ new RenderFrameProxyHost(site_instance, frame_tree_node_);
+ proxy_hosts_[site_instance->GetId()] = proxy;
+ render_frame_host->SwapOut(proxy);
+ if (frame_tree_node_->IsMainFrame())
+ proxy->TakeFrameHostOwnership(render_frame_host.Pass());
+ } else {
+ // We won't be coming back, so delete this one.
+ render_frame_host.reset();
+ }
+}
+
void RenderFrameHostManager::MoveToPendingDeleteHosts(
scoped_ptr<RenderFrameHostImpl> render_frame_host) {
// |render_frame_host| will be deleted when its SwapOut ACK is received, or
@@ -594,6 +645,152 @@ void RenderFrameHostManager::ResetProxyHosts() {
STLDeleteValues(&proxy_hosts_);
}
+void RenderFrameHostManager::BeginNavigation(
+ const FrameHostMsg_BeginNavigation_Params& params,
+ const CommonNavigationParams& common_params) {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+ // If there is an ongoing navigation, just clean it up.
clamy 2014/11/14 10:11:09 nit: s/just clean it up/cancel it
carlosk 2014/11/14 17:43:37 Done.
+ CancelNavigation();
+
+ SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
+ // TODO(carlosk): Replace the default values by the right ones.
+ scoped_refptr<SiteInstanceImpl> new_instance =
+ static_cast<SiteInstanceImpl*>(GetSiteInstanceForNavigation(
+ common_params.url, NULL, common_params.transition, false, false,
+ true));
+
+ if (new_instance.get() != current_instance) {
+ // Navigating to a new SiteInstance -> speculatively create a new RFH
+
+ // TODO(carlosk): what the TRACE_EVENT_INSTANT2 for New SiteInstance found
+ // in UpdateStateForNavigate be copied here?
+
+ bool success = CreateSpeculativeRenderFrameHost(
+ common_params.url, current_instance, new_instance.get());
+ if (!success)
+ return;
+ } else {
+ // Navigating to the same SiteInstance -> make sure the current RFH is alive
+ DCHECK(render_frame_host_->GetSiteInstance() == new_instance);
+ if (!render_frame_host_->render_view_host()->IsRenderViewLive()) {
+ // Recreate the opener chain.
+ int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager(
+ render_frame_host_->GetSiteInstance());
+ if (!InitRenderView(render_frame_host_->render_view_host(),
+ opener_route_id, MSG_ROUTING_NONE,
+ frame_tree_node_->IsMainFrame())) {
+ return;
+ }
+ }
+ }
+ DCHECK(new_instance->GetProcess()->HasConnection());
+ DCHECK(new_instance->GetProcess()->GetBrowserContext());
+}
+
+bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost(
+ const GURL& url,
+ SiteInstance* old_instance,
+ SiteInstance* new_instance) {
+ CHECK(new_instance);
+ CHECK_NE(old_instance, new_instance);
+
+ // TODO(carlosk): should also try to reuse the current web_ui
+ // (ShouldReuseWebUI)?
+ scoped_ptr<WebUIImpl> new_web_ui(delegate_->CreateWebUIForRenderManager(url));
+ // TODO(carlosk): confirm this next section copied from SetPendingWebUI
+ // is in fact needed... I need access to the respective navigation entry
+ // though.
+ // If we have assigned (zero or more) bindings to this NavigationEntry in the
+ // past, make sure we're not granting it different bindings than it had
+ // before. If so, note it and don't give it any bindings, to avoid a
+ // potential privilege escalation.
+ // if (new_web_ui &&
+ // bindings != NavigationEntryImpl::kInvalidBindings &&
+ // new_web_ui->GetBindings() != bindings) {
+ // RecordAction(
+ // base::UserMetricsAction("ProcessSwapBindingsMismatch_RVHM"));
+ // new_web_ui.reset();
+ // }
+
+ scoped_ptr<RenderFrameHostImpl> new_render_frame_host;
+
+ // Check if we've already created an RFH 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 proxy hosts below if it will be active.
+ RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(new_instance);
+ if (proxy && proxy->render_frame_host()) {
+ // Delete the existing RenderFrameProxyHost, but reuse the RenderFrameHost.
+ // Prevent the process from exiting while we're trying to use it.
+ new_render_frame_host = proxy->PassFrameHostOwnership();
+ new_render_frame_host->GetProcess()->AddPendingView();
+
+ proxy_hosts_.erase(new_instance->GetId());
+ delete proxy;
+
+ // When a new render view is created by the renderer, the new WebContents
+ // gets a RenderViewHost in the SiteInstance of its opener WebContents.
+ // If not used in the first navigation, this RVH is swapped out and is not
+ // granted bindings, so we may need to grant them when swapping it in.
+ if (new_web_ui && !new_render_frame_host->GetProcess()->IsIsolatedGuest()) {
+ int required_bindings = new_web_ui->GetBindings();
+ RenderViewHost* rvh = new_render_frame_host->render_view_host();
+ if ((rvh->GetEnabledBindings() & required_bindings) !=
+ required_bindings) {
+ rvh->AllowBindings(required_bindings);
+ }
+ }
+ } else {
+ // Create a new RenderFrameHost if we don't find an existing one.
+ new_render_frame_host =
+ CreateRenderFrameHost(new_instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE,
+ false, delegate_->IsHidden());
+ DCHECK(new_render_frame_host);
+ RenderViewHostImpl* rvh = new_render_frame_host->render_view_host();
+
+ // Prevent the process from exiting while we're trying to navigate in it.
+ // Otherwise, if the new RFH is swapped out already, store it.
+ new_render_frame_host->GetProcess()->AddPendingView();
+
+ // Ensure that we have created RFHs for the new RFH's opener chain if
+ // we are staying in the same BrowsingInstance. This allows the new RFH
+ // to send cross-process script calls to its opener(s).
+ int opener_route_id = MSG_ROUTING_NONE;
+ if (new_instance->IsRelatedSiteInstance(old_instance)) {
+ opener_route_id =
+ delegate_->CreateOpenerRenderViewsForRenderManager(new_instance);
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSitePerProcess)) {
+ // Ensure that the frame tree has RenderFrameProxyHosts for the new
+ // SiteInstance in all nodes except the current one.
+ frame_tree_node_->frame_tree()->CreateProxiesForSiteInstance(
+ frame_tree_node_, new_instance);
+ }
+ }
+
+ bool success = InitRenderView(rvh, opener_route_id, MSG_ROUTING_NONE,
+ frame_tree_node_->IsMainFrame());
+ if (success) {
+ if (frame_tree_node_->IsMainFrame()) {
+ // Don't show the main frame's view until we know it will be used.
+ rvh->GetView()->Hide();
+ } else {
+ // Init the RFH, so a RenderFrame is created in the renderer.
+ success = InitRenderFrame(new_render_frame_host.get());
+ }
+ }
+ if (!success)
+ return false;
+
+ render_frame_delegate_->RenderFrameCreated(new_render_frame_host.get());
+ }
+
+ DCHECK(new_render_frame_host->GetSiteInstance() == new_instance);
+ speculative_render_frame_host_.reset(new_render_frame_host.release());
+ speculative_web_ui_.reset(new_web_ui.release());
+ return true;
+}
+
// PlzNavigate
RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
const GURL& url,
@@ -757,7 +954,8 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation(
SiteInstance* dest_instance,
ui::PageTransition dest_transition,
bool dest_is_restore,
- bool dest_is_view_source_mode) {
+ bool dest_is_view_source_mode,
+ bool create_unbounded_site_instance) {
SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
SiteInstance* new_instance = current_instance;
@@ -789,13 +987,9 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation(
dest_is_view_source_mode);
if (ShouldTransitionCrossSite() || force_swap) {
new_instance = GetSiteInstanceForURL(
- dest_url,
- dest_instance,
- dest_transition,
- dest_is_restore,
- dest_is_view_source_mode,
- current_instance,
- force_swap);
+ dest_url, dest_instance, dest_transition, dest_is_restore,
+ dest_is_view_source_mode, current_instance, force_swap,
+ create_unbounded_site_instance);
}
// If force_swap is true, we must use a different SiteInstance. If we didn't,
@@ -813,7 +1007,8 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
bool dest_is_restore,
bool dest_is_view_source_mode,
SiteInstance* current_instance,
- bool force_browsing_instance_swap) {
+ bool force_browsing_instance_swap,
+ bool create_unbounded_site_instance) {
NavigationControllerImpl& controller =
delegate_->GetControllerForRenderManager();
BrowserContext* browser_context = controller.GetBrowserContext();
@@ -828,10 +1023,16 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
return dest_instance;
}
+ SiteInstanceImpl* current_site_instance =
+ static_cast<SiteInstanceImpl*>(current_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);
+ if (force_browsing_instance_swap) {
+ return CreateSiteInstanceForURL(browser_context, dest_url,
+ create_unbounded_site_instance,
+ current_site_instance);
+ }
// (UGLY) HEURISTIC, process-per-site only:
//
@@ -849,9 +1050,6 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
return current_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
@@ -873,28 +1071,36 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
RenderProcessHostImpl::GetProcessHostForSite(browser_context, dest_url);
if (current_site_instance->HasRelatedSiteInstance(dest_url) ||
use_process_per_site) {
- return current_site_instance->GetRelatedSiteInstance(dest_url);
+ return GetRelatedSiteInstanceForURL(current_site_instance, dest_url,
+ create_unbounded_site_instance);
}
// 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);
+ if (current_site_instance->HasWrongProcessForURL(dest_url)) {
+ return GetRelatedSiteInstanceForURL(current_site_instance, dest_url,
+ create_unbounded_site_instance);
+ }
// 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);
+ if (dest_is_view_source_mode) {
+ return CreateSiteInstanceForURL(browser_context, dest_url,
+ create_unbounded_site_instance,
+ current_site_instance);
+ }
// 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 CreateSiteInstanceForURL(browser_context, dest_url,
+ create_unbounded_site_instance,
+ current_site_instance);
}
// Normally the "site" on the SiteInstance is set lazily when the load
@@ -944,7 +1150,9 @@ 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 CreateSiteInstanceForURL(browser_context, dest_url,
+ create_unbounded_site_instance,
+ current_site_instance);
}
// Use the current SiteInstance for same site navigations, as long as the
@@ -962,6 +1170,51 @@ 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 GetRelatedSiteInstanceForURL(current_site_instance, dest_url,
+ create_unbounded_site_instance);
+}
+
+SiteInstance* RenderFrameHostManager::CreateSiteInstanceForURL(
+ BrowserContext* browser_context,
+ const GURL& dest_url,
+ bool create_unbounded_site_instance,
+ SiteInstanceImpl* current_instance) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
+ if (create_unbounded_site_instance) {
+ return SiteInstance::Create(browser_context);
+ }
+ if (speculative_render_frame_host_) {
+ SiteInstanceImpl* sii = speculative_render_frame_host_->GetSiteInstance();
+ if (!sii->HasSite() && !sii->IsRelatedSiteInstance(current_instance)) {
+ return sii;
+ }
+ }
+ }
+
+ return SiteInstance::CreateForURL(browser_context, dest_url);
+}
+
+SiteInstance* RenderFrameHostManager::GetRelatedSiteInstanceForURL(
+ SiteInstanceImpl* current_instance,
+ const GURL& dest_url,
+ bool create_unbounded_site_instance) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
+ if (!current_instance->HasRelatedSiteInstance(dest_url)) {
+ if (create_unbounded_site_instance) {
+ return current_instance->GetRelatedEmptySiteInstance();
+ }
+ if (speculative_render_frame_host_) {
+ SiteInstanceImpl* sii =
+ speculative_render_frame_host_->GetSiteInstance();
+ if (!sii->HasSite() && sii->IsRelatedSiteInstance(current_instance)) {
+ return sii;
+ }
+ }
+ }
+ }
+
return current_instance->GetRelatedSiteInstance(dest_url);
}
@@ -1197,10 +1450,9 @@ bool RenderFrameHostManager::InitRenderView(
}
}
- return delegate_->CreateRenderViewForRenderManager(render_view_host,
- opener_route_id,
- proxy_routing_id,
- for_main_frame_navigation);
+ return delegate_->CreateRenderViewForRenderManager(
+ render_view_host, opener_route_id, proxy_routing_id,
+ for_main_frame_navigation);
}
bool RenderFrameHostManager::InitRenderFrame(
@@ -1246,32 +1498,42 @@ int RenderFrameHostManager::GetRoutingIdForSiteInstance(
return MSG_ROUTING_NONE;
}
-void RenderFrameHostManager::CommitPending() {
+void RenderFrameHostManager::CommitPending(bool use_speculative_rfh) {
TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending",
"FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
+ // If use_speculative_rfh then kEnableBrowserSideNavigation must be enabled.
+ CHECK(!use_speculative_rfh ||
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+
// First check whether we're going to want to focus the location bar after
// this commit. We do this now because the navigation hasn't formally
// committed yet, so if we've already cleared |pending_web_ui_| the call chain
// this triggers won't be able to figure out what's going on.
bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
- // Next commit the Web UI, if any. Either replace |web_ui_| with
- // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or
- // leave |web_ui_| as is if reusing it.
- DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get()));
- if (pending_web_ui_) {
- web_ui_.reset(pending_web_ui_.release());
- } else if (!pending_and_current_web_ui_.get()) {
- web_ui_.reset();
+ if (!use_speculative_rfh) {
+ DCHECK(!speculative_web_ui_);
+ // Next commit the Web UI, if any. Either replace |web_ui_| with
+ // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or
+ // leave |web_ui_| as is if reusing it.
+ DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get()));
+ if (pending_web_ui_) {
+ web_ui_.reset(pending_web_ui_.release());
+ } else if (!pending_and_current_web_ui_.get()) {
+ web_ui_.reset();
+ } else {
+ DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get());
+ pending_and_current_web_ui_.reset();
+ }
} else {
- DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get());
- pending_and_current_web_ui_.reset();
+ web_ui_.reset(speculative_web_ui_.release());
}
// It's possible for the pending_render_frame_host_ to be NULL when we aren't
// crossing process boundaries. If so, we just needed to handle the Web UI
// committing above and we're done.
- if (!pending_render_frame_host_) {
+ if (!pending_render_frame_host_ && !use_speculative_rfh) {
if (will_focus_location_bar)
delegate_->SetFocusToLocationBar(false);
return;
@@ -1285,10 +1547,19 @@ void RenderFrameHostManager::CommitPending() {
bool is_main_frame = frame_tree_node_->IsMainFrame();
- // Swap in the pending frame and make it active. Also ensure the FrameTree
- // stays in sync.
- scoped_ptr<RenderFrameHostImpl> old_render_frame_host =
- SetRenderFrameHost(pending_render_frame_host_.Pass());
+ scoped_ptr<RenderFrameHostImpl> old_render_frame_host;
+ if (!use_speculative_rfh) {
+ DCHECK(!speculative_render_frame_host_);
+ // Swap in the pending frame and make it active. Also ensure the FrameTree
+ // stays in sync.
+ old_render_frame_host =
+ SetRenderFrameHost(pending_render_frame_host_.Pass());
+ } else {
+ DCHECK(speculative_render_frame_host_);
+ old_render_frame_host =
+ SetRenderFrameHost(speculative_render_frame_host_.Pass());
+ }
+
if (is_main_frame)
render_frame_host_->render_view_host()->AttachToFrameTree();
@@ -1415,7 +1686,15 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation(
- url, instance, transition, is_restore, is_view_source_mode);
+ url, instance, transition, is_restore, is_view_source_mode, false);
+
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation) &&
+ speculative_render_frame_host_) {
+ if (speculative_render_frame_host_->GetSiteInstance() == new_instance)
+ return speculative_render_frame_host_.get();
+ CleanUpSpeculativeRenderFrameHost();
+ }
const NavigationEntry* current_entry =
delegate_->GetLastCommittedNavigationEntryForRenderManager();
@@ -1452,7 +1731,7 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
// navigate. Just switch to the pending RFH now and go back to non
// cross-navigating (Note that we don't care about on{before}unload
// handlers if the current RFH isn't live.)
- CommitPending();
+ CommitPending(false);
return render_frame_host_.get();
} else {
NOTREACHED();
@@ -1557,29 +1836,23 @@ void RenderFrameHostManager::CancelPending() {
// We no longer need to prevent the process from exiting.
pending_render_frame_host->GetProcess()->RemovePendingView();
- // If the SiteInstance for the pending RFH is being used by others, don't
- // delete the RFH, just swap it out and it can be reused at a later point.
- SiteInstanceImpl* site_instance =
- pending_render_frame_host->GetSiteInstance();
- if (site_instance->active_frame_count() > 1) {
- // Any currently suspended navigations are no longer needed.
- pending_render_frame_host->CancelSuspendedNavigations();
-
- RenderFrameProxyHost* proxy =
- new RenderFrameProxyHost(site_instance, frame_tree_node_);
- proxy_hosts_[site_instance->GetId()] = proxy;
- pending_render_frame_host->SwapOut(proxy);
- if (frame_tree_node_->IsMainFrame())
- proxy->TakeFrameHostOwnership(pending_render_frame_host.Pass());
- } else {
- // We won't be coming back, so delete this one.
- pending_render_frame_host.reset();
- }
+ RecycleRenderFrameHost(pending_render_frame_host.Pass());
pending_web_ui_.reset();
pending_and_current_web_ui_.reset();
}
+void RenderFrameHostManager::CleanUpSpeculativeRenderFrameHost() {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+ if (speculative_render_frame_host_) {
+ speculative_render_frame_host_->GetProcess()->RemovePendingView();
+ RecycleRenderFrameHost(speculative_render_frame_host_.Pass());
+ }
+ if (speculative_web_ui_)
+ speculative_web_ui_.reset();
+}
+
scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::SetRenderFrameHost(
scoped_ptr<RenderFrameHostImpl> render_frame_host) {
// Swap the two.

Powered by Google App Engine
This is Rietveld 408576698