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 #include "net/cert_net/cert_net_fetcher_impl.h" | 5 #include "net/cert_net/cert_net_fetcher_impl.h" |
| 6 | 6 |
| 7 #include <deque> | |
| 8 | |
| 9 #include "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
| 8 #include "base/containers/linked_list.h" | |
| 10 #include "base/logging.h" | 9 #include "base/logging.h" |
| 11 #include "base/numerics/safe_math.h" | 10 #include "base/numerics/safe_math.h" |
| 12 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 13 #include "base/timer/timer.h" | 12 #include "base/timer/timer.h" |
| 14 #include "net/base/load_flags.h" | 13 #include "net/base/load_flags.h" |
| 15 #include "net/url_request/redirect_info.h" | 14 #include "net/url_request/redirect_info.h" |
| 16 #include "net/url_request/url_request_context.h" | 15 #include "net/url_request/url_request_context.h" |
| 17 | 16 |
| 18 // TODO(eroman): Add support for POST parameters. | 17 // TODO(eroman): Add support for POST parameters. |
| 19 // TODO(eroman): Add controls for bypassing the cache. | 18 // TODO(eroman): Add controls for bypassing the cache. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 67 } | 66 } |
| 68 | 67 |
| 69 enum HttpMethod { | 68 enum HttpMethod { |
| 70 HTTP_METHOD_GET, | 69 HTTP_METHOD_GET, |
| 71 HTTP_METHOD_POST, | 70 HTTP_METHOD_POST, |
| 72 }; | 71 }; |
| 73 | 72 |
| 74 } // namespace | 73 } // namespace |
| 75 | 74 |
| 76 // CertNetFetcherImpl::RequestImpl tracks an outstanding call to Fetch(). | 75 // CertNetFetcherImpl::RequestImpl tracks an outstanding call to Fetch(). |
| 77 class CertNetFetcherImpl::RequestImpl : public CertNetFetcher::Request { | 76 class CertNetFetcherImpl::RequestImpl : public CertNetFetcher::Request, |
| 77 public base::LinkNode<RequestImpl> { | |
|
davidben
2015/04/08 22:45:33
Huh, I didn't know that existed. Neat.
| |
| 78 public: | 78 public: |
| 79 RequestImpl(Job* job, const FetchCallback& callback) | 79 RequestImpl(Job* job, const FetchCallback& callback) |
| 80 : callback_(callback), job_(job) { | 80 : callback_(callback), job_(job) { |
| 81 DCHECK(!callback.is_null()); | 81 DCHECK(!callback.is_null()); |
| 82 } | 82 } |
| 83 | 83 |
| 84 // Deletion cancels the outstanding request. | 84 // Deletion cancels the outstanding request. |
| 85 ~RequestImpl() override; | 85 ~RequestImpl() override; |
| 86 | 86 |
| 87 void OnJobCancelled(Job* job) { | 87 void OnJobCancelled(Job* job) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 163 // Removes |request| from the job. | 163 // Removes |request| from the job. |
| 164 void DetachRequest(RequestImpl* request); | 164 void DetachRequest(RequestImpl* request); |
| 165 | 165 |
| 166 // Creates and starts a URLRequest for the job. After the request has | 166 // Creates and starts a URLRequest for the job. After the request has |
| 167 // completed, OnJobCompleted() will be invoked and all the registered requests | 167 // completed, OnJobCompleted() will be invoked and all the registered requests |
| 168 // notified of completion. | 168 // notified of completion. |
| 169 void StartURLRequest(URLRequestContext* context); | 169 void StartURLRequest(URLRequestContext* context); |
| 170 | 170 |
| 171 private: | 171 private: |
| 172 // The pointers in RequestList are not owned by the Job. | 172 // The pointers in RequestList are not owned by the Job. |
| 173 using RequestList = std::deque<RequestImpl*>; | 173 using RequestList = base::LinkedList<RequestImpl>; |
| 174 | 174 |
| 175 // Implementation of URLRequest::Delegate | 175 // Implementation of URLRequest::Delegate |
| 176 void OnReceivedRedirect(URLRequest* request, | 176 void OnReceivedRedirect(URLRequest* request, |
| 177 const RedirectInfo& redirect_info, | 177 const RedirectInfo& redirect_info, |
| 178 bool* defer_redirect) override; | 178 bool* defer_redirect) override; |
| 179 void OnResponseStarted(URLRequest* request) override; | 179 void OnResponseStarted(URLRequest* request) override; |
| 180 void OnReadCompleted(URLRequest* request, int bytes_read) override; | 180 void OnReadCompleted(URLRequest* request, int bytes_read) override; |
| 181 | 181 |
| 182 // Clears the URLRequest and timer. Helper for doing work common to | 182 // Clears the URLRequest and timer. Helper for doing work common to |
| 183 // cancellation and job completion. | 183 // cancellation and job completion. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 237 parent_(parent) { | 237 parent_(parent) { |
| 238 } | 238 } |
| 239 | 239 |
| 240 CertNetFetcherImpl::Job::~Job() { | 240 CertNetFetcherImpl::Job::~Job() { |
| 241 Cancel(); | 241 Cancel(); |
| 242 } | 242 } |
| 243 | 243 |
| 244 void CertNetFetcherImpl::Job::Cancel() { | 244 void CertNetFetcherImpl::Job::Cancel() { |
| 245 parent_ = nullptr; | 245 parent_ = nullptr; |
| 246 | 246 |
| 247 for (RequestImpl* request : requests_) | 247 // Notify each request of cancellation and remove it from the list. |
| 248 request->OnJobCancelled(this); | 248 for (base::LinkNode<RequestImpl>* current = requests_.head(); |
| 249 requests_.clear(); | 249 current != requests_.end();) { |
| 250 base::LinkNode<RequestImpl>* next = current->next(); | |
| 251 current->value()->OnJobCancelled(this); | |
| 252 current->RemoveFromList(); | |
| 253 current = next; | |
| 254 } | |
| 255 | |
| 256 DCHECK(requests_.empty()); | |
| 250 | 257 |
| 251 Stop(); | 258 Stop(); |
| 252 } | 259 } |
| 253 | 260 |
| 254 scoped_ptr<CertNetFetcher::Request> CertNetFetcherImpl::Job::CreateRequest( | 261 scoped_ptr<CertNetFetcher::Request> CertNetFetcherImpl::Job::CreateRequest( |
| 255 const FetchCallback& callback) { | 262 const FetchCallback& callback) { |
| 256 scoped_ptr<RequestImpl> request(new RequestImpl(this, callback)); | 263 scoped_ptr<RequestImpl> request(new RequestImpl(this, callback)); |
| 257 requests_.push_back(request.get()); | 264 requests_.Append(request.get()); |
| 258 return request.Pass(); | 265 return request.Pass(); |
| 259 } | 266 } |
| 260 | 267 |
| 261 void CertNetFetcherImpl::Job::DetachRequest(RequestImpl* request) { | 268 void CertNetFetcherImpl::Job::DetachRequest(RequestImpl* request) { |
| 262 scoped_ptr<Job> delete_this; | 269 scoped_ptr<Job> delete_this; |
| 263 | 270 |
| 264 // TODO(eroman): If a lot of requests are cancelled this is not efficient. | 271 request->RemoveFromList(); |
| 265 RequestList::iterator it = | |
| 266 std::find(requests_.begin(), requests_.end(), request); | |
| 267 CHECK(it != requests_.end()); | |
| 268 requests_.erase(it); | |
| 269 | 272 |
| 270 // If there are no longer any requests attached to the job then | 273 // If there are no longer any requests attached to the job then |
| 271 // cancel and delete it. | 274 // cancel and delete it. |
| 272 if (requests_.empty()) | 275 if (requests_.empty()) |
| 273 delete_this = parent_->RemoveJob(this); | 276 delete_this = parent_->RemoveJob(this); |
| 274 } | 277 } |
| 275 | 278 |
| 276 void CertNetFetcherImpl::Job::StartURLRequest(URLRequestContext* context) { | 279 void CertNetFetcherImpl::Job::StartURLRequest(URLRequestContext* context) { |
| 277 Error error = CanFetchUrl(request_params_->url); | 280 Error error = CanFetchUrl(request_params_->url); |
| 278 if (error != OK) { | 281 if (error != OK) { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 406 // Invoking the callbacks is subtle as state may be mutated while iterating | 409 // Invoking the callbacks is subtle as state may be mutated while iterating |
| 407 // through the callbacks: | 410 // through the callbacks: |
| 408 // | 411 // |
| 409 // * The parent CertNetFetcherImpl may be deleted | 412 // * The parent CertNetFetcherImpl may be deleted |
| 410 // * Requests in this job may be cancelled | 413 // * Requests in this job may be cancelled |
| 411 | 414 |
| 412 scoped_ptr<Job> delete_this = parent_->RemoveJob(this); | 415 scoped_ptr<Job> delete_this = parent_->RemoveJob(this); |
| 413 parent_->SetCurrentlyCompletingJob(this); | 416 parent_->SetCurrentlyCompletingJob(this); |
| 414 | 417 |
| 415 while (!requests_.empty()) { | 418 while (!requests_.empty()) { |
| 416 RequestImpl* request = requests_.front(); | 419 base::LinkNode<RequestImpl>* request = requests_.head(); |
| 417 requests_.pop_front(); | 420 request->RemoveFromList(); |
| 418 request->OnJobCompleted(this, result_net_error_, response_body_); | 421 request->value()->OnJobCompleted(this, result_net_error_, response_body_); |
| 419 } | 422 } |
| 420 | 423 |
| 421 if (parent_) | 424 if (parent_) |
| 422 parent_->ClearCurrentlyCompletingJob(this); | 425 parent_->ClearCurrentlyCompletingJob(this); |
| 423 } | 426 } |
| 424 | 427 |
| 425 CertNetFetcherImpl::CertNetFetcherImpl(URLRequestContext* context) | 428 CertNetFetcherImpl::CertNetFetcherImpl(URLRequestContext* context) |
| 426 : currently_completing_job_(nullptr), context_(context) { | 429 : currently_completing_job_(nullptr), context_(context) { |
| 427 } | 430 } |
| 428 | 431 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 538 DCHECK(job); | 541 DCHECK(job); |
| 539 currently_completing_job_ = job; | 542 currently_completing_job_ = job; |
| 540 } | 543 } |
| 541 | 544 |
| 542 void CertNetFetcherImpl::ClearCurrentlyCompletingJob(Job* job) { | 545 void CertNetFetcherImpl::ClearCurrentlyCompletingJob(Job* job) { |
| 543 DCHECK_EQ(currently_completing_job_, job); | 546 DCHECK_EQ(currently_completing_job_, job); |
| 544 currently_completing_job_ = nullptr; | 547 currently_completing_job_ = nullptr; |
| 545 } | 548 } |
| 546 | 549 |
| 547 } // namespace net | 550 } // namespace net |
| OLD | NEW |