| OLD | NEW |
| 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 // |
| 5 // Overview |
| 6 // |
| 7 // The main entry point is CertNetFetcherImpl. This is an implementation of |
| 8 // CertNetFetcher that provides a service for fetching network requests. |
| 9 // |
| 10 // The interface for CertNetFetcher is synchronous, however allows |
| 11 // overlapping requests. When starting a request CertNetFetcherImpl |
| 12 // returns a CertNetFetcher::Request (CertNetFetcherImpl) that the |
| 13 // caller can use to cancel the fetch, or wait for it to complete |
| 14 // (blocking). |
| 15 // |
| 16 // The classes are mainly organized based on their thread affinity: |
| 17 // |
| 18 // --------------- |
| 19 // Lives on caller thread |
| 20 // --------------- |
| 21 // |
| 22 // CertNetFetcherImpl (implements CertNetFetcher) |
| 23 // * Main entry point |
| 24 // * Provides a service to start/cancel/wait for URL fetches |
| 25 // * Returns callers a CertNetFetcher::Request as a handle |
| 26 // * Requests can run in parallel, however will block the current thread when |
| 27 // reading results. |
| 28 // * Posts tasks to network thread to coordinate actual work |
| 29 // |
| 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 |
| 45 // * Reference-counted bridge between CertNetFetcherRequestImpl and the |
| 46 // dependencies on the network thread |
| 47 // * Holds the result of the request, a WaitableEvent for signaling |
| 48 // completion, and pointers for canceling work on network thread. |
| 49 // |
| 50 // --------------- |
| 51 // Lives on network thread |
| 52 // --------------- |
| 53 // |
| 54 // AsyncCertNetFetcherImpl |
| 55 // * Asyncronous manager for outstanding requests. Handles de-duplication, |
| 56 // timeouts, and actual integration with network stack. This is where the |
| 57 // majority of the logic lives. |
| 58 // * Signals completion of requests through RequestCore's WaitableEvent. |
| 59 // * Attaches requests to Jobs for the purpose of de-duplication |
| 4 | 60 |
| 5 #include "net/cert_net/cert_net_fetcher_impl.h" | 61 #include "net/cert_net/cert_net_fetcher_impl.h" |
| 6 | 62 |
| 7 #include <tuple> | 63 #include <tuple> |
| 8 #include <utility> | 64 #include <utility> |
| 9 | 65 |
| 10 #include "base/callback_helpers.h" | 66 #include "base/callback_helpers.h" |
| 11 #include "base/containers/linked_list.h" | |
| 12 #include "base/logging.h" | 67 #include "base/logging.h" |
| 13 #include "base/macros.h" | 68 #include "base/macros.h" |
| 14 #include "base/memory/ptr_util.h" | 69 #include "base/memory/ptr_util.h" |
| 15 #include "base/numerics/safe_math.h" | 70 #include "base/numerics/safe_math.h" |
| 71 #include "base/synchronization/waitable_event.h" |
| 16 #include "base/timer/timer.h" | 72 #include "base/timer/timer.h" |
| 17 #include "net/base/load_flags.h" | 73 #include "net/base/load_flags.h" |
| 74 #include "net/cert/cert_net_fetcher.h" |
| 18 #include "net/url_request/redirect_info.h" | 75 #include "net/url_request/redirect_info.h" |
| 19 #include "net/url_request/url_request_context.h" | 76 #include "net/url_request/url_request_context.h" |
| 77 #include "net/url_request/url_request_context_getter.h" |
| 20 | 78 |
| 21 // TODO(eroman): Add support for POST parameters. | 79 // TODO(eroman): Add support for POST parameters. |
| 22 // TODO(eroman): Add controls for bypassing the cache. | 80 // TODO(eroman): Add controls for bypassing the cache. |
| 23 // TODO(eroman): Add a maximum number of in-flight jobs/requests. | 81 // TODO(eroman): Add a maximum number of in-flight jobs/requests. |
| 24 // TODO(eroman): Add NetLog integration. | 82 // TODO(eroman): Add NetLog integration. |
| 25 | 83 |
| 26 namespace net { | 84 namespace net { |
| 27 | 85 |
| 28 namespace { | 86 namespace { |
| 29 | 87 |
| 30 // The size of the buffer used for reading the response body of the URLRequest. | 88 // The size of the buffer used for reading the response body of the URLRequest. |
| 31 const int kReadBufferSizeInBytes = 4096; | 89 const int kReadBufferSizeInBytes = 4096; |
| 32 | 90 |
| 33 // The maximum size in bytes for the response body when fetching a CRL. | 91 // The maximum size in bytes for the response body when fetching a CRL. |
| 34 const int kMaxResponseSizeInBytesForCrl = 5 * 1024 * 1024; | 92 const int kMaxResponseSizeInBytesForCrl = 5 * 1024 * 1024; |
| 35 | 93 |
| 36 // The maximum size in bytes for the response body when fetching an AIA URL | 94 // The maximum size in bytes for the response body when fetching an AIA URL |
| 37 // (caIssuers/OCSP). | 95 // (caIssuers/OCSP). |
| 38 const int kMaxResponseSizeInBytesForAia = 64 * 1024; | 96 const int kMaxResponseSizeInBytesForAia = 64 * 1024; |
| 39 | 97 |
| 40 // The default timeout in seconds for fetch requests. | 98 // The default timeout in seconds for fetch requests. |
| 41 const int kTimeoutSeconds = 15; | 99 const int kTimeoutSeconds = 15; |
| 42 | 100 |
| 101 class RequestCore; |
| 102 struct RequestParams; |
| 103 class Job; |
| 104 |
| 105 struct JobToRequestParamsComparator; |
| 106 |
| 107 struct JobComparator { |
| 108 bool operator()(const Job* job1, const Job* job2) const; |
| 109 }; |
| 110 |
| 111 // Would be a set<unique_ptr> but extraction of owned objects from a set of |
| 112 // owned types doesn't come until C++17. |
| 113 using JobSet = std::map<Job*, std::unique_ptr<Job>, JobComparator>; |
| 114 |
| 115 // AsyncCertNetFetcherImpl manages URLRequests in an async fashion on the |
| 116 // URLRequestContexts's task runner thread. |
| 117 // |
| 118 // * Schedules |
| 119 // * De-duplicates requests |
| 120 // * Handles timeouts |
| 121 class AsyncCertNetFetcherImpl { |
| 122 public: |
| 123 // Initializes AsyncCertNetFetcherImpl using the specified URLRequestContext |
| 124 // for issuing requests. |context| must remain valid for the entire |
| 125 // lifetime of the AsyncCertNetFetcherImpl. |
| 126 explicit AsyncCertNetFetcherImpl(URLRequestContext* context); |
| 127 |
| 128 // Deletion implicitly cancels any outstanding requests. |
| 129 ~AsyncCertNetFetcherImpl(); |
| 130 |
| 131 // Starts an asynchronous request to fetch the given URL. On completion |
| 132 // |callback| will be invoked. |
| 133 // |
| 134 // Completion of the request will never occur synchronously. In other words it |
| 135 // is guaranteed that |callback| will only be invoked once the Fetch*() method |
| 136 // has returned. |
| 137 void Fetch(std::unique_ptr<RequestParams> request_params, |
| 138 RequestCore* request); |
| 139 |
| 140 private: |
| 141 friend class Job; |
| 142 |
| 143 // Finds a job with a matching RequestPararms or returns nullptr if there was |
| 144 // no match. |
| 145 Job* FindJob(const RequestParams& params); |
| 146 |
| 147 // Removes |job| from the in progress jobs and transfers ownership to the |
| 148 // caller. |
| 149 std::unique_ptr<Job> RemoveJob(Job* job); |
| 150 |
| 151 // The in-progress jobs. This set does not contain the job which is actively |
| 152 // invoking callbacks (OnJobCompleted). |
| 153 JobSet jobs_; |
| 154 |
| 155 // Not owned. |context_| must outlive the AsyncCertNetFetcherImpl. |
| 156 URLRequestContext* context_ = nullptr; |
| 157 |
| 158 base::ThreadChecker thread_checker_; |
| 159 |
| 160 DISALLOW_COPY_AND_ASSIGN(AsyncCertNetFetcherImpl); |
| 161 }; |
| 162 |
| 43 // Policy for which URLs are allowed to be fetched. This is called both for the | 163 // Policy for which URLs are allowed to be fetched. This is called both for the |
| 44 // initial URL and for each redirect. Returns OK on success or a net error | 164 // initial URL and for each redirect. Returns OK on success or a net error |
| 45 // code on failure. | 165 // code on failure. |
| 46 Error CanFetchUrl(const GURL& url) { | 166 Error CanFetchUrl(const GURL& url) { |
| 47 if (!url.SchemeIs("http")) | 167 if (!url.SchemeIs("http")) |
| 48 return ERR_DISALLOWED_URL_SCHEME; | 168 return ERR_DISALLOWED_URL_SCHEME; |
| 49 return OK; | 169 return OK; |
| 50 } | 170 } |
| 51 | 171 |
| 52 base::TimeDelta GetTimeout(int timeout_milliseconds) { | 172 base::TimeDelta GetTimeout(int timeout_milliseconds) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 67 DCHECK(check.IsValid()); | 187 DCHECK(check.IsValid()); |
| 68 | 188 |
| 69 return max_response_bytes; | 189 return max_response_bytes; |
| 70 } | 190 } |
| 71 | 191 |
| 72 enum HttpMethod { | 192 enum HttpMethod { |
| 73 HTTP_METHOD_GET, | 193 HTTP_METHOD_GET, |
| 74 HTTP_METHOD_POST, | 194 HTTP_METHOD_POST, |
| 75 }; | 195 }; |
| 76 | 196 |
| 77 } // namespace | 197 // RequestCore tracks an outstanding call to Fetch(). It is |
| 198 // reference-counted for ease of sharing between threads. |
| 199 class RequestCore : public base::RefCountedThreadSafe<RequestCore> { |
| 200 public: |
| 201 explicit RequestCore(scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
| 202 : completion_event_(base::WaitableEvent::ResetPolicy::MANUAL, |
| 203 base::WaitableEvent::InitialState::NOT_SIGNALED), |
| 204 task_runner_(std::move(task_runner)) {} |
| 78 | 205 |
| 79 // CertNetFetcherImpl::RequestImpl tracks an outstanding call to Fetch(). | 206 void AttachedToJob(Job* job) { |
| 80 class CertNetFetcherImpl::RequestImpl : public CertNetFetcher::Request, | 207 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 81 public base::LinkNode<RequestImpl> { | 208 DCHECK(!job_); |
| 82 public: | 209 job_ = job; |
| 83 RequestImpl(Job* job, const FetchCallback& callback) | |
| 84 : callback_(callback), job_(job) { | |
| 85 DCHECK(!callback.is_null()); | |
| 86 } | |
| 87 | |
| 88 // Deletion cancels the outstanding request. | |
| 89 ~RequestImpl() override; | |
| 90 | |
| 91 void OnJobCancelled(Job* job) { | |
| 92 DCHECK_EQ(job_, job); | |
| 93 job_ = nullptr; | |
| 94 callback_.Reset(); | |
| 95 } | 210 } |
| 96 | 211 |
| 97 void OnJobCompleted(Job* job, | 212 void OnJobCompleted(Job* job, |
| 98 Error error, | 213 Error error, |
| 99 const std::vector<uint8_t>& response_body) { | 214 const std::vector<uint8_t>& response_body) { |
| 215 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 216 |
| 100 DCHECK_EQ(job_, job); | 217 DCHECK_EQ(job_, job); |
| 101 job_ = nullptr; | 218 job_ = nullptr; |
| 102 base::ResetAndReturn(&callback_).Run(error, response_body); | 219 |
| 220 error_ = error; |
| 221 bytes_ = response_body; |
| 222 completion_event_.Signal(); |
| 223 } |
| 224 |
| 225 // Can be called from any thread. |
| 226 void Cancel(); |
| 227 |
| 228 // Should only be called once. |
| 229 void WaitForResult(Error* error, std::vector<uint8_t>* bytes) { |
| 230 DCHECK(!task_runner_->RunsTasksOnCurrentThread()); |
| 231 |
| 232 completion_event_.Wait(); |
| 233 *bytes = std::move(bytes_); |
| 234 *error = error_; |
| 235 |
| 236 error_ = ERR_UNEXPECTED; |
| 103 } | 237 } |
| 104 | 238 |
| 105 private: | 239 private: |
| 106 // The callback to invoke when the request has completed. | 240 friend class base::RefCountedThreadSafe<RequestCore>; |
| 107 FetchCallback callback_; | 241 |
| 242 ~RequestCore() { |
| 243 // Requests should have been cancelled prior to destruction. |
| 244 DCHECK(!job_); |
| 245 } |
| 108 | 246 |
| 109 // A non-owned pointer to the job that is executing the request. | 247 // A non-owned pointer to the job that is executing the request. |
| 110 Job* job_; | 248 Job* job_ = nullptr; |
| 111 | 249 |
| 112 private: | 250 // May be written to from network thread. |
| 113 DISALLOW_COPY_AND_ASSIGN(RequestImpl); | 251 Error error_; |
| 252 std::vector<uint8_t> bytes_; |
| 253 |
| 254 // Indicates when |error_| and |bytes_| have been written to. |
| 255 base::WaitableEvent completion_event_; |
| 256 |
| 257 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 258 |
| 259 DISALLOW_COPY_AND_ASSIGN(RequestCore); |
| 114 }; | 260 }; |
| 115 | 261 |
| 116 struct CertNetFetcherImpl::RequestParams { | 262 struct RequestParams { |
| 117 RequestParams(); | 263 RequestParams(); |
| 118 | 264 |
| 119 bool operator<(const RequestParams& other) const; | 265 bool operator<(const RequestParams& other) const; |
| 120 | 266 |
| 121 GURL url; | 267 GURL url; |
| 122 HttpMethod http_method; | 268 HttpMethod http_method; |
| 123 size_t max_response_bytes; | 269 size_t max_response_bytes; |
| 124 | 270 |
| 125 // If set to a value <= 0 then means "no timeout". | 271 // If set to a value <= 0 then means "no timeout". |
| 126 base::TimeDelta timeout; | 272 base::TimeDelta timeout; |
| 127 | 273 |
| 128 // IMPORTANT: When adding fields to this structure, update operator<(). | 274 // IMPORTANT: When adding fields to this structure, update operator<(). |
| 129 | 275 |
| 130 private: | 276 private: |
| 131 DISALLOW_COPY_AND_ASSIGN(RequestParams); | 277 DISALLOW_COPY_AND_ASSIGN(RequestParams); |
| 132 }; | 278 }; |
| 133 | 279 |
| 134 CertNetFetcherImpl::RequestParams::RequestParams() | 280 RequestParams::RequestParams() |
| 135 : http_method(HTTP_METHOD_GET), max_response_bytes(0) { | 281 : http_method(HTTP_METHOD_GET), max_response_bytes(0) {} |
| 136 } | |
| 137 | 282 |
| 138 bool CertNetFetcherImpl::RequestParams::operator<( | 283 bool RequestParams::operator<(const RequestParams& other) const { |
| 139 const RequestParams& other) const { | |
| 140 return std::tie(url, http_method, max_response_bytes, timeout) < | 284 return std::tie(url, http_method, max_response_bytes, timeout) < |
| 141 std::tie(other.url, other.http_method, other.max_response_bytes, | 285 std::tie(other.url, other.http_method, other.max_response_bytes, |
| 142 other.timeout); | 286 other.timeout); |
| 143 } | 287 } |
| 144 | 288 |
| 145 // CertNetFetcherImpl::Job tracks an outstanding URLRequest as well as all of | 289 // Job tracks an outstanding URLRequest as well as all of the pending requests |
| 146 // the pending requests for it. | 290 // for it. |
| 147 class CertNetFetcherImpl::Job : public URLRequest::Delegate { | 291 class Job : public URLRequest::Delegate { |
| 148 public: | 292 public: |
| 149 Job(std::unique_ptr<RequestParams> request_params, | 293 Job(std::unique_ptr<RequestParams> request_params, |
| 150 CertNetFetcherImpl* parent); | 294 AsyncCertNetFetcherImpl* parent); |
| 151 ~Job() override; | 295 ~Job() override; |
| 152 | 296 |
| 153 // Cancels the job and all requests attached to it. No callbacks will be | |
| 154 // invoked following cancellation. | |
| 155 void Cancel(); | |
| 156 | |
| 157 const RequestParams& request_params() const { return *request_params_; } | 297 const RequestParams& request_params() const { return *request_params_; } |
| 158 | 298 |
| 159 // Create a request and attaches it to the job. When the job completes it will | 299 // Create a request and attaches it to the job. When the job completes it will |
| 160 // notify the request of completion through OnJobCompleted. Note that the Job | 300 // notify the request of completion through OnJobCompleted. Note that the Job |
| 161 // does NOT own the request. | 301 // does NOT own the request. |
| 162 std::unique_ptr<Request> CreateRequest(const FetchCallback& callback); | 302 void AttachRequest(RequestCore* request); |
| 163 | 303 |
| 164 // Removes |request| from the job. | 304 // Removes |request| from the job. |
| 165 void DetachRequest(RequestImpl* request); | 305 void DetachRequest(RequestCore* request); |
| 166 | 306 |
| 167 // Creates and starts a URLRequest for the job. After the request has | 307 // Creates and starts a URLRequest for the job. After the URLRequest has |
| 168 // completed, OnJobCompleted() will be invoked and all the registered requests | 308 // completed, OnJobCompleted() will be invoked and all the registered requests |
| 169 // notified of completion. | 309 // notified of completion. |
| 170 void StartURLRequest(URLRequestContext* context); | 310 void StartURLRequest(URLRequestContext* context); |
| 171 | 311 |
| 172 private: | 312 private: |
| 173 // The pointers in RequestList are not owned by the Job. | |
| 174 using RequestList = base::LinkedList<RequestImpl>; | |
| 175 | |
| 176 // Implementation of URLRequest::Delegate | 313 // Implementation of URLRequest::Delegate |
| 177 void OnReceivedRedirect(URLRequest* request, | 314 void OnReceivedRedirect(URLRequest* request, |
| 178 const RedirectInfo& redirect_info, | 315 const RedirectInfo& redirect_info, |
| 179 bool* defer_redirect) override; | 316 bool* defer_redirect) override; |
| 180 void OnResponseStarted(URLRequest* request, int net_error) override; | 317 void OnResponseStarted(URLRequest* request, int net_error) override; |
| 181 void OnReadCompleted(URLRequest* request, int bytes_read) override; | 318 void OnReadCompleted(URLRequest* request, int bytes_read) override; |
| 182 | 319 |
| 183 // Clears the URLRequest and timer. Helper for doing work common to | 320 // Clears the URLRequest and timer. Helper for doing work common to |
| 184 // cancellation and job completion. | 321 // cancellation and job completion. |
| 185 void Stop(); | 322 void Stop(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 196 | 333 |
| 197 // Called when the Job has completed. The job may finish in response to a | 334 // Called when the Job has completed. The job may finish in response to a |
| 198 // timeout, an invalid URL, or the URLRequest completing. By the time this | 335 // timeout, an invalid URL, or the URLRequest completing. By the time this |
| 199 // method is called, the |response_body_| variable have been assigned. | 336 // method is called, the |response_body_| variable have been assigned. |
| 200 void OnJobCompleted(Error error); | 337 void OnJobCompleted(Error error); |
| 201 | 338 |
| 202 // Cancels a request with a specified error code and calls | 339 // Cancels a request with a specified error code and calls |
| 203 // OnUrlRequestCompleted(). | 340 // OnUrlRequestCompleted(). |
| 204 void FailRequest(Error error); | 341 void FailRequest(Error error); |
| 205 | 342 |
| 206 // The requests attached to this job. | 343 // The requests attached to this job (non-owned). |
| 207 RequestList requests_; | 344 std::vector<RequestCore*> requests_; |
| 208 | 345 |
| 209 // The input parameters for starting a URLRequest. | 346 // The input parameters for starting a URLRequest. |
| 210 std::unique_ptr<RequestParams> request_params_; | 347 std::unique_ptr<RequestParams> request_params_; |
| 211 | 348 |
| 212 // The URLRequest response information. | 349 // The URLRequest response information. |
| 213 std::vector<uint8_t> response_body_; | 350 std::vector<uint8_t> response_body_; |
| 214 | 351 |
| 215 std::unique_ptr<URLRequest> url_request_; | 352 std::unique_ptr<URLRequest> url_request_; |
| 216 scoped_refptr<IOBuffer> read_buffer_; | 353 scoped_refptr<IOBuffer> read_buffer_; |
| 217 | 354 |
| 218 // Used to timeout the job when the URLRequest takes too long. This timer is | 355 // Used to timeout the job when the URLRequest takes too long. This timer is |
| 219 // also used for notifying a failure to start the URLRequest. | 356 // also used for notifying a failure to start the URLRequest. |
| 220 base::OneShotTimer timer_; | 357 base::OneShotTimer timer_; |
| 221 | 358 |
| 222 // Non-owned pointer to the CertNetFetcherImpl that created this job. | 359 // Non-owned pointer to the AsyncCertNetFetcherImpl that created this job. |
| 223 CertNetFetcherImpl* parent_; | 360 AsyncCertNetFetcherImpl* parent_; |
| 224 | 361 |
| 225 DISALLOW_COPY_AND_ASSIGN(Job); | 362 DISALLOW_COPY_AND_ASSIGN(Job); |
| 226 }; | 363 }; |
| 227 | 364 |
| 228 CertNetFetcherImpl::RequestImpl::~RequestImpl() { | 365 void RequestCore::Cancel() { |
| 229 if (job_) | 366 if (!task_runner_->RunsTasksOnCurrentThread()) { |
| 230 job_->DetachRequest(this); | 367 task_runner_->PostTask(FROM_HERE, base::Bind(&RequestCore::Cancel, this)); |
| 368 return; |
| 369 } |
| 370 |
| 371 if (job_) { |
| 372 auto* job = job_; |
| 373 job_ = nullptr; |
| 374 job->DetachRequest(this); |
| 375 } |
| 376 |
| 377 bytes_.clear(); |
| 378 error_ = ERR_UNEXPECTED; |
| 231 } | 379 } |
| 232 | 380 |
| 233 CertNetFetcherImpl::Job::Job(std::unique_ptr<RequestParams> request_params, | 381 Job::Job(std::unique_ptr<RequestParams> request_params, |
| 234 CertNetFetcherImpl* parent) | 382 AsyncCertNetFetcherImpl* parent) |
| 235 : request_params_(std::move(request_params)), | 383 : request_params_(std::move(request_params)), parent_(parent) {} |
| 236 parent_(parent) {} | |
| 237 | 384 |
| 238 CertNetFetcherImpl::Job::~Job() { | 385 Job::~Job() { |
| 239 Cancel(); | |
| 240 } | |
| 241 | |
| 242 void CertNetFetcherImpl::Job::Cancel() { | |
| 243 parent_ = nullptr; | |
| 244 | |
| 245 // Notify each request of cancellation and remove it from the list. | |
| 246 for (base::LinkNode<RequestImpl>* current = requests_.head(); | |
| 247 current != requests_.end();) { | |
| 248 base::LinkNode<RequestImpl>* next = current->next(); | |
| 249 current->value()->OnJobCancelled(this); | |
| 250 current->RemoveFromList(); | |
| 251 current = next; | |
| 252 } | |
| 253 | |
| 254 DCHECK(requests_.empty()); | 386 DCHECK(requests_.empty()); |
| 255 | |
| 256 Stop(); | 387 Stop(); |
| 257 } | 388 } |
| 258 | 389 |
| 259 std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::Job::CreateRequest( | 390 void Job::AttachRequest(RequestCore* request) { |
| 260 const FetchCallback& callback) { | 391 requests_.push_back(request); |
| 261 std::unique_ptr<RequestImpl> request(new RequestImpl(this, callback)); | 392 request->AttachedToJob(this); |
| 262 requests_.Append(request.get()); | |
| 263 return std::move(request); | |
| 264 } | 393 } |
| 265 | 394 |
| 266 void CertNetFetcherImpl::Job::DetachRequest(RequestImpl* request) { | 395 void Job::DetachRequest(RequestCore* request) { |
| 267 std::unique_ptr<Job> delete_this; | 396 std::unique_ptr<Job> delete_this; |
| 268 | 397 |
| 269 request->RemoveFromList(); | 398 auto it = std::find(requests_.begin(), requests_.end(), request); |
| 399 DCHECK(it != requests_.end()); |
| 400 requests_.erase(it); |
| 270 | 401 |
| 271 // If there are no longer any requests attached to the job then | 402 // If there are no longer any requests attached to the job then |
| 272 // cancel and delete it. | 403 // cancel and delete it. |
| 273 if (requests_.empty() && !parent_->IsCurrentlyCompletingJob(this)) | 404 if (requests_.empty()) |
| 274 delete_this = parent_->RemoveJob(this); | 405 delete_this = parent_->RemoveJob(this); |
| 275 } | 406 } |
| 276 | 407 |
| 277 void CertNetFetcherImpl::Job::StartURLRequest(URLRequestContext* context) { | 408 void Job::StartURLRequest(URLRequestContext* context) { |
| 278 Error error = CanFetchUrl(request_params_->url); | 409 Error error = CanFetchUrl(request_params_->url); |
| 279 if (error != OK) { | 410 if (error != OK) { |
| 280 // The CertNetFetcher's API contract is that requests always complete | 411 // TODO(eroman): Don't post a task for this case. |
| 281 // asynchronously. Use the timer class so the task is easily cancelled. | |
| 282 timer_.Start( | 412 timer_.Start( |
| 283 FROM_HERE, base::TimeDelta(), | 413 FROM_HERE, base::TimeDelta(), |
| 284 base::Bind(&Job::OnJobCompleted, base::Unretained(this), error)); | 414 base::Bind(&Job::OnJobCompleted, base::Unretained(this), error)); |
| 285 return; | 415 return; |
| 286 } | 416 } |
| 287 | 417 |
| 288 // Start the URLRequest. | 418 // Start the URLRequest. |
| 289 read_buffer_ = new IOBuffer(kReadBufferSizeInBytes); | 419 read_buffer_ = new IOBuffer(kReadBufferSizeInBytes); |
| 290 url_request_ = | 420 url_request_ = |
| 291 context->CreateRequest(request_params_->url, DEFAULT_PRIORITY, this); | 421 context->CreateRequest(request_params_->url, DEFAULT_PRIORITY, this); |
| 292 if (request_params_->http_method == HTTP_METHOD_POST) | 422 if (request_params_->http_method == HTTP_METHOD_POST) |
| 293 url_request_->set_method("POST"); | 423 url_request_->set_method("POST"); |
| 294 url_request_->SetLoadFlags(LOAD_DO_NOT_SAVE_COOKIES | | 424 url_request_->SetLoadFlags(LOAD_DO_NOT_SAVE_COOKIES | |
| 295 LOAD_DO_NOT_SEND_COOKIES); | 425 LOAD_DO_NOT_SEND_COOKIES); |
| 296 url_request_->Start(); | 426 url_request_->Start(); |
| 297 | 427 |
| 298 // Start a timer to limit how long the job runs for. | 428 // Start a timer to limit how long the job runs for. |
| 299 if (request_params_->timeout > base::TimeDelta()) | 429 if (request_params_->timeout > base::TimeDelta()) |
| 300 timer_.Start( | 430 timer_.Start( |
| 301 FROM_HERE, request_params_->timeout, | 431 FROM_HERE, request_params_->timeout, |
| 302 base::Bind(&Job::FailRequest, base::Unretained(this), ERR_TIMED_OUT)); | 432 base::Bind(&Job::FailRequest, base::Unretained(this), ERR_TIMED_OUT)); |
| 303 } | 433 } |
| 304 | 434 |
| 305 void CertNetFetcherImpl::Job::OnReceivedRedirect( | 435 void Job::OnReceivedRedirect(URLRequest* request, |
| 306 URLRequest* request, | 436 const RedirectInfo& redirect_info, |
| 307 const RedirectInfo& redirect_info, | 437 bool* defer_redirect) { |
| 308 bool* defer_redirect) { | |
| 309 DCHECK_EQ(url_request_.get(), request); | 438 DCHECK_EQ(url_request_.get(), request); |
| 310 | 439 |
| 311 // Ensure that the new URL matches the policy. | 440 // Ensure that the new URL matches the policy. |
| 312 Error error = CanFetchUrl(redirect_info.new_url); | 441 Error error = CanFetchUrl(redirect_info.new_url); |
| 313 if (error != OK) { | 442 if (error != OK) { |
| 314 FailRequest(error); | 443 FailRequest(error); |
| 315 return; | 444 return; |
| 316 } | 445 } |
| 317 } | 446 } |
| 318 | 447 |
| 319 void CertNetFetcherImpl::Job::OnResponseStarted(URLRequest* request, | 448 void Job::OnResponseStarted(URLRequest* request, int net_error) { |
| 320 int net_error) { | |
| 321 DCHECK_EQ(url_request_.get(), request); | 449 DCHECK_EQ(url_request_.get(), request); |
| 322 DCHECK_NE(ERR_IO_PENDING, net_error); | 450 DCHECK_NE(ERR_IO_PENDING, net_error); |
| 323 | 451 |
| 324 if (net_error != OK) { | 452 if (net_error != OK) { |
| 325 OnUrlRequestCompleted(net_error); | 453 OnUrlRequestCompleted(net_error); |
| 326 return; | 454 return; |
| 327 } | 455 } |
| 328 | 456 |
| 329 if (request->GetResponseCode() != 200) { | 457 if (request->GetResponseCode() != 200) { |
| 330 // TODO(eroman): Use a more specific error code. | 458 // TODO(eroman): Use a more specific error code. |
| 331 FailRequest(ERR_FAILED); | 459 FailRequest(ERR_FAILED); |
| 332 return; | 460 return; |
| 333 } | 461 } |
| 334 | 462 |
| 335 ReadBody(request); | 463 ReadBody(request); |
| 336 } | 464 } |
| 337 | 465 |
| 338 void CertNetFetcherImpl::Job::OnReadCompleted(URLRequest* request, | 466 void Job::OnReadCompleted(URLRequest* request, int bytes_read) { |
| 339 int bytes_read) { | |
| 340 DCHECK_EQ(url_request_.get(), request); | 467 DCHECK_EQ(url_request_.get(), request); |
| 341 DCHECK_NE(ERR_IO_PENDING, bytes_read); | 468 DCHECK_NE(ERR_IO_PENDING, bytes_read); |
| 342 | 469 |
| 343 // Keep reading the response body. | 470 // Keep reading the response body. |
| 344 if (ConsumeBytesRead(request, bytes_read)) | 471 if (ConsumeBytesRead(request, bytes_read)) |
| 345 ReadBody(request); | 472 ReadBody(request); |
| 346 } | 473 } |
| 347 | 474 |
| 348 void CertNetFetcherImpl::Job::Stop() { | 475 void Job::Stop() { |
| 349 timer_.Stop(); | 476 timer_.Stop(); |
| 350 url_request_.reset(); | 477 url_request_.reset(); |
| 351 } | 478 } |
| 352 | 479 |
| 353 void CertNetFetcherImpl::Job::ReadBody(URLRequest* request) { | 480 void Job::ReadBody(URLRequest* request) { |
| 354 // Read as many bytes as are available synchronously. | 481 // Read as many bytes as are available synchronously. |
| 355 int num_bytes = 0; | 482 int num_bytes = 0; |
| 356 while (num_bytes >= 0) { | 483 while (num_bytes >= 0) { |
| 357 num_bytes = request->Read(read_buffer_.get(), kReadBufferSizeInBytes); | 484 num_bytes = request->Read(read_buffer_.get(), kReadBufferSizeInBytes); |
| 358 if (num_bytes == ERR_IO_PENDING) | 485 if (num_bytes == ERR_IO_PENDING) |
| 359 return; | 486 return; |
| 360 if (!ConsumeBytesRead(request, num_bytes)) | 487 if (!ConsumeBytesRead(request, num_bytes)) |
| 361 return; | 488 return; |
| 362 } | 489 } |
| 363 | 490 |
| 364 OnUrlRequestCompleted(num_bytes); | 491 OnUrlRequestCompleted(num_bytes); |
| 365 } | 492 } |
| 366 | 493 |
| 367 bool CertNetFetcherImpl::Job::ConsumeBytesRead(URLRequest* request, | 494 bool Job::ConsumeBytesRead(URLRequest* request, int num_bytes) { |
| 368 int num_bytes) { | |
| 369 DCHECK_NE(ERR_IO_PENDING, num_bytes); | 495 DCHECK_NE(ERR_IO_PENDING, num_bytes); |
| 370 if (num_bytes <= 0) { | 496 if (num_bytes <= 0) { |
| 371 // Error while reading, or EOF. | 497 // Error while reading, or EOF. |
| 372 OnUrlRequestCompleted(num_bytes); | 498 OnUrlRequestCompleted(num_bytes); |
| 373 return false; | 499 return false; |
| 374 } | 500 } |
| 375 | 501 |
| 376 // Enforce maximum size bound. | 502 // Enforce maximum size bound. |
| 377 if (num_bytes + response_body_.size() > request_params_->max_response_bytes) { | 503 if (num_bytes + response_body_.size() > request_params_->max_response_bytes) { |
| 378 FailRequest(ERR_FILE_TOO_BIG); | 504 FailRequest(ERR_FILE_TOO_BIG); |
| 379 return false; | 505 return false; |
| 380 } | 506 } |
| 381 | 507 |
| 382 // Append the data to |response_body_|. | 508 // Append the data to |response_body_|. |
| 383 response_body_.reserve(num_bytes); | 509 response_body_.reserve(num_bytes); |
| 384 response_body_.insert(response_body_.end(), read_buffer_->data(), | 510 response_body_.insert(response_body_.end(), read_buffer_->data(), |
| 385 read_buffer_->data() + num_bytes); | 511 read_buffer_->data() + num_bytes); |
| 386 return true; | 512 return true; |
| 387 } | 513 } |
| 388 | 514 |
| 389 void CertNetFetcherImpl::Job::OnUrlRequestCompleted(int net_error) { | 515 void Job::OnUrlRequestCompleted(int net_error) { |
| 390 DCHECK_NE(ERR_IO_PENDING, net_error); | 516 DCHECK_NE(ERR_IO_PENDING, net_error); |
| 391 Error result = static_cast<Error>(net_error); | 517 Error result = static_cast<Error>(net_error); |
| 392 OnJobCompleted(result); | 518 OnJobCompleted(result); |
| 393 } | 519 } |
| 394 | 520 |
| 395 void CertNetFetcherImpl::Job::OnJobCompleted(Error error) { | 521 void Job::OnJobCompleted(Error error) { |
| 396 DCHECK_NE(ERR_IO_PENDING, error); | 522 DCHECK_NE(ERR_IO_PENDING, error); |
| 397 // Stop the timer and clear the URLRequest. | 523 // Stop the timer and clear the URLRequest. |
| 398 Stop(); | 524 Stop(); |
| 399 | 525 |
| 400 // Invoking the callbacks is subtle as state may be mutated while iterating | 526 std::unique_ptr<Job> delete_this = parent_->RemoveJob(this); |
| 401 // through the callbacks: | |
| 402 // | |
| 403 // * The parent CertNetFetcherImpl may be deleted | |
| 404 // * Requests in this job may be cancelled | |
| 405 | 527 |
| 406 std::unique_ptr<Job> delete_this = parent_->RemoveJob(this); | 528 for (auto* request : requests_) { |
| 407 parent_->SetCurrentlyCompletingJob(this); | 529 request->OnJobCompleted(this, error, response_body_); |
| 408 | |
| 409 while (!requests_.empty()) { | |
| 410 base::LinkNode<RequestImpl>* request = requests_.head(); | |
| 411 request->RemoveFromList(); | |
| 412 request->value()->OnJobCompleted(this, error, response_body_); | |
| 413 } | 530 } |
| 414 | 531 |
| 415 if (parent_) | 532 requests_.clear(); |
| 416 parent_->ClearCurrentlyCompletingJob(this); | |
| 417 } | 533 } |
| 418 | 534 |
| 419 void CertNetFetcherImpl::Job::FailRequest(Error error) { | 535 void Job::FailRequest(Error error) { |
| 420 DCHECK_NE(ERR_IO_PENDING, error); | 536 DCHECK_NE(ERR_IO_PENDING, error); |
| 421 int result = url_request_->CancelWithError(error); | 537 int result = url_request_->CancelWithError(error); |
| 422 OnUrlRequestCompleted(result); | 538 OnUrlRequestCompleted(result); |
| 423 } | 539 } |
| 424 | 540 |
| 425 CertNetFetcherImpl::CertNetFetcherImpl(URLRequestContext* context) | 541 AsyncCertNetFetcherImpl::AsyncCertNetFetcherImpl(URLRequestContext* context) |
| 426 : currently_completing_job_(nullptr), context_(context) { | 542 : context_(context) { |
| 543 // Allow creation to happen from another thread. |
| 544 thread_checker_.DetachFromThread(); |
| 427 } | 545 } |
| 428 | 546 |
| 429 CertNetFetcherImpl::~CertNetFetcherImpl() { | 547 AsyncCertNetFetcherImpl::~AsyncCertNetFetcherImpl() { |
| 548 DCHECK(thread_checker_.CalledOnValidThread()); |
| 430 jobs_.clear(); | 549 jobs_.clear(); |
| 431 | |
| 432 // The CertNetFetcherImpl was destroyed in a FetchCallback. Detach all | |
| 433 // remaining requests from the job so no further callbacks are called. | |
| 434 if (currently_completing_job_) | |
| 435 currently_completing_job_->Cancel(); | |
| 436 } | 550 } |
| 437 | 551 |
| 438 std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchCaIssuers( | 552 bool JobComparator::operator()(const Job* job1, const Job* job2) const { |
| 439 const GURL& url, | |
| 440 int timeout_milliseconds, | |
| 441 int max_response_bytes, | |
| 442 const FetchCallback& callback) { | |
| 443 std::unique_ptr<RequestParams> request_params(new RequestParams); | |
| 444 | |
| 445 request_params->url = url; | |
| 446 request_params->http_method = HTTP_METHOD_GET; | |
| 447 request_params->timeout = GetTimeout(timeout_milliseconds); | |
| 448 request_params->max_response_bytes = | |
| 449 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); | |
| 450 | |
| 451 return Fetch(std::move(request_params), callback); | |
| 452 } | |
| 453 | |
| 454 std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchCrl( | |
| 455 const GURL& url, | |
| 456 int timeout_milliseconds, | |
| 457 int max_response_bytes, | |
| 458 const FetchCallback& callback) { | |
| 459 std::unique_ptr<RequestParams> request_params(new RequestParams); | |
| 460 | |
| 461 request_params->url = url; | |
| 462 request_params->http_method = HTTP_METHOD_GET; | |
| 463 request_params->timeout = GetTimeout(timeout_milliseconds); | |
| 464 request_params->max_response_bytes = | |
| 465 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForCrl); | |
| 466 | |
| 467 return Fetch(std::move(request_params), callback); | |
| 468 } | |
| 469 | |
| 470 std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchOcsp( | |
| 471 const GURL& url, | |
| 472 int timeout_milliseconds, | |
| 473 int max_response_bytes, | |
| 474 const FetchCallback& callback) { | |
| 475 std::unique_ptr<RequestParams> request_params(new RequestParams); | |
| 476 | |
| 477 request_params->url = url; | |
| 478 request_params->http_method = HTTP_METHOD_GET; | |
| 479 request_params->timeout = GetTimeout(timeout_milliseconds); | |
| 480 request_params->max_response_bytes = | |
| 481 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); | |
| 482 | |
| 483 return Fetch(std::move(request_params), callback); | |
| 484 } | |
| 485 | |
| 486 bool CertNetFetcherImpl::JobComparator::operator()(const Job* job1, | |
| 487 const Job* job2) const { | |
| 488 return job1->request_params() < job2->request_params(); | 553 return job1->request_params() < job2->request_params(); |
| 489 } | 554 } |
| 490 | 555 |
| 491 std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::Fetch( | 556 void AsyncCertNetFetcherImpl::Fetch( |
| 492 std::unique_ptr<RequestParams> request_params, | 557 std::unique_ptr<RequestParams> request_params, |
| 493 const FetchCallback& callback) { | 558 RequestCore* request) { |
| 494 DCHECK(thread_checker_.CalledOnValidThread()); | 559 DCHECK(thread_checker_.CalledOnValidThread()); |
| 495 | 560 |
| 496 // If there is an in-progress job that matches the request parameters use it. | 561 // If there is an in-progress job that matches the request parameters use it. |
| 497 // Otherwise start a new job. | 562 // Otherwise start a new job. |
| 498 Job* job = FindJob(*request_params); | 563 Job* job = FindJob(*request_params); |
| 499 | 564 |
| 500 if (!job) { | 565 if (!job) { |
| 501 job = new Job(std::move(request_params), this); | 566 job = new Job(std::move(request_params), this); |
| 502 jobs_[job] = base::WrapUnique(job); | 567 jobs_[job] = base::WrapUnique(job); |
| 503 job->StartURLRequest(context_); | 568 job->StartURLRequest(context_); |
| 504 } | 569 } |
| 505 | 570 |
| 506 return job->CreateRequest(callback); | 571 return job->AttachRequest(request); |
| 507 } | 572 } |
| 508 | 573 |
| 509 struct CertNetFetcherImpl::JobToRequestParamsComparator { | 574 struct JobToRequestParamsComparator { |
| 510 bool operator()(const CertNetFetcherImpl::JobSet::value_type& job, | 575 bool operator()(const JobSet::value_type& job, |
| 511 const CertNetFetcherImpl::RequestParams& value) const { | 576 const RequestParams& value) const { |
| 512 return job.first->request_params() < value; | 577 return job.first->request_params() < value; |
| 513 } | 578 } |
| 514 }; | 579 }; |
| 515 | 580 |
| 516 CertNetFetcherImpl::Job* CertNetFetcherImpl::FindJob( | 581 Job* AsyncCertNetFetcherImpl::FindJob(const RequestParams& params) { |
| 517 const RequestParams& params) { | |
| 518 DCHECK(thread_checker_.CalledOnValidThread()); | 582 DCHECK(thread_checker_.CalledOnValidThread()); |
| 519 | 583 |
| 520 // The JobSet is kept in sorted order so items can be found using binary | 584 // The JobSet is kept in sorted order so items can be found using binary |
| 521 // search. | 585 // search. |
| 522 JobSet::iterator it = std::lower_bound(jobs_.begin(), jobs_.end(), params, | 586 JobSet::iterator it = std::lower_bound(jobs_.begin(), jobs_.end(), params, |
| 523 JobToRequestParamsComparator()); | 587 JobToRequestParamsComparator()); |
| 524 if (it != jobs_.end() && !(params < (*it).first->request_params())) | 588 if (it != jobs_.end() && !(params < (*it).first->request_params())) |
| 525 return (*it).first; | 589 return (*it).first; |
| 526 return nullptr; | 590 return nullptr; |
| 527 } | 591 } |
| 528 | 592 |
| 529 std::unique_ptr<CertNetFetcherImpl::Job> CertNetFetcherImpl::RemoveJob( | 593 std::unique_ptr<Job> AsyncCertNetFetcherImpl::RemoveJob(Job* job) { |
| 530 Job* job) { | |
| 531 DCHECK(thread_checker_.CalledOnValidThread()); | 594 DCHECK(thread_checker_.CalledOnValidThread()); |
| 532 auto it = jobs_.find(job); | 595 auto it = jobs_.find(job); |
| 533 CHECK(it != jobs_.end()); | 596 CHECK(it != jobs_.end()); |
| 534 std::unique_ptr<Job> owned_job = std::move(it->second); | 597 std::unique_ptr<Job> owned_job = std::move(it->second); |
| 535 jobs_.erase(it); | 598 jobs_.erase(it); |
| 536 return owned_job; | 599 return owned_job; |
| 537 } | 600 } |
| 538 | 601 |
| 539 void CertNetFetcherImpl::SetCurrentlyCompletingJob(Job* job) { | 602 class CertNetFetcherRequestImpl : public CertNetFetcher::Request { |
| 540 DCHECK(!currently_completing_job_); | 603 public: |
| 541 DCHECK(job); | 604 explicit CertNetFetcherRequestImpl(scoped_refptr<RequestCore> core) |
| 542 currently_completing_job_ = job; | 605 : core_(std::move(core)) { |
| 543 } | 606 DCHECK(core_); |
| 607 } |
| 544 | 608 |
| 545 void CertNetFetcherImpl::ClearCurrentlyCompletingJob(Job* job) { | 609 void WaitForResult(Error* error, std::vector<uint8_t>* bytes) override { |
| 546 DCHECK_EQ(currently_completing_job_, job); | 610 // Should only be called a single time. |
| 547 currently_completing_job_ = nullptr; | 611 DCHECK(core_); |
| 548 } | 612 core_->WaitForResult(error, bytes); |
| 613 core_ = nullptr; |
| 614 } |
| 549 | 615 |
| 550 bool CertNetFetcherImpl::IsCurrentlyCompletingJob(Job* job) { | 616 ~CertNetFetcherRequestImpl() override { |
| 551 return job == currently_completing_job_; | 617 if (core_) |
| 618 core_->Cancel(); |
| 619 } |
| 620 |
| 621 private: |
| 622 scoped_refptr<RequestCore> core_; |
| 623 }; |
| 624 |
| 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 { |
| 673 public: |
| 674 explicit CertNetFetcherImpl(URLRequestContextGetter* context_getter) |
| 675 : core_(new CertNetFetcherCore(context_getter)) {} |
| 676 |
| 677 ~CertNetFetcherImpl() override { core_->Abandon(); } |
| 678 |
| 679 std::unique_ptr<Request> FetchCaIssuers(const GURL& url, |
| 680 int timeout_milliseconds, |
| 681 int max_response_bytes) override { |
| 682 std::unique_ptr<RequestParams> request_params(new RequestParams); |
| 683 |
| 684 request_params->url = url; |
| 685 request_params->http_method = HTTP_METHOD_GET; |
| 686 request_params->timeout = GetTimeout(timeout_milliseconds); |
| 687 request_params->max_response_bytes = |
| 688 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); |
| 689 |
| 690 return DoFetch(std::move(request_params)); |
| 691 } |
| 692 |
| 693 std::unique_ptr<Request> FetchCrl(const GURL& url, |
| 694 int timeout_milliseconds, |
| 695 int max_response_bytes) override { |
| 696 std::unique_ptr<RequestParams> request_params(new RequestParams); |
| 697 |
| 698 request_params->url = url; |
| 699 request_params->http_method = HTTP_METHOD_GET; |
| 700 request_params->timeout = GetTimeout(timeout_milliseconds); |
| 701 request_params->max_response_bytes = |
| 702 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForCrl); |
| 703 |
| 704 return DoFetch(std::move(request_params)); |
| 705 } |
| 706 |
| 707 WARN_UNUSED_RESULT std::unique_ptr<Request> FetchOcsp( |
| 708 const GURL& url, |
| 709 int timeout_milliseconds, |
| 710 int max_response_bytes) override { |
| 711 std::unique_ptr<RequestParams> request_params(new RequestParams); |
| 712 |
| 713 request_params->url = url; |
| 714 request_params->http_method = HTTP_METHOD_GET; |
| 715 request_params->timeout = GetTimeout(timeout_milliseconds); |
| 716 request_params->max_response_bytes = |
| 717 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); |
| 718 |
| 719 return DoFetch(std::move(request_params)); |
| 720 } |
| 721 |
| 722 private: |
| 723 std::unique_ptr<Request> DoFetch( |
| 724 std::unique_ptr<RequestParams> request_params) { |
| 725 auto task_runner = core_->GetNetworkTaskRunner(); |
| 726 scoped_refptr<RequestCore> request_core = new RequestCore(task_runner); |
| 727 |
| 728 task_runner->PostTask( |
| 729 FROM_HERE, |
| 730 base::Bind(&CertNetFetcherCore::DoFetchOnNetworkThread, core_, |
| 731 base::Passed(&request_params), request_core)); |
| 732 |
| 733 return base::MakeUnique<CertNetFetcherRequestImpl>(std::move(request_core)); |
| 734 } |
| 735 |
| 736 private: |
| 737 scoped_refptr<CertNetFetcherCore> core_; |
| 738 }; |
| 739 |
| 740 } // namespace |
| 741 |
| 742 std::unique_ptr<CertNetFetcher> CreateCertNetFetcher( |
| 743 URLRequestContextGetter* context_getter) { |
| 744 return base::MakeUnique<CertNetFetcherImpl>(context_getter); |
| 552 } | 745 } |
| 553 | 746 |
| 554 } // namespace net | 747 } // namespace net |
| OLD | NEW |