1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/cert_verifier.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/compiler_specific.h"
821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/message_loop.h"
921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/stl_util-inl.h"
1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/synchronization/lock.h"
113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/worker_pool.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h"
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/x509_certificate.h"
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#if defined(USE_NSS)
1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <private/pprthred.h>  // PR_DetachThread
1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif
1821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net {
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen////////////////////////////////////////////////////////////////////////////
2221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Life of a request:
2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//
2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// CertVerifier CertVerifierJob       CertVerifierWorker          Request
2621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |                       (origin loop)    (worker loop)
2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |
2821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//   Verify()
2921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |---->-------------------<creates>
3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |
3121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |---->----<creates>
3221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |
3321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |---->---------------------------------------------------<creates>
3421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |
3521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |---->--------------------Start
3621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |                           |
3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |                        PostTask
3821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |
3921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |                                     <starts verifying>
4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |---->-----AddRequest                         |
4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//                                                    |
4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//                                                    |
4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//                                                    |
4421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//                                                  Finish
4521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//                                                    |
4621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//                                                 PostTask
4721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//
4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//                                   |
4921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//                                DoReply
5021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |----<-----------------------|
5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//  HandleResult
5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |
5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//      |---->-----HandleResult
5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//                      |
5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//                      |------>-----------------------------------Post
5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//
5721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//
5821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//
5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// On a cache hit, CertVerifier::Verify() returns synchronously without
6021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// posting a task to a worker thread.
6121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// The number of CachedCertVerifyResult objects that we'll cache.
6321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstatic const unsigned kMaxCacheEntries = 256;
6421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
6521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// The number of seconds for which we'll cache a cache entry.
6621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstatic const unsigned kTTLSecs = 1800;  // 30 minutes.
6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace {
6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass DefaultTimeService : public CertVerifier::TimeService {
7121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen public:
7221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // CertVerifier::TimeService methods:
7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  virtual base::Time Now() { return base::Time::Now(); }
7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen};
7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}  // namespace
7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenCachedCertVerifyResult::CachedCertVerifyResult() : error(ERR_FAILED) {
7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenCachedCertVerifyResult::~CachedCertVerifyResult() {}
8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool CachedCertVerifyResult::HasExpired(const base::Time current_time) const {
8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return current_time >= expiry;
8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Represents the output and result callback of a request.
8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass CertVerifierRequest {
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CertVerifierRequest(CompletionCallback* callback,
9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                      CertVerifyResult* verify_result)
9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      : callback_(callback),
9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        verify_result_(verify_result) {
9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Ensures that the result callback will never be made.
9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  void Cancel() {
9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    callback_ = NULL;
9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    verify_result_ = NULL;
10021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Copies the contents of |verify_result| to the caller's
10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // CertVerifyResult and calls the callback.
10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  void Post(const CachedCertVerifyResult& verify_result) {
10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (callback_) {
10621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      *verify_result_ = verify_result.result;
10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      callback_->Run(verify_result.error);
10821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    delete this;
11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool canceled() const { return !callback_; }
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen private:
11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CompletionCallback* callback_;
11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CertVerifyResult* verify_result_;
11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen};
11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
11921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
12021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// CertVerifierWorker runs on a worker thread and takes care of the blocking
12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// process of performing the certificate verification.  Deletes itself
12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// eventually if Start() succeeds.
12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass CertVerifierWorker {
12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen public:
12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CertVerifierWorker(X509Certificate* cert,
12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                     const std::string& hostname,
12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                     int flags,
12821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                     CertVerifier* cert_verifier)
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      : cert_(cert),
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        hostname_(hostname),
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        flags_(flags),
13221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        origin_loop_(MessageLoop::current()),
13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        cert_verifier_(cert_verifier),
13421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        canceled_(false),
13521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        error_(ERR_FAILED) {
13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
13721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
13821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  bool Start() {
13921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    DCHECK_EQ(MessageLoop::current(), origin_loop_);
14021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
1413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    return base::WorkerPool::PostTask(
1423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::Run),
1433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        true /* task is slow */);
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Cancel is called from the origin loop when the CertVerifier is getting
14721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // deleted.
14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  void Cancel() {
14921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    DCHECK_EQ(MessageLoop::current(), origin_loop_);
15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    base::AutoLock locked(lock_);
15121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    canceled_ = true;
15221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
15321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
15421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen private:
15521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  void Run() {
15621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Runs on a worker thread.
15721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    error_ = cert_->Verify(hostname_, flags_, &verify_result_);
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(USE_NSS)
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Detach the thread from NSPR.
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Calling NSS functions attaches the thread to NSPR, which stores
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // the NSPR thread ID in thread-specific data.
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // The threads in our thread pool terminate after we have called
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // PR_Cleanup.  Unless we detach them from NSPR, net_unittests gets
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // segfaults on shutdown when the threads' thread-specific data
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // destructors run.
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PR_DetachThread();
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
16821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    Finish();
16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // DoReply runs on the origin thread.
17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  void DoReply() {
17321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    DCHECK_EQ(MessageLoop::current(), origin_loop_);
17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {
17521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // We lock here because the worker thread could still be in Finished,
17621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // after the PostTask, but before unlocking |lock_|. If we do not lock in
17721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // this case, we will end up deleting a locked Lock, which can lead to
17821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // memory leaks or worse errors.
17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      base::AutoLock locked(lock_);
18021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      if (!canceled_) {
18121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        cert_verifier_->HandleResult(cert_, hostname_, flags_,
18221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                     error_, verify_result_);
18321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      }
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
18521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    delete this;
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
18821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  void Finish() {
18921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Runs on the worker thread.
19021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // We assume that the origin loop outlives the CertVerifier. If the
19121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // CertVerifier is deleted, it will call Cancel on us. If it does so
19221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // before the Acquire, we'll delete ourselves and return. If it's trying to
19321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // do so concurrently, then it'll block on the lock and we'll call PostTask
19421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // while the CertVerifier (and therefore the MessageLoop) is still alive.
19521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // If it does so after this function, we assume that the MessageLoop will
19621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // process pending tasks. In which case we'll notice the |canceled_| flag
19721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // in DoReply.
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
19921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    bool canceled;
20021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {
20172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      base::AutoLock locked(lock_);
20221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      canceled = canceled_;
20321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      if (!canceled) {
20421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        origin_loop_->PostTask(
20521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::DoReply));
20621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      }
20721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
20921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (canceled)
21021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      delete this;
21121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
21321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  scoped_refptr<X509Certificate> cert_;
21421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const std::string hostname_;
21521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const int flags_;
21621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  MessageLoop* const origin_loop_;
21721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CertVerifier* const cert_verifier_;
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
21921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // lock_ protects canceled_.
22072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::Lock lock_;
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
22221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // If canceled_ is true,
22321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // * origin_loop_ cannot be accessed by the worker thread,
22421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // * cert_verifier_ cannot be accessed by any thread.
22521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  bool canceled_;
22621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
22721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int error_;
22821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CertVerifyResult verify_result_;
22921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
23021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DISALLOW_COPY_AND_ASSIGN(CertVerifierWorker);
23121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen};
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
23321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// A CertVerifierJob is a one-to-one counterpart of a CertVerifierWorker. It
23421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// lives only on the CertVerifier's origin message loop.
23521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass CertVerifierJob {
23621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen public:
23721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  explicit CertVerifierJob(CertVerifierWorker* worker) : worker_(worker) {
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
24021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ~CertVerifierJob() {
24172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (worker_) {
24221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      worker_->Cancel();
24372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      DeleteAllCanceled();
24472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
24521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
24721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  void AddRequest(CertVerifierRequest* request) {
24821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    requests_.push_back(request);
24921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
25121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  void HandleResult(const CachedCertVerifyResult& verify_result) {
25221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    worker_ = NULL;
25321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    PostAll(verify_result);
25421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
25621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen private:
25721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  void PostAll(const CachedCertVerifyResult& verify_result) {
25821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    std::vector<CertVerifierRequest*> requests;
25921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    requests_.swap(requests);
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
26121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    for (std::vector<CertVerifierRequest*>::iterator
26221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         i = requests.begin(); i != requests.end(); i++) {
26321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      (*i)->Post(verify_result);
26421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // Post() causes the CertVerifierRequest to delete itself.
26521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
26621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
26872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  void DeleteAllCanceled() {
26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    for (std::vector<CertVerifierRequest*>::iterator
27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         i = requests_.begin(); i != requests_.end(); i++) {
27172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if ((*i)->canceled()) {
27272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        delete *i;
27372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      } else {
27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        LOG(DFATAL) << "CertVerifierRequest leaked!";
27572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
27672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
27772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
27872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
27921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::vector<CertVerifierRequest*> requests_;
28021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CertVerifierWorker* worker_;
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
28421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenCertVerifier::CertVerifier()
28521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    : time_service_(new DefaultTimeService),
28621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      requests_(0),
28721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      cache_hits_(0),
28821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      inflight_joins_(0) {
289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CertDatabase::AddObserver(this);
29021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
29121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
29221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenCertVerifier::CertVerifier(TimeService* time_service)
29321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    : time_service_(time_service),
29421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      requests_(0),
29521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      cache_hits_(0),
29621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      inflight_joins_(0) {
297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CertDatabase::AddObserver(this);
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCertVerifier::~CertVerifier() {
30121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  STLDeleteValues(&inflight_);
302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CertDatabase::RemoveObserver(this);
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint CertVerifier::Verify(X509Certificate* cert,
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         const std::string& hostname,
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         int flags,
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         CertVerifyResult* verify_result,
31021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                         CompletionCallback* callback,
31121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                         RequestHandle* out_req) {
31221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(CalledOnValidThread());
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
31421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!callback || !verify_result || hostname.empty()) {
31521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    *out_req = NULL;
31621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_INVALID_ARGUMENT;
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
31921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  requests_++;
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
32121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const RequestParams key = {cert->fingerprint(), hostname, flags};
32221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // First check the cache.
32321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::map<RequestParams, CachedCertVerifyResult>::iterator i;
32421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  i = cache_.find(key);
32521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (i != cache_.end()) {
32621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (!i->second.HasExpired(time_service_->Now())) {
32721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      cache_hits_++;
32821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      *out_req = NULL;
32921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      *verify_result = i->second.result;
33021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return i->second.error;
33121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
33221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Cache entry has expired.
33321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cache_.erase(i);
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
33621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // No cache hit. See if an identical request is currently in flight.
33721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CertVerifierJob* job;
33821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::map<RequestParams, CertVerifierJob*>::const_iterator j;
33921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  j = inflight_.find(key);
34021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (j != inflight_.end()) {
34121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // An identical request is in flight already. We'll just attach our
34221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // callback.
34321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    inflight_joins_++;
34421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    job = j->second;
34521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } else {
34621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Need to make a new request.
34721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    CertVerifierWorker* worker = new CertVerifierWorker(cert, hostname, flags,
34821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                                        this);
34921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    job = new CertVerifierJob(worker);
35021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (!worker->Start()) {
35121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      delete job;
35221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      delete worker;
35321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      *out_req = NULL;
35472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // TODO(wtc): log to the NetLog.
35572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      LOG(ERROR) << "CertVerifierWorker couldn't be started.";
35672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return ERR_INSUFFICIENT_RESOURCES;  // Just a guess.
35721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
35872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    inflight_.insert(std::make_pair(key, job));
35921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
36021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
36121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CertVerifierRequest* request =
36221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      new CertVerifierRequest(callback, verify_result);
36321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  job->AddRequest(request);
36421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  *out_req = request;
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ERR_IO_PENDING;
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
36821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid CertVerifier::CancelRequest(RequestHandle req) {
36921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(CalledOnValidThread());
37021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req);
37121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  request->Cancel();
37221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
37321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
37421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid CertVerifier::ClearCache() {
37521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(CalledOnValidThread());
37621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
37721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  cache_.clear();
37821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Leaves inflight_ alone.
37921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
38021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
38121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsensize_t CertVerifier::GetCacheSize() const {
38221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(CalledOnValidThread());
38321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
38421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return cache_.size();
38521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
38621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
38721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// HandleResult is called by CertVerifierWorker on the origin message loop.
38821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// It deletes CertVerifierJob.
38921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid CertVerifier::HandleResult(X509Certificate* cert,
39021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                const std::string& hostname,
39121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                int flags,
39221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                int error,
39321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                const CertVerifyResult& verify_result) {
39421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(CalledOnValidThread());
39521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
39621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const base::Time current_time(time_service_->Now());
39721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
39821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CachedCertVerifyResult cached_result;
39921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  cached_result.error = error;
40021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  cached_result.result = verify_result;
40121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  uint32 ttl = kTTLSecs;
40221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  cached_result.expiry = current_time + base::TimeDelta::FromSeconds(ttl);
40321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
40421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const RequestParams key = {cert->fingerprint(), hostname, flags};
40521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
40621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK_GE(kMaxCacheEntries, 1u);
40721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK_LE(cache_.size(), kMaxCacheEntries);
40821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (cache_.size() == kMaxCacheEntries) {
40921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Need to remove an element of the cache.
41021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    std::map<RequestParams, CachedCertVerifyResult>::iterator i, cur;
41121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    for (i = cache_.begin(); i != cache_.end(); ) {
41221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      cur = i++;
41321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      if (cur->second.HasExpired(current_time))
41421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        cache_.erase(cur);
41521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
41621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
41721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (cache_.size() == kMaxCacheEntries) {
41821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // If we didn't clear out any expired entries, we just remove the first
41921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // element. Crummy but simple.
42021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cache_.erase(cache_.begin());
42121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
42221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
42321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  cache_.insert(std::make_pair(key, cached_result));
42421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
42521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::map<RequestParams, CertVerifierJob*>::iterator j;
42621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  j = inflight_.find(key);
42721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (j == inflight_.end()) {
42821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    NOTREACHED();
42921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return;
43021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
43121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CertVerifierJob* job = j->second;
43221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  inflight_.erase(j);
43321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
43421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  job->HandleResult(cached_result);
43521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  delete job;
43621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
43721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid CertVerifier::OnCertTrustChanged(const X509Certificate* cert) {
439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(CalledOnValidThread());
440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ClearCache();
442ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
443ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
44421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen/////////////////////////////////////////////////////////////////////
44521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
44621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenSingleRequestCertVerifier::SingleRequestCertVerifier(
44721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    CertVerifier* cert_verifier)
44821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    : cert_verifier_(cert_verifier),
44921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      cur_request_(NULL),
45021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      cur_request_callback_(NULL),
45121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      ALLOW_THIS_IN_INITIALIZER_LIST(
45221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          callback_(this, &SingleRequestCertVerifier::OnVerifyCompletion)) {
45321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(cert_verifier_ != NULL);
45421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
45521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
45621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenSingleRequestCertVerifier::~SingleRequestCertVerifier() {
45721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (cur_request_) {
45821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cert_verifier_->CancelRequest(cur_request_);
45921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cur_request_ = NULL;
46021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
46121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
46221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
46321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SingleRequestCertVerifier::Verify(X509Certificate* cert,
46421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                      const std::string& hostname,
46521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                      int flags,
46621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                      CertVerifyResult* verify_result,
46721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                      CompletionCallback* callback) {
46821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Should not be already in use.
46921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(!cur_request_ && !cur_request_callback_);
47021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
47121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Do a synchronous verification.
47221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!callback)
47321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return cert->Verify(hostname, flags, verify_result);
47421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
47521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CertVerifier::RequestHandle request = NULL;
47621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
47721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // We need to be notified of completion before |callback| is called, so that
47821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // we can clear out |cur_request_*|.
47921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int rv = cert_verifier_->Verify(
48021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      cert, hostname, flags, verify_result, &callback_, &request);
48121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
48221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv == ERR_IO_PENDING) {
48321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Cleared in OnVerifyCompletion().
48421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cur_request_ = request;
48521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cur_request_callback_ = callback;
48621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
48721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
48821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return rv;
48921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
49021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
49121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid SingleRequestCertVerifier::OnVerifyCompletion(int result) {
49221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(cur_request_ && cur_request_callback_);
49321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
49421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CompletionCallback* callback = cur_request_callback_;
49521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
49621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Clear the outstanding request information.
49721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  cur_request_ = NULL;
49821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  cur_request_callback_ = NULL;
49921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
50021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Call the user's original callback.
50121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  callback->Run(result);
50221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
50321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace net
50521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
50621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenDISABLE_RUNNABLE_METHOD_REFCOUNT(net::CertVerifierWorker);
507