sqlite_channel_id_store.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 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)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/extras/sqlite/sqlite_channel_id_store.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/location.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/memory/scoped_vector.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h"
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/sequenced_task_runner.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.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"
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace {
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Version number of the database.
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kCurrentVersionNumber = 4;
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kCompatibleVersionNumber = 1;
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Initializes the certs table, returning true on success.
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool InitTable(sql::Connection* db) {
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The table is named "origin_bound_certs" for backwards compatability before
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // we renamed this class to SQLiteChannelIDStore.  Likewise, the primary
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // key is "origin", but now can be other things like a plain domain.
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!db->DoesTableExist("origin_bound_certs")) {
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!db->Execute(
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            "CREATE TABLE origin_bound_certs ("
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            "origin TEXT NOT NULL UNIQUE PRIMARY KEY,"
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            "private_key BLOB NOT NULL,"
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            "cert BLOB NOT NULL,"
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            "cert_type INTEGER,"
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            "expiration_time INTEGER,"
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            "creation_time INTEGER)")) {
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace net {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class is designed to be shared between any calling threads and the
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// background task runner. It batches operations and commits them on a timer.
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class SQLiteChannelIDStore::Backend
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : public base::RefCountedThreadSafe<SQLiteChannelIDStore::Backend> {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Backend(
664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const base::FilePath& path,
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const scoped_refptr<base::SequencedTaskRunner>& background_task_runner)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : path_(path),
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_pending_(0),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        force_keep_session_state_(false),
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        background_task_runner_(background_task_runner),
727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        corruption_detected_(false) {}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Creates or loads the SQLite database.
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Load(const LoadedCallback& loaded_callback);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Batch a channel ID addition.
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void AddChannelID(const DefaultChannelIDStore::ChannelID& channel_id);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Batch a channel ID deletion.
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void DeleteChannelID(const DefaultChannelIDStore::ChannelID& channel_id);
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Post background delete of all channel ids for |server_identifiers|.
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void DeleteAllInList(const std::list<std::string>& server_identifiers);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commit any pending operations and close the database.  This must be called
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // before the object is destructed.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Close();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetForceKeepSessionState();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  friend class base::RefCountedThreadSafe<SQLiteChannelIDStore::Backend>;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // You should call Close() before destructing this object.
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual ~Backend() {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!db_.get()) << "Close should have already been called.";
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK_EQ(0u, num_pending_);
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK(pending_.empty());
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void LoadInBackground(
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ScopedVector<DefaultChannelIDStore::ChannelID>* channel_ids);
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Database upgrade statements.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool EnsureDatabaseVersion();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class PendingOperation {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    enum OperationType { CHANNEL_ID_ADD, CHANNEL_ID_DELETE };
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    PendingOperation(OperationType op,
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     const DefaultChannelIDStore::ChannelID& channel_id)
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        : op_(op), channel_id_(channel_id) {}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OperationType op() const { return op_; }
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const DefaultChannelIDStore::ChannelID& channel_id() const {
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return channel_id_;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OperationType op_;
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DefaultChannelIDStore::ChannelID channel_id_;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Batch a channel id operation (add or delete).
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void BatchOperation(PendingOperation::OperationType op,
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                      const DefaultChannelIDStore::ChannelID& channel_id);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commit our pending operations to the database.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Commit();
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Close() executed on the background task runner.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InternalBackgroundClose();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void BackgroundDeleteAllInList(
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const std::list<std::string>& server_identifiers);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void DatabaseErrorCallback(int error, sql::Statement* stmt);
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void KillDatabase();
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const base::FilePath path_;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<sql::Connection> db_;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::MetaTable meta_table_;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::list<PendingOperation*> PendingOperationsList;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOperationsList pending_;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOperationsList::size_type num_pending_;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the persistent store should skip clear on exit rules.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool force_keep_session_state_;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Guard |pending_|, |num_pending_| and |force_keep_session_state_|.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock lock_;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Indicates if the kill-database callback has been scheduled.
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool corruption_detected_;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Backend);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SQLiteChannelIDStore::Backend::Load(
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const LoadedCallback& loaded_callback) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This function should be called only once per instance.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!db_.get());
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<ScopedVector<DefaultChannelIDStore::ChannelID> > channel_ids(
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new ScopedVector<DefaultChannelIDStore::ChannelID>());
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScopedVector<DefaultChannelIDStore::ChannelID>* channel_ids_ptr =
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      channel_ids.get();
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  background_task_runner_->PostTaskAndReply(
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      FROM_HERE,
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&Backend::LoadInBackground, this, channel_ids_ptr),
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(loaded_callback, base::Passed(&channel_ids)));
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SQLiteChannelIDStore::Backend::LoadInBackground(
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ScopedVector<DefaultChannelIDStore::ChannelID>* channel_ids) {
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This method should be called only once per instance.
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!db_.get());
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeTicks start = base::TimeTicks::Now();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure the parent directory for storing certs is created before reading
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from it.
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::FilePath dir = path_.DirName();
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!base::PathExists(dir) && !base::CreateDirectory(dir))
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 db_size = 0;
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (base::GetFileSize(path_, &db_size))
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    UMA_HISTOGRAM_COUNTS("DomainBoundCerts.DBSizeInKB", db_size / 1024);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_.reset(new sql::Connection);
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  db_->set_histogram_tag("DomainBoundCerts");
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Unretained to avoid a ref loop with db_.
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  db_->set_error_callback(
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&SQLiteChannelIDStore::Backend::DatabaseErrorCallback,
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 base::Unretained(this)));
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db_->Open(path_)) {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Unable to open cert DB.";
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (corruption_detected_)
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      KillDatabase();
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    db_.reset();
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EnsureDatabaseVersion() || !InitTable(db_.get())) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Unable to open cert DB.";
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (corruption_detected_)
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      KillDatabase();
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    meta_table_.Reset();
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    db_.reset();
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_->Preload();
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Slurp all the certs into the out-vector.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement smt(db_->GetUniqueStatement(
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "SELECT origin, private_key, cert, cert_type, expiration_time, "
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "creation_time FROM origin_bound_certs"));
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!smt.is_valid()) {
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (corruption_detected_)
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      KillDatabase();
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    meta_table_.Reset();
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    db_.reset();
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (smt.Step()) {
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SSLClientCertType type = static_cast<SSLClientCertType>(smt.ColumnInt(3));
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (type != CLIENT_CERT_ECDSA_SIGN)
237bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      continue;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string private_key_from_db, cert_from_db;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    smt.ColumnBlobAsString(1, &private_key_from_db);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    smt.ColumnBlobAsString(2, &cert_from_db);
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<DefaultChannelIDStore::ChannelID> channel_id(
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new DefaultChannelIDStore::ChannelID(
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            smt.ColumnString(0),  // origin
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::Time::FromInternalValue(smt.ColumnInt64(5)),
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::Time::FromInternalValue(smt.ColumnInt64(4)),
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            private_key_from_db,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            cert_from_db));
2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    channel_ids->push_back(channel_id.release());
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  UMA_HISTOGRAM_COUNTS_10000(
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      "DomainBoundCerts.DBLoadedCount",
2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      static_cast<base::HistogramBase::Sample>(channel_ids->size()));
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta load_time = base::TimeTicks::Now() - start;
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.DBLoadTime",
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             load_time,
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             base::TimeDelta::FromMilliseconds(1),
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             base::TimeDelta::FromMinutes(1),
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             50);
2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DVLOG(1) << "loaded " << channel_ids->size() << " in "
2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)           << load_time.InMilliseconds() << " ms";
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool SQLiteChannelIDStore::Backend::EnsureDatabaseVersion() {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Version check.
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!meta_table_.Init(
2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          db_.get(), kCurrentVersionNumber, kCompatibleVersionNumber)) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Server bound cert database is too new.";
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int cur_version = meta_table_.GetVersionNumber();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cur_version == 1) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Transaction transaction(db_.get());
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!transaction.Begin())
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!db_->Execute(
2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            "ALTER TABLE origin_bound_certs ADD COLUMN cert_type "
2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            "INTEGER")) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Unable to update server bound cert database to "
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << "version 2.";
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
288bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // All certs in version 1 database are rsa_sign, which are unsupported.
289bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // Just discard them all.
290bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    if (!db_->Execute("DELETE from origin_bound_certs")) {
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)    }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++cur_version;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    meta_table_.SetVersionNumber(cur_version);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    meta_table_.SetCompatibleVersionNumber(
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::min(cur_version, kCompatibleVersionNumber));
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transaction.Commit();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cur_version <= 3) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Transaction transaction(db_.get());
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!transaction.Begin())
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cur_version == 2) {
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (!db_->Execute(
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              "ALTER TABLE origin_bound_certs ADD COLUMN "
3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              "expiration_time INTEGER")) {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Unable to update server bound cert database to "
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     << "version 4.";
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!db_->Execute(
3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            "ALTER TABLE origin_bound_certs ADD COLUMN "
3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            "creation_time INTEGER")) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Unable to update server bound cert database to "
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << "version 4.";
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    sql::Statement statement(
3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        db_->GetUniqueStatement("SELECT origin, cert FROM origin_bound_certs"));
3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    sql::Statement update_expires_statement(db_->GetUniqueStatement(
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "UPDATE origin_bound_certs SET expiration_time = ? WHERE origin = ?"));
3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    sql::Statement update_creation_statement(db_->GetUniqueStatement(
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "UPDATE origin_bound_certs SET creation_time = ? WHERE origin = ?"));
3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!statement.is_valid() || !update_expires_statement.is_valid() ||
3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        !update_creation_statement.is_valid()) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Unable to update server bound cert database to "
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << "version 4.";
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    while (statement.Step()) {
3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      std::string origin = statement.ColumnString(0);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string cert_from_db;
3411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      statement.ColumnBlobAsString(1, &cert_from_db);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Parse the cert and extract the real value and then update the DB.
3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromBytes(
3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          cert_from_db.data(), static_cast<int>(cert_from_db.size())));
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (cert.get()) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (cur_version == 2) {
3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          update_expires_statement.Reset(true);
3481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          update_expires_statement.BindInt64(
3491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              0, cert->valid_expiry().ToInternalValue());
3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          update_expires_statement.BindString(1, origin);
3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          if (!update_expires_statement.Run()) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            LOG(WARNING) << "Unable to update server bound cert database to "
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         << "version 4.";
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return false;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        update_creation_statement.Reset(true);
3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        update_creation_statement.BindInt64(
3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            0, cert->valid_start().ToInternalValue());
3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        update_creation_statement.BindString(1, origin);
3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (!update_creation_statement.Run()) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          LOG(WARNING) << "Unable to update server bound cert database to "
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       << "version 4.";
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If there's a cert we can't parse, just leave it.  It'll get replaced
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // with a new one if we ever try to use it.
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Error parsing cert for database upgrade for origin "
3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     << statement.ColumnString(0);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur_version = 4;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    meta_table_.SetVersionNumber(cur_version);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    meta_table_.SetCompatibleVersionNumber(
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::min(cur_version, kCompatibleVersionNumber));
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transaction.Commit();
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Put future migration cases here.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When the version is too old, we just try to continue anyway, there should
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not be a released product that makes a database too old for us to handle.
3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  LOG_IF(WARNING, cur_version < kCurrentVersionNumber)
3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      << "Server bound cert database version " << cur_version
3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      << " is too old to handle.";
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SQLiteChannelIDStore::Backend::DatabaseErrorCallback(
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int error,
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    sql::Statement* stmt) {
3964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!sql::IsErrorCatastrophic(error))
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(shess): Running KillDatabase() multiple times should be
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // safe.
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (corruption_detected_)
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  corruption_detected_ = true;
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(shess): Consider just calling RazeAndClose() immediately.
409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // db_ may not be safe to reset at this point, but RazeAndClose()
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // would cause the stack to unwind safely with errors.
4114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  background_task_runner_->PostTask(FROM_HERE,
4124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                    base::Bind(&Backend::KillDatabase, this));
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SQLiteChannelIDStore::Backend::KillDatabase() {
4164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (db_) {
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // This Backend will now be in-memory only. In a future run the database
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // will be recreated. Hopefully things go better then!
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool success = db_->RazeAndClose();
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UMA_HISTOGRAM_BOOLEAN("DomainBoundCerts.KillDatabaseResult", success);
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    meta_table_.Reset();
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    db_.reset();
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SQLiteChannelIDStore::Backend::AddChannelID(
4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const DefaultChannelIDStore::ChannelID& channel_id) {
4305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  BatchOperation(PendingOperation::CHANNEL_ID_ADD, channel_id);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SQLiteChannelIDStore::Backend::DeleteChannelID(
4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const DefaultChannelIDStore::ChannelID& channel_id) {
4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  BatchOperation(PendingOperation::CHANNEL_ID_DELETE, channel_id);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SQLiteChannelIDStore::Backend::DeleteAllInList(
4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::list<std::string>& server_identifiers) {
4401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (server_identifiers.empty())
4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Perform deletion on background task runner.
4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  background_task_runner_->PostTask(
4441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FROM_HERE,
4451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(
4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          &Backend::BackgroundDeleteAllInList, this, server_identifiers));
4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SQLiteChannelIDStore::Backend::BatchOperation(
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PendingOperation::OperationType op,
4511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const DefaultChannelIDStore::ChannelID& channel_id) {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commit every 30 seconds.
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kCommitIntervalMs = 30 * 1000;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commit right away if we have more than 512 outstanding operations.
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kCommitAfterBatchSize = 512;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do a full copy of the cert here, and hopefully just here.
4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<PendingOperation> po(new PendingOperation(op, channel_id));
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOperationsList::size_type num_pending;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock locked(lock_);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_.push_back(po.release());
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_pending = ++num_pending_;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_pending == 1) {
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've gotten our first entry for this batch, fire off the timer.
4694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    background_task_runner_->PostDelayedTask(
4704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        FROM_HERE,
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&Backend::Commit, this),
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(kCommitIntervalMs));
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (num_pending == kCommitAfterBatchSize) {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've reached a big enough batch, fire off a commit now.
4754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    background_task_runner_->PostTask(FROM_HERE,
4764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                      base::Bind(&Backend::Commit, this));
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SQLiteChannelIDStore::Backend::Commit() {
4814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOperationsList ops;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock locked(lock_);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_.swap(ops);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_pending_ = 0;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Maybe an old timer fired or we are already Close()'ed.
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db_.get() || ops.empty())
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  sql::Statement add_statement(db_->GetCachedStatement(
4951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      SQL_FROM_HERE,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "INSERT INTO origin_bound_certs (origin, private_key, cert, cert_type, "
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "expiration_time, creation_time) VALUES (?,?,?,?,?,?)"));
4981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!add_statement.is_valid())
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  sql::Statement del_statement(db_->GetCachedStatement(
5021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      SQL_FROM_HERE, "DELETE FROM origin_bound_certs WHERE origin=?"));
5031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!del_statement.is_valid())
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Transaction transaction(db_.get());
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!transaction.Begin())
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (PendingOperationsList::iterator it = ops.begin(); it != ops.end();
5111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       ++it) {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Free the certs as we commit them to the database.
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<PendingOperation> po(*it);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (po->op()) {
5155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      case PendingOperation::CHANNEL_ID_ADD: {
5161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        add_statement.Reset(true);
5171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        add_statement.BindString(0, po->channel_id().server_identifier());
5185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        const std::string& private_key = po->channel_id().private_key();
5191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        add_statement.BindBlob(
5201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            1, private_key.data(), static_cast<int>(private_key.size()));
5215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        const std::string& cert = po->channel_id().cert();
5221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        add_statement.BindBlob(2, cert.data(), static_cast<int>(cert.size()));
5231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        add_statement.BindInt(3, CLIENT_CERT_ECDSA_SIGN);
5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        add_statement.BindInt64(
5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            4, po->channel_id().expiration_time().ToInternalValue());
5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        add_statement.BindInt64(
5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            5, po->channel_id().creation_time().ToInternalValue());
5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (!add_statement.Run())
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NOTREACHED() << "Could not add a server bound cert to the DB.";
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      case PendingOperation::CHANNEL_ID_DELETE:
5331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        del_statement.Reset(true);
5341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        del_statement.BindString(0, po->channel_id().server_identifier());
5351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (!del_statement.Run())
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NOTREACHED() << "Could not delete a server bound cert from the DB.";
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED();
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transaction.Commit();
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Fire off a close message to the background task runner. We could still have a
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pending commit timer that will be holding a reference on us, but if/when
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this fires we will already have been cleaned up and it will be ignored.
5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SQLiteChannelIDStore::Backend::Close() {
5511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Must close the backend on the background task runner.
5524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  background_task_runner_->PostTask(
5534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      FROM_HERE, base::Bind(&Backend::InternalBackgroundClose, this));
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SQLiteChannelIDStore::Backend::InternalBackgroundClose() {
5574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commit any pending operations
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Commit();
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_.reset();
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SQLiteChannelIDStore::Backend::BackgroundDeleteAllInList(
5641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::list<std::string>& server_identifiers) {
5654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db_.get())
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement del_smt(db_->GetCachedStatement(
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SQL_FROM_HERE, "DELETE FROM origin_bound_certs WHERE origin=?"));
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!del_smt.is_valid()) {
5731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    LOG(WARNING) << "Unable to delete channel ids.";
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Transaction transaction(db_.get());
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!transaction.Begin()) {
5791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    LOG(WARNING) << "Unable to delete channel ids.";
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (std::list<std::string>::const_iterator it = server_identifiers.begin();
5841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       it != server_identifiers.end();
5851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       ++it) {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    del_smt.Reset(true);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    del_smt.BindString(0, *it);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!del_smt.Run())
5891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      NOTREACHED() << "Could not delete a channel id from the DB.";
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!transaction.Commit())
5931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    LOG(WARNING) << "Unable to delete channel ids.";
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SQLiteChannelIDStore::Backend::SetForceKeepSessionState() {
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock locked(lock_);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  force_keep_session_state_ = true;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SQLiteChannelIDStore::SQLiteChannelIDStore(
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& path,
6031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner)
6041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : backend_(new Backend(path, background_task_runner)) {
60503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SQLiteChannelIDStore::Load(const LoadedCallback& loaded_callback) {
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backend_->Load(loaded_callback);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SQLiteChannelIDStore::AddChannelID(
6121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const DefaultChannelIDStore::ChannelID& channel_id) {
6135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  backend_->AddChannelID(channel_id);
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SQLiteChannelIDStore::DeleteChannelID(
6171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const DefaultChannelIDStore::ChannelID& channel_id) {
6185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  backend_->DeleteChannelID(channel_id);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SQLiteChannelIDStore::DeleteAllInList(
6221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::list<std::string>& server_identifiers) {
6231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  backend_->DeleteAllInList(server_identifiers);
6241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
6251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SQLiteChannelIDStore::SetForceKeepSessionState() {
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backend_->SetForceKeepSessionState();
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SQLiteChannelIDStore::~SQLiteChannelIDStore() {
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backend_->Close();
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We release our reference to the Backend, though it will probably still have
6331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // a reference if the background task runner has not run Close() yet.
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace net
637