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

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: tweak comments Created 3 years, 12 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. Has constructors that allow it be created on
24 // * Provides a service to start/cancel/wait for URL fetches 27 // either thread, but can only be shutdown from the network thread.
28 // * Provides a service to start/cancel/wait for URL fetches, to be
29 // used on the caller thread.
25 // * Returns callers a CertNetFetcher::Request as a handle 30 // * Returns callers a CertNetFetcher::Request as a handle
26 // * Requests can run in parallel, however will block the current thread when 31 // * Requests can run in parallel, however will block the current thread when
27 // reading results. 32 // reading results.
28 // * Posts tasks to network thread to coordinate actual work 33 // * Posts tasks to network thread to coordinate actual work
29 // 34 //
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 35 // RequestCore
45 // * Reference-counted bridge between CertNetFetcherRequestImpl and the 36 // * Reference-counted bridge between CertNetFetcherRequestImpl and the
46 // dependencies on the network thread 37 // dependencies on the network thread
47 // * Holds the result of the request, a WaitableEvent for signaling 38 // * Holds the result of the request, a WaitableEvent for signaling
48 // completion, and pointers for canceling work on network thread. 39 // completion, and pointers for canceling work on network thread.
49 // 40 //
50 // --------------- 41 // ---------------
42 // Lives on caller thread
43 // ---------------
44 //
45 // CertNetFetcherRequestImpl (implements CertNetFetcher::Request)
46 // * Wrapper for cancelling events, or waiting for a request to complete
47 // * Waits on a WaitableEvent to complete requests.
48 //
49 // ---------------
51 // Lives on network thread 50 // Lives on network thread
52 // --------------- 51 // ---------------
53 // 52 //
54 // AsyncCertNetFetcherImpl 53 // AsyncCertNetFetcherImpl
55 // * Asyncronous manager for outstanding requests. Handles de-duplication, 54 // * Asyncronous manager for outstanding requests. Handles de-duplication,
56 // timeouts, and actual integration with network stack. This is where the 55 // timeouts, and actual integration with network stack. This is where the
57 // majority of the logic lives. 56 // majority of the logic lives.
58 // * Signals completion of requests through RequestCore's WaitableEvent. 57 // * Signals completion of requests through RequestCore's WaitableEvent.
59 // * Attaches requests to Jobs for the purpose of de-duplication 58 // * Attaches requests to Jobs for the purpose of de-duplication
60 59
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 113
115 // AsyncCertNetFetcherImpl manages URLRequests in an async fashion on the 114 // AsyncCertNetFetcherImpl manages URLRequests in an async fashion on the
116 // URLRequestContexts's task runner thread. 115 // URLRequestContexts's task runner thread.
117 // 116 //
118 // * Schedules 117 // * Schedules
119 // * De-duplicates requests 118 // * De-duplicates requests
120 // * Handles timeouts 119 // * Handles timeouts
121 class AsyncCertNetFetcherImpl { 120 class AsyncCertNetFetcherImpl {
122 public: 121 public:
123 // Initializes AsyncCertNetFetcherImpl using the specified URLRequestContext 122 // Initializes AsyncCertNetFetcherImpl using the specified URLRequestContext
124 // for issuing requests. |context| must remain valid for the entire 123 // for issuing requests. |context| must remain valid for the entire
eroman 2017/01/03 20:42:37 This comment is no longer true.
estark 2017/01/05 19:08:39 Done.
125 // lifetime of the AsyncCertNetFetcherImpl. 124 // lifetime of the AsyncCertNetFetcherImpl.
126 explicit AsyncCertNetFetcherImpl(URLRequestContext* context); 125 explicit AsyncCertNetFetcherImpl(URLRequestContext* context);
127 126
128 // Deletion implicitly cancels any outstanding requests. 127 // Deletion implicitly cancels any outstanding requests.
eroman 2017/01/03 20:42:37 This comment isn't quite true anymore either.
estark 2017/01/05 19:08:39 Done.
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 // 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
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 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 // for it. 292 // for it.
291 class Job : public URLRequest::Delegate { 293 class Job : public URLRequest::Delegate {
292 public: 294 public:
293 Job(std::unique_ptr<RequestParams> request_params, 295 Job(std::unique_ptr<RequestParams> request_params,
294 AsyncCertNetFetcherImpl* parent); 296 AsyncCertNetFetcherImpl* parent);
295 ~Job() override; 297 ~Job() override;
296 298
297 const RequestParams& request_params() const { return *request_params_; } 299 const RequestParams& request_params() const { return *request_params_; }
298 300
299 // Create a request and attaches it to the job. When the job completes it will 301 // Create a request and attaches it to the job. When the job completes it will
300 // notify the request of completion through OnJobCompleted. Note that the Job 302 // notify the request of completion through OnJobCompleted.
301 // does NOT own the request. 303 void AttachRequest(scoped_refptr<RequestCore> request);
302 void AttachRequest(RequestCore* request);
303 304
304 // Removes |request| from the job. 305 // Removes |request| from the job.
305 void DetachRequest(RequestCore* request); 306 void DetachRequest(RequestCore* request);
306 307
307 // Creates and starts a URLRequest for the job. After the URLRequest has 308 // Creates and starts a URLRequest for the job. After the URLRequest has
308 // completed, OnJobCompleted() will be invoked and all the registered requests 309 // completed, OnJobCompleted() will be invoked and all the registered requests
309 // notified of completion. 310 // notified of completion.
310 void StartURLRequest(URLRequestContext* context); 311 void StartURLRequest(URLRequestContext* context);
311 312
313 // Cancels the URLRequest. If StartURLRequest() is invoked subsequently,
314 // it will immediately call OnJobCompleted with an error.
315 void Cancel();
316
312 private: 317 private:
313 // Implementation of URLRequest::Delegate 318 // Implementation of URLRequest::Delegate
314 void OnReceivedRedirect(URLRequest* request, 319 void OnReceivedRedirect(URLRequest* request,
315 const RedirectInfo& redirect_info, 320 const RedirectInfo& redirect_info,
316 bool* defer_redirect) override; 321 bool* defer_redirect) override;
317 void OnResponseStarted(URLRequest* request, int net_error) override; 322 void OnResponseStarted(URLRequest* request, int net_error) override;
318 void OnReadCompleted(URLRequest* request, int bytes_read) override; 323 void OnReadCompleted(URLRequest* request, int bytes_read) override;
319 324
320 // Clears the URLRequest and timer. Helper for doing work common to 325 // Clears the URLRequest and timer. Helper for doing work common to
321 // cancellation and job completion. 326 // cancellation and job completion.
(...skipping 11 matching lines...) Expand all
333 338
334 // Called when the Job has completed. The job may finish in response to a 339 // 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 340 // timeout, an invalid URL, or the URLRequest completing. By the time this
336 // method is called, the |response_body_| variable have been assigned. 341 // method is called, the |response_body_| variable have been assigned.
337 void OnJobCompleted(Error error); 342 void OnJobCompleted(Error error);
338 343
339 // Cancels a request with a specified error code and calls 344 // Cancels a request with a specified error code and calls
340 // OnUrlRequestCompleted(). 345 // OnUrlRequestCompleted().
341 void FailRequest(Error error); 346 void FailRequest(Error error);
342 347
343 // The requests attached to this job (non-owned). 348 // The requests attached to this job.
344 std::vector<RequestCore*> requests_; 349 std::vector<scoped_refptr<RequestCore>> requests_;
345 350
346 // The input parameters for starting a URLRequest. 351 // The input parameters for starting a URLRequest.
347 std::unique_ptr<RequestParams> request_params_; 352 std::unique_ptr<RequestParams> request_params_;
348 353
349 // The URLRequest response information. 354 // The URLRequest response information.
350 std::vector<uint8_t> response_body_; 355 std::vector<uint8_t> response_body_;
351 356
352 std::unique_ptr<URLRequest> url_request_; 357 std::unique_ptr<URLRequest> url_request_;
353 scoped_refptr<IOBuffer> read_buffer_; 358 scoped_refptr<IOBuffer> read_buffer_;
354 359
355 // Used to timeout the job when the URLRequest takes too long. This timer is 360 // 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. 361 // also used for notifying a failure to start the URLRequest.
357 base::OneShotTimer timer_; 362 base::OneShotTimer timer_;
358 363
359 // Non-owned pointer to the AsyncCertNetFetcherImpl that created this job. 364 // Non-owned pointer to the AsyncCertNetFetcherImpl that created this job.
360 AsyncCertNetFetcherImpl* parent_; 365 AsyncCertNetFetcherImpl* parent_;
361 366
367 // When set, StartURLRequest() will post a task to run
368 // OnJobCompleted() with an error and return immediately.
369 bool cancelled_ = false;
370
362 DISALLOW_COPY_AND_ASSIGN(Job); 371 DISALLOW_COPY_AND_ASSIGN(Job);
363 }; 372 };
364 373
365 void RequestCore::Cancel() { 374 void RequestCore::Cancel() {
366 if (!task_runner_->RunsTasksOnCurrentThread()) { 375 if (!task_runner_->RunsTasksOnCurrentThread()) {
367 task_runner_->PostTask(FROM_HERE, base::Bind(&RequestCore::Cancel, this)); 376 task_runner_->PostTask(FROM_HERE, base::Bind(&RequestCore::Cancel, this));
368 return; 377 return;
369 } 378 }
370 379
371 if (job_) { 380 if (job_) {
372 auto* job = job_; 381 auto* job = job_;
373 job_ = nullptr; 382 job_ = nullptr;
374 job->DetachRequest(this); 383 job->DetachRequest(this);
375 } 384 }
376 385
377 bytes_.clear(); 386 bytes_.clear();
378 error_ = ERR_UNEXPECTED; 387 error_ = ERR_UNEXPECTED;
379 } 388 }
380 389
381 Job::Job(std::unique_ptr<RequestParams> request_params, 390 Job::Job(std::unique_ptr<RequestParams> request_params,
382 AsyncCertNetFetcherImpl* parent) 391 AsyncCertNetFetcherImpl* parent)
383 : request_params_(std::move(request_params)), parent_(parent) {} 392 : request_params_(std::move(request_params)), parent_(parent) {}
384 393
385 Job::~Job() { 394 Job::~Job() {
386 DCHECK(requests_.empty()); 395 DCHECK(requests_.empty());
eroman 2017/01/03 20:42:37 It looks like Job::Cancel() doesn't clear requests
estark 2017/01/05 19:08:40 Done. Job::Cancel now calls FailRequest which clea
387 Stop(); 396 Stop();
388 } 397 }
389 398
390 void Job::AttachRequest(RequestCore* request) { 399 void Job::AttachRequest(scoped_refptr<RequestCore> request) {
391 requests_.push_back(request); 400 requests_.push_back(request);
392 request->AttachedToJob(this); 401 request->AttachedToJob(this);
393 } 402 }
394 403
395 void Job::DetachRequest(RequestCore* request) { 404 void Job::DetachRequest(RequestCore* request) {
396 std::unique_ptr<Job> delete_this; 405 std::unique_ptr<Job> delete_this;
397 406
398 auto it = std::find(requests_.begin(), requests_.end(), request); 407 auto it = std::find(requests_.begin(), requests_.end(), request);
399 DCHECK(it != requests_.end()); 408 DCHECK(it != requests_.end());
400 requests_.erase(it); 409 requests_.erase(it);
401 410
402 // If there are no longer any requests attached to the job then 411 // If there are no longer any requests attached to the job then
403 // cancel and delete it. 412 // cancel and delete it.
404 if (requests_.empty()) 413 if (requests_.empty())
405 delete_this = parent_->RemoveJob(this); 414 delete_this = parent_->RemoveJob(this);
406 } 415 }
407 416
408 void Job::StartURLRequest(URLRequestContext* context) { 417 void Job::StartURLRequest(URLRequestContext* context) {
418 if (cancelled_) {
419 timer_.Start(
420 FROM_HERE, base::TimeDelta(),
421 base::Bind(&Job::OnJobCompleted, base::Unretained(this), ERR_ABORTED));
422 return;
423 }
409 Error error = CanFetchUrl(request_params_->url); 424 Error error = CanFetchUrl(request_params_->url);
410 if (error != OK) { 425 if (error != OK) {
411 // TODO(eroman): Don't post a task for this case. 426 // TODO(eroman): Don't post a task for this case.
412 timer_.Start( 427 timer_.Start(
413 FROM_HERE, base::TimeDelta(), 428 FROM_HERE, base::TimeDelta(),
414 base::Bind(&Job::OnJobCompleted, base::Unretained(this), error)); 429 base::Bind(&Job::OnJobCompleted, base::Unretained(this), error));
415 return; 430 return;
416 } 431 }
417 432
418 // Start the URLRequest. 433 // Start the URLRequest.
419 read_buffer_ = new IOBuffer(kReadBufferSizeInBytes); 434 read_buffer_ = new IOBuffer(kReadBufferSizeInBytes);
420 url_request_ = 435 url_request_ =
421 context->CreateRequest(request_params_->url, DEFAULT_PRIORITY, this); 436 context->CreateRequest(request_params_->url, DEFAULT_PRIORITY, this);
422 if (request_params_->http_method == HTTP_METHOD_POST) 437 if (request_params_->http_method == HTTP_METHOD_POST)
423 url_request_->set_method("POST"); 438 url_request_->set_method("POST");
424 url_request_->SetLoadFlags(LOAD_DO_NOT_SAVE_COOKIES | 439 url_request_->SetLoadFlags(LOAD_DO_NOT_SAVE_COOKIES |
425 LOAD_DO_NOT_SEND_COOKIES); 440 LOAD_DO_NOT_SEND_COOKIES);
426 url_request_->Start(); 441 url_request_->Start();
427 442
428 // Start a timer to limit how long the job runs for. 443 // Start a timer to limit how long the job runs for.
429 if (request_params_->timeout > base::TimeDelta()) 444 if (request_params_->timeout > base::TimeDelta())
430 timer_.Start( 445 timer_.Start(
431 FROM_HERE, request_params_->timeout, 446 FROM_HERE, request_params_->timeout,
432 base::Bind(&Job::FailRequest, base::Unretained(this), ERR_TIMED_OUT)); 447 base::Bind(&Job::FailRequest, base::Unretained(this), ERR_TIMED_OUT));
433 } 448 }
434 449
450 void Job::Cancel() {
451 cancelled_ = true;
452 if (url_request_)
453 url_request_->Cancel();
454 }
455
435 void Job::OnReceivedRedirect(URLRequest* request, 456 void Job::OnReceivedRedirect(URLRequest* request,
436 const RedirectInfo& redirect_info, 457 const RedirectInfo& redirect_info,
437 bool* defer_redirect) { 458 bool* defer_redirect) {
438 DCHECK_EQ(url_request_.get(), request); 459 DCHECK_EQ(url_request_.get(), request);
439 460
440 // Ensure that the new URL matches the policy. 461 // Ensure that the new URL matches the policy.
441 Error error = CanFetchUrl(redirect_info.new_url); 462 Error error = CanFetchUrl(redirect_info.new_url);
442 if (error != OK) { 463 if (error != OK) {
443 FailRequest(error); 464 FailRequest(error);
444 return; 465 return;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 OnJobCompleted(result); 539 OnJobCompleted(result);
519 } 540 }
520 541
521 void Job::OnJobCompleted(Error error) { 542 void Job::OnJobCompleted(Error error) {
522 DCHECK_NE(ERR_IO_PENDING, error); 543 DCHECK_NE(ERR_IO_PENDING, error);
523 // Stop the timer and clear the URLRequest. 544 // Stop the timer and clear the URLRequest.
524 Stop(); 545 Stop();
525 546
526 std::unique_ptr<Job> delete_this = parent_->RemoveJob(this); 547 std::unique_ptr<Job> delete_this = parent_->RemoveJob(this);
527 548
528 for (auto* request : requests_) { 549 for (auto request : requests_) {
529 request->OnJobCompleted(this, error, response_body_); 550 request->OnJobCompleted(this, error, response_body_);
530 } 551 }
531 552
532 requests_.clear(); 553 requests_.clear();
533 } 554 }
534 555
535 void Job::FailRequest(Error error) { 556 void Job::FailRequest(Error error) {
536 DCHECK_NE(ERR_IO_PENDING, error); 557 DCHECK_NE(ERR_IO_PENDING, error);
537 int result = url_request_->CancelWithError(error); 558 int result = url_request_->CancelWithError(error);
538 OnUrlRequestCompleted(result); 559 OnUrlRequestCompleted(result);
539 } 560 }
540 561
541 AsyncCertNetFetcherImpl::AsyncCertNetFetcherImpl(URLRequestContext* context) 562 AsyncCertNetFetcherImpl::AsyncCertNetFetcherImpl(URLRequestContext* context)
542 : context_(context) { 563 : context_(context) {
543 // Allow creation to happen from another thread. 564 // Allow creation to happen from another thread.
544 thread_checker_.DetachFromThread(); 565 thread_checker_.DetachFromThread();
545 } 566 }
546 567
547 AsyncCertNetFetcherImpl::~AsyncCertNetFetcherImpl() { 568 AsyncCertNetFetcherImpl::~AsyncCertNetFetcherImpl() {
548 DCHECK(thread_checker_.CalledOnValidThread()); 569 DCHECK(thread_checker_.CalledOnValidThread());
549 jobs_.clear(); 570 jobs_.clear();
550 } 571 }
551 572
552 bool JobComparator::operator()(const Job* job1, const Job* job2) const { 573 bool JobComparator::operator()(const Job* job1, const Job* job2) const {
553 return job1->request_params() < job2->request_params(); 574 return job1->request_params() < job2->request_params();
554 } 575 }
555 576
556 void AsyncCertNetFetcherImpl::Fetch( 577 void AsyncCertNetFetcherImpl::Fetch(
557 std::unique_ptr<RequestParams> request_params, 578 std::unique_ptr<RequestParams> request_params,
558 RequestCore* request) { 579 scoped_refptr<RequestCore> request) {
559 DCHECK(thread_checker_.CalledOnValidThread()); 580 DCHECK(thread_checker_.CalledOnValidThread());
560 581
561 // If there is an in-progress job that matches the request parameters use it. 582 // If there is an in-progress job that matches the request parameters use it.
562 // Otherwise start a new job. 583 // Otherwise start a new job.
563 Job* job = FindJob(*request_params); 584 Job* job = FindJob(*request_params);
564 585
565 if (!job) { 586 if (!job) {
566 job = new Job(std::move(request_params), this); 587 job = new Job(std::move(request_params), this);
567 jobs_[job] = base::WrapUnique(job); 588 jobs_[job] = base::WrapUnique(job);
568 job->StartURLRequest(context_); 589 job->StartURLRequest(context_);
569 } 590 }
570 591
571 return job->AttachRequest(request); 592 return job->AttachRequest(request);
572 } 593 }
573 594
595 void AsyncCertNetFetcherImpl::Shutdown() {
596 DCHECK(thread_checker_.CalledOnValidThread());
597 for (const auto& job : jobs_) {
598 job.first->Cancel();
599 }
600 }
601
574 struct JobToRequestParamsComparator { 602 struct JobToRequestParamsComparator {
575 bool operator()(const JobSet::value_type& job, 603 bool operator()(const JobSet::value_type& job,
576 const RequestParams& value) const { 604 const RequestParams& value) const {
577 return job.first->request_params() < value; 605 return job.first->request_params() < value;
578 } 606 }
579 }; 607 };
580 608
581 Job* AsyncCertNetFetcherImpl::FindJob(const RequestParams& params) { 609 Job* AsyncCertNetFetcherImpl::FindJob(const RequestParams& params) {
582 DCHECK(thread_checker_.CalledOnValidThread()); 610 DCHECK(thread_checker_.CalledOnValidThread());
583 611
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 643
616 ~CertNetFetcherRequestImpl() override { 644 ~CertNetFetcherRequestImpl() override {
617 if (core_) 645 if (core_)
618 core_->Cancel(); 646 core_->Cancel();
619 } 647 }
620 648
621 private: 649 private:
622 scoped_refptr<RequestCore> core_; 650 scoped_refptr<RequestCore> core_;
623 }; 651 };
624 652
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 { 653 class CertNetFetcherImpl : public CertNetFetcher {
673 public: 654 public:
674 explicit CertNetFetcherImpl(URLRequestContextGetter* context_getter) 655 CertNetFetcherImpl(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
675 : core_(new CertNetFetcherCore(context_getter)) {} 656 URLRequestContext* context)
657 : task_runner_(task_runner), context_(context) {}
676 658
677 ~CertNetFetcherImpl() override { core_->Abandon(); } 659 explicit CertNetFetcherImpl(URLRequestContextGetter* context_getter) {
660 context_getter->GetNetworkTaskRunner()->PostTask(
eroman 2017/01/03 20:42:37 There is a possible race with: (1) Create (on
estark 2017/01/05 19:08:40 Done.
661 FROM_HERE, base::Bind(&CertNetFetcherImpl::InitializeOnNetworkThread,
662 this, context_getter));
663 }
664
665 void Shutdown() override {
666 DCHECK(task_runner_->RunsTasksOnCurrentThread());
667 base::AutoLock auto_lock(shutdown_lock_);
668 shutdown_ = true;
669 if (impl_) {
670 impl_->Shutdown();
671 }
672 context_ = nullptr;
673 }
678 674
679 std::unique_ptr<Request> FetchCaIssuers(const GURL& url, 675 std::unique_ptr<Request> FetchCaIssuers(const GURL& url,
680 int timeout_milliseconds, 676 int timeout_milliseconds,
681 int max_response_bytes) override { 677 int max_response_bytes) override {
682 std::unique_ptr<RequestParams> request_params(new RequestParams); 678 std::unique_ptr<RequestParams> request_params(new RequestParams);
683 679
684 request_params->url = url; 680 request_params->url = url;
685 request_params->http_method = HTTP_METHOD_GET; 681 request_params->http_method = HTTP_METHOD_GET;
686 request_params->timeout = GetTimeout(timeout_milliseconds); 682 request_params->timeout = GetTimeout(timeout_milliseconds);
687 request_params->max_response_bytes = 683 request_params->max_response_bytes =
(...skipping 25 matching lines...) Expand all
713 request_params->url = url; 709 request_params->url = url;
714 request_params->http_method = HTTP_METHOD_GET; 710 request_params->http_method = HTTP_METHOD_GET;
715 request_params->timeout = GetTimeout(timeout_milliseconds); 711 request_params->timeout = GetTimeout(timeout_milliseconds);
716 request_params->max_response_bytes = 712 request_params->max_response_bytes =
717 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); 713 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia);
718 714
719 return DoFetch(std::move(request_params)); 715 return DoFetch(std::move(request_params));
720 } 716 }
721 717
722 private: 718 private:
719 ~CertNetFetcherImpl() override {}
720
721 void InitializeOnNetworkThread(URLRequestContextGetter* context_getter) {
722 DCHECK(context_getter->GetNetworkTaskRunner()->RunsTasksOnCurrentThread());
723 task_runner_ = context_getter->GetNetworkTaskRunner();
724 context_ = context_getter->GetURLRequestContext();
725 }
726
727 void DoFetchOnNetworkThread(std::unique_ptr<RequestParams> request_params,
728 scoped_refptr<RequestCore> request) {
729 DCHECK(task_runner_->RunsTasksOnCurrentThread());
730
731 if (!context_) {
732 request->Cancel();
733 return;
734 }
735
736 if (!impl_) {
737 impl_.reset(new AsyncCertNetFetcherImpl(context_));
738 }
739
740 impl_->Fetch(std::move(request_params), request);
741 }
742
723 std::unique_ptr<Request> DoFetch( 743 std::unique_ptr<Request> DoFetch(
724 std::unique_ptr<RequestParams> request_params) { 744 std::unique_ptr<RequestParams> request_params) {
725 auto task_runner = core_->GetNetworkTaskRunner(); 745 scoped_refptr<RequestCore> request_core = new RequestCore(task_runner_);
726 scoped_refptr<RequestCore> request_core = new RequestCore(task_runner);
727 746
728 task_runner->PostTask( 747 base::AutoLock auto_lock(shutdown_lock_);
729 FROM_HERE, 748 if (shutdown_)
730 base::Bind(&CertNetFetcherCore::DoFetchOnNetworkThread, core_, 749 return nullptr;
731 base::Passed(&request_params), request_core)); 750
751 if (!task_runner_->PostTask(
752 FROM_HERE,
753 base::Bind(&CertNetFetcherImpl::DoFetchOnNetworkThread, this,
754 base::Passed(&request_params), request_core))) {
755 return nullptr;
756 }
732 757
733 return base::MakeUnique<CertNetFetcherRequestImpl>(std::move(request_core)); 758 return base::MakeUnique<CertNetFetcherRequestImpl>(std::move(request_core));
734 } 759 }
735 760
736 private: 761 private:
737 scoped_refptr<CertNetFetcherCore> core_; 762 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
763 // Not owned. |context_| must stay valid until Shutdown() is called.
764 URLRequestContext* context_ = nullptr;
765 std::unique_ptr<AsyncCertNetFetcherImpl> impl_;
766 base::Lock shutdown_lock_;
767 bool shutdown_ = false;
738 }; 768 };
739 769
740 } // namespace 770 } // namespace
741 771
742 std::unique_ptr<CertNetFetcher> CreateCertNetFetcher( 772 scoped_refptr<CertNetFetcher> CreateCertNetFetcher(
773 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
774 URLRequestContext* context) {
775 return make_scoped_refptr(new CertNetFetcherImpl(task_runner, context));
776 }
777
778 scoped_refptr<CertNetFetcher> CreateCertNetFetcherOnCallerThread(
743 URLRequestContextGetter* context_getter) { 779 URLRequestContextGetter* context_getter) {
744 return base::MakeUnique<CertNetFetcherImpl>(context_getter); 780 return make_scoped_refptr(new CertNetFetcherImpl(context_getter));
745 } 781 }
746 782
747 } // namespace net 783 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698