X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fcontent%2Fbrowser%2Fframe_host%2Frender_frame_host_manager.cc;h=c871e0430c7229a4232c80fb27728e24a491857a;hb=ff3e2503a20db9193d323c1d19c38c68004dec4a;hp=5738861afde58d76599a11046288aee3948dfed6;hpb=7338fba38ba696536d1cc9d389afd716a6ab2fe6;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/content/browser/frame_host/render_frame_host_manager.cc b/src/content/browser/frame_host/render_frame_host_manager.cc index 5738861..c871e04 100644 --- a/src/content/browser/frame_host/render_frame_host_manager.cc +++ b/src/content/browser/frame_host/render_frame_host_manager.cc @@ -12,11 +12,13 @@ #include "content/browser/child_process_security_policy_impl.h" #include "content/browser/devtools/render_view_devtools_agent_host.h" #include "content/browser/frame_host/cross_process_frame_connector.h" +#include "content/browser/frame_host/debug_urls.h" #include "content/browser/frame_host/interstitial_page_impl.h" #include "content/browser/frame_host/navigation_controller_impl.h" #include "content/browser/frame_host/navigation_entry_impl.h" #include "content/browser/frame_host/render_frame_host_factory.h" #include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/browser/renderer_host/cross_site_transferring_request.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_view_host_factory.h" #include "content/browser/renderer_host/render_view_host_impl.h" @@ -36,20 +38,16 @@ namespace content { -RenderFrameHostManager::PendingNavigationParams::PendingNavigationParams() - : is_transfer(false), frame_id(-1), should_replace_current_entry(false) { -} - RenderFrameHostManager::PendingNavigationParams::PendingNavigationParams( const GlobalRequestID& global_request_id, - bool is_transfer, + scoped_ptr cross_site_transferring_request, const std::vector& transfer_url_chain, Referrer referrer, PageTransition page_transition, int64 frame_id, bool should_replace_current_entry) : global_request_id(global_request_id), - is_transfer(is_transfer), + cross_site_transferring_request(cross_site_transferring_request.Pass()), transfer_url_chain(transfer_url_chain), referrer(referrer), page_transition(page_transition), @@ -74,7 +72,8 @@ RenderFrameHostManager::RenderFrameHostManager( render_frame_host_(NULL), pending_render_frame_host_(NULL), interstitial_page_(NULL), - cross_process_frame_connector_(NULL) {} + cross_process_frame_connector_(NULL), + weak_factory_(this) {} RenderFrameHostManager::~RenderFrameHostManager() { if (pending_render_frame_host_) @@ -205,6 +204,15 @@ RenderFrameHostImpl* RenderFrameHostManager::Navigate( } } + // If entry includes the request ID of a request that is being transferred, + // the destination render frame will take ownership, so release ownership of + // the request. + if (pending_nav_params_ && + pending_nav_params_->global_request_id == + entry.transferred_global_request_id()) { + pending_nav_params_->cross_site_transferring_request->ReleaseRequest(); + } + return dest_render_frame_host; } @@ -236,7 +244,7 @@ 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. @@ -277,7 +285,7 @@ void RenderFrameHostManager::SwappedOut(RenderViewHost* render_view_host) { // TODO(creis): The blank swapped out page is visible during this time, but // we can shorten this by delivering the response directly, rather than // forcing an identical request to be made. - if (pending_nav_params_->is_transfer) { + if (pending_nav_params_->cross_site_transferring_request) { // Treat the last URL in the chain as the destination and the remainder as // the redirect chain. CHECK(pending_nav_params_->transfer_url_chain.size()); @@ -326,7 +334,7 @@ void RenderFrameHostManager::SwappedOutFrame( // TODO(creis): The blank swapped out page is visible during this time, but // we can shorten this by delivering the response directly, rather than // forcing an identical request to be made. - if (pending_nav_params_->is_transfer) { + if (pending_nav_params_->cross_site_transferring_request) { // Treat the last URL in the chain as the destination and the remainder as // the redirect chain. CHECK(pending_nav_params_->transfer_url_chain.size()); @@ -478,7 +486,7 @@ void RenderFrameHostManager::ShouldClosePage( void RenderFrameHostManager::OnCrossSiteResponse( RenderViewHost* pending_render_view_host, const GlobalRequestID& global_request_id, - bool is_transfer, + scoped_ptr cross_site_transferring_request, const std::vector& transfer_url_chain, const Referrer& referrer, PageTransition page_transition, @@ -494,10 +502,12 @@ void RenderFrameHostManager::OnCrossSiteResponse( // here, but currently we pass information for a transfer if // ShouldSwapProcessesForRedirect returned true in the network stack. // In that case, we should set up a transfer after the unload handler runs. - // If is_transfer is false, we will just run the unload handler and resume. + // If |cross_site_transferring_request| is NULL, we will just run the unload + // handler and resume. pending_nav_params_.reset(new PendingNavigationParams( - global_request_id, is_transfer, transfer_url_chain, referrer, - page_transition, frame_id, should_replace_current_entry)); + global_request_id, cross_site_transferring_request.Pass(), + transfer_url_chain, referrer, page_transition, frame_id, + should_replace_current_entry)); // Run the unload handler of the current page. SwapOutOldPage(); @@ -539,6 +549,15 @@ void RenderFrameHostManager::SwapOutOldPage() { } } +void RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance( + int32 site_instance_id, + RenderFrameHostImpl* rfh) { + RFHPendingDeleteMap::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, @@ -560,8 +579,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::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) { + node->render_manager()->pending_delete_hosts_[site_instance_id] = + linked_ptr(swapped_out_rfh); + } + } else { + delete swapped_out_rfh; + } + node->render_manager()->swapped_out_hosts_.erase(site_instance_id); + } return true; } @@ -602,6 +643,11 @@ bool RenderFrameHostManager::ShouldSwapBrowsingInstancesForNavigation( const GURL& new_url = SiteInstanceImpl::GetEffectiveURL(browser_context, new_entry->GetURL()); + // Don't force a new BrowsingInstance for debug URLs that are handled in the + // renderer process, like javascript: or chrome://crash. + if (IsRendererDebugURL(new_url)) + return false; + // For security, we should transition between processes when one is a Web UI // page and one isn't. if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL( @@ -781,10 +827,13 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForEntry( current_instance->GetSiteURL(); // View-source URLs must use a new SiteInstance and BrowsingInstance. + // We don't need a swap when going from view-source to a debug URL like + // chrome://crash, however. // TODO(creis): Refactor this method so this duplicated code isn't needed. // See http://crbug.com/123007. if (current_entry && - current_entry->IsViewSourceMode() != entry.IsViewSourceMode()) { + current_entry->IsViewSourceMode() != entry.IsViewSourceMode() && + !IsRendererDebugURL(dest_url)) { return SiteInstance::CreateForURL(browser_context, dest_url); } @@ -944,7 +993,7 @@ bool RenderFrameHostManager::InitRenderView(RenderViewHost* render_view_host, // process unless it's swapped out. RenderViewHostImpl* rvh_impl = static_cast(render_view_host); - if (!rvh_impl->is_swapped_out()) { + if (!rvh_impl->IsSwappedOut()) { CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( render_view_host->GetProcess()->GetID())); } @@ -972,10 +1021,14 @@ void RenderFrameHostManager::CommitPending() { // |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_) + if (pending_web_ui_) { web_ui_.reset(pending_web_ui_.release()); - else if (!pending_and_current_web_ui_.get()) + } 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(); + } // 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 @@ -1019,10 +1072,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); @@ -1056,18 +1115,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() && @@ -1075,7 +1133,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, + // the RenderFrameHost should be put in the map of RenderFrameHosts pending + // shutdown. Otherwise, it is stored in the map of swapped out + // RenderFrameHosts. + if (old_render_frame_host->render_view_host()->rvh_state() == + RenderViewHostImpl::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(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 @@ -1118,7 +1192,6 @@ void RenderFrameHostManager::ShutdownRenderFrameHostsInSiteInstance( tree->ForEach(base::Bind( &RenderFrameHostManager::ClearSwappedOutRFHsInSiteInstance, site_instance_id)); - // rvh is now deleted. } } }