Chromium Code Reviews| Index: net/ssl/channel_id_service.cc |
| diff --git a/net/ssl/channel_id_service.cc b/net/ssl/channel_id_service.cc |
| index 986b4f413a1b9be77bbbb8ac48f6c12e6461e295..17cf49232e7d482c1ca2a3e31fda7f8ed3de4fd4 100644 |
| --- a/net/ssl/channel_id_service.cc |
| +++ b/net/ssl/channel_id_service.cc |
| @@ -108,64 +108,6 @@ scoped_ptr<ChannelIDStore::ChannelID> GenerateChannelID( |
| } // namespace |
| -// Represents the output and result callback of a request. |
| -class ChannelIDServiceRequest { |
| - public: |
| - ChannelIDServiceRequest(base::TimeTicks request_start, |
| - const CompletionCallback& callback, |
| - scoped_ptr<crypto::ECPrivateKey>* key) |
| - : request_start_(request_start), callback_(callback), key_(key) {} |
| - |
| - // Ensures that the result callback will never be made. |
| - void Cancel() { |
| - RecordGetChannelIDResult(ASYNC_CANCELLED); |
| - callback_.Reset(); |
| - } |
| - |
| - // Copies the contents of |key| to the caller's output argument and calls the |
| - // callback. |
| - void Post(int error, scoped_ptr<crypto::ECPrivateKey> key) { |
| - switch (error) { |
| - case OK: { |
| - base::TimeDelta request_time = base::TimeTicks::Now() - request_start_; |
| - UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.GetCertTimeAsync", |
| - request_time, |
| - base::TimeDelta::FromMilliseconds(1), |
| - base::TimeDelta::FromMinutes(5), |
| - 50); |
| - RecordGetChannelIDTime(request_time); |
| - RecordGetChannelIDResult(ASYNC_SUCCESS); |
| - break; |
| - } |
| - case ERR_KEY_GENERATION_FAILED: |
| - RecordGetChannelIDResult(ASYNC_FAILURE_KEYGEN); |
| - break; |
| - case ERR_PRIVATE_KEY_EXPORT_FAILED: |
| - RecordGetChannelIDResult(ASYNC_FAILURE_EXPORT_KEY); |
| - break; |
| - case ERR_INSUFFICIENT_RESOURCES: |
| - RecordGetChannelIDResult(WORKER_FAILURE); |
| - break; |
| - default: |
| - RecordGetChannelIDResult(ASYNC_FAILURE_UNKNOWN); |
| - break; |
| - } |
| - if (!callback_.is_null()) { |
| - if (key) |
| - *key_ = key.Pass(); |
| - callback_.Run(error); |
| - } |
| - delete this; |
| - } |
| - |
| - bool canceled() const { return callback_.is_null(); } |
| - |
| - private: |
| - base::TimeTicks request_start_; |
| - CompletionCallback callback_; |
| - scoped_ptr<crypto::ECPrivateKey>* key_; |
| -}; |
| - |
| // ChannelIDServiceWorker runs on a worker thread and takes care of the |
| // blocking process of performing key generation. Will take care of deleting |
| // itself once Start() is called. |
| @@ -232,12 +174,7 @@ class ChannelIDServiceJob { |
| : create_if_missing_(create_if_missing) { |
| } |
| - ~ChannelIDServiceJob() { |
|
mattm
2015/06/08 23:59:30
Maybe keep destructor and DCHECK that requests_ is
nharper
2015/06/09 19:19:32
Yes, that seems reasonable. I had to re-read the c
|
| - if (!requests_.empty()) |
| - DeleteAllCanceled(); |
| - } |
| - |
| - void AddRequest(ChannelIDServiceRequest* request, |
| + void AddRequest(ChannelIDService::Request* request, |
| bool create_if_missing = false) { |
| create_if_missing_ |= create_if_missing; |
| requests_.push_back(request); |
| @@ -249,70 +186,104 @@ class ChannelIDServiceJob { |
| bool CreateIfMissing() const { return create_if_missing_; } |
| + void CancelRequest(ChannelIDService::Request* req) { |
| + for (std::vector<ChannelIDService::Request*>::iterator i = |
|
mattm
2015/06/08 23:59:30
maybe use std::find?
nharper
2015/06/09 19:19:32
Done.
|
| + requests_.begin(); |
| + i != requests_.end(); i++) { |
| + if (*i == req) { |
| + requests_.erase(i); |
| + return; |
| + } |
| + } |
| + } |
| + |
| private: |
| void PostAll(int error, scoped_ptr<crypto::ECPrivateKey> key) { |
| - std::vector<ChannelIDServiceRequest*> requests; |
| + std::vector<ChannelIDService::Request*> requests; |
| requests_.swap(requests); |
| - for (std::vector<ChannelIDServiceRequest*>::iterator |
| - i = requests.begin(); i != requests.end(); i++) { |
| + for (std::vector<ChannelIDService::Request*>::iterator i = requests.begin(); |
| + i != requests.end(); i++) { |
| scoped_ptr<crypto::ECPrivateKey> key_copy; |
| if (key) |
| key_copy.reset(key->Copy()); |
| (*i)->Post(error, key_copy.Pass()); |
| - // Post() causes the ChannelIDServiceRequest to delete itself. |
| - } |
| - } |
| - |
| - void DeleteAllCanceled() { |
| - for (std::vector<ChannelIDServiceRequest*>::iterator |
| - i = requests_.begin(); i != requests_.end(); i++) { |
| - if ((*i)->canceled()) { |
| - delete *i; |
| - } else { |
| - LOG(DFATAL) << "ChannelIDServiceRequest leaked!"; |
| - } |
| } |
| } |
| - std::vector<ChannelIDServiceRequest*> requests_; |
| + std::vector<ChannelIDService::Request*> requests_; |
| bool create_if_missing_; |
| }; |
| // static |
| const char ChannelIDService::kEPKIPassword[] = ""; |
| -ChannelIDService::RequestHandle::RequestHandle() |
| - : service_(NULL), |
| - request_(NULL) {} |
| +ChannelIDService::Request::Request() : service_(NULL) { |
| +} |
| -ChannelIDService::RequestHandle::~RequestHandle() { |
| +ChannelIDService::Request::~Request() { |
| Cancel(); |
| } |
| -void ChannelIDService::RequestHandle::Cancel() { |
| - if (request_) { |
| - service_->CancelRequest(request_); |
| - request_ = NULL; |
| +void ChannelIDService::Request::Cancel() { |
| + if (service_) { |
| + RecordGetChannelIDResult(ASYNC_CANCELLED); |
| callback_.Reset(); |
| + service_->CancelRequest(server_identifier_, this); |
| + |
| + service_ = NULL; |
| } |
| } |
| -void ChannelIDService::RequestHandle::RequestStarted( |
| +void ChannelIDService::Request::RequestStarted( |
| ChannelIDService* service, |
| - ChannelIDServiceRequest* request, |
| - const CompletionCallback& callback) { |
| - DCHECK(request_ == NULL); |
| + base::TimeTicks request_start, |
| + const CompletionCallback& callback, |
| + scoped_ptr<crypto::ECPrivateKey>* key, |
| + const std::string& server_identifier) { |
|
mattm
2015/06/08 23:59:30
Could just pass in a pointer to the Job and avoid
nharper
2015/06/09 19:19:32
I believe the assumption that a job never gets del
|
| + DCHECK(service_ == NULL); |
| service_ = service; |
| - request_ = request; |
| + request_start_ = request_start; |
| callback_ = callback; |
| + key_ = key; |
| + server_identifier_ = server_identifier; |
| } |
| -void ChannelIDService::RequestHandle::OnRequestComplete(int result) { |
| - request_ = NULL; |
| - // Running the callback might delete |this|, so we can't touch any of our |
| - // members afterwards. Reset callback_ first. |
| - base::ResetAndReturn(&callback_).Run(result); |
| +void ChannelIDService::Request::Post(int error, |
| + scoped_ptr<crypto::ECPrivateKey> key) { |
| + switch (error) { |
| + case OK: { |
| + base::TimeDelta request_time = base::TimeTicks::Now() - request_start_; |
| + UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.GetCertTimeAsync", |
| + request_time, |
| + base::TimeDelta::FromMilliseconds(1), |
| + base::TimeDelta::FromMinutes(5), 50); |
| + RecordGetChannelIDTime(request_time); |
| + RecordGetChannelIDResult(ASYNC_SUCCESS); |
| + break; |
| + } |
| + case ERR_KEY_GENERATION_FAILED: |
| + RecordGetChannelIDResult(ASYNC_FAILURE_KEYGEN); |
| + break; |
| + case ERR_PRIVATE_KEY_EXPORT_FAILED: |
| + RecordGetChannelIDResult(ASYNC_FAILURE_EXPORT_KEY); |
| + break; |
| + case ERR_INSUFFICIENT_RESOURCES: |
| + RecordGetChannelIDResult(WORKER_FAILURE); |
| + break; |
| + default: |
| + RecordGetChannelIDResult(ASYNC_FAILURE_UNKNOWN); |
| + break; |
| + } |
| + service_ = NULL; |
| + if (!callback_.is_null()) { |
|
mattm
2015/06/08 23:59:30
Should we change this to a DCHECK? It shouldn't be
nharper
2015/06/09 19:19:32
No, this shouldn't be changed to a DCHECK. It's va
mattm
2015/06/09 19:32:24
Hm, GetChannelID and GetOrCreateChannelID both hav
nharper
2015/06/09 21:30:16
The DCHECK failed because I got the condition back
|
| + if (key) |
| + *key_ = key.Pass(); |
| + // Running the callback might delete |this| (e.g. the callback cleans up |
| + // resources created for the request), so we can't touch any of our |
| + // members afterwards. Reset callback_ first. |
| + base::ResetAndReturn(&callback_).Run(error); |
| + } |
| } |
| ChannelIDService::ChannelIDService( |
| @@ -345,7 +316,7 @@ int ChannelIDService::GetOrCreateChannelID( |
| const std::string& host, |
| scoped_ptr<crypto::ECPrivateKey>* key, |
| const CompletionCallback& callback, |
| - RequestHandle* out_req) { |
| + Request* out_req) { |
| DVLOG(1) << __FUNCTION__ << " " << host; |
| DCHECK(CalledOnValidThread()); |
| base::TimeTicks request_start = base::TimeTicks::Now(); |
| @@ -389,12 +360,8 @@ int ChannelIDService::GetOrCreateChannelID( |
| ChannelIDServiceJob* job = new ChannelIDServiceJob(create_if_missing); |
| inflight_[domain] = job; |
| - ChannelIDServiceRequest* request = new ChannelIDServiceRequest( |
| - request_start, base::Bind(&RequestHandle::OnRequestComplete, |
| - base::Unretained(out_req)), |
| - key); |
| - job->AddRequest(request); |
| - out_req->RequestStarted(this, request, callback); |
| + job->AddRequest(out_req); |
| + out_req->RequestStarted(this, request_start, callback, key, domain); |
| return ERR_IO_PENDING; |
| } |
| @@ -404,7 +371,7 @@ int ChannelIDService::GetOrCreateChannelID( |
| int ChannelIDService::GetChannelID(const std::string& host, |
| scoped_ptr<crypto::ECPrivateKey>* key, |
| const CompletionCallback& callback, |
| - RequestHandle* out_req) { |
| + Request* out_req) { |
| DVLOG(1) << __FUNCTION__ << " " << host; |
| DCHECK(CalledOnValidThread()); |
| base::TimeTicks request_start = base::TimeTicks::Now(); |
| @@ -449,7 +416,7 @@ void ChannelIDService::GotChannelID(int err, |
| if (err == OK) { |
| // Async DB lookup found a valid channel ID. |
| key_store_hits_++; |
| - // ChannelIDServiceRequest::Post will do the histograms and stuff. |
| + // ChannelIDService::Request::Post will do the histograms and stuff. |
| HandleResult(OK, server_identifier, key.Pass()); |
| return; |
| } |
| @@ -478,11 +445,6 @@ ChannelIDStore* ChannelIDService::GetChannelIDStore() { |
| return channel_id_store_.get(); |
| } |
| -void ChannelIDService::CancelRequest(ChannelIDServiceRequest* req) { |
| - DCHECK(CalledOnValidThread()); |
| - req->Cancel(); |
| -} |
| - |
| void ChannelIDService::GeneratedChannelID( |
| const std::string& server_identifier, |
| int error, |
| @@ -515,13 +477,28 @@ void ChannelIDService::HandleResult(int error, |
| delete job; |
| } |
| +void ChannelIDService::CancelRequest(const std::string& server_identifier, |
| + Request* req) { |
| + DCHECK(CalledOnValidThread()); |
| + |
| + std::map<std::string, ChannelIDServiceJob*>::iterator j; |
| + j = inflight_.find(server_identifier); |
| + if (j == inflight_.end()) { |
| + NOTREACHED(); |
| + return; |
| + } |
| + ChannelIDServiceJob* job = j->second; |
| + |
| + job->CancelRequest(req); |
| +} |
| + |
| bool ChannelIDService::JoinToInFlightRequest( |
| const base::TimeTicks& request_start, |
| const std::string& domain, |
| scoped_ptr<crypto::ECPrivateKey>* key, |
| bool create_if_missing, |
| const CompletionCallback& callback, |
| - RequestHandle* out_req) { |
| + Request* out_req) { |
| ChannelIDServiceJob* job = NULL; |
| std::map<std::string, ChannelIDServiceJob*>::const_iterator j = |
| inflight_.find(domain); |
| @@ -532,12 +509,8 @@ bool ChannelIDService::JoinToInFlightRequest( |
| job = j->second; |
| inflight_joins_++; |
| - ChannelIDServiceRequest* request = new ChannelIDServiceRequest( |
| - request_start, base::Bind(&RequestHandle::OnRequestComplete, |
| - base::Unretained(out_req)), |
| - key); |
| - job->AddRequest(request, create_if_missing); |
| - out_req->RequestStarted(this, request, callback); |
| + job->AddRequest(out_req, create_if_missing); |
| + out_req->RequestStarted(this, request_start, callback, key, domain); |
| return true; |
| } |
| return false; |
| @@ -548,7 +521,7 @@ int ChannelIDService::LookupChannelID(const base::TimeTicks& request_start, |
| scoped_ptr<crypto::ECPrivateKey>* key, |
| bool create_if_missing, |
| const CompletionCallback& callback, |
| - RequestHandle* out_req) { |
| + Request* out_req) { |
| // Check if a channel ID key already exists for this domain. |
| int err = channel_id_store_->GetChannelID( |
| domain, key, base::Bind(&ChannelIDService::GotChannelID, |
| @@ -570,12 +543,8 @@ int ChannelIDService::LookupChannelID(const base::TimeTicks& request_start, |
| ChannelIDServiceJob* job = new ChannelIDServiceJob(create_if_missing); |
| inflight_[domain] = job; |
| - ChannelIDServiceRequest* request = new ChannelIDServiceRequest( |
| - request_start, base::Bind(&RequestHandle::OnRequestComplete, |
| - base::Unretained(out_req)), |
| - key); |
| - job->AddRequest(request); |
| - out_req->RequestStarted(this, request, callback); |
| + job->AddRequest(out_req); |
| + out_req->RequestStarted(this, request_start, callback, key, domain); |
| return ERR_IO_PENDING; |
| } |