15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/net/sqlite_server_bound_cert_store.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cookies/cookie_util.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_client_cert_type.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "sql/error_delegate_util.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/meta_table.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/statement.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/transaction.h"
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/sqlite/sqlite3.h"
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/quota/special_storage_policy.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class is designed to be shared between any calling threads and the
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// database thread. It batches operations and commits them on a timer.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SQLiteServerBoundCertStore::Backend
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public base::RefCountedThreadSafe<SQLiteServerBoundCertStore::Backend> {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Backend(const base::FilePath& path,
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          quota::SpecialStoragePolicy* special_storage_policy)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : path_(path),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_pending_(0),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        force_keep_session_state_(false),
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        special_storage_policy_(special_storage_policy),
457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        corruption_detected_(false) {}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Creates or loads the SQLite database.
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Load(const LoadedCallback& loaded_callback);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Batch a server bound cert addition.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddServerBoundCert(
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const net::DefaultServerBoundCertStore::ServerBoundCert& cert);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Batch a server bound cert deletion.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DeleteServerBoundCert(
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const net::DefaultServerBoundCertStore::ServerBoundCert& cert);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commit any pending operations and close the database.  This must be called
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // before the object is destructed.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Close();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetForceKeepSessionState();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void LoadOnDBThreadAndNotify(const LoadedCallback& loaded_callback);
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void LoadOnDBThread(
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::vector<net::DefaultServerBoundCertStore::ServerBoundCert*>* certs);
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<SQLiteServerBoundCertStore::Backend>;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // You should call Close() before destructing this object.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Backend() {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!db_.get()) << "Close should have already been called.";
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(num_pending_ == 0 && pending_.empty());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Database upgrade statements.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool EnsureDatabaseVersion();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class PendingOperation {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef enum {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERT_ADD,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERT_DELETE
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } OperationType;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PendingOperation(
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OperationType op,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const net::DefaultServerBoundCertStore::ServerBoundCert& cert)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : op_(op), cert_(cert) {}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OperationType op() const { return op_; }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::DefaultServerBoundCertStore::ServerBoundCert& cert() const {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return cert_;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OperationType op_;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::DefaultServerBoundCertStore::ServerBoundCert cert_;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Batch a server bound cert operation (add or delete).
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BatchOperation(
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PendingOperation::OperationType op,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const net::DefaultServerBoundCertStore::ServerBoundCert& cert);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commit our pending operations to the database.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Commit();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close() executed on the background thread.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InternalBackgroundClose();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DeleteCertificatesOnShutdown();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void DatabaseErrorCallback(int error, sql::Statement* stmt);
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void KillDatabase();
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path_;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<sql::Connection> db_;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::MetaTable meta_table_;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::list<PendingOperation*> PendingOperationsList;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOperationsList pending_;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOperationsList::size_type num_pending_;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the persistent store should skip clear on exit rules.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool force_keep_session_state_;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Guard |pending_|, |num_pending_| and |force_keep_session_state_|.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock lock_;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cache of origins we have certificates stored for.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<std::string> cert_origins_;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Indicates if the kill-database callback has been scheduled.
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool corruption_detected_;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Backend);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Version number of the database.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCurrentVersionNumber = 4;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompatibleVersionNumber = 1;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Initializes the certs table, returning true on success.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InitTable(sql::Connection* db) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The table is named "origin_bound_certs" for backwards compatability before
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we renamed this class to SQLiteServerBoundCertStore.  Likewise, the primary
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // key is "origin", but now can be other things like a plain domain.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db->DoesTableExist("origin_bound_certs")) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!db->Execute("CREATE TABLE origin_bound_certs ("
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "origin TEXT NOT NULL UNIQUE PRIMARY KEY,"
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "private_key BLOB NOT NULL,"
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "cert BLOB NOT NULL,"
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "cert_type INTEGER,"
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "expiration_time INTEGER,"
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "creation_time INTEGER)"))
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SQLiteServerBoundCertStore::Backend::Load(
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const LoadedCallback& loaded_callback) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This function should be called only once per instance.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!db_.get());
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BrowserThread::PostTask(
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BrowserThread::DB, FROM_HERE,
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Backend::LoadOnDBThreadAndNotify, this, loaded_callback));
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SQLiteServerBoundCertStore::Backend::LoadOnDBThreadAndNotify(
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const LoadedCallback& loaded_callback) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ScopedVector<net::DefaultServerBoundCertStore::ServerBoundCert> >
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      certs(new ScopedVector<net::DefaultServerBoundCertStore::ServerBoundCert>(
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          ));
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LoadOnDBThread(&certs->get());
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BrowserThread::PostTask(
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BrowserThread::IO, FROM_HERE,
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(loaded_callback, base::Passed(&certs)));
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SQLiteServerBoundCertStore::Backend::LoadOnDBThread(
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::vector<net::DefaultServerBoundCertStore::ServerBoundCert*>* certs) {
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This method should be called only once per instance.
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!db_.get());
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeTicks start = base::TimeTicks::Now();
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure the parent directory for storing certs is created before reading
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from it.
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::FilePath dir = path_.DirName();
2037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!base::PathExists(dir) && !file_util::CreateDirectory(dir))
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 db_size = 0;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (file_util::GetFileSize(path_, &db_size))
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_COUNTS("DomainBoundCerts.DBSizeInKB", db_size / 1024 );
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_.reset(new sql::Connection);
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  db_->set_histogram_tag("DomainBoundCerts");
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Unretained to avoid a ref loop with db_.
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  db_->set_error_callback(
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Bind(&SQLiteServerBoundCertStore::Backend::DatabaseErrorCallback,
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 base::Unretained(this)));
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db_->Open(path_)) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Unable to open cert DB.";
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (corruption_detected_)
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      KillDatabase();
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    db_.reset();
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EnsureDatabaseVersion() || !InitTable(db_.get())) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Unable to open cert DB.";
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (corruption_detected_)
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      KillDatabase();
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    meta_table_.Reset();
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    db_.reset();
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_->Preload();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Slurp all the certs into the out-vector.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement smt(db_->GetUniqueStatement(
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "SELECT origin, private_key, cert, cert_type, expiration_time, "
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "creation_time FROM origin_bound_certs"));
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!smt.is_valid()) {
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (corruption_detected_)
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      KillDatabase();
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    meta_table_.Reset();
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    db_.reset();
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (smt.Step()) {
250bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    net::SSLClientCertType type =
251bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        static_cast<net::SSLClientCertType>(smt.ColumnInt(3));
252bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    if (type != net::CLIENT_CERT_ECDSA_SIGN)
253bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      continue;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string private_key_from_db, cert_from_db;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    smt.ColumnBlobAsString(1, &private_key_from_db);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    smt.ColumnBlobAsString(2, &cert_from_db);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<net::DefaultServerBoundCertStore::ServerBoundCert> cert(
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new net::DefaultServerBoundCertStore::ServerBoundCert(
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            smt.ColumnString(0),  // origin
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::Time::FromInternalValue(smt.ColumnInt64(5)),
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::Time::FromInternalValue(smt.ColumnInt64(4)),
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            private_key_from_db,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            cert_from_db));
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cert_origins_.insert(cert->server_identifier());
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    certs->push_back(cert.release());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UMA_HISTOGRAM_COUNTS_10000("DomainBoundCerts.DBLoadedCount", certs->size());
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta load_time = base::TimeTicks::Now() - start;
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.DBLoadTime",
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             load_time,
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             base::TimeDelta::FromMilliseconds(1),
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             base::TimeDelta::FromMinutes(1),
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             50);
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "loaded " << certs->size() << " in " << load_time.InMilliseconds()
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << " ms";
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SQLiteServerBoundCertStore::Backend::EnsureDatabaseVersion() {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Version check.
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!meta_table_.Init(
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      db_.get(), kCurrentVersionNumber, kCompatibleVersionNumber)) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Server bound cert database is too new.";
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int cur_version = meta_table_.GetVersionNumber();
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cur_version == 1) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Transaction transaction(db_.get());
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!transaction.Begin())
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!db_->Execute("ALTER TABLE origin_bound_certs ADD COLUMN cert_type "
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "INTEGER")) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Unable to update server bound cert database to "
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << "version 2.";
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
302bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // All certs in version 1 database are rsa_sign, which are unsupported.
303bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // Just discard them all.
304bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    if (!db_->Execute("DELETE from origin_bound_certs")) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Unable to update server bound cert database to "
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << "version 2.";
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++cur_version;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    meta_table_.SetVersionNumber(cur_version);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    meta_table_.SetCompatibleVersionNumber(
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::min(cur_version, kCompatibleVersionNumber));
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transaction.Commit();
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cur_version <= 3) {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Transaction transaction(db_.get());
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!transaction.Begin())
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cur_version == 2) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!db_->Execute("ALTER TABLE origin_bound_certs ADD COLUMN "
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        "expiration_time INTEGER")) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Unable to update server bound cert database to "
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     << "version 4.";
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!db_->Execute("ALTER TABLE origin_bound_certs ADD COLUMN "
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "creation_time INTEGER")) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Unable to update server bound cert database to "
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << "version 4.";
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Statement smt(db_->GetUniqueStatement(
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "SELECT origin, cert FROM origin_bound_certs"));
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Statement update_expires_smt(db_->GetUniqueStatement(
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "UPDATE origin_bound_certs SET expiration_time = ? WHERE origin = ?"));
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Statement update_creation_smt(db_->GetUniqueStatement(
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "UPDATE origin_bound_certs SET creation_time = ? WHERE origin = ?"));
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!smt.is_valid() ||
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !update_expires_smt.is_valid() ||
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !update_creation_smt.is_valid()) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Unable to update server bound cert database to "
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << "version 4.";
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (smt.Step()) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string origin = smt.ColumnString(0);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string cert_from_db;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      smt.ColumnBlobAsString(1, &cert_from_db);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Parse the cert and extract the real value and then update the DB.
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_refptr<net::X509Certificate> cert(
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::X509Certificate::CreateFromBytes(
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              cert_from_db.data(), cert_from_db.size()));
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (cert.get()) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (cur_version == 2) {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          update_expires_smt.Reset(true);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          update_expires_smt.BindInt64(0,
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       cert->valid_expiry().ToInternalValue());
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          update_expires_smt.BindString(1, origin);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!update_expires_smt.Run()) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            LOG(WARNING) << "Unable to update server bound cert database to "
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         << "version 4.";
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return false;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        update_creation_smt.Reset(true);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        update_creation_smt.BindInt64(0, cert->valid_start().ToInternalValue());
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        update_creation_smt.BindString(1, origin);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!update_creation_smt.Run()) {
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          LOG(WARNING) << "Unable to update server bound cert database to "
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       << "version 4.";
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If there's a cert we can't parse, just leave it.  It'll get replaced
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // with a new one if we ever try to use it.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Error parsing cert for database upgrade for origin "
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     << smt.ColumnString(0);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur_version = 4;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    meta_table_.SetVersionNumber(cur_version);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    meta_table_.SetCompatibleVersionNumber(
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::min(cur_version, kCompatibleVersionNumber));
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transaction.Commit();
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Put future migration cases here.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When the version is too old, we just try to continue anyway, there should
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not be a released product that makes a database too old for us to handle.
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(WARNING, cur_version < kCurrentVersionNumber) <<
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Server bound cert database version " << cur_version <<
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " is too old to handle.";
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::DatabaseErrorCallback(
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int error,
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    sql::Statement* stmt) {
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!sql::IsErrorCatastrophic(error))
412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(shess): Running KillDatabase() multiple times should be
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // safe.
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (corruption_detected_)
417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  corruption_detected_ = true;
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(shess): Consider just calling RazeAndClose() immediately.
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // db_ may not be safe to reset at this point, but RazeAndClose()
423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // would cause the stack to unwind safely with errors.
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          base::Bind(&Backend::KillDatabase, this));
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SQLiteServerBoundCertStore::Backend::KillDatabase() {
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (db_) {
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // This Backend will now be in-memory only. In a future run the database
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // will be recreated. Hopefully things go better then!
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool success = db_->RazeAndClose();
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UMA_HISTOGRAM_BOOLEAN("DomainBoundCerts.KillDatabaseResult", success);
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    meta_table_.Reset();
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    db_.reset();
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::AddServerBoundCert(
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::DefaultServerBoundCertStore::ServerBoundCert& cert) {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BatchOperation(PendingOperation::CERT_ADD, cert);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::DeleteServerBoundCert(
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::DefaultServerBoundCertStore::ServerBoundCert& cert) {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BatchOperation(PendingOperation::CERT_DELETE, cert);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::BatchOperation(
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PendingOperation::OperationType op,
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::DefaultServerBoundCertStore::ServerBoundCert& cert) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commit every 30 seconds.
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kCommitIntervalMs = 30 * 1000;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commit right away if we have more than 512 outstanding operations.
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kCommitAfterBatchSize = 512;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do a full copy of the cert here, and hopefully just here.
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<PendingOperation> po(new PendingOperation(op, cert));
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOperationsList::size_type num_pending;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock locked(lock_);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_.push_back(po.release());
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_pending = ++num_pending_;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_pending == 1) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've gotten our first entry for this batch, fire off the timer.
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostDelayedTask(
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::DB, FROM_HERE,
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&Backend::Commit, this),
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(kCommitIntervalMs));
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (num_pending == kCommitAfterBatchSize) {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've reached a big enough batch, fire off a commit now.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::DB, FROM_HERE,
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&Backend::Commit, this));
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::Commit() {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOperationsList ops;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock locked(lock_);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_.swap(ops);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_pending_ = 0;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Maybe an old timer fired or we are already Close()'ed.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db_.get() || ops.empty())
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement add_smt(db_->GetCachedStatement(SQL_FROM_HERE,
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "INSERT INTO origin_bound_certs (origin, private_key, cert, cert_type, "
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "expiration_time, creation_time) VALUES (?,?,?,?,?,?)"));
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!add_smt.is_valid())
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement del_smt(db_->GetCachedStatement(SQL_FROM_HERE,
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "DELETE FROM origin_bound_certs WHERE origin=?"));
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!del_smt.is_valid())
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Transaction transaction(db_.get());
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!transaction.Begin())
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingOperationsList::iterator it = ops.begin();
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != ops.end(); ++it) {
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Free the certs as we commit them to the database.
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<PendingOperation> po(*it);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (po->op()) {
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PendingOperation::CERT_ADD: {
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cert_origins_.insert(po->cert().server_identifier());
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        add_smt.Reset(true);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        add_smt.BindString(0, po->cert().server_identifier());
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const std::string& private_key = po->cert().private_key();
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        add_smt.BindBlob(1, private_key.data(), private_key.size());
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const std::string& cert = po->cert().cert();
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        add_smt.BindBlob(2, cert.data(), cert.size());
525bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        add_smt.BindInt(3, net::CLIENT_CERT_ECDSA_SIGN);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        add_smt.BindInt64(4, po->cert().expiration_time().ToInternalValue());
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        add_smt.BindInt64(5, po->cert().creation_time().ToInternalValue());
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!add_smt.Run())
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NOTREACHED() << "Could not add a server bound cert to the DB.";
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PendingOperation::CERT_DELETE:
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cert_origins_.erase(po->cert().server_identifier());
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        del_smt.Reset(true);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        del_smt.BindString(0, po->cert().server_identifier());
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!del_smt.Run())
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NOTREACHED() << "Could not delete a server bound cert from the DB.";
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED();
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transaction.Commit();
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fire off a close message to the background thread. We could still have a
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pending commit timer that will be holding a reference on us, but if/when
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this fires we will already have been cleaned up and it will be ignored.
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::Close() {
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Must close the backend on the background thread.
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::DB, FROM_HERE,
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&Backend::InternalBackgroundClose, this));
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::InternalBackgroundClose() {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commit any pending operations
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Commit();
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!force_keep_session_state_ &&
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      special_storage_policy_.get() &&
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      special_storage_policy_->HasSessionOnlyOrigins()) {
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeleteCertificatesOnShutdown();
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_.reset();
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::DeleteCertificatesOnShutdown() {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db_.get())
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cert_origins_.empty())
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!special_storage_policy_.get())
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement del_smt(db_->GetCachedStatement(
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SQL_FROM_HERE, "DELETE FROM origin_bound_certs WHERE origin=?"));
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!del_smt.is_valid()) {
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Unable to delete certificates on shutdown.";
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Transaction transaction(db_.get());
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!transaction.Begin()) {
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Unable to delete certificates on shutdown.";
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<std::string>::iterator it = cert_origins_.begin();
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != cert_origins_.end(); ++it) {
599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const GURL url(net::cookie_util::CookieOriginToURL(*it, true));
600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!url.is_valid() || !special_storage_policy_->IsStorageSessionOnly(url))
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    del_smt.Reset(true);
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    del_smt.BindString(0, *it);
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!del_smt.Run())
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Could not delete a certificate from the DB.";
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!transaction.Commit())
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Unable to delete certificates on shutdown.";
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::SetForceKeepSessionState() {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock locked(lock_);
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  force_keep_session_state_ = true;
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SQLiteServerBoundCertStore::SQLiteServerBoundCertStore(
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& path,
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    quota::SpecialStoragePolicy* special_storage_policy)
620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : backend_(new Backend(path, special_storage_policy)) {
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SQLiteServerBoundCertStore::Load(
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const LoadedCallback& loaded_callback) {
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backend_->Load(loaded_callback);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::AddServerBoundCert(
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::DefaultServerBoundCertStore::ServerBoundCert& cert) {
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backend_->AddServerBoundCert(cert);
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::DeleteServerBoundCert(
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::DefaultServerBoundCertStore::ServerBoundCert& cert) {
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backend_->DeleteServerBoundCert(cert);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::SetForceKeepSessionState() {
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backend_->SetForceKeepSessionState();
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SQLiteServerBoundCertStore::~SQLiteServerBoundCertStore() {
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backend_->Close();
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We release our reference to the Backend, though it will probably still have
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a reference if the background thread has not run Close() yet.
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
647