1ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// found in the LICENSE file.
4ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
5ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "content/browser/media/webrtc_identity_store_backend.h"
6ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
7ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/files/file_path.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/memory/scoped_vector.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/strings/string_util.h"
11ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "content/public/browser/browser_thread.h"
12ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "net/base/net_errors.h"
13ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "sql/error_delegate_util.h"
14ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "sql/statement.h"
15ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "sql/transaction.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/quota/special_storage_policy.h"
17ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "url/gurl.h"
18ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
19ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace content {
20ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)static const char kWebRTCIdentityStoreDBName[] = "webrtc_identity_store";
22ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
23ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstatic const base::FilePath::CharType kWebRTCIdentityStoreDirectory[] =
24ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    FILE_PATH_LITERAL("WebRTCIdentityStore");
25ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
26ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Initializes the identity table, returning true on success.
27ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstatic bool InitDB(sql::Connection* db) {
28ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (db->DoesTableExist(kWebRTCIdentityStoreDBName)) {
29ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (db->DoesColumnExist(kWebRTCIdentityStoreDBName, "origin") &&
30ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        db->DoesColumnExist(kWebRTCIdentityStoreDBName, "identity_name") &&
31ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        db->DoesColumnExist(kWebRTCIdentityStoreDBName, "common_name") &&
32ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        db->DoesColumnExist(kWebRTCIdentityStoreDBName, "certificate") &&
33ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        db->DoesColumnExist(kWebRTCIdentityStoreDBName, "private_key") &&
34ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        db->DoesColumnExist(kWebRTCIdentityStoreDBName, "creation_time"))
35ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return true;
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
37ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!db->Execute("DROP TABLE webrtc_identity_store"))
38ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return false;
39ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
40ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
41ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return db->Execute(
42ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "CREATE TABLE webrtc_identity_store"
43ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      " ("
44ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "origin TEXT NOT NULL,"
45ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "identity_name TEXT NOT NULL,"
46ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "common_name TEXT NOT NULL,"
47ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "certificate BLOB NOT NULL,"
48ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "private_key BLOB NOT NULL,"
49ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "creation_time INTEGER)");
50ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
51ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
52ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstruct WebRTCIdentityStoreBackend::IdentityKey {
53ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IdentityKey(const GURL& origin, const std::string& identity_name)
54ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      : origin(origin), identity_name(identity_name) {}
55ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
56ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool operator<(const IdentityKey& other) const {
57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return origin < other.origin ||
58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           (origin == other.origin && identity_name < other.identity_name);
59ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GURL origin;
62ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string identity_name;
63ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
65ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstruct WebRTCIdentityStoreBackend::Identity {
66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Identity(const std::string& common_name,
67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           const std::string& certificate,
68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           const std::string& private_key)
69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      : common_name(common_name),
70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        certificate(certificate),
71ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        private_key(private_key),
72ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        creation_time(base::Time::Now().ToInternalValue()) {}
73ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Identity(const std::string& common_name,
75ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           const std::string& certificate,
76ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           const std::string& private_key,
77ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           int64 creation_time)
78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      : common_name(common_name),
79ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        certificate(certificate),
80ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        private_key(private_key),
81ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        creation_time(creation_time) {}
82ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
83ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string common_name;
84ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string certificate;
85ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string private_key;
86ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  int64 creation_time;
87ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
88ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
89ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstruct WebRTCIdentityStoreBackend::PendingFindRequest {
90ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  PendingFindRequest(const GURL& origin,
91ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     const std::string& identity_name,
92ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     const std::string& common_name,
93ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     const FindIdentityCallback& callback)
94ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      : origin(origin),
95ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        identity_name(identity_name),
96ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        common_name(common_name),
97ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        callback(callback) {}
98ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
99ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  ~PendingFindRequest() {}
100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
101ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GURL origin;
102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string identity_name;
103ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string common_name;
104ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  FindIdentityCallback callback;
105ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
106ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
107ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// The class encapsulates the database operations. All members except ctor and
108ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// dtor should be accessed on the DB thread.
109ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// It can be created/destroyed on any thread.
110ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochclass WebRTCIdentityStoreBackend::SqlLiteStorage
111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : public base::RefCountedThreadSafe<SqlLiteStorage> {
112ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch public:
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SqlLiteStorage(base::TimeDelta validity_period,
1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 const base::FilePath& path,
11503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                 storage::SpecialStoragePolicy* policy)
1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      : validity_period_(validity_period), special_storage_policy_(policy) {
117ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!path.empty())
118ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      path_ = path.Append(kWebRTCIdentityStoreDirectory);
119ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
120ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
121ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void Load(IdentityMap* out_map);
122ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void Close();
123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void AddIdentity(const GURL& origin,
124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   const std::string& identity_name,
125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   const Identity& identity);
126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void DeleteIdentity(const GURL& origin,
127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      const std::string& identity_name,
128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      const Identity& identity);
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void DeleteBetween(base::Time delete_begin, base::Time delete_end);
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void SetValidityPeriodForTesting(base::TimeDelta validity_period) {
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK(!db_.get());
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    validity_period_ = validity_period;
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch private:
138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  friend class base::RefCountedThreadSafe<SqlLiteStorage>;
139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  enum OperationType {
141ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    ADD_IDENTITY,
142ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DELETE_IDENTITY
143ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  };
144ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  struct PendingOperation {
145ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    PendingOperation(OperationType type,
146ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     const GURL& origin,
147ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     const std::string& identity_name,
148ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     const Identity& identity)
149ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        : type(type),
150ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          origin(origin),
151ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          identity_name(identity_name),
152ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          identity(identity) {}
153ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
154ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    OperationType type;
155ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    GURL origin;
156ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    std::string identity_name;
157ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    Identity identity;
158ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  };
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  typedef ScopedVector<PendingOperation> PendingOperationList;
160ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
161ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  virtual ~SqlLiteStorage() {}
162ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void OnDatabaseError(int error, sql::Statement* stmt);
163ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void BatchOperation(OperationType type,
164ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      const GURL& origin,
165ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      const std::string& identity_name,
166ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      const Identity& identity);
167ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void Commit();
168ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::TimeDelta validity_period_;
170ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // The file path of the DB. Empty if temporary.
171ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::FilePath path_;
17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
173ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  scoped_ptr<sql::Connection> db_;
174ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Batched DB operations pending to commit.
175ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  PendingOperationList pending_operations_;
176ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
177ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(SqlLiteStorage);
178ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
179ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
180ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochWebRTCIdentityStoreBackend::WebRTCIdentityStoreBackend(
181ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const base::FilePath& path,
18203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    storage::SpecialStoragePolicy* policy,
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::TimeDelta validity_period)
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : validity_period_(validity_period),
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      state_(NOT_STARTED),
18603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      sql_lite_storage_(new SqlLiteStorage(validity_period, path, policy)) {
18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
189ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool WebRTCIdentityStoreBackend::FindIdentity(
190ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const GURL& origin,
191ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& identity_name,
192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& common_name,
193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const FindIdentityCallback& callback) {
194ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
195ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (state_ == CLOSED)
196ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return false;
197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
198ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (state_ != LOADED) {
199ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Queues the request to wait for the DB to load.
200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    pending_find_requests_.push_back(
201ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        new PendingFindRequest(origin, identity_name, common_name, callback));
202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (state_ == LOADING)
203ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return true;
204ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
205ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DCHECK_EQ(state_, NOT_STARTED);
206ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
207ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Kick off loading the DB.
208ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    scoped_ptr<IdentityMap> out_map(new IdentityMap());
2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::Closure task(
2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        base::Bind(&SqlLiteStorage::Load, sql_lite_storage_, out_map.get()));
2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // |out_map| will be NULL after this call.
212ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (BrowserThread::PostTaskAndReply(
213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            BrowserThread::DB,
214ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            FROM_HERE,
2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            task,
216ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            base::Bind(&WebRTCIdentityStoreBackend::OnLoaded,
217ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       this,
218ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       base::Passed(&out_map)))) {
219ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      state_ = LOADING;
220ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return true;
221ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // If it fails to post task, falls back to ERR_FILE_NOT_FOUND.
223ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
224ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
225ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IdentityKey key(origin, identity_name);
226ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IdentityMap::iterator iter = identities_.find(key);
227ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (iter != identities_.end() && iter->second.common_name == common_name) {
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::TimeDelta age = base::Time::Now() - base::Time::FromInternalValue(
2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                                  iter->second.creation_time);
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (age < validity_period_) {
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Identity found.
2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return BrowserThread::PostTask(BrowserThread::IO,
2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                     FROM_HERE,
2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                     base::Bind(callback,
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                                net::OK,
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                                iter->second.certificate,
2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                                iter->second.private_key));
2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Removes the expired identity from the in-memory cache. The copy in the
2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // database will be removed on the next load.
2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    identities_.erase(iter);
242ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
243ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
244ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return BrowserThread::PostTask(
245ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      BrowserThread::IO,
246ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FROM_HERE,
247ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(callback, net::ERR_FILE_NOT_FOUND, "", ""));
248ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
249ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
250ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::AddIdentity(const GURL& origin,
251ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             const std::string& identity_name,
252ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             const std::string& common_name,
253ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             const std::string& certificate,
254ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             const std::string& private_key) {
255ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
256ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (state_ == CLOSED)
257ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
258ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
259ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // If there is an existing identity for the same origin and identity_name,
260ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // delete it.
261ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IdentityKey key(origin, identity_name);
262ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Identity identity(common_name, certificate, private_key);
263ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
264ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (identities_.find(key) != identities_.end()) {
265ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!BrowserThread::PostTask(BrowserThread::DB,
266ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                 FROM_HERE,
267ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                 base::Bind(&SqlLiteStorage::DeleteIdentity,
268ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            sql_lite_storage_,
269ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            origin,
270ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            identity_name,
271ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            identities_.find(key)->second)))
272ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return;
273ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
274ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  identities_.insert(std::pair<IdentityKey, Identity>(key, identity));
275ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
276ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BrowserThread::PostTask(BrowserThread::DB,
277ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                          FROM_HERE,
278ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                          base::Bind(&SqlLiteStorage::AddIdentity,
279ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                     sql_lite_storage_,
280ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                     origin,
281ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                     identity_name,
282ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                     identity));
283ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
284ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
285ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::Close() {
286ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
287ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    BrowserThread::PostTask(
288ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        BrowserThread::IO,
289ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        FROM_HERE,
290ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        base::Bind(&WebRTCIdentityStoreBackend::Close, this));
291ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
292ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
293ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
294ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (state_ == CLOSED)
295ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
296ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
297ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_ = CLOSED;
298ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BrowserThread::PostTask(
299ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      BrowserThread::DB,
300ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FROM_HERE,
301ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&SqlLiteStorage::Close, sql_lite_storage_));
302ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
303ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
304ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::DeleteBetween(base::Time delete_begin,
305ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                               base::Time delete_end,
306ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                               const base::Closure& callback) {
307ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (state_ == CLOSED)
3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
311ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Delete the in-memory cache.
312ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IdentityMap::iterator it = identities_.begin();
313ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  while (it != identities_.end()) {
314ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (it->second.creation_time >= delete_begin.ToInternalValue() &&
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        it->second.creation_time <= delete_end.ToInternalValue()) {
316ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      identities_.erase(it++);
3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    } else {
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ++it;
3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
320ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
321ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BrowserThread::PostTaskAndReply(BrowserThread::DB,
322ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                  FROM_HERE,
323ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                  base::Bind(&SqlLiteStorage::DeleteBetween,
324ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             sql_lite_storage_,
325ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             delete_begin,
3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                             delete_end),
327ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                  callback);
328ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
329ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRTCIdentityStoreBackend::SetValidityPeriodForTesting(
3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::TimeDelta validity_period) {
3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  validity_period_ = validity_period;
3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrowserThread::PostTask(
3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      BrowserThread::DB,
3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      FROM_HERE,
3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(&SqlLiteStorage::SetValidityPeriodForTesting,
3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 sql_lite_storage_,
3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 validity_period));
3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
342ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochWebRTCIdentityStoreBackend::~WebRTCIdentityStoreBackend() {}
343ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
344ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::OnLoaded(scoped_ptr<IdentityMap> out_map) {
345ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (state_ != LOADING)
3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DVLOG(3) << "WebRTC identity store has loaded.";
3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
352ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_ = LOADED;
353ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  identities_.swap(*out_map);
354ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
355ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (size_t i = 0; i < pending_find_requests_.size(); ++i) {
356ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    FindIdentity(pending_find_requests_[i]->origin,
357ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 pending_find_requests_[i]->identity_name,
358ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 pending_find_requests_[i]->common_name,
359ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 pending_find_requests_[i]->callback);
360ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    delete pending_find_requests_[i];
361ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
362ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  pending_find_requests_.clear();
363ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
364ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
365ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//
366ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Implementation of SqlLiteStorage.
367ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//
368ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
369ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::Load(IdentityMap* out_map) {
370ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
371ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(!db_.get());
372ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
373ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Ensure the parent directory for storing certs is created before reading
374ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // from it.
375ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const base::FilePath dir = path_.DirName();
376a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!base::PathExists(dir) && !base::CreateDirectory(dir)) {
377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Unable to open DB file path.";
378ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
379ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
380ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
381ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  db_.reset(new sql::Connection());
382ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
383ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  db_->set_error_callback(base::Bind(&SqlLiteStorage::OnDatabaseError, this));
384ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
385ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!db_->Open(path_)) {
386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Unable to open DB.";
387ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    db_.reset();
388ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
389ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
390ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
391ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!InitDB(db_.get())) {
392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Unable to init DB.";
393ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    db_.reset();
394ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
395ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
396ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
397ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  db_->Preload();
398ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Delete expired identities.
4004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DeleteBetween(base::Time(), base::Time::Now() - validity_period_);
4014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
402ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Slurp all the identities into the out_map.
403ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  sql::Statement stmt(db_->GetUniqueStatement(
404ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "SELECT origin, identity_name, common_name, "
405ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "certificate, private_key, creation_time "
406ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "FROM webrtc_identity_store"));
407ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  CHECK(stmt.is_valid());
408ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
409ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  while (stmt.Step()) {
410ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    IdentityKey key(GURL(stmt.ColumnString(0)), stmt.ColumnString(1));
411ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    std::string common_name(stmt.ColumnString(2));
412ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    std::string cert, private_key;
413ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    stmt.ColumnBlobAsString(3, &cert);
414ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    stmt.ColumnBlobAsString(4, &private_key);
415ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int64 creation_time = stmt.ColumnInt64(5);
416ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    std::pair<IdentityMap::iterator, bool> result =
417ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        out_map->insert(std::pair<IdentityKey, Identity>(
418ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            key, Identity(common_name, cert, private_key, creation_time)));
419ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DCHECK(result.second);
420ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
421ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
422ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
423ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::Close() {
424ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
425ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Commit();
426ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  db_.reset();
427ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
428ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
429ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::AddIdentity(
430ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const GURL& origin,
431ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& identity_name,
432ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Identity& identity) {
433ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
434ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!db_.get())
435ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
436ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
437ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Do not add for session only origins.
438ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (special_storage_policy_.get() &&
439ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      !special_storage_policy_->IsStorageProtected(origin) &&
440ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      special_storage_policy_->IsStorageSessionOnly(origin)) {
441ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
442ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
443ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BatchOperation(ADD_IDENTITY, origin, identity_name, identity);
444ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
445ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
446ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteIdentity(
447ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const GURL& origin,
448ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& identity_name,
449ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Identity& identity) {
450ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
451ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!db_.get())
452ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
453ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BatchOperation(DELETE_IDENTITY, origin, identity_name, identity);
454ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
455ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteBetween(
4574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::Time delete_begin,
4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::Time delete_end) {
4594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
4604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!db_.get())
4614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
4624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Commit pending operations first.
4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Commit();
4654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  sql::Statement del_stmt(db_->GetCachedStatement(
4674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      SQL_FROM_HERE,
4684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      "DELETE FROM webrtc_identity_store"
4694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      " WHERE creation_time >= ? AND creation_time <= ?"));
4704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CHECK(del_stmt.is_valid());
4714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  del_stmt.BindInt64(0, delete_begin.ToInternalValue());
4734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  del_stmt.BindInt64(1, delete_end.ToInternalValue());
4744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  sql::Transaction transaction(db_.get());
4764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!transaction.Begin()) {
477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Failed to begin the transaction.";
478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
479cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!del_stmt.Run()) {
482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Failed to run the delete statement.";
4834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
4844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!transaction.Commit())
487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Failed to commit the transaction.";
4884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
490ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::OnDatabaseError(
491ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int error,
492ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    sql::Statement* stmt) {
493ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
494cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
495ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  db_->RazeAndClose();
496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // It's not safe to reset |db_| here.
497ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
498ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
499ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::BatchOperation(
500ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    OperationType type,
501ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const GURL& origin,
502ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& identity_name,
503ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Identity& identity) {
504ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
505ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Commit every 30 seconds.
506ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  static const base::TimeDelta kCommitInterval(
507ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::TimeDelta::FromSeconds(30));
508ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Commit right away if we have more than 512 outstanding operations.
509ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  static const size_t kCommitAfterBatchSize = 512;
510ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
511ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // We do a full copy of the cert here, and hopefully just here.
512ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  scoped_ptr<PendingOperation> operation(
513ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      new PendingOperation(type, origin, identity_name, identity));
514ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
515ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  pending_operations_.push_back(operation.release());
516ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
517ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (pending_operations_.size() == 1) {
518ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // We've gotten our first entry for this batch, fire off the timer.
519ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    BrowserThread::PostDelayedTask(BrowserThread::DB,
520ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                   FROM_HERE,
521ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                   base::Bind(&SqlLiteStorage::Commit, this),
522ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                   kCommitInterval);
523ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  } else if (pending_operations_.size() >= kCommitAfterBatchSize) {
524ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // We've reached a big enough batch, fire off a commit now.
525ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    BrowserThread::PostTask(BrowserThread::DB,
526ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                            FROM_HERE,
527ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                            base::Bind(&SqlLiteStorage::Commit, this));
528ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
529ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
530ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
531ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::Commit() {
532ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
533ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Maybe an old timer fired or we are already Close()'ed.
534ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!db_.get() || pending_operations_.empty())
535ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
536ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
537ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  sql::Statement add_stmt(db_->GetCachedStatement(
538ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      SQL_FROM_HERE,
539ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "INSERT INTO webrtc_identity_store "
540ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "(origin, identity_name, common_name, certificate,"
541ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      " private_key, creation_time) VALUES"
542ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      " (?,?,?,?,?,?)"));
543ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
544ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  CHECK(add_stmt.is_valid());
545ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
546ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  sql::Statement del_stmt(db_->GetCachedStatement(
547ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      SQL_FROM_HERE,
548ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "DELETE FROM webrtc_identity_store WHERE origin=? AND identity_name=?"));
549ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
550ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  CHECK(del_stmt.is_valid());
551ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
552ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  sql::Transaction transaction(db_.get());
553ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!transaction.Begin()) {
554cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Failed to begin the transaction.";
555ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
556ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
557ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
558cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Swaps |pending_operations_| into a temporary list to make sure
559cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // |pending_operations_| is always cleared in case of DB errors.
560cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PendingOperationList pending_operations_copy;
561cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  pending_operations_.swap(pending_operations_copy);
562cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
563cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (PendingOperationList::const_iterator it =
564cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)           pending_operations_copy.begin();
565cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       it != pending_operations_copy.end();
566ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       ++it) {
567cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    switch ((*it)->type) {
568ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      case ADD_IDENTITY: {
569ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        add_stmt.Reset(true);
570cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        add_stmt.BindString(0, (*it)->origin.spec());
571cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        add_stmt.BindString(1, (*it)->identity_name);
572cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        add_stmt.BindString(2, (*it)->identity.common_name);
573cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        const std::string& cert = (*it)->identity.certificate;
574ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        add_stmt.BindBlob(3, cert.data(), cert.size());
575cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        const std::string& private_key = (*it)->identity.private_key;
576ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        add_stmt.BindBlob(4, private_key.data(), private_key.size());
577cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        add_stmt.BindInt64(5, (*it)->identity.creation_time);
578cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (!add_stmt.Run()) {
579cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          DVLOG(2) << "Failed to add the identity to DB.";
580cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          return;
581cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
582ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        break;
583ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
584ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      case DELETE_IDENTITY:
585ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        del_stmt.Reset(true);
586cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        del_stmt.BindString(0, (*it)->origin.spec());
587cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        del_stmt.BindString(1, (*it)->identity_name);
588cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (!del_stmt.Run()) {
589cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          DVLOG(2) << "Failed to delete the identity from DB.";
590cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          return;
591cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
592ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        break;
593ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
594ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      default:
595ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        NOTREACHED();
596ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        break;
597ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
598ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
599cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
600cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!transaction.Commit())
601cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Failed to commit the transaction.";
602ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
603ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
604ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace content
605