summaryrefslogtreecommitdiffstats
path: root/content/browser/loader/cross_site_resource_handler.cc
diff options
context:
space:
mode:
authorcreis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-01 20:12:54 +0000
committercreis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-01 20:12:54 +0000
commit37403f36a6984400c226fda2afd139be51043a1c (patch)
tree72b6ca06acd47399f37a784a8bb2c96d8dde44fc /content/browser/loader/cross_site_resource_handler.cc
parent584a1aaa6645e49fc05fb7a43c7d6693c329f01e (diff)
downloadchromium_src-37403f36a6984400c226fda2afd139be51043a1c.zip
chromium_src-37403f36a6984400c226fda2afd139be51043a1c.tar.gz
chromium_src-37403f36a6984400c226fda2afd139be51043a1c.tar.bz2
Move TransferNavigationResourceThrottle into CrossSiteResourceHandler.
We now transfer requests to a new process when they are ready to commit, rather than each time a redirect occurs. This simplifies the ResourceDispatcherHost logic, and it prepares for a future CL to intercept all navigations in the browser process. BUG=238331 TEST=No more than one process swap for repeated redirects. Review URL: https://codereview.chromium.org/15476003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@226284 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/loader/cross_site_resource_handler.cc')
-rw-r--r--content/browser/loader/cross_site_resource_handler.cc92
1 files changed, 67 insertions, 25 deletions
diff --git a/content/browser/loader/cross_site_resource_handler.cc b/content/browser/loader/cross_site_resource_handler.cc
index 90fe84a..6bac75a 100644
--- a/content/browser/loader/cross_site_resource_handler.cc
+++ b/content/browser/loader/cross_site_resource_handler.cc
@@ -9,14 +9,17 @@
#include "base/bind.h"
#include "base/logging.h"
#include "content/browser/cross_site_request_manager.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/resource_controller.h"
#include "content/public/common/resource_response.h"
#include "net/http/http_response_headers.h"
+#include "net/url_request/url_request.h"
namespace content {
@@ -24,13 +27,21 @@ namespace {
void OnCrossSiteResponseHelper(int render_process_id,
int render_view_id,
- int request_id) {
+ const GlobalRequestID& global_request_id,
+ bool is_transfer,
+ const GURL& transfer_url,
+ const Referrer& referrer,
+ int64 frame_id) {
RenderViewHostImpl* rvh = RenderViewHostImpl::FromID(render_process_id,
render_view_id);
- if (rvh && rvh->GetDelegate()->GetRendererManagementDelegate()) {
- rvh->GetDelegate()->GetRendererManagementDelegate()->OnCrossSiteResponse(
- rvh, GlobalRequestID(render_process_id, request_id));
- }
+ if (!rvh)
+ return;
+ RenderViewHostDelegate* delegate = rvh->GetDelegate();
+ if (!delegate || !delegate->GetRendererManagementDelegate())
+ return;
+
+ delegate->GetRendererManagementDelegate()->OnCrossSiteResponse(
+ rvh, global_request_id, is_transfer, transfer_url, referrer, frame_id);
}
} // namespace
@@ -77,10 +88,16 @@ bool CrossSiteResourceHandler::OnResponseStarted(
ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request_);
- // A swap may no longer be needed if we transferred back into the original
- // process due to a redirect.
- bool swap_needed = CrossSiteRequestManager::GetInstance()->
- HasPendingCrossSiteRequest(info->GetChildID(), info->GetRouteID());
+ // We will need to swap processes if either (1) a redirect that requires a
+ // transfer occurred before we got here, or (2) a pending cross-site request
+ // was already in progress. Note that a swap may no longer be needed if we
+ // transferred back into the original process due to a redirect.
+ bool should_transfer =
+ GetContentClient()->browser()->ShouldSwapProcessesForRedirect(
+ info->GetContext(), request_->original_url(), request_->url());
+ bool swap_needed = should_transfer ||
+ CrossSiteRequestManager::GetInstance()->
+ HasPendingCrossSiteRequest(info->GetChildID(), info->GetRouteID());
// If this is a download, just pass the response through without doing a
// cross-site check. The renderer will see it is a download and abort the
@@ -90,8 +107,9 @@ bool CrossSiteResourceHandler::OnResponseStarted(
// page. We should allow the navigation to finish without running the unload
// handler or swapping in the pending RenderViewHost.
//
- // In both cases, the pending RenderViewHost will stick around until the next
- // cross-site navigation, since we are unable to tell when to destroy it.
+ // In both cases, any pending RenderViewHost (if one was created for this
+ // navigation) will stick around until the next cross-site navigation, since
+ // we are unable to tell when to destroy it.
// See RenderViewHostManager::RendererAbortedProvisionalLoad.
if (!swap_needed || info->is_download() ||
(response->head.headers.get() &&
@@ -99,8 +117,10 @@ bool CrossSiteResourceHandler::OnResponseStarted(
return next_handler_->OnResponseStarted(request_id, response, defer);
}
- // Tell the renderer to run the onunload event handler.
- StartCrossSiteTransition(request_id, response);
+ // Now that we know a swap is needed and we have something to commit, we
+ // pause to let the UI thread run the unload handler of the previous page
+ // and set up a transfer if needed.
+ StartCrossSiteTransition(request_id, response, should_transfer);
// Defer loading until after the onunload event handler has run.
did_defer_ = *defer = true;
@@ -119,19 +139,24 @@ bool CrossSiteResourceHandler::OnResponseCompleted(
const net::URLRequestStatus& status,
const std::string& security_info) {
if (!in_cross_site_transition_) {
+ ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
+ // If we've already completed the transition, or we're canceling the
+ // request, or an error occurred with no cross-process navigation in
+ // progress, then we should just pass this through.
if (has_started_response_ ||
- status.status() != net::URLRequestStatus::FAILED) {
- // We've already completed the transition or we're canceling the request,
- // so just pass it through.
+ status.status() != net::URLRequestStatus::FAILED ||
+ !CrossSiteRequestManager::GetInstance()->HasPendingCrossSiteRequest(
+ info->GetChildID(), info->GetRouteID())) {
return next_handler_->OnResponseCompleted(request_id, status,
security_info);
}
- // An error occured, we should wait now for the cross-site transition,
+ // An error occurred. We should wait now for the cross-process transition,
// so that the error message (e.g., 404) can be displayed to the user.
// Also continue with the logic below to remember that we completed
// during the cross-site transition.
- StartCrossSiteTransition(request_id, NULL);
+ StartCrossSiteTransition(request_id, NULL, false);
}
// We have to buffer the call until after the transition completes.
@@ -186,19 +211,35 @@ void CrossSiteResourceHandler::ResumeResponse() {
// telling the old RenderViewHost to run its onunload handler.
void CrossSiteResourceHandler::StartCrossSiteTransition(
int request_id,
- ResourceResponse* response) {
+ ResourceResponse* response,
+ bool should_transfer) {
in_cross_site_transition_ = true;
response_ = response;
// Store this handler on the ExtraRequestInfo, so that RDH can call our
- // ResumeResponse method when the close ACK is received.
+ // ResumeResponse method when we are ready to resume.
ResourceRequestInfoImpl* info =
ResourceRequestInfoImpl::ForRequest(request_);
info->set_cross_site_handler(this);
+ DCHECK_EQ(request_id, info->GetRequestID());
+ GlobalRequestID global_id(info->GetChildID(), info->GetRequestID());
+
// Tell the contents responsible for this request that a cross-site response
// is starting, so that it can tell its old renderer to run its onunload
- // handler now. We will wait to hear the corresponding ClosePage_ACK.
+ // handler now. We will wait until the unload is finished and (if a transfer
+ // is needed) for the new renderer's request to arrive.
+ GURL transfer_url;
+ Referrer referrer;
+ int frame_id = -1;
+ if (should_transfer) {
+ transfer_url = request_->url();
+ referrer = Referrer(GURL(request_->referrer()), info->GetReferrerPolicy());
+ frame_id = info->GetFrameID();
+
+ ResourceDispatcherHostImpl::Get()->MarkAsTransferredNavigation(
+ global_id, transfer_url);
+ }
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
@@ -206,10 +247,11 @@ void CrossSiteResourceHandler::StartCrossSiteTransition(
&OnCrossSiteResponseHelper,
info->GetChildID(),
info->GetRouteID(),
- request_id));
-
- // TODO(creis): If the above call should fail, then we need to notify the IO
- // thread to proceed anyway, using ResourceDispatcherHost::OnClosePageACK.
+ global_id,
+ should_transfer,
+ transfer_url,
+ referrer,
+ frame_id));
}
void CrossSiteResourceHandler::ResumeIfDeferred() {