Chromium Code Reviews| 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 885a6b628e80e3ebe16f5444f275d6666581c0d2..b738a3eb6295a8b09d87312ff9d881780731bc30 100644 | 
| --- a/content/browser/frame_host/render_frame_host_manager.cc | 
| +++ b/content/browser/frame_host/render_frame_host_manager.cc | 
| @@ -72,7 +72,8 @@ RenderFrameHostManager::RenderFrameHostManager( | 
| render_widget_delegate_(render_widget_delegate), | 
| render_frame_host_(NULL), | 
| pending_render_frame_host_(NULL), | 
| - interstitial_page_(NULL) { | 
| + interstitial_page_(NULL), | 
| + weak_factory_(this) { | 
| } | 
| RenderFrameHostManager::~RenderFrameHostManager() { | 
| @@ -232,13 +233,14 @@ bool RenderFrameHostManager::ShouldCloseTabOnUnresponsiveRenderer() { | 
| // If the tab becomes unresponsive during {before}unload while doing a | 
| // cross-site navigation, proceed with the navigation. (This assumes that | 
| // the pending RenderFrameHost is still responsive.) | 
| - if (render_frame_host_->render_view_host()->is_waiting_for_unload_ack()) { | 
| + if (render_frame_host_->render_view_host()->IsWaitingForUnloadACK()) { | 
| // The request has been started and paused while we're waiting for the | 
| // unload handler to finish. We'll pretend that it did. 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 pending_nav_params_ state will already be cleaned up.) | 
| - current_host()->OnSwappedOut(true); | 
| + current_host()->SwapOut(); | 
| 
 
nasko
2014/01/23 23:34:58
Calling SwapOut() will cause us to run the unload
 
clamy
2014/01/24 17:01:54
Done.
 
 | 
| + current_host()->OnSwappedOut(false); | 
| } else if (render_frame_host_->render_view_host()-> | 
| is_waiting_for_beforeunload_ack()) { | 
| // Haven't gotten around to starting the request, because we're still | 
| @@ -535,6 +537,15 @@ void RenderFrameHostManager::SwapOutOldPage() { | 
| } | 
| } | 
| +void RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance( | 
| + int32 site_instance_id, | 
| + RenderFrameHostImpl* rfh) { | 
| + base::hash_map<int32, linked_ptr<RenderFrameHostImpl> >::iterator iter = | 
| + pending_delete_hosts_.find(site_instance_id); | 
| + if (iter != pending_delete_hosts_.end() && iter->second.get() == rfh) | 
| + pending_delete_hosts_.erase(site_instance_id); | 
| +} | 
| + | 
| void RenderFrameHostManager::Observe( | 
| int type, | 
| const NotificationSource& source, | 
| @@ -556,8 +567,30 @@ bool RenderFrameHostManager::ClearSwappedOutRFHsInSiteInstance( | 
| FrameTreeNode* node) { | 
| RenderFrameHostMap::iterator iter = | 
| node->render_manager()->swapped_out_hosts_.find(site_instance_id); | 
| - if (iter != node->render_manager()->swapped_out_hosts_.end()) | 
| - delete iter->second; | 
| + if (iter != node->render_manager()->swapped_out_hosts_.end()) { | 
| + RenderFrameHostImpl* swapped_out_rfh = iter->second; | 
| + // If the RVH is pending swap out, it needs to switch state to | 
| + // pending shutdown. Otherwise it is deleted. | 
| + if (swapped_out_rfh->render_view_host()->rvh_state() == | 
| + RenderViewHostImpl::RVH_STATE_PENDING_SWAP_OUT) { | 
| + swapped_out_rfh->SetPendingShutdown(base::Bind( | 
| + &RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance, | 
| + node->render_manager()->weak_factory_.GetWeakPtr(), | 
| + site_instance_id, | 
| + swapped_out_rfh)); | 
| + RFHPendingDeleteMap::iterator pending_delete_iter = | 
| + node->render_manager()->pending_delete_hosts_.find(site_instance_id); | 
| + if (pending_delete_iter == | 
| + node->render_manager()->pending_delete_hosts_.end() || | 
| + pending_delete_iter->second.get() != iter->second) { | 
| 
 
nasko
2014/01/23 23:34:58
What happens if there is already an entry for this
 
clamy
2014/01/24 17:01:54
Since it is stored in a linked_ptr, the only ref o
 
 | 
| + node->render_manager()->pending_delete_hosts_[site_instance_id] = | 
| + linked_ptr<RenderFrameHostImpl>(swapped_out_rfh); | 
| + } | 
| + } else { | 
| + delete swapped_out_rfh; | 
| + } | 
| + node->render_manager()->swapped_out_hosts_.erase(site_instance_id); | 
| + } | 
| return true; | 
| } | 
| @@ -911,7 +944,7 @@ bool RenderFrameHostManager::InitRenderView(RenderViewHost* render_view_host, | 
| // process unless it's swapped out. | 
| RenderViewHostImpl* rvh_impl = | 
| static_cast<RenderViewHostImpl*>(render_view_host); | 
| - if (!rvh_impl->is_swapped_out()) { | 
| + if (rvh_impl->rvh_state() != RenderViewHostImpl::RVH_STATE_SWAPPED_OUT) { | 
| CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( | 
| render_view_host->GetProcess()->GetID())); | 
| } | 
| @@ -986,10 +1019,16 @@ void RenderFrameHostManager::CommitPending() { | 
| // If the old view is live and top-level, hide it now that the new one is | 
| // visible. | 
| + int32 old_site_instance_id = | 
| + old_render_frame_host->render_view_host()->GetSiteInstance()->GetId(); | 
| if (old_render_frame_host->render_view_host()->GetView()) { | 
| if (is_main_frame) { | 
| old_render_frame_host->render_view_host()->GetView()->Hide(); | 
| - old_render_frame_host->render_view_host()->WasSwappedOut(); | 
| + old_render_frame_host->render_view_host()->WasSwappedOut(base::Bind( | 
| + &RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance, | 
| + weak_factory_.GetWeakPtr(), | 
| + old_site_instance_id, | 
| + old_render_frame_host)); | 
| } else { | 
| // TODO(creis): We'll need to set this back to false if we navigate back. | 
| old_render_frame_host->set_swapped_out(true); | 
| @@ -1023,18 +1062,17 @@ void RenderFrameHostManager::CommitPending() { | 
| if (old_render_frame_host->render_view_host()->IsRenderViewLive()) { | 
| // If the old RFH is live, we are swapping it out and should keep track of | 
| - // it in case we navigate back to it. | 
| + // it in case we navigate back to it, or it is waiting for the unload event | 
| + // to execute in the background. | 
| // TODO(creis): Swap out the subframe in --site-per-process. | 
| if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) | 
| DCHECK(old_render_frame_host->is_swapped_out() || | 
| - old_render_frame_host->render_view_host()->is_swapped_out()); | 
| - | 
| + !RenderViewHostImpl::IsRVHStateActive( | 
| + old_render_frame_host->render_view_host()->rvh_state())); | 
| // Temp fix for http://crbug.com/90867 until we do a better cleanup to make | 
| // sure we don't get different rvh instances for the same site instance | 
| // in the same rvhmgr. | 
| // TODO(creis): Clean this up. | 
| - int32 old_site_instance_id = | 
| - old_render_frame_host->render_view_host()->GetSiteInstance()->GetId(); | 
| RenderFrameHostMap::iterator iter = | 
| swapped_out_hosts_.find(old_site_instance_id); | 
| if (iter != swapped_out_hosts_.end() && | 
| @@ -1042,7 +1080,23 @@ void RenderFrameHostManager::CommitPending() { | 
| // Delete the RFH that will be replaced in the map to avoid a leak. | 
| delete iter->second; | 
| } | 
| - swapped_out_hosts_[old_site_instance_id] = old_render_frame_host; | 
| + // If the RenderViewHost backing the RenderFrameHost is pending shutdown, | 
| 
 
nasko
2014/01/23 23:34:58
nit: You are mixing terminology - pending shutdown
 
clamy
2014/01/24 17:01:54
We call delete on the RenderFrameHost, which will
 
nasko
2014/01/27 19:09:51
I think it is best we keep it using "delete", sinc
 
 | 
| + // the RenderFrameHost should be put in the map of RenderFrameHost pending | 
| + // shutdown. Otherwise, it is stored in the map of swapped out | 
| + // RenderFrameHosts. | 
| + if (old_render_frame_host->render_view_host()->rvh_state() == | 
| + RenderViewHostImpl::RVH_STATE_PENDING_SHUTDOWN) { | 
| + swapped_out_hosts_.erase(old_site_instance_id); | 
| + RFHPendingDeleteMap::iterator pending_delete_iter = | 
| + pending_delete_hosts_.find(old_site_instance_id); | 
| + if (pending_delete_iter == pending_delete_hosts_.end() || | 
| + pending_delete_iter->second.get() != old_render_frame_host) { | 
| + pending_delete_hosts_[old_site_instance_id] = | 
| + linked_ptr<RenderFrameHostImpl>(old_render_frame_host); | 
| + } | 
| + } else { | 
| + swapped_out_hosts_[old_site_instance_id] = old_render_frame_host; | 
| + } | 
| // If there are no active views in this SiteInstance, it means that | 
| // this RFH was the last active one in the SiteInstance. Now that we | 
| @@ -1085,7 +1139,6 @@ void RenderFrameHostManager::ShutdownRenderFrameHostsInSiteInstance( | 
| tree->ForEach(base::Bind( | 
| &RenderFrameHostManager::ClearSwappedOutRFHsInSiteInstance, | 
| site_instance_id)); | 
| - // rvh is now deleted. | 
| } | 
| } | 
| } |