diff options
author | davidben <davidben@chromium.org> | 2014-10-08 21:46:42 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-09 04:46:56 +0000 |
commit | 99aee5eb0f6733566c60dfe356a1b7169477808f (patch) | |
tree | ecc8fb7a9631544684210ce83787813c43a288db /content/browser/ssl | |
parent | ae33495f402831f69b83afda2fe4db3041b7c7bb (diff) | |
download | chromium_src-99aee5eb0f6733566c60dfe356a1b7169477808f.zip chromium_src-99aee5eb0f6733566c60dfe356a1b7169477808f.tar.gz chromium_src-99aee5eb0f6733566c60dfe356a1b7169477808f.tar.bz2 |
Remove SSLClientAuthHandler's RDH dependency.
Instead, give it a callback to select the client certificate. This removes a
dependency on GlobalRequestID. Also stop reference-counting it and avoid
passing an HttpNetworkSession to the UI thread. (Use BrowserContext instead.)
BUG=376003
Review URL: https://codereview.chromium.org/596873002
Cr-Commit-Position: refs/heads/master@{#298782}
Diffstat (limited to 'content/browser/ssl')
-rw-r--r-- | content/browser/ssl/ssl_client_auth_handler.cc | 111 | ||||
-rw-r--r-- | content/browser/ssl/ssl_client_auth_handler.h | 58 |
2 files changed, 69 insertions, 100 deletions
diff --git a/content/browser/ssl/ssl_client_auth_handler.cc b/content/browser/ssl/ssl_client_auth_handler.cc index b7fe9f0..8cab2c7 100644 --- a/content/browser/ssl/ssl_client_auth_handler.cc +++ b/content/browser/ssl/ssl_client_auth_handler.cc @@ -5,77 +5,84 @@ #include "content/browser/ssl/ssl_client_auth_handler.h" #include "base/bind.h" -#include "content/browser/loader/resource_dispatcher_host_impl.h" +#include "base/logging.h" #include "content/browser/loader/resource_request_info_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" #include "net/cert/x509_certificate.h" -#include "net/http/http_transaction_factory.h" #include "net/ssl/client_cert_store.h" #include "net/url_request/url_request.h" -#include "net/url_request/url_request_context.h" namespace content { +namespace { + +typedef base::Callback<void(net::X509Certificate*)> CertificateCallback; + +void CertificateSelectedOnUIThread( + const CertificateCallback& io_thread_callback, + net::X509Certificate* cert) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(io_thread_callback, make_scoped_refptr(cert))); +} + +void SelectCertificateOnUIThread( + int render_process_host_id, + int render_frame_host_id, + net::SSLCertRequestInfo* cert_request_info, + const CertificateCallback& io_thread_callback) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + GetContentClient()->browser()->SelectClientCertificate( + render_process_host_id, render_frame_host_id, cert_request_info, + base::Bind(&CertificateSelectedOnUIThread, io_thread_callback)); +} + +} // namespace + SSLClientAuthHandler::SSLClientAuthHandler( scoped_ptr<net::ClientCertStore> client_cert_store, net::URLRequest* request, - net::SSLCertRequestInfo* cert_request_info) + net::SSLCertRequestInfo* cert_request_info, + const SSLClientAuthHandler::CertificateCallback& callback) : request_(request), - http_network_session_( - request_->context()->http_transaction_factory()->GetSession()), cert_request_info_(cert_request_info), - client_cert_store_(client_cert_store.Pass()) { + client_cert_store_(client_cert_store.Pass()), + callback_(callback), + weak_factory_(this) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); } SSLClientAuthHandler::~SSLClientAuthHandler() { - // If we were simply dropped, then act as if we selected no certificate. - DoCertificateSelected(NULL); -} - -void SSLClientAuthHandler::OnRequestCancelled() { - request_ = NULL; } void SSLClientAuthHandler::SelectCertificate() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - DCHECK(request_); if (client_cert_store_) { client_cert_store_->GetClientCerts( *cert_request_info_, &cert_request_info_->client_certs, - base::Bind(&SSLClientAuthHandler::DidGetClientCerts, this)); + base::Bind(&SSLClientAuthHandler::DidGetClientCerts, + weak_factory_.GetWeakPtr())); } else { DidGetClientCerts(); } } -void SSLClientAuthHandler::CertificateSelected(net::X509Certificate* cert) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - VLOG(1) << this << " CertificateSelected " << cert; - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind( - &SSLClientAuthHandler::DoCertificateSelected, this, - make_scoped_refptr(cert))); -} - void SSLClientAuthHandler::DidGetClientCerts() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - // Request may have cancelled while we were getting client certs. - if (!request_) - return; // Note that if |client_cert_store_| is NULL, we intentionally fall through to // DoCertificateSelected. This is for platforms where the client cert matching - // is not performed by Chrome, the platform can handle the cert matching - // before showing the dialog. + // is not performed by Chrome. Those platforms handle the cert matching before + // showing the dialog. if (client_cert_store_ && cert_request_info_->client_certs.empty()) { // No need to query the user if there are no certs to choose from. - DoCertificateSelected(NULL); + CertificateSelected(NULL); return; } @@ -83,43 +90,27 @@ void SSLClientAuthHandler::DidGetClientCerts() { int render_frame_host_id; if (!ResourceRequestInfo::ForRequest(request_)->GetAssociatedRenderFrame( &render_process_host_id, - &render_frame_host_id)) + &render_frame_host_id)) { NOTREACHED(); + CertificateSelected(NULL); + return; + } - // If the RVH does not exist by the time this task gets run, then the task - // will be dropped and the scoped_refptr to SSLClientAuthHandler will go - // away, so we do not leak anything. The destructor takes care of ensuring - // the net::URLRequest always gets a response. BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind( - &SSLClientAuthHandler::DoSelectCertificate, this, - render_process_host_id, render_frame_host_id)); + base::Bind(&SelectCertificateOnUIThread, + render_process_host_id, render_frame_host_id, + cert_request_info_, + base::Bind(&SSLClientAuthHandler::CertificateSelected, + weak_factory_.GetWeakPtr()))); } -void SSLClientAuthHandler::DoCertificateSelected(net::X509Certificate* cert) { +void SSLClientAuthHandler::CertificateSelected(net::X509Certificate* cert) { VLOG(1) << this << " DoCertificateSelected " << cert; DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - // request_ could have been NULLed if the request was cancelled while the - // user was choosing a cert, or because we have already responded to the - // certificate. - if (request_) { - request_->ContinueWithCertificate(cert); - - ResourceDispatcherHostImpl::Get()-> - ClearSSLClientAuthHandlerForRequest(request_); - request_ = NULL; - } -} -void SSLClientAuthHandler::DoSelectCertificate( - int render_process_host_id, int render_frame_host_id) { - GetContentClient()->browser()->SelectClientCertificate( - render_process_host_id, - render_frame_host_id, - http_network_session_, - cert_request_info_.get(), - base::Bind(&SSLClientAuthHandler::CertificateSelected, this)); + callback_.Run(cert); + // |this| may be deleted at this point. } } // namespace content diff --git a/content/browser/ssl/ssl_client_auth_handler.h b/content/browser/ssl/ssl_client_auth_handler.h index b848d54..f95e65d 100644 --- a/content/browser/ssl/ssl_client_auth_handler.h +++ b/content/browser/ssl/ssl_client_auth_handler.h @@ -6,79 +6,57 @@ #define CONTENT_BROWSER_SSL_SSL_CLIENT_AUTH_HANDLER_H_ #include "base/basictypes.h" +#include "base/callback.h" #include "base/memory/ref_counted.h" -#include "base/sequenced_task_runner_helpers.h" -#include "content/common/content_export.h" +#include "base/memory/weak_ptr.h" #include "content/public/browser/browser_thread.h" #include "net/ssl/ssl_cert_request_info.h" namespace net { class ClientCertStore; -class HttpNetworkSession; class URLRequest; class X509Certificate; } // namespace net namespace content { -class ResourceContext; - // This class handles the approval and selection of a certificate for SSL client -// authentication by the user. -// It is self-owned and deletes itself when the UI reports the user selection or -// when the net::URLRequest is cancelled. -class CONTENT_EXPORT SSLClientAuthHandler - : public base::RefCountedThreadSafe< - SSLClientAuthHandler, BrowserThread::DeleteOnIOThread> { +// authentication by the user. Should only be used on the IO thread. If the +// SSLClientAuthHandler is destroyed before the certificate is selected, the +// selection is canceled and the callback never called. +class SSLClientAuthHandler { public: + typedef base::Callback<void(net::X509Certificate*)> CertificateCallback; + SSLClientAuthHandler(scoped_ptr<net::ClientCertStore> client_cert_store, net::URLRequest* request, - net::SSLCertRequestInfo* cert_request_info); + net::SSLCertRequestInfo* cert_request_info, + const CertificateCallback& callback); + ~SSLClientAuthHandler(); // Selects a certificate and resumes the URL request with that certificate. - // Should only be called on the IO thread. void SelectCertificate(); - // Invoked when the request associated with this handler is cancelled. - // Should only be called on the IO thread. - void OnRequestCancelled(); - - // Calls DoCertificateSelected on the I/O thread. - // Called on the UI thread after the user has made a selection (which may - // be long after DoSelectCertificate returns, if the UI is modeless/async.) - void CertificateSelected(net::X509Certificate* cert); - - protected: - virtual ~SSLClientAuthHandler(); - private: - friend class base::RefCountedThreadSafe< - SSLClientAuthHandler, BrowserThread::DeleteOnIOThread>; - friend class BrowserThread; - friend class base::DeleteHelper<SSLClientAuthHandler>; - // Called when ClientCertStore is done retrieving the cert list. void DidGetClientCerts(); - // Notifies that the user has selected a cert. - // Called on the IO thread. - void DoCertificateSelected(net::X509Certificate* cert); - - // Selects a client certificate on the UI thread. - void DoSelectCertificate(int render_process_host_id, - int render_frame_host_id); + // Called when the user has selected a cert. + void CertificateSelected(net::X509Certificate* cert); // The net::URLRequest that triggered this client auth. net::URLRequest* request_; - // The HttpNetworkSession |request_| is associated with. - const net::HttpNetworkSession* http_network_session_; - // The certs to choose from. scoped_refptr<net::SSLCertRequestInfo> cert_request_info_; scoped_ptr<net::ClientCertStore> client_cert_store_; + // The callback to call when the certificate is selected. + CertificateCallback callback_; + + base::WeakPtrFactory<SSLClientAuthHandler> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(SSLClientAuthHandler); }; |