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/file_util.h"
8ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/files/file_path.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"
16ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "url/gurl.h"
17ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "webkit/browser/quota/special_storage_policy.h"
18ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
19ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace content {
20ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
21ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstatic 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,
115ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 quota::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_;
172ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  scoped_refptr<quota::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,
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    quota::SpecialStoragePolicy* policy,
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::TimeDelta validity_period)
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : validity_period_(validity_period),
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      state_(NOT_STARTED),
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      sql_lite_storage_(new SqlLiteStorage(validity_period, path, policy)) {}
187ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool WebRTCIdentityStoreBackend::FindIdentity(
189ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const GURL& origin,
190ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& identity_name,
191ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& common_name,
192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const FindIdentityCallback& callback) {
193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
194ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (state_ == CLOSED)
195ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return false;
196ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (state_ != LOADED) {
198ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Queues the request to wait for the DB to load.
199ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    pending_find_requests_.push_back(
200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        new PendingFindRequest(origin, identity_name, common_name, callback));
201ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (state_ == LOADING)
202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return true;
203ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
204ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DCHECK_EQ(state_, NOT_STARTED);
205ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
206ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Kick off loading the DB.
207ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    scoped_ptr<IdentityMap> out_map(new IdentityMap());
2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::Closure task(
2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        base::Bind(&SqlLiteStorage::Load, sql_lite_storage_, out_map.get()));
2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // |out_map| will be NULL after this call.
211ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (BrowserThread::PostTaskAndReply(
212ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            BrowserThread::DB,
213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            FROM_HERE,
2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            task,
215ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            base::Bind(&WebRTCIdentityStoreBackend::OnLoaded,
216ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       this,
217ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       base::Passed(&out_map)))) {
218ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      state_ = LOADING;
219ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return true;
220ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
221ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // If it fails to post task, falls back to ERR_FILE_NOT_FOUND.
222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
223ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
224ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IdentityKey key(origin, identity_name);
225ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IdentityMap::iterator iter = identities_.find(key);
226ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (iter != identities_.end() && iter->second.common_name == common_name) {
2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::TimeDelta age = base::Time::Now() - base::Time::FromInternalValue(
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                                  iter->second.creation_time);
2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (age < validity_period_) {
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Identity found.
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return BrowserThread::PostTask(BrowserThread::IO,
2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                     FROM_HERE,
2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                     base::Bind(callback,
2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                                net::OK,
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                                iter->second.certificate,
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                                iter->second.private_key));
2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Removes the expired identity from the in-memory cache. The copy in the
2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // database will be removed on the next load.
2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    identities_.erase(iter);
241ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
242ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
243ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return BrowserThread::PostTask(
244ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      BrowserThread::IO,
245ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FROM_HERE,
246ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(callback, net::ERR_FILE_NOT_FOUND, "", ""));
247ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
248ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
249ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::AddIdentity(const GURL& origin,
250ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             const std::string& identity_name,
251ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             const std::string& common_name,
252ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             const std::string& certificate,
253ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             const std::string& private_key) {
254ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
255ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (state_ == CLOSED)
256ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
257ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
258ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // If there is an existing identity for the same origin and identity_name,
259ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // delete it.
260ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IdentityKey key(origin, identity_name);
261ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Identity identity(common_name, certificate, private_key);
262ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
263ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (identities_.find(key) != identities_.end()) {
264ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!BrowserThread::PostTask(BrowserThread::DB,
265ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                 FROM_HERE,
266ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                 base::Bind(&SqlLiteStorage::DeleteIdentity,
267ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            sql_lite_storage_,
268ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            origin,
269ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            identity_name,
270ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            identities_.find(key)->second)))
271ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return;
272ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
273ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  identities_.insert(std::pair<IdentityKey, Identity>(key, identity));
274ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
275ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BrowserThread::PostTask(BrowserThread::DB,
276ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                          FROM_HERE,
277ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                          base::Bind(&SqlLiteStorage::AddIdentity,
278ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                     sql_lite_storage_,
279ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                     origin,
280ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                     identity_name,
281ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                     identity));
282ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
283ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
284ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::Close() {
285ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
286ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    BrowserThread::PostTask(
287ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        BrowserThread::IO,
288ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        FROM_HERE,
289ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        base::Bind(&WebRTCIdentityStoreBackend::Close, this));
290ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
291ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
292ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
293ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (state_ == CLOSED)
294ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
295ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
296ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_ = CLOSED;
297ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BrowserThread::PostTask(
298ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      BrowserThread::DB,
299ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FROM_HERE,
300ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&SqlLiteStorage::Close, sql_lite_storage_));
301ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
302ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
303ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::DeleteBetween(base::Time delete_begin,
304ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                               base::Time delete_end,
305ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                               const base::Closure& callback) {
306ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (state_ == CLOSED)
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
310ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Delete the in-memory cache.
311ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IdentityMap::iterator it = identities_.begin();
312ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  while (it != identities_.end()) {
313ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (it->second.creation_time >= delete_begin.ToInternalValue() &&
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        it->second.creation_time <= delete_end.ToInternalValue()) {
315ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      identities_.erase(it++);
3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    } else {
3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ++it;
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
319ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
320ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BrowserThread::PostTaskAndReply(BrowserThread::DB,
321ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                  FROM_HERE,
322ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                  base::Bind(&SqlLiteStorage::DeleteBetween,
323ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             sql_lite_storage_,
324ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             delete_begin,
3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                             delete_end),
326ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                  callback);
327ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
328ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRTCIdentityStoreBackend::SetValidityPeriodForTesting(
3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::TimeDelta validity_period) {
3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  validity_period_ = validity_period;
3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrowserThread::PostTask(
3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      BrowserThread::DB,
3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      FROM_HERE,
3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(&SqlLiteStorage::SetValidityPeriodForTesting,
3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 sql_lite_storage_,
3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 validity_period));
3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
341ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochWebRTCIdentityStoreBackend::~WebRTCIdentityStoreBackend() {}
342ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
343ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::OnLoaded(scoped_ptr<IdentityMap> out_map) {
344ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (state_ != LOADING)
3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DVLOG(3) << "WebRTC identity store has loaded.";
3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
351ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_ = LOADED;
352ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  identities_.swap(*out_map);
353ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
354ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (size_t i = 0; i < pending_find_requests_.size(); ++i) {
355ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    FindIdentity(pending_find_requests_[i]->origin,
356ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 pending_find_requests_[i]->identity_name,
357ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 pending_find_requests_[i]->common_name,
358ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 pending_find_requests_[i]->callback);
359ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    delete pending_find_requests_[i];
360ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
361ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  pending_find_requests_.clear();
362ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
363ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
364ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//
365ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Implementation of SqlLiteStorage.
366ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//
367ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
368ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::Load(IdentityMap* out_map) {
369ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
370ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(!db_.get());
371ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
372ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Ensure the parent directory for storing certs is created before reading
373ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // from it.
374ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const base::FilePath dir = path_.DirName();
375a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!base::PathExists(dir) && !base::CreateDirectory(dir)) {
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Unable to open DB file path.";
377ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
378ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
379ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
380ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  db_.reset(new sql::Connection());
381ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
382ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  db_->set_error_callback(base::Bind(&SqlLiteStorage::OnDatabaseError, this));
383ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
384ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!db_->Open(path_)) {
385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Unable to open DB.";
386ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    db_.reset();
387ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
388ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
389ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
390ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!InitDB(db_.get())) {
391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Unable to init DB.";
392ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    db_.reset();
393ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
394ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
395ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
396ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  db_->Preload();
397ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Delete expired identities.
3994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DeleteBetween(base::Time(), base::Time::Now() - validity_period_);
4004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
401ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Slurp all the identities into the out_map.
402ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  sql::Statement stmt(db_->GetUniqueStatement(
403ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "SELECT origin, identity_name, common_name, "
404ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "certificate, private_key, creation_time "
405ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "FROM webrtc_identity_store"));
406ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  CHECK(stmt.is_valid());
407ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
408ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  while (stmt.Step()) {
409ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    IdentityKey key(GURL(stmt.ColumnString(0)), stmt.ColumnString(1));
410ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    std::string common_name(stmt.ColumnString(2));
411ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    std::string cert, private_key;
412ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    stmt.ColumnBlobAsString(3, &cert);
413ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    stmt.ColumnBlobAsString(4, &private_key);
414ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int64 creation_time = stmt.ColumnInt64(5);
415ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    std::pair<IdentityMap::iterator, bool> result =
416ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        out_map->insert(std::pair<IdentityKey, Identity>(
417ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            key, Identity(common_name, cert, private_key, creation_time)));
418ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DCHECK(result.second);
419ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
420ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
421ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
422ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::Close() {
423ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
424ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Commit();
425ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  db_.reset();
426ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
427ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
428ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::AddIdentity(
429ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const GURL& origin,
430ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& identity_name,
431ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Identity& identity) {
432ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
433ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!db_.get())
434ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
435ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
436ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Do not add for session only origins.
437ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (special_storage_policy_.get() &&
438ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      !special_storage_policy_->IsStorageProtected(origin) &&
439ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      special_storage_policy_->IsStorageSessionOnly(origin)) {
440ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
441ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
442ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BatchOperation(ADD_IDENTITY, origin, identity_name, identity);
443ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
444ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
445ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteIdentity(
446ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const GURL& origin,
447ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& identity_name,
448ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Identity& identity) {
449ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
450ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!db_.get())
451ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
452ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BatchOperation(DELETE_IDENTITY, origin, identity_name, identity);
453ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
454ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteBetween(
4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::Time delete_begin,
4574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::Time delete_end) {
4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
4594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!db_.get())
4604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
4614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Commit pending operations first.
4634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Commit();
4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  sql::Statement del_stmt(db_->GetCachedStatement(
4664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      SQL_FROM_HERE,
4674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      "DELETE FROM webrtc_identity_store"
4684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      " WHERE creation_time >= ? AND creation_time <= ?"));
4694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CHECK(del_stmt.is_valid());
4704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  del_stmt.BindInt64(0, delete_begin.ToInternalValue());
4724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  del_stmt.BindInt64(1, delete_end.ToInternalValue());
4734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  sql::Transaction transaction(db_.get());
4754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!transaction.Begin()) {
476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Failed to begin the transaction.";
477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
479cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!del_stmt.Run()) {
481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Failed to run the delete statement.";
4824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
4834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!transaction.Commit())
486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Failed to commit the transaction.";
4874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
489ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::OnDatabaseError(
490ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int error,
491ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    sql::Statement* stmt) {
492ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
494ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  db_->RazeAndClose();
495cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // It's not safe to reset |db_| here.
496ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
497ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
498ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::BatchOperation(
499ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    OperationType type,
500ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const GURL& origin,
501ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& identity_name,
502ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Identity& identity) {
503ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
504ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Commit every 30 seconds.
505ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  static const base::TimeDelta kCommitInterval(
506ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::TimeDelta::FromSeconds(30));
507ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Commit right away if we have more than 512 outstanding operations.
508ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  static const size_t kCommitAfterBatchSize = 512;
509ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
510ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // We do a full copy of the cert here, and hopefully just here.
511ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  scoped_ptr<PendingOperation> operation(
512ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      new PendingOperation(type, origin, identity_name, identity));
513ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
514ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  pending_operations_.push_back(operation.release());
515ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
516ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (pending_operations_.size() == 1) {
517ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // We've gotten our first entry for this batch, fire off the timer.
518ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    BrowserThread::PostDelayedTask(BrowserThread::DB,
519ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                   FROM_HERE,
520ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                   base::Bind(&SqlLiteStorage::Commit, this),
521ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                   kCommitInterval);
522ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  } else if (pending_operations_.size() >= kCommitAfterBatchSize) {
523ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // We've reached a big enough batch, fire off a commit now.
524ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    BrowserThread::PostTask(BrowserThread::DB,
525ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                            FROM_HERE,
526ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                            base::Bind(&SqlLiteStorage::Commit, this));
527ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
528ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
529ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
530ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::Commit() {
531ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
532ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Maybe an old timer fired or we are already Close()'ed.
533ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!db_.get() || pending_operations_.empty())
534ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
535ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
536ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  sql::Statement add_stmt(db_->GetCachedStatement(
537ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      SQL_FROM_HERE,
538ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "INSERT INTO webrtc_identity_store "
539ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "(origin, identity_name, common_name, certificate,"
540ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      " private_key, creation_time) VALUES"
541ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      " (?,?,?,?,?,?)"));
542ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
543ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  CHECK(add_stmt.is_valid());
544ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
545ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  sql::Statement del_stmt(db_->GetCachedStatement(
546ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      SQL_FROM_HERE,
547ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "DELETE FROM webrtc_identity_store WHERE origin=? AND identity_name=?"));
548ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
549ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  CHECK(del_stmt.is_valid());
550ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
551ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  sql::Transaction transaction(db_.get());
552ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!transaction.Begin()) {
553cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Failed to begin the transaction.";
554ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
555ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
556ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
557cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Swaps |pending_operations_| into a temporary list to make sure
558cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // |pending_operations_| is always cleared in case of DB errors.
559cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PendingOperationList pending_operations_copy;
560cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  pending_operations_.swap(pending_operations_copy);
561cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
562cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (PendingOperationList::const_iterator it =
563cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)           pending_operations_copy.begin();
564cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       it != pending_operations_copy.end();
565ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       ++it) {
566cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    switch ((*it)->type) {
567ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      case ADD_IDENTITY: {
568ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        add_stmt.Reset(true);
569cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        add_stmt.BindString(0, (*it)->origin.spec());
570cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        add_stmt.BindString(1, (*it)->identity_name);
571cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        add_stmt.BindString(2, (*it)->identity.common_name);
572cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        const std::string& cert = (*it)->identity.certificate;
573ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        add_stmt.BindBlob(3, cert.data(), cert.size());
574cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        const std::string& private_key = (*it)->identity.private_key;
575ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        add_stmt.BindBlob(4, private_key.data(), private_key.size());
576cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        add_stmt.BindInt64(5, (*it)->identity.creation_time);
577cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (!add_stmt.Run()) {
578cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          DVLOG(2) << "Failed to add the identity to DB.";
579cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          return;
580cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
581ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        break;
582ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
583ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      case DELETE_IDENTITY:
584ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        del_stmt.Reset(true);
585cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        del_stmt.BindString(0, (*it)->origin.spec());
586cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        del_stmt.BindString(1, (*it)->identity_name);
587cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (!del_stmt.Run()) {
588cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          DVLOG(2) << "Failed to delete the identity from DB.";
589cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          return;
590cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
591ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        break;
592ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
593ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      default:
594ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        NOTREACHED();
595ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        break;
596ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
597ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
598cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
599cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!transaction.Commit())
600cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "Failed to commit the transaction.";
601ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
602ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
603ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace content
604