Home | History | Annotate | Download | only in ssl
      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.Equals(
     64            cert_request_info_->host_and_port))
     65     return;
     66 
     67   VLOG(1) << this << " got matching notification and selecting cert "
     68           << cert_details->second;
     69   StopObserving();
     70   callback_.Run(cert_details->second);
     71   callback_.Reset();
     72   OnCertSelectedByNotification();
     73 }
     74 
     75 void SSLClientAuthObserver::StartObserving() {
     76   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     77   notification_registrar_.Add(
     78       this, chrome::NOTIFICATION_SSL_CLIENT_AUTH_CERT_SELECTED,
     79       content::Source<net::HttpNetworkSession>(network_session_));
     80 }
     81 
     82 void SSLClientAuthObserver::StopObserving() {
     83   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     84   notification_registrar_.RemoveAll();
     85 }
     86