- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / ssl / ssl_client_auth_handler.cc
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/ssl/client_cert_store.h"
15 #include "net/url_request/url_request.h"
16 #include "net/url_request/url_request_context.h"
17
18 namespace content {
19
20 SSLClientAuthHandler::SSLClientAuthHandler(
21     scoped_ptr<net::ClientCertStore> client_cert_store,
22     net::URLRequest* request,
23     net::SSLCertRequestInfo* cert_request_info)
24     : request_(request),
25       http_network_session_(
26           request_->context()->http_transaction_factory()->GetSession()),
27       cert_request_info_(cert_request_info),
28       client_cert_store_(client_cert_store.Pass()) {
29   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
30 }
31
32 SSLClientAuthHandler::~SSLClientAuthHandler() {
33   // If we were simply dropped, then act as if we selected no certificate.
34   DoCertificateSelected(NULL);
35 }
36
37 void SSLClientAuthHandler::OnRequestCancelled() {
38   request_ = NULL;
39 }
40
41 void SSLClientAuthHandler::SelectCertificate() {
42   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
43   DCHECK(request_);
44
45   if (client_cert_store_) {
46     client_cert_store_->GetClientCerts(
47         *cert_request_info_,
48         &cert_request_info_->client_certs,
49         base::Bind(&SSLClientAuthHandler::DidGetClientCerts, this));
50   } else {
51     DidGetClientCerts();
52   }
53 }
54
55 void SSLClientAuthHandler::CertificateSelected(net::X509Certificate* cert) {
56   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
57
58   VLOG(1) << this << " CertificateSelected " << cert;
59   BrowserThread::PostTask(
60       BrowserThread::IO, FROM_HERE,
61       base::Bind(
62           &SSLClientAuthHandler::DoCertificateSelected, this,
63           make_scoped_refptr(cert)));
64 }
65
66 void SSLClientAuthHandler::DidGetClientCerts() {
67   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
68   // Request may have cancelled while we were getting client certs.
69   if (!request_)
70     return;
71
72   // Note that if |client_cert_store_| is NULL, we intentionally fall through to
73   // DoCertificateSelected. This is for platforms where the client cert matching
74   // is not performed by Chrome, the platform can handle the cert matching
75   // before showing the dialog.
76   if (client_cert_store_ && cert_request_info_->client_certs.empty()) {
77     // No need to query the user if there are no certs to choose from.
78     DoCertificateSelected(NULL);
79     return;
80   }
81
82   int render_process_host_id;
83   int render_view_host_id;
84   if (!ResourceRequestInfo::ForRequest(request_)->GetAssociatedRenderView(
85           &render_process_host_id,
86           &render_view_host_id))
87     NOTREACHED();
88
89   // If the RVH does not exist by the time this task gets run, then the task
90   // will be dropped and the scoped_refptr to SSLClientAuthHandler will go
91   // away, so we do not leak anything. The destructor takes care of ensuring
92   // the net::URLRequest always gets a response.
93   BrowserThread::PostTask(
94       BrowserThread::UI, FROM_HERE,
95       base::Bind(
96           &SSLClientAuthHandler::DoSelectCertificate, this,
97           render_process_host_id, render_view_host_id));
98 }
99
100 void SSLClientAuthHandler::DoCertificateSelected(net::X509Certificate* cert) {
101   VLOG(1) << this << " DoCertificateSelected " << cert;
102   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
103   // request_ could have been NULLed if the request was cancelled while the
104   // user was choosing a cert, or because we have already responded to the
105   // certificate.
106   if (request_) {
107     request_->ContinueWithCertificate(cert);
108
109     ResourceDispatcherHostImpl::Get()->
110         ClearSSLClientAuthHandlerForRequest(request_);
111     request_ = NULL;
112   }
113 }
114
115 void SSLClientAuthHandler::DoSelectCertificate(
116     int render_process_host_id, int render_view_host_id) {
117   GetContentClient()->browser()->SelectClientCertificate(
118       render_process_host_id,
119       render_view_host_id,
120       http_network_session_,
121       cert_request_info_.get(),
122       base::Bind(&SSLClientAuthHandler::CertificateSelected, this));
123 }
124
125 }  // namespace content