| Index: content/browser/web_contents/render_view_host_manager.cc
|
| diff --git a/content/browser/web_contents/render_view_host_manager.cc b/content/browser/web_contents/render_view_host_manager.cc
|
| index 66d8244086cc2897e9f56166e7d9027b4a3bb1d8..14334789e41fba615bbc00cab4dd602b17bbd2ba 100644
|
| --- a/content/browser/web_contents/render_view_host_manager.cc
|
| +++ b/content/browser/web_contents/render_view_host_manager.cc
|
| @@ -32,12 +32,19 @@
|
|
|
| namespace content {
|
|
|
| -RenderViewHostManager::PendingNavigationParams::PendingNavigationParams() {
|
| +RenderViewHostManager::PendingNavigationParams::PendingNavigationParams()
|
| + : frame_id(-1) {
|
| }
|
|
|
| RenderViewHostManager::PendingNavigationParams::PendingNavigationParams(
|
| + const GURL& new_url,
|
| + Referrer referrer,
|
| + int64 frame_id,
|
| const GlobalRequestID& global_request_id)
|
| - : global_request_id(global_request_id) {
|
| + : new_url(new_url),
|
| + referrer(referrer),
|
| + frame_id(frame_id),
|
| + global_request_id(global_request_id) {
|
| }
|
|
|
| RenderViewHostManager::RenderViewHostManager(
|
| @@ -230,8 +237,20 @@ void RenderViewHostManager::SwappedOut(RenderViewHost* render_view_host) {
|
| return;
|
| }
|
|
|
| - // Now that the unload handler has run, we need to resume the paused response.
|
| - if (pending_render_view_host_) {
|
| + // Now that the unload handler has run, we need to either initiate the
|
| + // pending transfer (if there is one) or resume the paused response (if not).
|
| + // 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_->new_url.is_empty()) {
|
| + render_view_host->GetDelegate()->RequestTransferURL(
|
| + pending_nav_params_->new_url,
|
| + pending_nav_params_->referrer,
|
| + CURRENT_TAB,
|
| + pending_nav_params_->frame_id,
|
| + pending_nav_params_->global_request_id,
|
| + false);
|
| + } else if (pending_render_view_host_) {
|
| RenderProcessHostImpl* pending_process =
|
| static_cast<RenderProcessHostImpl*>(
|
| pending_render_view_host_->GetProcess());
|
| @@ -361,22 +380,31 @@ void RenderViewHostManager::ShouldClosePage(
|
|
|
| void RenderViewHostManager::OnCrossSiteResponse(
|
| RenderViewHost* pending_render_view_host,
|
| + const GURL& pending_url,
|
| + const Referrer& referrer,
|
| + int64 frame_id,
|
| const GlobalRequestID& global_request_id) {
|
| - // This should be called when the pending RVH is ready to commit.
|
| - DCHECK_EQ(pending_render_view_host_, pending_render_view_host);
|
| -
|
| - // Remember the request ID until the unload handler has run.
|
| - pending_nav_params_.reset(new PendingNavigationParams(global_request_id));
|
| + // This should be called either when the pending RVH is ready to commit or
|
| + // when we realize that the current RVH's request requires a transfer.
|
| + DCHECK(
|
| + pending_render_view_host == pending_render_view_host_ ||
|
| + pending_render_view_host == render_view_host_);
|
| +
|
| + // TODO(creis): Eventually we will want to check all navigation responses
|
| + // here, but currently we only pass a non-empty URL if
|
| + // ShouldSwapProcessesForRedirect returned true in the network stack.
|
| + // In that case, we should set up a transfer after the unload handler runs.
|
| + // If new_url is empty, we will just run the unload handler and resume.
|
| + pending_nav_params_.reset(new PendingNavigationParams(
|
| + pending_url, referrer, frame_id, global_request_id));
|
|
|
| // Run the unload handler of the current page.
|
| SwapOutOldPage();
|
| }
|
|
|
| void RenderViewHostManager::SwapOutOldPage() {
|
| - // Should only see this while we have a pending renderer.
|
| - if (!cross_navigation_pending_)
|
| - return;
|
| - DCHECK(pending_render_view_host_);
|
| + // Should only see this while we have a pending renderer or transfer.
|
| + CHECK(cross_navigation_pending_ || pending_nav_params_.get());
|
|
|
| // 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
|
| @@ -389,7 +417,8 @@ void RenderViewHostManager::SwapOutOldPage() {
|
| // means it is not a download or unsafe page, and we are going to perform the
|
| // navigation. Thus, we no longer need to remember that the RenderViewHost
|
| // is part of a pending cross-site request.
|
| - pending_render_view_host_->SetHasPendingCrossSiteRequest(false);
|
| + if (pending_render_view_host_)
|
| + pending_render_view_host_->SetHasPendingCrossSiteRequest(false);
|
| }
|
|
|
| void RenderViewHostManager::Observe(
|
| @@ -873,7 +902,12 @@ RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate(
|
| DCHECK(!pending_render_view_host_->are_navigations_suspended());
|
| bool is_transfer =
|
| entry.transferred_global_request_id() != GlobalRequestID();
|
| - if (!is_transfer) {
|
| + if (is_transfer) {
|
| + // We don't need to stop the old renderer or run beforeunload/unload
|
| + // handlers, because those have already been done.
|
| + DCHECK(pending_nav_params_->global_request_id ==
|
| + entry.transferred_global_request_id());
|
| + } else {
|
| // Also make sure the old render view stops, in case a load is in
|
| // progress. (We don't want to do this for transfers, since it will
|
| // interrupt the transfer with an unexpected DidStopLoading.)
|
| @@ -882,12 +916,12 @@ RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate(
|
|
|
| pending_render_view_host_->SetNavigationsSuspended(true,
|
| base::TimeTicks());
|
| - }
|
|
|
| - // Tell the CrossSiteRequestManager that this RVH has a pending cross-site
|
| - // request, so that ResourceDispatcherHost will know to tell us to run the
|
| - // old page's unload handler before it sends the response.
|
| - pending_render_view_host_->SetHasPendingCrossSiteRequest(true);
|
| + // Tell the CrossSiteRequestManager that this RVH has a pending cross-site
|
| + // request, so that ResourceDispatcherHost will know to tell us to run the
|
| + // old page's unload handler before it sends the response.
|
| + pending_render_view_host_->SetHasPendingCrossSiteRequest(true);
|
| + }
|
|
|
| // We now have a pending RVH.
|
| DCHECK(!cross_navigation_pending_);
|
|
|