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 |