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 |