crypto_module_delegate_nss.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/crypto_module_delegate_nss.h"
6
7#include "base/basictypes.h"
8#include "base/bind.h"
9#include "chrome/browser/net/nss_context.h"
10#include "content/public/browser/browser_thread.h"
11
12using content::BrowserThread;
13
14ChromeNSSCryptoModuleDelegate::ChromeNSSCryptoModuleDelegate(
15    chrome::CryptoModulePasswordReason reason,
16    const net::HostPortPair& server)
17    : reason_(reason),
18      server_(server),
19      event_(false, false),
20      cancelled_(false) {}
21
22ChromeNSSCryptoModuleDelegate::~ChromeNSSCryptoModuleDelegate() {}
23
24bool ChromeNSSCryptoModuleDelegate::InitializeSlot(
25    content::ResourceContext* context,
26    const base::Closure& initialization_complete_callback) {
27  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
28  DCHECK(!slot_);
29  base::Callback<void(crypto::ScopedPK11Slot)> get_slot_callback;
30  if (!initialization_complete_callback.is_null())
31    get_slot_callback = base::Bind(&ChromeNSSCryptoModuleDelegate::DidGetSlot,
32                                   // Caller is responsible for keeping |this|
33                                   // alive until the callback is run.
34                                   base::Unretained(this),
35                                   initialization_complete_callback);
36
37  slot_ = GetPrivateNSSKeySlotForResourceContext(context, get_slot_callback);
38  return slot_.get() != NULL;
39}
40
41// TODO(mattm): allow choosing which slot to generate and store the key.
42crypto::ScopedPK11Slot ChromeNSSCryptoModuleDelegate::RequestSlot() {
43  return slot_.Pass();
44}
45
46std::string ChromeNSSCryptoModuleDelegate::RequestPassword(
47    const std::string& slot_name,
48    bool retry,
49    bool* cancelled) {
50  DCHECK(!event_.IsSignaled());
51  event_.Reset();
52
53  if (BrowserThread::PostTask(
54          BrowserThread::UI,
55          FROM_HERE,
56          base::Bind(&ChromeNSSCryptoModuleDelegate::ShowDialog,
57                     // This method blocks on |event_| until the task completes,
58                     // so there's no need to ref-count.
59                     base::Unretained(this),
60                     slot_name,
61                     retry))) {
62    event_.Wait();
63  }
64  *cancelled = cancelled_;
65  return password_;
66}
67
68void ChromeNSSCryptoModuleDelegate::ShowDialog(const std::string& slot_name,
69                                               bool retry) {
70  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
71  ShowCryptoModulePasswordDialog(
72      slot_name,
73      retry,
74      reason_,
75      server_.host(),
76      NULL,  // TODO(mattm): Supply parent window.
77      base::Bind(&ChromeNSSCryptoModuleDelegate::GotPassword,
78                 // RequestPassword is blocked on |event_| until GotPassword is
79                 // called, so there's no need to ref-count.
80                 base::Unretained(this)));
81}
82
83void ChromeNSSCryptoModuleDelegate::GotPassword(const std::string& password) {
84  if (!password.empty())
85    password_ = password;
86  else
87    cancelled_ = true;
88  event_.Signal();
89}
90
91void ChromeNSSCryptoModuleDelegate::DidGetSlot(const base::Closure& callback,
92                                               crypto::ScopedPK11Slot slot) {
93  DCHECK(!slot_);
94  slot_ = slot.Pass();
95  callback.Run();
96}
97
98crypto::CryptoModuleBlockingPasswordDelegate*
99CreateCryptoModuleBlockingPasswordDelegate(
100    chrome::CryptoModulePasswordReason reason,
101    const net::HostPortPair& server) {
102  // Returns a ChromeNSSCryptoModuleDelegate without calling InitializeSlot.
103  // Since it is only being used as a CreateCryptoModuleBlockingDialogDelegate,
104  // initializing the slot handle is unnecessary.
105  return new ChromeNSSCryptoModuleDelegate(reason, server);
106}
107