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

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: Re-applying previous changes over. 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 7780cc05e2c90df1464137488038106a0f2316f6..31f8131f2caf38ce61c4b9ebfdddef5fe3772e68 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -61,7 +61,8 @@ RenderFrameHostManager::RenderFrameHostManager(
render_view_delegate_(render_view_delegate),
render_widget_delegate_(render_widget_delegate),
interstitial_page_(NULL),
- weak_factory_(this) {
+ weak_factory_(this),
+ should_reuse_web_ui_(false) {
DCHECK(frame_tree_node_);
}
@@ -69,6 +70,11 @@ RenderFrameHostManager::~RenderFrameHostManager() {
if (pending_render_frame_host_)
CancelPending();
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
+ CleanUpNavigation();
+ }
+
// We should always have a current RenderFrameHost except in some tests.
SetRenderFrameHost(scoped_ptr<RenderFrameHostImpl>());
@@ -134,23 +140,25 @@ RenderFrameProxyHost* RenderFrameHostManager::GetProxyToParent() {
return iter->second;
}
-void RenderFrameHostManager::SetPendingWebUI(const GURL& url,
- int bindings) {
- pending_web_ui_.reset(
- delegate_->CreateWebUIForRenderManager(url));
+void RenderFrameHostManager::SetPendingWebUI(const GURL& url, int bindings) {
+ pending_web_ui_.reset(CreateWebUI(url, bindings));
pending_and_current_web_ui_.reset();
+}
+
+WebUIImpl* RenderFrameHostManager::CreateWebUI(const GURL& url, int bindings) {
+ WebUIImpl* new_web_ui = delegate_->CreateWebUIForRenderManager(url);
// 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 (pending_web_ui_.get() &&
- bindings != NavigationEntryImpl::kInvalidBindings &&
- pending_web_ui_->GetBindings() != bindings) {
- RecordAction(
- base::UserMetricsAction("ProcessSwapBindingsMismatch_RVHM"));
- pending_web_ui_.reset();
+ if (new_web_ui && bindings != NavigationEntryImpl::kInvalidBindings &&
+ new_web_ui->GetBindings() != bindings) {
+ RecordAction(base::UserMetricsAction("ProcessSwapBindingsMismatch_RVHM"));
+ delete new_web_ui;
+ return nullptr;
}
+ return new_web_ui;
}
RenderFrameHostImpl* RenderFrameHostManager::Navigate(
@@ -286,6 +294,8 @@ void RenderFrameHostManager::OnBeforeUnloadACK(
bool proceed,
const base::TimeTicks& proceed_time) {
if (for_cross_site_transition) {
+ DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
// Ignore if we're not in a cross-site navigation.
if (!cross_navigation_pending_)
return;
@@ -417,6 +427,12 @@ void RenderFrameHostManager::ClearNavigationTransitionData() {
void RenderFrameHostManager::DidNavigateFrame(
RenderFrameHostImpl* render_frame_host) {
+ DCHECK(render_frame_host);
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
+ return;
+ }
+
if (!cross_navigation_pending_) {
DCHECK(!pending_render_frame_host_);
@@ -425,13 +441,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
@@ -557,6 +573,30 @@ void RenderFrameHostManager::SwapOutOldFrame(
}
}
+void RenderFrameHostManager::DiscardRenderFrameHost(
+ 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
@@ -593,6 +633,84 @@ void RenderFrameHostManager::ResetProxyHosts() {
}
// PlzNavigate
+void RenderFrameHostManager::BeginNavigation(
+ const FrameHostMsg_BeginNavigation_Params& params,
+ const CommonNavigationParams& common_params) {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+ // If there is an ongoing navigation, cancel it.
+ CleanUpNavigation();
+
+ 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, nullptr, common_params.transition, false, false));
+
+ if (new_instance.get() != current_instance) {
+ // Navigating to a new SiteInstance -> speculatively create a new RFH.
+
+ // TODO(carlosk): enable bindings check below.
+ bool success = CreateSpeculativeRenderFrameHost(
+ common_params.url, current_instance, new_instance.get(),
+ NavigationEntryImpl::kInvalidBindings);
+ 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());
+}
+
+// PlzNavigate
+bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost(
+ const GURL& url,
+ SiteInstance* old_instance,
+ SiteInstance* new_instance,
+ int bindings) {
+ CHECK(new_instance);
+ CHECK_NE(old_instance, new_instance);
+
+ const NavigationEntry* current_navigation_entry =
+ delegate_->GetLastCommittedNavigationEntryForRenderManager();
+ scoped_ptr<WebUIImpl> new_web_ui;
+ should_reuse_web_ui_ = ShouldReuseWebUI(current_navigation_entry, url);
+ if (!should_reuse_web_ui_)
+ new_web_ui.reset(CreateWebUI(url, bindings));
+
+ int opener_route_id =
+ CreateOpenerRenderViewsIfNeeded(old_instance, new_instance);
+
+ int create_render_frame_flags = 0;
+ if (frame_tree_node_->IsMainFrame())
+ create_render_frame_flags |= CREATE_RF_FOR_MAIN_FRAME_NAVIGATION;
+ if (delegate_->IsHidden())
+ create_render_frame_flags |= CREATE_RF_HIDDEN;
+ scoped_ptr<RenderFrameHostImpl> new_render_frame_host =
+ CreateRenderFrame(new_instance, opener_route_id,
+ create_render_frame_flags, new_web_ui.get(), nullptr);
+ if (!new_render_frame_host) {
+ return false;
+ }
+ 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,
ui::PageTransition transition) {
@@ -624,6 +742,18 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
return render_frame_host;
}
+// PlzNavigate
+void RenderFrameHostManager::CleanUpNavigation() {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+ if (speculative_render_frame_host_) {
+ speculative_render_frame_host_->GetProcess()->RemovePendingView();
+ DiscardRenderFrameHost(speculative_render_frame_host_.Pass());
+ }
+ if (speculative_web_ui_)
+ speculative_web_ui_.reset();
+}
+
void RenderFrameHostManager::Observe(
int type,
const NotificationSource& source,
@@ -997,9 +1127,24 @@ void RenderFrameHostManager::CreateRenderFrameHostForNewSiteInstance(
int create_render_frame_flags = 0;
if (is_main_frame)
create_render_frame_flags |= CREATE_RF_FOR_MAIN_FRAME_NAVIGATION;
- // 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).
+ if (delegate_->IsHidden())
+ create_render_frame_flags |= CREATE_RF_HIDDEN;
+ int opener_route_id =
+ CreateOpenerRenderViewsIfNeeded(old_instance, new_instance);
+ // TODO(carlosk): does this "earlier" call for CancelPending affects anything?
+ // It used to happen inside the creation method iff the new RFH was
+ // successfully created.
+ if (pending_render_frame_host_)
+ CancelPending();
+ // Create a non-swapped-out RFH with the given opener.
+ pending_render_frame_host_ =
+ CreateRenderFrame(new_instance, opener_route_id,
+ create_render_frame_flags, pending_web_ui(), nullptr);
+}
+
+int RenderFrameHostManager::CreateOpenerRenderViewsIfNeeded(
+ SiteInstance* old_instance,
+ SiteInstance* new_instance) {
int opener_route_id = MSG_ROUTING_NONE;
if (new_instance->IsRelatedSiteInstance(old_instance)) {
opener_route_id =
@@ -1012,17 +1157,7 @@ void RenderFrameHostManager::CreateRenderFrameHostForNewSiteInstance(
frame_tree_node_, new_instance);
}
}
-
- if (delegate_->IsHidden())
- create_render_frame_flags |= CREATE_RF_HIDDEN;
-
- // Create a non-swapped-out RFH with the given opener.
- int route_id = CreateRenderFrame(new_instance, opener_route_id,
- create_render_frame_flags);
- if (route_id == MSG_ROUTING_NONE) {
- pending_render_frame_host_.reset();
- return;
- }
+ return opener_route_id;
}
scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost(
@@ -1056,9 +1191,12 @@ scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost(
return render_frame_host.Pass();
}
-int RenderFrameHostManager::CreateRenderFrame(SiteInstance* instance,
- int opener_route_id,
- int flags) {
+scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame(
+ SiteInstance* instance,
+ int opener_route_id,
+ int flags,
+ const WebUIImpl* web_ui,
+ int* routing_id_ptr) {
bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT);
CHECK(instance);
// Swapped out views should always be hidden.
@@ -1071,20 +1209,21 @@ int RenderFrameHostManager::CreateRenderFrame(SiteInstance* instance,
}
scoped_ptr<RenderFrameHostImpl> new_render_frame_host;
- RenderFrameHostImpl* frame_to_announce = NULL;
- int routing_id = MSG_ROUTING_NONE;
+ bool success = true;
+ if (routing_id_ptr)
+ *routing_id_ptr = MSG_ROUTING_NONE;
- // We are creating a pending or swapped out RFH here. We should never create
- // it in the same SiteInstance as our current RFH.
+ // We are creating a pending, speculative or swapped out RFH here. We should
+ // never create it in the same SiteInstance as our current RFH.
CHECK_NE(render_frame_host_->GetSiteInstance(), instance);
// 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(instance);
-
if (proxy && proxy->render_frame_host()) {
- routing_id = proxy->GetRenderViewHost()->GetRoutingID();
+ if (routing_id_ptr)
+ *routing_id_ptr = proxy->GetRenderViewHost()->GetRoutingID();
// Delete the existing RenderFrameProxyHost, but reuse the RenderFrameHost.
// Prevent the process from exiting while we're trying to use it.
if (!swapped_out) {
@@ -1098,13 +1237,13 @@ int RenderFrameHostManager::CreateRenderFrame(SiteInstance* instance,
// 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 (pending_web_ui() &&
- !new_render_frame_host->GetProcess()->IsIsolatedGuest()) {
- int required_bindings = pending_web_ui()->GetBindings();
- RenderViewHost* rvh = new_render_frame_host->render_view_host();
- if ((rvh->GetEnabledBindings() & required_bindings) !=
- required_bindings) {
- rvh->AllowBindings(required_bindings);
+ if (web_ui && !new_render_frame_host->GetProcess()->IsIsolatedGuest()) {
+ int required_bindings = web_ui->GetBindings();
+ RenderViewHost* render_view_host =
+ new_render_frame_host->render_view_host();
+ if ((render_view_host->GetEnabledBindings() & required_bindings) !=
+ required_bindings) {
+ render_view_host->AllowBindings(required_bindings);
}
}
}
@@ -1129,7 +1268,7 @@ int RenderFrameHostManager::CreateRenderFrame(SiteInstance* instance,
proxy->TakeFrameHostOwnership(new_render_frame_host.Pass());
}
- bool success =
+ success =
InitRenderView(render_view_host, opener_route_id, proxy_routing_id,
!!(flags & CREATE_RF_FOR_MAIN_FRAME_NAVIGATION));
if (success) {
@@ -1141,22 +1280,27 @@ int RenderFrameHostManager::CreateRenderFrame(SiteInstance* instance,
DCHECK(new_render_frame_host.get());
success = InitRenderFrame(new_render_frame_host.get());
}
- } else if (!swapped_out && pending_render_frame_host_) {
- CancelPending();
+ if (success) {
+ if (routing_id_ptr)
+ *routing_id_ptr = render_view_host->GetRoutingID();
+ // If a brand new RFH was created, announce it to observers.
+ // TODO(carlosk): verify there's no problem that now this RFH will only
+ // be set as the pending one *after* this delegate call (used to be
+ // before).
+ if (new_render_frame_host) {
+ render_frame_delegate_->RenderFrameCreated(
+ new_render_frame_host.get());
+ }
+ }
}
- routing_id = render_view_host->GetRoutingID();
- frame_to_announce = new_render_frame_host.get();
}
- // Use this as our new pending RFH if it isn't swapped out.
- if (!swapped_out)
- pending_render_frame_host_ = new_render_frame_host.Pass();
-
- // If a brand new RFH was created, announce it to observers.
- if (frame_to_announce)
- render_frame_delegate_->RenderFrameCreated(frame_to_announce);
-
- return routing_id;
+ // Returns the new RFH if it isn't swapped out.
+ if (success && !swapped_out) {
+ DCHECK(new_render_frame_host->GetSiteInstance() == instance);
+ return new_render_frame_host.Pass();
+ }
+ return nullptr;
}
int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) {
@@ -1247,32 +1391,43 @@ 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) {
nasko 2014/11/25 00:19:10 Can't this be just a check for browser-site-naviga
carlosk 2014/11/28 13:08:17 Indeed, now it can! Great catch! :)
+ 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();
+ if (!should_reuse_web_ui_)
+ 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;
@@ -1286,10 +1441,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();
@@ -1418,6 +1582,33 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation(
url, instance, transition, is_restore, is_view_source_mode);
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
+ if (current_instance == new_instance.get()) {
+ CleanUpNavigation();
+ } else {
+ // If the SiteInstance for the final URL doesn't match the one form the
+ // speculatively created RenderFrameHost, create a new one using the
+ // former.
+ if (!speculative_render_frame_host_ ||
+ speculative_render_frame_host_->GetSiteInstance() !=
+ new_instance.get()) {
+ CleanUpNavigation();
+ // TODO(carlosk): Should rename this method and the speculative members
+ // because in this case they are not speculative. Suggestions are
+ // very welcome!
+ bool success = CreateSpeculativeRenderFrameHost(
+ url, current_instance, new_instance.get(), bindings);
+ if (!success)
+ return nullptr;
+ }
+ DCHECK(speculative_render_frame_host_);
+ CommitPending(true);
+ DCHECK(!speculative_render_frame_host_);
+ }
+ return render_frame_host_.get();
+ }
+
const NavigationEntry* current_entry =
delegate_->GetLastCommittedNavigationEntryForRenderManager();
@@ -1453,7 +1644,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();
@@ -1558,24 +1749,7 @@ 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();
- }
+ DiscardRenderFrameHost(pending_render_frame_host.Pass());
pending_web_ui_.reset();
pending_and_current_web_ui_.reset();

Powered by Google App Engine
This is Rietveld 408576698