1 // Copyright (c) 2012 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/ssl/ssl_client_auth_observer.h" 6 7 #include <utility> 8 9 #include "base/bind.h" 10 #include "base/logging.h" 11 #include "chrome/browser/chrome_notification_types.h" 12 #include "content/public/browser/browser_thread.h" 13 #include "content/public/browser/notification_service.h" 14 #include "net/cert/x509_certificate.h" 15 #include "net/ssl/ssl_cert_request_info.h" 16 17 using content::BrowserThread; 18 19 typedef std::pair<net::SSLCertRequestInfo*, net::X509Certificate*> CertDetails; 20 21 SSLClientAuthObserver::SSLClientAuthObserver( 22 const net::HttpNetworkSession* network_session, 23 net::SSLCertRequestInfo* cert_request_info, 24 const base::Callback<void(net::X509Certificate*)>& callback) 25 : network_session_(network_session), 26 cert_request_info_(cert_request_info), 27 callback_(callback) { 28 } 29 30 SSLClientAuthObserver::~SSLClientAuthObserver() { 31 } 32 33 void SSLClientAuthObserver::CertificateSelected( 34 net::X509Certificate* certificate) { 35 if (callback_.is_null()) 36 return; 37 38 // Stop listening right away so we don't get our own notification. 39 StopObserving(); 40 41 CertDetails details; 42 details.first = cert_request_info_.get(); 43 details.second = certificate; 44 content::NotificationService* service = 45 content::NotificationService::current(); 46 service->Notify(chrome::NOTIFICATION_SSL_CLIENT_AUTH_CERT_SELECTED, 47 content::Source<net::HttpNetworkSession>(network_session_), 48 content::Details<CertDetails>(&details)); 49 50 callback_.Run(certificate); 51 callback_.Reset(); 52 } 53 54 void SSLClientAuthObserver::Observe( 55 int type, 56 const content::NotificationSource& source, 57 const content::NotificationDetails& details) { 58 VLOG(1) << "SSLClientAuthObserver::Observe " << this; 59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 60 DCHECK(type == chrome::NOTIFICATION_SSL_CLIENT_AUTH_CERT_SELECTED); 61 62 CertDetails* cert_details = content::Details<CertDetails>(details).ptr(); 63 if (cert_details->first->host_and_port != cert_request_info_->host_and_port) 64 return; 65 66 VLOG(1) << this << " got matching notification and selecting cert " 67 << cert_details->second; 68 StopObserving(); 69 callback_.Run(cert_details->second); 70 callback_.Reset(); 71 OnCertSelectedByNotification(); 72 } 73 74 void SSLClientAuthObserver::StartObserving() { 75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 76 notification_registrar_.Add( 77 this, chrome::NOTIFICATION_SSL_CLIENT_AUTH_CERT_SELECTED, 78 content::Source<net::HttpNetworkSession>(network_session_)); 79 } 80 81 void SSLClientAuthObserver::StopObserving() { 82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 83 notification_registrar_.RemoveAll(); 84 } 85