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

Unified 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, 10 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/android/ssl_client_certificate_request.cc
diff --git a/chrome/browser/ui/android/ssl_client_certificate_request.cc b/chrome/browser/ui/android/ssl_client_certificate_request.cc
new file mode 100644
index 0000000000000000000000000000000000000000..18001d8baa7feba665b9846978518476204d9d7c
--- /dev/null
+++ b/chrome/browser/ui/android/ssl_client_certificate_request.cc
@@ -0,0 +1,148 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/android/ssl_client_certificate_request.h"
+
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/logging.h"
+#include "content/public/browser/browser_thread.h"
+#include "jni/SSLClientCertificateRequest_jni.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/ssl_cert_request_info.h"
+#include "net/base/ssl_client_cert_type.h"
+
+namespace browser {
+namespace android {
+
+using content::BrowserThread;
+
+bool SSLClientCertificateRequest::Start(
+ const net::SSLCertRequestInfo* cert_request_info) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ JNIEnv* env = base::android::AttachCurrentThread();
+
+ // Build the |key_types| JNI parameter, as a String[]
+ std::vector<std::string> key_types;
+ for (size_t n = 0; n < cert_request_info->cert_key_types.size(); ++n) {
+ switch (cert_request_info->cert_key_types[n]) {
+ case net::CLIENT_CERT_RSA_SIGN:
+ key_types.push_back("RSA");
+ break;
+ case net::CLIENT_CERT_DSS_SIGN:
+ key_types.push_back("DSA");
+ break;
+ case net::CLIENT_CERT_ECDSA_SIGN:
+ key_types.push_back("ECDSA");
+ break;
+ default:
+ // Ignore unknown types.
+ break;
+ }
+ }
+ ScopedJavaLocalRef<jobjectArray> key_types_ref =
+ base::android::ToJavaArrayOfStrings(env, key_types);
+ if (key_types_ref.is_null()) {
+ LOG(ERROR) << "Could not create key types array (String[])";
+ return false;
+ }
+
+ // Build the |encoded_principals| JNI parameter, as a byte[][]
+ ScopedJavaLocalRef<jobjectArray> principals_ref =
+ base::android::ToJavaArrayOfByteArray(
+ env, cert_request_info->cert_authorities);
+ if (principals_ref.is_null()) {
+ LOG(ERROR) << "Could not create principals array (byte[][])";
+ return false;
+ }
+
+ // Build the |host_name| and |port| JNI parameters, as a String and
+ // a jint.
+ net::HostPortPair host_and_port =
+ net::HostPortPair::FromString(cert_request_info->host_and_port);
+
+ ScopedJavaLocalRef<jstring> host_name_ref =
+ base::android::ConvertUTF8ToJavaString(env, host_and_port.host());
+ if (host_name_ref.is_null()) {
+ LOG(ERROR) << "Could not extract host name from: '"
+ << cert_request_info->host_and_port << "'";
+ return false;
+ }
+
+ jint port = host_and_port.port();
+ if (port <= 0 || port > 65535) {
+ LOG(ERROR) << "Invalid port number in: "
+ << cert_request_info->host_and_port << "'";
+ return false;
+ }
+
+ // Convert the request's address into a pointer that will be passed
+ // to the Java method through JNI.
+ jint request_id = reinterpret_cast<jint>(this);
+
+ if (!Java_SSLClientCertificateRequest_selectClientCertificate(
+ env, request_id, key_types_ref.obj(), principals_ref.obj(),
+ host_name_ref.obj(), port)) {
+ return false;
+ }
+
+ // Ensure the request won't be destroyed until OnRequestCompletion is
+ // called later in the future.
+ this->AddRef();
+ return true;
+}
+
+// Called from JNI on request completion/result.
+// |env| is the current thread's JNIEnv.
+// |object| is the SSLClientCertificateRequest Java class reference.
+// |delegate_id| is the id passed to
+// Java_SSLClientCertificateRequest_selectClientCertificate() in Start().
+// |encoded_chain_ref| is a JNI reference to a Java array of byte arrays,
+// each item holding a DER-encoded X.509 certificate.
+// |private_key_ref| is the platform PrivateKey object JNI reference for
+// the client certificate.
+// Note: both |encoded_chain_ref| and |private_key_ref| will be NULL if
+// the user didn't select a certificate.
+void SSLClientCertificateRequest::OnRequestCompletion(
+ JNIEnv* env,
+ jobject object,
+ jobjectArray encoded_chain_ref,
+ jobject private_key_ref) {
+
+ // Ensure that the request is released when the
+ // function exits. Note that this also undoes the AddRef
+ // from ::Start().
+ scoped_refptr<SSLClientCertificateRequest> guard(this);
+ this->Release();
+
+ // When the request is cancelled by the user, just send NULL
+ // to the callback immediately.
+ if (private_key_ref == NULL || private_key_ref == NULL) {
+ LOG(ERROR) << "Client certificate request cancelled";
+ OnCompletion(NULL, NULL);
+ return;
+ }
+
+ // Convert the encoded chain to a vector of strings.
+ std::vector<std::string> encoded_chain_strings;
+ if (encoded_chain_ref) {
+ base::android::JavaArrayOfByteArrayToStringVector(
+ env, encoded_chain_ref, &encoded_chain_strings);
+ }
+
+ std::vector<base::StringPiece> encoded_chain;
+ for (size_t n = 0; n < encoded_chain_strings.size(); ++n)
+ encoded_chain.push_back(encoded_chain_strings[n]);
+
+ // Pass the results to the subclass.
+ OnCompletion(&encoded_chain, private_key_ref);
+}
+
+} // namespace android
+} // namespace browser
+
+bool RegisterSSLClientCertificateRequestAndroid(JNIEnv* env) {
+ return browser::android::RegisterNativesImpl(env);
+}

Powered by Google App Engine
This is Rietveld 408576698