| 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 0ddf31c7e0912b616ba6610b1ed2a24a4c8174f2..1518817856ed4a6add5ebcb39b2f6f284b749e82 100644
|
| --- a/content/browser/loader/resource_dispatcher_host_unittest.cc
|
| +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
|
| @@ -430,6 +430,27 @@ class URLRequestTestDelayedCompletionJob : public net::URLRequestTestJob {
|
| bool NextReadAsync() override { return true; }
|
| };
|
|
|
| +// This class is a variation on URLRequestTestJob that ensures that no read is
|
| +// asked of this job.
|
| +class URLRequestMustNotReadTestJob : public net::URLRequestTestJob {
|
| + public:
|
| + URLRequestMustNotReadTestJob(net::URLRequest* request,
|
| + net::NetworkDelegate* network_delegate,
|
| + const std::string& response_headers,
|
| + const std::string& response_data)
|
| + : net::URLRequestTestJob(request,
|
| + network_delegate,
|
| + response_headers,
|
| + response_data,
|
| + false) {}
|
| +
|
| + int ReadRawData(net::IOBuffer* buf, int buf_size) override {
|
| + EXPECT_TRUE(false) << "The job should have been cancelled before trying to "
|
| + "read the response body.";
|
| + return 0;
|
| + }
|
| +};
|
| +
|
| class URLRequestBigJob : public net::URLRequestSimpleJob {
|
| public:
|
| URLRequestBigJob(net::URLRequest* request,
|
| @@ -525,8 +546,8 @@ class TestURLRequestJobFactory : public net::URLRequestJobFactory {
|
| hang_after_start_(false),
|
| delay_start_(false),
|
| delay_complete_(false),
|
| - url_request_jobs_created_count_(0) {
|
| - }
|
| + must_not_read_(false),
|
| + url_request_jobs_created_count_(0) {}
|
|
|
| void HandleScheme(const std::string& scheme) {
|
| supported_schemes_.insert(scheme);
|
| @@ -549,6 +570,10 @@ class TestURLRequestJobFactory : public net::URLRequestJobFactory {
|
| delay_complete_ = delay_job_complete;
|
| }
|
|
|
| + void SetMustNotReadJobGeneration(bool must_not_read) {
|
| + must_not_read_ = must_not_read;
|
| + }
|
| +
|
| net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
|
| const std::string& scheme,
|
| net::URLRequest* request,
|
| @@ -580,6 +605,7 @@ class TestURLRequestJobFactory : public net::URLRequestJobFactory {
|
| bool hang_after_start_;
|
| bool delay_start_;
|
| bool delay_complete_;
|
| + bool must_not_read_;
|
| mutable int url_request_jobs_created_count_;
|
| std::set<std::string> supported_schemes_;
|
|
|
| @@ -610,10 +636,12 @@ class TransfersAllNavigationsContentBrowserClient
|
| };
|
|
|
| enum GenericResourceThrottleFlags {
|
| - NONE = 0,
|
| - DEFER_STARTING_REQUEST = 1 << 0,
|
| - DEFER_PROCESSING_RESPONSE = 1 << 1,
|
| - CANCEL_BEFORE_START = 1 << 2
|
| + NONE = 0,
|
| + DEFER_STARTING_REQUEST = 1 << 0,
|
| + DEFER_PROCESSING_RESPONSE = 1 << 1,
|
| + CANCEL_BEFORE_START = 1 << 2,
|
| + CANCEL_PROCESSING_RESPONSE = 1 << 3,
|
| + MUST_NOT_CACHE_BODY = 1 << 4,
|
| };
|
|
|
| // Throttle that tracks the current throttle blocking a request. Only one
|
| @@ -658,6 +686,14 @@ class GenericResourceThrottle : public ResourceThrottle {
|
| active_throttle_ = this;
|
| *defer = true;
|
| }
|
| +
|
| + if (flags_ & CANCEL_PROCESSING_RESPONSE) {
|
| + if (error_code_for_cancellation_ == USE_DEFAULT_CANCEL_ERROR_CODE) {
|
| + controller()->Cancel();
|
| + } else {
|
| + controller()->CancelWithError(error_code_for_cancellation_);
|
| + }
|
| + }
|
| }
|
|
|
| const char* GetNameForLogging() const override {
|
| @@ -674,6 +710,10 @@ class GenericResourceThrottle : public ResourceThrottle {
|
| return active_throttle_;
|
| }
|
|
|
| + bool MustProcessResponseBeforeReadingBody() override {
|
| + return flags_ & MUST_NOT_CACHE_BODY;
|
| + }
|
| +
|
| private:
|
| int flags_; // bit-wise union of GenericResourceThrottleFlags.
|
| int error_code_for_cancellation_;
|
| @@ -2505,6 +2545,7 @@ TEST_P(ResourceDispatcherHostTest, IgnoreCancelForDownloads) {
|
| // Return some data so that the request is identified as a download
|
| // and the proper resource handlers are created.
|
| EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
|
| + base::RunLoop().RunUntilIdle();
|
|
|
| // And now simulate a cancellation coming from the renderer.
|
| ResourceHostMsg_CancelRequest msg(request_id);
|
| @@ -2516,6 +2557,7 @@ TEST_P(ResourceDispatcherHostTest, IgnoreCancelForDownloads) {
|
| EXPECT_EQ(1, host_.pending_requests());
|
|
|
| while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
|
| + base::RunLoop().RunUntilIdle();
|
| }
|
|
|
| TEST_P(ResourceDispatcherHostTest, CancelRequestsForContext) {
|
| @@ -2576,6 +2618,7 @@ TEST_P(ResourceDispatcherHostTest, CancelRequestsForContext) {
|
| // Return some data so that the request is identified as a download
|
| // and the proper resource handlers are created.
|
| EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
|
| + base::RunLoop().RunUntilIdle();
|
|
|
| // And now simulate a cancellation coming from the renderer.
|
| ResourceHostMsg_CancelRequest msg(request_id);
|
| @@ -2593,6 +2636,10 @@ TEST_P(ResourceDispatcherHostTest, CancelRequestsForContext) {
|
| // Cancelling by context should work.
|
| host_.CancelRequestsForContext(filter_->resource_context());
|
| EXPECT_EQ(0, host_.pending_requests());
|
| +
|
| + while (net::URLRequestTestJob::ProcessOnePendingMessage()) {
|
| + }
|
| + base::RunLoop().RunUntilIdle();
|
| }
|
| }
|
|
|
| @@ -2964,6 +3011,7 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationText) {
|
| // Flush all the pending requests to get the response through the
|
| // MimeTypeResourceHandler.
|
| while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
|
| + base::RunLoop().RunUntilIdle();
|
|
|
| // Restore, now that we've set up a transfer.
|
| SetBrowserClientForTesting(old_client);
|
| @@ -3132,6 +3180,7 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
|
| // Flush all the pending requests to get the response through the
|
| // MimeTypeResourceHandler.
|
| while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
|
| + base::RunLoop().RunUntilIdle();
|
|
|
| // Restore.
|
| SetBrowserClientForTesting(old_client);
|
| @@ -3738,6 +3787,38 @@ TEST_P(ResourceDispatcherHostTest, TransferRequestRedirectedDownload) {
|
| web_contents_observer_->resource_request_redirect_count());
|
| }
|
|
|
| +// Tests that a ResourceThrottle that needs to process the response before any
|
| +// part of the body is read can do so.
|
| +TEST_P(ResourceDispatcherHostTest, ThrottleMustProcessResponseBeforeRead) {
|
| + // Ensure all jobs will check that no read operation is called.
|
| + job_factory_->SetMustNotReadJobGeneration(true);
|
| + HandleScheme("http");
|
| +
|
| + // Create a ResourceThrottle that must process the response before any part of
|
| + // the body is read. This throttle will also cancel the request in
|
| + // WillProcessResponse.
|
| + TestResourceDispatcherHostDelegate delegate;
|
| + int throttle_flags = CANCEL_PROCESSING_RESPONSE | MUST_NOT_CACHE_BODY;
|
| + delegate.set_flags(throttle_flags);
|
| + host_.SetDelegate(&delegate);
|
| +
|
| + // This response should normally result in the MIME type being sniffed, which
|
| + // requires reading the body.
|
| + std::string raw_headers(
|
| + "HTTP/1.1 200 OK\n"
|
| + "Content-Type: text/plain; charset=utf-8\n\n");
|
| + std::string response_data("p { text-align: center; }");
|
| + SetResponse(raw_headers, response_data);
|
| +
|
| + MakeTestRequestWithResourceType(filter_.get(), filter_->child_id(), 1,
|
| + GURL("http://example.com/blah"),
|
| + RESOURCE_TYPE_STYLESHEET);
|
| +
|
| + while (net::URLRequestTestJob::ProcessOnePendingMessage()) {
|
| + }
|
| + base::RunLoop().RunUntilIdle();
|
| +}
|
| +
|
| // A URLRequestTestJob that sets a test certificate on the |ssl_info|
|
| // field of the response.
|
| class TestHTTPSURLRequestJob : public net::URLRequestTestJob {
|
| @@ -3801,6 +3882,10 @@ net::URLRequestJob* TestURLRequestJobFactory::MaybeCreateJobWithProtocolHandler(
|
| request, network_delegate,
|
| test_fixture_->response_headers_, test_fixture_->response_data_,
|
| false);
|
| + } else if (must_not_read_) {
|
| + return new URLRequestMustNotReadTestJob(request, network_delegate,
|
| + test_fixture_->response_headers_,
|
| + test_fixture_->response_data_);
|
| } else if (test_fixture_->use_test_ssl_certificate_) {
|
| return new TestHTTPSURLRequestJob(request, network_delegate,
|
| test_fixture_->response_headers_,
|
|
|