webrtc_identity_store_backend.cc revision 3551c9c881056c480085172ff9840cab31610854
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"
9ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "content/public/browser/browser_thread.h"
10ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "net/base/net_errors.h"
11ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "sql/error_delegate_util.h"
12ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "sql/statement.h"
13ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "sql/transaction.h"
14ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "url/gurl.h"
15ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "webkit/browser/quota/special_storage_policy.h"
16ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
17ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace content {
18ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
19ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstatic const char* kWebRTCIdentityStoreDBName = "webrtc_identity_store";
20ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
21ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstatic const base::FilePath::CharType kWebRTCIdentityStoreDirectory[] =
22ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    FILE_PATH_LITERAL("WebRTCIdentityStore");
23ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
24ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Initializes the identity table, returning true on success.
25ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstatic bool InitDB(sql::Connection* db) {
26ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (db->DoesTableExist(kWebRTCIdentityStoreDBName)) {
27ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (db->DoesColumnExist(kWebRTCIdentityStoreDBName, "origin") &&
28ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        db->DoesColumnExist(kWebRTCIdentityStoreDBName, "identity_name") &&
29ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        db->DoesColumnExist(kWebRTCIdentityStoreDBName, "common_name") &&
30ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        db->DoesColumnExist(kWebRTCIdentityStoreDBName, "certificate") &&
31ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        db->DoesColumnExist(kWebRTCIdentityStoreDBName, "private_key") &&
32ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        db->DoesColumnExist(kWebRTCIdentityStoreDBName, "creation_time"))
33ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return true;
34ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!db->Execute("DROP TABLE webrtc_identity_store"))
35ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return false;
36ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
37ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
38ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return db->Execute(
39ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "CREATE TABLE webrtc_identity_store"
40ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      " ("
41ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "origin TEXT NOT NULL,"
42ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "identity_name TEXT NOT NULL,"
43ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "common_name TEXT NOT NULL,"
44ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "certificate BLOB NOT NULL,"
45ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "private_key BLOB NOT NULL,"
46ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "creation_time INTEGER)");
47ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
48ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
49ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstruct WebRTCIdentityStoreBackend::IdentityKey {
50ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IdentityKey(const GURL& origin, const std::string& identity_name)
51ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      : origin(origin), identity_name(identity_name) {}
52ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
53ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool operator<(const IdentityKey& other) const {
54ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return origin < other.origin ||
55ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           (origin == other.origin && identity_name < other.identity_name);
56ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GURL origin;
59ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string identity_name;
60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
62ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstruct WebRTCIdentityStoreBackend::Identity {
63ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Identity(const std::string& common_name,
64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           const std::string& certificate,
65ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           const std::string& private_key)
66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      : common_name(common_name),
67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        certificate(certificate),
68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        private_key(private_key),
69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        creation_time(base::Time::Now().ToInternalValue()) {}
70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
71ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Identity(const std::string& common_name,
72ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           const std::string& certificate,
73ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           const std::string& private_key,
74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           int64 creation_time)
75ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      : common_name(common_name),
76ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        certificate(certificate),
77ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        private_key(private_key),
78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        creation_time(creation_time) {}
79ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
80ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string common_name;
81ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string certificate;
82ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string private_key;
83ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  int64 creation_time;
84ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
85ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
86ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstruct WebRTCIdentityStoreBackend::PendingFindRequest {
87ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  PendingFindRequest(const GURL& origin,
88ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     const std::string& identity_name,
89ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     const std::string& common_name,
90ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     const FindIdentityCallback& callback)
91ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      : origin(origin),
92ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        identity_name(identity_name),
93ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        common_name(common_name),
94ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        callback(callback) {}
95ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
96ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  ~PendingFindRequest() {}
97ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
98ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GURL origin;
99ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string identity_name;
100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string common_name;
101ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  FindIdentityCallback callback;
102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
103ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
104ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// The class encapsulates the database operations. All members except ctor and
105ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// dtor should be accessed on the DB thread.
106ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// It can be created/destroyed on any thread.
107ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochclass WebRTCIdentityStoreBackend::SqlLiteStorage
108ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : public base::RefCountedThreadSafe<SqlLiteStorage> {
109ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch public:
110ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  SqlLiteStorage(const base::FilePath& path,
111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 quota::SpecialStoragePolicy* policy)
112ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      : special_storage_policy_(policy) {
113ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!path.empty())
114ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      path_ = path.Append(kWebRTCIdentityStoreDirectory);
115ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
116ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
117ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void Load(IdentityMap* out_map);
118ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void Close();
119ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void AddIdentity(const GURL& origin,
120ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   const std::string& identity_name,
121ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   const Identity& identity);
122ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void DeleteIdentity(const GURL& origin,
123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      const std::string& identity_name,
124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      const Identity& identity);
125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void DeleteBetween(base::Time delete_begin,
126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     base::Time delete_end,
127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     const base::Closure& callback);
128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
129ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch private:
130ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  friend class base::RefCountedThreadSafe<SqlLiteStorage>;
131ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
132ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  enum OperationType {
133ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    ADD_IDENTITY,
134ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DELETE_IDENTITY
135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  };
136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  struct PendingOperation {
137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    PendingOperation(OperationType type,
138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     const GURL& origin,
139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     const std::string& identity_name,
140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     const Identity& identity)
141ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        : type(type),
142ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          origin(origin),
143ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          identity_name(identity_name),
144ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          identity(identity) {}
145ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
146ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    OperationType type;
147ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    GURL origin;
148ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    std::string identity_name;
149ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    Identity identity;
150ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  };
151ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  typedef std::vector<PendingOperation*> PendingOperationList;
152ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
153ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  virtual ~SqlLiteStorage() {}
154ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void OnDatabaseError(int error, sql::Statement* stmt);
155ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void BatchOperation(OperationType type,
156ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      const GURL& origin,
157ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      const std::string& identity_name,
158ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      const Identity& identity);
159ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void Commit();
160ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
161ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // The file path of the DB. Empty if temporary.
162ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::FilePath path_;
163ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
164ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  scoped_ptr<sql::Connection> db_;
165ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Batched DB operations pending to commit.
166ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  PendingOperationList pending_operations_;
167ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
168ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(SqlLiteStorage);
169ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
170ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
171ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochWebRTCIdentityStoreBackend::WebRTCIdentityStoreBackend(
172ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const base::FilePath& path,
173ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    quota::SpecialStoragePolicy* policy)
174ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : state_(NOT_STARTED),
175ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      sql_lite_storage_(new SqlLiteStorage(path, policy)) {}
176ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
177ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool WebRTCIdentityStoreBackend::FindIdentity(
178ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const GURL& origin,
179ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& identity_name,
180ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& common_name,
181ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const FindIdentityCallback& callback) {
182ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
183ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (state_ == CLOSED)
184ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return false;
185ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
186ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (state_ != LOADED) {
187ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Queues the request to wait for the DB to load.
188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    pending_find_requests_.push_back(
189ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        new PendingFindRequest(origin, identity_name, common_name, callback));
190ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (state_ == LOADING)
191ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return true;
192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DCHECK_EQ(state_, NOT_STARTED);
194ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
195ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Kick off loading the DB.
196ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    scoped_ptr<IdentityMap> out_map(new IdentityMap());
1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::Closure task(
1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        base::Bind(&SqlLiteStorage::Load, sql_lite_storage_, out_map.get()));
1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // |out_map| will be NULL after this call.
200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (BrowserThread::PostTaskAndReply(
201ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            BrowserThread::DB,
202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            FROM_HERE,
2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            task,
204ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            base::Bind(&WebRTCIdentityStoreBackend::OnLoaded,
205ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       this,
206ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       base::Passed(&out_map)))) {
207ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      state_ = LOADING;
208ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return true;
209ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
210ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // If it fails to post task, falls back to ERR_FILE_NOT_FOUND.
211ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
212ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IdentityKey key(origin, identity_name);
214ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IdentityMap::iterator iter = identities_.find(key);
215ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (iter != identities_.end() && iter->second.common_name == common_name) {
216ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Identity found.
217ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return BrowserThread::PostTask(BrowserThread::IO,
218ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                   FROM_HERE,
219ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                   base::Bind(callback,
220ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                              net::OK,
221ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                              iter->second.certificate,
222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                              iter->second.private_key));
223ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
224ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
225ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return BrowserThread::PostTask(
226ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      BrowserThread::IO,
227ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FROM_HERE,
228ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(callback, net::ERR_FILE_NOT_FOUND, "", ""));
229ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
230ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
231ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::AddIdentity(const GURL& origin,
232ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             const std::string& identity_name,
233ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             const std::string& common_name,
234ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             const std::string& certificate,
235ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             const std::string& private_key) {
236ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
237ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (state_ == CLOSED)
238ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
239ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
240ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // If there is an existing identity for the same origin and identity_name,
241ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // delete it.
242ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IdentityKey key(origin, identity_name);
243ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Identity identity(common_name, certificate, private_key);
244ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
245ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (identities_.find(key) != identities_.end()) {
246ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!BrowserThread::PostTask(BrowserThread::DB,
247ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                 FROM_HERE,
248ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                 base::Bind(&SqlLiteStorage::DeleteIdentity,
249ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            sql_lite_storage_,
250ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            origin,
251ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            identity_name,
252ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            identities_.find(key)->second)))
253ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return;
254ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
255ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  identities_.insert(std::pair<IdentityKey, Identity>(key, identity));
256ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
257ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BrowserThread::PostTask(BrowserThread::DB,
258ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                          FROM_HERE,
259ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                          base::Bind(&SqlLiteStorage::AddIdentity,
260ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                     sql_lite_storage_,
261ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                     origin,
262ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                     identity_name,
263ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                     identity));
264ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
265ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
266ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::Close() {
267ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
268ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    BrowserThread::PostTask(
269ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        BrowserThread::IO,
270ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        FROM_HERE,
271ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        base::Bind(&WebRTCIdentityStoreBackend::Close, this));
272ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
273ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
274ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
275ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (state_ == CLOSED)
276ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
277ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
278ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_ = CLOSED;
279ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BrowserThread::PostTask(
280ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      BrowserThread::DB,
281ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FROM_HERE,
282ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&SqlLiteStorage::Close, sql_lite_storage_));
283ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
284ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
285ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::DeleteBetween(base::Time delete_begin,
286ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                               base::Time delete_end,
287ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                               const base::Closure& callback) {
288ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
289ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Delete the in-memory cache.
290ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IdentityMap::iterator it = identities_.begin();
291ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  while (it != identities_.end()) {
292ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (it->second.creation_time >= delete_begin.ToInternalValue() &&
293ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        it->second.creation_time <= delete_end.ToInternalValue())
294ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      identities_.erase(it++);
295ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    else
296ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      it++;
297ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
298ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
299ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BrowserThread::PostTaskAndReply(BrowserThread::DB,
300ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                  FROM_HERE,
301ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                  base::Bind(&SqlLiteStorage::DeleteBetween,
302ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             sql_lite_storage_,
303ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             delete_begin,
304ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             delete_end,
305ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                             callback),
306ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                  callback);
307ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
308ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
309ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochWebRTCIdentityStoreBackend::~WebRTCIdentityStoreBackend() {}
310ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
311ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::OnLoaded(scoped_ptr<IdentityMap> out_map) {
312ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
313ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_ = LOADED;
314ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  identities_.swap(*out_map);
315ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
316ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (size_t i = 0; i < pending_find_requests_.size(); ++i) {
317ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    FindIdentity(pending_find_requests_[i]->origin,
318ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 pending_find_requests_[i]->identity_name,
319ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 pending_find_requests_[i]->common_name,
320ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 pending_find_requests_[i]->callback);
321ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    delete pending_find_requests_[i];
322ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
323ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  pending_find_requests_.clear();
324ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
325ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
326ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//
327ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Implementation of SqlLiteStorage.
328ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//
329ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
330ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::Load(IdentityMap* out_map) {
331ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
332ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(!db_.get());
333ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
334ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Ensure the parent directory for storing certs is created before reading
335ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // from it.
336ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const base::FilePath dir = path_.DirName();
337ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!base::PathExists(dir) && !file_util::CreateDirectory(dir)) {
338ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DLOG(ERROR) << "Unable to open DB file path.";
339ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
340ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
341ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
342ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  db_.reset(new sql::Connection());
343ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
344ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  db_->set_error_callback(base::Bind(&SqlLiteStorage::OnDatabaseError, this));
345ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
346ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!db_->Open(path_)) {
347ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DLOG(ERROR) << "Unable to open DB.";
348ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    db_.reset();
349ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
350ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
351ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
352ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!InitDB(db_.get())) {
353ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DLOG(ERROR) << "Unable to init DB.";
354ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    db_.reset();
355ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
356ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
357ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
358ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  db_->Preload();
359ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
360ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Slurp all the identities into the out_map.
361ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  sql::Statement stmt(db_->GetUniqueStatement(
362ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "SELECT origin, identity_name, common_name, "
363ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "certificate, private_key, creation_time "
364ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "FROM webrtc_identity_store"));
365ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  CHECK(stmt.is_valid());
366ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
367ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  while (stmt.Step()) {
368ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    IdentityKey key(GURL(stmt.ColumnString(0)), stmt.ColumnString(1));
369ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    std::string common_name(stmt.ColumnString(2));
370ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    std::string cert, private_key;
371ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    stmt.ColumnBlobAsString(3, &cert);
372ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    stmt.ColumnBlobAsString(4, &private_key);
373ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int64 creation_time = stmt.ColumnInt64(5);
374ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    std::pair<IdentityMap::iterator, bool> result =
375ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        out_map->insert(std::pair<IdentityKey, Identity>(
376ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            key, Identity(common_name, cert, private_key, creation_time)));
377ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DCHECK(result.second);
378ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
379ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
380ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
381ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::Close() {
382ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
383ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Commit();
384ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  db_.reset();
385ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
386ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
387ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::AddIdentity(
388ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const GURL& origin,
389ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& identity_name,
390ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Identity& identity) {
391ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
392ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!db_.get())
393ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
394ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
395ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Do not add for session only origins.
396ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (special_storage_policy_.get() &&
397ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      !special_storage_policy_->IsStorageProtected(origin) &&
398ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      special_storage_policy_->IsStorageSessionOnly(origin)) {
399ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
400ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
401ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BatchOperation(ADD_IDENTITY, origin, identity_name, identity);
402ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
403ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
404ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteIdentity(
405ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const GURL& origin,
406ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& identity_name,
407ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Identity& identity) {
408ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
409ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!db_.get())
410ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
411ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BatchOperation(DELETE_IDENTITY, origin, identity_name, identity);
412ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
413ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
414ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::OnDatabaseError(
415ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int error,
416ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    sql::Statement* stmt) {
417ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
418ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!sql::IsErrorCatastrophic(error))
419ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
420ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  db_->RazeAndClose();
421ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
422ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
423ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::BatchOperation(
424ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    OperationType type,
425ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const GURL& origin,
426ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& identity_name,
427ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Identity& identity) {
428ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
429ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Commit every 30 seconds.
430ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  static const base::TimeDelta kCommitInterval(
431ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::TimeDelta::FromSeconds(30));
432ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Commit right away if we have more than 512 outstanding operations.
433ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  static const size_t kCommitAfterBatchSize = 512;
434ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
435ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // We do a full copy of the cert here, and hopefully just here.
436ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  scoped_ptr<PendingOperation> operation(
437ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      new PendingOperation(type, origin, identity_name, identity));
438ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
439ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  pending_operations_.push_back(operation.release());
440ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
441ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (pending_operations_.size() == 1) {
442ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // We've gotten our first entry for this batch, fire off the timer.
443ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    BrowserThread::PostDelayedTask(BrowserThread::DB,
444ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                   FROM_HERE,
445ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                   base::Bind(&SqlLiteStorage::Commit, this),
446ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                   kCommitInterval);
447ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  } else if (pending_operations_.size() >= kCommitAfterBatchSize) {
448ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // We've reached a big enough batch, fire off a commit now.
449ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    BrowserThread::PostTask(BrowserThread::DB,
450ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                            FROM_HERE,
451ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                            base::Bind(&SqlLiteStorage::Commit, this));
452ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
453ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
454ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
455ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::Commit() {
456ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
457ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Maybe an old timer fired or we are already Close()'ed.
458ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!db_.get() || pending_operations_.empty())
459ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
460ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
461ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  sql::Statement add_stmt(db_->GetCachedStatement(
462ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      SQL_FROM_HERE,
463ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "INSERT INTO webrtc_identity_store "
464ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "(origin, identity_name, common_name, certificate,"
465ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      " private_key, creation_time) VALUES"
466ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      " (?,?,?,?,?,?)"));
467ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
468ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  CHECK(add_stmt.is_valid());
469ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
470ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  sql::Statement del_stmt(db_->GetCachedStatement(
471ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      SQL_FROM_HERE,
472ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "DELETE FROM webrtc_identity_store WHERE origin=? AND identity_name=?"));
473ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
474ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  CHECK(del_stmt.is_valid());
475ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
476ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  sql::Transaction transaction(db_.get());
477ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!transaction.Begin()) {
478ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DLOG(ERROR) << "Failed to begin the transaction.";
479ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
480ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
481ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
482ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (PendingOperationList::iterator it = pending_operations_.begin();
483ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       it != pending_operations_.end();
484ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       ++it) {
485ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    scoped_ptr<PendingOperation> po(*it);
486ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    switch (po->type) {
487ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      case ADD_IDENTITY: {
488ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        add_stmt.Reset(true);
489ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        add_stmt.BindString(0, po->origin.spec());
490ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        add_stmt.BindString(1, po->identity_name);
491ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        add_stmt.BindString(2, po->identity.common_name);
492ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        const std::string& cert = po->identity.certificate;
493ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        add_stmt.BindBlob(3, cert.data(), cert.size());
494ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        const std::string& private_key = po->identity.private_key;
495ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        add_stmt.BindBlob(4, private_key.data(), private_key.size());
496ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        add_stmt.BindInt64(5, po->identity.creation_time);
497ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        CHECK(add_stmt.Run());
498ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        break;
499ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
500ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      case DELETE_IDENTITY:
501ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        del_stmt.Reset(true);
502ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        del_stmt.BindString(0, po->origin.spec());
503ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        add_stmt.BindString(1, po->identity_name);
504ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        CHECK(del_stmt.Run());
505ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        break;
506ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
507ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      default:
508ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        NOTREACHED();
509ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        break;
510ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
511ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
512ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  transaction.Commit();
513ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  pending_operations_.clear();
514ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
515ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
516ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteBetween(
517ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    base::Time delete_begin,
518ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    base::Time delete_end,
519ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const base::Closure& callback) {
520ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
521ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!db_.get())
522ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
523ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
524ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Commit pending operations first.
525ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Commit();
526ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
527ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  sql::Statement del_stmt(db_->GetCachedStatement(
528ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      SQL_FROM_HERE,
529ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "DELETE FROM webrtc_identity_store"
530ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      " WHERE creation_time >= ? AND creation_time <= ?"));
531ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  CHECK(del_stmt.is_valid());
532ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
533ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  del_stmt.BindInt64(0, delete_begin.ToInternalValue());
534ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  del_stmt.BindInt64(1, delete_end.ToInternalValue());
535ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
536ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  sql::Transaction transaction(db_.get());
537ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!transaction.Begin()) {
538ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DLOG(ERROR) << "Failed to begin the transaction.";
539ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
540ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
541ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
542ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  CHECK(del_stmt.Run());
543ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  transaction.Commit();
544ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
545ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
546ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace content
547