Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1204)

Unified Diff: content/browser/renderer_host/resource_dispatcher_host_unittest.cc

Issue 10700170: Fix transferring processes during a redirect. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/resource_dispatcher_host_unittest.cc
===================================================================
--- content/browser/renderer_host/resource_dispatcher_host_unittest.cc (revision 146180)
+++ content/browser/renderer_host/resource_dispatcher_host_unittest.cc (working copy)
@@ -26,6 +26,7 @@
#include "content/public/browser/resource_throttle.h"
#include "content/public/common/resource_response.h"
#include "content/public/test/test_browser_context.h"
+#include "content/test/test_content_browser_client.h"
#include "net/base/net_errors.h"
#include "net/base/upload_data.h"
#include "net/http/http_util.h"
@@ -133,21 +134,24 @@
// only for tests!
void ResourceIPCAccumulator::GetClassifiedMessages(ClassifiedMessages* msgs) {
while (!messages_.empty()) {
- std::vector<IPC::Message> cur_requests;
- cur_requests.push_back(messages_[0]);
+ // Ignore unknown message types as it is valid for code to generated other
+ // IPCs as side-effects that we are not testing here.
int cur_id = RequestIDForMessage(messages_[0]);
-
- // find all other messages with this ID
- for (int i = 1; i < static_cast<int>(messages_.size()); i++) {
- int id = RequestIDForMessage(messages_[i]);
- if (id == cur_id) {
- cur_requests.push_back(messages_[i]);
- messages_.erase(messages_.begin() + i);
- i--;
+ if (cur_id != -1) {
+ std::vector<IPC::Message> cur_requests;
+ cur_requests.push_back(messages_[0]);
+ // find all other messages with this ID
+ for (int i = 1; i < static_cast<int>(messages_.size()); i++) {
+ int id = RequestIDForMessage(messages_[i]);
+ if (id == cur_id) {
+ cur_requests.push_back(messages_[i]);
+ messages_.erase(messages_.begin() + i);
+ i--;
+ }
}
+ msgs->push_back(cur_requests);
}
messages_.erase(messages_.begin());
- msgs->push_back(cur_requests);
}
}
@@ -356,6 +360,16 @@
bool* was_deleted_;
};
+class TransfersAllNavigationsContentBrowserClient
+ : public TestContentBrowserClient {
+ public:
+ virtual bool ShouldSwapProcessesForRedirect(ResourceContext* resource_context,
+ const GURL& current_url,
+ const GURL& new_url) {
+ return true;
+ }
+};
+
enum {
DEFER_NONE = 0,
DEFER_STARTING_REQUEST = 1 << 0,
@@ -503,6 +517,7 @@
void CancelRequest(int request_id);
void CompleteStartRequest(int request_id);
+ void CompleteStartRequest(ResourceMessageFilter* filter, int request_id);
void EnsureSchemeIsAllowed(const std::string& scheme) {
ChildProcessSecurityPolicyImpl* policy =
@@ -519,9 +534,13 @@
// the default bahavior, pass an empty |headers|. |headers| should be raw-
// formatted (NULLs instead of EOLs).
void SetResponse(const std::string& headers, const std::string& data) {
- response_headers_ = headers;
+ response_headers_ = net::HttpUtil::AssembleRawHeaders(headers.data(),
+ headers.size());
response_data_ = data;
}
+ void SetResponse(const std::string& headers) {
+ SetResponse(headers, std::string());
+ }
// Sets a particular resource type for any request from now on.
void SetResourceType(ResourceType::Type type) {
@@ -641,7 +660,13 @@
}
void ResourceDispatcherHostTest::CompleteStartRequest(int request_id) {
- GlobalRequestID gid(filter_->child_id(), request_id);
+ CompleteStartRequest(filter_, request_id);
+}
+
+void ResourceDispatcherHostTest::CompleteStartRequest(
+ ResourceMessageFilter* filter,
+ int request_id) {
+ GlobalRequestID gid(filter->child_id(), request_id);
net::URLRequest* req = host_.GetURLRequest(gid);
EXPECT_TRUE(req);
if (req)
@@ -1198,9 +1223,7 @@
TEST_F(ResourceDispatcherHostTest, MimeSniffed) {
EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
- std::string response("HTTP/1.1 200 OK\n\n");
- std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
- response.size()));
+ std::string raw_headers("HTTP/1.1 200 OK\n\n");
std::string response_data("<html><title>Test One</title></html>");
SetResponse(raw_headers, response_data);
@@ -1226,10 +1249,8 @@
TEST_F(ResourceDispatcherHostTest, MimeNotSniffed) {
EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
- std::string response("HTTP/1.1 200 OK\n"
- "Content-type: image/jpeg\n\n");
- std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
- response.size()));
+ std::string raw_headers("HTTP/1.1 200 OK\n"
+ "Content-type: image/jpeg\n\n");
std::string response_data("<html><title>Test One</title></html>");
SetResponse(raw_headers, response_data);
@@ -1256,11 +1277,7 @@
EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
- std::string response("HTTP/1.1 304 Not Modified\n\n");
- std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
- response.size()));
- std::string response_data;
- SetResponse(raw_headers, response_data);
+ SetResponse("HTTP/1.1 304 Not Modified\n\n");
HandleScheme("http");
MakeTestRequest(0, 1, GURL("http:bla"));
@@ -1283,11 +1300,7 @@
TEST_F(ResourceDispatcherHostTest, MimeSniff204) {
EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
- std::string response("HTTP/1.1 204 No Content\n\n");
- std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
- response.size()));
- std::string response_data;
- SetResponse(raw_headers, response_data);
+ SetResponse("HTTP/1.1 204 No Content\n\n");
HandleScheme("http");
MakeTestRequest(0, 1, GURL("http:bla"));
@@ -1310,11 +1323,7 @@
TEST_F(ResourceDispatcherHostTest, MimeSniffEmpty) {
EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
- std::string response("HTTP/1.1 200 OK\n\n");
- std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
- response.size()));
- std::string response_data;
- SetResponse(raw_headers, response_data);
+ SetResponse("HTTP/1.1 200 OK\n\n");
HandleScheme("http");
MakeTestRequest(0, 1, GURL("http:bla"));
@@ -1338,11 +1347,9 @@
TEST_F(ResourceDispatcherHostTest, ForbiddenDownload) {
EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
- std::string response("HTTP/1.1 403 Forbidden\n"
- "Content-disposition: attachment; filename=blah\n"
- "Content-type: application/octet-stream\n\n");
- std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
- response.size()));
+ std::string raw_headers("HTTP/1.1 403 Forbidden\n"
+ "Content-disposition: attachment; filename=blah\n"
+ "Content-type: application/octet-stream\n\n");
std::string response_data("<html><title>Test One</title></html>");
SetResponse(raw_headers, response_data);
@@ -1388,10 +1395,8 @@
int render_view_id = 0;
int request_id = 1;
- std::string response("HTTP\n"
- "Content-disposition: attachment; filename=foo\n\n");
- std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
- response.size()));
+ std::string raw_headers("HTTP\n"
+ "Content-disposition: attachment; filename=foo\n\n");
std::string response_data("01234567890123456789\x01foobar");
// Get past sniffing metrics in the BufferedResourceHandler. Note that
@@ -1431,10 +1436,8 @@
int render_view_id = 0;
int request_id = 1;
- std::string response("HTTP\n"
- "Content-disposition: attachment; filename=foo\n\n");
- std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
- response.size()));
+ std::string raw_headers("HTTP\n"
+ "Content-disposition: attachment; filename=foo\n\n");
std::string response_data("01234567890123456789\x01foobar");
// Get past sniffing metrics.
response_data.resize(1025, ' ');
@@ -1476,10 +1479,8 @@
int render_view_id = 0;
int request_id = 1;
- std::string response("HTTP/1.1 200 OK\n"
- "Content-Type: text/html; charset=utf-8\n\n");
- std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
- response.size()));
+ std::string raw_headers("HTTP/1.1 200 OK\n"
+ "Content-Type: text/html; charset=utf-8\n\n");
std::string response_data("<html>foobar</html>");
SetResponse(raw_headers, response_data);
@@ -1510,6 +1511,150 @@
EXPECT_EQ(0, host_.pending_requests());
}
+TEST_F(ResourceDispatcherHostTest, TransferNavigation) {
+ 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.
+ ContentBrowserClient* old_client = GetContentClient()->browser();
+ TransfersAllNavigationsContentBrowserClient new_client;
+ GetContentClient()->set_browser_for_testing(&new_client);
+
+ MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
+
+ // Restore.
+ GetContentClient()->set_browser_for_testing(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;
+
+ 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"));
+ request.transferred_request_child_id = filter_->child_id();
+ request.transferred_request_request_id = request_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, &msg_was_ok);
+ MessageLoop::current()->RunAllPending();
+
+ // 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);
+}
+
+TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
+ 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.
+ ContentBrowserClient* old_client = GetContentClient()->browser();
+ TransfersAllNavigationsContentBrowserClient new_client;
+ GetContentClient()->set_browser_for_testing(&new_client);
+
+ MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
+
+ // Restore.
+ GetContentClient()->set_browser_for_testing(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;
+
+ // 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"));
+ request.transferred_request_child_id = filter_->child_id();
+ request.transferred_request_request_id = request_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, &msg_was_ok);
+ MessageLoop::current()->RunAllPending();
+
+ // 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, new_request_id);
+ MessageLoop::current()->RunAllPending();
+
+ // Flush all the pending requests.
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+
+ // Now, simulate the renderer choosing to follow the redirect.
+ ResourceHostMsg_FollowRedirect redirect_msg(
+ new_render_view_id, new_request_id, false, GURL());
+ host_.OnMessageReceived(redirect_msg, second_filter, &msg_was_ok);
+ MessageLoop::current()->RunAllPending();
+
+ // 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.
+ EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
+ msgs[0].erase(msgs[0].begin());
+ CheckSuccessfulRequest(msgs[0], kResponseBody);
+}
+
TEST_F(ResourceDispatcherHostTest, UnknownURLScheme) {
EXPECT_EQ(0, host_.pending_requests());
« no previous file with comments | « content/browser/renderer_host/resource_dispatcher_host_impl.cc ('k') | content/browser/renderer_host/resource_loader.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698