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

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: fix AIA tests 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
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.
eroman 2017/01/11 01:56:59 Thanks for fixing
133 // 132 //
134 // Completion of the request will never occur synchronously. In other words it 133 // Completion of the request will never occur synchronously. In other
135 // is guaranteed that |callback| will only be invoked once the Fetch*() method 134 // words it is guaranteed that request->OnJobCompleted() will only be
eroman 2017/01/11 01:56:59 Can you remove the comment about guaranteeing OnJo
estark 2017/01/12 01:06:30 Done.
136 // has returned. 135 // invoked once the Fetch*() method has returned.
137 void Fetch(std::unique_ptr<RequestParams> request_params, 136 void Fetch(std::unique_ptr<RequestParams> request_params,
138 RequestCore* request); 137 scoped_refptr<RequestCore> request);
138
139 // Cancels outstanding jobs.
140 void Shutdown();
139 141
140 private: 142 private:
141 friend class Job; 143 friend class Job;
142 144
143 // Finds a job with a matching RequestPararms or returns nullptr if there was 145 // Finds a job with a matching RequestPararms or returns nullptr if there was
144 // no match. 146 // no match.
145 Job* FindJob(const RequestParams& params); 147 Job* FindJob(const RequestParams& params);
146 148
147 // Removes |job| from the in progress jobs and transfers ownership to the 149 // Removes |job| from the in progress jobs and transfers ownership to the
148 // caller. 150 // caller.
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 job_ = nullptr; 220 job_ = nullptr;
219 221
220 error_ = error; 222 error_ = error;
221 bytes_ = response_body; 223 bytes_ = response_body;
222 completion_event_.Signal(); 224 completion_event_.Signal();
223 } 225 }
224 226
225 // Can be called from any thread. 227 // Can be called from any thread.
226 void Cancel(); 228 void Cancel();
227 229
230 // Signals that an error was encountered before the request was
231 // attached to a job. Should only be called from the caller thread.
232 void SignalImmediateError();
233
228 // Should only be called once. 234 // Should only be called once.
229 void WaitForResult(Error* error, std::vector<uint8_t>* bytes) { 235 void WaitForResult(Error* error, std::vector<uint8_t>* bytes) {
230 DCHECK(!task_runner_->RunsTasksOnCurrentThread()); 236 DCHECK(!task_runner_->RunsTasksOnCurrentThread());
231 237
232 completion_event_.Wait(); 238 completion_event_.Wait();
233 *bytes = std::move(bytes_); 239 *bytes = std::move(bytes_);
234 *error = error_; 240 *error = error_;
235 241
236 error_ = ERR_UNEXPECTED; 242 error_ = ERR_UNEXPECTED;
237 } 243 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 // Job tracks an outstanding URLRequest as well as all of the pending requests 295 // Job tracks an outstanding URLRequest as well as all of the pending requests
290 // for it. 296 // for it.
291 class Job : public URLRequest::Delegate { 297 class Job : public URLRequest::Delegate {
292 public: 298 public:
293 Job(std::unique_ptr<RequestParams> request_params, 299 Job(std::unique_ptr<RequestParams> request_params,
294 AsyncCertNetFetcherImpl* parent); 300 AsyncCertNetFetcherImpl* parent);
295 ~Job() override; 301 ~Job() override;
296 302
297 const RequestParams& request_params() const { return *request_params_; } 303 const RequestParams& request_params() const { return *request_params_; }
298 304
299 // Create a request and attaches it to the job. When the job completes it will 305 // Create a request and attaches it to the job. When the job completes it will
eroman 2017/01/11 01:56:59 side-comment: Could you update Create --> Creates
estark 2017/01/12 01:06:30 Done.
300 // notify the request of completion through OnJobCompleted. Note that the Job 306 // notify the request of completion through OnJobCompleted.
301 // does NOT own the request. 307 void AttachRequest(scoped_refptr<RequestCore> request);
302 void AttachRequest(RequestCore* request);
303 308
304 // Removes |request| from the job. 309 // Removes |request| from the job.
305 void DetachRequest(RequestCore* request); 310 void DetachRequest(RequestCore* request);
306 311
307 // Creates and starts a URLRequest for the job. After the URLRequest has 312 // Creates and starts a URLRequest for the job. After the URLRequest has
308 // completed, OnJobCompleted() will be invoked and all the registered requests 313 // completed, OnJobCompleted() will be invoked and all the registered requests
309 // notified of completion. 314 // notified of completion.
310 void StartURLRequest(URLRequestContext* context); 315 void StartURLRequest(URLRequestContext* context);
311 316
317 // Cancels the request with an ERR_ABORTED error and invokes
318 // OnJobCompleted() to notify the registered requests of the
319 // cancellation. If StartURLRequest() is invoked subsequently, it will
eroman 2017/01/11 01:57:00 See earlier comment. We should be able to call r-
estark 2017/01/12 01:06:30 Addressed the earlier comment, but I don't think I
320 // immediately call OnJobCompleted() with an error.
321 void Cancel();
322
312 private: 323 private:
313 // Implementation of URLRequest::Delegate 324 // Implementation of URLRequest::Delegate
314 void OnReceivedRedirect(URLRequest* request, 325 void OnReceivedRedirect(URLRequest* request,
315 const RedirectInfo& redirect_info, 326 const RedirectInfo& redirect_info,
316 bool* defer_redirect) override; 327 bool* defer_redirect) override;
317 void OnResponseStarted(URLRequest* request, int net_error) override; 328 void OnResponseStarted(URLRequest* request, int net_error) override;
318 void OnReadCompleted(URLRequest* request, int bytes_read) override; 329 void OnReadCompleted(URLRequest* request, int bytes_read) override;
319 330
320 // Clears the URLRequest and timer. Helper for doing work common to 331 // Clears the URLRequest and timer. Helper for doing work common to
321 // cancellation and job completion. 332 // cancellation and job completion.
(...skipping 11 matching lines...) Expand all
333 344
334 // Called when the Job has completed. The job may finish in response to a 345 // 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 346 // timeout, an invalid URL, or the URLRequest completing. By the time this
336 // method is called, the |response_body_| variable have been assigned. 347 // method is called, the |response_body_| variable have been assigned.
337 void OnJobCompleted(Error error); 348 void OnJobCompleted(Error error);
338 349
339 // Cancels a request with a specified error code and calls 350 // Cancels a request with a specified error code and calls
340 // OnUrlRequestCompleted(). 351 // OnUrlRequestCompleted().
341 void FailRequest(Error error); 352 void FailRequest(Error error);
342 353
343 // The requests attached to this job (non-owned). 354 // The requests attached to this job.
344 std::vector<RequestCore*> requests_; 355 std::vector<scoped_refptr<RequestCore>> requests_;
345 356
346 // The input parameters for starting a URLRequest. 357 // The input parameters for starting a URLRequest.
347 std::unique_ptr<RequestParams> request_params_; 358 std::unique_ptr<RequestParams> request_params_;
348 359
349 // The URLRequest response information. 360 // The URLRequest response information.
350 std::vector<uint8_t> response_body_; 361 std::vector<uint8_t> response_body_;
351 362
352 std::unique_ptr<URLRequest> url_request_; 363 std::unique_ptr<URLRequest> url_request_;
353 scoped_refptr<IOBuffer> read_buffer_; 364 scoped_refptr<IOBuffer> read_buffer_;
354 365
355 // Used to timeout the job when the URLRequest takes too long. This timer is 366 // 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. 367 // also used for notifying a failure to start the URLRequest.
357 base::OneShotTimer timer_; 368 base::OneShotTimer timer_;
358 369
359 // Non-owned pointer to the AsyncCertNetFetcherImpl that created this job. 370 // Non-owned pointer to the AsyncCertNetFetcherImpl that created this job.
360 AsyncCertNetFetcherImpl* parent_; 371 AsyncCertNetFetcherImpl* parent_;
361 372
373 // When set, StartURLRequest() will post a task to run
374 // OnJobCompleted() with an error and return immediately.
375 bool cancelled_ = false;
376
362 DISALLOW_COPY_AND_ASSIGN(Job); 377 DISALLOW_COPY_AND_ASSIGN(Job);
363 }; 378 };
364 379
365 void RequestCore::Cancel() { 380 void RequestCore::Cancel() {
366 if (!task_runner_->RunsTasksOnCurrentThread()) { 381 if (!task_runner_->RunsTasksOnCurrentThread()) {
367 task_runner_->PostTask(FROM_HERE, base::Bind(&RequestCore::Cancel, this)); 382 task_runner_->PostTask(FROM_HERE, base::Bind(&RequestCore::Cancel, this));
368 return; 383 return;
369 } 384 }
370 385
371 if (job_) { 386 if (job_) {
372 auto* job = job_; 387 auto* job = job_;
373 job_ = nullptr; 388 job_ = nullptr;
374 job->DetachRequest(this); 389 job->DetachRequest(this);
375 } 390 }
376 391
377 bytes_.clear(); 392 bytes_.clear();
378 error_ = ERR_UNEXPECTED; 393 error_ = ERR_ABORTED;
394 }
395
396 void RequestCore::SignalImmediateError() {
397 DCHECK(!task_runner_->RunsTasksOnCurrentThread());
398 error_ = ERR_ABORTED;
399 completion_event_.Signal();
379 } 400 }
380 401
381 Job::Job(std::unique_ptr<RequestParams> request_params, 402 Job::Job(std::unique_ptr<RequestParams> request_params,
382 AsyncCertNetFetcherImpl* parent) 403 AsyncCertNetFetcherImpl* parent)
383 : request_params_(std::move(request_params)), parent_(parent) {} 404 : request_params_(std::move(request_params)), parent_(parent) {}
384 405
385 Job::~Job() { 406 Job::~Job() {
386 DCHECK(requests_.empty()); 407 DCHECK(requests_.empty());
387 Stop(); 408 Stop();
388 } 409 }
389 410
390 void Job::AttachRequest(RequestCore* request) { 411 void Job::AttachRequest(scoped_refptr<RequestCore> request) {
391 requests_.push_back(request); 412 requests_.push_back(request);
eroman 2017/01/11 01:56:59 std::move()
estark 2017/01/12 01:06:30 Done.
392 request->AttachedToJob(this); 413 request->AttachedToJob(this);
393 } 414 }
394 415
395 void Job::DetachRequest(RequestCore* request) { 416 void Job::DetachRequest(RequestCore* request) {
396 std::unique_ptr<Job> delete_this; 417 std::unique_ptr<Job> delete_this;
397 418
398 auto it = std::find(requests_.begin(), requests_.end(), request); 419 auto it = std::find(requests_.begin(), requests_.end(), request);
399 DCHECK(it != requests_.end()); 420 DCHECK(it != requests_.end());
400 requests_.erase(it); 421 requests_.erase(it);
401 422
402 // If there are no longer any requests attached to the job then 423 // If there are no longer any requests attached to the job then
403 // cancel and delete it. 424 // cancel and delete it.
404 if (requests_.empty()) 425 if (requests_.empty())
405 delete_this = parent_->RemoveJob(this); 426 delete_this = parent_->RemoveJob(this);
406 } 427 }
407 428
408 void Job::StartURLRequest(URLRequestContext* context) { 429 void Job::StartURLRequest(URLRequestContext* context) {
430 if (cancelled_) {
eroman 2017/01/11 01:56:59 I don't think we need this boolean. AsyncCertNetF
estark 2017/01/12 01:06:30 Ah, yes, that's right, thanks. Done.
431 timer_.Start(
432 FROM_HERE, base::TimeDelta(),
433 base::Bind(&Job::OnJobCompleted, base::Unretained(this), ERR_ABORTED));
434 return;
435 }
409 Error error = CanFetchUrl(request_params_->url); 436 Error error = CanFetchUrl(request_params_->url);
410 if (error != OK) { 437 if (error != OK) {
411 // TODO(eroman): Don't post a task for this case. 438 // TODO(eroman): Don't post a task for this case.
eroman 2017/01/11 01:57:00 [optional] While you are here, you could also remo
estark 2017/01/12 01:06:30 Done.
412 timer_.Start( 439 timer_.Start(
413 FROM_HERE, base::TimeDelta(), 440 FROM_HERE, base::TimeDelta(),
414 base::Bind(&Job::OnJobCompleted, base::Unretained(this), error)); 441 base::Bind(&Job::OnJobCompleted, base::Unretained(this), error));
415 return; 442 return;
416 } 443 }
417 444
418 // Start the URLRequest. 445 // Start the URLRequest.
419 read_buffer_ = new IOBuffer(kReadBufferSizeInBytes); 446 read_buffer_ = new IOBuffer(kReadBufferSizeInBytes);
420 url_request_ = 447 url_request_ =
421 context->CreateRequest(request_params_->url, DEFAULT_PRIORITY, this); 448 context->CreateRequest(request_params_->url, DEFAULT_PRIORITY, this);
422 if (request_params_->http_method == HTTP_METHOD_POST) 449 if (request_params_->http_method == HTTP_METHOD_POST)
423 url_request_->set_method("POST"); 450 url_request_->set_method("POST");
424 url_request_->SetLoadFlags(LOAD_DO_NOT_SAVE_COOKIES | 451 url_request_->SetLoadFlags(LOAD_DO_NOT_SAVE_COOKIES |
425 LOAD_DO_NOT_SEND_COOKIES); 452 LOAD_DO_NOT_SEND_COOKIES);
426 url_request_->Start(); 453 url_request_->Start();
427 454
428 // Start a timer to limit how long the job runs for. 455 // Start a timer to limit how long the job runs for.
429 if (request_params_->timeout > base::TimeDelta()) 456 if (request_params_->timeout > base::TimeDelta())
430 timer_.Start( 457 timer_.Start(
431 FROM_HERE, request_params_->timeout, 458 FROM_HERE, request_params_->timeout,
432 base::Bind(&Job::FailRequest, base::Unretained(this), ERR_TIMED_OUT)); 459 base::Bind(&Job::FailRequest, base::Unretained(this), ERR_TIMED_OUT));
433 } 460 }
434 461
462 void Job::Cancel() {
463 cancelled_ = true;
464 FailRequest(ERR_ABORTED);
465 }
466
435 void Job::OnReceivedRedirect(URLRequest* request, 467 void Job::OnReceivedRedirect(URLRequest* request,
436 const RedirectInfo& redirect_info, 468 const RedirectInfo& redirect_info,
437 bool* defer_redirect) { 469 bool* defer_redirect) {
438 DCHECK_EQ(url_request_.get(), request); 470 DCHECK_EQ(url_request_.get(), request);
439 471
440 // Ensure that the new URL matches the policy. 472 // Ensure that the new URL matches the policy.
441 Error error = CanFetchUrl(redirect_info.new_url); 473 Error error = CanFetchUrl(redirect_info.new_url);
442 if (error != OK) { 474 if (error != OK) {
443 FailRequest(error); 475 FailRequest(error);
444 return; 476 return;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 OnJobCompleted(result); 550 OnJobCompleted(result);
519 } 551 }
520 552
521 void Job::OnJobCompleted(Error error) { 553 void Job::OnJobCompleted(Error error) {
522 DCHECK_NE(ERR_IO_PENDING, error); 554 DCHECK_NE(ERR_IO_PENDING, error);
523 // Stop the timer and clear the URLRequest. 555 // Stop the timer and clear the URLRequest.
524 Stop(); 556 Stop();
525 557
526 std::unique_ptr<Job> delete_this = parent_->RemoveJob(this); 558 std::unique_ptr<Job> delete_this = parent_->RemoveJob(this);
527 559
528 for (auto* request : requests_) { 560 for (auto request : requests_) {
eroman 2017/01/11 01:56:59 nit: remove the spurious reference counting during
estark 2017/01/12 01:06:31 Done. (I think -- this is done via const auto&, co
529 request->OnJobCompleted(this, error, response_body_); 561 request->OnJobCompleted(this, error, response_body_);
530 } 562 }
531 563
532 requests_.clear(); 564 requests_.clear();
533 } 565 }
534 566
535 void Job::FailRequest(Error error) { 567 void Job::FailRequest(Error error) {
536 DCHECK_NE(ERR_IO_PENDING, error); 568 DCHECK_NE(ERR_IO_PENDING, error);
537 int result = url_request_->CancelWithError(error); 569 int result = url_request_->CancelWithError(error);
538 OnUrlRequestCompleted(result); 570 OnUrlRequestCompleted(result);
539 } 571 }
540 572
541 AsyncCertNetFetcherImpl::AsyncCertNetFetcherImpl(URLRequestContext* context) 573 AsyncCertNetFetcherImpl::AsyncCertNetFetcherImpl(URLRequestContext* context)
542 : context_(context) { 574 : context_(context) {
543 // Allow creation to happen from another thread. 575 // Allow creation to happen from another thread.
544 thread_checker_.DetachFromThread(); 576 thread_checker_.DetachFromThread();
545 } 577 }
546 578
547 AsyncCertNetFetcherImpl::~AsyncCertNetFetcherImpl() { 579 AsyncCertNetFetcherImpl::~AsyncCertNetFetcherImpl() {
548 DCHECK(thread_checker_.CalledOnValidThread()); 580 DCHECK(thread_checker_.CalledOnValidThread());
549 jobs_.clear(); 581 jobs_.clear();
550 } 582 }
551 583
552 bool JobComparator::operator()(const Job* job1, const Job* job2) const { 584 bool JobComparator::operator()(const Job* job1, const Job* job2) const {
553 return job1->request_params() < job2->request_params(); 585 return job1->request_params() < job2->request_params();
554 } 586 }
555 587
556 void AsyncCertNetFetcherImpl::Fetch( 588 void AsyncCertNetFetcherImpl::Fetch(
557 std::unique_ptr<RequestParams> request_params, 589 std::unique_ptr<RequestParams> request_params,
558 RequestCore* request) { 590 scoped_refptr<RequestCore> request) {
559 DCHECK(thread_checker_.CalledOnValidThread()); 591 DCHECK(thread_checker_.CalledOnValidThread());
560 592
561 // If there is an in-progress job that matches the request parameters use it. 593 // If there is an in-progress job that matches the request parameters use it.
562 // Otherwise start a new job. 594 // Otherwise start a new job.
563 Job* job = FindJob(*request_params); 595 Job* job = FindJob(*request_params);
564 596
565 if (!job) { 597 if (!job) {
566 job = new Job(std::move(request_params), this); 598 job = new Job(std::move(request_params), this);
567 jobs_[job] = base::WrapUnique(job); 599 jobs_[job] = base::WrapUnique(job);
568 job->StartURLRequest(context_); 600 job->StartURLRequest(context_);
569 } 601 }
570 602
571 return job->AttachRequest(request); 603 return job->AttachRequest(request);
572 } 604 }
573 605
606 void AsyncCertNetFetcherImpl::Shutdown() {
607 DCHECK(thread_checker_.CalledOnValidThread());
608 for (JobSet::iterator job = jobs_.begin(); job != jobs_.end();) {
eroman 2017/01/11 01:56:59 Does post-increment work? for (auto it = jobs_.be
estark 2017/01/12 01:06:30 Done.
609 // Jobs get removed when they are cancelled, so increment before
610 // the |job| iterator is erased.
611 JobSet::iterator next = job;
612 ++next;
613 job->first->Cancel();
614 job = next;
615 }
616 }
617
574 struct JobToRequestParamsComparator { 618 struct JobToRequestParamsComparator {
575 bool operator()(const JobSet::value_type& job, 619 bool operator()(const JobSet::value_type& job,
576 const RequestParams& value) const { 620 const RequestParams& value) const {
577 return job.first->request_params() < value; 621 return job.first->request_params() < value;
578 } 622 }
579 }; 623 };
580 624
581 Job* AsyncCertNetFetcherImpl::FindJob(const RequestParams& params) { 625 Job* AsyncCertNetFetcherImpl::FindJob(const RequestParams& params) {
582 DCHECK(thread_checker_.CalledOnValidThread()); 626 DCHECK(thread_checker_.CalledOnValidThread());
583 627
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 659
616 ~CertNetFetcherRequestImpl() override { 660 ~CertNetFetcherRequestImpl() override {
617 if (core_) 661 if (core_)
618 core_->Cancel(); 662 core_->Cancel();
619 } 663 }
620 664
621 private: 665 private:
622 scoped_refptr<RequestCore> core_; 666 scoped_refptr<RequestCore> core_;
623 }; 667 };
624 668
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 { 669 class CertNetFetcherImpl : public CertNetFetcher {
673 public: 670 public:
674 explicit CertNetFetcherImpl(URLRequestContextGetter* context_getter) 671 explicit CertNetFetcherImpl(URLRequestContext* context)
675 : core_(new CertNetFetcherCore(context_getter)) {} 672 : task_runner_(base::ThreadTaskRunnerHandle::Get()), context_(context) {}
676 673
677 ~CertNetFetcherImpl() override { core_->Abandon(); } 674 void Shutdown() override {
675 DCHECK(task_runner_->RunsTasksOnCurrentThread());
676 base::AutoLock auto_lock(shutdown_lock_);
677 shutdown_ = true;
678 if (impl_) {
679 impl_->Shutdown();
680 impl_.reset();
681 }
682 context_ = nullptr;
683 }
678 684
679 std::unique_ptr<Request> FetchCaIssuers(const GURL& url, 685 std::unique_ptr<Request> FetchCaIssuers(const GURL& url,
680 int timeout_milliseconds, 686 int timeout_milliseconds,
681 int max_response_bytes) override { 687 int max_response_bytes) override {
682 std::unique_ptr<RequestParams> request_params(new RequestParams); 688 std::unique_ptr<RequestParams> request_params(new RequestParams);
683 689
684 request_params->url = url; 690 request_params->url = url;
685 request_params->http_method = HTTP_METHOD_GET; 691 request_params->http_method = HTTP_METHOD_GET;
686 request_params->timeout = GetTimeout(timeout_milliseconds); 692 request_params->timeout = GetTimeout(timeout_milliseconds);
687 request_params->max_response_bytes = 693 request_params->max_response_bytes =
(...skipping 25 matching lines...) Expand all
713 request_params->url = url; 719 request_params->url = url;
714 request_params->http_method = HTTP_METHOD_GET; 720 request_params->http_method = HTTP_METHOD_GET;
715 request_params->timeout = GetTimeout(timeout_milliseconds); 721 request_params->timeout = GetTimeout(timeout_milliseconds);
716 request_params->max_response_bytes = 722 request_params->max_response_bytes =
717 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); 723 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia);
718 724
719 return DoFetch(std::move(request_params)); 725 return DoFetch(std::move(request_params));
720 } 726 }
721 727
722 private: 728 private:
729 ~CertNetFetcherImpl() override {}
eroman 2017/01/11 01:56:59 From what I can tell this relies on Shutdown() hav
estark 2017/01/12 01:06:31 Done. (This invalidated one of the tests I had, w
730
731 void DoFetchOnNetworkThread(std::unique_ptr<RequestParams> request_params,
732 scoped_refptr<RequestCore> request) {
733 DCHECK(task_runner_->RunsTasksOnCurrentThread());
734
735 if (!context_) {
736 request->Cancel();
eroman 2017/01/11 01:56:59 I don't think this is right. RequestCore::Cancel(
estark 2017/01/12 01:06:31 Ah, oops, that was indeed supposed to be SignalImm
estark 2017/01/12 01:19:10 Sorry, this comment about the test is out-of-date.
737 return;
738 }
739
740 if (!impl_) {
741 impl_.reset(new AsyncCertNetFetcherImpl(context_));
742 }
743
744 impl_->Fetch(std::move(request_params), request);
745 }
746
723 std::unique_ptr<Request> DoFetch( 747 std::unique_ptr<Request> DoFetch(
724 std::unique_ptr<RequestParams> request_params) { 748 std::unique_ptr<RequestParams> request_params) {
725 auto task_runner = core_->GetNetworkTaskRunner(); 749 scoped_refptr<RequestCore> request_core = new RequestCore(task_runner_);
726 scoped_refptr<RequestCore> request_core = new RequestCore(task_runner);
727 750
728 task_runner->PostTask( 751 base::AutoLock auto_lock(shutdown_lock_);
eroman 2017/01/11 01:56:59 Are you locking here to better handle the case whe
estark 2017/01/12 01:06:30 Yes, I was thinking of that case, because I can't
729 FROM_HERE, 752 if (shutdown_ ||
730 base::Bind(&CertNetFetcherCore::DoFetchOnNetworkThread, core_, 753 !task_runner_->PostTask(
731 base::Passed(&request_params), request_core)); 754 FROM_HERE,
755 base::Bind(&CertNetFetcherImpl::DoFetchOnNetworkThread, this,
756 base::Passed(&request_params), request_core))) {
757 request_core->SignalImmediateError();
758 }
732 759
733 return base::MakeUnique<CertNetFetcherRequestImpl>(std::move(request_core)); 760 return base::MakeUnique<CertNetFetcherRequestImpl>(std::move(request_core));
734 } 761 }
735 762
736 private: 763 private:
737 scoped_refptr<CertNetFetcherCore> core_; 764 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
765 // Not owned. |context_| must stay valid until Shutdown() is called.
766 URLRequestContext* context_ = nullptr;
767 std::unique_ptr<AsyncCertNetFetcherImpl> impl_;
768 base::Lock shutdown_lock_;
769 bool shutdown_ = false;
738 }; 770 };
739 771
740 } // namespace 772 } // namespace
741 773
742 std::unique_ptr<CertNetFetcher> CreateCertNetFetcher( 774 scoped_refptr<CertNetFetcher> CreateCertNetFetcher(URLRequestContext* context) {
743 URLRequestContextGetter* context_getter) { 775 return make_scoped_refptr(new CertNetFetcherImpl(context));
744 return base::MakeUnique<CertNetFetcherImpl>(context_getter);
745 } 776 }
746 777
747 } // namespace net 778 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698