Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Make CertVerifier a pure virtual interface.

The existing CertVerifier implementation has been renamed to
MultiThreadedCertVerifier, consistent with ProxyResolver naming.

This is patch 1 of N for http://crbug.com/114343

BUG=114343
TEST=Compiles and existing unittests pass.
Review URL: https://chromiumcodereview.appspot.com/9476035

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@128090 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information...
commit 9f59fac37e0af9a1e8a840fa18b6c1c69f221cdf 1 parent 48f6766
rsleevi@chromium.org authored

Showing 45 changed files with 870 additions and 736 deletions. Show diff stats Hide diff stats

  1. +1 1  chrome/browser/chromeos/web_socket_proxy.cc
  2. +1 1  chrome/browser/io_thread.cc
  3. +1 1  chrome/browser/net/connection_tester.cc
  4. +4 3 chrome/browser/net/connection_tester_unittest.cc
  5. +1 1  chrome/service/net/service_url_request_context.cc
  6. +1 1  content/browser/renderer_host/pepper_message_filter.cc
  7. +1 1  content/shell/shell_url_request_context_getter.cc
  8. +4 3 jingle/notifier/base/chrome_async_socket_unittest.cc
  9. +0 1  net/base/cert_database.cc
  10. +1 3 net/base/cert_database.h
  11. +3 490 net/base/cert_verifier.cc
  12. +25 154 net/base/cert_verifier.h
  13. +444 0 net/base/multi_threaded_cert_verifier.cc
  14. +142 0 net/base/multi_threaded_cert_verifier.h
  15. +36 27 net/base/{cert_verifier_unittest.cc → multi_threaded_cert_verifier_unittest.cc}
  16. +74 0 net/base/single_request_cert_verifier.cc
  17. +53 0 net/base/single_request_cert_verifier.h
  18. +1 0  net/base/transport_security_state_unittest.cc
  19. +14 7 net/http/disk_cache_based_ssl_host_info_unittest.cc
  20. +6 4 net/http/http_network_layer_unittest.cc
  21. +2 2 net/http/http_network_transaction_spdy21_unittest.cc
  22. +2 2 net/http/http_network_transaction_spdy2_unittest.cc
  23. +3 2 net/http/http_network_transaction_spdy3_unittest.cc
  24. +4 3 net/http/http_proxy_client_socket_pool_spdy21_unittest.cc
  25. +4 3 net/http/http_proxy_client_socket_pool_spdy2_unittest.cc
  26. +5 3 net/http/http_proxy_client_socket_pool_spdy3_unittest.cc
  27. +1 1  net/http/http_stream_factory_impl_unittest.cc
  28. +5 1 net/net.gyp
  29. +2 1  net/proxy/proxy_script_fetcher_impl_unittest.cc
  30. +1 0  net/socket/ssl_client_socket_mac.cc
  31. +1 0  net/socket/ssl_client_socket_nss.cc
  32. +1 0  net/socket/ssl_client_socket_openssl.cc
  33. +2 2 net/socket/ssl_client_socket_pool_unittest.cc
  34. +1 1  net/socket/ssl_client_socket_unittest.cc
  35. +1 0  net/socket/ssl_client_socket_win.cc
  36. +1 0  net/socket/ssl_host_info.h
  37. +4 3 net/socket/ssl_server_socket_unittest.cc
  38. +4 3 net/spdy/spdy_test_util_spdy2.cc
  39. +3 3 net/spdy/spdy_test_util_spdy3.cc
  40. +3 2 net/tools/fetch/fetch_client.cc
  41. +2 1  net/url_request/url_request_test_util.cc
  42. +1 1  remoting/host/url_request_context.cc
  43. +2 2 remoting/jingle_glue/ssl_socket_adapter.cc
  44. +1 1  remoting/protocol/ssl_hmac_channel_authenticator.cc
  45. +1 1  webkit/tools/test_shell/test_shell_request_context.cc
2  chrome/browser/chromeos/web_socket_proxy.cc
@@ -615,7 +615,7 @@ class SSLChan : public MessageLoopForIO::Watcher {
615 615 net::ClientSocketFactory::GetDefaultFactory();
616 616 net::SSLClientSocketContext ssl_context;
617 617 if (!cert_verifier_.get())
618   - cert_verifier_.reset(new net::CertVerifier());
  618 + cert_verifier_.reset(net::CertVerifier::CreateDefault());
619 619 ssl_context.cert_verifier = cert_verifier_.get();
620 620 socket_.reset(factory->CreateSSLClientSocket(
621 621 handle, host_port_pair_, ssl_config_, NULL, ssl_context));
2  chrome/browser/io_thread.cc
@@ -393,7 +393,7 @@ void IOThread::Init() {
393 393 &system_enable_referrers_));
394 394 globals_->host_resolver.reset(
395 395 CreateGlobalHostResolver(net_log_));
396   - globals_->cert_verifier.reset(new net::CertVerifier);
  396 + globals_->cert_verifier.reset(net::CertVerifier::CreateDefault());
