// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/ui/crypto_module_delegate_nss.h" #include "base/basictypes.h" #include "base/bind.h" #include "chrome/browser/net/nss_context.h" #include "content/public/browser/browser_thread.h" using content::BrowserThread; ChromeNSSCryptoModuleDelegate::ChromeNSSCryptoModuleDelegate( chrome::CryptoModulePasswordReason reason, const net::HostPortPair& server) : reason_(reason), server_(server), event_(false, false), cancelled_(false) {} ChromeNSSCryptoModuleDelegate::~ChromeNSSCryptoModuleDelegate() {} bool ChromeNSSCryptoModuleDelegate::InitializeSlot( content::ResourceContext* context, const base::Closure& initialization_complete_callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!slot_); base::Callback get_slot_callback; if (!initialization_complete_callback.is_null()) get_slot_callback = base::Bind(&ChromeNSSCryptoModuleDelegate::DidGetSlot, // Caller is responsible for keeping |this| // alive until the callback is run. base::Unretained(this), initialization_complete_callback); slot_ = GetPrivateNSSKeySlotForResourceContext(context, get_slot_callback); return slot_.get() != NULL; } // TODO(mattm): allow choosing which slot to generate and store the key. crypto::ScopedPK11Slot ChromeNSSCryptoModuleDelegate::RequestSlot() { return slot_.Pass(); } std::string ChromeNSSCryptoModuleDelegate::RequestPassword( const std::string& slot_name, bool retry, bool* cancelled) { DCHECK(!event_.IsSignaled()); event_.Reset(); if (BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&ChromeNSSCryptoModuleDelegate::ShowDialog, // This method blocks on |event_| until the task completes, // so there's no need to ref-count. base::Unretained(this), slot_name, retry))) { event_.Wait(); } *cancelled = cancelled_; return password_; } void ChromeNSSCryptoModuleDelegate::ShowDialog(const std::string& slot_name, bool retry) { DCHECK_CURRENTLY_ON(BrowserThread::UI); ShowCryptoModulePasswordDialog( slot_name, retry, reason_, server_.host(), NULL, // TODO(mattm): Supply parent window. base::Bind(&ChromeNSSCryptoModuleDelegate::GotPassword, // RequestPassword is blocked on |event_| until GotPassword is // called, so there's no need to ref-count. base::Unretained(this))); } void ChromeNSSCryptoModuleDelegate::GotPassword(const std::string& password) { if (!password.empty()) password_ = password; else cancelled_ = true; event_.Signal(); } void ChromeNSSCryptoModuleDelegate::DidGetSlot(const base::Closure& callback, crypto::ScopedPK11Slot slot) { DCHECK(!slot_); slot_ = slot.Pass(); callback.Run(); } crypto::CryptoModuleBlockingPasswordDelegate* CreateCryptoModuleBlockingPasswordDelegate( chrome::CryptoModulePasswordReason reason, const net::HostPortPair& server) { // Returns a ChromeNSSCryptoModuleDelegate without calling InitializeSlot. // Since it is only being used as a CreateCryptoModuleBlockingDialogDelegate, // initializing the slot handle is unnecessary. return new ChromeNSSCryptoModuleDelegate(reason, server); }