| Index: content/browser/tab_contents/render_view_host_manager.cc
|
| diff --git a/content/browser/tab_contents/render_view_host_manager.cc b/content/browser/tab_contents/render_view_host_manager.cc
|
| index 973a1d0e7832c4490cc74e698f2fce67dfc8d133..d06ccf53afe70d572d8491ef56e234636ac5621c 100644
|
| --- a/content/browser/tab_contents/render_view_host_manager.cc
|
| +++ b/content/browser/tab_contents/render_view_host_manager.cc
|
| @@ -49,6 +49,13 @@ RenderViewHostManager::~RenderViewHostManager() {
|
| RenderViewHost* render_view_host = render_view_host_;
|
| render_view_host_ = NULL;
|
| render_view_host->Shutdown();
|
| +
|
| + // Shut down any swapped out RenderViewHosts.
|
| + for (RenderViewHostMap::iterator iter = swapped_out_hosts_.begin();
|
| + iter != swapped_out_hosts_.end();
|
| + ++iter) {
|
| + iter->second->Shutdown();
|
| + }
|
| }
|
|
|
| void RenderViewHostManager::Init(Profile* profile,
|
| @@ -148,21 +155,17 @@ bool RenderViewHostManager::ShouldCloseTabOnUnresponsiveRenderer() {
|
| if (pending_render_view_host_->are_navigations_suspended())
|
| pending_render_view_host_->SetNavigationsSuspended(false);
|
| } else {
|
| - // The request has been started and paused, while we're waiting for the
|
| + // The request has been started and paused while we're waiting for the
|
| // unload handler to finish. We'll pretend that it did, by notifying the
|
| // IO thread to let the response continue. The pending renderer will then
|
| // be swapped in as part of the usual DidNavigate logic. (If the unload
|
| // handler later finishes, this call will be ignored because the state in
|
| // CrossSiteResourceHandler will already be cleaned up.)
|
| - ViewMsg_ClosePage_Params params;
|
| - params.closing_process_id =
|
| - render_view_host_->process()->id();
|
| - params.closing_route_id = render_view_host_->routing_id();
|
| - params.for_cross_site_transition = true;
|
| + ViewMsg_SwapOut_Params params;
|
| params.new_render_process_host_id =
|
| pending_render_view_host_->process()->id();
|
| params.new_request_id = pending_request_id;
|
| - current_host()->process()->CrossSiteClosePageACK(params);
|
| + current_host()->process()->CrossSiteSwapOutACK(params);
|
| }
|
| return false;
|
| }
|
| @@ -244,7 +247,7 @@ void RenderViewHostManager::ShouldClosePage(bool for_cross_site_transition,
|
|
|
| if (proceed_to_fire_unload) {
|
| // This is not a cross-site navigation, the tab is being closed.
|
| - render_view_host_->ClosePage(false, -1, -1);
|
| + render_view_host_->ClosePage();
|
| }
|
| }
|
| }
|
| @@ -256,12 +259,12 @@ void RenderViewHostManager::OnCrossSiteResponse(int new_render_process_host_id,
|
| return;
|
| DCHECK(pending_render_view_host_);
|
|
|
| - // Tell the old renderer to run its onunload handler. When it finishes, it
|
| - // will send a ClosePage_ACK to the ResourceDispatcherHost with the given
|
| - // IDs (of the pending RVH's request), allowing the pending RVH's response to
|
| - // resume.
|
| - render_view_host_->ClosePage(true,
|
| - new_render_process_host_id, new_request_id);
|
| + // Tell the old renderer it is being swapped out. This will fire the unload
|
| + // handler (without firing the beforeunload handler a second time). When the
|
| + // unload handler finishes and the navigation completes, we will send a
|
| + // message to the ResourceDispatcherHost with the given pending request IDs,
|
| + // allowing the pending RVH's response to resume.
|
| + render_view_host_->SwapOut(new_render_process_host_id, new_request_id);
|
|
|
| // ResourceDispatcherHost has told us to run the onunload handler, which
|
| // means it is not a download or unsafe page, and we are going to perform the
|
| @@ -459,6 +462,17 @@ bool RenderViewHostManager::CreatePendingRenderView(
|
| // we're about to switch away, so that it sends an UpdateState message.
|
| }
|
|
|
| + // Check if we've already created an RVH for this SiteInstance.
|
| + CHECK(instance);
|
| + RenderViewHostMap::iterator iter =
|
| + swapped_out_hosts_.find(instance->id());
|
| + if (iter != swapped_out_hosts_.end()) {
|
| + // Re-use the existing RenderViewHost, which has already been initialized.
|
| + // We'll remove it from the list of swapped out hosts if it commits.
|
| + pending_render_view_host_ = iter->second;
|
| + return true;
|
| + }
|
| +
|
| pending_render_view_host_ = RenderViewHostFactory::Create(
|
| instance, render_view_delegate_, MSG_ROUTING_NONE, delegate_->
|
| GetControllerForRenderManager().session_storage_namespace());
|
| @@ -515,9 +529,7 @@ void RenderViewHostManager::CommitPending() {
|
| bool focus_render_view = !will_focus_location_bar &&
|
| render_view_host_->view() && render_view_host_->view()->HasFocus();
|
|
|
| - // Hide the current view and prepare to destroy it.
|
| - // TODO(creis): Get the old RenderViewHost to send us an UpdateState message
|
| - // before we destroy it.
|
| + // Hide the current view and prepare to swap it out.
|
| if (render_view_host_->view())
|
| render_view_host_->view()->Hide();
|
| RenderViewHost* old_render_view_host = render_view_host_;
|
| @@ -526,6 +538,13 @@ void RenderViewHostManager::CommitPending() {
|
| render_view_host_ = pending_render_view_host_;
|
| pending_render_view_host_ = NULL;
|
|
|
| + // If the pending view was on the swapped out list, we can remove it.
|
| + RenderViewHostMap::iterator iter = swapped_out_hosts_.find(
|
| + render_view_host_->site_instance()->id());
|
| + if (iter != swapped_out_hosts_.end()) {
|
| + swapped_out_hosts_.erase(iter);
|
| + }
|
| +
|
| // If the view is gone, then this RenderViewHost died while it was hidden.
|
| // We ignored the RenderViewGone call at the time, so we should send it now
|
| // to make sure the sad tab shows up, etc.
|
| @@ -550,7 +569,9 @@ void RenderViewHostManager::CommitPending() {
|
| Source<NavigationController>(&delegate_->GetControllerForRenderManager()),
|
| Details<RenderViewHostSwitchedDetails>(&details));
|
|
|
| - old_render_view_host->Shutdown();
|
| + // Keep track of the old swapped out RVH in case we navigate back to it.
|
| + swapped_out_hosts_[old_render_view_host->site_instance()->id()] =
|
| + old_render_view_host;
|
|
|
| // Let the task manager know that we've swapped RenderViewHosts, since it
|
| // might need to update its process groupings.
|
| @@ -661,7 +682,11 @@ RenderViewHost* RenderViewHostManager::UpdateRendererStateForNavigate(
|
| void RenderViewHostManager::CancelPending() {
|
| RenderViewHost* pending_render_view_host = pending_render_view_host_;
|
| pending_render_view_host_ = NULL;
|
| - pending_render_view_host->Shutdown();
|
| +
|
| + // Only shutdown the pending RVH if it isn't currently swapped out.
|
| + // This can happen if we abort a pending load.
|
| + if (!IsSwappedOut(pending_render_view_host))
|
| + pending_render_view_host->Shutdown();
|
|
|
| pending_web_ui_.reset();
|
| }
|
| @@ -681,9 +706,10 @@ void RenderViewHostManager::RenderViewDeleted(RenderViewHost* rvh) {
|
| }
|
|
|
| void RenderViewHostManager::SwapInRenderViewHost(RenderViewHost* rvh) {
|
| + // TODO(creis): Abstract out the common code between this and CommitPending.
|
| web_ui_.reset();
|
|
|
| - // Hide the current view and prepare to destroy it.
|
| + // Hide the current view and prepare to swap it out.
|
| if (render_view_host_->view())
|
| render_view_host_->view()->Hide();
|
| RenderViewHost* old_render_view_host = render_view_host_;
|
| @@ -704,6 +730,13 @@ void RenderViewHostManager::SwapInRenderViewHost(RenderViewHost* rvh) {
|
| render_view_host_->view()->Show();
|
| }
|
|
|
| + // If the given RVH was on the swapped out list, we can remove it.
|
| + RenderViewHostMap::iterator iter = swapped_out_hosts_.find(
|
| + render_view_host_->site_instance()->id());
|
| + if (iter != swapped_out_hosts_.end()) {
|
| + swapped_out_hosts_.erase(iter);
|
| + }
|
| +
|
| delegate_->UpdateRenderViewSizeForRenderManager();
|
|
|
| RenderViewHostSwitchedDetails details;
|
| @@ -714,10 +747,19 @@ void RenderViewHostManager::SwapInRenderViewHost(RenderViewHost* rvh) {
|
| Source<NavigationController>(&delegate_->GetControllerForRenderManager()),
|
| Details<RenderViewHostSwitchedDetails>(&details));
|
|
|
| - // This will cause the old RenderViewHost to delete itself.
|
| - old_render_view_host->Shutdown();
|
| + // Keep track of the old swapped out RVH in case we navigate back to it.
|
| + swapped_out_hosts_[old_render_view_host->site_instance()->id()] =
|
| + old_render_view_host;
|
|
|
| // Let the task manager know that we've swapped RenderViewHosts, since it
|
| // might need to update its process groupings.
|
| delegate_->NotifySwappedFromRenderManager();
|
| }
|
| +
|
| +bool RenderViewHostManager::IsSwappedOut(RenderViewHost* rvh) {
|
| + if (!rvh->site_instance())
|
| + return false;
|
| +
|
| + return swapped_out_hosts_.find(rvh->site_instance()->id()) !=
|
| + swapped_out_hosts_.end();
|
| +}
|
|
|