15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ssl/ssl_client_auth_observer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_cert_request_info.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::pair<net::SSLCertRequestInfo*, net::X509Certificate*> CertDetails;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientAuthObserver::SSLClientAuthObserver(
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::HttpNetworkSession* network_session,
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<net::SSLCertRequestInfo>& cert_request_info,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Callback<void(net::X509Certificate*)>& callback)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : network_session_(network_session),
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cert_request_info_(cert_request_info),
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_(callback) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientAuthObserver::~SSLClientAuthObserver() {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientAuthObserver::CertificateSelected(
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::X509Certificate* certificate) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (callback_.is_null())
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop listening right away so we don't get our own notification.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopObserving();
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CertDetails details;
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  details.first = cert_request_info_.get();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  details.second = certificate;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationService* service =
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::current();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service->Notify(chrome::NOTIFICATION_SSL_CLIENT_AUTH_CERT_SELECTED,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  content::Source<net::HttpNetworkSession>(network_session_),
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  content::Details<CertDetails>(&details));
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_.Run(certificate);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_.Reset();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientAuthObserver::Observe(
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int type,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationSource& source,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationDetails& details) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "SSLClientAuthObserver::Observe " << this;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type == chrome::NOTIFICATION_SSL_CLIENT_AUTH_CERT_SELECTED);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CertDetails* cert_details = content::Details<CertDetails>(details).ptr();
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!cert_details->first->host_and_port.Equals(
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           cert_request_info_->host_and_port))
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << this << " got matching notification and selecting cert "
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << cert_details->second;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopObserving();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_.Run(cert_details->second);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_.Reset();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnCertSelectedByNotification();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientAuthObserver::StartObserving() {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_registrar_.Add(
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, chrome::NOTIFICATION_SSL_CLIENT_AUTH_CERT_SELECTED,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<net::HttpNetworkSession>(network_session_));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientAuthObserver::StopObserving() {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_registrar_.RemoveAll();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
86