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/cert/multi_threaded_cert_verifier.h" | 5 #include "net/cert/multi_threaded_cert_verifier.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <memory> | 8 #include <memory> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
13 #include "base/callback_helpers.h" | 13 #include "base/callback_helpers.h" |
14 #include "base/compiler_specific.h" | 14 #include "base/compiler_specific.h" |
15 #include "base/containers/linked_list.h" | 15 #include "base/containers/linked_list.h" |
16 #include "base/memory/ptr_util.h" | 16 #include "base/memory/ptr_util.h" |
17 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
18 #include "base/metrics/histogram_macros.h" | 18 #include "base/metrics/histogram_macros.h" |
19 #include "base/profiler/scoped_tracker.h" | 19 #include "base/profiler/scoped_tracker.h" |
20 #include "base/sha1.h" | 20 #include "base/sha1.h" |
21 #include "base/threading/worker_pool.h" | 21 #include "base/task_scheduler/post_task.h" |
22 #include "base/time/time.h" | 22 #include "base/time/time.h" |
23 #include "base/trace_event/trace_event.h" | 23 #include "base/trace_event/trace_event.h" |
24 #include "base/values.h" | 24 #include "base/values.h" |
25 #include "net/base/hash_value.h" | 25 #include "net/base/hash_value.h" |
26 #include "net/base/net_errors.h" | 26 #include "net/base/net_errors.h" |
27 #include "net/base/trace_constants.h" | 27 #include "net/base/trace_constants.h" |
28 #include "net/cert/cert_verify_proc.h" | 28 #include "net/cert/cert_verify_proc.h" |
29 #include "net/cert/cert_verify_result.h" | 29 #include "net/cert/cert_verify_result.h" |
30 #include "net/cert/crl_set.h" | 30 #include "net/cert/crl_set.h" |
31 #include "net/cert/x509_certificate.h" | 31 #include "net/cert/x509_certificate.h" |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 | 172 |
173 const NetLogWithSource& net_log() const { return net_log_; } | 173 const NetLogWithSource& net_log() const { return net_log_; } |
174 | 174 |
175 private: | 175 private: |
176 CertVerifierJob* job_; // Not owned. | 176 CertVerifierJob* job_; // Not owned. |
177 CompletionCallback callback_; | 177 CompletionCallback callback_; |
178 CertVerifyResult* verify_result_; | 178 CertVerifyResult* verify_result_; |
179 const NetLogWithSource net_log_; | 179 const NetLogWithSource net_log_; |
180 }; | 180 }; |
181 | 181 |
182 // DoVerifyOnWorkerThread runs the verification synchronously on a worker | 182 // DoVerifyAsync runs the verification in TaskScheduler. The output parameters |
183 // thread. The output parameters (error and result) must remain alive. | 183 // (error and result) must remain alive. |
184 void DoVerifyOnWorkerThread(const scoped_refptr<CertVerifyProc>& verify_proc, | 184 void DoVerifyAsync(const scoped_refptr<CertVerifyProc>& verify_proc, |
185 const scoped_refptr<X509Certificate>& cert, | 185 const scoped_refptr<X509Certificate>& cert, |
186 const std::string& hostname, | 186 const std::string& hostname, |
187 const std::string& ocsp_response, | 187 const std::string& ocsp_response, |
188 int flags, | 188 int flags, |
189 const scoped_refptr<CRLSet>& crl_set, | 189 const scoped_refptr<CRLSet>& crl_set, |
190 const CertificateList& additional_trust_anchors, | 190 const CertificateList& additional_trust_anchors, |
191 int* error, | 191 int* error, |
192 CertVerifyResult* result) { | 192 CertVerifyResult* result) { |
193 TRACE_EVENT0(kNetTracingCategory, "DoVerifyOnWorkerThread"); | 193 TRACE_EVENT0(kNetTracingCategory, "DoVerifyAsync"); |
194 *error = verify_proc->Verify(cert.get(), hostname, ocsp_response, flags, | 194 *error = verify_proc->Verify(cert.get(), hostname, ocsp_response, flags, |
195 crl_set.get(), additional_trust_anchors, result); | 195 crl_set.get(), additional_trust_anchors, result); |
196 | 196 |
197 #if defined(USE_NSS_CERTS) | 197 #if defined(USE_NSS_CERTS) |
198 // Detach the thread from NSPR. | 198 // Detach the thread from NSPR. |
199 // Calling NSS functions attaches the thread to NSPR, which stores | 199 // Calling NSS functions attaches the thread to NSPR, which stores |
200 // the NSPR thread ID in thread-specific data. | 200 // the NSPR thread ID in thread-specific data. |
201 // The threads in our thread pool terminate after we have called | 201 // The threads in our thread pool terminate after we have called |
202 // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets | 202 // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets |
203 // segfaults on shutdown when the threads' thread-specific data | 203 // segfaults on shutdown when the threads' thread-specific data |
(...skipping 22 matching lines...) Expand all Loading... |
226 | 226 |
227 // Indicates whether this was the first job started by the CertVerifier. This | 227 // Indicates whether this was the first job started by the CertVerifier. This |
228 // is only used for logging certain UMA stats. | 228 // is only used for logging certain UMA stats. |
229 void set_is_first_job(bool is_first_job) { is_first_job_ = is_first_job; } | 229 void set_is_first_job(bool is_first_job) { is_first_job_ = is_first_job; } |
230 | 230 |
231 const CertVerifier::RequestParams& key() const { return key_; } | 231 const CertVerifier::RequestParams& key() const { return key_; } |
232 | 232 |
233 // Posts a task to the worker pool to do the verification. Once the | 233 // Posts a task to the worker pool to do the verification. Once the |
234 // verification has completed on the worker thread, it will call | 234 // verification has completed on the worker thread, it will call |
235 // OnJobCompleted() on the origin thread. | 235 // OnJobCompleted() on the origin thread. |
236 bool Start(const scoped_refptr<CertVerifyProc>& verify_proc, | 236 void Start(const scoped_refptr<CertVerifyProc>& verify_proc, |
237 const scoped_refptr<CRLSet>& crl_set) { | 237 const scoped_refptr<CRLSet>& crl_set) { |
238 // Owned by the bound reply callback. | 238 // Owned by the bound reply callback. |
239 std::unique_ptr<ResultHelper> owned_result(new ResultHelper()); | 239 std::unique_ptr<ResultHelper> owned_result(new ResultHelper()); |
240 | 240 |
241 // Parameter evaluation order is undefined in C++. Ensure the pointer value | 241 // Parameter evaluation order is undefined in C++. Ensure the pointer value |
242 // is gotten before calling base::Passed(). | 242 // is gotten before calling base::Passed(). |
243 auto* result = owned_result.get(); | 243 auto* result = owned_result.get(); |
244 | 244 |
245 return base::WorkerPool::PostTaskAndReply( | 245 base::PostTaskWithTraitsAndReply( |
246 FROM_HERE, | 246 FROM_HERE, base::TaskTraits() |
247 base::Bind(&DoVerifyOnWorkerThread, verify_proc, key_.certificate(), | 247 .WithShutdownBehavior( |
| 248 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) |
| 249 .MayBlock() |
| 250 .WithBaseSyncPrimitives(), |
| 251 base::Bind(&DoVerifyAsync, verify_proc, key_.certificate(), |
248 key_.hostname(), key_.ocsp_response(), key_.flags(), crl_set, | 252 key_.hostname(), key_.ocsp_response(), key_.flags(), crl_set, |
249 key_.additional_trust_anchors(), &result->error, | 253 key_.additional_trust_anchors(), &result->error, |
250 &result->result), | 254 &result->result), |
251 base::Bind(&CertVerifierJob::OnJobCompleted, | 255 base::Bind(&CertVerifierJob::OnJobCompleted, |
252 weak_ptr_factory_.GetWeakPtr(), base::Passed(&owned_result)), | 256 weak_ptr_factory_.GetWeakPtr(), |
253 true /* task is slow */); | 257 base::Passed(&owned_result))); |
254 } | 258 } |
255 | 259 |
256 ~CertVerifierJob() { | 260 ~CertVerifierJob() { |
257 // If the job is in progress, cancel it. | 261 // If the job is in progress, cancel it. |
258 if (cert_verifier_) { | 262 if (cert_verifier_) { |
259 cert_verifier_ = nullptr; | 263 cert_verifier_ = nullptr; |
260 | 264 |
261 net_log_.AddEvent(NetLogEventType::CANCELLED); | 265 net_log_.AddEvent(NetLogEventType::CANCELLED); |
262 net_log_.EndEvent(NetLogEventType::CERT_VERIFIER_JOB); | 266 net_log_.EndEvent(NetLogEventType::CERT_VERIFIER_JOB); |
263 | 267 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 // See if an identical request is currently in flight. | 369 // See if an identical request is currently in flight. |
366 CertVerifierJob* job = FindJob(params); | 370 CertVerifierJob* job = FindJob(params); |
367 if (job) { | 371 if (job) { |
368 // An identical request is in flight already. We'll just attach our | 372 // An identical request is in flight already. We'll just attach our |
369 // callback. | 373 // callback. |
370 inflight_joins_++; | 374 inflight_joins_++; |
371 } else { | 375 } else { |
372 // Need to make a new job. | 376 // Need to make a new job. |
373 std::unique_ptr<CertVerifierJob> new_job = | 377 std::unique_ptr<CertVerifierJob> new_job = |
374 base::MakeUnique<CertVerifierJob>(params, net_log.net_log(), this); | 378 base::MakeUnique<CertVerifierJob>(params, net_log.net_log(), this); |
375 | 379 new_job->Start(verify_proc_, crl_set); |
376 if (!new_job->Start(verify_proc_, crl_set)) { | |
377 // TODO(wtc): log to the NetLog. | |
378 LOG(ERROR) << "CertVerifierJob couldn't be started."; | |
379 return ERR_INSUFFICIENT_RESOURCES; // Just a guess. | |
380 } | |
381 | 380 |
382 job = new_job.get(); | 381 job = new_job.get(); |
383 inflight_[job] = std::move(new_job); | 382 inflight_[job] = std::move(new_job); |
384 | 383 |
385 if (requests_ == 1) | 384 if (requests_ == 1) |
386 job->set_is_first_job(true); | 385 job->set_is_first_job(true); |
387 } | 386 } |
388 | 387 |
389 std::unique_ptr<CertVerifierRequest> request = | 388 std::unique_ptr<CertVerifierRequest> request = |
390 job->CreateRequest(callback, verify_result, net_log); | 389 job->CreateRequest(callback, verify_result, net_log); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 // The JobSet is kept in sorted order so items can be found using binary | 425 // The JobSet is kept in sorted order so items can be found using binary |
427 // search. | 426 // search. |
428 auto it = std::lower_bound(inflight_.begin(), inflight_.end(), key, | 427 auto it = std::lower_bound(inflight_.begin(), inflight_.end(), key, |
429 JobToRequestParamsComparator()); | 428 JobToRequestParamsComparator()); |
430 if (it != inflight_.end() && !(key < it->first->key())) | 429 if (it != inflight_.end() && !(key < it->first->key())) |
431 return it->first; | 430 return it->first; |
432 return nullptr; | 431 return nullptr; |
433 } | 432 } |
434 | 433 |
435 } // namespace net | 434 } // namespace net |
OLD | NEW |