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 "content/browser/ssl/ssl_client_auth_handler.h" 6 7 #include "base/bind.h" 8 #include "content/browser/loader/resource_dispatcher_host_impl.h" 9 #include "content/browser/loader/resource_request_info_impl.h" 10 #include "content/public/browser/browser_thread.h" 11 #include "content/public/browser/content_browser_client.h" 12 #include "net/cert/x509_certificate.h" 13 #include "net/http/http_transaction_factory.h" 14 #include "net/url_request/url_request.h" 15 #include "net/url_request/url_request_context.h" 16 17 namespace content { 18 19 SSLClientAuthHandler::SSLClientAuthHandler( 20 net::URLRequest* request, 21 net::SSLCertRequestInfo* cert_request_info) 22 : request_(request), 23 http_network_session_( 24 request_->context()->http_transaction_factory()->GetSession()), 25 cert_request_info_(cert_request_info) { 26 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 27 } 28 29 SSLClientAuthHandler::~SSLClientAuthHandler() { 30 // If we were simply dropped, then act as if we selected no certificate. 31 DoCertificateSelected(NULL); 32 } 33 34 void SSLClientAuthHandler::OnRequestCancelled() { 35 request_ = NULL; 36 } 37 38 void SSLClientAuthHandler::SelectCertificate() { 39 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 40 DCHECK(request_); 41 42 int render_process_host_id; 43 int render_view_host_id; 44 if (!ResourceRequestInfo::ForRequest(request_)->GetAssociatedRenderView( 45 &render_process_host_id, 46 &render_view_host_id)) 47 NOTREACHED(); 48 49 // If the RVH does not exist by the time this task gets run, then the task 50 // will be dropped and the scoped_refptr to SSLClientAuthHandler will go 51 // away, so we do not leak anything. The destructor takes care of ensuring 52 // the net::URLRequest always gets a response. 53 BrowserThread::PostTask( 54 BrowserThread::UI, FROM_HERE, 55 base::Bind( 56 &SSLClientAuthHandler::DoSelectCertificate, this, 57 render_process_host_id, render_view_host_id)); 58 } 59 60 void SSLClientAuthHandler::CertificateSelected(net::X509Certificate* cert) { 61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 62 63 VLOG(1) << this << " CertificateSelected " << cert; 64 BrowserThread::PostTask( 65 BrowserThread::IO, FROM_HERE, 66 base::Bind( 67 &SSLClientAuthHandler::DoCertificateSelected, this, 68 make_scoped_refptr(cert))); 69 } 70 71 void SSLClientAuthHandler::DoCertificateSelected(net::X509Certificate* cert) { 72 VLOG(1) << this << " DoCertificateSelected " << cert; 73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 74 // request_ could have been NULLed if the request was cancelled while the 75 // user was choosing a cert, or because we have already responded to the 76 // certificate. 77 if (request_) { 78 request_->ContinueWithCertificate(cert); 79 80 ResourceDispatcherHostImpl::Get()-> 81 ClearSSLClientAuthHandlerForRequest(request_); 82 request_ = NULL; 83 } 84 } 85 86 void SSLClientAuthHandler::DoSelectCertificate( 87 int render_process_host_id, int render_view_host_id) { 88 GetContentClient()->browser()->SelectClientCertificate( 89 render_process_host_id, 90 render_view_host_id, 91 http_network_session_, 92 cert_request_info_.get(), 93 base::Bind(&SSLClientAuthHandler::CertificateSelected, this)); 94 } 95 96 } // namespace content 97