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. |