Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: chrome/browser/ui/android/ssl_client_certificate_request.cc

Issue 12374020: Add Android support for SSL client authentication to the browser layer. (Closed) Base URL: http://git.chromium.org/chromium/src.git@client-cert-test
Patch Set: a few more nits Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2013 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/ui/android/ssl_client_certificate_request.h"
6
7 #include "base/android/jni_array.h"
8 #include "base/android/jni_string.h"
9 #include "base/android/scoped_java_ref.h"
10 #include "base/logging.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "jni/SSLClientCertificateRequest_jni.h"
13 #include "net/base/host_port_pair.h"
14 #include "net/base/ssl_cert_request_info.h"
15 #include "net/base/ssl_client_cert_type.h"
16
17 namespace browser {
18 namespace android {
19
20 using content::BrowserThread;
21
22 bool SSLClientCertificateRequest::Start(
23 const net::SSLCertRequestInfo* cert_request_info) {
24 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
25 JNIEnv* env = base::android::AttachCurrentThread();
26
27 // Build the |key_types| JNI parameter, as a String[]
28 std::vector<std::string> key_types;
29 for (size_t n = 0; n < cert_request_info->cert_key_types.size(); ++n) {
30 switch (cert_request_info->cert_key_types[n]) {
31 case net::CLIENT_CERT_RSA_SIGN:
32 key_types.push_back("RSA");
33 break;
34 case net::CLIENT_CERT_DSS_SIGN:
35 key_types.push_back("DSA");
36 break;
37 case net::CLIENT_CERT_ECDSA_SIGN:
38 key_types.push_back("ECDSA");
39 break;
40 default:
41 // Ignore unknown types.
42 break;
43 }
44 }
45 ScopedJavaLocalRef<jobjectArray> key_types_ref =
46 base::android::ToJavaArrayOfStrings(env, key_types);
47 if (key_types_ref.is_null()) {
48 LOG(ERROR) << "Could not create key types array (String[])";
49 return false;
50 }
51
52 // Build the |encoded_principals| JNI parameter, as a byte[][]
53 ScopedJavaLocalRef<jobjectArray> principals_ref =
54 base::android::ToJavaArrayOfByteArray(
55 env, cert_request_info->cert_authorities);
56 if (principals_ref.is_null()) {
57 LOG(ERROR) << "Could not create principals array (byte[][])";
58 return false;
59 }
60
61 // Build the |host_name| and |port| JNI parameters, as a String and
62 // a jint.
63 net::HostPortPair host_and_port =
64 net::HostPortPair::FromString(cert_request_info->host_and_port);
65
66 ScopedJavaLocalRef<jstring> host_name_ref =
67 base::android::ConvertUTF8ToJavaString(env, host_and_port.host());
68 if (host_name_ref.is_null()) {
69 LOG(ERROR) << "Could not extract host name from: '"
70 << cert_request_info->host_and_port << "'";
71 return false;
72 }
73
74 jint port = host_and_port.port();
75 if (port <= 0 || port > 65535) {
76 LOG(ERROR) << "Invalid port number in: "
77 << cert_request_info->host_and_port << "'";
78 return false;
79 }
80
81 // Convert the request's address into a pointer that will be passed
82 // to the Java method through JNI.
83 jint request_id = reinterpret_cast<jint>(this);
84
85 if (!Java_SSLClientCertificateRequest_selectClientCertificate(
86 env, request_id, key_types_ref.obj(), principals_ref.obj(),
87 host_name_ref.obj(), port)) {
88 return false;
89 }
90
91 // Ensure the request won't be destroyed until OnRequestCompletion is
92 // called later in the future.
93 this->AddRef();
94 return true;
95 }
96
97 // Called from JNI on request completion/result.
98 // |env| is the current thread's JNIEnv.
99 // |object| is the SSLClientCertificateRequest Java class reference.
100 // |delegate_id| is the id passed to
101 // Java_SSLClientCertificateRequest_selectClientCertificate() in Start().
102 // |encoded_chain_ref| is a JNI reference to a Java array of byte arrays,
103 // each item holding a DER-encoded X.509 certificate.
104 // |private_key_ref| is the platform PrivateKey object JNI reference for
105 // the client certificate.
106 // Note: both |encoded_chain_ref| and |private_key_ref| will be NULL if
107 // the user didn't select a certificate.
108 void SSLClientCertificateRequest::OnRequestCompletion(
109 JNIEnv* env,
110 jobject object,
111 jobjectArray encoded_chain_ref,
112 jobject private_key_ref) {
113
114 // Ensure that the request is released when the
115 // function exits. Note that this also undoes the AddRef
116 // from ::Start().
117 scoped_refptr<SSLClientCertificateRequest> guard(this);
118 this->Release();
119
120 // When the request is cancelled by the user, just send NULL
121 // to the callback immediately.
122 if (private_key_ref == NULL || private_key_ref == NULL) {
123 LOG(ERROR) << "Client certificate request cancelled";
124 OnCompletion(NULL, NULL);
125 return;
126 }
127
128 // Convert the encoded chain to a vector of strings.
129 std::vector<std::string> encoded_chain_strings;
130 if (encoded_chain_ref) {
131 base::android::JavaArrayOfByteArrayToStringVector(
132 env, encoded_chain_ref, &encoded_chain_strings);
133 }
134
135 std::vector<base::StringPiece> encoded_chain;
136 for (size_t n = 0; n < encoded_chain_strings.size(); ++n)
137 encoded_chain.push_back(encoded_chain_strings[n]);
138
139 // Pass the results to the subclass.
140 OnCompletion(&encoded_chain, private_key_ref);
141 }
142
143 } // namespace android
144 } // namespace browser
145
146 bool RegisterSSLClientCertificateRequestAndroid(JNIEnv* env) {
147 return browser::android::RegisterNativesImpl(env);
148 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698