| Index: chrome/browser/ui/crypto_module_password_dialog_nss.cc
|
| diff --git a/chrome/browser/ui/crypto_module_password_dialog_nss.cc b/chrome/browser/ui/crypto_module_password_dialog_nss.cc
|
| index e2b6bb3c3bf3a451e3cf3fb7d465d65b4ac95996..44bf47bd22badf04ff8c31a8a54f6de2c3777eec 100644
|
| --- a/chrome/browser/ui/crypto_module_password_dialog_nss.cc
|
| +++ b/chrome/browser/ui/crypto_module_password_dialog_nss.cc
|
| @@ -13,12 +13,18 @@
|
|
|
| namespace {
|
|
|
| +bool ShouldShowDialog(const net::CryptoModule* module) {
|
| + // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc.
|
| + return (PK11_NeedLogin(module->os_module_handle()) &&
|
| + !PK11_IsLoggedIn(module->os_module_handle(), NULL /* wincx */));
|
| +}
|
| +
|
| // Basically an asynchronous implementation of NSS's PK11_DoPassword.
|
| // Note: This currently handles only the simple case. See the TODOs in
|
| // GotPassword for what is yet unimplemented.
|
| class SlotUnlocker {
|
| public:
|
| - SlotUnlocker(net::CryptoModule* module,
|
| + SlotUnlocker(const net::CryptoModuleList& modules,
|
| browser::CryptoModulePasswordReason reason,
|
| const std::string& host,
|
| Callback0::Type* callback);
|
| @@ -29,18 +35,20 @@ class SlotUnlocker {
|
| void GotPassword(const char* password);
|
| void Done();
|
|
|
| - scoped_refptr<net::CryptoModule> module_;
|
| + size_t current_;
|
| + net::CryptoModuleList modules_;
|
| browser::CryptoModulePasswordReason reason_;
|
| std::string host_;
|
| Callback0::Type* callback_;
|
| PRBool retry_;
|
| };
|
|
|
| -SlotUnlocker::SlotUnlocker(net::CryptoModule* module,
|
| +SlotUnlocker::SlotUnlocker(const net::CryptoModuleList& modules,
|
| browser::CryptoModulePasswordReason reason,
|
| const std::string& host,
|
| Callback0::Type* callback)
|
| - : module_(module),
|
| + : current_(0),
|
| + modules_(modules),
|
| reason_(reason),
|
| host_(host),
|
| callback_(callback),
|
| @@ -51,12 +59,18 @@ SlotUnlocker::SlotUnlocker(net::CryptoModule* module,
|
| void SlotUnlocker::Start() {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
|
|
| - ShowCryptoModulePasswordDialog(
|
| - module_->GetTokenName(),
|
| - retry_,
|
| - reason_,
|
| - host_,
|
| - NewCallback(this, &SlotUnlocker::GotPassword));
|
| + for (; current_ < modules_.size(); ++current_) {
|
| + if (ShouldShowDialog(modules_[current_].get())) {
|
| + ShowCryptoModulePasswordDialog(
|
| + modules_[current_]->GetTokenName(),
|
| + retry_,
|
| + reason_,
|
| + host_,
|
| + NewCallback(this, &SlotUnlocker::GotPassword));
|
| + return;
|
| + }
|
| + }
|
| + Done();
|
| }
|
|
|
| void SlotUnlocker::GotPassword(const char* password) {
|
| @@ -66,12 +80,13 @@ void SlotUnlocker::GotPassword(const char* password) {
|
|
|
| if (!password) {
|
| // User cancelled entering password. Oh well.
|
| - Done();
|
| + ++current_;
|
| + Start();
|
| return;
|
| }
|
|
|
| // TODO(mattm): handle protectedAuthPath
|
| - SECStatus rv = PK11_CheckUserPassword(module_->os_module_handle(),
|
| + SECStatus rv = PK11_CheckUserPassword(modules_[current_]->os_module_handle(),
|
| password);
|
| if (rv == SECWouldBlock) {
|
| // Incorrect password. Try again.
|
| @@ -84,11 +99,13 @@ void SlotUnlocker::GotPassword(const char* password) {
|
| // non-friendly slots. How important is that?
|
|
|
| // Correct password (SECSuccess) or too many attempts/other failure
|
| - // (SECFailure). Either way we're done.
|
| - Done();
|
| + // (SECFailure). Either way we're done with this slot.
|
| + ++current_;
|
| + Start();
|
| }
|
|
|
| void SlotUnlocker::Done() {
|
| + DCHECK_EQ(current_, modules_.size());
|
| callback_->Run();
|
| delete this;
|
| }
|
| @@ -97,27 +114,28 @@ void SlotUnlocker::Done() {
|
|
|
| namespace browser {
|
|
|
| -void UnlockSlotIfNecessary(net::CryptoModule* module,
|
| - browser::CryptoModulePasswordReason reason,
|
| - const std::string& host,
|
| - Callback0::Type* callback) {
|
| +void UnlockSlotsIfNecessary(const net::CryptoModuleList& modules,
|
| + browser::CryptoModulePasswordReason reason,
|
| + const std::string& host,
|
| + Callback0::Type* callback) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc.
|
| - if (PK11_NeedLogin(module->os_module_handle()) &&
|
| - !PK11_IsLoggedIn(module->os_module_handle(), NULL /* wincx */)) {
|
| - (new SlotUnlocker(module, reason, host, callback))->Start();
|
| - } else {
|
| - callback->Run();
|
| + for (size_t i = 0; i < modules.size(); ++i) {
|
| + if (ShouldShowDialog(modules[i].get())) {
|
| + (new SlotUnlocker(modules, reason, host, callback))->Start();
|
| + return;
|
| + }
|
| }
|
| + callback->Run();
|
| }
|
|
|
| void UnlockCertSlotIfNecessary(net::X509Certificate* cert,
|
| browser::CryptoModulePasswordReason reason,
|
| const std::string& host,
|
| Callback0::Type* callback) {
|
| - scoped_refptr<net::CryptoModule> module(net::CryptoModule::CreateFromHandle(
|
| + net::CryptoModuleList modules;
|
| + modules.push_back(net::CryptoModule::CreateFromHandle(
|
| cert->os_cert_handle()->slot));
|
| - UnlockSlotIfNecessary(module.get(), reason, host, callback);
|
| + UnlockSlotsIfNecessary(modules, reason, host, callback);
|
| }
|
|
|
| } // namespace browser
|
|
|