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