1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file.
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/browser/media/webrtc_identity_store.h"
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
7ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include <map>
8ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/bind.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/callback_helpers.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/logging.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/rand_util.h"
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/threading/worker_pool.h"
14ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "content/browser/media/webrtc_identity_store_backend.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/browser/browser_thread.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "crypto/rsa_private_key.h"
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/base/net_errors.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/cert/x509_util.h"
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace content {
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstruct WebRTCIdentityRequestResult {
24ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  WebRTCIdentityRequestResult(int error,
25ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                              const std::string& certificate,
26ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                              const std::string& private_key)
27ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      : error(error), certificate(certificate), private_key(private_key) {}
28ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int error;
30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string certificate;
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string private_key;
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Generates a new identity using |common_name| which expires after
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// |validity_period| and returns the result in |result|.
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic void GenerateIdentityWorker(const std::string& common_name,
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                   base::TimeDelta validity_period,
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   WebRTCIdentityRequestResult* result) {
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  result->error = net::OK;
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int serial_number = base::RandInt(0, std::numeric_limits<int>::max());
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  scoped_ptr<crypto::RSAPrivateKey> key;
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::Time now = base::Time::Now();
440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  bool success = net::x509_util::CreateKeyAndSelfSignedCert(
450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      "CN=" + common_name,
460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      serial_number,
470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      now,
480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      now + validity_period,
490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      &key,
500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      &result->certificate);
510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!success) {
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DLOG(ERROR) << "Unable to create x509 cert for client";
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    result->error = net::ERR_SELF_SIGNED_CERT_GENERATION_FAILED;
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<uint8> private_key_info;
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!key->ExportPrivateKey(&private_key_info)) {
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DLOG(ERROR) << "Unable to export private key";
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    result->error = net::ERR_PRIVATE_KEY_EXPORT_FAILED;
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  result->private_key =
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      std::string(private_key_info.begin(), private_key_info.end());
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochclass WebRTCIdentityRequestHandle;
70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The class represents an identity request internal to WebRTCIdentityStore.
72ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// It has a one-to-many mapping to the external version of the request,
73ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// WebRTCIdentityRequestHandle, i.e. multiple identical external requests are
74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// combined into one internal request.
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// It's deleted automatically when the request is completed.
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass WebRTCIdentityRequest {
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  WebRTCIdentityRequest(const GURL& origin,
79ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                        const std::string& identity_name,
80ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                        const std::string& common_name)
81ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      : origin_(origin),
82ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        identity_name_(identity_name),
83ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        common_name_(common_name) {}
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
85ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void Cancel(WebRTCIdentityRequestHandle* handle) {
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
87ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (callbacks_.find(handle) == callbacks_.end())
88ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return;
89ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    callbacks_.erase(handle);
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  friend class WebRTCIdentityStore;
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
95ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void AddCallback(WebRTCIdentityRequestHandle* handle,
96ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   const WebRTCIdentityStore::CompletionCallback& callback) {
97ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DCHECK(callbacks_.find(handle) == callbacks_.end());
98ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    callbacks_[handle] = callback;
99ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
101ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // This method deletes "this" and no one should access it after the request
102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // completes.
103ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // We do not use base::Owned to tie its lifetime to the callback for
104ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // WebRTCIdentityStoreBackend::FindIdentity, because it needs to live longer
105ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // than that if the identity does not exist in DB.
106ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void Post(const WebRTCIdentityRequestResult& result) {
107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
108ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    for (CallbackMap::iterator it = callbacks_.begin(); it != callbacks_.end();
109ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch         ++it)
110ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      it->second.Run(result.error, result.certificate, result.private_key);
111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    delete this;
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
114ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GURL origin_;
115ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string identity_name_;
116ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string common_name_;
117ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  typedef std::map<WebRTCIdentityRequestHandle*,
118ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   WebRTCIdentityStore::CompletionCallback> CallbackMap;
119ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  CallbackMap callbacks_;
120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The class represents an identity request which calls back to the external
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// client when the request completes.
124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Its lifetime is tied with the Callback held by the corresponding
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// WebRTCIdentityRequest.
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass WebRTCIdentityRequestHandle {
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  WebRTCIdentityRequestHandle(
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      WebRTCIdentityStore* store,
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      const WebRTCIdentityStore::CompletionCallback& callback)
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : store_(store), request_(NULL), callback_(callback) {}
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  friend class WebRTCIdentityStore;
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Cancel the request.  Does nothing if the request finished or was already
137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // cancelled.
138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void Cancel() {
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!request_)
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return;
142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    callback_.Reset();
144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    WebRTCIdentityRequest* request = request_;
145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    request_ = NULL;
146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // "this" will be deleted after the following call, because "this" is
147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // owned by the Callback held by |request|.
148ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    request->Cancel(this);
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void OnRequestStarted(WebRTCIdentityRequest* request) {
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DCHECK(request);
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    request_ = request;
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void OnRequestComplete(int error,
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         const std::string& certificate,
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         const std::string& private_key) {
160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DCHECK(request_);
162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    request_ = NULL;
163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::ResetAndReturn(&callback_).Run(error, certificate, private_key);
164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  WebRTCIdentityStore* store_;
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  WebRTCIdentityRequest* request_;
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  WebRTCIdentityStore::CompletionCallback callback_;
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DISALLOW_COPY_AND_ASSIGN(WebRTCIdentityRequestHandle);
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
173ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochWebRTCIdentityStore::WebRTCIdentityStore(const base::FilePath& path,
17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                         storage::SpecialStoragePolicy* policy)
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : validity_period_(base::TimeDelta::FromDays(30)),
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      task_runner_(base::WorkerPool::GetTaskRunner(true)),
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      backend_(new WebRTCIdentityStoreBackend(path, policy, validity_period_)) {
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
180ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochWebRTCIdentityStore::~WebRTCIdentityStore() { backend_->Close(); }
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbase::Closure WebRTCIdentityStore::RequestIdentity(
183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const GURL& origin,
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& identity_name,
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& common_name,
186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const CompletionCallback& callback) {
187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  WebRTCIdentityRequest* request =
189ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FindRequest(origin, identity_name, common_name);
190ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // If there is no identical request in flight, create a new one, queue it,
191ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // and make the backend request.
192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!request) {
193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    request = new WebRTCIdentityRequest(origin, identity_name, common_name);
194c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch    // |request| will delete itself after the result is posted.
195ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!backend_->FindIdentity(
196ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            origin,
197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            identity_name,
198ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            common_name,
199ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            base::Bind(
200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                &WebRTCIdentityStore::BackendFindCallback, this, request))) {
201c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      // Bail out if the backend failed to start the task.
202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      delete request;
203ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return base::Closure();
204ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
205ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    in_flight_requests_.push_back(request);
206ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
207ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
208c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  WebRTCIdentityRequestHandle* handle =
209c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch    new WebRTCIdentityRequestHandle(this, callback);
210c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch
211ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  request->AddCallback(
212ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      handle,
213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&WebRTCIdentityRequestHandle::OnRequestComplete,
214ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 base::Owned(handle)));
215ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  handle->OnRequestStarted(request);
216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return base::Bind(&WebRTCIdentityRequestHandle::Cancel,
217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    base::Unretained(handle));
218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
220ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStore::DeleteBetween(base::Time delete_begin,
221ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                        base::Time delete_end,
222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                        const base::Closure& callback) {
223ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
224ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  backend_->DeleteBetween(delete_begin, delete_end, callback);
225ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
226ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebRTCIdentityStore::SetValidityPeriodForTesting(
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::TimeDelta validity_period) {
2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  validity_period_ = validity_period;
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  backend_->SetValidityPeriodForTesting(validity_period);
2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid WebRTCIdentityStore::SetTaskRunnerForTesting(
235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const scoped_refptr<base::TaskRunner>& task_runner) {
236ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  task_runner_ = task_runner;
238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
240ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStore::BackendFindCallback(WebRTCIdentityRequest* request,
241ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                              int error,
242ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                              const std::string& certificate,
243ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                              const std::string& private_key) {
244ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
245ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (error == net::OK) {
246ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DVLOG(2) << "Identity found in DB.";
247ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    WebRTCIdentityRequestResult result(error, certificate, private_key);
248ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    PostRequestResult(request, result);
249ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
250ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
251ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Generate a new identity if not found in the DB.
252ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  WebRTCIdentityRequestResult* result =
253ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      new WebRTCIdentityRequestResult(0, "", "");
254ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!task_runner_->PostTaskAndReply(
2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)           FROM_HERE,
2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)           base::Bind(&GenerateIdentityWorker,
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                      request->common_name_,
2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                      validity_period_,
2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                      result),
2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)           base::Bind(&WebRTCIdentityStore::GenerateIdentityCallback,
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                      this,
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                      request,
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                      base::Owned(result)))) {
264ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Completes the request with error if failed to post the task.
265ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    WebRTCIdentityRequestResult result(net::ERR_UNEXPECTED, "", "");
266ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    PostRequestResult(request, result);
267ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
268ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
269ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
270ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStore::GenerateIdentityCallback(
271ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    WebRTCIdentityRequest* request,
272ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    WebRTCIdentityRequestResult* result) {
273ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
274ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (result->error == net::OK) {
275ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DVLOG(2) << "New identity generated and added to the backend.";
276ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    backend_->AddIdentity(request->origin_,
277ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                          request->identity_name_,
278ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                          request->common_name_,
279ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                          result->certificate,
280ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                          result->private_key);
281ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
282ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  PostRequestResult(request, *result);
283ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
284ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
285ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid WebRTCIdentityStore::PostRequestResult(
286ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    WebRTCIdentityRequest* request,
287ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const WebRTCIdentityRequestResult& result) {
288ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
289ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Removes the in flight request from the queue.
290ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (size_t i = 0; i < in_flight_requests_.size(); ++i) {
291ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (in_flight_requests_[i] == request) {
292ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      in_flight_requests_.erase(in_flight_requests_.begin() + i);
293ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      break;
294ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
295ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
296ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // |request| will be deleted after this call.
297ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  request->Post(result);
298ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
299ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
300ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Find an identical request from the in flight requests.
301ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochWebRTCIdentityRequest* WebRTCIdentityStore::FindRequest(
302ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const GURL& origin,
303ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& identity_name,
304ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& common_name) {
305ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (size_t i = 0; i < in_flight_requests_.size(); ++i) {
306ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (in_flight_requests_[i]->origin_ == origin &&
307ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        in_flight_requests_[i]->identity_name_ == identity_name &&
308ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        in_flight_requests_[i]->common_name_ == common_name) {
309ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return in_flight_requests_[i];
310ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
311ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
312ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return NULL;
313ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
314ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace content
316