Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / ui / crypto_module_password_dialog_nss.cc
blob5569fc43dea8026166f04ef315d3d4e70b5d28f8
1 // Copyright (c) 2011 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.
5 #include "chrome/browser/ui/crypto_module_password_dialog_nss.h"
7 #include <pk11pub.h>
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "net/base/crypto_module.h"
13 #include "net/cert/x509_certificate.h"
15 using content::BrowserThread;
17 namespace {
19 bool ShouldShowDialog(const net::CryptoModule* module) {
20 // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc.
21 return (PK11_NeedLogin(module->os_module_handle()) &&
22 !PK11_IsLoggedIn(module->os_module_handle(), NULL /* wincx */));
25 // Basically an asynchronous implementation of NSS's PK11_DoPassword.
26 // Note: This currently handles only the simple case. See the TODOs in
27 // GotPassword for what is yet unimplemented.
28 class SlotUnlocker {
29 public:
30 SlotUnlocker(const net::CryptoModuleList& modules,
31 chrome::CryptoModulePasswordReason reason,
32 const net::HostPortPair& server,
33 gfx::NativeWindow parent,
34 const base::Closure& callback);
36 void Start();
38 private:
39 void GotPassword(const std::string& password);
40 void Done();
42 size_t current_;
43 net::CryptoModuleList modules_;
44 chrome::CryptoModulePasswordReason reason_;
45 net::HostPortPair server_;
46 gfx::NativeWindow parent_;
47 base::Closure callback_;
48 PRBool retry_;
51 SlotUnlocker::SlotUnlocker(const net::CryptoModuleList& modules,
52 chrome::CryptoModulePasswordReason reason,
53 const net::HostPortPair& server,
54 gfx::NativeWindow parent,
55 const base::Closure& callback)
56 : current_(0),
57 modules_(modules),
58 reason_(reason),
59 server_(server),
60 parent_(parent),
61 callback_(callback),
62 retry_(PR_FALSE) {
63 DCHECK_CURRENTLY_ON(BrowserThread::UI);
66 void SlotUnlocker::Start() {
67 DCHECK_CURRENTLY_ON(BrowserThread::UI);
69 for (; current_ < modules_.size(); ++current_) {
70 if (ShouldShowDialog(modules_[current_].get())) {
71 ShowCryptoModulePasswordDialog(
72 modules_[current_]->GetTokenName(),
73 retry_,
74 reason_,
75 server_.host(),
76 parent_,
77 base::Bind(&SlotUnlocker::GotPassword, base::Unretained(this)));
78 return;
81 Done();
84 void SlotUnlocker::GotPassword(const std::string& password) {
85 // TODO(mattm): PK11_DoPassword has something about PK11_Global.verifyPass.
86 // Do we need it?
87 // http://mxr.mozilla.org/mozilla/source/security/nss/lib/pk11wrap/pk11auth.c#577
89 if (password.empty()) {
90 // User cancelled entering password. Oh well.
91 ++current_;
92 Start();
93 return;
96 // TODO(mattm): handle protectedAuthPath
97 SECStatus rv = PK11_CheckUserPassword(modules_[current_]->os_module_handle(),
98 password.c_str());
99 if (rv == SECWouldBlock) {
100 // Incorrect password. Try again.
101 retry_ = PR_TRUE;
102 Start();
103 return;
106 // TODO(mattm): PK11_DoPassword calls nssTrustDomain_UpdateCachedTokenCerts on
107 // non-friendly slots. How important is that?
109 // Correct password (SECSuccess) or too many attempts/other failure
110 // (SECFailure). Either way we're done with this slot.
111 ++current_;
112 Start();
115 void SlotUnlocker::Done() {
116 DCHECK_EQ(current_, modules_.size());
117 callback_.Run();
118 delete this;
121 } // namespace
123 namespace chrome {
125 void UnlockSlotsIfNecessary(const net::CryptoModuleList& modules,
126 chrome::CryptoModulePasswordReason reason,
127 const net::HostPortPair& server,
128 gfx::NativeWindow parent,
129 const base::Closure& callback) {
130 DCHECK_CURRENTLY_ON(BrowserThread::UI);
131 for (size_t i = 0; i < modules.size(); ++i) {
132 if (ShouldShowDialog(modules[i].get())) {
133 (new SlotUnlocker(modules, reason, server, parent, callback))->Start();
134 return;
137 callback.Run();
140 void UnlockCertSlotIfNecessary(net::X509Certificate* cert,
141 chrome::CryptoModulePasswordReason reason,
142 const net::HostPortPair& server,
143 gfx::NativeWindow parent,
144 const base::Closure& callback) {
145 net::CryptoModuleList modules;
146 modules.push_back(net::CryptoModule::CreateFromHandle(
147 cert->os_cert_handle()->slot));
148 UnlockSlotsIfNecessary(modules, reason, server, parent, callback);
151 } // namespace chrome