summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-21 23:18:11 +0000
committerrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-21 23:18:11 +0000
commit9f59fac37e0af9a1e8a840fa18b6c1c69f221cdf (patch)
tree6ac47bc52e32f5a1b9a7917582e993116c0bcf17 /net
parent48f67668c7362e2532636fe241a3f631a0c9945c (diff)
downloadchromium_src-9f59fac37e0af9a1e8a840fa18b6c1c69f221cdf.zip
chromium_src-9f59fac37e0af9a1e8a840fa18b6c1c69f221cdf.tar.gz
chromium_src-9f59fac37e0af9a1e8a840fa18b6c1c69f221cdf.tar.bz2
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
Diffstat (limited to 'net')
-rw-r--r--net/base/cert_database.cc1
-rw-r--r--net/base/cert_database.h4
-rw-r--r--net/base/cert_verifier.cc493
-rw-r--r--net/base/cert_verifier.h179
-rw-r--r--net/base/multi_threaded_cert_verifier.cc444
-rw-r--r--net/base/multi_threaded_cert_verifier.h142
-rw-r--r--net/base/multi_threaded_cert_verifier_unittest.cc (renamed from net/base/cert_verifier_unittest.cc)63
-rw-r--r--net/base/single_request_cert_verifier.cc74
-rw-r--r--net/base/single_request_cert_verifier.h53
-rw-r--r--net/base/transport_security_state_unittest.cc1
-rw-r--r--net/http/disk_cache_based_ssl_host_info_unittest.cc21
-rw-r--r--net/http/http_network_layer_unittest.cc10
-rw-r--r--net/http/http_network_transaction_spdy21_unittest.cc4
-rw-r--r--net/http/http_network_transaction_spdy2_unittest.cc4
-rw-r--r--net/http/http_network_transaction_spdy3_unittest.cc5
-rw-r--r--net/http/http_proxy_client_socket_pool_spdy21_unittest.cc7
-rw-r--r--net/http/http_proxy_client_socket_pool_spdy2_unittest.cc7
-rw-r--r--net/http/http_proxy_client_socket_pool_spdy3_unittest.cc8
-rw-r--r--net/http/http_stream_factory_impl_unittest.cc2
-rw-r--r--net/net.gyp6
-rw-r--r--net/proxy/proxy_script_fetcher_impl_unittest.cc3
-rw-r--r--net/socket/ssl_client_socket_mac.cc1
-rw-r--r--net/socket/ssl_client_socket_nss.cc1
-rw-r--r--net/socket/ssl_client_socket_openssl.cc1
-rw-r--r--net/socket/ssl_client_socket_pool_unittest.cc4
-rw-r--r--net/socket/ssl_client_socket_unittest.cc2
-rw-r--r--net/socket/ssl_client_socket_win.cc1
-rw-r--r--net/socket/ssl_host_info.h1
-rw-r--r--net/socket/ssl_server_socket_unittest.cc7
-rw-r--r--net/spdy/spdy_test_util_spdy2.cc7
-rw-r--r--net/spdy/spdy_test_util_spdy3.cc6
-rw-r--r--net/tools/fetch/fetch_client.cc5
-rw-r--r--net/url_request/url_request_test_util.cc3
33 files changed, 851 insertions, 719 deletions
diff --git a/net/base/cert_database.cc b/net/base/cert_database.cc
index 6f9c609..7930750 100644
--- a/net/base/cert_database.cc
+++ b/net/base/cert_database.cc
@@ -6,7 +6,6 @@
#include "base/memory/singleton.h"
#include "base/observer_list_threadsafe.h"
-#include "net/base/x509_certificate.h"
namespace net {
diff --git a/net/base/cert_database.h b/net/base/cert_database.h
index 9761bd1..2e95624 100644
--- a/net/base/cert_database.h
+++ b/net/base/cert_database.h
@@ -14,14 +14,12 @@
#include "base/string16.h"
#include "net/base/cert_type.h"
#include "net/base/net_export.h"
+#include "net/base/x509_certificate.h"
namespace net {
class CryptoModule;
typedef std::vector<scoped_refptr<CryptoModule> > CryptoModuleList;
-class X509Certificate;
-typedef std::vector<scoped_refptr<X509Certificate> > CertificateList;
-
// This class provides functions to manipulate the local
// certificate store.
diff --git a/net/base/cert_verifier.cc b/net/base/cert_verifier.cc
index f5f0bc2..c86c97b 100644
--- a/net/base/cert_verifier.cc
+++ b/net/base/cert_verifier.cc
@@ -4,499 +4,12 @@
#include "net/base/cert_verifier.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/compiler_specific.h"
-#include "base/message_loop.h"
-#include "base/metrics/histogram.h"
-#include "base/stl_util.h"
-#include "base/synchronization/lock.h"
-#include "base/time.h"
-#include "base/threading/worker_pool.h"
-#include "net/base/crl_set.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_log.h"
-#include "net/base/x509_certificate.h"
-#include "net/base/x509_certificate_net_log_param.h"
-
-#if defined(USE_NSS)
-#include <private/pprthred.h> // PR_DetachThread
-#endif
+#include "net/base/multi_threaded_cert_verifier.h"
namespace net {
-////////////////////////////////////////////////////////////////////////////
-
-// Life of a request:
-//
-// CertVerifier CertVerifierJob CertVerifierWorker Request
-// | (origin loop) (worker loop)
-// |
-// Verify()
-// |---->-------------------<creates>
-// |
-// |---->----<creates>
-// |
-// |---->---------------------------------------------------<creates>
-// |
-// |---->--------------------Start
-// | |
-// | PostTask
-// |
-// | <starts verifying>
-// |---->-----AddRequest |
-// |
-// |
-// |
-// Finish
-// |
-// PostTask
-//
-// |
-// DoReply
-// |----<-----------------------|
-// HandleResult
-// |
-// |---->-----HandleResult
-// |
-// |------>-----------------------------------Post
-//
-//
-//
-// On a cache hit, CertVerifier::Verify() returns synchronously without
-// posting a task to a worker thread.
-
-namespace {
-
-// The default value of max_cache_entries_.
-const unsigned kMaxCacheEntries = 256;
-
-// The number of seconds for which we'll cache a cache entry.
-const unsigned kTTLSecs = 1800; // 30 minutes.
-
-} // namespace
-
-CertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {}
-
-CertVerifier::CachedResult::~CachedResult() {}
-
-// Represents the output and result callback of a request.
-class CertVerifierRequest {
- public:
- CertVerifierRequest(const CompletionCallback& callback,
- CertVerifyResult* verify_result,
- const BoundNetLog& net_log)
- : callback_(callback),
- verify_result_(verify_result),
- net_log_(net_log) {
- net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL);
- }
-
- ~CertVerifierRequest() {
- }
-
- // Ensures that the result callback will never be made.
- void Cancel() {
- callback_.Reset();
- verify_result_ = NULL;
- net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
- net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL);
- }
-
- // Copies the contents of |verify_result| to the caller's
- // CertVerifyResult and calls the callback.
- void Post(const CertVerifier::CachedResult& verify_result) {
- if (!callback_.is_null()) {
- net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL);
- *verify_result_ = verify_result.result;
- callback_.Run(verify_result.error);
- }
- delete this;
- }
-
- bool canceled() const { return callback_.is_null(); }
-
- const BoundNetLog& net_log() const { return net_log_; }
-
- private:
- CompletionCallback callback_;
- CertVerifyResult* verify_result_;
- const BoundNetLog net_log_;
-};
-
-
-// CertVerifierWorker runs on a worker thread and takes care of the blocking
-// process of performing the certificate verification. Deletes itself
-// eventually if Start() succeeds.
-class CertVerifierWorker {
- public:
- CertVerifierWorker(X509Certificate* cert,
- const std::string& hostname,
- int flags,
- CRLSet* crl_set,
- CertVerifier* cert_verifier)
- : cert_(cert),
- hostname_(hostname),
- flags_(flags),
- crl_set_(crl_set),
- origin_loop_(MessageLoop::current()),
- cert_verifier_(cert_verifier),
- canceled_(false),
- error_(ERR_FAILED) {
- }
-
- // Returns the certificate being verified. May only be called /before/
- // Start() is called.
- X509Certificate* certificate() const { return cert_; }
-
- bool Start() {
- DCHECK_EQ(MessageLoop::current(), origin_loop_);
-
- return base::WorkerPool::PostTask(
- FROM_HERE, base::Bind(&CertVerifierWorker::Run, base::Unretained(this)),
- true /* task is slow */);
- }
-
- // Cancel is called from the origin loop when the CertVerifier is getting
- // deleted.
- void Cancel() {
- DCHECK_EQ(MessageLoop::current(), origin_loop_);
- base::AutoLock locked(lock_);
- canceled_ = true;
- }
-
- private:
- void Run() {
- // Runs on a worker thread.
- error_ = cert_->Verify(hostname_, flags_, crl_set_, &verify_result_);
-#if defined(USE_NSS)
- // Detach the thread from NSPR.
- // Calling NSS functions attaches the thread to NSPR, which stores
- // the NSPR thread ID in thread-specific data.
- // The threads in our thread pool terminate after we have called
- // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets
- // segfaults on shutdown when the threads' thread-specific data
- // destructors run.
- PR_DetachThread();
-#endif
- Finish();
- }
-
- // DoReply runs on the origin thread.
- void DoReply() {
- DCHECK_EQ(MessageLoop::current(), origin_loop_);
- {
- // We lock here because the worker thread could still be in Finished,
- // after the PostTask, but before unlocking |lock_|. If we do not lock in
- // this case, we will end up deleting a locked Lock, which can lead to
- // memory leaks or worse errors.
- base::AutoLock locked(lock_);
- if (!canceled_) {
- cert_verifier_->HandleResult(cert_, hostname_, flags_,
- error_, verify_result_);
- }
- }
- delete this;
- }
-
- void Finish() {
- // Runs on the worker thread.
- // We assume that the origin loop outlives the CertVerifier. If the
- // CertVerifier is deleted, it will call Cancel on us. If it does so
- // before the Acquire, we'll delete ourselves and return. If it's trying to
- // do so concurrently, then it'll block on the lock and we'll call PostTask
- // while the CertVerifier (and therefore the MessageLoop) is still alive.
- // If it does so after this function, we assume that the MessageLoop will
- // process pending tasks. In which case we'll notice the |canceled_| flag
- // in DoReply.
-
- bool canceled;
- {
- base::AutoLock locked(lock_);
- canceled = canceled_;
- if (!canceled) {
- origin_loop_->PostTask(
- FROM_HERE, base::Bind(
- &CertVerifierWorker::DoReply, base::Unretained(this)));
- }
- }
-
- if (canceled)
- delete this;
- }
-
- scoped_refptr<X509Certificate> cert_;
- const std::string hostname_;
- const int flags_;
- scoped_refptr<CRLSet> crl_set_;
- MessageLoop* const origin_loop_;
- CertVerifier* const cert_verifier_;
-
- // lock_ protects canceled_.
- base::Lock lock_;
-
- // If canceled_ is true,
- // * origin_loop_ cannot be accessed by the worker thread,
- // * cert_verifier_ cannot be accessed by any thread.
- bool canceled_;
-
- int error_;
- CertVerifyResult verify_result_;
-
- DISALLOW_COPY_AND_ASSIGN(CertVerifierWorker);
-};
-
-// A CertVerifierJob is a one-to-one counterpart of a CertVerifierWorker. It
-// lives only on the CertVerifier's origin message loop.
-class CertVerifierJob {
- public:
- CertVerifierJob(CertVerifierWorker* worker,
- const BoundNetLog& net_log)
- : start_time_(base::TimeTicks::Now()),
- worker_(worker),
- net_log_(net_log) {
- scoped_refptr<NetLog::EventParameters> params(
- new X509CertificateNetLogParam(worker_->certificate()));
- net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_JOB, params);
- }
-
- ~CertVerifierJob() {
- if (worker_) {
- net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
- net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_JOB, NULL);
- worker_->Cancel();
- DeleteAllCanceled();
- }
- }
-
- void AddRequest(CertVerifierRequest* request) {
- request->net_log().AddEvent(
- NetLog::TYPE_CERT_VERIFIER_REQUEST_BOUND_TO_JOB,
- make_scoped_refptr(new NetLogSourceParameter(
- "source_dependency", net_log_.source())));
-
- requests_.push_back(request);
- }
-
- void HandleResult(const CertVerifier::CachedResult& verify_result) {
- worker_ = NULL;
- net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_JOB, NULL);
- UMA_HISTOGRAM_CUSTOM_TIMES("Net.CertVerifier_Job_Latency",
- base::TimeTicks::Now() - start_time_,
- base::TimeDelta::FromMilliseconds(1),
- base::TimeDelta::FromMinutes(10),
- 100);
- PostAll(verify_result);
- }
-
- private:
- void PostAll(const CertVerifier::CachedResult& verify_result) {
- std::vector<CertVerifierRequest*> requests;
- requests_.swap(requests);
-
- for (std::vector<CertVerifierRequest*>::iterator
- i = requests.begin(); i != requests.end(); i++) {
- (*i)->Post(verify_result);
- // Post() causes the CertVerifierRequest to delete itself.
- }
- }
-
- void DeleteAllCanceled() {
- for (std::vector<CertVerifierRequest*>::iterator
- i = requests_.begin(); i != requests_.end(); i++) {
- if ((*i)->canceled()) {
- delete *i;
- } else {
- LOG(DFATAL) << "CertVerifierRequest leaked!";
- }
- }
- }
-
- const base::TimeTicks start_time_;
- std::vector<CertVerifierRequest*> requests_;
- CertVerifierWorker* worker_;
- const BoundNetLog net_log_;
-};
-
-CertVerifier::CertVerifier()
- : cache_(kMaxCacheEntries),
- requests_(0),
- cache_hits_(0),
- inflight_joins_(0) {
- CertDatabase::AddObserver(this);
-}
-
-CertVerifier::~CertVerifier() {
- STLDeleteValues(&inflight_);
-
- CertDatabase::RemoveObserver(this);
-}
-
-int CertVerifier::Verify(X509Certificate* cert,
- const std::string& hostname,
- int flags,
- CRLSet* crl_set,
- CertVerifyResult* verify_result,
- const CompletionCallback& callback,
- RequestHandle* out_req,
- const BoundNetLog& net_log) {
- DCHECK(CalledOnValidThread());
-
- if (callback.is_null() || !verify_result || hostname.empty()) {
- *out_req = NULL;
- return ERR_INVALID_ARGUMENT;
- }
-
- requests_++;
-
- const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(),
- hostname, flags);
- const CertVerifierCache::value_type* cached_entry =
- cache_.Get(key, base::TimeTicks::Now());
- if (cached_entry) {
- ++cache_hits_;
- *out_req = NULL;
- *verify_result = cached_entry->result;
- return cached_entry->error;
- }
-
- // No cache hit. See if an identical request is currently in flight.
- CertVerifierJob* job;
- std::map<RequestParams, CertVerifierJob*>::const_iterator j;
- j = inflight_.find(key);
- if (j != inflight_.end()) {
- // An identical request is in flight already. We'll just attach our
- // callback.
- inflight_joins_++;
- job = j->second;
- } else {
- // Need to make a new request.
- CertVerifierWorker* worker = new CertVerifierWorker(cert, hostname, flags,
- crl_set, this);
- job = new CertVerifierJob(
- worker,
- BoundNetLog::Make(net_log.net_log(), NetLog::SOURCE_CERT_VERIFIER_JOB));
- if (!worker->Start()) {
- delete job;
- delete worker;
- *out_req = NULL;
- // TODO(wtc): log to the NetLog.
- LOG(ERROR) << "CertVerifierWorker couldn't be started.";
- return ERR_INSUFFICIENT_RESOURCES; // Just a guess.
- }
- inflight_.insert(std::make_pair(key, job));
- }
-
- CertVerifierRequest* request =
- new CertVerifierRequest(callback, verify_result, net_log);
- job->AddRequest(request);
- *out_req = request;
- return ERR_IO_PENDING;
-}
-
-void CertVerifier::CancelRequest(RequestHandle req) {
- DCHECK(CalledOnValidThread());
- CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req);
- request->Cancel();
-}
-
-// HandleResult is called by CertVerifierWorker on the origin message loop.
-// It deletes CertVerifierJob.
-void CertVerifier::HandleResult(X509Certificate* cert,
- const std::string& hostname,
- int flags,
- int error,
- const CertVerifyResult& verify_result) {
- DCHECK(CalledOnValidThread());
-
- const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(),
- hostname, flags);
-
- CachedResult cached_result;
- cached_result.error = error;
- cached_result.result = verify_result;
- cache_.Put(key, cached_result, base::TimeTicks::Now(),
- base::TimeDelta::FromSeconds(kTTLSecs));
-
- std::map<RequestParams, CertVerifierJob*>::iterator j;
- j = inflight_.find(key);
- if (j == inflight_.end()) {
- NOTREACHED();
- return;
- }
- CertVerifierJob* job = j->second;
- inflight_.erase(j);
-
- job->HandleResult(cached_result);
- delete job;
-}
-
-void CertVerifier::OnCertTrustChanged(const X509Certificate* cert) {
- DCHECK(CalledOnValidThread());
-
- ClearCache();
-}
-
-/////////////////////////////////////////////////////////////////////
-
-SingleRequestCertVerifier::SingleRequestCertVerifier(
- CertVerifier* cert_verifier)
- : cert_verifier_(cert_verifier),
- cur_request_(NULL) {
- DCHECK(cert_verifier_ != NULL);
-}
-
-SingleRequestCertVerifier::~SingleRequestCertVerifier() {
- if (cur_request_) {
- cert_verifier_->CancelRequest(cur_request_);
- cur_request_ = NULL;
- }
-}
-
-int SingleRequestCertVerifier::Verify(X509Certificate* cert,
- const std::string& hostname,
- int flags,
- CRLSet* crl_set,
- CertVerifyResult* verify_result,
- const CompletionCallback& callback,
- const BoundNetLog& net_log) {
- // Should not be already in use.
- DCHECK(!cur_request_ && cur_request_callback_.is_null());
-
- // Do a synchronous verification.
- if (callback.is_null())
- return cert->Verify(hostname, flags, crl_set, verify_result);
-
- CertVerifier::RequestHandle request = NULL;
-
- // We need to be notified of completion before |callback| is called, so that
- // we can clear out |cur_request_*|.
- int rv = cert_verifier_->Verify(
- cert, hostname, flags, crl_set, verify_result,
- base::Bind(&SingleRequestCertVerifier::OnVerifyCompletion,
- base::Unretained(this)),
- &request, net_log);
-
- if (rv == ERR_IO_PENDING) {
- // Cleared in OnVerifyCompletion().
- cur_request_ = request;
- cur_request_callback_ = callback;
- }
-
- return rv;
-}
-
-void SingleRequestCertVerifier::OnVerifyCompletion(int result) {
- DCHECK(cur_request_ && !cur_request_callback_.is_null());
-
- CompletionCallback callback = cur_request_callback_;
-
- // Clear the outstanding request information.
- cur_request_ = NULL;
- cur_request_callback_.Reset();
-
- // Call the user's original callback.
- callback.Run(result);
+CertVerifier* CertVerifier::CreateDefault() {
+ return new MultiThreadedCertVerifier();
}
} // namespace net
diff --git a/net/base/cert_verifier.h b/net/base/cert_verifier.h
index fae7ec4..18c035f 100644
--- a/net/base/cert_verifier.h
+++ b/net/base/cert_verifier.h
@@ -6,50 +6,36 @@
#define NET_BASE_CERT_VERIFIER_H_
#pragma once
-#include <map>
#include <string>
#include "base/basictypes.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/threading/non_thread_safe.h"
-#include "net/base/cert_database.h"
-#include "net/base/cert_verify_result.h"
#include "net/base/completion_callback.h"
-#include "net/base/expiring_cache.h"
#include "net/base/net_export.h"
-#include "net/base/x509_cert_types.h"
namespace net {
class BoundNetLog;
-class CertVerifierJob;
-class CertVerifierWorker;
+class CertVerifyResult;
class CRLSet;
class X509Certificate;
// CertVerifier represents a service for verifying certificates.
//
-// CertVerifier can handle multiple requests at a time, so when canceling a
-// request the RequestHandle that was returned by Verify() needs to be
-// given. A simpler alternative for consumers that only have 1 outstanding
-// request at a time is to create a SingleRequestCertVerifier wrapper around
-// CertVerifier (which will automatically cancel the single request when it
-// goes out of scope).
-class NET_EXPORT CertVerifier : NON_EXPORTED_BASE(public base::NonThreadSafe),
- public CertDatabase::Observer {
+// CertVerifiers can handle multiple requests at a time. A simpler alternative
+// for consumers that only have 1 outstanding request at a time is to create a
+// SingleRequestCertVerifier wrapper around CertVerifier (which will
+// automatically cancel the single request when it goes out of scope).
+class NET_EXPORT CertVerifier {
public:
- // Opaque type used to cancel a request.
+ // Opaque pointer type used to cancel outstanding requests.
typedef void* RequestHandle;
- CertVerifier();
-
- // When the verifier is destroyed, all certificate verifications requests are
+ // When the verifier is destroyed, all certificate verification requests are
// canceled, and their completion callbacks will not be called.
- virtual ~CertVerifier();
+ virtual ~CertVerifier() {}
- // Verifies the given certificate against the given hostname. Returns OK if
- // successful or an error code upon failure.
+ // Verifies the given certificate against the given hostname as an SSL server.
+ // Returns OK if successful or an error code upon failure.
//
// The |*verify_result| structure, including the |verify_result->cert_status|
// 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),
// If |out_req| is non-NULL, then |*out_req| will be filled with a handle to
// the async request. This handle is not valid after the request has
// completed.
- int Verify(X509Certificate* cert,
- const std::string& hostname,
- int flags,
- CRLSet* crl_set,
- CertVerifyResult* verify_result,
- const CompletionCallback& callback,
- RequestHandle* out_req,
- const BoundNetLog& net_log);
+ //
+ // TODO(rsleevi): Move CRLSet* out of the CertVerifier signature.
+ virtual int Verify(X509Certificate* cert,
+ const std::string& hostname,
+ int flags,
+ CRLSet* crl_set,
+ CertVerifyResult* verify_result,
+ const CompletionCallback& callback,
+ RequestHandle* out_req,
+ const BoundNetLog& net_log) = 0;
// Cancels the specified request. |req| is the handle returned by Verify().
// After a request is canceled, its completion callback will not be called.
- void CancelRequest(RequestHandle req);
-
- private:
- friend class CertVerifierWorker; // Calls HandleResult.
- friend class CertVerifierRequest;
- friend class CertVerifierJob;
- FRIEND_TEST_ALL_PREFIXES(CertVerifierTest, CacheHit);
- FRIEND_TEST_ALL_PREFIXES(CertVerifierTest, DifferentCACerts);
- FRIEND_TEST_ALL_PREFIXES(CertVerifierTest, InflightJoin);
- FRIEND_TEST_ALL_PREFIXES(CertVerifierTest, CancelRequest);
- FRIEND_TEST_ALL_PREFIXES(CertVerifierTest, RequestParamsComparators);
-
- // Input parameters of a certificate verification request.
- struct RequestParams {
- RequestParams(const SHA1Fingerprint& cert_fingerprint_arg,
- const SHA1Fingerprint& ca_fingerprint_arg,
- const std::string& hostname_arg,
- int flags_arg)
- : cert_fingerprint(cert_fingerprint_arg),
- ca_fingerprint(ca_fingerprint_arg),
- hostname(hostname_arg),
- flags(flags_arg) {}
-
- bool operator<(const RequestParams& other) const {
- // |flags| is compared before |cert_fingerprint|, |ca_fingerprint|, and
- // |hostname| under assumption that integer comparisons are faster than
- // memory and string comparisons.
- if (flags != other.flags)
- return flags < other.flags;
- int rv = memcmp(cert_fingerprint.data, other.cert_fingerprint.data,
- sizeof(cert_fingerprint.data));
- if (rv != 0)
- return rv < 0;
- rv = memcmp(ca_fingerprint.data, other.ca_fingerprint.data,
- sizeof(ca_fingerprint.data));
- if (rv != 0)
- return rv < 0;
- return hostname < other.hostname;
- }
-
- SHA1Fingerprint cert_fingerprint;
- SHA1Fingerprint ca_fingerprint;
- std::string hostname;
- int flags;
- };
-
- // CachedResult contains the result of a certificate verification.
- struct CachedResult {
- CachedResult();
- ~CachedResult();
-
- int error; // The return value of CertVerifier::Verify.
- CertVerifyResult result; // The output of CertVerifier::Verify.
- };
-
- void HandleResult(X509Certificate* cert,
- const std::string& hostname,
- int flags,
- int error,
- const CertVerifyResult& verify_result);
-
- // CertDatabase::Observer methods:
- virtual void OnCertTrustChanged(const X509Certificate* cert) OVERRIDE;
-
- // For unit testing.
- void ClearCache() { cache_.Clear(); }
- size_t GetCacheSize() const { return cache_.size(); }
- uint64 cache_hits() const { return cache_hits_; }
- uint64 requests() const { return requests_; }
- uint64 inflight_joins() const { return inflight_joins_; }
-
- // cache_ maps from a request to a cached result.
- typedef ExpiringCache<RequestParams, CachedResult> CertVerifierCache;
- CertVerifierCache cache_;
-
- // inflight_ maps from a request to an active verification which is taking
- // place.
- std::map<RequestParams, CertVerifierJob*> inflight_;
-
- uint64 requests_;
- uint64 cache_hits_;
- uint64 inflight_joins_;
-
- DISALLOW_COPY_AND_ASSIGN(CertVerifier);
-};
-
-// This class represents the task of verifying a certificate. It wraps
-// CertVerifier to verify only a single certificate at a time and cancels this
-// request when going out of scope.
-class SingleRequestCertVerifier {
- public:
- // |cert_verifier| must remain valid for the lifetime of |this|.
- explicit SingleRequestCertVerifier(CertVerifier* cert_verifier);
-
- // If a completion callback is pending when the verifier is destroyed, the
- // certificate verification is canceled, and the completion callback will
- // not be called.
- ~SingleRequestCertVerifier();
-
- // Verifies the given certificate, filling out the |verify_result| object
- // upon success. See CertVerifier::Verify() for details.
- int Verify(X509Certificate* cert,
- const std::string& hostname,
- int flags,
- CRLSet* crl_set,
- CertVerifyResult* verify_result,
- const CompletionCallback& callback,
- const BoundNetLog& net_log);
-
- private:
- // Callback for when the request to |cert_verifier_| completes, so we
- // dispatch to the user's callback.
- void OnVerifyCompletion(int result);
-
- // The actual certificate verifier that will handle the request.
- CertVerifier* const cert_verifier_;
-
- // The current request (if any).
- CertVerifier::RequestHandle cur_request_;
- CompletionCallback cur_request_callback_;
+ virtual void CancelRequest(RequestHandle req) = 0;
- DISALLOW_COPY_AND_ASSIGN(SingleRequestCertVerifier);
+ // Creates a CertVerifier implementation that verifies certificates using
+ // the preferred underlying cryptographic libraries.
+ static CertVerifier* CreateDefault();
};
} // namespace net
diff --git a/net/base/multi_threaded_cert_verifier.cc b/net/base/multi_threaded_cert_verifier.cc
new file mode 100644
index 0000000..6a3037b
--- /dev/null
+++ b/net/base/multi_threaded_cert_verifier.cc
@@ -0,0 +1,444 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/multi_threaded_cert_verifier.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/compiler_specific.h"
+#include "base/message_loop.h"
+#include "base/metrics/histogram.h"
+#include "base/stl_util.h"
+#include "base/synchronization/lock.h"
+#include "base/time.h"
+#include "base/threading/worker_pool.h"
+#include "net/base/crl_set.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_log.h"
+#include "net/base/x509_certificate.h"
+#include "net/base/x509_certificate_net_log_param.h"
+
+#if defined(USE_NSS)
+#include <private/pprthred.h> // PR_DetachThread
+#endif
+
+namespace net {
+
+////////////////////////////////////////////////////////////////////////////
+
+// Life of a request:
+//
+// MultiThreadedCertVerifier CertVerifierJob CertVerifierWorker Request
+// | (origin loop) (worker loop)
+// |
+// Verify()
+// |---->-------------------------------------<creates>
+// |
+// |---->-------------------<creates>
+// |
+// |---->-------------------------------------------------------<creates>
+// |
+// |---->---------------------------------------Start
+// | |
+// | PostTask
+// |
+// | <starts verifying>
+// |---->-------------------AddRequest |
+// |
+// |
+// |
+// Finish
+// |
+// PostTask
+//
+// |
+// DoReply
+// |----<-----------------------------------------|
+// HandleResult
+// |
+// |---->------------------HandleResult
+// |
+// |------>---------------------------Post
+//
+//
+//
+// On a cache hit, MultiThreadedCertVerifier::Verify() returns synchronously
+// without posting a task to a worker thread.
+
+namespace {
+
+// The default value of max_cache_entries_.
+const unsigned kMaxCacheEntries = 256;
+
+// The number of seconds for which we'll cache a cache entry.
+const unsigned kTTLSecs = 1800; // 30 minutes.
+
+} // namespace
+
+MultiThreadedCertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {}
+
+MultiThreadedCertVerifier::CachedResult::~CachedResult() {}
+
+// Represents the output and result callback of a request.
+class CertVerifierRequest {
+ public:
+ CertVerifierRequest(const CompletionCallback& callback,
+ CertVerifyResult* verify_result,
+ const BoundNetLog& net_log)
+ : callback_(callback),
+ verify_result_(verify_result),
+ net_log_(net_log) {
+ net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL);
+ }
+
+ ~CertVerifierRequest() {
+ }
+
+ // Ensures that the result callback will never be made.
+ void Cancel() {
+ callback_.Reset();
+ verify_result_ = NULL;
+ net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
+ net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL);
+ }
+
+ // Copies the contents of |verify_result| to the caller's
+ // CertVerifyResult and calls the callback.
+ void Post(const MultiThreadedCertVerifier::CachedResult& verify_result) {
+ if (!callback_.is_null()) {
+ net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL);
+ *verify_result_ = verify_result.result;
+ callback_.Run(verify_result.error);
+ }
+ delete this;
+ }
+
+ bool canceled() const { return callback_.is_null(); }
+
+ const BoundNetLog& net_log() const { return net_log_; }
+
+ private:
+ CompletionCallback callback_;
+ CertVerifyResult* verify_result_;
+ const BoundNetLog net_log_;
+};
+
+
+// CertVerifierWorker runs on a worker thread and takes care of the blocking
+// process of performing the certificate verification. Deletes itself
+// eventually if Start() succeeds.
+class CertVerifierWorker {
+ public:
+ CertVerifierWorker(X509Certificate* cert,
+ const std::string& hostname,
+ int flags,
+ CRLSet* crl_set,
+ MultiThreadedCertVerifier* cert_verifier)
+ : cert_(cert),
+ hostname_(hostname),
+ flags_(flags),
+ crl_set_(crl_set),
+ origin_loop_(MessageLoop::current()),
+ cert_verifier_(cert_verifier),
+ canceled_(false),
+ error_(ERR_FAILED) {
+ }
+
+ // Returns the certificate being verified. May only be called /before/
+ // Start() is called.
+ X509Certificate* certificate() const { return cert_; }
+
+ bool Start() {
+ DCHECK_EQ(MessageLoop::current(), origin_loop_);
+
+ return base::WorkerPool::PostTask(
+ FROM_HERE, base::Bind(&CertVerifierWorker::Run, base::Unretained(this)),
+ true /* task is slow */);
+ }
+
+ // Cancel is called from the origin loop when the MultiThreadedCertVerifier is
+ // getting deleted.
+ void Cancel() {
+ DCHECK_EQ(MessageLoop::current(), origin_loop_);
+ base::AutoLock locked(lock_);
+ canceled_ = true;
+ }
+
+ private:
+ void Run() {
+ // Runs on a worker thread.
+ error_ = cert_->Verify(hostname_, flags_, crl_set_, &verify_result_);
+#if defined(USE_NSS)
+ // Detach the thread from NSPR.
+ // Calling NSS functions attaches the thread to NSPR, which stores
+ // the NSPR thread ID in thread-specific data.
+ // The threads in our thread pool terminate after we have called
+ // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets
+ // segfaults on shutdown when the threads' thread-specific data
+ // destructors run.
+ PR_DetachThread();
+#endif
+ Finish();
+ }
+
+ // DoReply runs on the origin thread.
+ void DoReply() {
+ DCHECK_EQ(MessageLoop::current(), origin_loop_);
+ {
+ // We lock here because the worker thread could still be in Finished,
+ // after the PostTask, but before unlocking |lock_|. If we do not lock in
+ // this case, we will end up deleting a locked Lock, which can lead to
+ // memory leaks or worse errors.
+ base::AutoLock locked(lock_);
+ if (!canceled_) {
+ cert_verifier_->HandleResult(cert_, hostname_, flags_,
+ error_, verify_result_);
+ }
+ }
+ delete this;
+ }
+
+ void Finish() {
+ // Runs on the worker thread.
+ // We assume that the origin loop outlives the MultiThreadedCertVerifier. If
+ // the MultiThreadedCertVerifier is deleted, it will call Cancel on us. If
+ // it does so before the Acquire, we'll delete ourselves and return. If it's
+ // trying to do so concurrently, then it'll block on the lock and we'll call
+ // PostTask while the MultiThreadedCertVerifier (and therefore the
+ // MessageLoop) is still alive.
+ // If it does so after this function, we assume that the MessageLoop will
+ // process pending tasks. In which case we'll notice the |canceled_| flag
+ // in DoReply.
+
+ bool canceled;
+ {
+ base::AutoLock locked(lock_);
+ canceled = canceled_;
+ if (!canceled) {
+ origin_loop_->PostTask(
+ FROM_HERE, base::Bind(
+ &CertVerifierWorker::DoReply, base::Unretained(this)));
+ }
+ }
+
+ if (canceled)
+ delete this;
+ }
+
+ scoped_refptr<X509Certificate> cert_;
+ const std::string hostname_;
+ const int flags_;
+ scoped_refptr<CRLSet> crl_set_;
+ MessageLoop* const origin_loop_;
+ MultiThreadedCertVerifier* const cert_verifier_;
+
+ // lock_ protects canceled_.
+ base::Lock lock_;
+
+ // If canceled_ is true,
+ // * origin_loop_ cannot be accessed by the worker thread,
+ // * cert_verifier_ cannot be accessed by any thread.
+ bool canceled_;
+
+ int error_;
+ CertVerifyResult verify_result_;
+
+ DISALLOW_COPY_AND_ASSIGN(CertVerifierWorker);
+};
+
+// A CertVerifierJob is a one-to-one counterpart of a CertVerifierWorker. It
+// lives only on the CertVerifier's origin message loop.
+class CertVerifierJob {
+ public:
+ CertVerifierJob(CertVerifierWorker* worker,
+ const BoundNetLog& net_log)
+ : start_time_(base::TimeTicks::Now()),
+ worker_(worker),
+ net_log_(net_log) {
+ scoped_refptr<NetLog::EventParameters> params(
+ new X509CertificateNetLogParam(worker_->certificate()));
+ net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_JOB, params);
+ }
+
+ ~CertVerifierJob() {
+ if (worker_) {
+ net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
+ net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_JOB, NULL);
+ worker_->Cancel();
+ DeleteAllCanceled();
+ }
+ }
+
+ void AddRequest(CertVerifierRequest* request) {
+ request->net_log().AddEvent(
+ NetLog::TYPE_CERT_VERIFIER_REQUEST_BOUND_TO_JOB,
+ make_scoped_refptr(new NetLogSourceParameter(
+ "source_dependency", net_log_.source())));
+
+ requests_.push_back(request);
+ }
+
+ void HandleResult(
+ const MultiThreadedCertVerifier::CachedResult& verify_result) {
+ worker_ = NULL;
+ net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_JOB, NULL);
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.CertVerifier_Job_Latency",
+ base::TimeTicks::Now() - start_time_,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(10),
+ 100);
+ PostAll(verify_result);
+ }
+
+ private:
+ void PostAll(const MultiThreadedCertVerifier::CachedResult& verify_result) {
+ std::vector<CertVerifierRequest*> requests;
+ requests_.swap(requests);
+
+ for (std::vector<CertVerifierRequest*>::iterator
+ i = requests.begin(); i != requests.end(); i++) {
+ (*i)->Post(verify_result);
+ // Post() causes the CertVerifierRequest to delete itself.
+ }
+ }
+
+ void DeleteAllCanceled() {
+ for (std::vector<CertVerifierRequest*>::iterator
+ i = requests_.begin(); i != requests_.end(); i++) {
+ if ((*i)->canceled()) {
+ delete *i;
+ } else {
+ LOG(DFATAL) << "CertVerifierRequest leaked!";
+ }
+ }
+ }
+
+ const base::TimeTicks start_time_;
+ std::vector<CertVerifierRequest*> requests_;
+ CertVerifierWorker* worker_;
+ const BoundNetLog net_log_;
+};
+
+MultiThreadedCertVerifier::MultiThreadedCertVerifier()
+ : cache_(kMaxCacheEntries),
+ requests_(0),
+ cache_hits_(0),
+ inflight_joins_(0) {
+ CertDatabase::AddObserver(this);
+}
+
+MultiThreadedCertVerifier::~MultiThreadedCertVerifier() {
+ STLDeleteValues(&inflight_);
+
+ CertDatabase::RemoveObserver(this);
+}
+
+int MultiThreadedCertVerifier::Verify(X509Certificate* cert,
+ const std::string& hostname,
+ int flags,
+ CRLSet* crl_set,
+ CertVerifyResult* verify_result,
+ const CompletionCallback& callback,
+ RequestHandle* out_req,
+ const BoundNetLog& net_log) {
+ DCHECK(CalledOnValidThread());
+
+ if (callback.is_null() || !verify_result || hostname.empty()) {
+ *out_req = NULL;
+ return ERR_INVALID_ARGUMENT;
+ }
+
+ requests_++;
+
+ const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(),
+ hostname, flags);
+ const CertVerifierCache::value_type* cached_entry =
+ cache_.Get(key, base::TimeTicks::Now());
+ if (cached_entry) {
+ ++cache_hits_;
+ *out_req = NULL;
+ *verify_result = cached_entry->result;
+ return cached_entry->error;
+ }
+
+ // No cache hit. See if an identical request is currently in flight.
+ CertVerifierJob* job;
+ std::map<RequestParams, CertVerifierJob*>::const_iterator j;
+ j = inflight_.find(key);
+ if (j != inflight_.end()) {
+ // An identical request is in flight already. We'll just attach our
+ // callback.
+ inflight_joins_++;
+ job = j->second;
+ } else {
+ // Need to make a new request.
+ CertVerifierWorker* worker = new CertVerifierWorker(cert, hostname, flags,
+ crl_set, this);
+ job = new CertVerifierJob(
+ worker,
+ BoundNetLog::Make(net_log.net_log(), NetLog::SOURCE_CERT_VERIFIER_JOB));
+ if (!worker->Start()) {
+ delete job;
+ delete worker;
+ *out_req = NULL;
+ // TODO(wtc): log to the NetLog.
+ LOG(ERROR) << "CertVerifierWorker couldn't be started.";
+ return ERR_INSUFFICIENT_RESOURCES; // Just a guess.
+ }
+ inflight_.insert(std::make_pair(key, job));
+ }
+
+ CertVerifierRequest* request =
+ new CertVerifierRequest(callback, verify_result, net_log);
+ job->AddRequest(request);
+ *out_req = request;
+ return ERR_IO_PENDING;
+}
+
+void MultiThreadedCertVerifier::CancelRequest(RequestHandle req) {
+ DCHECK(CalledOnValidThread());
+ CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req);
+ request->Cancel();
+}
+
+// HandleResult is called by CertVerifierWorker on the origin message loop.
+// It deletes CertVerifierJob.
+void MultiThreadedCertVerifier::HandleResult(
+ X509Certificate* cert,
+ const std::string& hostname,
+ int flags,
+ int error,
+ const CertVerifyResult& verify_result) {
+ DCHECK(CalledOnValidThread());
+
+ const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(),
+ hostname, flags);
+
+ CachedResult cached_result;
+ cached_result.error = error;
+ cached_result.result = verify_result;
+ cache_.Put(key, cached_result, base::TimeTicks::Now(),
+ base::TimeDelta::FromSeconds(kTTLSecs));
+
+ std::map<RequestParams, CertVerifierJob*>::iterator j;
+ j = inflight_.find(key);
+ if (j == inflight_.end()) {
+ NOTREACHED();
+ return;
+ }
+ CertVerifierJob* job = j->second;
+ inflight_.erase(j);
+
+ job->HandleResult(cached_result);
+ delete job;
+}
+
+void MultiThreadedCertVerifier::OnCertTrustChanged(
+ const X509Certificate* cert) {
+ DCHECK(CalledOnValidThread());
+
+ ClearCache();
+}
+
+} // namespace net
diff --git a/net/base/multi_threaded_cert_verifier.h b/net/base/multi_threaded_cert_verifier.h
new file mode 100644
index 0000000..c8eca2e
--- /dev/null
+++ b/net/base/multi_threaded_cert_verifier.h
@@ -0,0 +1,142 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_BASE_MULTI_THREADED_CERT_VERIFIER_H_
+#define NET_BASE_MULTI_THREADED_CERT_VERIFIER_H_
+#pragma once
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/non_thread_safe.h"
+#include "net/base/cert_database.h"
+#include "net/base/cert_verifier.h"
+#include "net/base/cert_verify_result.h"
+#include "net/base/completion_callback.h"
+#include "net/base/expiring_cache.h"
+#include "net/base/net_export.h"
+#include "net/base/x509_cert_types.h"
+
+namespace net {
+
+class CertVerifierJob;
+class CertVerifierRequest;
+class CertVerifierWorker;
+
+// MultiThreadedCertVerifier is a CertVerifier implementation that runs
+// synchronous CertVerifier implementations on worker threads.
+class NET_EXPORT MultiThreadedCertVerifier :
+ public CertVerifier,
+ NON_EXPORTED_BASE(public base::NonThreadSafe),
+ public CertDatabase::Observer {
+ public:
+ MultiThreadedCertVerifier();
+
+ // When the verifier is destroyed, all certificate verifications requests are
+ // canceled, and their completion callbacks will not be called.
+ virtual ~MultiThreadedCertVerifier();
+
+ // CertVerifier implementation
+ virtual int Verify(X509Certificate* cert,
+ const std::string& hostname,
+ int flags,
+ CRLSet* crl_set,
+ CertVerifyResult* verify_result,
+ const CompletionCallback& callback,
+ CertVerifier::RequestHandle* out_req,
+ const BoundNetLog& net_log) OVERRIDE;
+
+ virtual void CancelRequest(CertVerifier::RequestHandle req) OVERRIDE;
+
+ private:
+ friend class CertVerifierWorker; // Calls HandleResult.
+ friend class CertVerifierRequest;
+ friend class CertVerifierJob;
+ FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, CacheHit);
+ FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, DifferentCACerts);
+ FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, InflightJoin);
+ FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, CancelRequest);
+ FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest,
+ RequestParamsComparators);
+
+ // Input parameters of a certificate verification request.
+ struct RequestParams {
+ RequestParams(const SHA1Fingerprint& cert_fingerprint_arg,
+ const SHA1Fingerprint& ca_fingerprint_arg,
+ const std::string& hostname_arg,
+ int flags_arg)
+ : cert_fingerprint(cert_fingerprint_arg),
+ ca_fingerprint(ca_fingerprint_arg),
+ hostname(hostname_arg),
+ flags(flags_arg) {}
+
+ bool operator<(const RequestParams& other) const {
+ // |flags| is compared before |cert_fingerprint|, |ca_fingerprint|, and
+ // |hostname| under assumption that integer comparisons are faster than
+ // memory and string comparisons.
+ if (flags != other.flags)
+ return flags < other.flags;
+ int rv = memcmp(cert_fingerprint.data, other.cert_fingerprint.data,
+ sizeof(cert_fingerprint.data));
+ if (rv != 0)
+ return rv < 0;
+ rv = memcmp(ca_fingerprint.data, other.ca_fingerprint.data,
+ sizeof(ca_fingerprint.data));
+ if (rv != 0)
+ return rv < 0;
+ return hostname < other.hostname;
+ }
+
+ SHA1Fingerprint cert_fingerprint;
+ SHA1Fingerprint ca_fingerprint;
+ std::string hostname;
+ int flags;
+ };
+
+ // CachedResult contains the result of a certificate verification.
+ struct CachedResult {
+ CachedResult();
+ ~CachedResult();
+
+ int error; // The return value of CertVerifier::Verify.
+ CertVerifyResult result; // The output of CertVerifier::Verify.
+ };
+
+ void HandleResult(X509Certificate* cert,
+ const std::string& hostname,
+ int flags,
+ int error,
+ const CertVerifyResult& verify_result);
+
+ // CertDatabase::Observer methods:
+ virtual void OnCertTrustChanged(const X509Certificate* cert) OVERRIDE;
+
+ // For unit testing.
+ void ClearCache() { cache_.Clear(); }
+ size_t GetCacheSize() const { return cache_.size(); }
+ uint64 cache_hits() const { return cache_hits_; }
+ uint64 requests() const { return requests_; }
+ uint64 inflight_joins() const { return inflight_joins_; }
+
+ // cache_ maps from a request to a cached result.
+ typedef ExpiringCache<RequestParams, CachedResult> CertVerifierCache;
+ CertVerifierCache cache_;
+
+ // inflight_ maps from a request to an active verification which is taking
+ // place.
+ std::map<RequestParams, CertVerifierJob*> inflight_;
+
+ uint64 requests_;
+ uint64 cache_hits_;
+ uint64 inflight_joins_;
+
+ DISALLOW_COPY_AND_ASSIGN(MultiThreadedCertVerifier);
+};
+
+} // namespace net
+
+#endif // NET_BASE_MULTI_THREADED_CERT_VERIFIER_H_
diff --git a/net/base/cert_verifier_unittest.cc b/net/base/multi_threaded_cert_verifier_unittest.cc
index 9d2528c..17eed99 100644
--- a/net/base/cert_verifier_unittest.cc
+++ b/net/base/multi_threaded_cert_verifier_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/base/cert_verifier.h"
+#include "net/base/multi_threaded_cert_verifier.h"
#include "base/bind.h"
#include "base/file_path.h"
@@ -32,8 +32,8 @@ void FailTest(int /* result */) {
#else
#define MAYBE_CacheHit CacheHit
#endif // defined(OS_MACOSX)
-TEST(CertVerifierTest, MAYBE_CacheHit) {
- CertVerifier verifier;
+TEST(MultiThreadedCertVerifierTest, MAYBE_CacheHit) {
+ MultiThreadedCertVerifier verifier;
FilePath certs_dir = GetTestCertsDirectory();
scoped_refptr<X509Certificate> test_cert(
@@ -71,8 +71,8 @@ TEST(CertVerifierTest, MAYBE_CacheHit) {
// Tests the same server certificate with different intermediate CA
// certificates. These should be treated as different certificate chains even
// though the two X509Certificate objects contain the same server certificate.
-TEST(CertVerifierTest, DifferentCACerts) {
- CertVerifier verifier;
+TEST(MultiThreadedCertVerifierTest, DifferentCACerts) {
+ MultiThreadedCertVerifier verifier;
FilePath certs_dir = GetTestCertsDirectory();
@@ -131,8 +131,8 @@ TEST(CertVerifierTest, DifferentCACerts) {
}
// Tests an inflight join.
-TEST(CertVerifierTest, InflightJoin) {
- CertVerifier verifier;
+TEST(MultiThreadedCertVerifierTest, InflightJoin) {
+ MultiThreadedCertVerifier verifier;
FilePath certs_dir = GetTestCertsDirectory();
scoped_refptr<X509Certificate> test_cert(
@@ -166,8 +166,8 @@ TEST(CertVerifierTest, InflightJoin) {
}
// Tests that the callback of a canceled request is never made.
-TEST(CertVerifierTest, CancelRequest) {
- CertVerifier verifier;
+TEST(MultiThreadedCertVerifierTest, CancelRequest) {
+ MultiThreadedCertVerifier verifier;
FilePath certs_dir = GetTestCertsDirectory();
scoped_refptr<X509Certificate> test_cert(
@@ -201,8 +201,8 @@ TEST(CertVerifierTest, CancelRequest) {
}
// Tests that a canceled request is not leaked.
-TEST(CertVerifierTest, CancelRequestThenQuit) {
- CertVerifier verifier;
+TEST(MultiThreadedCertVerifierTest, CancelRequestThenQuit) {
+ MultiThreadedCertVerifier verifier;
FilePath certs_dir = GetTestCertsDirectory();
scoped_refptr<X509Certificate> test_cert(
@@ -222,7 +222,7 @@ TEST(CertVerifierTest, CancelRequestThenQuit) {
// Destroy |verifier| by going out of scope.
}
-TEST(CertVerifierTest, RequestParamsComparators) {
+TEST(MultiThreadedCertVerifierTest, RequestParamsComparators) {
SHA1Fingerprint a_key;
memset(a_key.data, 'a', sizeof(a_key.data));
@@ -231,8 +231,8 @@ TEST(CertVerifierTest, RequestParamsComparators) {
struct {
// Keys to test
- CertVerifier::RequestParams key1;
- CertVerifier::RequestParams key2;
+ MultiThreadedCertVerifier::RequestParams key1;
+ MultiThreadedCertVerifier::RequestParams key2;
// Expectation:
// -1 means key1 is less than key2
@@ -241,41 +241,50 @@ TEST(CertVerifierTest, RequestParamsComparators) {
int expected_result;
} tests[] = {
{ // Test for basic equivalence.
- CertVerifier::RequestParams(a_key, a_key, "www.example.test", 0),
- CertVerifier::RequestParams(a_key, a_key, "www.example.test", 0),
+ MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test",
+ 0),
+ MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test",
+ 0),
0,
},
{ // Test that different certificates but with the same CA and for
// the same host are different validation keys.
- CertVerifier::RequestParams(a_key, a_key, "www.example.test", 0),
- CertVerifier::RequestParams(z_key, a_key, "www.example.test", 0),
+ MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test",
+ 0),
+ MultiThreadedCertVerifier::RequestParams(z_key, a_key, "www.example.test",
+ 0),
-1,
},
{ // Test that the same EE certificate for the same host, but with
// different chains are different validation keys.
- CertVerifier::RequestParams(a_key, z_key, "www.example.test", 0),
- CertVerifier::RequestParams(a_key, a_key, "www.example.test", 0),
+ MultiThreadedCertVerifier::RequestParams(a_key, z_key, "www.example.test",
+ 0),
+ MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test",
+ 0),
1,
},
{ // The same certificate, with the same chain, but for different
// hosts are different validation keys.
- CertVerifier::RequestParams(a_key, a_key, "www1.example.test", 0),
- CertVerifier::RequestParams(a_key, a_key, "www2.example.test", 0),
+ MultiThreadedCertVerifier::RequestParams(a_key, a_key,
+ "www1.example.test", 0),
+ MultiThreadedCertVerifier::RequestParams(a_key, a_key,
+ "www2.example.test", 0),
-1,
},
{ // The same certificate, chain, and host, but with different flags
// are different validation keys.
- CertVerifier::RequestParams(a_key, a_key, "www.example.test",
- X509Certificate::VERIFY_EV_CERT),
- CertVerifier::RequestParams(a_key, a_key, "www.example.test", 0),
+ MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test",
+ X509Certificate::VERIFY_EV_CERT),
+ MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test",
+ 0),
1,
}
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i));
- const CertVerifier::RequestParams& key1 = tests[i].key1;
- const CertVerifier::RequestParams& key2 = tests[i].key2;
+ const MultiThreadedCertVerifier::RequestParams& key1 = tests[i].key1;
+ const MultiThreadedCertVerifier::RequestParams& key2 = tests[i].key2;
switch (tests[i].expected_result) {
case -1:
diff --git a/net/base/single_request_cert_verifier.cc b/net/base/single_request_cert_verifier.cc
new file mode 100644
index 0000000..3370600
--- /dev/null
+++ b/net/base/single_request_cert_verifier.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/single_request_cert_verifier.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "net/base/net_errors.h"
+#include "net/base/x509_certificate.h"
+
+namespace net {
+
+SingleRequestCertVerifier::SingleRequestCertVerifier(
+ CertVerifier* cert_verifier)
+ : cert_verifier_(cert_verifier),
+ cur_request_(NULL) {
+ DCHECK(cert_verifier_ != NULL);
+}
+
+SingleRequestCertVerifier::~SingleRequestCertVerifier() {
+ if (cur_request_) {
+ cert_verifier_->CancelRequest(cur_request_);
+ cur_request_ = NULL;
+ }
+}
+
+int SingleRequestCertVerifier::Verify(X509Certificate* cert,
+ const std::string& hostname,
+ int flags,
+ CRLSet* crl_set,
+ CertVerifyResult* verify_result,
+ const CompletionCallback& callback,
+ const BoundNetLog& net_log) {
+ // Should not be already in use.
+ DCHECK(!cur_request_ && cur_request_callback_.is_null());
+
+ // Do a synchronous verification.
+ if (callback.is_null())
+ return cert->Verify(hostname, flags, crl_set, verify_result);
+
+ CertVerifier::RequestHandle request = NULL;
+
+ // We need to be notified of completion before |callback| is called, so that
+ // we can clear out |cur_request_*|.
+ int rv = cert_verifier_->Verify(
+ cert, hostname, flags, crl_set, verify_result,
+ base::Bind(&SingleRequestCertVerifier::OnVerifyCompletion,
+ base::Unretained(this)),
+ &request, net_log);
+
+ if (rv == ERR_IO_PENDING) {
+ // Cleared in OnVerifyCompletion().
+ cur_request_ = request;
+ cur_request_callback_ = callback;
+ }
+
+ return rv;
+}
+
+void SingleRequestCertVerifier::OnVerifyCompletion(int result) {
+ DCHECK(cur_request_ && !cur_request_callback_.is_null());
+
+ CompletionCallback callback = cur_request_callback_;
+
+ // Clear the outstanding request information.
+ cur_request_ = NULL;
+ cur_request_callback_.Reset();
+
+ // Call the user's original callback.
+ callback.Run(result);
+}
+
+} // namespace net
diff --git a/net/base/single_request_cert_verifier.h b/net/base/single_request_cert_verifier.h
new file mode 100644
index 0000000..6ae8bb6
--- /dev/null
+++ b/net/base/single_request_cert_verifier.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_BASE_SINGLE_REQUEST_CERT_VERIFIER_H_
+#define NET_BASE_SINGLE_REQUEST_CERT_VERIFIER_H_
+#pragma once
+
+#include "net/base/cert_verifier.h"
+
+namespace net {
+
+// This class represents the task of verifying a certificate. It wraps
+// CertVerifier to verify only a single certificate at a time and cancels this
+// request when going out of scope.
+class SingleRequestCertVerifier {
+ public:
+ // |cert_verifier| must remain valid for the lifetime of |this|.
+ explicit SingleRequestCertVerifier(CertVerifier* cert_verifier);
+
+ // If a completion callback is pending when the verifier is destroyed, the
+ // certificate verification is canceled, and the completion callback will
+ // not be called.
+ ~SingleRequestCertVerifier();
+
+ // Verifies the given certificate, filling out the |verify_result| object
+ // upon success. See CertVerifier::Verify() for details.
+ int Verify(X509Certificate* cert,
+ const std::string& hostname,
+ int flags,
+ CRLSet* crl_set,
+ CertVerifyResult* verify_result,
+ const CompletionCallback& callback,
+ const BoundNetLog& net_log);
+
+ private:
+ // Callback for when the request to |cert_verifier_| completes, so we
+ // dispatch to the user's callback.
+ void OnVerifyCompletion(int result);
+
+ // The actual certificate verifier that will handle the request.
+ CertVerifier* const cert_verifier_;
+
+ // The current request (if any).
+ CertVerifier::RequestHandle cur_request_;
+ CompletionCallback cur_request_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(SingleRequestCertVerifier);
+};
+
+} // namespace net
+
+#endif // NET_BASE_SINGLE_REQUEST_CERT_VERIFIER_H_
diff --git a/net/base/transport_security_state_unittest.cc b/net/base/transport_security_state_unittest.cc
index 3fc6562..cc681dd 100644
--- a/net/base/transport_security_state_unittest.cc
+++ b/net/base/transport_security_state_unittest.cc
@@ -14,6 +14,7 @@
#include "net/base/asn1_util.h"
#include "net/base/cert_test_util.h"
#include "net/base/cert_verifier.h"
+#include "net/base/cert_verify_result.h"
#include "net/base/ssl_info.h"
#include "net/base/test_root_certs.h"
#include "net/base/x509_certificate.h"
diff --git a/net/http/disk_cache_based_ssl_host_info_unittest.cc b/net/http/disk_cache_based_ssl_host_info_unittest.cc
index 9fb4727..41b200f 100644
--- a/net/http/disk_cache_based_ssl_host_info_unittest.cc
+++ b/net/http/disk_cache_based_ssl_host_info_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -6,6 +6,7 @@
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
#include "base/message_loop.h"
+#include "net/base/cert_verifier.h"
#include "net/base/net_errors.h"
#include "net/base/ssl_config_service.h"
#include "net/http/disk_cache_based_ssl_host_info.h"
@@ -33,7 +34,8 @@ const MockTransaction kHostInfoTransaction = {
// Tests that we can delete a DiskCacheBasedSSLHostInfo object in a
// completion callback for DiskCacheBasedSSLHostInfo::WaitForDataReady.
TEST(DiskCacheBasedSSLHostInfo, DeleteInCallback) {
- net::CertVerifier cert_verifier;
+ scoped_ptr<net::CertVerifier> cert_verifier(
+ net::CertVerifier::CreateDefault());
// Use the blocking mock backend factory to force asynchronous completion
// of ssl_host_info->WaitForDataReady(), so that the callback will run.
MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
@@ -41,7 +43,8 @@ TEST(DiskCacheBasedSSLHostInfo, DeleteInCallback) {
net::SSLConfig ssl_config;
scoped_ptr<net::SSLHostInfo> ssl_host_info(
new net::DiskCacheBasedSSLHostInfo("https://www.verisign.com", ssl_config,
- &cert_verifier, cache.http_cache()));
+ cert_verifier.get(),
+ cache.http_cache()));
ssl_host_info->Start();
net::TestCompletionCallback callback;
int rv = ssl_host_info->WaitForDataReady(callback.callback());
@@ -58,11 +61,13 @@ TEST(DiskCacheBasedSSLHostInfo, Update) {
net::TestCompletionCallback callback;
// Store a certificate chain.
- net::CertVerifier cert_verifier;
+ scoped_ptr<net::CertVerifier> cert_verifier(
+ net::CertVerifier::CreateDefault());
net::SSLConfig ssl_config;
scoped_ptr<net::SSLHostInfo> ssl_host_info(
new net::DiskCacheBasedSSLHostInfo("https://www.google.com", ssl_config,
- &cert_verifier, cache.http_cache()));
+ cert_verifier.get(),
+ cache.http_cache()));
ssl_host_info->Start();
int rv = ssl_host_info->WaitForDataReady(callback.callback());
EXPECT_EQ(net::OK, callback.GetResult(rv));
@@ -78,7 +83,8 @@ TEST(DiskCacheBasedSSLHostInfo, Update) {
// Open the stored certificate chain.
ssl_host_info.reset(
new net::DiskCacheBasedSSLHostInfo("https://www.google.com", ssl_config,
- &cert_verifier, cache.http_cache()));
+ cert_verifier.get(),
+ cache.http_cache()));
ssl_host_info->Start();
rv = ssl_host_info->WaitForDataReady(callback.callback());
EXPECT_EQ(net::OK, callback.GetResult(rv));
@@ -97,7 +103,8 @@ TEST(DiskCacheBasedSSLHostInfo, Update) {
// Verify that the state was updated.
ssl_host_info.reset(
new net::DiskCacheBasedSSLHostInfo("https://www.google.com", ssl_config,
- &cert_verifier, cache.http_cache()));
+ cert_verifier.get(),
+ cache.http_cache()));
ssl_host_info->Start();
rv = ssl_host_info->WaitForDataReady(callback.callback());
EXPECT_EQ(net::OK, callback.GetResult(rv));
diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc
index bdb777c..596b1ab 100644
--- a/net/http/http_network_layer_unittest.cc
+++ b/net/http/http_network_layer_unittest.cc
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "net/http/http_network_layer.h"
+
#include "net/base/cert_verifier.h"
#include "net/base/mock_host_resolver.h"
#include "net/base/net_log.h"
#include "net/base/ssl_config_service_defaults.h"
-#include "net/http/http_network_layer.h"
#include "net/http/http_network_session.h"
#include "net/http/http_server_properties_impl.h"
#include "net/http/http_transaction_unittest.h"
@@ -23,12 +24,13 @@ namespace {
class HttpNetworkLayerTest : public PlatformTest {
protected:
HttpNetworkLayerTest()
- : proxy_service_(ProxyService::CreateDirect()),
+ : cert_verifier_(CertVerifier::CreateDefault()),
+ proxy_service_(ProxyService::CreateDirect()),
ssl_config_service_(new SSLConfigServiceDefaults) {
HttpNetworkSession::Params session_params;
session_params.client_socket_factory = &mock_socket_factory_;
session_params.host_resolver = &host_resolver_;
- session_params.cert_verifier = &cert_verifier_;
+ session_params.cert_verifier = cert_verifier_.get();
session_params.proxy_service = proxy_service_.get();
session_params.ssl_config_service = ssl_config_service_;
session_params.http_server_properties = &http_server_properties_;
@@ -38,7 +40,7 @@ class HttpNetworkLayerTest : public PlatformTest {
MockClientSocketFactory mock_socket_factory_;
MockHostResolver host_resolver_;
- CertVerifier cert_verifier_;
+ scoped_ptr<CertVerifier> cert_verifier_;
const scoped_ptr<ProxyService> proxy_service_;
const scoped_refptr<SSLConfigService> ssl_config_service_;
scoped_refptr<HttpNetworkSession> network_session_;
diff --git a/net/http/http_network_transaction_spdy21_unittest.cc b/net/http/http_network_transaction_spdy21_unittest.cc
index 0f21f9d..fed205f 100644
--- a/net/http/http_network_transaction_spdy21_unittest.cc
+++ b/net/http/http_network_transaction_spdy21_unittest.cc
@@ -122,7 +122,7 @@ struct SessionDependencies {
// Default set of dependencies -- "null" proxy service.
SessionDependencies()
: host_resolver(new MockHostResolver),
- cert_verifier(new CertVerifier),
+ cert_verifier(CertVerifier::CreateDefault()),
proxy_service(ProxyService::CreateDirect()),
ssl_config_service(new SSLConfigServiceDefaults),
http_auth_handler_factory(
@@ -132,7 +132,7 @@ struct SessionDependencies {
// Custom proxy service dependency.
explicit SessionDependencies(ProxyService* proxy_service)
: host_resolver(new MockHostResolver),
- cert_verifier(new CertVerifier),
+ cert_verifier(CertVerifier::CreateDefault()),
proxy_service(proxy_service),
ssl_config_service(new SSLConfigServiceDefaults),
http_auth_handler_factory(
diff --git a/net/http/http_network_transaction_spdy2_unittest.cc b/net/http/http_network_transaction_spdy2_unittest.cc
index b09ca119..49d5ae5 100644
--- a/net/http/http_network_transaction_spdy2_unittest.cc
+++ b/net/http/http_network_transaction_spdy2_unittest.cc
@@ -122,7 +122,7 @@ struct SessionDependencies {
// Default set of dependencies -- "null" proxy service.
SessionDependencies()
: host_resolver(new MockHostResolver),
- cert_verifier(new CertVerifier),
+ cert_verifier(CertVerifier::CreateDefault()),
proxy_service(ProxyService::CreateDirect()),
ssl_config_service(new SSLConfigServiceDefaults),
http_auth_handler_factory(
@@ -132,7 +132,7 @@ struct SessionDependencies {
// Custom proxy service dependency.
explicit SessionDependencies(ProxyService* proxy_service)
: host_resolver(new MockHostResolver),
- cert_verifier(new CertVerifier),
+ cert_verifier(CertVerifier::CreateDefault()),
proxy_service(proxy_service),
ssl_config_service(new SSLConfigServiceDefaults),
http_auth_handler_factory(
diff --git a/net/http/http_network_transaction_spdy3_unittest.cc b/net/http/http_network_transaction_spdy3_unittest.cc
index 631e803..4052959 100644
--- a/net/http/http_network_transaction_spdy3_unittest.cc
+++ b/net/http/http_network_transaction_spdy3_unittest.cc
@@ -19,6 +19,7 @@
#include "base/utf_string_conversions.h"
#include "net/base/auth.h"
#include "net/base/capturing_net_log.h"
+#include "net/base/cert_verifier.h"
#include "net/base/completion_callback.h"
#include "net/base/host_cache.h"
#include "net/base/mock_host_resolver.h"
@@ -122,7 +123,7 @@ struct SessionDependencies {
// Default set of dependencies -- "null" proxy service.
SessionDependencies()
: host_resolver(new MockHostResolver),
- cert_verifier(new CertVerifier),
+ cert_verifier(CertVerifier::CreateDefault()),
proxy_service(ProxyService::CreateDirect()),
ssl_config_service(new SSLConfigServiceDefaults),
http_auth_handler_factory(
@@ -132,7 +133,7 @@ struct SessionDependencies {
// Custom proxy service dependency.
explicit SessionDependencies(ProxyService* proxy_service)
: host_resolver(new MockHostResolver),
- cert_verifier(new CertVerifier),
+ cert_verifier(CertVerifier::CreateDefault()),
proxy_service(proxy_service),
ssl_config_service(new SSLConfigServiceDefaults),
http_auth_handler_factory(
diff --git a/net/http/http_proxy_client_socket_pool_spdy21_unittest.cc b/net/http/http_proxy_client_socket_pool_spdy21_unittest.cc
index 25f8c64..ba0b9e1 100644
--- a/net/http/http_proxy_client_socket_pool_spdy21_unittest.cc
+++ b/net/http/http_proxy_client_socket_pool_spdy21_unittest.cc
@@ -63,12 +63,13 @@ class HttpProxyClientSocketPoolSpdy21Test : public TestWithHttpParam {
&tcp_histograms_,
&socket_factory_),
ssl_histograms_("MockSSL"),
+ cert_verifier_(CertVerifier::CreateDefault()),
proxy_service_(ProxyService::CreateDirect()),
ssl_config_service_(new SSLConfigServiceDefaults),
ssl_socket_pool_(kMaxSockets, kMaxSocketsPerGroup,
&ssl_histograms_,
&host_resolver_,
- &cert_verifier_,
+ cert_verifier_.get(),
NULL /* server_bound_cert_store */,
NULL /* transport_security_state */,
NULL /* ssl_host_info_factory */,
@@ -181,7 +182,7 @@ class HttpProxyClientSocketPoolSpdy21Test : public TestWithHttpParam {
HttpNetworkSession* CreateNetworkSession() {
HttpNetworkSession::Params params;
params.host_resolver = &host_resolver_;
- params.cert_verifier = &cert_verifier_;
+ params.cert_verifier = cert_verifier_.get();
params.proxy_service = proxy_service_.get();
params.client_socket_factory = &socket_factory_;
params.ssl_config_service = ssl_config_service_;
@@ -200,7 +201,7 @@ class HttpProxyClientSocketPoolSpdy21Test : public TestWithHttpParam {
MockTransportClientSocketPool transport_socket_pool_;
ClientSocketPoolHistograms ssl_histograms_;
MockHostResolver host_resolver_;
- CertVerifier cert_verifier_;
+ scoped_ptr<CertVerifier> cert_verifier_;
const scoped_ptr<ProxyService> proxy_service_;
const scoped_refptr<SSLConfigService> ssl_config_service_;
SSLClientSocketPool ssl_socket_pool_;
diff --git a/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc b/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc
index f54e7d2..00e55b3 100644
--- a/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc
+++ b/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc
@@ -63,12 +63,13 @@ class HttpProxyClientSocketPoolSpdy2Test : public TestWithHttpParam {
&tcp_histograms_,
&socket_factory_),
ssl_histograms_("MockSSL"),
+ cert_verifier_(CertVerifier::CreateDefault()),
proxy_service_(ProxyService::CreateDirect()),
ssl_config_service_(new SSLConfigServiceDefaults),
ssl_socket_pool_(kMaxSockets, kMaxSocketsPerGroup,
&ssl_histograms_,
&host_resolver_,
- &cert_verifier_,
+ cert_verifier_.get(),
NULL /* server_bound_cert_store */,
NULL /* transport_security_state */,
NULL /* ssl_host_info_factory */,
@@ -181,7 +182,7 @@ class HttpProxyClientSocketPoolSpdy2Test : public TestWithHttpParam {
HttpNetworkSession* CreateNetworkSession() {
HttpNetworkSession::Params params;
params.host_resolver = &host_resolver_;
- params.cert_verifier = &cert_verifier_;
+ params.cert_verifier = cert_verifier_.get();
params.proxy_service = proxy_service_.get();
params.client_socket_factory = &socket_factory_;
params.ssl_config_service = ssl_config_service_;
@@ -200,7 +201,7 @@ class HttpProxyClientSocketPoolSpdy2Test : public TestWithHttpParam {
MockTransportClientSocketPool transport_socket_pool_;
ClientSocketPoolHistograms ssl_histograms_;
MockHostResolver host_resolver_;
- CertVerifier cert_verifier_;
+ scoped_ptr<CertVerifier> cert_verifier_;
const scoped_ptr<ProxyService> proxy_service_;
const scoped_refptr<SSLConfigService> ssl_config_service_;
SSLClientSocketPool ssl_socket_pool_;
diff --git a/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc b/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc
index 0bc603e..4aead906 100644
--- a/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc
+++ b/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc
@@ -8,6 +8,7 @@
#include "base/compiler_specific.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
+#include "net/base/cert_verifier.h"
#include "net/base/mock_host_resolver.h"
#include "net/base/net_errors.h"
#include "net/base/ssl_config_service_defaults.h"
@@ -63,12 +64,13 @@ class HttpProxyClientSocketPoolSpdy3Test : public TestWithHttpParam {
&tcp_histograms_,
&socket_factory_),
ssl_histograms_("MockSSL"),
+ cert_verifier_(CertVerifier::CreateDefault()),
proxy_service_(ProxyService::CreateDirect()),
ssl_config_service_(new SSLConfigServiceDefaults),
ssl_socket_pool_(kMaxSockets, kMaxSocketsPerGroup,
&ssl_histograms_,
&host_resolver_,
- &cert_verifier_,
+ cert_verifier_.get(),
NULL /* server_bound_cert_store */,
NULL /* transport_security_state */,
NULL /* ssl_host_info_factory */,
@@ -181,7 +183,7 @@ class HttpProxyClientSocketPoolSpdy3Test : public TestWithHttpParam {
HttpNetworkSession* CreateNetworkSession() {
HttpNetworkSession::Params params;
params.host_resolver = &host_resolver_;
- params.cert_verifier = &cert_verifier_;
+ params.cert_verifier = cert_verifier_.get();
params.proxy_service = proxy_service_.get();
params.client_socket_factory = &socket_factory_;
params.ssl_config_service = ssl_config_service_;
@@ -200,7 +202,7 @@ class HttpProxyClientSocketPoolSpdy3Test : public TestWithHttpParam {
MockTransportClientSocketPool transport_socket_pool_;
ClientSocketPoolHistograms ssl_histograms_;
MockHostResolver host_resolver_;
- CertVerifier cert_verifier_;
+ scoped_ptr<CertVerifier> cert_verifier_;
const scoped_ptr<ProxyService> proxy_service_;
const scoped_refptr<SSLConfigService> ssl_config_service_;
SSLClientSocketPool ssl_socket_pool_;
diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc
index d554256..c69ef8f 100644
--- a/net/http/http_stream_factory_impl_unittest.cc
+++ b/net/http/http_stream_factory_impl_unittest.cc
@@ -118,7 +118,7 @@ struct SessionDependencies {
// Custom proxy service dependency.
explicit SessionDependencies(ProxyService* proxy_service)
: host_resolver(new MockHostResolver),
- cert_verifier(new CertVerifier),
+ cert_verifier(CertVerifier::CreateDefault()),
proxy_service(proxy_service),
ssl_config_service(new SSLConfigServiceDefaults),
http_auth_handler_factory(
diff --git a/net/net.gyp b/net/net.gyp
index 4360fc0..5c70b88a 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -154,6 +154,8 @@
'base/mime_sniffer.h',
'base/mime_util.cc',
'base/mime_util.h',
+ 'base/multi_threaded_cert_verifier.cc',
+ 'base/multi_threaded_cert_verifier.h',
'base/net_error_list.h',
'base/net_errors.cc',
'base/net_errors.h',
@@ -212,6 +214,8 @@
'base/sdch_filter.h',
'base/sdch_manager.cc',
'base/sdch_manager.h',
+ 'base/single_request_cert_verifier.cc',
+ 'base/single_request_cert_verifier.h',
'base/single_request_host_resolver.cc',
'base/single_request_host_resolver.h',
'base/ssl_cert_request_info.cc',
@@ -1019,7 +1023,6 @@
'base/backoff_entry_unittest.cc',
'base/big_endian_unittest.cc',
'base/cert_database_nss_unittest.cc',
- 'base/cert_verifier_unittest.cc',
'base/crl_set_unittest.cc',
'base/data_url_unittest.cc',
'base/default_origin_bound_cert_store_unittest.cc',
@@ -1046,6 +1049,7 @@
'base/mime_util_unittest.cc',
'base/mock_filter_context.cc',
'base/mock_filter_context.h',
+ 'base/multi_threaded_cert_verifier_unittest.cc',
'base/net_log_unittest.cc',
'base/net_log_unittest.h',
'base/net_util_unittest.cc',
diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/proxy_script_fetcher_impl_unittest.cc
index d29dcba..f365393 100644
--- a/net/proxy/proxy_script_fetcher_impl_unittest.cc
+++ b/net/proxy/proxy_script_fetcher_impl_unittest.cc
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/path_service.h"
#include "base/utf_string_conversions.h"
+#include "net/base/cert_verifier.h"
#include "net/base/net_util.h"
#include "net/base/load_flags.h"
#include "net/base/ssl_config_service_defaults.h"
@@ -72,7 +73,7 @@ class RequestContext : public URLRequestContext {
CreateSystemHostResolver(HostResolver::kDefaultParallelism,
HostResolver::kDefaultRetryAttempts,
NULL));
- storage_.set_cert_verifier(new CertVerifier);
+ storage_.set_cert_verifier(CertVerifier::CreateDefault());
storage_.set_proxy_service(ProxyService::CreateFixed(no_proxy));
storage_.set_ssl_config_service(new SSLConfigServiceDefaults);
storage_.set_http_server_properties(new HttpServerPropertiesImpl);
diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc
index 7bb1dcd..e847c15 100644
--- a/net/socket/ssl_client_socket_mac.cc
+++ b/net/socket/ssl_client_socket_mac.cc
@@ -21,6 +21,7 @@
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"
+#include "net/base/single_request_cert_verifier.h"
#include "net/base/ssl_cert_request_info.h"
#include "net/base/ssl_connection_status_flags.h"
#include "net/base/ssl_info.h"
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index 0d712e3..3ae9eb1 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -90,6 +90,7 @@
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"
+#include "net/base/single_request_cert_verifier.h"
#include "net/base/ssl_cert_request_info.h"
#include "net/base/ssl_connection_status_flags.h"
#include "net/base/ssl_info.h"
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index d691f22..3ee7886 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -18,6 +18,7 @@
#include "net/base/cert_verifier.h"
#include "net/base/net_errors.h"
#include "net/base/openssl_private_key_store.h"
+#include "net/base/single_request_cert_verifier.h"
#include "net/base/ssl_cert_request_info.h"
#include "net/base/ssl_connection_status_flags.h"
#include "net/base/ssl_info.h"
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc
index c6896ec..0ca0cb8 100644
--- a/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -137,7 +137,7 @@ class SSLClientSocketPoolTest : public testing::Test {
HttpNetworkSession* CreateNetworkSession() {
HttpNetworkSession::Params params;
params.host_resolver = &host_resolver_;
- params.cert_verifier = &cert_verifier_;
+ params.cert_verifier = cert_verifier_.get();
params.proxy_service = proxy_service_.get();
params.client_socket_factory = &socket_factory_;
params.ssl_config_service = ssl_config_service_;
@@ -148,7 +148,7 @@ class SSLClientSocketPoolTest : public testing::Test {
MockClientSocketFactory socket_factory_;
MockCachingHostResolver host_resolver_;
- CertVerifier cert_verifier_;
+ scoped_ptr<CertVerifier> cert_verifier_;
const scoped_ptr<ProxyService> proxy_service_;
const scoped_refptr<SSLConfigService> ssl_config_service_;
const scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index c8dfc8a..85ef0a7 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -31,7 +31,7 @@ class SSLClientSocketTest : public PlatformTest {
public:
SSLClientSocketTest()
: socket_factory_(net::ClientSocketFactory::GetDefaultFactory()),
- cert_verifier_(new net::CertVerifier) {
+ cert_verifier_(net::CertVerifier::CreateDefault()) {
}
protected:
diff --git a/net/socket/ssl_client_socket_win.cc b/net/socket/ssl_client_socket_win.cc
index b2054eb..1442ad6 100644
--- a/net/socket/ssl_client_socket_win.cc
+++ b/net/socket/ssl_client_socket_win.cc
@@ -22,6 +22,7 @@
#include "net/base/io_buffer.h"
#include "net/base/net_log.h"
#include "net/base/net_errors.h"
+#include "net/base/single_request_cert_verifier.h"
#include "net/base/ssl_cert_request_info.h"
#include "net/base/ssl_connection_status_flags.h"
#include "net/base/ssl_info.h"
diff --git a/net/socket/ssl_host_info.h b/net/socket/ssl_host_info.h
index 34fb0ef..af2c418 100644
--- a/net/socket/ssl_host_info.h
+++ b/net/socket/ssl_host_info.h
@@ -16,6 +16,7 @@
#include "net/base/cert_verify_result.h"
#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
+#include "net/base/single_request_cert_verifier.h"
#include "net/socket/ssl_client_socket.h"
namespace net {
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc
index ce998e4..ccb8ac1 100644
--- a/net/socket/ssl_server_socket_unittest.cc
+++ b/net/socket/ssl_server_socket_unittest.cc
@@ -245,7 +245,8 @@ TEST(FakeSocketTest, DataTransfer) {
class SSLServerSocketTest : public PlatformTest {
public:
SSLServerSocketTest()
- : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()) {
+ : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()),
+ cert_verifier_(net::CertVerifier::CreateDefault()) {
}
protected:
@@ -293,7 +294,7 @@ class SSLServerSocketTest : public PlatformTest {
net::HostPortPair host_and_pair("unittest", 0);
net::SSLClientSocketContext context;
- context.cert_verifier = &cert_verifier_;
+ context.cert_verifier = cert_verifier_.get();
client_socket_.reset(
socket_factory_->CreateSSLClientSocket(
fake_client_socket, host_and_pair, ssl_config, NULL, context));
@@ -307,7 +308,7 @@ class SSLServerSocketTest : public PlatformTest {
scoped_ptr<net::SSLClientSocket> client_socket_;
scoped_ptr<net::SSLServerSocket> server_socket_;
net::ClientSocketFactory* socket_factory_;
- net::CertVerifier cert_verifier_;
+ scoped_ptr<net::CertVerifier> cert_verifier_;
};
// SSLServerSocket is only implemented using NSS.
diff --git a/net/spdy/spdy_test_util_spdy2.cc b/net/spdy/spdy_test_util_spdy2.cc
index aadd177..9c095f4 100644
--- a/net/spdy/spdy_test_util_spdy2.cc
+++ b/net/spdy/spdy_test_util_spdy2.cc
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
+#include "net/base/cert_verifier.h"
#include "net/http/http_network_session.h"
#include "net/http/http_network_transaction.h"
#include "net/http/http_server_properties_impl.h"
@@ -903,7 +904,7 @@ int CombineFrames(const spdy::SpdyFrame** frames, int num_frames,
SpdySessionDependencies::SpdySessionDependencies()
: host_resolver(new MockCachingHostResolver),
- cert_verifier(new CertVerifier),
+ cert_verifier(CertVerifier::CreateDefault()),
proxy_service(ProxyService::CreateDirect()),
ssl_config_service(new SSLConfigServiceDefaults),
socket_factory(new MockClientSocketFactory),
@@ -921,7 +922,7 @@ SpdySessionDependencies::SpdySessionDependencies()
SpdySessionDependencies::SpdySessionDependencies(ProxyService* proxy_service)
: host_resolver(new MockHostResolver),
- cert_verifier(new CertVerifier),
+ cert_verifier(CertVerifier::CreateDefault()),
proxy_service(proxy_service),
ssl_config_service(new SSLConfigServiceDefaults),
socket_factory(new MockClientSocketFactory),
@@ -965,7 +966,7 @@ HttpNetworkSession* SpdySessionDependencies::SpdyCreateSessionDeterministic(
SpdyURLRequestContext::SpdyURLRequestContext()
: ALLOW_THIS_IN_INITIALIZER_LIST(storage_(this)) {
storage_.set_host_resolver(new MockHostResolver());
- storage_.set_cert_verifier(new CertVerifier);
+ storage_.set_cert_verifier(CertVerifier::CreateDefault());
storage_.set_proxy_service(ProxyService::CreateDirect());
storage_.set_ssl_config_service(new SSLConfigServiceDefaults);
storage_.set_http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault(
diff --git a/net/spdy/spdy_test_util_spdy3.cc b/net/spdy/spdy_test_util_spdy3.cc
index 1958fda..f0d7e49 100644
--- a/net/spdy/spdy_test_util_spdy3.cc
+++ b/net/spdy/spdy_test_util_spdy3.cc
@@ -904,7 +904,7 @@ int CombineFrames(const spdy::SpdyFrame** frames, int num_frames,
SpdySessionDependencies::SpdySessionDependencies()
: host_resolver(new MockCachingHostResolver),
- cert_verifier(new CertVerifier),
+ cert_verifier(CertVerifier::CreateDefault()),
proxy_service(ProxyService::CreateDirect()),
ssl_config_service(new SSLConfigServiceDefaults),
socket_factory(new MockClientSocketFactory),
@@ -922,7 +922,7 @@ SpdySessionDependencies::SpdySessionDependencies()
SpdySessionDependencies::SpdySessionDependencies(ProxyService* proxy_service)
: host_resolver(new MockHostResolver),
- cert_verifier(new CertVerifier),
+ cert_verifier(CertVerifier::CreateDefault()),
proxy_service(proxy_service),
ssl_config_service(new SSLConfigServiceDefaults),
socket_factory(new MockClientSocketFactory),
@@ -966,7 +966,7 @@ HttpNetworkSession* SpdySessionDependencies::SpdyCreateSessionDeterministic(
SpdyURLRequestContext::SpdyURLRequestContext()
: ALLOW_THIS_IN_INITIALIZER_LIST(storage_(this)) {
storage_.set_host_resolver(new MockHostResolver());
- storage_.set_cert_verifier(new CertVerifier);
+ storage_.set_cert_verifier(CertVerifier::CreateDefault());
storage_.set_proxy_service(ProxyService::CreateDirect());
storage_.set_ssl_config_service(new SSLConfigServiceDefaults);
storage_.set_http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault(
diff --git a/net/tools/fetch/fetch_client.cc b/net/tools/fetch/fetch_client.cc
index 7b8c7e2..32feba3 100644
--- a/net/tools/fetch/fetch_client.cc
+++ b/net/tools/fetch/fetch_client.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -145,7 +145,8 @@ int main(int argc, char** argv) {
net::HostResolver::kDefaultRetryAttempts,
NULL));
- scoped_ptr<net::CertVerifier> cert_verifier(new net::CertVerifier);
+ scoped_ptr<net::CertVerifier> cert_verifier(
+ net::CertVerifier::CreateDefault());
scoped_ptr<net::ProxyService> proxy_service(
net::ProxyService::CreateDirect());
scoped_refptr<net::SSLConfigService> ssl_config_service(
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc
index 165382a..2ed65bd 100644
--- a/net/url_request/url_request_test_util.cc
+++ b/net/url_request/url_request_test_util.cc
@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/threading/thread.h"
+#include "net/base/cert_verifier.h"
#include "net/base/default_origin_bound_cert_store.h"
#include "net/base/host_port_pair.h"
#include "net/base/origin_bound_cert_service.h"
@@ -111,7 +112,7 @@ void TestURLRequestContext::Init() {
DCHECK(!initialized_);
initialized_ = true;
if (!cert_verifier())
- context_storage_.set_cert_verifier(new net::CertVerifier);
+ context_storage_.set_cert_verifier(net::CertVerifier::CreateDefault());
if (!ftp_transaction_factory()) {
context_storage_.set_ftp_transaction_factory(
new net::FtpNetworkLayer(host_resolver()));