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

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: Use histograms instead of user actions. 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 base::WeakPtrFactory<MockClientCertURLRequestJob> weak_factory_;
252 };
253
254 class AsyncRevalidationDriverClientCertTest
255 : public AsyncRevalidationDriverTest {
256 protected:
257 AsyncRevalidationDriverClientCertTest()
258 : AsyncRevalidationDriverTest(
259 BindCreateProtocolHandlerCallback<MockClientCertURLRequestJob>()) {}
260 };
261
262 // Test browser client that causes the test to fail if SelectClientCertificate()
263 // is called. Automatically sets itself as the browser client when constructed
264 // and restores the old browser client in the destructor.
265 class ScopedDontSelectCertificateBrowserClient
266 : public TestContentBrowserClient {
267 public:
268 ScopedDontSelectCertificateBrowserClient() {
269 old_client_ = SetBrowserClientForTesting(this);
270 }
271
272 ~ScopedDontSelectCertificateBrowserClient() override {
273 SetBrowserClientForTesting(old_client_);
274 }
275
276 void SelectClientCertificate(
277 WebContents* web_contents,
278 net::SSLCertRequestInfo* cert_request_info,
279 scoped_ptr<ClientCertificateDelegate> delegate) override {
280 ADD_FAILURE() << "SelectClientCertificate was called.";
281 }
282
283 private:
284 ContentBrowserClient* old_client_;
285
286 DISALLOW_COPY_AND_ASSIGN(ScopedDontSelectCertificateBrowserClient);
287 };
288
289 // Verifies that async revalidation requests do not attempt to provide client
290 // certificates.
291 TEST_F(AsyncRevalidationDriverClientCertTest, RequestRejected) {
292 // Ensure that SelectClientCertificate is not called during this test.
293 ScopedDontSelectCertificateBrowserClient test_client;
294
295 // Start the request and wait for it to pause.
296 driver_->StartRequest();
297
298 // Because TestBrowserThreadBundle only uses one real thread, this is
299 // sufficient to ensure that tasks posted to the "UI thread" have run.
300 base::RunLoop().RunUntilIdle();
301
302 // Check that the request aborted.
303 EXPECT_FALSE(last_status().is_success());
304 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, last_status().error());
305 EXPECT_TRUE(async_revalidation_complete_called());
306 }
307
308 // A mock URLRequestJob which simulates an SSL certificate error.
309 class MockSSLErrorURLRequestJob : public net::URLRequestTestJob {
310 public:
311 MockSSLErrorURLRequestJob(net::URLRequest* request,
312 net::NetworkDelegate* network_delegate)
313 : net::URLRequestTestJob(request, network_delegate, true),
314 weak_factory_(this) {}
315
316 // net::URLRequestTestJob implementation:
317 void Start() override {
318 // This SSLInfo isn't really valid, but it is good enough for testing.
319 net::SSLInfo ssl_info;
320 ssl_info.SetCertError(net::ERR_CERT_DATE_INVALID);
321 base::ThreadTaskRunnerHandle::Get()->PostTask(
322 FROM_HERE,
323 base::Bind(&MockSSLErrorURLRequestJob::NotifySSLCertificateError,
324 weak_factory_.GetWeakPtr(), ssl_info, false));
325 }
326
327 void ContinueDespiteLastError() override {
328 ADD_FAILURE() << "ContinueDespiteLastError called.";
329 }
330
331 private:
332 base::WeakPtrFactory<MockSSLErrorURLRequestJob> weak_factory_;
333 };
334
335 class AsyncRevalidationDriverSSLErrorTest : public AsyncRevalidationDriverTest {
336 protected:
337 AsyncRevalidationDriverSSLErrorTest()
338 : AsyncRevalidationDriverTest(
339 BindCreateProtocolHandlerCallback<MockSSLErrorURLRequestJob>()) {}
340 };
341
342 // Verifies that async revalidation requests do not attempt to recover from SSL
343 // certificate errors.
344 TEST_F(AsyncRevalidationDriverSSLErrorTest, RequestWithSSLErrorRejected) {
345 // Start the request and wait for it to pause.
346 driver_->StartRequest();
347 base::RunLoop().RunUntilIdle();
348
349 // Check that the request has been aborted.
350 EXPECT_FALSE(last_status().is_success());
351 EXPECT_EQ(net::ERR_ABORTED, last_status().error());
352 EXPECT_TRUE(async_revalidation_complete_called());
353 }
354
355 // A URLRequestTestJob that sets |request_time| and |was_cached| on their
356 // response_info, and causes the test to fail if Read() is called.
357 class FromCacheURLRequestJob : public net::URLRequestTestJob {
358 public:
359 FromCacheURLRequestJob(net::URLRequest* request,
360 net::NetworkDelegate* network_delegate)
361 : net::URLRequestTestJob(request, network_delegate, true) {}
362
363 void GetResponseInfo(net::HttpResponseInfo* info) override {
364 URLRequestTestJob::GetResponseInfo(info);
365 info->request_time = base::Time::Now();
366 info->was_cached = true;
367 }
368
369 int ReadRawData(net::IOBuffer* buf, int buf_size) override {
370 ADD_FAILURE() << "ReadRawData() was called.";
371 return URLRequestTestJob::ReadRawData(buf, buf_size);
372 }
373
374 private:
375 ~FromCacheURLRequestJob() override {}
376
377 DISALLOW_COPY_AND_ASSIGN(FromCacheURLRequestJob);
378 };
379
380 class AsyncRevalidationDriverFromCacheTest
381 : public AsyncRevalidationDriverTest {
382 protected:
383 AsyncRevalidationDriverFromCacheTest()
384 : AsyncRevalidationDriverTest(
385 BindCreateProtocolHandlerCallback<FromCacheURLRequestJob>()) {}
386 };
387
388 TEST_F(AsyncRevalidationDriverFromCacheTest,
389 CacheNotReadOnSuccessfulRevalidation) {
390 driver_->StartRequest();
391 base::RunLoop().RunUntilIdle();
392
393 EXPECT_TRUE(async_revalidation_complete_called());
394 }
395
396 } // namespace
397 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/loader/async_revalidation_driver.cc ('k') | content/browser/loader/async_revalidation_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698