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

Side by Side Diff: net/cert_net/cert_net_fetcher_impl.cc

Issue 2595723002: Allow CertNetFetcher to be shutdown from the network thread (Closed)
Patch Set: last round of eroman comments Created 3 years, 11 months 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
« no previous file with comments | « net/cert_net/cert_net_fetcher_impl.h ('k') | net/cert_net/cert_net_fetcher_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // Overview 5 // Overview
6 // 6 //
7 // The main entry point is CertNetFetcherImpl. This is an implementation of 7 // The main entry point is CertNetFetcherImpl. This is an implementation of
8 // CertNetFetcher that provides a service for fetching network requests. 8 // CertNetFetcher that provides a service for fetching network requests.
9 // 9 //
10 // The interface for CertNetFetcher is synchronous, however allows 10 // The interface for CertNetFetcher is synchronous, however allows
11 // overlapping requests. When starting a request CertNetFetcherImpl 11 // overlapping requests. When starting a request CertNetFetcherImpl
12 // returns a CertNetFetcher::Request (CertNetFetcherImpl) that the 12 // returns a CertNetFetcher::Request (CertNetFetcherImpl) that the
13 // caller can use to cancel the fetch, or wait for it to complete 13 // caller can use to cancel the fetch, or wait for it to complete
14 // (blocking). 14 // (blocking).
15 // 15 //
16 // The CertNetFetcherImpl is shared between a network thread and a
17 // caller thread that waits for fetches to happen on the network thread.
18 //
16 // The classes are mainly organized based on their thread affinity: 19 // The classes are mainly organized based on their thread affinity:
17 // 20 //
18 // --------------- 21 // ---------------
19 // Lives on caller thread 22 // Straddles caller thread and network thread
20 // --------------- 23 // ---------------
21 // 24 //
22 // CertNetFetcherImpl (implements CertNetFetcher) 25 // CertNetFetcherImpl (implements CertNetFetcher)
23 // * Main entry point 26 // * Main entry point. Must be created and shutdown from the network thread.
24 // * Provides a service to start/cancel/wait for URL fetches 27 // * Provides a service to start/cancel/wait for URL fetches, to be
28 // used on the caller thread.
25 // * Returns callers a CertNetFetcher::Request as a handle 29 // * Returns callers a CertNetFetcher::Request as a handle
26 // * Requests can run in parallel, however will block the current thread when 30 // * Requests can run in parallel, however will block the current thread when
27 // reading results. 31 // reading results.
28 // * Posts tasks to network thread to coordinate actual work 32 // * Posts tasks to network thread to coordinate actual work
29 // 33 //
30 // CertNetFetcherRequestImpl (implements CertNetFetcher::Request)
31 // * Wrapper for cancelling events, or waiting for a request to complete
32 // * Waits on a WaitableEvent to complete requests.
33 //
34 // ---------------
35 // Straddles caller thread and network thread
36 // ---------------
37 //
38 // CertNetFetcherCore
39 // * Reference-counted bridge between CertNetFetcherImpl and the dependencies
40 // on network thread.
41 // * Small wrapper to holds the state that is conceptually owned by
42 // CertNetFetcherImpl, but belongs on the network thread.
43 //
44 // RequestCore 34 // RequestCore
45 // * Reference-counted bridge between CertNetFetcherRequestImpl and the 35 // * Reference-counted bridge between CertNetFetcherRequestImpl and the
46 // dependencies on the network thread 36 // dependencies on the network thread
47 // * Holds the result of the request, a WaitableEvent for signaling 37 // * Holds the result of the request, a WaitableEvent for signaling
48 // completion, and pointers for canceling work on network thread. 38 // completion, and pointers for canceling work on network thread.
49 // 39 //
50 // --------------- 40 // ---------------
41 // Lives on caller thread
42 // ---------------
43 //
44 // CertNetFetcherRequestImpl (implements CertNetFetcher::Request)
45 // * Wrapper for cancelling events, or waiting for a request to complete
46 // * Waits on a WaitableEvent to complete requests.
47 //
48 // ---------------
51 // Lives on network thread 49 // Lives on network thread
52 // --------------- 50 // ---------------
53 // 51 //
54 // AsyncCertNetFetcherImpl 52 // AsyncCertNetFetcherImpl
55 // * Asyncronous manager for outstanding requests. Handles de-duplication, 53 // * Asyncronous manager for outstanding requests. Handles de-duplication,
56 // timeouts, and actual integration with network stack. This is where the 54 // timeouts, and actual integration with network stack. This is where the
57 // majority of the logic lives. 55 // majority of the logic lives.
58 // * Signals completion of requests through RequestCore's WaitableEvent. 56 // * Signals completion of requests through RequestCore's WaitableEvent.
59 // * Attaches requests to Jobs for the purpose of de-duplication 57 // * Attaches requests to Jobs for the purpose of de-duplication
60 58
61 #include "net/cert_net/cert_net_fetcher_impl.h" 59 #include "net/cert_net/cert_net_fetcher_impl.h"
62 60
63 #include <tuple> 61 #include <tuple>
64 #include <utility> 62 #include <utility>
65 63
66 #include "base/callback_helpers.h" 64 #include "base/callback_helpers.h"
67 #include "base/logging.h" 65 #include "base/logging.h"
68 #include "base/macros.h" 66 #include "base/macros.h"
69 #include "base/memory/ptr_util.h" 67 #include "base/memory/ptr_util.h"
70 #include "base/numerics/safe_math.h" 68 #include "base/numerics/safe_math.h"
71 #include "base/synchronization/waitable_event.h" 69 #include "base/synchronization/waitable_event.h"
70 #include "base/threading/thread_task_runner_handle.h"
72 #include "base/timer/timer.h" 71 #include "base/timer/timer.h"
73 #include "net/base/load_flags.h" 72 #include "net/base/load_flags.h"
74 #include "net/cert/cert_net_fetcher.h" 73 #include "net/cert/cert_net_fetcher.h"
75 #include "net/url_request/redirect_info.h" 74 #include "net/url_request/redirect_info.h"
76 #include "net/url_request/url_request_context.h" 75 #include "net/url_request/url_request_context.h"
77 #include "net/url_request/url_request_context_getter.h"
78 76
79 // TODO(eroman): Add support for POST parameters. 77 // TODO(eroman): Add support for POST parameters.
80 // TODO(eroman): Add controls for bypassing the cache. 78 // TODO(eroman): Add controls for bypassing the cache.
81 // TODO(eroman): Add a maximum number of in-flight jobs/requests. 79 // TODO(eroman): Add a maximum number of in-flight jobs/requests.
82 // TODO(eroman): Add NetLog integration. 80 // TODO(eroman): Add NetLog integration.
83 81
84 namespace net { 82 namespace net {
85 83
86 namespace { 84 namespace {
87 85
(...skipping 26 matching lines...) Expand all
114 112
115 // AsyncCertNetFetcherImpl manages URLRequests in an async fashion on the 113 // AsyncCertNetFetcherImpl manages URLRequests in an async fashion on the
116 // URLRequestContexts's task runner thread. 114 // URLRequestContexts's task runner thread.
117 // 115 //
118 // * Schedules 116 // * Schedules
119 // * De-duplicates requests 117 // * De-duplicates requests
120 // * Handles timeouts 118 // * Handles timeouts
121 class AsyncCertNetFetcherImpl { 119 class AsyncCertNetFetcherImpl {
122 public: 120 public:
123 // Initializes AsyncCertNetFetcherImpl using the specified URLRequestContext 121 // Initializes AsyncCertNetFetcherImpl using the specified URLRequestContext
124 // for issuing requests. |context| must remain valid for the entire 122 // for issuing requests. |context| must remain valid until Shutdown() is
125 // lifetime of the AsyncCertNetFetcherImpl. 123 // called or the AsyncCertNetFetcherImpl is destroyed.
126 explicit AsyncCertNetFetcherImpl(URLRequestContext* context); 124 explicit AsyncCertNetFetcherImpl(URLRequestContext* context);
127 125
128 // Deletion implicitly cancels any outstanding requests. 126 // The AsyncCertNetFetcherImpl is expected to be kept alive until all
127 // requests have completed or Shutdown() is called.
129 ~AsyncCertNetFetcherImpl(); 128 ~AsyncCertNetFetcherImpl();
130 129
131 // Starts an asynchronous request to fetch the given URL. On completion 130 // Starts an asynchronous request to fetch the given URL. On completion
132 // |callback| will be invoked. 131 // request->OnJobCompleted() will be invoked.
133 //
134 // Completion of the request will never occur synchronously. In other words it
135 // is guaranteed that |callback| will only be invoked once the Fetch*() method
136 // has returned.
137 void Fetch(std::unique_ptr<RequestParams> request_params, 132 void Fetch(std::unique_ptr<RequestParams> request_params,
138 RequestCore* request); 133 scoped_refptr<RequestCore> request);
134
135 // Cancels outstanding jobs, which stops network requests and signals the
136 // corresponding RequestCores that the requests have completed.
137 void Shutdown();
139 138
140 private: 139 private:
141 friend class Job; 140 friend class Job;
142 141
143 // Finds a job with a matching RequestPararms or returns nullptr if there was 142 // Finds a job with a matching RequestPararms or returns nullptr if there was
144 // no match. 143 // no match.
145 Job* FindJob(const RequestParams& params); 144 Job* FindJob(const RequestParams& params);
146 145
147 // Removes |job| from the in progress jobs and transfers ownership to the 146 // Removes |job| from the in progress jobs and transfers ownership to the
148 // caller. 147 // caller.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 class RequestCore : public base::RefCountedThreadSafe<RequestCore> { 198 class RequestCore : public base::RefCountedThreadSafe<RequestCore> {
200 public: 199 public:
201 explicit RequestCore(scoped_refptr<base::SingleThreadTaskRunner> task_runner) 200 explicit RequestCore(scoped_refptr<base::SingleThreadTaskRunner> task_runner)
202 : completion_event_(base::WaitableEvent::ResetPolicy::MANUAL, 201 : completion_event_(base::WaitableEvent::ResetPolicy::MANUAL,
203 base::WaitableEvent::InitialState::NOT_SIGNALED), 202 base::WaitableEvent::InitialState::NOT_SIGNALED),
204 task_runner_(std::move(task_runner)) {} 203 task_runner_(std::move(task_runner)) {}
205 204
206 void AttachedToJob(Job* job) { 205 void AttachedToJob(Job* job) {
207 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 206 DCHECK(task_runner_->RunsTasksOnCurrentThread());
208 DCHECK(!job_); 207 DCHECK(!job_);
208 // Requests should not be attached to jobs after they have been signalled
209 // with a cancellation error (which happens via either Cancel() or
210 // SignalImmediateError()).
211 DCHECK_NE(error_, ERR_ABORTED);
209 job_ = job; 212 job_ = job;
210 } 213 }
211 214
212 void OnJobCompleted(Job* job, 215 void OnJobCompleted(Job* job,
213 Error error, 216 Error error,
214 const std::vector<uint8_t>& response_body) { 217 const std::vector<uint8_t>& response_body) {
215 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 218 DCHECK(task_runner_->RunsTasksOnCurrentThread());
216 219
217 DCHECK_EQ(job_, job); 220 DCHECK_EQ(job_, job);
218 job_ = nullptr; 221 job_ = nullptr;
219 222
220 error_ = error; 223 error_ = error;
221 bytes_ = response_body; 224 bytes_ = response_body;
222 completion_event_.Signal(); 225 completion_event_.Signal();
223 } 226 }
224 227
225 // Can be called from any thread. 228 // Detaches this request from its job (if it is attached to any), but
226 void Cancel(); 229 // does not signal completion. Can be called from any thread.
eroman 2017/01/13 02:51:17 Change the comment about signalling completion (wi
estark 2017/01/13 02:57:34 Done.
230 void CancelJob();
231
232 // Can be used to signal that an error was encountered before the request was
233 // attached to a job. Can be called from any thread.
234 void SignalImmediateError();
227 235
228 // Should only be called once. 236 // Should only be called once.
229 void WaitForResult(Error* error, std::vector<uint8_t>* bytes) { 237 void WaitForResult(Error* error, std::vector<uint8_t>* bytes) {
230 DCHECK(!task_runner_->RunsTasksOnCurrentThread()); 238 DCHECK(!task_runner_->RunsTasksOnCurrentThread());
231 239
232 completion_event_.Wait(); 240 completion_event_.Wait();
233 *bytes = std::move(bytes_); 241 *bytes = std::move(bytes_);
234 *error = error_; 242 *error = error_;
235 243
236 error_ = ERR_UNEXPECTED; 244 error_ = ERR_UNEXPECTED;
237 } 245 }
238 246
239 private: 247 private:
240 friend class base::RefCountedThreadSafe<RequestCore>; 248 friend class base::RefCountedThreadSafe<RequestCore>;
241 249
242 ~RequestCore() { 250 ~RequestCore() {
243 // Requests should have been cancelled prior to destruction. 251 // Requests should have been cancelled prior to destruction.
244 DCHECK(!job_); 252 DCHECK(!job_);
245 } 253 }
246 254
247 // A non-owned pointer to the job that is executing the request. 255 // A non-owned pointer to the job that is executing the request.
248 Job* job_ = nullptr; 256 Job* job_ = nullptr;
249 257
250 // May be written to from network thread. 258 // May be written to from network thread, or from the caller thread only when
259 // there is no work that will be done on the network thread (e.g. when the
260 // network thread has been shutdown before the request begins). See comment in
261 // SignalImmediateError.
251 Error error_; 262 Error error_;
252 std::vector<uint8_t> bytes_; 263 std::vector<uint8_t> bytes_;
253 264
254 // Indicates when |error_| and |bytes_| have been written to. 265 // Indicates when |error_| and |bytes_| have been written to.
255 base::WaitableEvent completion_event_; 266 base::WaitableEvent completion_event_;
256 267
257 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 268 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
258 269
259 DISALLOW_COPY_AND_ASSIGN(RequestCore); 270 DISALLOW_COPY_AND_ASSIGN(RequestCore);
260 }; 271 };
(...skipping 28 matching lines...) Expand all
289 // Job tracks an outstanding URLRequest as well as all of the pending requests 300 // Job tracks an outstanding URLRequest as well as all of the pending requests
290 // for it. 301 // for it.
291 class Job : public URLRequest::Delegate { 302 class Job : public URLRequest::Delegate {
292 public: 303 public:
293 Job(std::unique_ptr<RequestParams> request_params, 304 Job(std::unique_ptr<RequestParams> request_params,
294 AsyncCertNetFetcherImpl* parent); 305 AsyncCertNetFetcherImpl* parent);
295 ~Job() override; 306 ~Job() override;
296 307
297 const RequestParams& request_params() const { return *request_params_; } 308 const RequestParams& request_params() const { return *request_params_; }
298 309
299 // Create a request and attaches it to the job. When the job completes it will 310 // Creates a request and attaches it to the job. When the job completes it
300 // notify the request of completion through OnJobCompleted. Note that the Job 311 // will notify the request of completion through OnJobCompleted.
301 // does NOT own the request. 312 void AttachRequest(scoped_refptr<RequestCore> request);
302 void AttachRequest(RequestCore* request);
303 313
304 // Removes |request| from the job. 314 // Removes |request| from the job.
305 void DetachRequest(RequestCore* request); 315 void DetachRequest(RequestCore* request);
306 316
307 // Creates and starts a URLRequest for the job. After the URLRequest has 317 // Creates and starts a URLRequest for the job. After the URLRequest has
308 // completed, OnJobCompleted() will be invoked and all the registered requests 318 // completed, OnJobCompleted() will be invoked and all the registered requests
309 // notified of completion. 319 // notified of completion.
310 void StartURLRequest(URLRequestContext* context); 320 void StartURLRequest(URLRequestContext* context);
311 321
322 // Cancels the request with an ERR_ABORTED error and invokes
323 // RequestCore::OnJobCompleted() to notify the registered requests of the
324 // cancellation. The job is *not* removed from the AsyncCertNetFetcherImpl.
325 void Cancel();
326
312 private: 327 private:
313 // Implementation of URLRequest::Delegate 328 // Implementation of URLRequest::Delegate
314 void OnReceivedRedirect(URLRequest* request, 329 void OnReceivedRedirect(URLRequest* request,
315 const RedirectInfo& redirect_info, 330 const RedirectInfo& redirect_info,
316 bool* defer_redirect) override; 331 bool* defer_redirect) override;
317 void OnResponseStarted(URLRequest* request, int net_error) override; 332 void OnResponseStarted(URLRequest* request, int net_error) override;
318 void OnReadCompleted(URLRequest* request, int bytes_read) override; 333 void OnReadCompleted(URLRequest* request, int bytes_read) override;
319 334
320 // Clears the URLRequest and timer. Helper for doing work common to 335 // Clears the URLRequest and timer. Helper for doing work common to
321 // cancellation and job completion. 336 // cancellation and job completion.
322 void Stop(); 337 void Stop();
323 338
324 // Reads as much data as available from |request|. 339 // Reads as much data as available from |request|.
325 void ReadBody(URLRequest* request); 340 void ReadBody(URLRequest* request);
326 341
327 // Helper to copy the partial bytes read from the read IOBuffer to an 342 // Helper to copy the partial bytes read from the read IOBuffer to an
328 // aggregated buffer. 343 // aggregated buffer.
329 bool ConsumeBytesRead(URLRequest* request, int num_bytes); 344 bool ConsumeBytesRead(URLRequest* request, int num_bytes);
330 345
331 // Called when the URLRequest has completed (either success or failure). 346 // Called when the URLRequest has completed (either success or failure).
332 void OnUrlRequestCompleted(int net_error); 347 void OnUrlRequestCompleted(int net_error);
333 348
334 // Called when the Job has completed. The job may finish in response to a 349 // Called when the Job has completed. The job may finish in response to a
335 // timeout, an invalid URL, or the URLRequest completing. By the time this 350 // timeout, an invalid URL, or the URLRequest completing. By the time this
336 // method is called, the |response_body_| variable have been assigned. 351 // method is called, the |response_body_| variable have been assigned.
337 void OnJobCompleted(Error error); 352 void OnJobCompleted(Error error);
338 353
354 // Calls r->OnJobCompleted() for each RequestCore |r| currently attached
355 // to this job, and then clears |requests_|.
356 void CompleteAndClearRequests(Error error);
357
339 // Cancels a request with a specified error code and calls 358 // Cancels a request with a specified error code and calls
340 // OnUrlRequestCompleted(). 359 // OnUrlRequestCompleted().
341 void FailRequest(Error error); 360 void FailRequest(Error error);
342 361
343 // The requests attached to this job (non-owned). 362 // The requests attached to this job.
344 std::vector<RequestCore*> requests_; 363 std::vector<scoped_refptr<RequestCore>> requests_;
345 364
346 // The input parameters for starting a URLRequest. 365 // The input parameters for starting a URLRequest.
347 std::unique_ptr<RequestParams> request_params_; 366 std::unique_ptr<RequestParams> request_params_;
348 367
349 // The URLRequest response information. 368 // The URLRequest response information.
350 std::vector<uint8_t> response_body_; 369 std::vector<uint8_t> response_body_;
351 370
352 std::unique_ptr<URLRequest> url_request_; 371 std::unique_ptr<URLRequest> url_request_;
353 scoped_refptr<IOBuffer> read_buffer_; 372 scoped_refptr<IOBuffer> read_buffer_;
354 373
355 // Used to timeout the job when the URLRequest takes too long. This timer is 374 // Used to timeout the job when the URLRequest takes too long. This timer is
356 // also used for notifying a failure to start the URLRequest. 375 // also used for notifying a failure to start the URLRequest.
357 base::OneShotTimer timer_; 376 base::OneShotTimer timer_;
358 377
359 // Non-owned pointer to the AsyncCertNetFetcherImpl that created this job. 378 // Non-owned pointer to the AsyncCertNetFetcherImpl that created this job.
360 AsyncCertNetFetcherImpl* parent_; 379 AsyncCertNetFetcherImpl* parent_;
361 380
362 DISALLOW_COPY_AND_ASSIGN(Job); 381 DISALLOW_COPY_AND_ASSIGN(Job);
363 }; 382 };
364 383
365 void RequestCore::Cancel() { 384 void RequestCore::CancelJob() {
366 if (!task_runner_->RunsTasksOnCurrentThread()) { 385 if (!task_runner_->RunsTasksOnCurrentThread()) {
367 task_runner_->PostTask(FROM_HERE, base::Bind(&RequestCore::Cancel, this)); 386 task_runner_->PostTask(FROM_HERE,
387 base::Bind(&RequestCore::CancelJob, this));
368 return; 388 return;
369 } 389 }
370 390
371 if (job_) { 391 if (job_) {
372 auto* job = job_; 392 auto* job = job_;
373 job_ = nullptr; 393 job_ = nullptr;
374 job->DetachRequest(this); 394 job->DetachRequest(this);
375 } 395 }
376 396
397 SignalImmediateError();
398 }
399
400 void RequestCore::SignalImmediateError() {
401 // Writing to |error_| or |job_| is safe here from either thread, because
eroman 2017/01/13 02:51:17 did you mean |bytes_| instead of |job_| ?
estark 2017/01/13 02:57:33 I did indeed mean |job_|, but it really should hav
eroman 2017/01/13 03:04:12 New comment is good. What I think was weird in th
402 // SignalImmediateError is only to be called before this request is attached
403 // to a job. In particular, if called from the caller thread, no work will be
404 // done on the network thread for this request, so these variables will only
405 // be written and read on the caller thread. If called from the network
406 // thread, they will only be written to on the network thread and will not
407 // be read on the caller thread until |completion_event_| is signalled (after
408 // which it will be not be written on the network thread again).
409 DCHECK(!job_);
410 error_ = ERR_ABORTED;
377 bytes_.clear(); 411 bytes_.clear();
378 error_ = ERR_UNEXPECTED; 412 completion_event_.Signal();
379 } 413 }
380 414
381 Job::Job(std::unique_ptr<RequestParams> request_params, 415 Job::Job(std::unique_ptr<RequestParams> request_params,
382 AsyncCertNetFetcherImpl* parent) 416 AsyncCertNetFetcherImpl* parent)
383 : request_params_(std::move(request_params)), parent_(parent) {} 417 : request_params_(std::move(request_params)), parent_(parent) {}
384 418
385 Job::~Job() { 419 Job::~Job() {
386 DCHECK(requests_.empty()); 420 DCHECK(requests_.empty());
387 Stop(); 421 Stop();
388 } 422 }
389 423
390 void Job::AttachRequest(RequestCore* request) { 424 void Job::AttachRequest(scoped_refptr<RequestCore> request) {
391 requests_.push_back(request);
392 request->AttachedToJob(this); 425 request->AttachedToJob(this);
426 requests_.push_back(std::move(request));
393 } 427 }
394 428
395 void Job::DetachRequest(RequestCore* request) { 429 void Job::DetachRequest(RequestCore* request) {
396 std::unique_ptr<Job> delete_this; 430 std::unique_ptr<Job> delete_this;
397 431
398 auto it = std::find(requests_.begin(), requests_.end(), request); 432 auto it = std::find(requests_.begin(), requests_.end(), request);
399 DCHECK(it != requests_.end()); 433 DCHECK(it != requests_.end());
400 requests_.erase(it); 434 requests_.erase(it);
401 435
402 // If there are no longer any requests attached to the job then 436 // If there are no longer any requests attached to the job then
403 // cancel and delete it. 437 // cancel and delete it.
404 if (requests_.empty()) 438 if (requests_.empty())
405 delete_this = parent_->RemoveJob(this); 439 delete_this = parent_->RemoveJob(this);
406 } 440 }
407 441
408 void Job::StartURLRequest(URLRequestContext* context) { 442 void Job::StartURLRequest(URLRequestContext* context) {
409 Error error = CanFetchUrl(request_params_->url); 443 Error error = CanFetchUrl(request_params_->url);
410 if (error != OK) { 444 if (error != OK) {
411 // TODO(eroman): Don't post a task for this case. 445 OnJobCompleted(error);
412 timer_.Start(
413 FROM_HERE, base::TimeDelta(),
414 base::Bind(&Job::OnJobCompleted, base::Unretained(this), error));
415 return; 446 return;
416 } 447 }
417 448
418 // Start the URLRequest. 449 // Start the URLRequest.
419 read_buffer_ = new IOBuffer(kReadBufferSizeInBytes); 450 read_buffer_ = new IOBuffer(kReadBufferSizeInBytes);
420 url_request_ = 451 url_request_ =
421 context->CreateRequest(request_params_->url, DEFAULT_PRIORITY, this); 452 context->CreateRequest(request_params_->url, DEFAULT_PRIORITY, this);
422 if (request_params_->http_method == HTTP_METHOD_POST) 453 if (request_params_->http_method == HTTP_METHOD_POST)
423 url_request_->set_method("POST"); 454 url_request_->set_method("POST");
424 url_request_->SetLoadFlags(LOAD_DO_NOT_SAVE_COOKIES | 455 url_request_->SetLoadFlags(LOAD_DO_NOT_SAVE_COOKIES |
425 LOAD_DO_NOT_SEND_COOKIES); 456 LOAD_DO_NOT_SEND_COOKIES);
426 url_request_->Start(); 457 url_request_->Start();
427 458
428 // Start a timer to limit how long the job runs for. 459 // Start a timer to limit how long the job runs for.
429 if (request_params_->timeout > base::TimeDelta()) 460 if (request_params_->timeout > base::TimeDelta())
430 timer_.Start( 461 timer_.Start(
431 FROM_HERE, request_params_->timeout, 462 FROM_HERE, request_params_->timeout,
432 base::Bind(&Job::FailRequest, base::Unretained(this), ERR_TIMED_OUT)); 463 base::Bind(&Job::FailRequest, base::Unretained(this), ERR_TIMED_OUT));
433 } 464 }
434 465
466 void Job::Cancel() {
467 // Stop the timer and clear the URLRequest.
468 Stop();
469 // Signal attached requests that they've been completed.
470 CompleteAndClearRequests(static_cast<Error>(ERR_ABORTED));
471 }
472
435 void Job::OnReceivedRedirect(URLRequest* request, 473 void Job::OnReceivedRedirect(URLRequest* request,
436 const RedirectInfo& redirect_info, 474 const RedirectInfo& redirect_info,
437 bool* defer_redirect) { 475 bool* defer_redirect) {
438 DCHECK_EQ(url_request_.get(), request); 476 DCHECK_EQ(url_request_.get(), request);
439 477
440 // Ensure that the new URL matches the policy. 478 // Ensure that the new URL matches the policy.
441 Error error = CanFetchUrl(redirect_info.new_url); 479 Error error = CanFetchUrl(redirect_info.new_url);
442 if (error != OK) { 480 if (error != OK) {
443 FailRequest(error); 481 FailRequest(error);
444 return; 482 return;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 Error result = static_cast<Error>(net_error); 555 Error result = static_cast<Error>(net_error);
518 OnJobCompleted(result); 556 OnJobCompleted(result);
519 } 557 }
520 558
521 void Job::OnJobCompleted(Error error) { 559 void Job::OnJobCompleted(Error error) {
522 DCHECK_NE(ERR_IO_PENDING, error); 560 DCHECK_NE(ERR_IO_PENDING, error);
523 // Stop the timer and clear the URLRequest. 561 // Stop the timer and clear the URLRequest.
524 Stop(); 562 Stop();
525 563
526 std::unique_ptr<Job> delete_this = parent_->RemoveJob(this); 564 std::unique_ptr<Job> delete_this = parent_->RemoveJob(this);
565 CompleteAndClearRequests(error);
566 }
527 567
528 for (auto* request : requests_) { 568 void Job::CompleteAndClearRequests(Error error) {
569 for (const auto& request : requests_) {
529 request->OnJobCompleted(this, error, response_body_); 570 request->OnJobCompleted(this, error, response_body_);
530 } 571 }
531 572
532 requests_.clear(); 573 requests_.clear();
533 } 574 }
534 575
535 void Job::FailRequest(Error error) { 576 void Job::FailRequest(Error error) {
536 DCHECK_NE(ERR_IO_PENDING, error); 577 DCHECK_NE(ERR_IO_PENDING, error);
537 int result = url_request_->CancelWithError(error); 578 int result = url_request_->CancelWithError(error);
538 OnUrlRequestCompleted(result); 579 OnUrlRequestCompleted(result);
539 } 580 }
540 581
541 AsyncCertNetFetcherImpl::AsyncCertNetFetcherImpl(URLRequestContext* context) 582 AsyncCertNetFetcherImpl::AsyncCertNetFetcherImpl(URLRequestContext* context)
542 : context_(context) { 583 : context_(context) {
543 // Allow creation to happen from another thread. 584 // Allow creation to happen from another thread.
544 thread_checker_.DetachFromThread(); 585 thread_checker_.DetachFromThread();
545 } 586 }
546 587
547 AsyncCertNetFetcherImpl::~AsyncCertNetFetcherImpl() { 588 AsyncCertNetFetcherImpl::~AsyncCertNetFetcherImpl() {
548 DCHECK(thread_checker_.CalledOnValidThread()); 589 DCHECK(thread_checker_.CalledOnValidThread());
549 jobs_.clear(); 590 jobs_.clear();
550 } 591 }
551 592
552 bool JobComparator::operator()(const Job* job1, const Job* job2) const { 593 bool JobComparator::operator()(const Job* job1, const Job* job2) const {
553 return job1->request_params() < job2->request_params(); 594 return job1->request_params() < job2->request_params();
554 } 595 }
555 596
556 void AsyncCertNetFetcherImpl::Fetch( 597 void AsyncCertNetFetcherImpl::Fetch(
557 std::unique_ptr<RequestParams> request_params, 598 std::unique_ptr<RequestParams> request_params,
558 RequestCore* request) { 599 scoped_refptr<RequestCore> request) {
559 DCHECK(thread_checker_.CalledOnValidThread()); 600 DCHECK(thread_checker_.CalledOnValidThread());
560 601
561 // If there is an in-progress job that matches the request parameters use it. 602 // If there is an in-progress job that matches the request parameters use it.
562 // Otherwise start a new job. 603 // Otherwise start a new job.
563 Job* job = FindJob(*request_params); 604 Job* job = FindJob(*request_params);
564 605 if (job) {
565 if (!job) { 606 job->AttachRequest(std::move(request));
566 job = new Job(std::move(request_params), this); 607 return;
567 jobs_[job] = base::WrapUnique(job);
568 job->StartURLRequest(context_);
569 } 608 }
570 609
571 return job->AttachRequest(request); 610 job = new Job(std::move(request_params), this);
611 jobs_[job] = base::WrapUnique(job);
612 // Attach the request before calling StartURLRequest; this ensures that the
613 // request will get signalled if StartURLRequest completes the job
614 // synchronously.
615 job->AttachRequest(std::move(request));
616 job->StartURLRequest(context_);
617 }
618
619 void AsyncCertNetFetcherImpl::Shutdown() {
620 DCHECK(thread_checker_.CalledOnValidThread());
621 for (const auto& job : jobs_) {
622 job.first->Cancel();
623 }
624 jobs_.clear();
572 } 625 }
573 626
574 struct JobToRequestParamsComparator { 627 struct JobToRequestParamsComparator {
575 bool operator()(const JobSet::value_type& job, 628 bool operator()(const JobSet::value_type& job,
576 const RequestParams& value) const { 629 const RequestParams& value) const {
577 return job.first->request_params() < value; 630 return job.first->request_params() < value;
578 } 631 }
579 }; 632 };
580 633
581 Job* AsyncCertNetFetcherImpl::FindJob(const RequestParams& params) { 634 Job* AsyncCertNetFetcherImpl::FindJob(const RequestParams& params) {
(...skipping 26 matching lines...) Expand all
608 661
609 void WaitForResult(Error* error, std::vector<uint8_t>* bytes) override { 662 void WaitForResult(Error* error, std::vector<uint8_t>* bytes) override {
610 // Should only be called a single time. 663 // Should only be called a single time.
611 DCHECK(core_); 664 DCHECK(core_);
612 core_->WaitForResult(error, bytes); 665 core_->WaitForResult(error, bytes);
613 core_ = nullptr; 666 core_ = nullptr;
614 } 667 }
615 668
616 ~CertNetFetcherRequestImpl() override { 669 ~CertNetFetcherRequestImpl() override {
617 if (core_) 670 if (core_)
618 core_->Cancel(); 671 core_->CancelJob();
619 } 672 }
620 673
621 private: 674 private:
622 scoped_refptr<RequestCore> core_; 675 scoped_refptr<RequestCore> core_;
623 }; 676 };
624 677
625 class CertNetFetcherCore
626 : public base::RefCountedThreadSafe<CertNetFetcherCore> {
627 public:
628 explicit CertNetFetcherCore(URLRequestContextGetter* context_getter)
629 : context_getter_(context_getter) {}
630
631 void Abandon() {
632 GetNetworkTaskRunner()->PostTask(
633 FROM_HERE,
634 base::Bind(&CertNetFetcherCore::DoAbandonOnNetworkThread, this));
635 }
636
637 scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() {
638 return context_getter_->GetNetworkTaskRunner();
639 }
640
641 void DoFetchOnNetworkThread(std::unique_ptr<RequestParams> request_params,
642 scoped_refptr<RequestCore> request) {
643 DCHECK(GetNetworkTaskRunner()->RunsTasksOnCurrentThread());
644
645 if (!impl_) {
646 impl_.reset(
647 new AsyncCertNetFetcherImpl(context_getter_->GetURLRequestContext()));
648 }
649
650 // Don't need to retain a reference to |request| because consume is
651 // expected to keep it alive.
652 impl_->Fetch(std::move(request_params), request.get());
653 }
654
655 private:
656 friend class base::RefCountedThreadSafe<CertNetFetcherCore>;
657
658 void DoAbandonOnNetworkThread() {
659 DCHECK(GetNetworkTaskRunner()->RunsTasksOnCurrentThread());
660 impl_.reset();
661 }
662
663 ~CertNetFetcherCore() { DCHECK(!impl_); }
664
665 scoped_refptr<URLRequestContextGetter> context_getter_;
666
667 std::unique_ptr<AsyncCertNetFetcherImpl> impl_;
668
669 DISALLOW_COPY_AND_ASSIGN(CertNetFetcherCore);
670 };
671
672 class CertNetFetcherImpl : public CertNetFetcher { 678 class CertNetFetcherImpl : public CertNetFetcher {
673 public: 679 public:
674 explicit CertNetFetcherImpl(URLRequestContextGetter* context_getter) 680 explicit CertNetFetcherImpl(URLRequestContext* context)
675 : core_(new CertNetFetcherCore(context_getter)) {} 681 : task_runner_(base::ThreadTaskRunnerHandle::Get()), context_(context) {}
676 682
677 ~CertNetFetcherImpl() override { core_->Abandon(); } 683 void Shutdown() override {
684 DCHECK(task_runner_->RunsTasksOnCurrentThread());
685 if (impl_) {
686 impl_->Shutdown();
687 impl_.reset();
688 }
689 context_ = nullptr;
690 }
678 691
679 std::unique_ptr<Request> FetchCaIssuers(const GURL& url, 692 std::unique_ptr<Request> FetchCaIssuers(const GURL& url,
680 int timeout_milliseconds, 693 int timeout_milliseconds,
681 int max_response_bytes) override { 694 int max_response_bytes) override {
682 std::unique_ptr<RequestParams> request_params(new RequestParams); 695 std::unique_ptr<RequestParams> request_params(new RequestParams);
683 696
684 request_params->url = url; 697 request_params->url = url;
685 request_params->http_method = HTTP_METHOD_GET; 698 request_params->http_method = HTTP_METHOD_GET;
686 request_params->timeout = GetTimeout(timeout_milliseconds); 699 request_params->timeout = GetTimeout(timeout_milliseconds);
687 request_params->max_response_bytes = 700 request_params->max_response_bytes =
(...skipping 25 matching lines...) Expand all
713 request_params->url = url; 726 request_params->url = url;
714 request_params->http_method = HTTP_METHOD_GET; 727 request_params->http_method = HTTP_METHOD_GET;
715 request_params->timeout = GetTimeout(timeout_milliseconds); 728 request_params->timeout = GetTimeout(timeout_milliseconds);
716 request_params->max_response_bytes = 729 request_params->max_response_bytes =
717 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); 730 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia);
718 731
719 return DoFetch(std::move(request_params)); 732 return DoFetch(std::move(request_params));
720 } 733 }
721 734
722 private: 735 private:
736 ~CertNetFetcherImpl() override {
737 // The fetcher must be shutdown (at which point |context_| will be set to
738 // null) before destruction.
739 DCHECK(!context_);
740 }
741
742 void DoFetchOnNetworkThread(std::unique_ptr<RequestParams> request_params,
743 scoped_refptr<RequestCore> request) {
744 DCHECK(task_runner_->RunsTasksOnCurrentThread());
745
746 if (!context_) {
747 // The fetcher might have been shutdown between when this task was posted
748 // and when it is running. In this case, signal the request and do not
749 // start a network request.
750 request->SignalImmediateError();
751 return;
752 }
753
754 if (!impl_) {
755 impl_.reset(new AsyncCertNetFetcherImpl(context_));
756 }
757
758 impl_->Fetch(std::move(request_params), request);
759 }
760
723 std::unique_ptr<Request> DoFetch( 761 std::unique_ptr<Request> DoFetch(
724 std::unique_ptr<RequestParams> request_params) { 762 std::unique_ptr<RequestParams> request_params) {
725 auto task_runner = core_->GetNetworkTaskRunner(); 763 scoped_refptr<RequestCore> request_core = new RequestCore(task_runner_);
726 scoped_refptr<RequestCore> request_core = new RequestCore(task_runner);
727 764
728 task_runner->PostTask( 765 // If the fetcher has already been shutdown, DoFetchOnNetworkThread will
729 FROM_HERE, 766 // signal the request with an error. However, if the fetcher shuts down
730 base::Bind(&CertNetFetcherCore::DoFetchOnNetworkThread, core_, 767 // before DoFetchOnNetworkThread runs and PostTask still returns true, then
731 base::Passed(&request_params), request_core)); 768 // the request will hang (that is, WaitForResult will not return).
769 if (!task_runner_->PostTask(
770 FROM_HERE,
771 base::Bind(&CertNetFetcherImpl::DoFetchOnNetworkThread, this,
772 base::Passed(&request_params), request_core))) {
773 request_core->SignalImmediateError();
774 }
732 775
733 return base::MakeUnique<CertNetFetcherRequestImpl>(std::move(request_core)); 776 return base::MakeUnique<CertNetFetcherRequestImpl>(std::move(request_core));
734 } 777 }
735 778
736 private: 779 private:
737 scoped_refptr<CertNetFetcherCore> core_; 780 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
781 // Not owned. |context_| must stay valid until Shutdown() is called.
782 URLRequestContext* context_ = nullptr;
783 std::unique_ptr<AsyncCertNetFetcherImpl> impl_;
738 }; 784 };
739 785
740 } // namespace 786 } // namespace
741 787
742 std::unique_ptr<CertNetFetcher> CreateCertNetFetcher( 788 scoped_refptr<CertNetFetcher> CreateCertNetFetcher(URLRequestContext* context) {
743 URLRequestContextGetter* context_getter) { 789 return make_scoped_refptr(new CertNetFetcherImpl(context));
744 return base::MakeUnique<CertNetFetcherImpl>(context_getter);
745 } 790 }
746 791
747 } // namespace net 792 } // namespace net
OLDNEW
« no previous file with comments | « net/cert_net/cert_net_fetcher_impl.h ('k') | net/cert_net/cert_net_fetcher_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698