| Index: chrome/browser/ui/views/ssl_client_certificate_selector.cc
|
| diff --git a/chrome/browser/ui/views/ssl_client_certificate_selector.cc b/chrome/browser/ui/views/ssl_client_certificate_selector.cc
|
| index 0176e6528f177ad45408e4c6c9bbc9f6c31db040..421a622654b50e0a87aca2389edd236dbe7af610 100644
|
| --- a/chrome/browser/ui/views/ssl_client_certificate_selector.cc
|
| +++ b/chrome/browser/ui/views/ssl_client_certificate_selector.cc
|
| @@ -10,31 +10,84 @@
|
| #include "base/bind_helpers.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "build/build_config.h"
|
| +#include "chrome/browser/ssl/ssl_client_auth_observer.h"
|
| #include "chrome/browser/ui/browser_dialogs.h"
|
| #include "chrome/grit/generated_resources.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/client_certificate_delegate.h"
|
| #include "content/public/browser/web_contents.h"
|
| +#include "content/public/browser/web_contents_observer.h"
|
| #include "net/cert/x509_certificate.h"
|
| #include "net/ssl/ssl_cert_request_info.h"
|
| #include "ui/base/l10n/l10n_util.h"
|
| #include "ui/views/controls/label.h"
|
| #include "ui/views/widget/widget.h"
|
|
|
| -#if defined(USE_NSS_CERTS) && !defined(OS_CHROMEOS)
|
| -#include "chrome/browser/ui/crypto_module_password_dialog_nss.h"
|
| -#endif
|
| +class SSLClientCertificateSelector::SSLClientAuthObserverImpl
|
| + : public SSLClientAuthObserver,
|
| + public content::WebContentsObserver {
|
| + public:
|
| + SSLClientAuthObserverImpl(
|
| + content::WebContents* web_contents,
|
| + const scoped_refptr<net::SSLCertRequestInfo>& cert_request_info,
|
| + std::unique_ptr<content::ClientCertificateDelegate> delegate)
|
| + : SSLClientAuthObserver(web_contents->GetBrowserContext(),
|
| + cert_request_info,
|
| + std::move(delegate)),
|
| + content::WebContentsObserver(web_contents) {}
|
| +
|
| + void Init(base::OnceClosure close_dialog_callback) {
|
| + close_dialog_callback_ = std::move(close_dialog_callback);
|
| + StartObserving();
|
| + }
|
| +
|
| + static void AcceptCertificate(
|
| + std::unique_ptr<SSLClientAuthObserverImpl> self,
|
| + std::unique_ptr<net::ClientCertIdentity> identity) {
|
| + // Remove the observer before we try acquiring private key, otherwise we
|
| + // might act on a notification while waiting for the callback, causing us
|
| + // to delete ourself before the callback gets called, or to try to run
|
| + // |close_dialog_callback_| on a dialog which is already closed.
|
| + self->StopObserving();
|
| + net::X509Certificate* cert = identity->certificate();
|
| + net::ClientCertIdentity::SelfOwningAcquirePrivateKey(
|
| + std::move(identity),
|
| + base::Bind(&SSLClientAuthObserverImpl::GotPrivateKey,
|
| + base::Passed(&self), base::Unretained(cert)));
|
| + }
|
| +
|
| + void GotPrivateKey(net::X509Certificate* cert,
|
| + scoped_refptr<net::SSLPrivateKey> private_key) {
|
| + CertificateSelected(cert, private_key.get());
|
| + }
|
| +
|
| + // SSLClientAuthObserver:
|
| + void OnCertSelectedByNotification() override {
|
| + std::move(close_dialog_callback_).Run();
|
| + }
|
| +
|
| + // content::WebContentsObserver:
|
| + void WebContentsDestroyed() override {
|
| + // If the tab is closed (either while the selector dialog is still showing,
|
| + // or after the dialog has closed but the AcquirePrivateKey callback is
|
| + // still pending), abort the request.
|
| + CancelCertificateSelection();
|
| + }
|
| +
|
| + private:
|
| + base::OnceClosure close_dialog_callback_;
|
| +};
|
|
|
| SSLClientCertificateSelector::SSLClientCertificateSelector(
|
| content::WebContents* web_contents,
|
| const scoped_refptr<net::SSLCertRequestInfo>& cert_request_info,
|
| - net::CertificateList client_certs,
|
| + net::ClientCertIdentityList client_certs,
|
| std::unique_ptr<content::ClientCertificateDelegate> delegate)
|
| : CertificateSelector(std::move(client_certs), web_contents),
|
| - SSLClientAuthObserver(web_contents->GetBrowserContext(),
|
| - cert_request_info,
|
| - std::move(delegate)),
|
| - WebContentsObserver(web_contents) {
|
| + auth_observer_impl_(
|
| + base::MakeUnique<SSLClientAuthObserverImpl>(web_contents,
|
| + cert_request_info,
|
| + std::move(delegate))) {
|
| chrome::RecordDialogCreation(
|
| chrome::DialogIdentifier::SSL_CLIENT_CERTIFICATE_SELECTOR);
|
| }
|
| @@ -42,11 +95,13 @@ SSLClientCertificateSelector::SSLClientCertificateSelector(
|
| SSLClientCertificateSelector::~SSLClientCertificateSelector() {}
|
|
|
| void SSLClientCertificateSelector::Init() {
|
| - StartObserving();
|
| + auth_observer_impl_->Init(base::BindOnce(
|
| + &SSLClientCertificateSelector::CloseDialog, base::Unretained(this)));
|
| std::unique_ptr<views::Label> text_label(
|
| new views::Label(l10n_util::GetStringFUTF16(
|
| IDS_CLIENT_CERT_DIALOG_TEXT,
|
| - base::ASCIIToUTF16(cert_request_info()->host_and_port.ToString()))));
|
| + base::ASCIIToUTF16(auth_observer_impl_->cert_request_info()
|
| + ->host_and_port.ToString()))));
|
| text_label->SetMultiLine(true);
|
| text_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| text_label->SetAllowCharacterBreak(true);
|
| @@ -54,7 +109,7 @@ void SSLClientCertificateSelector::Init() {
|
| InitWithText(std::move(text_label));
|
| }
|
|
|
| -void SSLClientCertificateSelector::OnCertSelectedByNotification() {
|
| +void SSLClientCertificateSelector::CloseDialog() {
|
| GetWidget()->Close();
|
| }
|
|
|
| @@ -63,40 +118,18 @@ void SSLClientCertificateSelector::DeleteDelegate() {
|
| // to abort instead of proceeding with a null certificate. (This will be
|
| // ignored if there was a previous call to CertificateSelected or
|
| // CancelCertificateSelection.)
|
| - CertificateSelected(nullptr);
|
| + if (auth_observer_impl_)
|
| + auth_observer_impl_->CertificateSelected(nullptr, nullptr);
|
| chrome::CertificateSelector::DeleteDelegate();
|
| }
|
|
|
| -bool SSLClientCertificateSelector::Accept() {
|
| - scoped_refptr<net::X509Certificate> cert = GetSelectedCert();
|
| - if (cert.get()) {
|
| - // Remove the observer before we try unlocking, otherwise we might act on a
|
| - // notification while waiting for the unlock dialog, causing us to delete
|
| - // ourself before the Unlocked callback gets called.
|
| - StopObserving();
|
| -#if defined(USE_NSS_CERTS) && !defined(OS_CHROMEOS)
|
| - chrome::UnlockCertSlotIfNecessary(
|
| - cert.get(), chrome::kCryptoModulePasswordClientAuth,
|
| - cert_request_info()->host_and_port, GetWidget()->GetNativeView(),
|
| - base::Bind(&SSLClientCertificateSelector::Unlocked,
|
| - base::Unretained(this), base::RetainedRef(cert)));
|
| -#else
|
| - Unlocked(cert.get());
|
| -#endif
|
| - return false; // Unlocked() will close the dialog.
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -void SSLClientCertificateSelector::WebContentsDestroyed() {
|
| - // If the dialog is closed by closing the containing tab, abort the request.
|
| - CancelCertificateSelection();
|
| -}
|
| -
|
| -void SSLClientCertificateSelector::Unlocked(net::X509Certificate* cert) {
|
| - CertificateSelected(cert);
|
| - GetWidget()->Close();
|
| +void SSLClientCertificateSelector::AcceptCertificate(
|
| + std::unique_ptr<net::ClientCertIdentity> identity) {
|
| + // The SSLClientCertificateSelector will be destroyed after this method
|
| + // returns, so the SSLClientAuthObserverImpl manages its own lifetime while
|
| + // acquiring the private key from |identity|.
|
| + SSLClientAuthObserverImpl::AcceptCertificate(std::move(auth_observer_impl_),
|
| + std::move(identity));
|
| }
|
|
|
| namespace chrome {
|
| @@ -104,7 +137,7 @@ namespace chrome {
|
| void ShowSSLClientCertificateSelector(
|
| content::WebContents* contents,
|
| net::SSLCertRequestInfo* cert_request_info,
|
| - net::CertificateList client_certs,
|
| + net::ClientCertIdentityList client_certs,
|
| std::unique_ptr<content::ClientCertificateDelegate> delegate) {
|
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
|
|
|
|