397 397 globals_->transport_security_state.reset(new net::TransportSecurityState(""));
398 398 globals_->ssl_config_service = GetSSLConfigService();
399 399 globals_->http_auth_handler_factory.reset(CreateDefaultAuthHandlerFactory(
2  chrome/browser/net/connection_tester.cc
@@ -72,7 +72,7 @@ class ExperimentURLRequestContext : public net::URLRequestContext {
72 72
73 73 // The rest of the dependencies are standard, and don't depend on the
74 74 // experiment being run.
75   - storage_.set_cert_verifier(new net::CertVerifier);
  75 + storage_.set_cert_verifier(net::CertVerifier::CreateDefault());
76 76 storage_.set_ftp_transaction_factory(
77 77 new net::FtpNetworkLayer(host_resolver()));
78 78 storage_.set_ssl_config_service(new net::SSLConfigServiceDefaults);
7 chrome/browser/net/connection_tester_unittest.cc
@@ -108,7 +108,7 @@ class ConnectionTesterTest : public PlatformTest {
108 108 net::TestServer test_server_;
109 109 ConnectionTesterDelegate test_delegate_;
110 110 net::MockHostResolver host_resolver_;
111   - net::CertVerifier cert_verifier_;
  111 + scoped_ptr<net::CertVerifier> cert_verifier_;
112 112 scoped_ptr<net::ProxyService> proxy_service_;
113 113 scoped_refptr<net::SSLConfigService> ssl_config_service_;
114 114 scoped_ptr<net::HttpTransactionFactory> http_transaction_factory_;
@@ -119,7 +119,8 @@ class ConnectionTesterTest : public PlatformTest {
119 119 private:
120 120 void InitializeRequestContext() {
121 121 proxy_script_fetcher_context_->set_host_resolver(&host_resolver_);
122   - proxy_script_fetcher_context_->set_cert_verifier(&cert_verifier_);
  122 + cert_verifier_.reset(net::CertVerifier::CreateDefault());
  123 + proxy_script_fetcher_context_->set_cert_verifier(cert_verifier_.get());
123 124 proxy_script_fetcher_context_->set_http_auth_handler_factory(
124 125 &http_auth_handler_factory_);
125 126 proxy_service_.reset(net::ProxyService::CreateDirect());
@@ -127,7 +128,7 @@ class ConnectionTesterTest : public PlatformTest {
127 128 ssl_config_service_ = new net::SSLConfigServiceDefaults;
128 129 net::HttpNetworkSession::Params session_params;
129 130 session_params.host_resolver = &host_resolver_;
130   - session_params.cert_verifier = &cert_verifier_;
  131 + session_params.cert_verifier = cert_verifier_.get();
131 132 session_params.http_auth_handler_factory = &http_auth_handler_factory_;
132 133 session_params.ssl_config_service = ssl_config_service_;
133 134 session_params.proxy_service = proxy_service_.get();
2  chrome/service/net/service_url_request_context.cc
@@ -115,7 +115,7 @@ ServiceURLRequestContext::ServiceURLRequestContext(
115 115 NULL));
116 116 storage_.set_proxy_service(net::ProxyService::CreateUsingSystemProxyResolver(
117 117 net_proxy_config_service, 0u, NULL));
118   - storage_.set_cert_verifier(new net::CertVerifier);
  118 + storage_.set_cert_verifier(net::CertVerifier::CreateDefault());
119 119 storage_.set_ftp_transaction_factory(
120 120 new net::FtpNetworkLayer(host_resolver()));
121 121 storage_.set_ssl_config_service(new net::SSLConfigServiceDefaults);
2  content/browser/renderer_host/pepper_message_filter.cc
@@ -167,7 +167,7 @@ net::HostResolver* PepperMessageFilter::GetHostResolver() {
167 167
168 168 net::CertVerifier* PepperMessageFilter::GetCertVerifier() {
169 169 if (!cert_verifier_.get())
170   - cert_verifier_.reset(new net::CertVerifier());
  170 + cert_verifier_.reset(net::CertVerifier::CreateDefault());
171 171
172 172 return cert_verifier_.get();
173 173 }
2  content/shell/shell_url_request_context_getter.cc
@@ -61,7 +61,7 @@ net::URLRequestContext* ShellURLRequestContextGetter::GetURLRequestContext() {
61 61 net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism,
62 62 net::HostResolver::kDefaultRetryAttempts,
63 63 NULL));
64   - storage_->set_cert_verifier(new net::CertVerifier);
  64 + storage_->set_cert_verifier(net::CertVerifier::CreateDefault());
65 65 // TODO(jam): use v8 if possible, look at chrome code.
66 66 storage_->set_proxy_service(
67 67 net::ProxyService::CreateUsingSystemProxyResolver(
7 jingle/notifier/base/chrome_async_socket_unittest.cc
@@ -120,7 +120,8 @@ class MockXmppClientSocketFactory : public ResolvingClientSocketFactory {
120 120 net::ClientSocketFactory* mock_client_socket_factory,
121 121 const net::AddressList& address_list)
122 122 : mock_client_socket_factory_(mock_client_socket_factory),
123   - address_list_(address_list) {
  123 + address_list_(address_list),
  124 + cert_verifier_(net::CertVerifier::CreateDefault()) {
124 125 }
125 126
126 127 // ResolvingClientSocketFactory implementation.
@@ -134,7 +135,7 @@ class MockXmppClientSocketFactory : public ResolvingClientSocketFactory {
134 135 net::ClientSocketHandle* transport_socket,
135 136 const net::HostPortPair& host_and_port) {
136 137 net::SSLClientSocketContext context;
137   - context.cert_verifier = &cert_verifier_;
  138 + context.cert_verifier = cert_verifier_.get();
138 139 return mock_client_socket_factory_->CreateSSLClientSocket(
139 140 transport_socket, host_and_port, ssl_config_, NULL, context);
140 141 }
@@ -143,7 +144,7 @@ class MockXmppClientSocketFactory : public ResolvingClientSocketFactory {
143 144 scoped_ptr<net::ClientSocketFactory> mock_client_socket_factory_;
144 145 net::AddressList address_list_;
145 146 net::SSLConfig ssl_config_;
146   - net::CertVerifier cert_verifier_;
  147 + scoped_ptr<net::CertVerifier> cert_verifier_;
147 148 };
148 149
149 150 class ChromeAsyncSocketTest
1  net/base/cert_database.cc
@@ -6,7 +6,6 @@
6 6
7 7 #include "base/memory/singleton.h"
8 8 #include "base/observer_list_threadsafe.h"
9   -#include "net/base/x509_certificate.h"
10 9
11 10 namespace net {
12 11
4 net/base/cert_database.h
@@ -14,14 +14,12 @@
14 14 #include "base/string16.h"
15 15 #include "net/base/cert_type.h"
16 16 #include "net/base/net_export.h"
  17 +#include "net/base/x509_certificate.h"
17 18
18 19 namespace net {
19 20
20 21 class CryptoModule;
21 22 typedef std::vector<scoped_refptr<CryptoModule> > CryptoModuleList;
22   -class X509Certificate;
23   -typedef std::vector<scoped_refptr<X509Certificate> > CertificateList;
24   -
25 23
26 24 // This class provides functions to manipulate the local
27 25 // certificate store.
493 net/base/cert_verifier.cc
@@ -4,499 +4,12 @@
4 4
5 5 #include "net/base/cert_verifier.h"
6 6
7   -#include "base/bind.h"
8   -#include "base/bind_helpers.h"
9   -#include "base/compiler_specific.h"
10   -#include "base/message_loop.h"
11   -#include "base/metrics/histogram.h"
12   -#include "base/stl_util.h"
13   -#include "base/synchronization/lock.h"
14   -#include "base/time.h"
15   -#include "base/threading/worker_pool.h"
16   -#include "net/base/crl_set.h"
17   -#include "net/base/net_errors.h"
18   -#include "net/base/net_log.h"
19   -#include "net/base/x509_certificate.h"
20   -#include "net/base/x509_certificate_net_log_param.h"
21   -
22   -#if defined(USE_NSS)
23   -#include <private/pprthred.h> // PR_DetachThread
24   -#endif
  7 +#include "net/base/multi_threaded_cert_verifier.h"
25 8
26 9 namespace net {
27 10
28   -////////////////////////////////////////////////////////////////////////////
29   -
30   -// Life of a request:
31   -//
32   -// CertVerifier CertVerifierJob CertVerifierWorker Request
33   -// | (origin loop) (worker loop)
34   -// |
35   -// Verify()
36   -// |---->-------------------<creates>
37   -// |
38   -// |---->----<creates>
39   -// |
40   -// |---->---------------------------------------------------<creates>
41   -// |
42   -// |---->--------------------Start
43   -// | |
44   -// | PostTask
45   -// |
46   -// | <starts verifying>
47   -// |---->-----AddRequest |
48   -// |
49   -// |
50   -// |
51   -// Finish
52   -// |
53   -// PostTask
54   -//
55   -// |
56   -// DoReply
57   -// |----<-----------------------|
58   -// HandleResult
59   -// |
60   -// |---->-----HandleResult
61   -// |
62   -// |------>-----------------------------------Post
63   -//
64   -//
65   -//
66   -// On a cache hit, CertVerifier::Verify() returns synchronously without
67   -// posting a task to a worker thread.
68   -
69   -namespace {
70   -
71   -// The default value of max_cache_entries_.
72   -const unsigned kMaxCacheEntries = 256;
73   -
74   -// The number of seconds for which we'll cache a cache entry.
75   -const unsigned kTTLSecs = 1800; // 30 minutes.
76   -
77   -} // namespace
78   -
79   -CertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {}
80   -
81   -CertVerifier::CachedResult::~CachedResult() {}
82   -
83   -// Represents the output and result callback of a request.
84   -class CertVerifierRequest {
85   - public:
86   - CertVerifierRequest(const CompletionCallback& callback,
87   - CertVerifyResult* verify_result,
88   - const BoundNetLog& net_log)
89   - : callback_(callback),
90   - verify_result_(verify_result),
91   - net_log_(net_log) {
92   - net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL);
93   - }
94   -
95   - ~CertVerifierRequest() {
96   - }
97   -
98   - // Ensures that the result callback will never be made.
99   - void Cancel() {
100   - callback_.Reset();
101   - verify_result_ = NULL;
102   - net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
103   - net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL);
104   - }
105   -
106   - // Copies the contents of |verify_result| to the caller's
107   - // CertVerifyResult and calls the callback.
108   - void Post(const CertVerifier::CachedResult& verify_result) {
109   - if (!callback_.is_null()) {
110   - net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL);
111   - *verify_result_ = verify_result.result;
112   - callback_.Run(verify_result.error);
113   - }
114   - delete this;
115   - }
116   -
117   - bool canceled() const { return callback_.is_null(); }
118   -
119   - const BoundNetLog& net_log() const { return net_log_; }
120   -
121   - private:
122   - CompletionCallback callback_;
123   - CertVerifyResult* verify_result_;
124   - const BoundNetLog net_log_;
125   -};
126   -
127   -
128   -// CertVerifierWorker runs on a worker thread and takes care of the blocking
129   -// process of performing the certificate verification. Deletes itself
130   -// eventually if Start() succeeds.
131   -class CertVerifierWorker {
132   - public:
133   - CertVerifierWorker(X509Certificate* cert,
134   - const std::string& hostname,
135   - int flags,
136   - CRLSet* crl_set,
137   - CertVerifier* cert_verifier)
138   - : cert_(cert),
139   - hostname_(hostname),
140   - flags_(flags),
141   - crl_set_(crl_set),
142   - origin_loop_(MessageLoop::current()),
143   - cert_verifier_(cert_verifier),
144   - canceled_(false),
145   - error_(ERR_FAILED) {
146   - }
147   -
148   - // Returns the certificate being verified. May only be called /before/
149   - // Start() is called.
150   - X509Certificate* certificate() const { return cert_; }
151   -
152   - bool Start() {
153   - DCHECK_EQ(MessageLoop::current(), origin_loop_);
154   -
155   - return base::WorkerPool::PostTask(
156   - FROM_HERE, base::Bind(&CertVerifierWorker::Run, base::Unretained(this)),
157   - true /* task is slow */);
158   - }
159   -
160   - // Cancel is called from the origin loop when the CertVerifier is getting
161   - // deleted.
162   - void Cancel() {
163   - DCHECK_EQ(MessageLoop::current(), origin_loop_);
164   - base::AutoLock locked(lock_);
165   - canceled_ = true;
166   - }
167   -
168   - private:
169   - void Run() {
170   - // Runs on a worker thread.
171   - error_ = cert_->Verify(hostname_, flags_, crl_set_, &verify_result_);
172   -#if defined(USE_NSS)
173   - // Detach the thread from NSPR.
174   - // Calling NSS functions attaches the thread to NSPR, which stores
175   - // the NSPR thread ID in thread-specific data.
176   - // The threads in our thread pool terminate after we have called
177   - // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets
178   - // segfaults on shutdown when the threads' thread-specific data
179   - // destructors run.
180   - PR_DetachThread();
181   -#endif
182   - Finish();
183   - }
184   -
185   - // DoReply runs on the origin thread.
186   - void DoReply() {
187   - DCHECK_EQ(MessageLoop::current(), origin_loop_);
188   - {
189   - // We lock here because the worker thread could still be in Finished,
190   - // after the PostTask, but before unlocking |lock_|. If we do not lock in
191   - // this case, we will end up deleting a locked Lock, which can lead to
192   - // memory leaks or worse errors.
193   - base::AutoLock locked(lock_);
194   - if (!canceled_) {
195   - cert_verifier_->HandleResult(cert_, hostname_, flags_,
196   - error_, verify_result_);
197   - }
198   - }
199   - delete this;
200   - }
201   -
202   - void Finish() {
203   - // Runs on the worker thread.
204   - // We assume that the origin loop outlives the CertVerifier. If the
205   - // CertVerifier is deleted, it will call Cancel on us. If it does so
206   - // before the Acquire, we'll delete ourselves and return. If it's trying to
207   - // do so concurrently, then it'll block on the lock and we'll call PostTask
208   - // while the CertVerifier (and therefore the MessageLoop) is still alive.
209   - // 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   - // in DoReply.
212   -
213   - bool canceled;
214   - {
215   - base::AutoLock locked(lock_);
216   - canceled = canceled_;
217   - if (!canceled) {
218   - origin_loop_->PostTask(
219   - FROM_HERE, base::Bind(
220   - &CertVerifierWorker::DoReply, base::Unretained(this)));
221   - }
222   - }
223   -
224   - if (canceled)
225   - delete this;
226   - }
227   -
228   - scoped_refptr<X509Certificate> cert_;
229   - const std::string hostname_;
230   - const int flags_;
231   - scoped_refptr<CRLSet> crl_set_;
232   - MessageLoop* const origin_loop_;
233   - CertVerifier* const cert_verifier_;
234   -
235   - // lock_ protects canceled_.
236   - base::Lock lock_;
237   -
238   - // If canceled_ is true,
239   - // * origin_loop_ cannot be accessed by the worker thread,
240   - // * cert_verifier_ cannot be accessed by any thread.
241   - bool canceled_;
242   -
243   - int error_;
244   - CertVerifyResult verify_result_;
245   -
246   - DISALLOW_COPY_AND_ASSIGN(CertVerifierWorker);
247   -};
248   -
249   -// A CertVerifierJob is a one-to-one counterpart of a CertVerifierWorker. It
250   -// lives only on the CertVerifier's origin message loop.
251   -class CertVerifierJob {
252   - public:
253   - CertVerifierJob(CertVerifierWorker* worker,
254   - const BoundNetLog& net_log)
255   - : start_time_(base::TimeTicks::Now()),
256   - worker_(worker),
257   - net_log_(net_log) {
258   - scoped_refptr<NetLog::EventParameters> params(
259   - new X509CertificateNetLogParam(worker_->certificate()));
260   - net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_JOB, params);
261   - }
262   -
263   - ~CertVerifierJob() {
264   - if (worker_) {
265   - net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
266   - net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_JOB, NULL);
267   - worker_->Cancel();
268   - DeleteAllCanceled();
269   - }
270   - }
271   -
272   - void AddRequest(CertVerifierRequest* request) {
273   - request->net_log().AddEvent(
274   - NetLog::TYPE_CERT_VERIFIER_REQUEST_BOUND_TO_JOB,
275   - make_scoped_refptr(new NetLogSourceParameter(
276   - "source_dependency", net_log_.source())));
277   -
278   - requests_.push_back(request);
279   - }
280   -
281   - void HandleResult(const CertVerifier::CachedResult& verify_result) {
282   - worker_ = NULL;
283   - net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_JOB, NULL);
284   - UMA_HISTOGRAM_CUSTOM_TIMES("Net.CertVerifier_Job_Latency",
285   - base::TimeTicks::Now() - start_time_,
286   - base::TimeDelta::FromMilliseconds(1),
287   - base::TimeDelta::FromMinutes(10),
288   - 100);
289   - PostAll(verify_result);
290   - }
291   -
292   - private:
293   - void PostAll(const CertVerifier::CachedResult& verify_result) {
294   - std::vector<CertVerifierRequest*> requests;
295   - requests_.swap(requests);
296   -
297   - for (std::vector<CertVerifierRequest*>::iterator
298   - i = requests.begin(); i != requests.end(); i++) {
299   - (*i)->Post(verify_result);
300   - // Post() causes the CertVerifierRequest to delete itself.
301   - }
302   - }
303   -
304   - void DeleteAllCanceled() {
305   - for (std::vector<CertVerifierRequest*>::iterator
306   - i = requests_.begin(); i != requests_.end(); i++) {
307   - if ((*i)->canceled()) {
308   - delete *i;
309   - } else {
310   - LOG(DFATAL) << "CertVerifierRequest leaked!";
311   - }
312   - }
313   - }
314   -
315   - const base::TimeTicks start_time_;
316   - std::vector<CertVerifierRequest*> requests_;
317   - CertVerifierWorker* worker_;
318   - const BoundNetLog net_log_;
319   -};
320   -
321   -CertVerifier::CertVerifier()
322   - : cache_(kMaxCacheEntries),
323   - requests_(0),
324   - cache_hits_(0),
325   - inflight_joins_(0) {
326   - CertDatabase::AddObserver(this);
327   -}
328   -
329   -CertVerifier::~CertVerifier() {
330   - STLDeleteValues(&inflight_);
331   -
332   - CertDatabase::RemoveObserver(this);
333   -}
334   -
335   -int CertVerifier::Verify(X509Certificate* cert,
336   - const std::string& hostname,
337   - int flags,
338   - CRLSet* crl_set,
339   - CertVerifyResult* verify_result,
340   - const CompletionCallback& callback,
341   - RequestHandle* out_req,
342   - const BoundNetLog& net_log) {
343   - DCHECK(CalledOnValidThread());
344   -
345   - if (callback.is_null() || !verify_result || hostname.empty()) {
346   - *out_req = NULL;
347   - return ERR_INVALID_ARGUMENT;
348   - }
349   -
350   - requests_++;
351   -
352   - const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(),
353   - hostname, flags);
354   - const CertVerifierCache::value_type* cached_entry =
355   - cache_.Get(key, base::TimeTicks::Now());
356   - if (cached_entry) {
357   - ++cache_hits_;
358   - *out_req = NULL;
359   - *verify_result = cached_entry->result;
360   - return cached_entry->error;
361   - }
362   -
363   - // No cache hit. See if an identical request is currently in flight.
364   - CertVerifierJob* job;
365   - std::map<RequestParams, CertVerifierJob*>::const_iterator j;
366   - j = inflight_.find(key);
367   - if (j != inflight_.end()) {
368   - // An identical request is in flight already. We'll just attach our
369   - // callback.
370   - inflight_joins_++;
371   - job = j->second;
372   - } else {
373   - // Need to make a new request.
374   - CertVerifierWorker* worker = new CertVerifierWorker(cert, hostname, flags,
375   - crl_set, this);
376   - job = new CertVerifierJob(
377   - worker,
378   - BoundNetLog::Make(net_log.net_log(), NetLog::SOURCE_CERT_VERIFIER_JOB));
379   - if (!worker->Start()) {
380   - delete job;
381   - delete worker;
382   - *out_req = NULL;
383   - // TODO(wtc): log to the NetLog.
384   - LOG(ERROR) << "CertVerifierWorker couldn't be started.";
385   - return ERR_INSUFFICIENT_RESOURCES; // Just a guess.
386   - }
387   - inflight_.insert(std::make_pair(key, job));
388   - }
389   -
390   - CertVerifierRequest* request =
391   - new CertVerifierRequest(callback, verify_result, net_log);
392   - job->AddRequest(request);
393   - *out_req = request;
394   - return ERR_IO_PENDING;
395   -}
396   -
397   -void CertVerifier::CancelRequest(RequestHandle req) {
398   - DCHECK(CalledOnValidThread());
399   - CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req);
400   - request->Cancel();
401   -}
402   -
403   -// HandleResult is called by CertVerifierWorker on the origin message loop.
404   -// It deletes CertVerifierJob.
405   -void CertVerifier::HandleResult(X509Certificate* cert,
406   - const std::string& hostname,
407   - int flags,
408   - int error,
409   - const CertVerifyResult& verify_result) {
410   - DCHECK(CalledOnValidThread());
411   -
412   - const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(),
413   - hostname, flags);
414   -
415   - CachedResult cached_result;
416   - cached_result.error = error;
417   - cached_result.result = verify_result;
418   - cache_.Put(key, cached_result, base::TimeTicks::Now(),
419   - base::TimeDelta::FromSeconds(kTTLSecs));
420   -
421   - std::map<RequestParams, CertVerifierJob*>::iterator j;
422   - j = inflight_.find(key);
423   - if (j == inflight_.end()) {
424   - NOTREACHED();
425   - return;
426   - }
427   - CertVerifierJob* job = j->second;
428   - inflight_.erase(j);
429   -
430   - job->HandleResult(cached_result);
431   - delete job;
432   -}
433   -
434   -void CertVerifier::OnCertTrustChanged(const X509Certificate* cert) {
435   - DCHECK(CalledOnValidThread());
436   -
437   - ClearCache();
438   -}
439   -
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);
  11 +CertVerifier* CertVerifier::CreateDefault() {
  12 + return new MultiThreadedCertVerifier();
500 13 }
501 14
502 15 } // namespace net
179 net/base/cert_verifier.h
@@ -6,50 +6,36 @@
6 6 #define NET_BASE_CERT_VERIFIER_H_
7 7 #pragma once
8 8
9   -#include <map>
10 9 #include <string>
11 10
12 11 #include "base/basictypes.h"
13   -#include "base/gtest_prod_util.h"
14   -#include "base/memory/scoped_ptr.h"
15   -#include "base/threading/non_thread_safe.h"
16   -#include "net/base/cert_database.h"
17   -#include "net/base/cert_verify_result.h"
18 12 #include "net/base/completion_callback.h"
19   -#include "net/base/expiring_cache.h"
20 13 #include "net/base/net_export.h"
21   -#include "net/base/x509_cert_types.h"
22 14
23 15 namespace net {
24 16
25 17 class BoundNetLog;
26   -class CertVerifierJob;
27   -class CertVerifierWorker;
  18 +class CertVerifyResult;
28 19 class CRLSet;
29 20 class X509Certificate;
30 21
31 22 // CertVerifier represents a service for verifying certificates.
32 23 //
33   -// CertVerifier can handle multiple requests at a time, so when canceling a
34   -// request the RequestHandle that was returned by Verify() needs to be
35   -// given. A simpler alternative for consumers that only have 1 outstanding
36   -// request at a time is to create a SingleRequestCertVerifier wrapper around
37   -// CertVerifier (which will automatically cancel the single request when it
38   -// goes out of scope).
39   -class NET_EXPORT CertVerifier : NON_EXPORTED_BASE(public base::NonThreadSafe),
40   - public CertDatabase::Observer {
  24 +// CertVerifiers can handle multiple requests at a time. A simpler alternative
  25 +// for consumers that only have 1 outstanding request at a time is to create a
  26 +// SingleRequestCertVerifier wrapper around CertVerifier (which will
  27 +// automatically cancel the single request when it goes out of scope).
  28 +class NET_EXPORT CertVerifier {
41 29 public:
42   - // Opaque type used to cancel a request.
  30 + // Opaque pointer type used to cancel outstanding requests.
43 31 typedef void* RequestHandle;
44 32
45   - CertVerifier();
46   -
47   - // When the verifier is destroyed, all certificate verifications requests are
  33 + // When the verifier is destroyed, all certificate verification requests are
48 34 // canceled, and their completion callbacks will not be called.
49   - virtual ~CertVerifier();
  35 + virtual ~CertVerifier() {}
50 36
51   - // Verifies the given certificate against the given hostname. Returns OK if
52   - // successful or an error code upon failure.
  37 + // Verifies the given certificate against the given hostname as an SSL server.
  38 + // Returns OK if successful or an error code upon failure.
53 39 //
54 40 // The |*verify_result| structure, including the |verify_result->cert_status|
55 41 // bitmask, is always filled out regardless of the return value. If the
@@ -76,139 +62,24 @@ class NET_EXPORT CertVerifier : NON_EXPORTED_BASE(public base::NonThreadSafe),
76 62 // If |out_req| is non-NULL, then |*out_req| will be filled with a handle to
77 63 // the async request. This handle is not valid after the request has
78 64 // completed.
79   - int Verify(X509Certificate* cert,
80   - const std::string& hostname,
81   - int flags,
82   - CRLSet* crl_set,
83   - CertVerifyResult* verify_result,
84   - const CompletionCallback& callback,
85   - RequestHandle* out_req,
86   - const BoundNetLog& net_log);
  65 + //
  66 + // TODO(rsleevi): Move CRLSet* out of the CertVerifier signature.
  67 + virtual int Verify(X509Certificate* cert,
  68 + const std::string& hostname,
  69 + int flags,
  70 + CRLSet* crl_set,
  71 + CertVerifyResult* verify_result,
  72 + const CompletionCallback& callback,
  73 + RequestHandle* out_req,
  74 + const BoundNetLog& net_log) = 0;
87 75
88 76 // Cancels the specified request. |req| is the handle returned by Verify().
89 77 // After a request is canceled, its completion callback will not be called.
90   - void CancelRequest(RequestHandle req);
91   -
92   - private:
93   - friend class CertVerifierWorker; // Calls HandleResult.
94   - friend class CertVerifierRequest;
95   - friend class CertVerifierJob;
96   - FRIEND_TEST_ALL_PREFIXES(CertVerifierTest, CacheHit);
97   - FRIEND_TEST_ALL_PREFIXES(CertVerifierTest, DifferentCACerts);
98   - FRIEND_TEST_ALL_PREFIXES(CertVerifierTest, InflightJoin);
99   - FRIEND_TEST_ALL_PREFIXES(CertVerifierTest, CancelRequest);
100   - FRIEND_TEST_ALL_PREFIXES(CertVerifierTest, RequestParamsComparators);
101   -
102   - // Input parameters of a certificate verification request.
103   - struct RequestParams {
104   - RequestParams(const SHA1Fingerprint& cert_fingerprint_arg,
105   - const SHA1Fingerprint& ca_fingerprint_arg,
106   - const std::string& hostname_arg,
107   - int flags_arg)
108   - : cert_fingerprint(cert_fingerprint_arg),
109   - ca_fingerprint(ca_fingerprint_arg),
110   - hostname(hostname_arg),
111   - flags(flags_arg) {}
112   -
113   - bool operator<(const RequestParams& other) const {
114   - // |flags| is compared before |cert_fingerprint|, |ca_fingerprint|, and
115   - // |hostname| under assumption that integer comparisons are faster than
116   - // memory and string comparisons.
117   - if (flags != other.flags)
118   - return flags < other.flags;
119   - int rv = memcmp(cert_fingerprint.data, other.cert_fingerprint.data,
120   - sizeof(cert_fingerprint.data));
121   - if (rv != 0)
122   - return rv < 0;
123   - rv = memcmp(ca_fingerprint.data, other.ca_fingerprint.data,
124   - sizeof(ca_fingerprint.data));
125   - if (rv != 0)
126   - return rv < 0;
127   - return hostname < other.hostname;
128   - }
129   -
130   - SHA1Fingerprint cert_fingerprint;
131   - SHA1Fingerprint ca_fingerprint;
132   - std::string hostname;
133   - int flags;
134   - };
135   -
136   - // CachedResult contains the result of a certificate verification.
137   - struct CachedResult {
138   - CachedResult();
139   - ~CachedResult();
140   -
141   - int error; // The return value of CertVerifier::Verify.
142   - CertVerifyResult result; // The output of CertVerifier::Verify.
143   - };
144   -
145   - void HandleResult(X509Certificate* cert,
146   - const std::string& hostname,
147   - int flags,
148   - int error,
149   - const CertVerifyResult& verify_result);
150   -
151   - // CertDatabase::Observer methods:
152   - virtual void OnCertTrustChanged(const X509Certificate* cert) OVERRIDE;
153   -
154   - // For unit testing.
155   - void ClearCache() { cache_.Clear(); }
156   - size_t GetCacheSize() const { return cache_.size(); }
157   - uint64 cache_hits() const { return cache_hits_; }
158   - uint64 requests() const { return requests_; }
159   - uint64 inflight_joins() const { return inflight_joins_; }
160   -
161   - // cache_ maps from a request to a cached result.
162   - typedef ExpiringCache<RequestParams, CachedResult> CertVerifierCache;
163   - CertVerifierCache cache_;
164   -
165   - // inflight_ maps from a request to an active verification which is taking
166   - // place.
167   - std::map<RequestParams, CertVerifierJob*> inflight_;
168   -
169   - uint64 requests_;
170   - uint64 cache_hits_;
171   - uint64 inflight_joins_;
172   -
173   - DISALLOW_COPY_AND_ASSIGN(CertVerifier);
174   -};
175   -
176   -// This class represents the task of verifying a certificate. It wraps
177   -// CertVerifier to verify only a single certificate at a time and cancels this
178   -// request when going out of scope.
179   -class SingleRequestCertVerifier {
180   - public:
181   - // |cert_verifier| must remain valid for the lifetime of |this|.
182   - explicit SingleRequestCertVerifier(CertVerifier* cert_verifier);
183   -
184   - // If a completion callback is pending when the verifier is destroyed, the
185   - // certificate verification is canceled, and the completion callback will
186   - // not be called.
187   - ~SingleRequestCertVerifier();
188   -
189   - // Verifies the given certificate, filling out the |verify_result| object
190   - // upon success. See CertVerifier::Verify() for details.
191   - int Verify(X509Certificate* cert,
192   - const std::string& hostname,
193   - int flags,
194   - CRLSet* crl_set,
195   - CertVerifyResult* verify_result,
196   - const CompletionCallback& callback,
197   - const BoundNetLog& net_log);
198   -
199   - private:
200   - // Callback for when the request to |cert_verifier_| completes, so we
201   - // dispatch to the user's callback.
202   - void OnVerifyCompletion(int result);
203   -
204   - // The actual certificate verifier that will handle the request.
205   - CertVerifier* const cert_verifier_;
206   -
207   - // The current request (if any).
208   - CertVerifier::RequestHandle cur_request_;
209   - CompletionCallback cur_request_callback_;
  78 + virtual void CancelRequest(RequestHandle req) = 0;
210 79
211   - DISALLOW_COPY_AND_ASSIGN(SingleRequestCertVerifier);
  80 + // Creates a CertVerifier implementation that verifies certificates using
  81 + // the preferred underlying cryptographic libraries.
  82 + static CertVerifier* CreateDefault();
212 83 };
213 84
214 85 } // namespace net
444 net/base/multi_threaded_cert_verifier.cc
... ... @@ -0,0 +1,444 @@
  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
  3 +// found in the LICENSE file.
  4 +
  5 +#include "net/base/multi_threaded_cert_verifier.h"
  6 +
  7 +#include "base/bind.h"
  8 +#include "base/bind_helpers.h"
  9 +#include "base/compiler_specific.h"
  10 +#include "base/message_loop.h"
  11 +#include "base/metrics/histogram.h"
  12 +#include "base/stl_util.h"
  13 +#include "base/synchronization/lock.h"
  14 +#include "base/time.h"
  15 +#include "base/threading/worker_pool.h"
  16 +#include "net/base/crl_set.h"
  17 +#include "net/base/net_errors.h"
  18 +#include "net/base/net_log.h"
  19 +#include "net/base/x509_certificate.h"
  20 +#include "net/base/x509_certificate_net_log_param.h"
  21 +
  22 +#if defined(USE_NSS)
  23 +#include <private/pprthred.h> // PR_DetachThread
  24 +#endif
  25 +
  26 +namespace net {
  27 +
  28 +////////////////////////////////////////////////////////////////////////////
  29 +
  30 +// Life of a request:
  31 +//
  32 +// MultiThreadedCertVerifier CertVerifierJob CertVerifierWorker Request
  33 +// | (origin loop) (worker loop)
  34 +// |
  35 +// Verify()
  36 +// |---->-------------------------------------<creates>
  37 +// |
  38 +// |---->-------------------<creates>
  39 +// |
  40 +// |---->-------------------------------------------------------<creates>
  41 +// |
  42 +// |---->---------------------------------------Start
  43 +// | |
  44 +// | PostTask
  45 +// |
  46 +// | <starts verifying>
  47 +// |---->-------------------AddRequest |
  48 +// |
  49 +// |
  50 +// |
  51 +// Finish
  52 +// |
  53 +// PostTask
  54 +//
  55 +// |
  56 +// DoReply
  57 +// |----<-----------------------------------------|
  58 +// HandleResult
  59 +// |
  60 +// |---->------------------HandleResult
  61 +// |
  62 +// |------>---------------------------Post
  63 +//
  64 +//
  65 +//
  66 +// On a cache hit, MultiThreadedCertVerifier::Verify() returns synchronously
  67 +// without posting a task to a worker thread.
  68 +
  69 +namespace {
  70 +
  71 +// The default value of max_cache_entries_.
  72 +const unsigned kMaxCacheEntries = 256;
  73 +
  74 +// The number of seconds for which we'll cache a cache entry.
  75 +const unsigned kTTLSecs = 1800; // 30 minutes.
  76 +
  77 +} // namespace
  78 +
  79 +MultiThreadedCertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {}
  80 +
  81 +MultiThreadedCertVerifier::CachedResult::~CachedResult() {}
  82 +
  83 +// Represents the output and result callback of a request.
  84 +class CertVerifierRequest {
  85 + public:
  86 + CertVerifierRequest(const CompletionCallback& callback,
  87 + CertVerifyResult* verify_result,
  88 + const BoundNetLog& net_log)
  89 + : callback_(callback),
  90 + verify_result_(verify_result),
  91 + net_log_(net_log) {
  92 + net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL);
  93 + }
  94 +
  95 + ~CertVerifierRequest() {
  96 + }
  97 +
  98 + // Ensures that the result callback will never be made.
  99 + void Cancel() {
  100 + callback_.Reset();
  101 + verify_result_ = NULL;
  102 + net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
  103 + net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL);
  104 + }
  105 +
  106 + // Copies the contents of |verify_result| to the caller's
  107 + // CertVerifyResult and calls the callback.
  108 + void Post(const MultiThreadedCertVerifier::CachedResult& verify_result) {
  109 + if (!callback_.is_null()) {
  110 + net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL);
  111 + *verify_result_ = verify_result.result;
  112 + callback_.Run(verify_result.error);
  113 + }
  114 + delete this;
  115 + }
  116 +
  117 + bool canceled() const { return callback_.is_null(); }
  118 +
  119 + const BoundNetLog& net_log() const { return net_log_; }
  120 +
  121 + private:
  122 + CompletionCallback callback_;
  123 + CertVerifyResult* verify_result_;
  124 + const BoundNetLog net_log_;
  125 +};
  126 +
  127 +
  128 +// CertVerifierWorker runs on a worker thread and takes care of the blocking
  129 +// process of performing the certificate verification. Deletes itself
  130 +// eventually if Start() succeeds.
  131 +class CertVerifierWorker {
  132 + public:
  133 + CertVerifierWorker(X509Certificate* cert,
  134 + const std::string& hostname,
  135 + int flags,
  136 + CRLSet* crl_set,
  137 + MultiThreadedCertVerifier* cert_verifier)
  138 + : cert_(cert),
  139 + hostname_(hostname),
  140 + flags_(flags),
  141 + crl_set_(crl_set),
  142 + origin_loop_(MessageLoop::current()),
  143 + cert_verifier_(cert_verifier),
  144 + canceled_(false),
  145 + error_(ERR_FAILED) {
  146 + }
  147 +
  148 + // Returns the certificate being verified. May only be called /before/
  149 + // Start() is called.
  150 + X509Certificate* certificate() const { return cert_; }
  151 +
  152 + bool Start() {
  153 + DCHECK_EQ(MessageLoop::current(), origin_loop_);
  154 +
  155 + return base::WorkerPool::PostTask(
  156 + FROM_HERE, base::Bind(&CertVerifierWorker::Run, base::Unretained(this)),
  157 + true /* task is slow */);
  158 + }
  159 +
  160 + // Cancel is called from the origin loop when the MultiThreadedCertVerifier is
  161 + // getting deleted.
  162 + void Cancel() {
  163 + DCHECK_EQ(MessageLoop::current(), origin_loop_);
  164 + base::AutoLock locked(lock_);
  165 + canceled_ = true;
  166 + }
  167 +
  168 + private:
  169 + void Run() {
  170 + // Runs on a worker thread.
  171 + error_ = cert_->Verify(hostname_, flags_, crl_set_, &verify_result_);
  172 +#if defined(USE_NSS)
  173 + // Detach the thread from NSPR.
  174 + // Calling NSS functions attaches the thread to NSPR, which stores
  175 + // the NSPR thread ID in thread-specific data.
  176 + // The threads in our thread pool terminate after we have called
  177 + // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets
  178 + // segfaults on shutdown when the threads' thread-specific data
  179 + // destructors run.
  180 + PR_DetachThread();
  181 +#endif
  182 + Finish();
  183 + }
  184 +
  185 + // DoReply runs on the origin thread.
  186 + void DoReply() {
  187 + DCHECK_EQ(MessageLoop::current(), origin_loop_);
  188 + {
  189 + // We lock here because the worker thread could still be in Finished,
  190 + // after the PostTask, but before unlocking |lock_|. If we do not lock in
  191 + // this case, we will end up deleting a locked Lock, which can lead to
  192 + // memory leaks or worse errors.
  193 + base::AutoLock locked(lock_);
  194 + if (!canceled_) {
  195 + cert_verifier_->HandleResult(cert_, hostname_, flags_,
  196 + error_, verify_result_);
  197 + }
  198 + }
  199 + delete this;
  200 + }
  201 +
  202 + void Finish() {
  203 + // Runs on the worker thread.
  204 + // We assume that the origin loop outlives the MultiThreadedCertVerifier. If
  205 + // the MultiThreadedCertVerifier is deleted, it will call Cancel on us. If
  206 + // it does so before the Acquire, we'll delete ourselves and return. If it's
  207 + // trying to do so concurrently, then it'll block on the lock and we'll call
  208 + // PostTask while the MultiThreadedCertVerifier (and therefore the
  209 + // MessageLoop) is still alive.
  210 + // If it does so after this function, we assume that the MessageLoop will
  211 + // process pending tasks. In which case we'll notice the |canceled_| flag
  212 + // in DoReply.
  213 +
  214 + bool canceled;
  215 + {
  216 + base::AutoLock locked(lock_);
  217 + canceled = canceled_;
  218 + if (!canceled) {
  219 + origin_loop_->PostTask(
  220 + FROM_HERE, base::Bind(
  221 + &CertVerifierWorker::DoReply, base::Unretained(this)));
  222 + }
  223 + }
  224 +
  225 + if (canceled)
  226 + delete this;
  227 + }
  228 +
  229 + scoped_refptr<X509Certificate> cert_;
  230 + const std::string hostname_;
  231 + const int flags_;
  232 + scoped_refptr<CRLSet> crl_set_;
  233 + MessageLoop* const origin_loop_;
  234 + MultiThreadedCertVerifier* const cert_verifier_;
  235 +
  236 + // lock_ protects canceled_.
  237 + base::Lock lock_;
  238 +
  239 + // If canceled_ is true,
  240 + // * origin_loop_ cannot be accessed by the worker thread,
  241 + // * cert_verifier_ cannot be accessed by any thread.
  242 + bool canceled_;
  243 +
  244 + int error_;
  245 + CertVerifyResult verify_result_;
  246 +
  247 + DISALLOW_COPY_AND_ASSIGN(CertVerifierWorker);
  248 +};
  249 +
  250 +// A CertVerifierJob is a one-to-one counterpart of a CertVerifierWorker. It
  251 +// lives only on the CertVerifier's origin message loop.
  252 +class CertVerifierJob {
  253 + public:
  254 + CertVerifierJob(CertVerifierWorker* worker,
  255 + const BoundNetLog& net_log)
  256 + : start_time_(base::TimeTicks::Now()),
  257 + worker_(worker),
  258 + net_log_(net_log) {
  259 + scoped_refptr<NetLog::EventParameters> params(
  260 + new X509CertificateNetLogParam(worker_->certificate()));
  261 + net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_JOB, params);
  262 + }