OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/base/cert_verifier.h" | 5 #include "net/base/multi_threaded_cert_verifier.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
13 #include "base/synchronization/lock.h" | 13 #include "base/synchronization/lock.h" |
14 #include "base/time.h" | 14 #include "base/time.h" |
15 #include "base/threading/worker_pool.h" | 15 #include "base/threading/worker_pool.h" |
16 #include "net/base/crl_set.h" | 16 #include "net/base/crl_set.h" |
17 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
18 #include "net/base/net_log.h" | 18 #include "net/base/net_log.h" |
19 #include "net/base/x509_certificate.h" | 19 #include "net/base/x509_certificate.h" |
20 #include "net/base/x509_certificate_net_log_param.h" | 20 #include "net/base/x509_certificate_net_log_param.h" |
21 | 21 |
22 #if defined(USE_NSS) | 22 #if defined(USE_NSS) |
23 #include <private/pprthred.h> // PR_DetachThread | 23 #include <private/pprthred.h> // PR_DetachThread |
24 #endif | 24 #endif |
25 | 25 |
26 namespace net { | 26 namespace net { |
27 | 27 |
28 //////////////////////////////////////////////////////////////////////////// | 28 //////////////////////////////////////////////////////////////////////////// |
29 | 29 |
30 // Life of a request: | 30 // Life of a request: |
31 // | 31 // |
32 // CertVerifier CertVerifierJob CertVerifierWorker Request | 32 // MultiThreadedCertVerifier CertVerifierJob CertVerifierWorker Request |
33 // | (origin loop) (worker loop) | 33 // | (origin loop) (worker loop) |
34 // | | 34 // | |
35 // Verify() | 35 // Verify() |
| 36 // |---->-------------------------------------<creates> |
| 37 // | |
36 // |---->-------------------<creates> | 38 // |---->-------------------<creates> |
37 // | | 39 // | |
38 // |---->----<creates> | 40 // |---->-------------------------------------------------------<creates> |
39 // | | 41 // | |
40 // |---->---------------------------------------------------<creates> | 42 // |---->---------------------------------------Start |
| 43 // | | |
| 44 // | PostTask |
41 // | | 45 // | |
42 // |---->--------------------Start | 46 // | <starts verifying> |
43 // | | | 47 // |---->-------------------AddRequest | |
44 // | PostTask | 48 // | |
45 // | | 49 // | |
46 // | <starts verifying> | 50 // | |
47 // |---->-----AddRequest | | 51 // Finish |
48 // | | 52 // | |
49 // | | 53 // PostTask |
50 // | | |
51 // Finish | |
52 // | | |
53 // PostTask | |
54 // | 54 // |
55 // | | 55 // | |
56 // DoReply | 56 // DoReply |
57 // |----<-----------------------| | 57 // |----<-----------------------------------------| |
58 // HandleResult | 58 // HandleResult |
59 // | | 59 // | |
60 // |---->-----HandleResult | 60 // |---->------------------HandleResult |
61 // | | 61 // | |
62 // |------>-----------------------------------Post | 62 // |------>---------------------------Post |
63 // | 63 // |
64 // | 64 // |
65 // | 65 // |
66 // On a cache hit, CertVerifier::Verify() returns synchronously without | 66 // On a cache hit, MultiThreadedCertVerifier::Verify() returns synchronously |
67 // posting a task to a worker thread. | 67 // without posting a task to a worker thread. |
68 | 68 |
69 namespace { | 69 namespace { |
70 | 70 |
71 // The default value of max_cache_entries_. | 71 // The default value of max_cache_entries_. |
72 const unsigned kMaxCacheEntries = 256; | 72 const unsigned kMaxCacheEntries = 256; |
73 | 73 |
74 // The number of seconds for which we'll cache a cache entry. | 74 // The number of seconds for which we'll cache a cache entry. |
75 const unsigned kTTLSecs = 1800; // 30 minutes. | 75 const unsigned kTTLSecs = 1800; // 30 minutes. |
76 | 76 |
77 } // namespace | 77 } // namespace |
78 | 78 |
79 CertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {} | 79 MultiThreadedCertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {} |
80 | 80 |
81 CertVerifier::CachedResult::~CachedResult() {} | 81 MultiThreadedCertVerifier::CachedResult::~CachedResult() {} |
82 | 82 |
83 // Represents the output and result callback of a request. | 83 // Represents the output and result callback of a request. |
84 class CertVerifierRequest { | 84 class CertVerifierRequest { |
85 public: | 85 public: |
86 CertVerifierRequest(const CompletionCallback& callback, | 86 CertVerifierRequest(const CompletionCallback& callback, |
87 CertVerifyResult* verify_result, | 87 CertVerifyResult* verify_result, |
88 const BoundNetLog& net_log) | 88 const BoundNetLog& net_log) |
89 : callback_(callback), | 89 : callback_(callback), |
90 verify_result_(verify_result), | 90 verify_result_(verify_result), |
91 net_log_(net_log) { | 91 net_log_(net_log) { |
92 net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL); | 92 net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL); |
93 } | 93 } |
94 | 94 |
95 ~CertVerifierRequest() { | 95 ~CertVerifierRequest() { |
96 } | 96 } |
97 | 97 |
98 // Ensures that the result callback will never be made. | 98 // Ensures that the result callback will never be made. |
99 void Cancel() { | 99 void Cancel() { |
100 callback_.Reset(); | 100 callback_.Reset(); |
101 verify_result_ = NULL; | 101 verify_result_ = NULL; |
102 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); | 102 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); |
103 net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL); | 103 net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL); |
104 } | 104 } |
105 | 105 |
106 // Copies the contents of |verify_result| to the caller's | 106 // Copies the contents of |verify_result| to the caller's |
107 // CertVerifyResult and calls the callback. | 107 // CertVerifyResult and calls the callback. |
108 void Post(const CertVerifier::CachedResult& verify_result) { | 108 void Post(const MultiThreadedCertVerifier::CachedResult& verify_result) { |
109 if (!callback_.is_null()) { | 109 if (!callback_.is_null()) { |
110 net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL); | 110 net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL); |
111 *verify_result_ = verify_result.result; | 111 *verify_result_ = verify_result.result; |
112 callback_.Run(verify_result.error); | 112 callback_.Run(verify_result.error); |
113 } | 113 } |
114 delete this; | 114 delete this; |
115 } | 115 } |
116 | 116 |
117 bool canceled() const { return callback_.is_null(); } | 117 bool canceled() const { return callback_.is_null(); } |
118 | 118 |
119 const BoundNetLog& net_log() const { return net_log_; } | 119 const BoundNetLog& net_log() const { return net_log_; } |
120 | 120 |
121 private: | 121 private: |
122 CompletionCallback callback_; | 122 CompletionCallback callback_; |
123 CertVerifyResult* verify_result_; | 123 CertVerifyResult* verify_result_; |
124 const BoundNetLog net_log_; | 124 const BoundNetLog net_log_; |
125 }; | 125 }; |
126 | 126 |
127 | 127 |
128 // CertVerifierWorker runs on a worker thread and takes care of the blocking | 128 // CertVerifierWorker runs on a worker thread and takes care of the blocking |
129 // process of performing the certificate verification. Deletes itself | 129 // process of performing the certificate verification. Deletes itself |
130 // eventually if Start() succeeds. | 130 // eventually if Start() succeeds. |
131 class CertVerifierWorker { | 131 class CertVerifierWorker { |
132 public: | 132 public: |
133 CertVerifierWorker(X509Certificate* cert, | 133 CertVerifierWorker(X509Certificate* cert, |
134 const std::string& hostname, | 134 const std::string& hostname, |
135 int flags, | 135 int flags, |
136 CRLSet* crl_set, | 136 CRLSet* crl_set, |
137 CertVerifier* cert_verifier) | 137 MultiThreadedCertVerifier* cert_verifier) |
138 : cert_(cert), | 138 : cert_(cert), |
139 hostname_(hostname), | 139 hostname_(hostname), |
140 flags_(flags), | 140 flags_(flags), |
141 crl_set_(crl_set), | 141 crl_set_(crl_set), |
142 origin_loop_(MessageLoop::current()), | 142 origin_loop_(MessageLoop::current()), |
143 cert_verifier_(cert_verifier), | 143 cert_verifier_(cert_verifier), |
144 canceled_(false), | 144 canceled_(false), |
145 error_(ERR_FAILED) { | 145 error_(ERR_FAILED) { |
146 } | 146 } |
147 | 147 |
148 // Returns the certificate being verified. May only be called /before/ | 148 // Returns the certificate being verified. May only be called /before/ |
149 // Start() is called. | 149 // Start() is called. |
150 X509Certificate* certificate() const { return cert_; } | 150 X509Certificate* certificate() const { return cert_; } |
151 | 151 |
152 bool Start() { | 152 bool Start() { |
153 DCHECK_EQ(MessageLoop::current(), origin_loop_); | 153 DCHECK_EQ(MessageLoop::current(), origin_loop_); |
154 | 154 |
155 return base::WorkerPool::PostTask( | 155 return base::WorkerPool::PostTask( |
156 FROM_HERE, base::Bind(&CertVerifierWorker::Run, base::Unretained(this)), | 156 FROM_HERE, base::Bind(&CertVerifierWorker::Run, base::Unretained(this)), |
157 true /* task is slow */); | 157 true /* task is slow */); |
158 } | 158 } |
159 | 159 |
160 // Cancel is called from the origin loop when the CertVerifier is getting | 160 // Cancel is called from the origin loop when the MultiThreadedCertVerifier is |
161 // deleted. | 161 // getting deleted. |
162 void Cancel() { | 162 void Cancel() { |
163 DCHECK_EQ(MessageLoop::current(), origin_loop_); | 163 DCHECK_EQ(MessageLoop::current(), origin_loop_); |
164 base::AutoLock locked(lock_); | 164 base::AutoLock locked(lock_); |
165 canceled_ = true; | 165 canceled_ = true; |
166 } | 166 } |
167 | 167 |
168 private: | 168 private: |
169 void Run() { | 169 void Run() { |
170 // Runs on a worker thread. | 170 // Runs on a worker thread. |
171 error_ = cert_->Verify(hostname_, flags_, crl_set_, &verify_result_); | 171 error_ = cert_->Verify(hostname_, flags_, crl_set_, &verify_result_); |
(...skipping 22 matching lines...) Expand all Loading... |
194 if (!canceled_) { | 194 if (!canceled_) { |
195 cert_verifier_->HandleResult(cert_, hostname_, flags_, | 195 cert_verifier_->HandleResult(cert_, hostname_, flags_, |
196 error_, verify_result_); | 196 error_, verify_result_); |
197 } | 197 } |
198 } | 198 } |
199 delete this; | 199 delete this; |
200 } | 200 } |
201 | 201 |
202 void Finish() { | 202 void Finish() { |
203 // Runs on the worker thread. | 203 // Runs on the worker thread. |
204 // We assume that the origin loop outlives the CertVerifier. If the | 204 // We assume that the origin loop outlives the MultiThreadedCertVerifier. If |
205 // CertVerifier is deleted, it will call Cancel on us. If it does so | 205 // the MultiThreadedCertVerifier is deleted, it will call Cancel on us. If |
206 // before the Acquire, we'll delete ourselves and return. If it's trying to | 206 // it does so before the Acquire, we'll delete ourselves and return. If it's |
207 // do so concurrently, then it'll block on the lock and we'll call PostTask | 207 // trying to do so concurrently, then it'll block on the lock and we'll call |
208 // while the CertVerifier (and therefore the MessageLoop) is still alive. | 208 // PostTask while the MultiThreadedCertVerifier (and therefore the |
| 209 // MessageLoop) is still alive. |
209 // If it does so after this function, we assume that the MessageLoop will | 210 // If it does so after this function, we assume that the MessageLoop will |
210 // process pending tasks. In which case we'll notice the |canceled_| flag | 211 // process pending tasks. In which case we'll notice the |canceled_| flag |
211 // in DoReply. | 212 // in DoReply. |
212 | 213 |
213 bool canceled; | 214 bool canceled; |
214 { | 215 { |
215 base::AutoLock locked(lock_); | 216 base::AutoLock locked(lock_); |
216 canceled = canceled_; | 217 canceled = canceled_; |
217 if (!canceled) { | 218 if (!canceled) { |
218 origin_loop_->PostTask( | 219 origin_loop_->PostTask( |
219 FROM_HERE, base::Bind( | 220 FROM_HERE, base::Bind( |
220 &CertVerifierWorker::DoReply, base::Unretained(this))); | 221 &CertVerifierWorker::DoReply, base::Unretained(this))); |
221 } | 222 } |
222 } | 223 } |
223 | 224 |
224 if (canceled) | 225 if (canceled) |
225 delete this; | 226 delete this; |
226 } | 227 } |
227 | 228 |
228 scoped_refptr<X509Certificate> cert_; | 229 scoped_refptr<X509Certificate> cert_; |
229 const std::string hostname_; | 230 const std::string hostname_; |
230 const int flags_; | 231 const int flags_; |
231 scoped_refptr<CRLSet> crl_set_; | 232 scoped_refptr<CRLSet> crl_set_; |
232 MessageLoop* const origin_loop_; | 233 MessageLoop* const origin_loop_; |
233 CertVerifier* const cert_verifier_; | 234 MultiThreadedCertVerifier* const cert_verifier_; |
234 | 235 |
235 // lock_ protects canceled_. | 236 // lock_ protects canceled_. |
236 base::Lock lock_; | 237 base::Lock lock_; |
237 | 238 |
238 // If canceled_ is true, | 239 // If canceled_ is true, |
239 // * origin_loop_ cannot be accessed by the worker thread, | 240 // * origin_loop_ cannot be accessed by the worker thread, |
240 // * cert_verifier_ cannot be accessed by any thread. | 241 // * cert_verifier_ cannot be accessed by any thread. |
241 bool canceled_; | 242 bool canceled_; |
242 | 243 |
243 int error_; | 244 int error_; |
(...skipping 27 matching lines...) Expand all Loading... |
271 | 272 |
272 void AddRequest(CertVerifierRequest* request) { | 273 void AddRequest(CertVerifierRequest* request) { |
273 request->net_log().AddEvent( | 274 request->net_log().AddEvent( |
274 NetLog::TYPE_CERT_VERIFIER_REQUEST_BOUND_TO_JOB, | 275 NetLog::TYPE_CERT_VERIFIER_REQUEST_BOUND_TO_JOB, |
275 make_scoped_refptr(new NetLogSourceParameter( | 276 make_scoped_refptr(new NetLogSourceParameter( |
276 "source_dependency", net_log_.source()))); | 277 "source_dependency", net_log_.source()))); |
277 | 278 |
278 requests_.push_back(request); | 279 requests_.push_back(request); |
279 } | 280 } |
280 | 281 |
281 void HandleResult(const CertVerifier::CachedResult& verify_result) { | 282 void HandleResult( |
| 283 const MultiThreadedCertVerifier::CachedResult& verify_result) { |
282 worker_ = NULL; | 284 worker_ = NULL; |
283 net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_JOB, NULL); | 285 net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_JOB, NULL); |
284 UMA_HISTOGRAM_CUSTOM_TIMES("Net.CertVerifier_Job_Latency", | 286 UMA_HISTOGRAM_CUSTOM_TIMES("Net.CertVerifier_Job_Latency", |
285 base::TimeTicks::Now() - start_time_, | 287 base::TimeTicks::Now() - start_time_, |
286 base::TimeDelta::FromMilliseconds(1), | 288 base::TimeDelta::FromMilliseconds(1), |
287 base::TimeDelta::FromMinutes(10), | 289 base::TimeDelta::FromMinutes(10), |
288 100); | 290 100); |
289 PostAll(verify_result); | 291 PostAll(verify_result); |
290 } | 292 } |
291 | 293 |
292 private: | 294 private: |
293 void PostAll(const CertVerifier::CachedResult& verify_result) { | 295 void PostAll(const MultiThreadedCertVerifier::CachedResult& verify_result) { |
294 std::vector<CertVerifierRequest*> requests; | 296 std::vector<CertVerifierRequest*> requests; |
295 requests_.swap(requests); | 297 requests_.swap(requests); |
296 | 298 |
297 for (std::vector<CertVerifierRequest*>::iterator | 299 for (std::vector<CertVerifierRequest*>::iterator |
298 i = requests.begin(); i != requests.end(); i++) { | 300 i = requests.begin(); i != requests.end(); i++) { |
299 (*i)->Post(verify_result); | 301 (*i)->Post(verify_result); |
300 // Post() causes the CertVerifierRequest to delete itself. | 302 // Post() causes the CertVerifierRequest to delete itself. |
301 } | 303 } |
302 } | 304 } |
303 | 305 |
304 void DeleteAllCanceled() { | 306 void DeleteAllCanceled() { |
305 for (std::vector<CertVerifierRequest*>::iterator | 307 for (std::vector<CertVerifierRequest*>::iterator |
306 i = requests_.begin(); i != requests_.end(); i++) { | 308 i = requests_.begin(); i != requests_.end(); i++) { |
307 if ((*i)->canceled()) { | 309 if ((*i)->canceled()) { |
308 delete *i; | 310 delete *i; |
309 } else { | 311 } else { |
310 LOG(DFATAL) << "CertVerifierRequest leaked!"; | 312 LOG(DFATAL) << "CertVerifierRequest leaked!"; |
311 } | 313 } |
312 } | 314 } |
313 } | 315 } |
314 | 316 |
315 const base::TimeTicks start_time_; | 317 const base::TimeTicks start_time_; |
316 std::vector<CertVerifierRequest*> requests_; | 318 std::vector<CertVerifierRequest*> requests_; |
317 CertVerifierWorker* worker_; | 319 CertVerifierWorker* worker_; |
318 const BoundNetLog net_log_; | 320 const BoundNetLog net_log_; |
319 }; | 321 }; |
320 | 322 |
321 CertVerifier::CertVerifier() | 323 MultiThreadedCertVerifier::MultiThreadedCertVerifier() |
322 : cache_(kMaxCacheEntries), | 324 : cache_(kMaxCacheEntries), |
323 requests_(0), | 325 requests_(0), |
324 cache_hits_(0), | 326 cache_hits_(0), |
325 inflight_joins_(0) { | 327 inflight_joins_(0) { |
326 CertDatabase::AddObserver(this); | 328 CertDatabase::AddObserver(this); |
327 } | 329 } |
328 | 330 |
329 CertVerifier::~CertVerifier() { | 331 MultiThreadedCertVerifier::~MultiThreadedCertVerifier() { |
330 STLDeleteValues(&inflight_); | 332 STLDeleteValues(&inflight_); |
331 | 333 |
332 CertDatabase::RemoveObserver(this); | 334 CertDatabase::RemoveObserver(this); |
333 } | 335 } |
334 | 336 |
335 int CertVerifier::Verify(X509Certificate* cert, | 337 int MultiThreadedCertVerifier::Verify(X509Certificate* cert, |
336 const std::string& hostname, | 338 const std::string& hostname, |
337 int flags, | 339 int flags, |
338 CRLSet* crl_set, | 340 CRLSet* crl_set, |
339 CertVerifyResult* verify_result, | 341 CertVerifyResult* verify_result, |
340 const CompletionCallback& callback, | 342 const CompletionCallback& callback, |
341 RequestHandle* out_req, | 343 RequestHandle* out_req, |
342 const BoundNetLog& net_log) { | 344 const BoundNetLog& net_log) { |
343 DCHECK(CalledOnValidThread()); | 345 DCHECK(CalledOnValidThread()); |
344 | 346 |
345 if (callback.is_null() || !verify_result || hostname.empty()) { | 347 if (callback.is_null() || !verify_result || hostname.empty()) { |
346 *out_req = NULL; | 348 *out_req = NULL; |
347 return ERR_INVALID_ARGUMENT; | 349 return ERR_INVALID_ARGUMENT; |
348 } | 350 } |
349 | 351 |
350 requests_++; | 352 requests_++; |
351 | 353 |
352 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), | 354 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 inflight_.insert(std::make_pair(key, job)); | 389 inflight_.insert(std::make_pair(key, job)); |
388 } | 390 } |
389 | 391 |
390 CertVerifierRequest* request = | 392 CertVerifierRequest* request = |
391 new CertVerifierRequest(callback, verify_result, net_log); | 393 new CertVerifierRequest(callback, verify_result, net_log); |
392 job->AddRequest(request); | 394 job->AddRequest(request); |
393 *out_req = request; | 395 *out_req = request; |
394 return ERR_IO_PENDING; | 396 return ERR_IO_PENDING; |
395 } | 397 } |
396 | 398 |
397 void CertVerifier::CancelRequest(RequestHandle req) { | 399 void MultiThreadedCertVerifier::CancelRequest(RequestHandle req) { |
398 DCHECK(CalledOnValidThread()); | 400 DCHECK(CalledOnValidThread()); |
399 CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req); | 401 CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req); |
400 request->Cancel(); | 402 request->Cancel(); |
401 } | 403 } |
402 | 404 |
403 // HandleResult is called by CertVerifierWorker on the origin message loop. | 405 // HandleResult is called by CertVerifierWorker on the origin message loop. |
404 // It deletes CertVerifierJob. | 406 // It deletes CertVerifierJob. |
405 void CertVerifier::HandleResult(X509Certificate* cert, | 407 void MultiThreadedCertVerifier::HandleResult( |
406 const std::string& hostname, | 408 X509Certificate* cert, |
407 int flags, | 409 const std::string& hostname, |
408 int error, | 410 int flags, |
409 const CertVerifyResult& verify_result) { | 411 int error, |
| 412 const CertVerifyResult& verify_result) { |
410 DCHECK(CalledOnValidThread()); | 413 DCHECK(CalledOnValidThread()); |
411 | 414 |
412 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), | 415 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), |
413 hostname, flags); | 416 hostname, flags); |
414 | 417 |
415 CachedResult cached_result; | 418 CachedResult cached_result; |
416 cached_result.error = error; | 419 cached_result.error = error; |
417 cached_result.result = verify_result; | 420 cached_result.result = verify_result; |
418 cache_.Put(key, cached_result, base::TimeTicks::Now(), | 421 cache_.Put(key, cached_result, base::TimeTicks::Now(), |
419 base::TimeDelta::FromSeconds(kTTLSecs)); | 422 base::TimeDelta::FromSeconds(kTTLSecs)); |
420 | 423 |
421 std::map<RequestParams, CertVerifierJob*>::iterator j; | 424 std::map<RequestParams, CertVerifierJob*>::iterator j; |
422 j = inflight_.find(key); | 425 j = inflight_.find(key); |
423 if (j == inflight_.end()) { | 426 if (j == inflight_.end()) { |
424 NOTREACHED(); | 427 NOTREACHED(); |
425 return; | 428 return; |
426 } | 429 } |
427 CertVerifierJob* job = j->second; | 430 CertVerifierJob* job = j->second; |
428 inflight_.erase(j); | 431 inflight_.erase(j); |
429 | 432 |
430 job->HandleResult(cached_result); | 433 job->HandleResult(cached_result); |
431 delete job; | 434 delete job; |
432 } | 435 } |
433 | 436 |
434 void CertVerifier::OnCertTrustChanged(const X509Certificate* cert) { | 437 void MultiThreadedCertVerifier::OnCertTrustChanged( |
| 438 const X509Certificate* cert) { |
435 DCHECK(CalledOnValidThread()); | 439 DCHECK(CalledOnValidThread()); |
436 | 440 |
437 ClearCache(); | 441 ClearCache(); |
438 } | 442 } |
439 | 443 |
440 ///////////////////////////////////////////////////////////////////// | |
441 | |
442 SingleRequestCertVerifier::SingleRequestCertVerifier( | |
443 CertVerifier* cert_verifier) | |
444 : cert_verifier_(cert_verifier), | |
445 cur_request_(NULL) { | |
446 DCHECK(cert_verifier_ != NULL); | |
447 } | |
448 | |
449 SingleRequestCertVerifier::~SingleRequestCertVerifier() { | |
450 if (cur_request_) { | |
451 cert_verifier_->CancelRequest(cur_request_); | |
452 cur_request_ = NULL; | |
453 } | |
454 } | |
455 | |
456 int SingleRequestCertVerifier::Verify(X509Certificate* cert, | |
457 const std::string& hostname, | |
458 int flags, | |
459 CRLSet* crl_set, | |
460 CertVerifyResult* verify_result, | |
461 const CompletionCallback& callback, | |
462 const BoundNetLog& net_log) { | |
463 // Should not be already in use. | |
464 DCHECK(!cur_request_ && cur_request_callback_.is_null()); | |
465 | |
466 // Do a synchronous verification. | |
467 if (callback.is_null()) | |
468 return cert->Verify(hostname, flags, crl_set, verify_result); | |
469 | |
470 CertVerifier::RequestHandle request = NULL; | |
471 | |
472 // We need to be notified of completion before |callback| is called, so that | |
473 // we can clear out |cur_request_*|. | |
474 int rv = cert_verifier_->Verify( | |
475 cert, hostname, flags, crl_set, verify_result, | |
476 base::Bind(&SingleRequestCertVerifier::OnVerifyCompletion, | |
477 base::Unretained(this)), | |
478 &request, net_log); | |
479 | |
480 if (rv == ERR_IO_PENDING) { | |
481 // Cleared in OnVerifyCompletion(). | |
482 cur_request_ = request; | |
483 cur_request_callback_ = callback; | |
484 } | |
485 | |
486 return rv; | |
487 } | |
488 | |
489 void SingleRequestCertVerifier::OnVerifyCompletion(int result) { | |
490 DCHECK(cur_request_ && !cur_request_callback_.is_null()); | |
491 | |
492 CompletionCallback callback = cur_request_callback_; | |
493 | |
494 // Clear the outstanding request information. | |
495 cur_request_ = NULL; | |
496 cur_request_callback_.Reset(); | |
497 | |
498 // Call the user's original callback. | |
499 callback.Run(result); | |
500 } | |
501 | |
502 } // namespace net | 444 } // namespace net |
OLD | NEW |