| Index: content/browser/loader/resource_dispatcher_host_unittest.cc
|
| diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc
|
| index 75f3c7b2dccbf07517dba4a54bc83529e9b2618e..18eb22247a0abd0c92ba507a0c23279fde418158 100644
|
| --- a/content/browser/loader/resource_dispatcher_host_unittest.cc
|
| +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
|
| @@ -5,6 +5,7 @@
|
| #include <vector>
|
|
|
| #include "base/bind.h"
|
| +#include "base/command_line.h"
|
| #include "base/files/file_path.h"
|
| #include "base/memory/scoped_vector.h"
|
| #include "base/message_loop/message_loop.h"
|
| @@ -14,6 +15,7 @@
|
| #include "content/browser/browser_thread_impl.h"
|
| #include "content/browser/child_process_security_policy_impl.h"
|
| #include "content/browser/loader/resource_dispatcher_host_impl.h"
|
| +#include "content/browser/loader/resource_loader.h"
|
| #include "content/browser/loader/resource_message_filter.h"
|
| #include "content/browser/loader/resource_request_info_impl.h"
|
| #include "content/browser/worker_host/worker_service_impl.h"
|
| @@ -25,6 +27,7 @@
|
| #include "content/public/browser/resource_dispatcher_host_delegate.h"
|
| #include "content/public/browser/resource_request_info.h"
|
| #include "content/public/browser/resource_throttle.h"
|
| +#include "content/public/common/content_switches.h"
|
| #include "content/public/common/process_type.h"
|
| #include "content/public/common/resource_response.h"
|
| #include "content/public/test/test_browser_context.h"
|
| @@ -599,12 +602,19 @@ class ResourceDispatcherHostTest : public testing::Test,
|
| const GURL& url);
|
|
|
| // Generates a request using the given filter. This will probably be a
|
| - // ForwardingFilter.
|
| + // ForwardingFilter. Uses the resource_type_ as the resource type.
|
| void MakeTestRequest(ResourceMessageFilter* filter,
|
| int render_view_id,
|
| int request_id,
|
| const GURL& url);
|
|
|
| + // Generates a request using the given filter. This will probably be a
|
| + // ForwardingFilter.
|
| + void MakeTestRequestWithResourceType(ResourceMessageFilter* filter,
|
| + int render_view_id, int request_id,
|
| + const GURL& url,
|
| + ResourceType::Type type);
|
| +
|
| void CancelRequest(int request_id);
|
|
|
| void CompleteStartRequest(int request_id);
|
| @@ -633,11 +643,6 @@ class ResourceDispatcherHostTest : public testing::Test,
|
| SetResponse(headers, std::string());
|
| }
|
|
|
| - // Sets a particular resource type for any request from now on.
|
| - void SetResourceType(ResourceType::Type type) {
|
| - resource_type_ = type;
|
| - }
|
| -
|
| void SendDataReceivedACKs(bool send_acks) {
|
| send_data_received_acks_ = send_acks;
|
| }
|
| @@ -748,11 +753,21 @@ void ResourceDispatcherHostTest::MakeTestRequest(
|
| int render_view_id,
|
| int request_id,
|
| const GURL& url) {
|
| + MakeTestRequestWithResourceType(filter, render_view_id, request_id, url,
|
| + resource_type_);
|
| +}
|
| +
|
| +void ResourceDispatcherHostTest::MakeTestRequestWithResourceType(
|
| + ResourceMessageFilter* filter,
|
| + int render_view_id,
|
| + int request_id,
|
| + const GURL& url,
|
| + ResourceType::Type type) {
|
| // If it's already there, this'll be dropped on the floor, which is fine.
|
| child_ids_.insert(filter->child_id());
|
|
|
| ResourceHostMsg_Request request =
|
| - CreateResourceRequest("GET", resource_type_, url);
|
| + CreateResourceRequest("GET", type, url);
|
| ResourceHostMsg_RequestResource msg(render_view_id, request_id, request);
|
| bool msg_was_ok;
|
| host_.OnMessageReceived(msg, filter, &msg_was_ok);
|
| @@ -907,6 +922,101 @@ TEST_F(ResourceDispatcherHostTest, Cancel) {
|
| CheckCancelledRequestCompleteMessage(msgs[1][1]);
|
| }
|
|
|
| +// Shows that unlike normal requests, prefetched async requests are not
|
| +// immediately canceled, and will complete within a timeout period.
|
| +TEST_F(ResourceDispatcherHostTest, PrefetchIgnoreCancel) {
|
| + CommandLine* command_line = CommandLine::ForCurrentProcess();
|
| + command_line->AppendSwitch(switches::kDelayPrefetchCancellation);
|
| + MakeTestRequestWithResourceType(filter_.get(), 0, 1,
|
| + net::URLRequestTestJob::test_url_1(),
|
| + ResourceType::PREFETCH);
|
| + MakeTestRequestWithResourceType(filter_.get(), 0, 2,
|
| + net::URLRequestTestJob::test_url_2(),
|
| + ResourceType::PREFETCH);
|
| + MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
|
| +
|
| + // test_url_1 is synchronous and already complete.
|
| + EXPECT_EQ(2, host_.pending_requests());
|
| + // We need to make sure that the request comes from the renderer, else it
|
| + // won't delay.
|
| + host_.CancelRequest(filter_->child_id(), 2, true);
|
| + host_.CancelRequest(filter_->child_id(), 3, true);
|
| +
|
| + // Process any completion messages from cancelling.
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| +
|
| + EXPECT_EQ(1, host_.pending_requests());
|
| +
|
| + // Run the requests to completion.
|
| + while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| +
|
| + EXPECT_EQ(0, host_.pending_requests());
|
| +
|
| + ResourceIPCAccumulator::ClassifiedMessages msgs;
|
| + accum_.GetClassifiedMessages(&msgs);
|
| +
|
| + ASSERT_EQ(3U, msgs.size());
|
| +
|
| + // The first fetch was synchronous and should have completed successfully.
|
| + ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[0][0].type());
|
| + ASSERT_EQ(ResourceMsg_RequestComplete::ID, msgs[0][1].type());
|
| +
|
| + // The prefetch should have ignored the cancel and completed. Note that
|
| + // prefetches run detached and do not receive data notifications.
|
| + ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[1][0].type());
|
| + ASSERT_EQ(ResourceMsg_RequestComplete::ID, msgs[1][1].type());
|
| + // Verify that there was no error.
|
| + int request_id;
|
| + int error_code;
|
| + PickleIterator iter(msgs[1][1]);
|
| + ASSERT_TRUE(IPC::ReadParam(&msgs[1][1], &iter, &request_id));
|
| + ASSERT_TRUE(IPC::ReadParam(&msgs[1][1], &iter, &error_code));
|
| + EXPECT_EQ(0, error_code);
|
| +
|
| + // Request 3 should have been cancelled immediately.
|
| + ASSERT_EQ(2U, msgs[2].size());
|
| + ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[2][0].type());
|
| + CheckCancelledRequestCompleteMessage(msgs[2][1]);
|
| +}
|
| +
|
| +// Shows that prefetched requests will timeout if the request takes too long
|
| +// to complete.
|
| +TEST_F(ResourceDispatcherHostTest, PrefetchIgnoreCancelTimesOut) {
|
| + CommandLine* command_line = CommandLine::ForCurrentProcess();
|
| + command_line->AppendSwitchASCII(switches::kDelayPrefetchCancellation, "200");
|
| +
|
| + MakeTestRequestWithResourceType(filter_.get(), 0, 1,
|
| + net::URLRequestTestJob::test_url_2(),
|
| + ResourceType::PREFETCH);
|
| + host_.CancelRequest(filter_->child_id(), 1, true);
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + EXPECT_EQ(1, host_.pending_requests());
|
| +
|
| + // Wait until after the delay timer times before letting any Reads complete.
|
| + base::OneShotTimer<base::MessageLoop> timer;
|
| + timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(210),
|
| + base::MessageLoop::current(), &base::MessageLoop::QuitWhenIdle);
|
| +
|
| + // We should have cancelled the prefetch by now.
|
| + base::MessageLoop::current()->Run();
|
| + EXPECT_EQ(0, host_.pending_requests());
|
| +
|
| + // In case any messages are still to be processed.
|
| + while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| +
|
| + ResourceIPCAccumulator::ClassifiedMessages msgs;
|
| + accum_.GetClassifiedMessages(&msgs);
|
| +
|
| + ASSERT_EQ(1U, msgs.size());
|
| +
|
| + // The request should have cancelled.
|
| + ASSERT_EQ(2U, msgs[0].size());
|
| + ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[0][0].type());
|
| + CheckCancelledRequestCompleteMessage(msgs[0][1]);
|
| +}
|
| +
|
| TEST_F(ResourceDispatcherHostTest, CancelWhileStartIsDeferred) {
|
| bool was_deleted = false;
|
|
|
| @@ -1543,11 +1653,11 @@ TEST_F(ResourceDispatcherHostTest, ForbiddenDownload) {
|
| std::string response_data("<html><title>Test One</title></html>");
|
| SetResponse(raw_headers, response_data);
|
|
|
| - // Only MAIN_FRAMEs can trigger a download.
|
| - SetResourceType(ResourceType::MAIN_FRAME);
|
| -
|
| HandleScheme("http");
|
| - MakeTestRequest(0, 1, GURL("http:bla"));
|
| +
|
| + // Only MAIN_FRAMEs can trigger a download.
|
| + MakeTestRequestWithResourceType(filter_.get(), 0, 1, GURL("http:bla"),
|
| + ResourceType::MAIN_FRAME);
|
|
|
| // Flush all pending requests.
|
| while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
|
| @@ -1594,11 +1704,12 @@ TEST_F(ResourceDispatcherHostTest, IgnoreCancelForDownloads) {
|
| response_data.resize(1025, ' ');
|
|
|
| SetResponse(raw_headers, response_data);
|
| - SetResourceType(ResourceType::MAIN_FRAME);
|
| SetDelayedCompleteJobGeneration(true);
|
| HandleScheme("http");
|
|
|
| - MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
|
| + MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
|
| + GURL("http://example.com/blah"),
|
| + ResourceType::MAIN_FRAME);
|
| // Return some data so that the request is identified as a download
|
| // and the proper resource handlers are created.
|
| EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
|
| @@ -1629,11 +1740,12 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContext) {
|
| response_data.resize(1025, ' ');
|
|
|
| SetResponse(raw_headers, response_data);
|
| - SetResourceType(ResourceType::MAIN_FRAME);
|
| SetDelayedCompleteJobGeneration(true);
|
| HandleScheme("http");
|
|
|
| - MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
|
| + MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
|
| + GURL("http://example.com/blah"),
|
| + ResourceType::MAIN_FRAME);
|
| // Return some data so that the request is identified as a download
|
| // and the proper resource handlers are created.
|
| EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
|
| @@ -1670,10 +1782,12 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
|
| std::string response_data("<html>foobar</html>");
|
|
|
| SetResponse(raw_headers, response_data);
|
| - SetResourceType(ResourceType::MAIN_FRAME);
|
| HandleScheme("http");
|
|
|
| - MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
|
| + MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
|
| + GURL("http://example.com/blah"),
|
| + ResourceType::MAIN_FRAME);
|
| +
|
|
|
| GlobalRequestID global_request_id(filter_->child_id(), request_id);
|
| host_.MarkAsTransferredNavigation(global_request_id,
|
| @@ -1708,7 +1822,6 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigation) {
|
| 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
|
| @@ -1716,7 +1829,8 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigation) {
|
| TransfersAllNavigationsContentBrowserClient new_client;
|
| ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
|
|
|
| - MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
|
| + MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
|
| + GURL("http://example.com/blah"), ResourceType::MAIN_FRAME);
|
|
|
| // Restore.
|
| SetBrowserClientForTesting(old_client);
|
| @@ -1770,7 +1884,6 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
|
| 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
|
| @@ -1853,7 +1966,6 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
|
| 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
|
| @@ -1861,7 +1973,9 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
|
| TransfersAllNavigationsContentBrowserClient new_client;
|
| ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
|
|
|
| - MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
|
| + MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
|
| + GURL("http://example.com/blah"),
|
| + ResourceType::MAIN_FRAME);
|
|
|
| // Restore.
|
| SetBrowserClientForTesting(old_client);
|
| @@ -1942,10 +2056,10 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
|
| TEST_F(ResourceDispatcherHostTest, UnknownURLScheme) {
|
| EXPECT_EQ(0, host_.pending_requests());
|
|
|
| - SetResourceType(ResourceType::MAIN_FRAME);
|
| HandleScheme("http");
|
|
|
| - MakeTestRequest(0, 1, GURL("foo://bar"));
|
| + MakeTestRequestWithResourceType(filter_.get(), 0, 1, GURL("foo://bar"),
|
| + ResourceType::MAIN_FRAME);
|
|
|
| // Flush all pending requests.
|
| while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
|
| @@ -1992,6 +2106,30 @@ TEST_F(ResourceDispatcherHostTest, DataReceivedACKs) {
|
| EXPECT_EQ(ResourceMsg_RequestComplete::ID, msgs[0][size - 1].type());
|
| }
|
|
|
| +// Request a very large prefetch. This tests to make sure that the data
|
| +// is not sent to the render process and verifies that the async handler
|
| +// doesn't fill up its pending buffers and block.
|
| +TEST_F(ResourceDispatcherHostTest, DetachedNoDataSentOrReceived) {
|
| + EXPECT_EQ(0, host_.pending_requests());
|
| +
|
| + SendDataReceivedACKs(true);
|
| +
|
| + HandleScheme("big-job");
|
| +
|
| + // This request would normally result in many messages (>300).
|
| + MakeTestRequestWithResourceType(filter_.get(), 0, 1,
|
| + GURL("big-job:0123456789,1000000"),
|
| + ResourceType::PREFETCH);
|
| +
|
| + // Sort all the messages we saw by request.
|
| + ResourceIPCAccumulator::ClassifiedMessages msgs;
|
| + accum_.GetClassifiedMessages(&msgs);
|
| +
|
| + EXPECT_EQ(size_t(2), msgs[0].size());
|
| + ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[0][0].type());
|
| + ASSERT_EQ(ResourceMsg_RequestComplete::ID, msgs[0][1].type());
|
| +}
|
| +
|
| TEST_F(ResourceDispatcherHostTest, DelayedDataReceivedACKs) {
|
| EXPECT_EQ(0, host_.pending_requests());
|
|
|
|
|