summaryrefslogtreecommitdiffstats
path: root/content/browser/loader
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
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')
-rw-r--r--content/browser/loader/cross_site_resource_handler.cc92
-rw-r--r--content/browser/loader/cross_site_resource_handler.h6
-rw-r--r--content/browser/loader/resource_dispatcher_host_impl.cc25
-rw-r--r--content/browser/loader/resource_dispatcher_host_unittest.cc190
-rw-r--r--content/browser/loader/resource_loader.cc5
-rw-r--r--content/browser/loader/transfer_navigation_resource_throttle.cc93
-rw-r--r--content/browser/loader/transfer_navigation_resource_throttle.h38
7 files changed, 217 insertions, 232 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() {
diff --git a/content/browser/loader/cross_site_resource_handler.h b/content/browser/loader/cross_site_resource_handler.h
index 39c3a14..5c08f7e 100644
--- a/content/browser/loader/cross_site_resource_handler.h
+++ b/content/browser/loader/cross_site_resource_handler.h
@@ -47,9 +47,9 @@ class CrossSiteResourceHandler : public LayeredResourceHandler {
private:
// Prepare to render the cross-site response in a new RenderViewHost, by
// telling the old RenderViewHost to run its onunload handler.
- void StartCrossSiteTransition(
- int request_id,
- ResourceResponse* response);
+ void StartCrossSiteTransition(int request_id,
+ ResourceResponse* response,
+ bool should_transfer);
void ResumeIfDeferred();
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index a44715d..839678e 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -40,7 +40,6 @@
#include "content/browser/loader/stream_resource_handler.h"
#include "content/browser/loader/sync_resource_handler.h"
#include "content/browser/loader/throttling_resource_handler.h"
-#include "content/browser/loader/transfer_navigation_resource_throttle.h"
#include "content/browser/loader/upload_data_stream_builder.h"
#include "content/browser/plugin_service_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
@@ -938,6 +937,9 @@ void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
route_id,
request_id);
}
+
+ // We should have a CrossSiteResourceHandler to finish the transfer.
+ DCHECK(info->cross_site_handler());
}
void ResourceDispatcherHostImpl::BeginRequest(
@@ -1107,16 +1109,11 @@ void ResourceDispatcherHostImpl::BeginRequest(
new RedirectToFileResourceHandler(handler.Pass(), request, this));
}
- // Install a CrossSiteResourceHandler if this request is coming from a
- // RenderViewHost with a pending cross-site request. We only check this for
- // MAIN_FRAME requests. Unblock requests only come from a blocked page, do
- // not count as cross-site, otherwise it gets blocked indefinitely.
- if (request_data.resource_type == ResourceType::MAIN_FRAME &&
- process_type == PROCESS_TYPE_RENDERER &&
- CrossSiteRequestManager::GetInstance()->
- HasPendingCrossSiteRequest(child_id, route_id)) {
- // Wrap the event handler to be sure the current page's onunload handler
- // has a chance to run before we render the new page.
+ // Install a CrossSiteResourceHandler for all main frame requests. This will
+ // let us check whether a transfer is required and pause for the unload
+ // handler either if so or if a cross-process navigation is already under way.
+ if (request_data.resource_type == ResourceType::MAIN_FRAME &&
+ process_type == PROCESS_TYPE_RENDERER) {
handler.reset(new CrossSiteResourceHandler(handler.Pass(), request));
}
@@ -1140,12 +1137,6 @@ void ResourceDispatcherHostImpl::BeginRequest(
throttles.push_back(new PowerSaveBlockResourceThrottle());
}
- if (request_data.resource_type == ResourceType::MAIN_FRAME) {
- throttles.insert(
- throttles.begin(),
- new TransferNavigationResourceThrottle(request));
- }
-
throttles.push_back(
scheduler_->ScheduleRequest(child_id, route_id, request).release());
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc
index 75f3c7b..4a9e275 100644
--- a/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -9,6 +9,7 @@
#include "base/memory/scoped_vector.h"
#include "base/message_loop/message_loop.h"
#include "base/pickle.h"
+#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "content/browser/browser_thread_impl.h"
@@ -1698,7 +1699,9 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
EXPECT_EQ(0, host_.pending_requests());
}
-TEST_F(ResourceDispatcherHostTest, TransferNavigation) {
+// Test transferred navigations with text/html, which doesn't trigger any
+// content sniffing.
+TEST_F(ResourceDispatcherHostTest, TransferNavigationHtml) {
EXPECT_EQ(0, host_.pending_requests());
int render_view_id = 0;
@@ -1718,7 +1721,22 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigation) {
MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
- // Restore.
+ // Now that we're blocked on the redirect, update the response and unblock by
+ // telling the AsyncResourceHandler to follow the redirect.
+ const std::string kResponseBody = "hello world";
+ SetResponse("HTTP/1.1 200 OK\n"
+ "Content-Type: text/html\n\n",
+ kResponseBody);
+ ResourceHostMsg_FollowRedirect redirect_msg(request_id, false, GURL());
+ bool msg_was_ok;
+ host_.OnMessageReceived(redirect_msg, filter_.get(), &msg_was_ok);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Flush all the pending requests to get the response through the
+ // BufferedResourceHandler.
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+
+ // Restore, now that we've set up a transfer.
SetBrowserClientForTesting(old_client);
// This second filter is used to emulate a second process.
@@ -1728,10 +1746,78 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigation) {
int new_render_view_id = 1;
int new_request_id = 2;
+ ResourceHostMsg_Request request =
+ CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
+ GURL("http://other.com/blech"));
+ request.transferred_request_child_id = filter_->child_id();
+ request.transferred_request_request_id = request_id;
+
+ // For cleanup.
+ child_ids_.insert(second_filter->child_id());
+ ResourceHostMsg_RequestResource transfer_request_msg(
+ new_render_view_id, new_request_id, request);
+ host_.OnMessageReceived(
+ transfer_request_msg, second_filter.get(), &msg_was_ok);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Check generated messages.
+ ResourceIPCAccumulator::ClassifiedMessages msgs;
+ accum_.GetClassifiedMessages(&msgs);
+
+ ASSERT_EQ(2U, msgs.size());
+ EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
+ CheckSuccessfulRequest(msgs[1], kResponseBody);
+}
+
+// Test transferred navigations with text/plain, which causes
+// BufferedResourceHandler to buffer the response to sniff the content
+// before the transfer occurs.
+TEST_F(ResourceDispatcherHostTest, TransferNavigationText) {
+ EXPECT_EQ(0, host_.pending_requests());
+
+ int render_view_id = 0;
+ int request_id = 1;
+
+ // Configure initial request.
+ SetResponse("HTTP/1.1 302 Found\n"
+ "Location: http://other.com/blech\n\n");
+
+ SetResourceType(ResourceType::MAIN_FRAME);
+ HandleScheme("http");
+
+ // Temporarily replace ContentBrowserClient with one that will trigger the
+ // transfer navigation code paths.
+ TransfersAllNavigationsContentBrowserClient new_client;
+ ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
+
+ MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
+
+ // Now that we're blocked on the redirect, update the response and unblock by
+ // telling the AsyncResourceHandler to follow the redirect. Use a text/plain
+ // MIME type, which causes BufferedResourceHandler to buffer it before the
+ // transfer occurs.
const std::string kResponseBody = "hello world";
SetResponse("HTTP/1.1 200 OK\n"
"Content-Type: text/plain\n\n",
kResponseBody);
+ ResourceHostMsg_FollowRedirect redirect_msg(request_id, false, GURL());
+ bool msg_was_ok;
+ host_.OnMessageReceived(redirect_msg, filter_.get(), &msg_was_ok);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Flush all the pending requests to get the response through the
+ // BufferedResourceHandler.
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+
+ // Restore, now that we've set up a transfer.
+ SetBrowserClientForTesting(old_client);
+
+ // This second filter is used to emulate a second process.
+ scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter(
+ this, browser_context_->GetResourceContext());
+
+ int new_render_view_id = 1;
+ int new_request_id = 2;
ResourceHostMsg_Request request =
CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
@@ -1743,20 +1829,17 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigation) {
child_ids_.insert(second_filter->child_id());
ResourceHostMsg_RequestResource transfer_request_msg(
new_render_view_id, new_request_id, request);
- bool msg_was_ok;
host_.OnMessageReceived(
transfer_request_msg, second_filter.get(), &msg_was_ok);
base::MessageLoop::current()->RunUntilIdle();
- // Flush all the pending requests.
- while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
-
// Check generated messages.
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
- ASSERT_EQ(1U, msgs.size());
- CheckSuccessfulRequest(msgs[0], kResponseBody);
+ ASSERT_EQ(2U, msgs.size());
+ EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
+ CheckSuccessfulRequest(msgs[1], kResponseBody);
}
TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
@@ -1769,6 +1852,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
// Configure initial request.
SetResponse("HTTP/1.1 302 Found\n"
"Location: http://other.com/blech\n\n");
+ const std::string kResponseBody = "hello world";
SetResourceType(ResourceType::MAIN_FRAME);
HandleScheme("http");
@@ -1796,6 +1880,19 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
host_.OnMessageReceived(
first_request_msg, first_filter.get(), &msg_was_ok);
base::MessageLoop::current()->RunUntilIdle();
+
+ // Now that we're blocked on the redirect, update the response and unblock
+ // by telling the AsyncResourceHandler to follow the redirect.
+ SetResponse("HTTP/1.1 200 OK\n"
+ "Content-Type: text/html\n\n",
+ kResponseBody);
+ ResourceHostMsg_FollowRedirect redirect_msg(request_id, false, GURL());
+ host_.OnMessageReceived(redirect_msg, first_filter.get(), &msg_was_ok);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Flush all the pending requests to get the response through the
+ // BufferedResourceHandler.
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
}
// The first filter is now deleted, as if the child process died.
@@ -1812,11 +1909,6 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
int new_render_view_id = 1;
int new_request_id = 2;
- const std::string kResponseBody = "hello world";
- SetResponse("HTTP/1.1 200 OK\n"
- "Content-Type: text/plain\n\n",
- kResponseBody);
-
ResourceHostMsg_Request request =
CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
GURL("http://other.com/blech"));
@@ -1832,18 +1924,16 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
transfer_request_msg, second_filter.get(), &msg_was_ok);
base::MessageLoop::current()->RunUntilIdle();
- // Flush all the pending requests.
- while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
-
// Check generated messages.
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
- ASSERT_EQ(1U, msgs.size());
- CheckSuccessfulRequest(msgs[0], kResponseBody);
+ ASSERT_EQ(2U, msgs.size());
+ EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
+ CheckSuccessfulRequest(msgs[1], kResponseBody);
}
-TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
+TEST_F(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
EXPECT_EQ(0, host_.pending_requests());
int render_view_id = 0;
@@ -1863,6 +1953,30 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
+ // Now that we're blocked on the redirect, simulate hitting another redirect.
+ SetResponse("HTTP/1.1 302 Found\n"
+ "Location: http://other.com/blerg\n\n");
+ ResourceHostMsg_FollowRedirect redirect_msg(request_id, false, GURL());
+ bool msg_was_ok;
+ host_.OnMessageReceived(redirect_msg, filter_.get(), &msg_was_ok);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Now that we're blocked on the second redirect, update the response and
+ // unblock by telling the AsyncResourceHandler to follow the redirect.
+ // Again, use text/plain to force BufferedResourceHandler to buffer before
+ // the transfer.
+ const std::string kResponseBody = "hello world";
+ SetResponse("HTTP/1.1 200 OK\n"
+ "Content-Type: text/plain\n\n",
+ kResponseBody);
+ ResourceHostMsg_FollowRedirect redirect_msg2(request_id, false, GURL());
+ host_.OnMessageReceived(redirect_msg2, filter_.get(), &msg_was_ok);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Flush all the pending requests to get the response through the
+ // BufferedResourceHandler.
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+
// Restore.
SetBrowserClientForTesting(old_client);
@@ -1873,13 +1987,6 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
int new_render_view_id = 1;
int new_request_id = 2;
- // Delay the start of the next request so that we can setup the response for
- // the next URL.
- SetDelayedStartJobGeneration(true);
-
- SetResponse("HTTP/1.1 302 Found\n"
- "Location: http://other.com/blerg\n\n");
-
ResourceHostMsg_Request request =
CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
GURL("http://other.com/blech"));
@@ -1890,24 +1997,8 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
child_ids_.insert(second_filter->child_id());
ResourceHostMsg_RequestResource transfer_request_msg(
new_render_view_id, new_request_id, request);
- bool msg_was_ok;
host_.OnMessageReceived(
transfer_request_msg, second_filter.get(), &msg_was_ok);
- base::MessageLoop::current()->RunUntilIdle();
-
- // Response data for "http://other.com/blerg":
- const std::string kResponseBody = "hello world";
- SetResponse("HTTP/1.1 200 OK\n"
- "Content-Type: text/plain\n\n",
- kResponseBody);
-
- // OK, let the redirect happen.
- SetDelayedStartJobGeneration(false);
- CompleteStartRequest(second_filter.get(), new_request_id);
- base::MessageLoop::current()->RunUntilIdle();
-
- // Flush all the pending requests.
- while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
// Verify that we update the ResourceRequestInfo.
GlobalRequestID global_request_id(second_filter->child_id(), new_request_id);
@@ -1918,25 +2009,16 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
EXPECT_EQ(new_request_id, info->GetRequestID());
EXPECT_EQ(second_filter, info->filter());
- // Now, simulate the renderer choosing to follow the redirect.
- ResourceHostMsg_FollowRedirect redirect_msg(
- new_request_id, false, GURL());
- host_.OnMessageReceived(redirect_msg, second_filter.get(), &msg_was_ok);
+ // Let request complete.
base::MessageLoop::current()->RunUntilIdle();
- // Flush all the pending requests.
- while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
-
// Check generated messages.
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
- ASSERT_EQ(1U, msgs.size());
-
- // We should have received a redirect followed by a "normal" payload.
+ ASSERT_EQ(2U, msgs.size());
EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
- msgs[0].erase(msgs[0].begin());
- CheckSuccessfulRequest(msgs[0], kResponseBody);
+ CheckSuccessfulRequest(msgs[1], kResponseBody);
}
TEST_F(ResourceDispatcherHostTest, UnknownURLScheme) {
diff --git a/content/browser/loader/resource_loader.cc b/content/browser/loader/resource_loader.cc
index c99fe5b..8f70ab5 100644
--- a/content/browser/loader/resource_loader.cc
+++ b/content/browser/loader/resource_loader.cc
@@ -9,6 +9,7 @@
#include "base/metrics/histogram.h"
#include "base/time/time.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/loader/cross_site_resource_handler.h"
#include "content/browser/loader/resource_loader_delegate.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/ssl/ssl_client_auth_handler.h"
@@ -165,10 +166,10 @@ void ResourceLoader::MarkAsTransferring(const GURL& target_url) {
}
void ResourceLoader::CompleteTransfer() {
- DCHECK_EQ(DEFERRED_REDIRECT, deferred_stage_);
+ DCHECK_EQ(DEFERRED_READ, deferred_stage_);
is_transferring_ = false;
- Resume();
+ GetRequestInfo()->cross_site_handler()->ResumeResponse();
}
ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() {
diff --git a/content/browser/loader/transfer_navigation_resource_throttle.cc b/content/browser/loader/transfer_navigation_resource_throttle.cc
deleted file mode 100644
index 8021bce..0000000
--- a/content/browser/loader/transfer_navigation_resource_throttle.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/transfer_navigation_resource_throttle.h"
-
-#include "base/bind.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/renderer_host/render_view_host_delegate.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/render_view_host.h"
-#include "content/public/browser/resource_request_info.h"
-#include "content/public/common/referrer.h"
-#include "net/url_request/url_request.h"
-
-namespace content {
-
-namespace {
-
-void RequestTransferURLOnUIThread(int render_process_id,
- int render_view_id,
- const GURL& new_url,
- const Referrer& referrer,
- WindowOpenDisposition window_open_disposition,
- int64 frame_id,
- const GlobalRequestID& global_request_id) {
- RenderViewHost* rvh =
- RenderViewHost::FromID(render_process_id, render_view_id);
- if (!rvh)
- return;
-
- RenderViewHostDelegate* delegate = rvh->GetDelegate();
- if (!delegate)
- return;
-
- // We don't know whether the original request had |user_action| set to true.
- // However, since we force the navigation to be in the current tab, it doesn't
- // matter.
- delegate->RequestTransferURL(
- new_url, referrer, window_open_disposition,
- frame_id, global_request_id, false, true);
-}
-
-} // namespace
-
-TransferNavigationResourceThrottle::TransferNavigationResourceThrottle(
- net::URLRequest* request)
- : request_(request) {
-}
-
-TransferNavigationResourceThrottle::~TransferNavigationResourceThrottle() {
-}
-
-void TransferNavigationResourceThrottle::WillRedirectRequest(
- const GURL& new_url,
- bool* defer) {
- const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
-
- // If a toplevel request is redirecting across extension extents, we want to
- // switch processes. We do this by deferring the redirect and resuming the
- // request once the navigation controller properly assigns the right process
- // to host the new URL.
- // TODO(mpcomplete): handle for cases other than extensions (e.g. WebUI).
- ResourceContext* resource_context = info->GetContext();
- if (GetContentClient()->browser()->ShouldSwapProcessesForRedirect(
- resource_context, request_->url(), new_url)) {
- int render_process_id, render_view_id;
- if (info->GetAssociatedRenderView(&render_process_id, &render_view_id)) {
- GlobalRequestID global_id(info->GetChildID(), info->GetRequestID());
-
- ResourceDispatcherHostImpl::Get()->MarkAsTransferredNavigation(global_id,
- new_url);
-
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&RequestTransferURLOnUIThread,
- render_process_id,
- render_view_id,
- new_url,
- Referrer(GURL(request_->referrer()), info->GetReferrerPolicy()),
- CURRENT_TAB,
- info->GetFrameID(),
- global_id));
-
- *defer = true;
- }
- }
-}
-
-} // namespace content
diff --git a/content/browser/loader/transfer_navigation_resource_throttle.h b/content/browser/loader/transfer_navigation_resource_throttle.h
deleted file mode 100644
index 6d08c2a..0000000
--- a/content/browser/loader/transfer_navigation_resource_throttle.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_LOADER_TRANSFER_NAVIGATION_RESOURCE_THROTTLE_H_
-#define CONTENT_BROWSER_LOADER_TRANSFER_NAVIGATION_RESOURCE_THROTTLE_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "content/public/browser/resource_throttle.h"
-
-namespace net {
-class URLRequest;
-}
-
-namespace content {
-
-// This ResourceThrottle checks whether a navigation redirect will cause a
-// renderer process swap. When that happens, we remember the request so
-// that we can transfer it to be handled by the new renderer. This fixes
-// http://crbug.com/79520
-class TransferNavigationResourceThrottle : public ResourceThrottle {
- public:
- explicit TransferNavigationResourceThrottle(net::URLRequest* request);
- virtual ~TransferNavigationResourceThrottle();
-
- // ResourceThrottle implementation:
- virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE;
-
- private:
- net::URLRequest* request_;
-
- DISALLOW_COPY_AND_ASSIGN(TransferNavigationResourceThrottle);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_TRANSFER_NAVIGATION_RESOURCE_THROTTLE_H_