ssl_client_auth_observer.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/common/chrome_notification_types.h"
12#include "content/public/browser/browser_thread.h"
13#include "content/public/browser/notification_service.h"
14#include "net/base/x509_certificate.h"
15#include "net/ssl/ssl_cert_request_info.h"
16
17using content::BrowserThread;
18
19typedef std::pair<net::SSLCertRequestInfo*, net::X509Certificate*> CertDetails;
20
21SSLClientAuthObserver::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
30SSLClientAuthObserver::~SSLClientAuthObserver() {
31}
32
33void 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_;
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
54void 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
74void 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
81void SSLClientAuthObserver::StopObserving() {
82  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
83  notification_registrar_.RemoveAll();
84}
85