| 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 9db7d37188e5d8e7068e16d5f5fc976784c70785..54f74d4145329ca3f7bfd148678852f8bcfeda57 100644
|
| --- a/content/browser/loader/resource_dispatcher_host_unittest.cc
|
| +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
|
| @@ -2,10 +2,13 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| +#include <queue>
|
| +#include <string>
|
| #include <vector>
|
|
|
| #include "base/basictypes.h"
|
| #include "base/bind.h"
|
| +#include "base/callback.h"
|
| #include "base/files/file_path.h"
|
| #include "base/files/file_util.h"
|
| #include "base/memory/scoped_vector.h"
|
| @@ -38,6 +41,7 @@
|
| #include "content/public/test/test_browser_thread_bundle.h"
|
| #include "content/test/test_content_browser_client.h"
|
| #include "net/base/elements_upload_data_stream.h"
|
| +#include "net/base/load_flags.h"
|
| #include "net/base/net_errors.h"
|
| #include "net/base/request_priority.h"
|
| #include "net/base/upload_bytes_element_reader.h"
|
| @@ -785,6 +789,8 @@ class ResourceDispatcherHostTest : public testing::Test,
|
| job_factory_.reset(new TestURLRequestJobFactory(this));
|
| request_context->set_job_factory(job_factory_.get());
|
| request_context->set_network_delegate(&network_delegate_);
|
| + // TODO(ricea): Remove this when it becomes the default.
|
| + host_.async_revalidation_enabled_ = true;
|
| }
|
|
|
| // IPC::Sender implementation
|
| @@ -942,9 +948,22 @@ class ResourceDispatcherHostTest : public testing::Test,
|
| wait_for_request_complete_loop_.reset();
|
| }
|
|
|
| + typedef base::Callback<net::URLRequestJob*(net::URLRequest*,
|
| + net::NetworkDelegate*)>
|
| + URLRequestJobCreateCallback;
|
| +
|
| + void SetCustomURLRequestJobCreateCallback(
|
| + const URLRequestJobCreateCallback& callback) {
|
| + custom_url_request_job_create_callback_.reset(
|
| + new URLRequestJobCreateCallback(callback));
|
| + }
|
| +
|
| scoped_ptr<LoadInfoTestRequestInfo> loader_test_request_info_;
|
| scoped_ptr<base::RunLoop> wait_for_request_create_loop_;
|
|
|
| + scoped_ptr<URLRequestJobCreateCallback>
|
| + custom_url_request_job_create_callback_;
|
| +
|
| content::TestBrowserThreadBundle thread_bundle_;
|
| scoped_ptr<TestBrowserContext> browser_context_;
|
| scoped_ptr<TestURLRequestJobFactory> job_factory_;
|
| @@ -3202,6 +3221,10 @@ net::URLRequestJob* TestURLRequestJobFactory::MaybeCreateJobWithProtocolHandler(
|
| return new URLRequestLoadInfoJob(request, network_delegate,
|
| info->load_state, info->upload_progress);
|
| }
|
| + if (test_fixture_->custom_url_request_job_create_callback_) {
|
| + return test_fixture_->custom_url_request_job_create_callback_->Run(
|
| + request, network_delegate);
|
| + }
|
| if (test_fixture_->response_headers_.empty()) {
|
| if (delay_start_) {
|
| return new URLRequestTestDelayedStartJob(request, network_delegate);
|
| @@ -3248,4 +3271,220 @@ net::URLRequestJob* TestURLRequestJobFactory::MaybeInterceptResponse(
|
| return nullptr;
|
| }
|
|
|
| +TEST_F(ResourceDispatcherHostTest, SupportsAsyncRevalidation) {
|
| + // Scheme has to be HTTP or HTTPS to support async revalidation.
|
| + HandleScheme("http");
|
| + // Prevent the job from completing synchronously.
|
| + job_factory_->SetDelayedCompleteJobGeneration(true);
|
| + SetResponse(net::URLRequestTestJob::test_headers(), "delay complete");
|
| + MakeTestRequest(0, 1, GURL("http://example.com/baz"));
|
| +
|
| + net::URLRequest* url_request(
|
| + host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
|
| + ASSERT_TRUE(url_request);
|
| +
|
| + EXPECT_TRUE(url_request->load_flags() & net::LOAD_SUPPORT_ASYNC_REVALIDATION);
|
| +}
|
| +
|
| +TEST_F(ResourceDispatcherHostTest, RequestsNotAsyncByDefault) {
|
| + // Scheme has to be HTTP or HTTPS to support async revalidation.
|
| + HandleScheme("http");
|
| + // Prevent the job from completing synchronously.
|
| + job_factory_->SetDelayedCompleteJobGeneration(true);
|
| + SetResponse(net::URLRequestTestJob::test_headers(), "delay complete");
|
| + MakeTestRequest(0, 1, GURL("http://example.com/baz"));
|
| +
|
| + ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
|
| + host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
|
| + ASSERT_TRUE(info);
|
| +
|
| + EXPECT_FALSE(info->IsAsyncRevalidation());
|
| +}
|
| +
|
| +TEST_F(ResourceDispatcherHostTest, AsyncRevalidationNotSupportedForPOST) {
|
| + // Scheme has to be HTTP or HTTPS to support async revalidation.
|
| + HandleScheme("http");
|
| + // Prevent the job from completing synchronously.
|
| + job_factory_->SetDelayedCompleteJobGeneration(true);
|
| + SetResponse(net::URLRequestTestJob::test_headers(), "delay complete");
|
| + // Create POST request.
|
| + ResourceHostMsg_Request request = CreateResourceRequest(
|
| + "POST", RESOURCE_TYPE_SUB_RESOURCE, GURL("http://example.com/baz.php"));
|
| + ResourceHostMsg_RequestResource msg(0, 1, request);
|
| + host_.OnMessageReceived(msg, filter_.get());
|
| + KickOffRequest();
|
| +
|
| + net::URLRequest* url_request(
|
| + host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
|
| + ASSERT_TRUE(url_request);
|
| +
|
| + EXPECT_FALSE(url_request->load_flags() &
|
| + net::LOAD_SUPPORT_ASYNC_REVALIDATION);
|
| +}
|
| +
|
| +// A URLRequest job type which sets the |async_revalidation_required| flag on
|
| +// the HttpResponseInfo object to true if the request has the
|
| +// LOAD_SUPPORT_ASYNC_REVALIDATION flag.
|
| +class AsyncRevalidationRequiredURLRequestTestJob
|
| + : public net::URLRequestTestJob {
|
| + public:
|
| + // The Create() method is useful for wrapping the construction of the object
|
| + // in a Callback.
|
| + static net::URLRequestJob* Create(net::URLRequest* request,
|
| + net::NetworkDelegate* network_delegate) {
|
| + return new AsyncRevalidationRequiredURLRequestTestJob(request,
|
| + network_delegate);
|
| + }
|
| +
|
| + void GetResponseInfo(net::HttpResponseInfo* info) override {
|
| + if (request()->load_flags() & net::LOAD_SUPPORT_ASYNC_REVALIDATION)
|
| + info->async_revalidation_required = true;
|
| + }
|
| +
|
| + private:
|
| + AsyncRevalidationRequiredURLRequestTestJob(
|
| + net::URLRequest* request,
|
| + net::NetworkDelegate* network_delegate)
|
| + : URLRequestTestJob(request,
|
| + network_delegate,
|
| + net::URLRequestTestJob::test_headers(),
|
| + std::string(),
|
| + false) {}
|
| +
|
| + ~AsyncRevalidationRequiredURLRequestTestJob() override {}
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(AsyncRevalidationRequiredURLRequestTestJob);
|
| +};
|
| +
|
| +// A ResourceDispatcherHostDelegate that records the URLRequests that it sees
|
| +// in a queue.
|
| +class URLRequestRecordingResourceDispatcherHostDelegate
|
| + : public ResourceDispatcherHostDelegate {
|
| + public:
|
| + URLRequestRecordingResourceDispatcherHostDelegate() : requests_() {}
|
| +
|
| + net::URLRequest* NextRequest() {
|
| + CHECK(!requests_.empty());
|
| + net::URLRequest* request = requests_.front();
|
| + requests_.pop();
|
| + return request;
|
| + }
|
| +
|
| + bool IsEmpty() {
|
| + return requests_.empty();
|
| + }
|
| +
|
| + void OnResponseStarted(net::URLRequest* request,
|
| + ResourceContext* resource_context,
|
| + ResourceResponse* response,
|
| + IPC::Sender* sender) override {
|
| + requests_.push(request);
|
| + }
|
| +
|
| + private:
|
| + std::queue<net::URLRequest*> requests_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(URLRequestRecordingResourceDispatcherHostDelegate);
|
| +};
|
| +
|
| +TEST_F(ResourceDispatcherHostTest, AsyncRevalidationIssued) {
|
| + // Scheme has to be HTTP or HTTPS to support async revalidation.
|
| + HandleScheme("http");
|
| + // Use the AsyncRevalidationRequiredURLRequestTestJob.
|
| + SetCustomURLRequestJobCreateCallback(
|
| + base::Bind(&AsyncRevalidationRequiredURLRequestTestJob::Create));
|
| + URLRequestRecordingResourceDispatcherHostDelegate delegate;
|
| + host_.SetDelegate(&delegate);
|
| + MakeTestRequest(0, 1, GURL("http://example.com/baz"));
|
| +
|
| + net::URLRequest* initial_request = delegate.NextRequest();
|
| + ASSERT_TRUE(initial_request);
|
| + ResourceRequestInfoImpl* initial_info =
|
| + ResourceRequestInfoImpl::ForRequest(initial_request);
|
| + ASSERT_TRUE(initial_info);
|
| +
|
| + EXPECT_FALSE(initial_info->IsAsyncRevalidation());
|
| +
|
| + net::URLRequest* async_request = delegate.NextRequest();
|
| + ASSERT_TRUE(async_request);
|
| + ResourceRequestInfoImpl* async_info =
|
| + ResourceRequestInfoImpl::ForRequest(async_request);
|
| + ASSERT_TRUE(async_info);
|
| +
|
| + EXPECT_TRUE(async_info->IsAsyncRevalidation());
|
| +}
|
| +
|
| +TEST_F(ResourceDispatcherHostTest,
|
| + AsyncRevalidationsDoNotSupportAsyncRevalidation) {
|
| + // Scheme has to be HTTP or HTTPS to support async revalidation.
|
| + HandleScheme("http");
|
| + // Use the AsyncRevalidationRequiredURLRequestTestJob.
|
| + SetCustomURLRequestJobCreateCallback(
|
| + base::Bind(&AsyncRevalidationRequiredURLRequestTestJob::Create));
|
| + URLRequestRecordingResourceDispatcherHostDelegate delegate;
|
| + host_.SetDelegate(&delegate);
|
| + MakeTestRequest(0, 1, GURL("http://example.com/baz"));
|
| +
|
| + // Discard the original request.
|
| + delegate.NextRequest();
|
| +
|
| + // Get the async revalidation request.
|
| + net::URLRequest* async_request = delegate.NextRequest();
|
| +
|
| + EXPECT_FALSE(async_request->load_flags() &
|
| + net::LOAD_SUPPORT_ASYNC_REVALIDATION);
|
| +}
|
| +
|
| +TEST_F(ResourceDispatcherHostTest, AsyncRevalidationsNotDuplicated) {
|
| + // Scheme has to be HTTP or HTTPS to support async revalidation.
|
| + HandleScheme("http");
|
| + // Use the AsyncRevalidationRequiredURLRequestTestJob.
|
| + SetCustomURLRequestJobCreateCallback(
|
| + base::Bind(&AsyncRevalidationRequiredURLRequestTestJob::Create));
|
| + URLRequestRecordingResourceDispatcherHostDelegate delegate;
|
| + host_.SetDelegate(&delegate);
|
| + MakeTestRequest(0, 1, GURL("http://example.com/baz"));
|
| +
|
| + // Discard the original request.
|
| + delegate.NextRequest();
|
| +
|
| + // Get the async revalidation request info.
|
| + ResourceRequestInfoImpl* async_info =
|
| + ResourceRequestInfoImpl::ForRequest(delegate.NextRequest());
|
| +
|
| + // Start a second request to the same URL.
|
| + MakeTestRequest(0, 2, GURL("http://example.com/baz"));
|
| +
|
| + ResourceRequestInfoImpl* second_request_info =
|
| + ResourceRequestInfoImpl::ForRequest(delegate.NextRequest());
|
| +
|
| + EXPECT_TRUE(async_info->IsAsyncRevalidation());
|
| + EXPECT_FALSE(second_request_info->IsAsyncRevalidation());
|
| + EXPECT_TRUE(delegate.IsEmpty());
|
| +}
|
| +
|
| +// Async revalidation to different URLs should not be treated as duplicates.
|
| +TEST_F(ResourceDispatcherHostTest,
|
| + AsyncRevalidationsToSeparateURLsAreSeparate) {
|
| + // Scheme has to be HTTP or HTTPS to support async revalidation.
|
| + HandleScheme("http");
|
| + // Use the AsyncRevalidationRequiredURLRequestTestJob.
|
| + SetCustomURLRequestJobCreateCallback(
|
| + base::Bind(&AsyncRevalidationRequiredURLRequestTestJob::Create));
|
| + URLRequestRecordingResourceDispatcherHostDelegate delegate;
|
| + host_.SetDelegate(&delegate);
|
| + MakeTestRequest(0, 1, GURL("http://example.com/baz"));
|
| + MakeTestRequest(0, 2, GURL("http://example.com/far"));
|
| +
|
| + net::URLRequest* initial_request = delegate.NextRequest();
|
| + net::URLRequest* initial_async_revalidation = delegate.NextRequest();
|
| + net::URLRequest* second_request = delegate.NextRequest();
|
| + net::URLRequest* second_async_revalidation = delegate.NextRequest();
|
| +
|
| + EXPECT_EQ("http://example.com/baz", initial_request->url().spec());
|
| + EXPECT_EQ("http://example.com/baz", initial_async_revalidation->url().spec());
|
| + EXPECT_EQ("http://example.com/far", second_request->url().spec());
|
| + EXPECT_EQ("http://example.com/far", second_async_revalidation->url().spec());
|
| +}
|
| +
|
| } // namespace content
|
|
|