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

Side by Side Diff: content/browser/loader/async_revalidation_driver_unittest.cc

Issue 1041993004: content::ResourceDispatcherHostImpl changes for stale-while-revalidate (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@s-w-r-yhirano-patch
Patch Set: Remove Driver::CancelRequest(). Simplify tests. Created 5 years 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/loader/async_revalidation_driver.h"
6
7 #include <string>
8 #include <type_traits>
9 #include <utility>
10 #include <vector>
11
12 #include "base/bind.h"
13 #include "base/callback.h"
14 #include "base/location.h"
15 #include "base/macros.h"
16 #include "base/run_loop.h"
17 #include "content/public/browser/client_certificate_delegate.h"
18 #include "content/public/common/content_client.h"
19 #include "content/public/test/test_browser_thread_bundle.h"
20 #include "content/test/test_content_browser_client.h"
21 #include "ipc/ipc_message.h"
22 #include "net/base/net_errors.h"
23 #include "net/base/network_delegate_impl.h"
24 #include "net/base/request_priority.h"
25 #include "net/ssl/ssl_cert_request_info.h"
26 #include "net/url_request/url_request_job_factory.h"
27 #include "net/url_request/url_request_job_factory_impl.h"
28 #include "net/url_request/url_request_status.h"
29 #include "net/url_request/url_request_test_job.h"
30 #include "net/url_request/url_request_test_util.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32
33 namespace content {
34 namespace {
35
36 // Dummy implementation of ResourceThrottle, an instance of which is needed to
37 // initialize AsyncRevalidationDriver.
38 class ResourceThrottleStub : public ResourceThrottle {
39 public:
40 ResourceThrottleStub() {}
41
42 // If true, defers the request in WillStartRequest.
43 void set_defer_request_on_will_start_request(
44 bool defer_request_on_will_start_request) {
45 defer_request_on_will_start_request_ = defer_request_on_will_start_request;
46 }
47
48 // ResourceThrottler implementation:
49 void WillStartRequest(bool* defer) override {
50 *defer = defer_request_on_will_start_request_;
51 }
52
53 const char* GetNameForLogging() const override {
54 return "ResourceThrottleStub";
55 }
56
57 private:
58 bool defer_request_on_will_start_request_ = false;
59
60 DISALLOW_COPY_AND_ASSIGN(ResourceThrottleStub);
61 };
62
63 // There are multiple layers of boilerplate needed to use a URLRequestTestJob
64 // subclass. Subclasses of AsyncRevalidationDriverTest can use
65 // BindCreateProtocolHandlerCallback() to bypass most of that boilerplate.
66 using CreateProtocolHandlerCallback =
67 base::Callback<scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>()>;
68
69 template <typename T>
70 CreateProtocolHandlerCallback BindCreateProtocolHandlerCallback() {
71 static_assert(std::is_base_of<net::URLRequestJob, T>::value,
72 "Template argument to BindCreateProtocolHandlerCallback() must "
73 "be a subclass of URLRequestJob.");
74
75 class TemplatedProtocolHandler
76 : public net::URLRequestJobFactory::ProtocolHandler {
77 public:
78 static scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> Create() {
79 return make_scoped_ptr(new TemplatedProtocolHandler());
80 }
81
82 // URLRequestJobFactory::ProtocolHandler implementation:
83 net::URLRequestJob* MaybeCreateJob(
84 net::URLRequest* request,
85 net::NetworkDelegate* network_delegate) const override {
86 return new T(request, network_delegate);
87 }
88 };
89
90 return base::Bind(&TemplatedProtocolHandler::Create);
91 }
92
93 // An implementation of NetworkDelegate that captures the status of the last
94 // URLRequest to be destroyed.
95 class StatusCapturingNetworkDelegate : public net::NetworkDelegateImpl {
96 public:
97 const net::URLRequestStatus& last_status() { return last_status_; }
98
99 private:
100 // net::NetworkDelegate implementation.
101 void OnURLRequestDestroyed(net::URLRequest* request) override {
102 last_status_ = request->status();
103 }
104
105 net::URLRequestStatus last_status_;
106 };
107
108 class AsyncRevalidationDriverTest : public testing::Test {
109 protected:
110 // Constructor for test fixtures that subclass this one.
111 AsyncRevalidationDriverTest(
112 const CreateProtocolHandlerCallback& create_protocol_handler_callback)
113 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
114 create_protocol_handler_callback_(create_protocol_handler_callback),
115 raw_ptr_resource_throttle_(nullptr),
116 raw_ptr_request_(nullptr) {
117 test_url_request_context_.set_job_factory(&job_factory_);
118 test_url_request_context_.set_network_delegate(&network_delegate_);
119 }
120
121 // Constructor for tests that use this fixture directly.
122 AsyncRevalidationDriverTest()
123 : AsyncRevalidationDriverTest(
124 base::Bind(net::URLRequestTestJob::CreateProtocolHandler)) {}
125
126 bool async_revalidation_complete_called() const {
127 return async_revalidation_complete_called_;
128 }
129
130 const net::URLRequestStatus& last_status() {
131 return network_delegate_.last_status();
132 }
133
134 void SetUpAsyncRevalidationDriverWithRequestToUrl(const GURL& url) {
135 scoped_ptr<net::URLRequest> request(test_url_request_context_.CreateRequest(
136 url, net::DEFAULT_PRIORITY, nullptr /* delegate */));
137 raw_ptr_request_ = request.get();
138 raw_ptr_resource_throttle_ = new ResourceThrottleStub();
139 // This use of base::Unretained() is safe because |driver_|, and the closure
140 // passed to it, will be destroyed before this object is.
141 driver_.reset(new AsyncRevalidationDriver(
142 std::move(request), make_scoped_ptr(raw_ptr_resource_throttle_),
143 base::Bind(&AsyncRevalidationDriverTest::OnAsyncRevalidationComplete,
144 base::Unretained(this))));
145 }
146
147 void SetUpAsyncRevalidationDriverWithDefaultRequest() {
148 SetUpAsyncRevalidationDriverWithRequestToUrl(
149 net::URLRequestTestJob::test_url_1());
150 }
151
152 void SetUp() override {
153 job_factory_.SetProtocolHandler("test",
154 create_protocol_handler_callback_.Run());
155 SetUpAsyncRevalidationDriverWithDefaultRequest();
156 }
157
158 void OnAsyncRevalidationComplete() {
159 EXPECT_FALSE(async_revalidation_complete_called_);
160 async_revalidation_complete_called_ = true;
161 driver_.reset();
162 }
163
164 TestBrowserThreadBundle thread_bundle_;
165 net::URLRequestJobFactoryImpl job_factory_;
166 net::TestURLRequestContext test_url_request_context_;
167 StatusCapturingNetworkDelegate network_delegate_;
168 CreateProtocolHandlerCallback create_protocol_handler_callback_;
169
170 // The AsyncRevalidationDriver owns the URLRequest and the ResourceThrottle.
171 ResourceThrottleStub* raw_ptr_resource_throttle_;
172 net::URLRequest* raw_ptr_request_;
173 scoped_ptr<AsyncRevalidationDriver> driver_;
174 bool async_revalidation_complete_called_ = false;
175 };
176
177 TEST_F(AsyncRevalidationDriverTest, NormalRequestCompletes) {
178 driver_->StartRequest();
179 base::RunLoop().RunUntilIdle();
180 EXPECT_TRUE(async_revalidation_complete_called());
181 }
182
183 // Verifies that request that should be deferred at start is deferred.
184 TEST_F(AsyncRevalidationDriverTest, DeferOnStart) {
185 raw_ptr_resource_throttle_->set_defer_request_on_will_start_request(true);
186
187 driver_->StartRequest();
188 base::RunLoop().RunUntilIdle();
189 EXPECT_FALSE(raw_ptr_request_->is_pending());
190 EXPECT_FALSE(async_revalidation_complete_called());
191 }
192
193 // Verifies that resuming a deferred request works. Assumes that DeferOnStart
194 // passes.
195 TEST_F(AsyncRevalidationDriverTest, ResumeDeferredRequestWorks) {
196 raw_ptr_resource_throttle_->set_defer_request_on_will_start_request(true);
197
198 driver_->StartRequest();
199 base::RunLoop().RunUntilIdle();
200
201 ResourceController* driver_as_resource_controller = driver_.get();
202 driver_as_resource_controller->Resume();
203 base::RunLoop().RunUntilIdle();
204 EXPECT_TRUE(async_revalidation_complete_called());
205 }
206
207 // Verifies that redirects are not followed.
208 TEST_F(AsyncRevalidationDriverTest, RedirectsAreNotFollowed) {
209 SetUpAsyncRevalidationDriverWithRequestToUrl(
210 net::URLRequestTestJob::test_url_redirect_to_url_2());
211
212 driver_->StartRequest();
213 while (net::URLRequestTestJob::ProcessOnePendingMessage())
214 base::RunLoop().RunUntilIdle();
215 base::RunLoop().RunUntilIdle();
216 EXPECT_FALSE(last_status().is_success());
217 EXPECT_EQ(net::ERR_ABORTED, last_status().error());
218 EXPECT_TRUE(async_revalidation_complete_called());
219 }
220
221 // A mock URLRequestJob which simulates an SSL client auth request.
222 class MockClientCertURLRequestJob : public net::URLRequestTestJob {
223 public:
224 MockClientCertURLRequestJob(net::URLRequest* request,
225 net::NetworkDelegate* network_delegate)
226 : net::URLRequestTestJob(request, network_delegate, true),
227 weak_factory_(this) {}
228
229 // net::URLRequestTestJob implementation:
230 void Start() override {
231 scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
232 new net::SSLCertRequestInfo);
233 base::ThreadTaskRunnerHandle::Get()->PostTask(
234 FROM_HERE,
235 base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested,
236 weak_factory_.GetWeakPtr(), cert_request_info));
237 }
238
239 void ContinueWithCertificate(
240 net::X509Certificate* cert,
241 net::SSLPrivateKey* client_private_key) override {
242 ADD_FAILURE() << "Certificate supplied.";
243 }
244
245 void Kill() override {
246 weak_factory_.InvalidateWeakPtrs();
247 URLRequestJob::Kill();
248 }
249
250 private:
251 ~MockClientCertURLRequestJob() override {}
252
253 base::WeakPtrFactory<MockClientCertURLRequestJob> weak_factory_;
254
255 DISALLOW_COPY_AND_ASSIGN(MockClientCertURLRequestJob);
256 };
257
258 class AsyncRevalidationDriverClientCertTest
259 : public AsyncRevalidationDriverTest {
260 protected:
261 AsyncRevalidationDriverClientCertTest()
262 : AsyncRevalidationDriverTest(
263 BindCreateProtocolHandlerCallback<MockClientCertURLRequestJob>()) {}
264 };
265
266 // Test browser client that causes the test to fail if SelectClientCertificate()
267 // is called. Automatically sets itself as the browser client when constructed
268 // and restores the old browser client in the destructor.
269 class ScopedDontSelectCertificateBrowserClient
270 : public TestContentBrowserClient {
271 public:
272 ScopedDontSelectCertificateBrowserClient() {
273 old_client_ = SetBrowserClientForTesting(this);
274 }
275
276 ~ScopedDontSelectCertificateBrowserClient() override {
277 SetBrowserClientForTesting(old_client_);
278 }
279
280 void SelectClientCertificate(
281 WebContents* web_contents,
282 net::SSLCertRequestInfo* cert_request_info,
283 scoped_ptr<ClientCertificateDelegate> delegate) override {
284 ADD_FAILURE() << "SelectClientCertificate was called.";
285 }
286
287 private:
288 ContentBrowserClient* old_client_;
289
290 DISALLOW_COPY_AND_ASSIGN(ScopedDontSelectCertificateBrowserClient);
291 };
292
293 // Verifies that async revalidation requests do not attempt to provide client
294 // certificates.
295 TEST_F(AsyncRevalidationDriverClientCertTest, RequestRejected) {
296 // Ensure that SelectClientCertificate is not called during this test.
297 ScopedDontSelectCertificateBrowserClient test_client;
298
299 // Start the request and wait for it to pause.
300 driver_->StartRequest();
301
302 // Because TestBrowserThreadBundle only uses one real thread, this is
303 // sufficient to ensure that tasks posted to the "UI thread" have run.
304 base::RunLoop().RunUntilIdle();
305
306 // Check that the request aborted.
307 EXPECT_FALSE(last_status().is_success());
308 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, last_status().error());
309 EXPECT_TRUE(async_revalidation_complete_called());
310 }
311
312 // A mock URLRequestJob which simulates an SSL certificate error.
313 class MockSSLErrorURLRequestJob : public net::URLRequestTestJob {
314 public:
315 MockSSLErrorURLRequestJob(net::URLRequest* request,
316 net::NetworkDelegate* network_delegate)
317 : net::URLRequestTestJob(request, network_delegate, true) {}
318
319 // net::URLRequestTestJob implementation:
320 void Start() override {
321 // This SSLInfo isn't really valid, but it is good enough for testing.
322 net::SSLInfo ssl_info;
323 ssl_info.SetCertError(net::ERR_CERT_DATE_INVALID);
324 base::ThreadTaskRunnerHandle::Get()->PostTask(
325 FROM_HERE,
326 base::Bind(&MockSSLErrorURLRequestJob::NotifySSLCertificateError, this,
327 ssl_info, false));
328 }
329
330 void ContinueDespiteLastError() override {
331 ADD_FAILURE() << "ContinueDespiteLastError called.";
332 }
333
334 private:
335 ~MockSSLErrorURLRequestJob() override {}
336
337 DISALLOW_COPY_AND_ASSIGN(MockSSLErrorURLRequestJob);
338 };
339
340 class AsyncRevalidationDriverSSLErrorTest : public AsyncRevalidationDriverTest {
341 protected:
342 AsyncRevalidationDriverSSLErrorTest()
343 : AsyncRevalidationDriverTest(
344 BindCreateProtocolHandlerCallback<MockSSLErrorURLRequestJob>()) {}
345 };
346
347 // Verifies that async revalidation requests do not attempt to recover from SSL
348 // certificate errors.
349 TEST_F(AsyncRevalidationDriverSSLErrorTest, RequestWithSSLErrorRejected) {
350 // Start the request and wait for it to pause.
351 driver_->StartRequest();
352 base::RunLoop().RunUntilIdle();
353
354 // Check that the request has been aborted.
355 EXPECT_FALSE(last_status().is_success());
356 EXPECT_EQ(net::ERR_ABORTED, last_status().error());
357 EXPECT_TRUE(async_revalidation_complete_called());
358 }
359
360 // A URLRequestTestJob that sets |request_time| and |was_cached| on their
361 // response_info, and causes the test to fail if Read() is called.
362 class FromCacheURLRequestJob : public net::URLRequestTestJob {
363 public:
364 FromCacheURLRequestJob(net::URLRequest* request,
365 net::NetworkDelegate* network_delegate)
366 : net::URLRequestTestJob(request, network_delegate, true) {}
367
368 void GetResponseInfo(net::HttpResponseInfo* info) override {
369 URLRequestTestJob::GetResponseInfo(info);
370 info->request_time = base::Time::Now();
371 info->was_cached = true;
372 }
373
374 int ReadRawData(net::IOBuffer* buf, int buf_size) override {
375 ADD_FAILURE() << "ReadRawData() was called.";
376 return URLRequestTestJob::ReadRawData(buf, buf_size);
377 }
378
379 private:
380 ~FromCacheURLRequestJob() override {}
381
382 DISALLOW_COPY_AND_ASSIGN(FromCacheURLRequestJob);
383 };
384
385 class AsyncRevalidationDriverFromCacheTest
386 : public AsyncRevalidationDriverTest {
387 protected:
388 AsyncRevalidationDriverFromCacheTest()
389 : AsyncRevalidationDriverTest(
390 BindCreateProtocolHandlerCallback<FromCacheURLRequestJob>()) {}
391 };
392
393 TEST_F(AsyncRevalidationDriverFromCacheTest,
394 CacheNotReadOnSuccessfulRevalidation) {
395 driver_->StartRequest();
396 base::RunLoop().RunUntilIdle();
397
398 EXPECT_TRUE(async_revalidation_complete_called());
399 }
400
401 } // namespace
402 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698