Chromium Code Reviews| Index: net/cert_net/cert_net_fetcher_impl.cc |
| diff --git a/net/cert_net/cert_net_fetcher_impl.cc b/net/cert_net/cert_net_fetcher_impl.cc |
| index 01fca4f796aa13d957a24df549f631151eec630e..1566fc772ab5eaf8f6213e4e54bbb16137b2e7ac 100644 |
| --- a/net/cert_net/cert_net_fetcher_impl.cc |
| +++ b/net/cert_net/cert_net_fetcher_impl.cc |
| @@ -8,15 +8,17 @@ |
| #include <utility> |
| #include "base/callback_helpers.h" |
| -#include "base/containers/linked_list.h" |
| #include "base/logging.h" |
| #include "base/macros.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/numerics/safe_math.h" |
| +#include "base/synchronization/waitable_event.h" |
| #include "base/timer/timer.h" |
| #include "net/base/load_flags.h" |
| +#include "net/cert/cert_net_fetcher.h" |
| #include "net/url_request/redirect_info.h" |
| #include "net/url_request/url_request_context.h" |
| +#include "net/url_request/url_request_context_getter.h" |
| // TODO(eroman): Add support for POST parameters. |
| // TODO(eroman): Add controls for bypassing the cache. |
| @@ -40,6 +42,65 @@ const int kMaxResponseSizeInBytesForAia = 64 * 1024; |
| // The default timeout in seconds for fetch requests. |
| const int kTimeoutSeconds = 15; |
| +class RequestCore; |
| +struct RequestParams; |
| +class Job; |
| + |
| +struct JobToRequestParamsComparator; |
| + |
| +struct JobComparator { |
| + bool operator()(const Job* job1, const Job* job2) const; |
| +}; |
| + |
| +// Would be a set<unique_ptr> but extraction of owned objects from a set of |
| +// owned types doesn't come until C++17. |
| +using JobSet = std::map<Job*, std::unique_ptr<Job>, JobComparator>; |
| + |
| +// AsyncCertNetFetcherImpl manages URLRequests (schedules, de-duplicates, |
| +// timeouts) in an async fashion on the network thread. |
| +class NET_EXPORT AsyncCertNetFetcherImpl { |
|
mattm
2016/10/28 02:11:56
NET_EXPORT of anonymous class?
eroman
2016/11/23 22:10:21
Done.
|
| + public: |
| + // Initializes AsyncCertNetFetcherImpl using the specified URLRequestContext |
| + // for issuing requests. |context| must remain valid for the entire |
| + // lifetime of the AsyncCertNetFetcherImpl. |
| + explicit AsyncCertNetFetcherImpl(URLRequestContext* context); |
| + |
| + // Deletion implicitly cancels any outstanding requests. |
| + ~AsyncCertNetFetcherImpl(); |
| + |
| + // Starts an asynchronous request to fetch the given URL. On completion |
| + // |callback| will be invoked. |
| + // |
| + // Completion of the request will never occur synchronously. In other words it |
| + // is guaranteed that |callback| will only be invoked once the Fetch*() method |
| + // has returned. |
| + void Fetch(std::unique_ptr<RequestParams> request_params, |
| + RequestCore* request); |
| + |
| + private: |
| + friend class Job; |
| + |
| + // Finds a job with a matching RequestPararms or returns nullptr if there was |
| + // no match. |
| + Job* FindJob(const RequestParams& params); |
| + |
| + // Removes |job| from the in progress jobs and transfers ownership to the |
| + // caller. |
| + std::unique_ptr<Job> RemoveJob(Job* job); |
| + |
| + // The in-progress jobs. This set does not contain the job which is actively |
| + // invoking callbacks (OnJobCompleted). Instead that is tracked by |
| + // |currently_completing_job_|. |
|
mattm
2016/10/28 02:11:56
currently_completing_job_ doesn't exist anymore
|
| + JobSet jobs_; |
| + |
| + // Not owned. AsyncCertNetFetcherImpl must outlive the URLRequestContext. |
|
mattm
2016/10/28 02:11:55
backwards?
eroman
2016/11/23 22:10:21
Done.
|
| + URLRequestContext* context_ = nullptr; |
| + |
| + base::ThreadChecker thread_checker_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(AsyncCertNetFetcherImpl); |
| +}; |
| + |
| // Policy for which URLs are allowed to be fetched. This is called both for the |
| // initial URL and for each redirect. Returns OK on success or a net error |
| // code on failure. |
| @@ -74,46 +135,72 @@ enum HttpMethod { |
| HTTP_METHOD_POST, |
| }; |
| -} // namespace |
| - |
| -// CertNetFetcherImpl::RequestImpl tracks an outstanding call to Fetch(). |
| -class CertNetFetcherImpl::RequestImpl : public CertNetFetcher::Request, |
| - public base::LinkNode<RequestImpl> { |
| +// RequestCore tracks an outstanding call to Fetch(). It is |
| +// reference-counted for ease of sharing between threads. |
| +class RequestCore : public base::RefCountedThreadSafe<RequestCore> { |
| public: |
| - RequestImpl(Job* job, const FetchCallback& callback) |
| - : callback_(callback), job_(job) { |
| - DCHECK(!callback.is_null()); |
| - } |
| - |
| - // Deletion cancels the outstanding request. |
| - ~RequestImpl() override; |
| - |
| - void OnJobCancelled(Job* job) { |
| - DCHECK_EQ(job_, job); |
| - job_ = nullptr; |
| - callback_.Reset(); |
| + explicit RequestCore(scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
| + : completion_event_(base::WaitableEvent::ResetPolicy::MANUAL, |
| + base::WaitableEvent::InitialState::NOT_SIGNALED), |
| + task_runner_(std::move(task_runner)) {} |
| + |
| + void AttachedToJob(Job* job) { |
| + DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| + DCHECK(!job_); |
| + job_ = job; |
| } |
| void OnJobCompleted(Job* job, |
| Error error, |
| const std::vector<uint8_t>& response_body) { |
| + DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| + |
| DCHECK_EQ(job_, job); |
| job_ = nullptr; |
| - base::ResetAndReturn(&callback_).Run(error, response_body); |
| + |
| + error_ = error; |
| + bytes_ = response_body; |
| + completion_event_.Signal(); |
| + } |
| + |
| + // Can be called from any thread. |
| + void Cancel(); |
| + |
| + // Should only be called once. |
| + void WaitForResult(Error* error, std::vector<uint8_t>* bytes) { |
| + DCHECK(!task_runner_->RunsTasksOnCurrentThread()); |
| + |
| + completion_event_.Wait(); |
| + *bytes = std::move(bytes_); |
| + *error = error_; |
| + |
| + error_ = ERR_UNEXPECTED; |
| } |
| private: |
| - // The callback to invoke when the request has completed. |
| - FetchCallback callback_; |
| + friend class base::RefCountedThreadSafe<RequestCore>; |
| + |
| + ~RequestCore() { |
| + // Requests should have been cancelled prior to destruction. |
| + DCHECK(!job_); |
| + } |
| // A non-owned pointer to the job that is executing the request. |
| - Job* job_; |
| + Job* job_ = nullptr; |
| - private: |
| - DISALLOW_COPY_AND_ASSIGN(RequestImpl); |
| + // May be written to from network thread. |
| + Error error_; |
| + std::vector<uint8_t> bytes_; |
| + |
| + // Indicates when |error_| and |bytes_| have been written to. |
| + base::WaitableEvent completion_event_; |
| + |
| + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(RequestCore); |
| }; |
| -struct CertNetFetcherImpl::RequestParams { |
| +struct RequestParams { |
| RequestParams(); |
| bool operator<(const RequestParams& other) const; |
| @@ -131,48 +218,39 @@ struct CertNetFetcherImpl::RequestParams { |
| DISALLOW_COPY_AND_ASSIGN(RequestParams); |
| }; |
| -CertNetFetcherImpl::RequestParams::RequestParams() |
| - : http_method(HTTP_METHOD_GET), max_response_bytes(0) { |
| -} |
| +RequestParams::RequestParams() |
| + : http_method(HTTP_METHOD_GET), max_response_bytes(0) {} |
| -bool CertNetFetcherImpl::RequestParams::operator<( |
| - const RequestParams& other) const { |
| +bool RequestParams::operator<(const RequestParams& other) const { |
| return std::tie(url, http_method, max_response_bytes, timeout) < |
| std::tie(other.url, other.http_method, other.max_response_bytes, |
| other.timeout); |
| } |
| -// CertNetFetcherImpl::Job tracks an outstanding URLRequest as well as all of |
| -// the pending requests for it. |
| -class CertNetFetcherImpl::Job : public URLRequest::Delegate { |
| +// Job tracks an outstanding URLRequest as well as all of the pending requests |
| +// for it. |
| +class Job : public URLRequest::Delegate { |
| public: |
| Job(std::unique_ptr<RequestParams> request_params, |
| - CertNetFetcherImpl* parent); |
| + AsyncCertNetFetcherImpl* parent); |
| ~Job() override; |
| - // Cancels the job and all requests attached to it. No callbacks will be |
| - // invoked following cancellation. |
| - void Cancel(); |
| - |
| const RequestParams& request_params() const { return *request_params_; } |
| // Create a request and attaches it to the job. When the job completes it will |
| // notify the request of completion through OnJobCompleted. Note that the Job |
| // does NOT own the request. |
| - std::unique_ptr<Request> CreateRequest(const FetchCallback& callback); |
| + void AttachRequest(RequestCore* request); |
| // Removes |request| from the job. |
| - void DetachRequest(RequestImpl* request); |
| + void DetachRequest(RequestCore* request); |
| - // Creates and starts a URLRequest for the job. After the request has |
| + // Creates and starts a URLRequest for the job. After the URLRequest has |
| // completed, OnJobCompleted() will be invoked and all the registered requests |
| // notified of completion. |
| void StartURLRequest(URLRequestContext* context); |
| private: |
| - // The pointers in RequestList are not owned by the Job. |
| - using RequestList = base::LinkedList<RequestImpl>; |
| - |
| // Implementation of URLRequest::Delegate |
| void OnReceivedRedirect(URLRequest* request, |
| const RedirectInfo& redirect_info, |
| @@ -203,8 +281,8 @@ class CertNetFetcherImpl::Job : public URLRequest::Delegate { |
| // OnUrlRequestCompleted(). |
| void FailRequest(Error error); |
| - // The requests attached to this job. |
| - RequestList requests_; |
| + // The requests attached to this job (non-owned). |
| + std::vector<RequestCore*> requests_; |
| // The input parameters for starting a URLRequest. |
| std::unique_ptr<RequestParams> request_params_; |
| @@ -219,66 +297,59 @@ class CertNetFetcherImpl::Job : public URLRequest::Delegate { |
| // also used for notifying a failure to start the URLRequest. |
| base::OneShotTimer timer_; |
| - // Non-owned pointer to the CertNetFetcherImpl that created this job. |
| - CertNetFetcherImpl* parent_; |
| + // Non-owned pointer to the AsyncCertNetFetcherImpl that created this job. |
| + AsyncCertNetFetcherImpl* parent_; |
| DISALLOW_COPY_AND_ASSIGN(Job); |
| }; |
| -CertNetFetcherImpl::RequestImpl::~RequestImpl() { |
| - if (job_) |
| - job_->DetachRequest(this); |
| -} |
| +void RequestCore::Cancel() { |
|
mattm
2016/10/28 02:11:56
Should be up with RequestCore definition? does it
eroman
2016/11/23 22:10:21
There is a circular dependency between Job and Req
|
| + if (!task_runner_->RunsTasksOnCurrentThread()) { |
| + task_runner_->PostTask(FROM_HERE, base::Bind(&RequestCore::Cancel, this)); |
| + return; |
| + } |
| -CertNetFetcherImpl::Job::Job(std::unique_ptr<RequestParams> request_params, |
| - CertNetFetcherImpl* parent) |
| - : request_params_(std::move(request_params)), |
| - parent_(parent) {} |
| + if (job_) { |
| + auto* job = job_; |
| + job_ = nullptr; |
| + job->DetachRequest(this); |
| + } |
| -CertNetFetcherImpl::Job::~Job() { |
| - Cancel(); |
| + bytes_.clear(); |
| + error_ = ERR_UNEXPECTED; |
| } |
| -void CertNetFetcherImpl::Job::Cancel() { |
| - parent_ = nullptr; |
| - |
| - // Notify each request of cancellation and remove it from the list. |
| - for (base::LinkNode<RequestImpl>* current = requests_.head(); |
| - current != requests_.end();) { |
| - base::LinkNode<RequestImpl>* next = current->next(); |
| - current->value()->OnJobCancelled(this); |
| - current->RemoveFromList(); |
| - current = next; |
| - } |
| +Job::Job(std::unique_ptr<RequestParams> request_params, |
| + AsyncCertNetFetcherImpl* parent) |
| + : request_params_(std::move(request_params)), parent_(parent) {} |
| +Job::~Job() { |
| DCHECK(requests_.empty()); |
| - |
| Stop(); |
| } |
| -std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::Job::CreateRequest( |
| - const FetchCallback& callback) { |
| - std::unique_ptr<RequestImpl> request(new RequestImpl(this, callback)); |
| - requests_.Append(request.get()); |
| - return std::move(request); |
| +void Job::AttachRequest(RequestCore* request) { |
| + requests_.push_back(request); |
| + request->AttachedToJob(this); |
| } |
| -void CertNetFetcherImpl::Job::DetachRequest(RequestImpl* request) { |
| +void Job::DetachRequest(RequestCore* request) { |
| std::unique_ptr<Job> delete_this; |
| - request->RemoveFromList(); |
| + auto it = std::find(requests_.begin(), requests_.end(), request); |
| + DCHECK(it != requests_.end()); |
| + requests_.erase(it); |
| // If there are no longer any requests attached to the job then |
| // cancel and delete it. |
| - if (requests_.empty() && !parent_->IsCurrentlyCompletingJob(this)) |
| + if (requests_.empty()) |
| delete_this = parent_->RemoveJob(this); |
| } |
| -void CertNetFetcherImpl::Job::StartURLRequest(URLRequestContext* context) { |
| +void Job::StartURLRequest(URLRequestContext* context) { |
| Error error = CanFetchUrl(request_params_->url); |
| if (error != OK) { |
| - // The CertNetFetcher's API contract is that requests always complete |
| - // asynchronously. Use the timer class so the task is easily cancelled. |
| + // TODO(eroman): Don't post a task for this case. |
| timer_.Start( |
| FROM_HERE, base::TimeDelta(), |
| base::Bind(&Job::OnJobCompleted, base::Unretained(this), error)); |
| @@ -302,10 +373,9 @@ void CertNetFetcherImpl::Job::StartURLRequest(URLRequestContext* context) { |
| base::Bind(&Job::FailRequest, base::Unretained(this), ERR_TIMED_OUT)); |
| } |
| -void CertNetFetcherImpl::Job::OnReceivedRedirect( |
| - URLRequest* request, |
| - const RedirectInfo& redirect_info, |
| - bool* defer_redirect) { |
| +void Job::OnReceivedRedirect(URLRequest* request, |
| + const RedirectInfo& redirect_info, |
| + bool* defer_redirect) { |
| DCHECK_EQ(url_request_.get(), request); |
| // Ensure that the new URL matches the policy. |
| @@ -316,8 +386,7 @@ void CertNetFetcherImpl::Job::OnReceivedRedirect( |
| } |
| } |
| -void CertNetFetcherImpl::Job::OnResponseStarted(URLRequest* request, |
| - int net_error) { |
| +void Job::OnResponseStarted(URLRequest* request, int net_error) { |
| DCHECK_EQ(url_request_.get(), request); |
| DCHECK_NE(ERR_IO_PENDING, net_error); |
| @@ -335,8 +404,7 @@ void CertNetFetcherImpl::Job::OnResponseStarted(URLRequest* request, |
| ReadBody(request); |
| } |
| -void CertNetFetcherImpl::Job::OnReadCompleted(URLRequest* request, |
| - int bytes_read) { |
| +void Job::OnReadCompleted(URLRequest* request, int bytes_read) { |
| DCHECK_EQ(url_request_.get(), request); |
| DCHECK_NE(ERR_IO_PENDING, bytes_read); |
| @@ -345,12 +413,12 @@ void CertNetFetcherImpl::Job::OnReadCompleted(URLRequest* request, |
| ReadBody(request); |
| } |
| -void CertNetFetcherImpl::Job::Stop() { |
| +void Job::Stop() { |
| timer_.Stop(); |
| url_request_.reset(); |
| } |
| -void CertNetFetcherImpl::Job::ReadBody(URLRequest* request) { |
| +void Job::ReadBody(URLRequest* request) { |
| // Read as many bytes as are available synchronously. |
| int num_bytes = 0; |
| while (num_bytes >= 0) { |
| @@ -364,8 +432,7 @@ void CertNetFetcherImpl::Job::ReadBody(URLRequest* request) { |
| OnUrlRequestCompleted(num_bytes); |
| } |
| -bool CertNetFetcherImpl::Job::ConsumeBytesRead(URLRequest* request, |
| - int num_bytes) { |
| +bool Job::ConsumeBytesRead(URLRequest* request, int num_bytes) { |
| DCHECK_NE(ERR_IO_PENDING, num_bytes); |
| if (num_bytes <= 0) { |
| // Error while reading, or EOF. |
| @@ -386,111 +453,50 @@ bool CertNetFetcherImpl::Job::ConsumeBytesRead(URLRequest* request, |
| return true; |
| } |
| -void CertNetFetcherImpl::Job::OnUrlRequestCompleted(int net_error) { |
| +void Job::OnUrlRequestCompleted(int net_error) { |
| DCHECK_NE(ERR_IO_PENDING, net_error); |
| Error result = static_cast<Error>(net_error); |
| OnJobCompleted(result); |
| } |
| -void CertNetFetcherImpl::Job::OnJobCompleted(Error error) { |
| +void Job::OnJobCompleted(Error error) { |
| DCHECK_NE(ERR_IO_PENDING, error); |
| // Stop the timer and clear the URLRequest. |
| Stop(); |
| - // Invoking the callbacks is subtle as state may be mutated while iterating |
| - // through the callbacks: |
| - // |
| - // * The parent CertNetFetcherImpl may be deleted |
| - // * Requests in this job may be cancelled |
| - |
| std::unique_ptr<Job> delete_this = parent_->RemoveJob(this); |
| - parent_->SetCurrentlyCompletingJob(this); |
| - while (!requests_.empty()) { |
| - base::LinkNode<RequestImpl>* request = requests_.head(); |
| - request->RemoveFromList(); |
| - request->value()->OnJobCompleted(this, error, response_body_); |
| + for (auto* request : requests_) { |
| + request->OnJobCompleted(this, error, response_body_); |
| } |
| - if (parent_) |
| - parent_->ClearCurrentlyCompletingJob(this); |
| + requests_.clear(); |
| } |
| -void CertNetFetcherImpl::Job::FailRequest(Error error) { |
| +void Job::FailRequest(Error error) { |
| DCHECK_NE(ERR_IO_PENDING, error); |
| int result = url_request_->CancelWithError(error); |
| OnUrlRequestCompleted(result); |
| } |
| -CertNetFetcherImpl::CertNetFetcherImpl(URLRequestContext* context) |
| - : currently_completing_job_(nullptr), context_(context) { |
| +AsyncCertNetFetcherImpl::AsyncCertNetFetcherImpl(URLRequestContext* context) |
| + : context_(context) { |
| + // Allow creation to happen from another thread. |
| + thread_checker_.DetachFromThread(); |
| } |
| -CertNetFetcherImpl::~CertNetFetcherImpl() { |
| +AsyncCertNetFetcherImpl::~AsyncCertNetFetcherImpl() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| jobs_.clear(); |
| - |
| - // The CertNetFetcherImpl was destroyed in a FetchCallback. Detach all |
| - // remaining requests from the job so no further callbacks are called. |
| - if (currently_completing_job_) |
| - currently_completing_job_->Cancel(); |
| -} |
| - |
| -std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchCaIssuers( |
| - const GURL& url, |
| - int timeout_milliseconds, |
| - int max_response_bytes, |
| - const FetchCallback& callback) { |
| - std::unique_ptr<RequestParams> request_params(new RequestParams); |
| - |
| - request_params->url = url; |
| - request_params->http_method = HTTP_METHOD_GET; |
| - request_params->timeout = GetTimeout(timeout_milliseconds); |
| - request_params->max_response_bytes = |
| - GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); |
| - |
| - return Fetch(std::move(request_params), callback); |
| -} |
| - |
| -std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchCrl( |
| - const GURL& url, |
| - int timeout_milliseconds, |
| - int max_response_bytes, |
| - const FetchCallback& callback) { |
| - std::unique_ptr<RequestParams> request_params(new RequestParams); |
| - |
| - request_params->url = url; |
| - request_params->http_method = HTTP_METHOD_GET; |
| - request_params->timeout = GetTimeout(timeout_milliseconds); |
| - request_params->max_response_bytes = |
| - GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForCrl); |
| - |
| - return Fetch(std::move(request_params), callback); |
| -} |
| - |
| -std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchOcsp( |
| - const GURL& url, |
| - int timeout_milliseconds, |
| - int max_response_bytes, |
| - const FetchCallback& callback) { |
| - std::unique_ptr<RequestParams> request_params(new RequestParams); |
| - |
| - request_params->url = url; |
| - request_params->http_method = HTTP_METHOD_GET; |
| - request_params->timeout = GetTimeout(timeout_milliseconds); |
| - request_params->max_response_bytes = |
| - GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); |
| - |
| - return Fetch(std::move(request_params), callback); |
| } |
| -bool CertNetFetcherImpl::JobComparator::operator()(const Job* job1, |
| - const Job* job2) const { |
| +bool JobComparator::operator()(const Job* job1, const Job* job2) const { |
| return job1->request_params() < job2->request_params(); |
| } |
| -std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::Fetch( |
| +void AsyncCertNetFetcherImpl::Fetch( |
| std::unique_ptr<RequestParams> request_params, |
| - const FetchCallback& callback) { |
| + RequestCore* request) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| // If there is an in-progress job that matches the request parameters use it. |
| @@ -503,18 +509,17 @@ std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::Fetch( |
| job->StartURLRequest(context_); |
| } |
| - return job->CreateRequest(callback); |
| + return job->AttachRequest(request); |
| } |
| -struct CertNetFetcherImpl::JobToRequestParamsComparator { |
| - bool operator()(const CertNetFetcherImpl::JobSet::value_type& job, |
| - const CertNetFetcherImpl::RequestParams& value) const { |
| +struct JobToRequestParamsComparator { |
| + bool operator()(const JobSet::value_type& job, |
| + const RequestParams& value) const { |
| return job.first->request_params() < value; |
| } |
| }; |
| -CertNetFetcherImpl::Job* CertNetFetcherImpl::FindJob( |
| - const RequestParams& params) { |
| +Job* AsyncCertNetFetcherImpl::FindJob(const RequestParams& params) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| // The JobSet is kept in sorted order so items can be found using binary |
| @@ -526,8 +531,7 @@ CertNetFetcherImpl::Job* CertNetFetcherImpl::FindJob( |
| return nullptr; |
| } |
| -std::unique_ptr<CertNetFetcherImpl::Job> CertNetFetcherImpl::RemoveJob( |
| - Job* job) { |
| +std::unique_ptr<Job> AsyncCertNetFetcherImpl::RemoveJob(Job* job) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| auto it = jobs_.find(job); |
| CHECK(it != jobs_.end()); |
| @@ -536,19 +540,149 @@ std::unique_ptr<CertNetFetcherImpl::Job> CertNetFetcherImpl::RemoveJob( |
| return owned_job; |
| } |
| -void CertNetFetcherImpl::SetCurrentlyCompletingJob(Job* job) { |
| - DCHECK(!currently_completing_job_); |
| - DCHECK(job); |
| - currently_completing_job_ = job; |
| -} |
| +class CertNetFetcherRequestImpl : public CertNetFetcher::Request { |
|
mattm
2016/10/28 02:11:56
class comments for all the classes. How about a fi
eroman
2016/11/23 22:10:21
Thanks, done!
|
| + public: |
| + explicit CertNetFetcherRequestImpl(scoped_refptr<RequestCore> core) |
| + : core_(std::move(core)) { |
| + DCHECK(core_); |
| + } |
| -void CertNetFetcherImpl::ClearCurrentlyCompletingJob(Job* job) { |
| - DCHECK_EQ(currently_completing_job_, job); |
| - currently_completing_job_ = nullptr; |
| -} |
| + void WaitForResult(Error* error, std::vector<uint8_t>* bytes) override { |
| + // Should only be called a single time. |
| + DCHECK(core_); |
| + core_->WaitForResult(error, bytes); |
| + core_ = nullptr; |
| + } |
| + |
| + ~CertNetFetcherRequestImpl() override { |
| + if (core_) |
| + core_->Cancel(); |
| + } |
| + |
| + private: |
| + scoped_refptr<RequestCore> core_; |
| +}; |
| + |
| +class CertNetFetcherCore |
| + : public base::RefCountedThreadSafe<CertNetFetcherCore> { |
| + public: |
| + explicit CertNetFetcherCore(URLRequestContextGetter* context_getter) |
| + : context_getter_(context_getter) {} |
| + |
| + void Abandon() { |
| + GetNetworkTaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&CertNetFetcherCore::DoAbandonOnNetworkThread, this)); |
| + } |
| + |
| + scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() { |
| + return context_getter_->GetNetworkTaskRunner(); |
| + } |
| + |
| + void DoFetchOnNetworkThread(std::unique_ptr<RequestParams> request_params, |
| + scoped_refptr<RequestCore> request) { |
| + DCHECK(GetNetworkTaskRunner()->RunsTasksOnCurrentThread()); |
| + |
| + if (!impl_) { |
| + impl_.reset( |
| + new AsyncCertNetFetcherImpl(context_getter_->GetURLRequestContext())); |
| + } |
| + |
| + // Don't need to retain a reference to |request| because consume is |
| + // expected to keep it alive. |
| + impl_->Fetch(std::move(request_params), request.get()); |
| + } |
| + |
| + private: |
| + friend class base::RefCountedThreadSafe<CertNetFetcherCore>; |
| + |
| + void DoAbandonOnNetworkThread() { |
| + DCHECK(GetNetworkTaskRunner()->RunsTasksOnCurrentThread()); |
| + impl_.reset(); |
| + } |
| + |
| + ~CertNetFetcherCore() { DCHECK(!impl_); } |
| + |
| + scoped_refptr<URLRequestContextGetter> context_getter_; |
| + |
| + std::unique_ptr<AsyncCertNetFetcherImpl> impl_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(CertNetFetcherCore); |
| +}; |
| + |
| +class CertNetFetcherImpl : public CertNetFetcher { |
| + public: |
| + explicit CertNetFetcherImpl(URLRequestContextGetter* context_getter) |
| + : core_(new CertNetFetcherCore(context_getter)) {} |
| + |
| + ~CertNetFetcherImpl() override { core_->Abandon(); } |
| + |
| + std::unique_ptr<Request> FetchCaIssuers(const GURL& url, |
| + int timeout_milliseconds, |
| + int max_response_bytes) override { |
| + std::unique_ptr<RequestParams> request_params(new RequestParams); |
| + |
| + request_params->url = url; |
| + request_params->http_method = HTTP_METHOD_GET; |
| + request_params->timeout = GetTimeout(timeout_milliseconds); |
| + request_params->max_response_bytes = |
| + GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); |
| + |
| + return DoFetch(std::move(request_params)); |
| + } |
| + |
| + std::unique_ptr<Request> FetchCrl(const GURL& url, |
| + int timeout_milliseconds, |
| + int max_response_bytes) override { |
| + std::unique_ptr<RequestParams> request_params(new RequestParams); |
| + |
| + request_params->url = url; |
| + request_params->http_method = HTTP_METHOD_GET; |
| + request_params->timeout = GetTimeout(timeout_milliseconds); |
| + request_params->max_response_bytes = |
| + GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForCrl); |
| + |
| + return DoFetch(std::move(request_params)); |
| + } |
| + |
| + WARN_UNUSED_RESULT std::unique_ptr<Request> FetchOcsp( |
| + const GURL& url, |
| + int timeout_milliseconds, |
| + int max_response_bytes) override { |
| + std::unique_ptr<RequestParams> request_params(new RequestParams); |
| + |
| + request_params->url = url; |
| + request_params->http_method = HTTP_METHOD_GET; |
| + request_params->timeout = GetTimeout(timeout_milliseconds); |
| + request_params->max_response_bytes = |
| + GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); |
| + |
| + return DoFetch(std::move(request_params)); |
| + } |
| + |
| + private: |
| + std::unique_ptr<Request> DoFetch( |
| + std::unique_ptr<RequestParams> request_params) { |
| + auto task_runner = core_->GetNetworkTaskRunner(); |
| + scoped_refptr<RequestCore> request_core = new RequestCore(task_runner); |
| + |
| + task_runner->PostTask( |
| + FROM_HERE, |
| + base::Bind(&CertNetFetcherCore::DoFetchOnNetworkThread, core_, |
| + base::Passed(&request_params), request_core)); |
| + |
| + return base::MakeUnique<CertNetFetcherRequestImpl>(std::move(request_core)); |
| + } |
| + |
| + private: |
| + scoped_refptr<CertNetFetcherCore> core_; |
| +}; |
| + |
| +} // namespace |
| -bool CertNetFetcherImpl::IsCurrentlyCompletingJob(Job* job) { |
| - return job == currently_completing_job_; |
| +std::unique_ptr<CertNetFetcher> CreateCertNetFetcher( |
| + URLRequestContextGetter* context_getter) { |
| + return base::MakeUnique<CertNetFetcherImpl>(context_getter); |
| } |
| } // namespace net |