| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 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_handler.h" | |
| 6 | |
| 7 #include "chrome/browser/ssl/ssl_client_auth_notification_details.h" | |
| 8 #include "chrome/browser/tab_contents/tab_contents_ssl_helper.h" | |
| 9 #include "chrome/browser/tab_contents/tab_util.h" | |
| 10 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | |
| 11 #include "content/browser/browser_thread.h" | |
| 12 #include "content/browser/renderer_host/resource_dispatcher_host.h" | |
| 13 #include "content/browser/renderer_host/resource_dispatcher_host_request_info.h" | |
| 14 #include "content/common/notification_service.h" | |
| 15 #include "net/url_request/url_request.h" | |
| 16 | |
| 17 SSLClientAuthHandler::SSLClientAuthHandler( | |
| 18 net::URLRequest* request, | |
| 19 net::SSLCertRequestInfo* cert_request_info) | |
| 20 : request_(request), | |
| 21 cert_request_info_(cert_request_info) { | |
| 22 } | |
| 23 | |
| 24 SSLClientAuthHandler::~SSLClientAuthHandler() { | |
| 25 // If we were simply dropped, then act as if we selected no certificate. | |
| 26 DoCertificateSelected(NULL); | |
| 27 } | |
| 28 | |
| 29 void SSLClientAuthHandler::OnRequestCancelled() { | |
| 30 request_ = NULL; | |
| 31 } | |
| 32 | |
| 33 void SSLClientAuthHandler::SelectCertificate() { | |
| 34 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 35 | |
| 36 int render_process_host_id; | |
| 37 int render_view_host_id; | |
| 38 if (!ResourceDispatcherHost::RenderViewForRequest(request_, | |
| 39 &render_process_host_id, | |
| 40 &render_view_host_id)) | |
| 41 NOTREACHED(); | |
| 42 | |
| 43 // If the RVH does not exist by the time this task gets run, then the task | |
| 44 // will be dropped and the scoped_refptr to SSLClientAuthHandler will go | |
| 45 // away, so we do not leak anything. The destructor takes care of ensuring | |
| 46 // the net::URLRequest always gets a response. | |
| 47 BrowserThread::PostTask( | |
| 48 BrowserThread::UI, FROM_HERE, | |
| 49 NewRunnableMethod( | |
| 50 this, &SSLClientAuthHandler::ShowClientCertificateRequestDialog, | |
| 51 render_process_host_id, render_view_host_id)); | |
| 52 } | |
| 53 | |
| 54 // Sends an SSL_CLIENT_AUTH_CERT_SELECTED notification and notifies the IO | |
| 55 // thread that we have selected a cert. | |
| 56 void SSLClientAuthHandler::CertificateSelected(net::X509Certificate* cert) { | |
| 57 VLOG(1) << this << " CertificateSelected " << cert; | |
| 58 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 59 | |
| 60 SSLClientAuthNotificationDetails details(cert_request_info_, cert); | |
| 61 NotificationService* service = NotificationService::current(); | |
| 62 service->Notify(NotificationType::SSL_CLIENT_AUTH_CERT_SELECTED, | |
| 63 Source<SSLClientAuthHandler>(this), | |
| 64 Details<SSLClientAuthNotificationDetails>(&details)); | |
| 65 | |
| 66 CertificateSelectedNoNotify(cert); | |
| 67 } | |
| 68 | |
| 69 // Notifies the IO thread that we have selected a cert. | |
| 70 void SSLClientAuthHandler::CertificateSelectedNoNotify( | |
| 71 net::X509Certificate* cert) { | |
| 72 VLOG(1) << this << " CertificateSelectedNoNotify " << cert; | |
| 73 BrowserThread::PostTask( | |
| 74 BrowserThread::IO, FROM_HERE, | |
| 75 NewRunnableMethod( | |
| 76 this, &SSLClientAuthHandler::DoCertificateSelected, | |
| 77 make_scoped_refptr(cert))); | |
| 78 } | |
| 79 | |
| 80 void SSLClientAuthHandler::DoCertificateSelected(net::X509Certificate* cert) { | |
| 81 VLOG(1) << this << " DoCertificateSelected " << cert; | |
| 82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 83 // request_ could have been NULLed if the request was cancelled while the | |
| 84 // user was choosing a cert, or because we have already responded to the | |
| 85 // certificate. | |
| 86 if (request_) { | |
| 87 request_->ContinueWithCertificate(cert); | |
| 88 | |
| 89 ResourceDispatcherHostRequestInfo* info = | |
| 90 ResourceDispatcherHost::InfoForRequest(request_); | |
| 91 if (info) | |
| 92 info->set_ssl_client_auth_handler(NULL); | |
| 93 | |
| 94 request_ = NULL; | |
| 95 } | |
| 96 } | |
| 97 | |
| 98 void SSLClientAuthHandler::ShowClientCertificateRequestDialog( | |
| 99 int render_process_host_id, int render_view_host_id) { | |
| 100 TabContents* tab = tab_util::GetTabContentsByID( | |
| 101 render_process_host_id, render_view_host_id); | |
| 102 if (!tab) | |
| 103 return; | |
| 104 | |
| 105 TabContentsWrapper* wrapper = | |
| 106 TabContentsWrapper::GetCurrentWrapperForContents(tab); | |
| 107 wrapper->ssl_helper()->ShowClientCertificateRequestDialog(this); | |
| 108 } | |
| 109 | |
| 110 SSLClientAuthObserver::SSLClientAuthObserver( | |
| 111 net::SSLCertRequestInfo* cert_request_info, | |
| 112 SSLClientAuthHandler* handler) | |
| 113 : cert_request_info_(cert_request_info), handler_(handler) { | |
| 114 } | |
| 115 | |
| 116 SSLClientAuthObserver::~SSLClientAuthObserver() { | |
| 117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 118 } | |
| 119 | |
| 120 void SSLClientAuthObserver::Observe( | |
| 121 NotificationType type, | |
| 122 const NotificationSource& source, | |
| 123 const NotificationDetails& details) { | |
| 124 VLOG(1) << "SSLClientAuthObserver::Observe " << this << " " << handler_.get(); | |
| 125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 126 DCHECK(type == NotificationType::SSL_CLIENT_AUTH_CERT_SELECTED); | |
| 127 | |
| 128 if (Source<SSLClientAuthHandler>(source).ptr() == handler_.get()) { | |
| 129 VLOG(1) << "got notification from ourself " << handler_.get(); | |
| 130 return; | |
| 131 } | |
| 132 | |
| 133 SSLClientAuthNotificationDetails* auth_details = | |
| 134 Details<SSLClientAuthNotificationDetails>(details).ptr(); | |
| 135 if (!auth_details->IsSameHost(cert_request_info_)) | |
| 136 return; | |
| 137 | |
| 138 VLOG(1) << this << " got matching notification for " | |
| 139 << handler_.get() << ", selecting cert " | |
| 140 << auth_details->selected_cert(); | |
| 141 StopObserving(); | |
| 142 handler_->CertificateSelectedNoNotify(auth_details->selected_cert()); | |
| 143 OnCertSelectedByNotification(); | |
| 144 } | |
| 145 | |
| 146 void SSLClientAuthObserver::StartObserving() { | |
| 147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 148 notification_registrar_.Add(this, | |
| 149 NotificationType::SSL_CLIENT_AUTH_CERT_SELECTED, | |
| 150 NotificationService::AllSources()); | |
| 151 } | |
| 152 | |
| 153 void SSLClientAuthObserver::StopObserving() { | |
| 154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 155 notification_registrar_.RemoveAll(); | |
| 156 } | |
| OLD | NEW |