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"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cookies/cookie_util.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_client_cert_type.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "sql/error_delegate_util.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/meta_table.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/statement.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/transaction.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/sqlite/sqlite3.h"
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/quota/special_storage_policy.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class is designed to be shared between any calling threads and the
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// background task runner. It batches operations and commits them on a timer.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SQLiteServerBoundCertStore::Backend
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public base::RefCountedThreadSafe<SQLiteServerBoundCertStore::Backend> {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Backend(
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const base::FilePath& path,
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      quota::SpecialStoragePolicy* special_storage_policy)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : path_(path),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_pending_(0),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        force_keep_session_state_(false),
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        background_task_runner_(background_task_runner),
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 LoadOnDBThread(
664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ScopedVector<net::DefaultServerBoundCertStore::ServerBoundCert>* certs);
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<SQLiteServerBoundCertStore::Backend>;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // You should call Close() before destructing this object.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Backend() {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!db_.get()) << "Close should have already been called.";
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(num_pending_ == 0 && pending_.empty());
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Database upgrade statements.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool EnsureDatabaseVersion();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class PendingOperation {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef enum {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERT_ADD,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERT_DELETE
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } OperationType;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PendingOperation(
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OperationType op,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const net::DefaultServerBoundCertStore::ServerBoundCert& cert)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : op_(op), cert_(cert) {}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OperationType op() const { return op_; }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::DefaultServerBoundCertStore::ServerBoundCert& cert() const {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return cert_;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OperationType op_;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::DefaultServerBoundCertStore::ServerBoundCert cert_;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Batch a server bound cert operation (add or delete).
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BatchOperation(
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PendingOperation::OperationType op,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const net::DefaultServerBoundCertStore::ServerBoundCert& cert);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commit our pending operations to the database.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Commit();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close() executed on the background thread.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InternalBackgroundClose();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DeleteCertificatesOnShutdown();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void DatabaseErrorCallback(int error, sql::Statement* stmt);
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void KillDatabase();
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path_;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<sql::Connection> db_;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::MetaTable meta_table_;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::list<PendingOperation*> PendingOperationsList;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOperationsList pending_;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOperationsList::size_type num_pending_;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the persistent store should skip clear on exit rules.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool force_keep_session_state_;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Guard |pending_|, |num_pending_| and |force_keep_session_state_|.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock lock_;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cache of origins we have certificates stored for.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<std::string> cert_origins_;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Indicates if the kill-database callback has been scheduled.
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool corruption_detected_;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Backend);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Version number of the database.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCurrentVersionNumber = 4;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompatibleVersionNumber = 1;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Initializes the certs table, returning true on success.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InitTable(sql::Connection* db) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The table is named "origin_bound_certs" for backwards compatability before
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we renamed this class to SQLiteServerBoundCertStore.  Likewise, the primary
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // key is "origin", but now can be other things like a plain domain.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db->DoesTableExist("origin_bound_certs")) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!db->Execute("CREATE TABLE origin_bound_certs ("
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "origin TEXT NOT NULL UNIQUE PRIMARY KEY,"
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "private_key BLOB NOT NULL,"
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "cert BLOB NOT NULL,"
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "cert_type INTEGER,"
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "expiration_time INTEGER,"
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "creation_time INTEGER)"))
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SQLiteServerBoundCertStore::Backend::Load(
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const LoadedCallback& loaded_callback) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This function should be called only once per instance.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!db_.get());
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ScopedVector<net::DefaultServerBoundCertStore::ServerBoundCert> >
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      certs(new ScopedVector<net::DefaultServerBoundCertStore::ServerBoundCert>(
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          ));
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedVector<net::DefaultServerBoundCertStore::ServerBoundCert>* certs_ptr =
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      certs.get();
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  background_task_runner_->PostTaskAndReply(
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      FROM_HERE,
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(&Backend::LoadOnDBThread, this, certs_ptr),
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(loaded_callback, base::Passed(&certs)));
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SQLiteServerBoundCertStore::Backend::LoadOnDBThread(
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ScopedVector<net::DefaultServerBoundCertStore::ServerBoundCert>* certs) {
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This method should be called only once per instance.
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!db_.get());
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeTicks start = base::TimeTicks::Now();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure the parent directory for storing certs is created before reading
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from it.
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::FilePath dir = path_.DirName();
196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!base::PathExists(dir) && !base::CreateDirectory(dir))
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 db_size = 0;
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (base::GetFileSize(path_, &db_size))
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_COUNTS("DomainBoundCerts.DBSizeInKB", db_size / 1024 );
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_.reset(new sql::Connection);
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  db_->set_histogram_tag("DomainBoundCerts");
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Unretained to avoid a ref loop with db_.
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  db_->set_error_callback(
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Bind(&SQLiteServerBoundCertStore::Backend::DatabaseErrorCallback,
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 base::Unretained(this)));
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db_->Open(path_)) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Unable to open cert DB.";
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (corruption_detected_)
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      KillDatabase();
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    db_.reset();
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EnsureDatabaseVersion() || !InitTable(db_.get())) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Unable to open cert DB.";
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (corruption_detected_)
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      KillDatabase();
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    meta_table_.Reset();
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    db_.reset();
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_->Preload();
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Slurp all the certs into the out-vector.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement smt(db_->GetUniqueStatement(
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "SELECT origin, private_key, cert, cert_type, expiration_time, "
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "creation_time FROM origin_bound_certs"));
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!smt.is_valid()) {
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (corruption_detected_)
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      KillDatabase();
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    meta_table_.Reset();
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    db_.reset();
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (smt.Step()) {
243bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    net::SSLClientCertType type =
244bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        static_cast<net::SSLClientCertType>(smt.ColumnInt(3));
245bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    if (type != net::CLIENT_CERT_ECDSA_SIGN)
246bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      continue;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string private_key_from_db, cert_from_db;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    smt.ColumnBlobAsString(1, &private_key_from_db);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    smt.ColumnBlobAsString(2, &cert_from_db);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<net::DefaultServerBoundCertStore::ServerBoundCert> cert(
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new net::DefaultServerBoundCertStore::ServerBoundCert(
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            smt.ColumnString(0),  // origin
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::Time::FromInternalValue(smt.ColumnInt64(5)),
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::Time::FromInternalValue(smt.ColumnInt64(4)),
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            private_key_from_db,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            cert_from_db));
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cert_origins_.insert(cert->server_identifier());
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    certs->push_back(cert.release());
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UMA_HISTOGRAM_COUNTS_10000("DomainBoundCerts.DBLoadedCount", certs->size());
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta load_time = base::TimeTicks::Now() - start;
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.DBLoadTime",
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             load_time,
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             base::TimeDelta::FromMilliseconds(1),
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             base::TimeDelta::FromMinutes(1),
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             50);
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "loaded " << certs->size() << " in " << load_time.InMilliseconds()
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << " ms";
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SQLiteServerBoundCertStore::Backend::EnsureDatabaseVersion() {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Version check.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!meta_table_.Init(
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      db_.get(), kCurrentVersionNumber, kCompatibleVersionNumber)) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Server bound cert database is too new.";
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int cur_version = meta_table_.GetVersionNumber();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cur_version == 1) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Transaction transaction(db_.get());
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!transaction.Begin())
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!db_->Execute("ALTER TABLE origin_bound_certs ADD COLUMN cert_type "
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "INTEGER")) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Unable to update server bound cert database to "
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << "version 2.";
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
295bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // All certs in version 1 database are rsa_sign, which are unsupported.
296bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // Just discard them all.
297bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    if (!db_->Execute("DELETE from origin_bound_certs")) {
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)    }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++cur_version;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    meta_table_.SetVersionNumber(cur_version);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    meta_table_.SetCompatibleVersionNumber(
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::min(cur_version, kCompatibleVersionNumber));
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transaction.Commit();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cur_version <= 3) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Transaction transaction(db_.get());
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!transaction.Begin())
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cur_version == 2) {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!db_->Execute("ALTER TABLE origin_bound_certs ADD COLUMN "
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        "expiration_time INTEGER")) {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Unable to update server bound cert database to "
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     << "version 4.";
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!db_->Execute("ALTER TABLE origin_bound_certs ADD COLUMN "
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "creation_time INTEGER")) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Unable to update server bound cert database to "
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << "version 4.";
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Statement smt(db_->GetUniqueStatement(
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "SELECT origin, cert FROM origin_bound_certs"));
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Statement update_expires_smt(db_->GetUniqueStatement(
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "UPDATE origin_bound_certs SET expiration_time = ? WHERE origin = ?"));
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Statement update_creation_smt(db_->GetUniqueStatement(
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "UPDATE origin_bound_certs SET creation_time = ? WHERE origin = ?"));
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!smt.is_valid() ||
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !update_expires_smt.is_valid() ||
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !update_creation_smt.is_valid()) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Unable to update server bound cert database to "
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << "version 4.";
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (smt.Step()) {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string origin = smt.ColumnString(0);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string cert_from_db;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      smt.ColumnBlobAsString(1, &cert_from_db);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Parse the cert and extract the real value and then update the DB.
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_refptr<net::X509Certificate> cert(
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::X509Certificate::CreateFromBytes(
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              cert_from_db.data(), cert_from_db.size()));
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (cert.get()) {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (cur_version == 2) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          update_expires_smt.Reset(true);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          update_expires_smt.BindInt64(0,
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       cert->valid_expiry().ToInternalValue());
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          update_expires_smt.BindString(1, origin);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!update_expires_smt.Run()) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            LOG(WARNING) << "Unable to update server bound cert database to "
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         << "version 4.";
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return false;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        update_creation_smt.Reset(true);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        update_creation_smt.BindInt64(0, cert->valid_start().ToInternalValue());
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        update_creation_smt.BindString(1, origin);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!update_creation_smt.Run()) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          LOG(WARNING) << "Unable to update server bound cert database to "
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       << "version 4.";
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If there's a cert we can't parse, just leave it.  It'll get replaced
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // with a new one if we ever try to use it.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Error parsing cert for database upgrade for origin "
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     << smt.ColumnString(0);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur_version = 4;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    meta_table_.SetVersionNumber(cur_version);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    meta_table_.SetCompatibleVersionNumber(
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::min(cur_version, kCompatibleVersionNumber));
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transaction.Commit();
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Put future migration cases here.
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When the version is too old, we just try to continue anyway, there should
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not be a released product that makes a database too old for us to handle.
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(WARNING, cur_version < kCurrentVersionNumber) <<
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Server bound cert database version " << cur_version <<
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " is too old to handle.";
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::DatabaseErrorCallback(
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int error,
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    sql::Statement* stmt) {
4024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!sql::IsErrorCatastrophic(error))
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(shess): Running KillDatabase() multiple times should be
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // safe.
409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (corruption_detected_)
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  corruption_detected_ = true;
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(shess): Consider just calling RazeAndClose() immediately.
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // db_ may not be safe to reset at this point, but RazeAndClose()
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // would cause the stack to unwind safely with errors.
4174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  background_task_runner_->PostTask(FROM_HERE,
4184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                    base::Bind(&Backend::KillDatabase, this));
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SQLiteServerBoundCertStore::Backend::KillDatabase() {
4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (db_) {
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // This Backend will now be in-memory only. In a future run the database
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // will be recreated. Hopefully things go better then!
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool success = db_->RazeAndClose();
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UMA_HISTOGRAM_BOOLEAN("DomainBoundCerts.KillDatabaseResult", success);
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    meta_table_.Reset();
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    db_.reset();
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::AddServerBoundCert(
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::DefaultServerBoundCertStore::ServerBoundCert& cert) {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BatchOperation(PendingOperation::CERT_ADD, cert);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::DeleteServerBoundCert(
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::DefaultServerBoundCertStore::ServerBoundCert& cert) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BatchOperation(PendingOperation::CERT_DELETE, cert);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::BatchOperation(
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PendingOperation::OperationType op,
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::DefaultServerBoundCertStore::ServerBoundCert& cert) {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commit every 30 seconds.
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kCommitIntervalMs = 30 * 1000;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commit right away if we have more than 512 outstanding operations.
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kCommitAfterBatchSize = 512;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do a full copy of the cert here, and hopefully just here.
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<PendingOperation> po(new PendingOperation(op, cert));
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOperationsList::size_type num_pending;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock locked(lock_);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_.push_back(po.release());
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_pending = ++num_pending_;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_pending == 1) {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've gotten our first entry for this batch, fire off the timer.
4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    background_task_runner_->PostDelayedTask(
4654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        FROM_HERE,
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&Backend::Commit, this),
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(kCommitIntervalMs));
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (num_pending == kCommitAfterBatchSize) {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've reached a big enough batch, fire off a commit now.
4704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    background_task_runner_->PostTask(FROM_HERE,
4714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                      base::Bind(&Backend::Commit, this));
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::Commit() {
4764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOperationsList ops;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock locked(lock_);
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_.swap(ops);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_pending_ = 0;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Maybe an old timer fired or we are already Close()'ed.
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db_.get() || ops.empty())
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement add_smt(db_->GetCachedStatement(SQL_FROM_HERE,
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "INSERT INTO origin_bound_certs (origin, private_key, cert, cert_type, "
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "expiration_time, creation_time) VALUES (?,?,?,?,?,?)"));
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!add_smt.is_valid())
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement del_smt(db_->GetCachedStatement(SQL_FROM_HERE,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "DELETE FROM origin_bound_certs WHERE origin=?"));
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!del_smt.is_valid())
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Transaction transaction(db_.get());
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!transaction.Begin())
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingOperationsList::iterator it = ops.begin();
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != ops.end(); ++it) {
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Free the certs as we commit them to the database.
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<PendingOperation> po(*it);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (po->op()) {
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PendingOperation::CERT_ADD: {
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cert_origins_.insert(po->cert().server_identifier());
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        add_smt.Reset(true);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        add_smt.BindString(0, po->cert().server_identifier());
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const std::string& private_key = po->cert().private_key();
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        add_smt.BindBlob(1, private_key.data(), private_key.size());
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const std::string& cert = po->cert().cert();
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        add_smt.BindBlob(2, cert.data(), cert.size());
517bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        add_smt.BindInt(3, net::CLIENT_CERT_ECDSA_SIGN);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        add_smt.BindInt64(4, po->cert().expiration_time().ToInternalValue());
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        add_smt.BindInt64(5, po->cert().creation_time().ToInternalValue());
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!add_smt.Run())
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NOTREACHED() << "Could not add a server bound cert to the DB.";
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PendingOperation::CERT_DELETE:
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cert_origins_.erase(po->cert().server_identifier());
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        del_smt.Reset(true);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        del_smt.BindString(0, po->cert().server_identifier());
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!del_smt.Run())
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NOTREACHED() << "Could not delete a server bound cert from the DB.";
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED();
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transaction.Commit();
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fire off a close message to the background thread. We could still have a
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pending commit timer that will be holding a reference on us, but if/when
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this fires we will already have been cleaned up and it will be ignored.
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::Close() {
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Must close the backend on the background thread.
5454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  background_task_runner_->PostTask(
5464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      FROM_HERE, base::Bind(&Backend::InternalBackgroundClose, this));
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::InternalBackgroundClose() {
5504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commit any pending operations
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Commit();
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!force_keep_session_state_ &&
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      special_storage_policy_.get() &&
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      special_storage_policy_->HasSessionOnlyOrigins()) {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeleteCertificatesOnShutdown();
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_.reset();
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::DeleteCertificatesOnShutdown() {
5644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db_.get())
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cert_origins_.empty())
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!special_storage_policy_.get())
573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement del_smt(db_->GetCachedStatement(
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SQL_FROM_HERE, "DELETE FROM origin_bound_certs WHERE origin=?"));
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!del_smt.is_valid()) {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Unable to delete certificates on shutdown.";
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Transaction transaction(db_.get());
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!transaction.Begin()) {
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Unable to delete certificates on shutdown.";
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<std::string>::iterator it = cert_origins_.begin();
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != cert_origins_.end(); ++it) {
590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const GURL url(net::cookie_util::CookieOriginToURL(*it, true));
591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!url.is_valid() || !special_storage_policy_->IsStorageSessionOnly(url))
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    del_smt.Reset(true);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    del_smt.BindString(0, *it);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!del_smt.Run())
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Could not delete a certificate from the DB.";
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!transaction.Commit())
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Unable to delete certificates on shutdown.";
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::Backend::SetForceKeepSessionState() {
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock locked(lock_);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  force_keep_session_state_ = true;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SQLiteServerBoundCertStore::SQLiteServerBoundCertStore(
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& path,
6104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    quota::SpecialStoragePolicy* special_storage_policy)
6124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : backend_(new Backend(path,
6134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           background_task_runner,
6144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           special_storage_policy)) {}
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SQLiteServerBoundCertStore::Load(
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const LoadedCallback& loaded_callback) {
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backend_->Load(loaded_callback);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::AddServerBoundCert(
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::DefaultServerBoundCertStore::ServerBoundCert& cert) {
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backend_->AddServerBoundCert(cert);
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::DeleteServerBoundCert(
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::DefaultServerBoundCertStore::ServerBoundCert& cert) {
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backend_->DeleteServerBoundCert(cert);
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SQLiteServerBoundCertStore::SetForceKeepSessionState() {
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backend_->SetForceKeepSessionState();
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SQLiteServerBoundCertStore::~SQLiteServerBoundCertStore() {
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backend_->Close();
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We release our reference to the Backend, though it will probably still have
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a reference if the background thread has not run Close() yet.
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
640