OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/ssl/channel_id_service.h" | 5 #include "net/ssl/channel_id_service.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
| 9 #include <utility> |
9 | 10 |
10 #include "base/bind.h" | 11 #include "base/bind.h" |
11 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
12 #include "base/callback_helpers.h" | 13 #include "base/callback_helpers.h" |
13 #include "base/compiler_specific.h" | 14 #include "base/compiler_specific.h" |
14 #include "base/location.h" | 15 #include "base/location.h" |
15 #include "base/logging.h" | 16 #include "base/logging.h" |
16 #include "base/macros.h" | 17 #include "base/macros.h" |
17 #include "base/memory/ref_counted.h" | 18 #include "base/memory/ref_counted.h" |
18 #include "base/memory/scoped_ptr.h" | 19 #include "base/memory/scoped_ptr.h" |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 int* error) { | 88 int* error) { |
88 scoped_ptr<ChannelIDStore::ChannelID> result; | 89 scoped_ptr<ChannelIDStore::ChannelID> result; |
89 | 90 |
90 base::TimeTicks start = base::TimeTicks::Now(); | 91 base::TimeTicks start = base::TimeTicks::Now(); |
91 base::Time creation_time = base::Time::Now(); | 92 base::Time creation_time = base::Time::Now(); |
92 scoped_ptr<crypto::ECPrivateKey> key(crypto::ECPrivateKey::Create()); | 93 scoped_ptr<crypto::ECPrivateKey> key(crypto::ECPrivateKey::Create()); |
93 | 94 |
94 if (!key) { | 95 if (!key) { |
95 DLOG(ERROR) << "Unable to create channel ID key pair"; | 96 DLOG(ERROR) << "Unable to create channel ID key pair"; |
96 *error = ERR_KEY_GENERATION_FAILED; | 97 *error = ERR_KEY_GENERATION_FAILED; |
97 return result.Pass(); | 98 return result; |
98 } | 99 } |
99 | 100 |
100 result.reset(new ChannelIDStore::ChannelID(server_identifier, creation_time, | 101 result.reset(new ChannelIDStore::ChannelID(server_identifier, creation_time, |
101 key.Pass())); | 102 std::move(key))); |
102 UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.GenerateCertTime", | 103 UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.GenerateCertTime", |
103 base::TimeTicks::Now() - start, | 104 base::TimeTicks::Now() - start, |
104 base::TimeDelta::FromMilliseconds(1), | 105 base::TimeDelta::FromMilliseconds(1), |
105 base::TimeDelta::FromMinutes(5), | 106 base::TimeDelta::FromMinutes(5), |
106 50); | 107 50); |
107 *error = OK; | 108 *error = OK; |
108 return result.Pass(); | 109 return result; |
109 } | 110 } |
110 | 111 |
111 } // namespace | 112 } // namespace |
112 | 113 |
113 // ChannelIDServiceWorker runs on a worker thread and takes care of the | 114 // ChannelIDServiceWorker runs on a worker thread and takes care of the |
114 // blocking process of performing key generation. Will take care of deleting | 115 // blocking process of performing key generation. Will take care of deleting |
115 // itself once Start() is called. | 116 // itself once Start() is called. |
116 class ChannelIDServiceWorker { | 117 class ChannelIDServiceWorker { |
117 public: | 118 public: |
118 typedef base::Callback<void( | 119 typedef base::Callback<void( |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 | 177 |
177 ~ChannelIDServiceJob() { DCHECK(requests_.empty()); } | 178 ~ChannelIDServiceJob() { DCHECK(requests_.empty()); } |
178 | 179 |
179 void AddRequest(ChannelIDService::Request* request, | 180 void AddRequest(ChannelIDService::Request* request, |
180 bool create_if_missing = false) { | 181 bool create_if_missing = false) { |
181 create_if_missing_ |= create_if_missing; | 182 create_if_missing_ |= create_if_missing; |
182 requests_.push_back(request); | 183 requests_.push_back(request); |
183 } | 184 } |
184 | 185 |
185 void HandleResult(int error, scoped_ptr<crypto::ECPrivateKey> key) { | 186 void HandleResult(int error, scoped_ptr<crypto::ECPrivateKey> key) { |
186 PostAll(error, key.Pass()); | 187 PostAll(error, std::move(key)); |
187 } | 188 } |
188 | 189 |
189 bool CreateIfMissing() const { return create_if_missing_; } | 190 bool CreateIfMissing() const { return create_if_missing_; } |
190 | 191 |
191 void CancelRequest(ChannelIDService::Request* req) { | 192 void CancelRequest(ChannelIDService::Request* req) { |
192 auto it = std::find(requests_.begin(), requests_.end(), req); | 193 auto it = std::find(requests_.begin(), requests_.end(), req); |
193 if (it != requests_.end()) | 194 if (it != requests_.end()) |
194 requests_.erase(it); | 195 requests_.erase(it); |
195 } | 196 } |
196 | 197 |
197 private: | 198 private: |
198 void PostAll(int error, scoped_ptr<crypto::ECPrivateKey> key) { | 199 void PostAll(int error, scoped_ptr<crypto::ECPrivateKey> key) { |
199 std::vector<ChannelIDService::Request*> requests; | 200 std::vector<ChannelIDService::Request*> requests; |
200 requests_.swap(requests); | 201 requests_.swap(requests); |
201 | 202 |
202 for (std::vector<ChannelIDService::Request*>::iterator i = requests.begin(); | 203 for (std::vector<ChannelIDService::Request*>::iterator i = requests.begin(); |
203 i != requests.end(); i++) { | 204 i != requests.end(); i++) { |
204 scoped_ptr<crypto::ECPrivateKey> key_copy; | 205 scoped_ptr<crypto::ECPrivateKey> key_copy; |
205 if (key) | 206 if (key) |
206 key_copy.reset(key->Copy()); | 207 key_copy.reset(key->Copy()); |
207 (*i)->Post(error, key_copy.Pass()); | 208 (*i)->Post(error, std::move(key_copy)); |
208 } | 209 } |
209 } | 210 } |
210 | 211 |
211 std::vector<ChannelIDService::Request*> requests_; | 212 std::vector<ChannelIDService::Request*> requests_; |
212 bool create_if_missing_; | 213 bool create_if_missing_; |
213 }; | 214 }; |
214 | 215 |
215 // static | 216 // static |
216 const char ChannelIDService::kEPKIPassword[] = ""; | 217 const char ChannelIDService::kEPKIPassword[] = ""; |
217 | 218 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 case ERR_INSUFFICIENT_RESOURCES: | 269 case ERR_INSUFFICIENT_RESOURCES: |
269 RecordGetChannelIDResult(WORKER_FAILURE); | 270 RecordGetChannelIDResult(WORKER_FAILURE); |
270 break; | 271 break; |
271 default: | 272 default: |
272 RecordGetChannelIDResult(ASYNC_FAILURE_UNKNOWN); | 273 RecordGetChannelIDResult(ASYNC_FAILURE_UNKNOWN); |
273 break; | 274 break; |
274 } | 275 } |
275 service_ = NULL; | 276 service_ = NULL; |
276 DCHECK(!callback_.is_null()); | 277 DCHECK(!callback_.is_null()); |
277 if (key) | 278 if (key) |
278 *key_ = key.Pass(); | 279 *key_ = std::move(key); |
279 // Running the callback might delete |this| (e.g. the callback cleans up | 280 // Running the callback might delete |this| (e.g. the callback cleans up |
280 // resources created for the request), so we can't touch any of our | 281 // resources created for the request), so we can't touch any of our |
281 // members afterwards. Reset callback_ first. | 282 // members afterwards. Reset callback_ first. |
282 base::ResetAndReturn(&callback_).Run(error); | 283 base::ResetAndReturn(&callback_).Run(error); |
283 } | 284 } |
284 | 285 |
285 ChannelIDService::ChannelIDService( | 286 ChannelIDService::ChannelIDService( |
286 ChannelIDStore* channel_id_store, | 287 ChannelIDStore* channel_id_store, |
287 const scoped_refptr<base::TaskRunner>& task_runner) | 288 const scoped_refptr<base::TaskRunner>& task_runner) |
288 : channel_id_store_(channel_id_store), | 289 : channel_id_store_(channel_id_store), |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 j = inflight_.find(server_identifier); | 407 j = inflight_.find(server_identifier); |
407 if (j == inflight_.end()) { | 408 if (j == inflight_.end()) { |
408 NOTREACHED(); | 409 NOTREACHED(); |
409 return; | 410 return; |
410 } | 411 } |
411 | 412 |
412 if (err == OK) { | 413 if (err == OK) { |
413 // Async DB lookup found a valid channel ID. | 414 // Async DB lookup found a valid channel ID. |
414 key_store_hits_++; | 415 key_store_hits_++; |
415 // ChannelIDService::Request::Post will do the histograms and stuff. | 416 // ChannelIDService::Request::Post will do the histograms and stuff. |
416 HandleResult(OK, server_identifier, key.Pass()); | 417 HandleResult(OK, server_identifier, std::move(key)); |
417 return; | 418 return; |
418 } | 419 } |
419 // Async lookup failed or the channel ID was missing. Return the error | 420 // Async lookup failed or the channel ID was missing. Return the error |
420 // directly, unless the channel ID was missing and a request asked to create | 421 // directly, unless the channel ID was missing and a request asked to create |
421 // one. | 422 // one. |
422 if (err != ERR_FILE_NOT_FOUND || !j->second->CreateIfMissing()) { | 423 if (err != ERR_FILE_NOT_FOUND || !j->second->CreateIfMissing()) { |
423 HandleResult(err, server_identifier, key.Pass()); | 424 HandleResult(err, server_identifier, std::move(key)); |
424 return; | 425 return; |
425 } | 426 } |
426 // At least one request asked to create a channel ID => start generating a new | 427 // At least one request asked to create a channel ID => start generating a new |
427 // one. | 428 // one. |
428 workers_created_++; | 429 workers_created_++; |
429 ChannelIDServiceWorker* worker = new ChannelIDServiceWorker( | 430 ChannelIDServiceWorker* worker = new ChannelIDServiceWorker( |
430 server_identifier, | 431 server_identifier, |
431 base::Bind(&ChannelIDService::GeneratedChannelID, | 432 base::Bind(&ChannelIDService::GeneratedChannelID, |
432 weak_ptr_factory_.GetWeakPtr())); | 433 weak_ptr_factory_.GetWeakPtr())); |
433 if (!worker->Start(task_runner_)) { | 434 if (!worker->Start(task_runner_)) { |
434 // TODO(rkn): Log to the NetLog. | 435 // TODO(rkn): Log to the NetLog. |
435 LOG(ERROR) << "ChannelIDServiceWorker couldn't be started."; | 436 LOG(ERROR) << "ChannelIDServiceWorker couldn't be started."; |
436 HandleResult(ERR_INSUFFICIENT_RESOURCES, server_identifier, nullptr); | 437 HandleResult(ERR_INSUFFICIENT_RESOURCES, server_identifier, nullptr); |
437 } | 438 } |
438 } | 439 } |
439 | 440 |
440 ChannelIDStore* ChannelIDService::GetChannelIDStore() { | 441 ChannelIDStore* ChannelIDService::GetChannelIDStore() { |
441 return channel_id_store_.get(); | 442 return channel_id_store_.get(); |
442 } | 443 } |
443 | 444 |
444 void ChannelIDService::GeneratedChannelID( | 445 void ChannelIDService::GeneratedChannelID( |
445 const std::string& server_identifier, | 446 const std::string& server_identifier, |
446 int error, | 447 int error, |
447 scoped_ptr<ChannelIDStore::ChannelID> channel_id) { | 448 scoped_ptr<ChannelIDStore::ChannelID> channel_id) { |
448 DCHECK(CalledOnValidThread()); | 449 DCHECK(CalledOnValidThread()); |
449 | 450 |
450 scoped_ptr<crypto::ECPrivateKey> key; | 451 scoped_ptr<crypto::ECPrivateKey> key; |
451 if (error == OK) { | 452 if (error == OK) { |
452 key.reset(channel_id->key()->Copy()); | 453 key.reset(channel_id->key()->Copy()); |
453 channel_id_store_->SetChannelID(channel_id.Pass()); | 454 channel_id_store_->SetChannelID(std::move(channel_id)); |
454 } | 455 } |
455 HandleResult(error, server_identifier, key.Pass()); | 456 HandleResult(error, server_identifier, std::move(key)); |
456 } | 457 } |
457 | 458 |
458 void ChannelIDService::HandleResult(int error, | 459 void ChannelIDService::HandleResult(int error, |
459 const std::string& server_identifier, | 460 const std::string& server_identifier, |
460 scoped_ptr<crypto::ECPrivateKey> key) { | 461 scoped_ptr<crypto::ECPrivateKey> key) { |
461 DCHECK(CalledOnValidThread()); | 462 DCHECK(CalledOnValidThread()); |
462 | 463 |
463 std::map<std::string, ChannelIDServiceJob*>::iterator j; | 464 std::map<std::string, ChannelIDServiceJob*>::iterator j; |
464 j = inflight_.find(server_identifier); | 465 j = inflight_.find(server_identifier); |
465 if (j == inflight_.end()) { | 466 if (j == inflight_.end()) { |
466 NOTREACHED(); | 467 NOTREACHED(); |
467 return; | 468 return; |
468 } | 469 } |
469 ChannelIDServiceJob* job = j->second; | 470 ChannelIDServiceJob* job = j->second; |
470 inflight_.erase(j); | 471 inflight_.erase(j); |
471 | 472 |
472 job->HandleResult(error, key.Pass()); | 473 job->HandleResult(error, std::move(key)); |
473 delete job; | 474 delete job; |
474 } | 475 } |
475 | 476 |
476 bool ChannelIDService::JoinToInFlightRequest( | 477 bool ChannelIDService::JoinToInFlightRequest( |
477 const base::TimeTicks& request_start, | 478 const base::TimeTicks& request_start, |
478 const std::string& domain, | 479 const std::string& domain, |
479 scoped_ptr<crypto::ECPrivateKey>* key, | 480 scoped_ptr<crypto::ECPrivateKey>* key, |
480 bool create_if_missing, | 481 bool create_if_missing, |
481 const CompletionCallback& callback, | 482 const CompletionCallback& callback, |
482 Request* out_req) { | 483 Request* out_req) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
530 } | 531 } |
531 | 532 |
532 return err; | 533 return err; |
533 } | 534 } |
534 | 535 |
535 int ChannelIDService::channel_id_count() { | 536 int ChannelIDService::channel_id_count() { |
536 return channel_id_store_->GetChannelIDCount(); | 537 return channel_id_store_->GetChannelIDCount(); |
537 } | 538 } |
538 | 539 |
539 } // namespace net | 540 } // namespace net |
OLD | NEW |