| 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 #include "net/cert_net/cert_net_fetcher_impl.h" | 5 #include "net/cert_net/cert_net_fetcher_impl.h" |
| 6 | 6 |
| 7 #include <tuple> | 7 #include <tuple> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| 11 #include "base/containers/linked_list.h" | 11 #include "base/containers/linked_list.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/memory/ptr_util.h" |
| 14 #include "base/numerics/safe_math.h" | 15 #include "base/numerics/safe_math.h" |
| 15 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
| 16 #include "base/timer/timer.h" | 17 #include "base/timer/timer.h" |
| 17 #include "net/base/load_flags.h" | 18 #include "net/base/load_flags.h" |
| 18 #include "net/url_request/redirect_info.h" | 19 #include "net/url_request/redirect_info.h" |
| 19 #include "net/url_request/url_request_context.h" | 20 #include "net/url_request/url_request_context.h" |
| 20 | 21 |
| 21 // TODO(eroman): Add support for POST parameters. | 22 // TODO(eroman): Add support for POST parameters. |
| 22 // TODO(eroman): Add controls for bypassing the cache. | 23 // TODO(eroman): Add controls for bypassing the cache. |
| 23 // TODO(eroman): Add a maximum number of in-flight jobs/requests. | 24 // TODO(eroman): Add a maximum number of in-flight jobs/requests. |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 const RequestParams& other) const { | 140 const RequestParams& other) const { |
| 140 return std::tie(url, http_method, max_response_bytes, timeout) < | 141 return std::tie(url, http_method, max_response_bytes, timeout) < |
| 141 std::tie(other.url, other.http_method, other.max_response_bytes, | 142 std::tie(other.url, other.http_method, other.max_response_bytes, |
| 142 other.timeout); | 143 other.timeout); |
| 143 } | 144 } |
| 144 | 145 |
| 145 // CertNetFetcherImpl::Job tracks an outstanding URLRequest as well as all of | 146 // CertNetFetcherImpl::Job tracks an outstanding URLRequest as well as all of |
| 146 // the pending requests for it. | 147 // the pending requests for it. |
| 147 class CertNetFetcherImpl::Job : public URLRequest::Delegate { | 148 class CertNetFetcherImpl::Job : public URLRequest::Delegate { |
| 148 public: | 149 public: |
| 149 Job(scoped_ptr<RequestParams> request_params, CertNetFetcherImpl* parent); | 150 Job(std::unique_ptr<RequestParams> request_params, |
| 151 CertNetFetcherImpl* parent); |
| 150 ~Job() override; | 152 ~Job() override; |
| 151 | 153 |
| 152 // Cancels the job and all requests attached to it. No callbacks will be | 154 // Cancels the job and all requests attached to it. No callbacks will be |
| 153 // invoked following cancellation. | 155 // invoked following cancellation. |
| 154 void Cancel(); | 156 void Cancel(); |
| 155 | 157 |
| 156 const RequestParams& request_params() const { return *request_params_; } | 158 const RequestParams& request_params() const { return *request_params_; } |
| 157 | 159 |
| 158 // Create a request and attaches it to the job. When the job completes it will | 160 // Create a request and attaches it to the job. When the job completes it will |
| 159 // notify the request of completion through OnJobCompleted. Note that the Job | 161 // notify the request of completion through OnJobCompleted. Note that the Job |
| 160 // does NOT own the request. | 162 // does NOT own the request. |
| 161 scoped_ptr<Request> CreateRequest(const FetchCallback& callback); | 163 std::unique_ptr<Request> CreateRequest(const FetchCallback& callback); |
| 162 | 164 |
| 163 // Removes |request| from the job. | 165 // Removes |request| from the job. |
| 164 void DetachRequest(RequestImpl* request); | 166 void DetachRequest(RequestImpl* request); |
| 165 | 167 |
| 166 // Creates and starts a URLRequest for the job. After the request has | 168 // Creates and starts a URLRequest for the job. After the request has |
| 167 // completed, OnJobCompleted() will be invoked and all the registered requests | 169 // completed, OnJobCompleted() will be invoked and all the registered requests |
| 168 // notified of completion. | 170 // notified of completion. |
| 169 void StartURLRequest(URLRequestContext* context); | 171 void StartURLRequest(URLRequestContext* context); |
| 170 | 172 |
| 171 private: | 173 private: |
| (...skipping 27 matching lines...) Expand all Loading... |
| 199 // Called when the Job has completed. The job may finish in response to a | 201 // Called when the Job has completed. The job may finish in response to a |
| 200 // timeout, an invalid URL, or the URLRequest completing. By the time this | 202 // timeout, an invalid URL, or the URLRequest completing. By the time this |
| 201 // method is called, the response variables have been assigned | 203 // method is called, the response variables have been assigned |
| 202 // (result_net_error_ and response_body_). | 204 // (result_net_error_ and response_body_). |
| 203 void OnJobCompleted(); | 205 void OnJobCompleted(); |
| 204 | 206 |
| 205 // The requests attached to this job. | 207 // The requests attached to this job. |
| 206 RequestList requests_; | 208 RequestList requests_; |
| 207 | 209 |
| 208 // The input parameters for starting a URLRequest. | 210 // The input parameters for starting a URLRequest. |
| 209 scoped_ptr<RequestParams> request_params_; | 211 std::unique_ptr<RequestParams> request_params_; |
| 210 | 212 |
| 211 // The URLRequest response information. | 213 // The URLRequest response information. |
| 212 std::vector<uint8_t> response_body_; | 214 std::vector<uint8_t> response_body_; |
| 213 Error result_net_error_; | 215 Error result_net_error_; |
| 214 | 216 |
| 215 scoped_ptr<URLRequest> url_request_; | 217 std::unique_ptr<URLRequest> url_request_; |
| 216 scoped_refptr<IOBuffer> read_buffer_; | 218 scoped_refptr<IOBuffer> read_buffer_; |
| 217 | 219 |
| 218 // Used to timeout the job when the URLRequest takes too long. This timer is | 220 // 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. | 221 // also used for notifying a failure to start the URLRequest. |
| 220 base::OneShotTimer timer_; | 222 base::OneShotTimer timer_; |
| 221 | 223 |
| 222 // Non-owned pointer to the CertNetFetcherImpl that created this job. | 224 // Non-owned pointer to the CertNetFetcherImpl that created this job. |
| 223 CertNetFetcherImpl* parent_; | 225 CertNetFetcherImpl* parent_; |
| 224 | 226 |
| 225 DISALLOW_COPY_AND_ASSIGN(Job); | 227 DISALLOW_COPY_AND_ASSIGN(Job); |
| 226 }; | 228 }; |
| 227 | 229 |
| 228 CertNetFetcherImpl::RequestImpl::~RequestImpl() { | 230 CertNetFetcherImpl::RequestImpl::~RequestImpl() { |
| 229 if (job_) | 231 if (job_) |
| 230 job_->DetachRequest(this); | 232 job_->DetachRequest(this); |
| 231 } | 233 } |
| 232 | 234 |
| 233 CertNetFetcherImpl::Job::Job(scoped_ptr<RequestParams> request_params, | 235 CertNetFetcherImpl::Job::Job(std::unique_ptr<RequestParams> request_params, |
| 234 CertNetFetcherImpl* parent) | 236 CertNetFetcherImpl* parent) |
| 235 : request_params_(std::move(request_params)), | 237 : request_params_(std::move(request_params)), |
| 236 result_net_error_(ERR_IO_PENDING), | 238 result_net_error_(ERR_IO_PENDING), |
| 237 parent_(parent) {} | 239 parent_(parent) {} |
| 238 | 240 |
| 239 CertNetFetcherImpl::Job::~Job() { | 241 CertNetFetcherImpl::Job::~Job() { |
| 240 Cancel(); | 242 Cancel(); |
| 241 } | 243 } |
| 242 | 244 |
| 243 void CertNetFetcherImpl::Job::Cancel() { | 245 void CertNetFetcherImpl::Job::Cancel() { |
| 244 parent_ = nullptr; | 246 parent_ = nullptr; |
| 245 | 247 |
| 246 // Notify each request of cancellation and remove it from the list. | 248 // Notify each request of cancellation and remove it from the list. |
| 247 for (base::LinkNode<RequestImpl>* current = requests_.head(); | 249 for (base::LinkNode<RequestImpl>* current = requests_.head(); |
| 248 current != requests_.end();) { | 250 current != requests_.end();) { |
| 249 base::LinkNode<RequestImpl>* next = current->next(); | 251 base::LinkNode<RequestImpl>* next = current->next(); |
| 250 current->value()->OnJobCancelled(this); | 252 current->value()->OnJobCancelled(this); |
| 251 current->RemoveFromList(); | 253 current->RemoveFromList(); |
| 252 current = next; | 254 current = next; |
| 253 } | 255 } |
| 254 | 256 |
| 255 DCHECK(requests_.empty()); | 257 DCHECK(requests_.empty()); |
| 256 | 258 |
| 257 Stop(); | 259 Stop(); |
| 258 } | 260 } |
| 259 | 261 |
| 260 scoped_ptr<CertNetFetcher::Request> CertNetFetcherImpl::Job::CreateRequest( | 262 std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::Job::CreateRequest( |
| 261 const FetchCallback& callback) { | 263 const FetchCallback& callback) { |
| 262 scoped_ptr<RequestImpl> request(new RequestImpl(this, callback)); | 264 std::unique_ptr<RequestImpl> request(new RequestImpl(this, callback)); |
| 263 requests_.Append(request.get()); | 265 requests_.Append(request.get()); |
| 264 return std::move(request); | 266 return std::move(request); |
| 265 } | 267 } |
| 266 | 268 |
| 267 void CertNetFetcherImpl::Job::DetachRequest(RequestImpl* request) { | 269 void CertNetFetcherImpl::Job::DetachRequest(RequestImpl* request) { |
| 268 scoped_ptr<Job> delete_this; | 270 std::unique_ptr<Job> delete_this; |
| 269 | 271 |
| 270 request->RemoveFromList(); | 272 request->RemoveFromList(); |
| 271 | 273 |
| 272 // If there are no longer any requests attached to the job then | 274 // If there are no longer any requests attached to the job then |
| 273 // cancel and delete it. | 275 // cancel and delete it. |
| 274 if (requests_.empty() && !parent_->IsCurrentlyCompletingJob(this)) | 276 if (requests_.empty() && !parent_->IsCurrentlyCompletingJob(this)) |
| 275 delete_this = parent_->RemoveJob(this); | 277 delete_this = parent_->RemoveJob(this); |
| 276 } | 278 } |
| 277 | 279 |
| 278 void CertNetFetcherImpl::Job::StartURLRequest(URLRequestContext* context) { | 280 void CertNetFetcherImpl::Job::StartURLRequest(URLRequestContext* context) { |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 404 void CertNetFetcherImpl::Job::OnJobCompleted() { | 406 void CertNetFetcherImpl::Job::OnJobCompleted() { |
| 405 // Stop the timer and clear the URLRequest. | 407 // Stop the timer and clear the URLRequest. |
| 406 Stop(); | 408 Stop(); |
| 407 | 409 |
| 408 // Invoking the callbacks is subtle as state may be mutated while iterating | 410 // Invoking the callbacks is subtle as state may be mutated while iterating |
| 409 // through the callbacks: | 411 // through the callbacks: |
| 410 // | 412 // |
| 411 // * The parent CertNetFetcherImpl may be deleted | 413 // * The parent CertNetFetcherImpl may be deleted |
| 412 // * Requests in this job may be cancelled | 414 // * Requests in this job may be cancelled |
| 413 | 415 |
| 414 scoped_ptr<Job> delete_this = parent_->RemoveJob(this); | 416 std::unique_ptr<Job> delete_this = parent_->RemoveJob(this); |
| 415 parent_->SetCurrentlyCompletingJob(this); | 417 parent_->SetCurrentlyCompletingJob(this); |
| 416 | 418 |
| 417 while (!requests_.empty()) { | 419 while (!requests_.empty()) { |
| 418 base::LinkNode<RequestImpl>* request = requests_.head(); | 420 base::LinkNode<RequestImpl>* request = requests_.head(); |
| 419 request->RemoveFromList(); | 421 request->RemoveFromList(); |
| 420 request->value()->OnJobCompleted(this, result_net_error_, response_body_); | 422 request->value()->OnJobCompleted(this, result_net_error_, response_body_); |
| 421 } | 423 } |
| 422 | 424 |
| 423 if (parent_) | 425 if (parent_) |
| 424 parent_->ClearCurrentlyCompletingJob(this); | 426 parent_->ClearCurrentlyCompletingJob(this); |
| 425 } | 427 } |
| 426 | 428 |
| 427 CertNetFetcherImpl::CertNetFetcherImpl(URLRequestContext* context) | 429 CertNetFetcherImpl::CertNetFetcherImpl(URLRequestContext* context) |
| 428 : currently_completing_job_(nullptr), context_(context) { | 430 : currently_completing_job_(nullptr), context_(context) { |
| 429 } | 431 } |
| 430 | 432 |
| 431 CertNetFetcherImpl::~CertNetFetcherImpl() { | 433 CertNetFetcherImpl::~CertNetFetcherImpl() { |
| 432 STLDeleteElements(&jobs_); | 434 STLDeleteElements(&jobs_); |
| 433 | 435 |
| 434 // The CertNetFetcherImpl was destroyed in a FetchCallback. Detach all | 436 // The CertNetFetcherImpl was destroyed in a FetchCallback. Detach all |
| 435 // remaining requests from the job so no further callbacks are called. | 437 // remaining requests from the job so no further callbacks are called. |
| 436 if (currently_completing_job_) | 438 if (currently_completing_job_) |
| 437 currently_completing_job_->Cancel(); | 439 currently_completing_job_->Cancel(); |
| 438 } | 440 } |
| 439 | 441 |
| 440 scoped_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchCaIssuers( | 442 std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchCaIssuers( |
| 441 const GURL& url, | 443 const GURL& url, |
| 442 int timeout_milliseconds, | 444 int timeout_milliseconds, |
| 443 int max_response_bytes, | 445 int max_response_bytes, |
| 444 const FetchCallback& callback) { | 446 const FetchCallback& callback) { |
| 445 scoped_ptr<RequestParams> request_params(new RequestParams); | 447 std::unique_ptr<RequestParams> request_params(new RequestParams); |
| 446 | 448 |
| 447 request_params->url = url; | 449 request_params->url = url; |
| 448 request_params->http_method = HTTP_METHOD_GET; | 450 request_params->http_method = HTTP_METHOD_GET; |
| 449 request_params->timeout = GetTimeout(timeout_milliseconds); | 451 request_params->timeout = GetTimeout(timeout_milliseconds); |
| 450 request_params->max_response_bytes = | 452 request_params->max_response_bytes = |
| 451 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); | 453 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); |
| 452 | 454 |
| 453 return Fetch(std::move(request_params), callback); | 455 return Fetch(std::move(request_params), callback); |
| 454 } | 456 } |
| 455 | 457 |
| 456 scoped_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchCrl( | 458 std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchCrl( |
| 457 const GURL& url, | 459 const GURL& url, |
| 458 int timeout_milliseconds, | 460 int timeout_milliseconds, |
| 459 int max_response_bytes, | 461 int max_response_bytes, |
| 460 const FetchCallback& callback) { | 462 const FetchCallback& callback) { |
| 461 scoped_ptr<RequestParams> request_params(new RequestParams); | 463 std::unique_ptr<RequestParams> request_params(new RequestParams); |
| 462 | 464 |
| 463 request_params->url = url; | 465 request_params->url = url; |
| 464 request_params->http_method = HTTP_METHOD_GET; | 466 request_params->http_method = HTTP_METHOD_GET; |
| 465 request_params->timeout = GetTimeout(timeout_milliseconds); | 467 request_params->timeout = GetTimeout(timeout_milliseconds); |
| 466 request_params->max_response_bytes = | 468 request_params->max_response_bytes = |
| 467 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForCrl); | 469 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForCrl); |
| 468 | 470 |
| 469 return Fetch(std::move(request_params), callback); | 471 return Fetch(std::move(request_params), callback); |
| 470 } | 472 } |
| 471 | 473 |
| 472 scoped_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchOcsp( | 474 std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchOcsp( |
| 473 const GURL& url, | 475 const GURL& url, |
| 474 int timeout_milliseconds, | 476 int timeout_milliseconds, |
| 475 int max_response_bytes, | 477 int max_response_bytes, |
| 476 const FetchCallback& callback) { | 478 const FetchCallback& callback) { |
| 477 scoped_ptr<RequestParams> request_params(new RequestParams); | 479 std::unique_ptr<RequestParams> request_params(new RequestParams); |
| 478 | 480 |
| 479 request_params->url = url; | 481 request_params->url = url; |
| 480 request_params->http_method = HTTP_METHOD_GET; | 482 request_params->http_method = HTTP_METHOD_GET; |
| 481 request_params->timeout = GetTimeout(timeout_milliseconds); | 483 request_params->timeout = GetTimeout(timeout_milliseconds); |
| 482 request_params->max_response_bytes = | 484 request_params->max_response_bytes = |
| 483 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); | 485 GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); |
| 484 | 486 |
| 485 return Fetch(std::move(request_params), callback); | 487 return Fetch(std::move(request_params), callback); |
| 486 } | 488 } |
| 487 | 489 |
| 488 bool CertNetFetcherImpl::JobComparator::operator()(const Job* job1, | 490 bool CertNetFetcherImpl::JobComparator::operator()(const Job* job1, |
| 489 const Job* job2) const { | 491 const Job* job2) const { |
| 490 return job1->request_params() < job2->request_params(); | 492 return job1->request_params() < job2->request_params(); |
| 491 } | 493 } |
| 492 | 494 |
| 493 scoped_ptr<CertNetFetcher::Request> CertNetFetcherImpl::Fetch( | 495 std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::Fetch( |
| 494 scoped_ptr<RequestParams> request_params, | 496 std::unique_ptr<RequestParams> request_params, |
| 495 const FetchCallback& callback) { | 497 const FetchCallback& callback) { |
| 496 DCHECK(thread_checker_.CalledOnValidThread()); | 498 DCHECK(thread_checker_.CalledOnValidThread()); |
| 497 | 499 |
| 498 // If there is an in-progress job that matches the request parameters use it. | 500 // If there is an in-progress job that matches the request parameters use it. |
| 499 // Otherwise start a new job. | 501 // Otherwise start a new job. |
| 500 Job* job = FindJob(*request_params); | 502 Job* job = FindJob(*request_params); |
| 501 | 503 |
| 502 if (!job) { | 504 if (!job) { |
| 503 job = new Job(std::move(request_params), this); | 505 job = new Job(std::move(request_params), this); |
| 504 jobs_.insert(job); | 506 jobs_.insert(job); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 521 | 523 |
| 522 // The JobSet is kept in sorted order so items can be found using binary | 524 // The JobSet is kept in sorted order so items can be found using binary |
| 523 // search. | 525 // search. |
| 524 JobSet::iterator it = std::lower_bound(jobs_.begin(), jobs_.end(), params, | 526 JobSet::iterator it = std::lower_bound(jobs_.begin(), jobs_.end(), params, |
| 525 JobToRequestParamsComparator()); | 527 JobToRequestParamsComparator()); |
| 526 if (it != jobs_.end() && !(params < (*it)->request_params())) | 528 if (it != jobs_.end() && !(params < (*it)->request_params())) |
| 527 return *it; | 529 return *it; |
| 528 return nullptr; | 530 return nullptr; |
| 529 } | 531 } |
| 530 | 532 |
| 531 scoped_ptr<CertNetFetcherImpl::Job> CertNetFetcherImpl::RemoveJob(Job* job) { | 533 std::unique_ptr<CertNetFetcherImpl::Job> CertNetFetcherImpl::RemoveJob( |
| 534 Job* job) { |
| 532 DCHECK(thread_checker_.CalledOnValidThread()); | 535 DCHECK(thread_checker_.CalledOnValidThread()); |
| 533 bool erased_job = jobs_.erase(job) == 1; | 536 bool erased_job = jobs_.erase(job) == 1; |
| 534 CHECK(erased_job); | 537 CHECK(erased_job); |
| 535 return make_scoped_ptr(job); | 538 return base::WrapUnique(job); |
| 536 } | 539 } |
| 537 | 540 |
| 538 void CertNetFetcherImpl::SetCurrentlyCompletingJob(Job* job) { | 541 void CertNetFetcherImpl::SetCurrentlyCompletingJob(Job* job) { |
| 539 DCHECK(!currently_completing_job_); | 542 DCHECK(!currently_completing_job_); |
| 540 DCHECK(job); | 543 DCHECK(job); |
| 541 currently_completing_job_ = job; | 544 currently_completing_job_ = job; |
| 542 } | 545 } |
| 543 | 546 |
| 544 void CertNetFetcherImpl::ClearCurrentlyCompletingJob(Job* job) { | 547 void CertNetFetcherImpl::ClearCurrentlyCompletingJob(Job* job) { |
| 545 DCHECK_EQ(currently_completing_job_, job); | 548 DCHECK_EQ(currently_completing_job_, job); |
| 546 currently_completing_job_ = nullptr; | 549 currently_completing_job_ = nullptr; |
| 547 } | 550 } |
| 548 | 551 |
| 549 bool CertNetFetcherImpl::IsCurrentlyCompletingJob(Job* job) { | 552 bool CertNetFetcherImpl::IsCurrentlyCompletingJob(Job* job) { |
| 550 return job == currently_completing_job_; | 553 return job == currently_completing_job_; |
| 551 } | 554 } |
| 552 | 555 |
| 553 } // namespace net | 556 } // namespace net |
| OLD | NEW |