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

Side by Side Diff: android_webview/browser/aw_contents_client_bridge.cc

Issue 2898573002: Refactor client cert private key handling. (Closed)
Patch Set: removed no longer needed forward declaration Created 3 years, 6 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
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "android_webview/browser/aw_contents_client_bridge.h" 5 #include "android_webview/browser/aw_contents_client_bridge.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <utility> 8 #include <utility>
9 9
10 #include "android_webview/browser/aw_contents.h" 10 #include "android_webview/browser/aw_contents.h"
11 #include "android_webview/common/devtools_instrumentation.h" 11 #include "android_webview/common/devtools_instrumentation.h"
12 #include "android_webview/grit/components_strings.h" 12 #include "android_webview/grit/components_strings.h"
13 #include "base/android/jni_android.h" 13 #include "base/android/jni_android.h"
14 #include "base/android/jni_array.h" 14 #include "base/android/jni_array.h"
15 #include "base/android/jni_string.h" 15 #include "base/android/jni_string.h"
16 #include "base/callback_helpers.h"
17 #include "base/macros.h" 16 #include "base/macros.h"
18 #include "base/memory/ptr_util.h" 17 #include "base/memory/ptr_util.h"
19 #include "base/memory/ref_counted.h" 18 #include "base/memory/ref_counted.h"
20 #include "base/message_loop/message_loop.h" 19 #include "base/message_loop/message_loop.h"
21 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/client_certificate_delegate.h" 21 #include "content/public/browser/client_certificate_delegate.h"
23 #include "content/public/browser/render_frame_host.h" 22 #include "content/public/browser/render_frame_host.h"
24 #include "content/public/browser/render_process_host.h" 23 #include "content/public/browser/render_process_host.h"
25 #include "content/public/browser/render_view_host.h" 24 #include "content/public/browser/render_view_host.h"
26 #include "content/public/browser/web_contents.h" 25 #include "content/public/browser/web_contents.h"
27 #include "jni/AwContentsClientBridge_jni.h" 26 #include "jni/AwContentsClientBridge_jni.h"
28 #include "net/cert/x509_certificate.h" 27 #include "net/cert/x509_certificate.h"
29 #include "net/http/http_response_headers.h" 28 #include "net/http/http_response_headers.h"
30 #include "net/ssl/openssl_client_key_store.h"
31 #include "net/ssl/ssl_cert_request_info.h" 29 #include "net/ssl/ssl_cert_request_info.h"
32 #include "net/ssl/ssl_client_cert_type.h" 30 #include "net/ssl/ssl_client_cert_type.h"
33 #include "net/ssl/ssl_platform_key_android.h" 31 #include "net/ssl/ssl_platform_key_android.h"
34 #include "net/ssl/ssl_private_key.h" 32 #include "net/ssl/ssl_private_key.h"
35 #include "ui/base/l10n/l10n_util.h" 33 #include "ui/base/l10n/l10n_util.h"
36 #include "url/gurl.h" 34 #include "url/gurl.h"
37 35
38 using base::android::AttachCurrentThread; 36 using base::android::AttachCurrentThread;
39 using base::android::ConvertJavaStringToUTF16; 37 using base::android::ConvertJavaStringToUTF16;
40 using base::android::ConvertUTF8ToJavaString; 38 using base::android::ConvertUTF8ToJavaString;
41 using base::android::ConvertUTF16ToJavaString; 39 using base::android::ConvertUTF16ToJavaString;
42 using base::android::HasException; 40 using base::android::HasException;
43 using base::android::JavaRef; 41 using base::android::JavaRef;
44 using base::android::ScopedJavaLocalRef; 42 using base::android::ScopedJavaLocalRef;
45 using base::android::ToJavaArrayOfStrings; 43 using base::android::ToJavaArrayOfStrings;
46 using content::BrowserThread; 44 using content::BrowserThread;
47 using content::WebContents; 45 using content::WebContents;
48 using std::vector; 46 using std::vector;
49 47
50 namespace android_webview { 48 namespace android_webview {
51 49
52 namespace { 50 namespace {
53 51
54 // Must be called on the I/O thread to record a client certificate
55 // and its private key in the OpenSSLClientKeyStore.
56 void RecordClientCertificateKey(net::X509Certificate* client_cert,
57 scoped_refptr<net::SSLPrivateKey> private_key) {
58 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
59 net::OpenSSLClientKeyStore::GetInstance()->RecordClientCertPrivateKey(
60 client_cert, std::move(private_key));
61 }
62
63 const void* const kAwContentsClientBridge = &kAwContentsClientBridge; 52 const void* const kAwContentsClientBridge = &kAwContentsClientBridge;
64 53
65 // This class is invented so that the UserData registry that we inject the 54 // This class is invented so that the UserData registry that we inject the
66 // AwContentsClientBridge object does not own and destroy it. 55 // AwContentsClientBridge object does not own and destroy it.
67 class UserData : public base::SupportsUserData::Data { 56 class UserData : public base::SupportsUserData::Data {
68 public: 57 public:
69 static AwContentsClientBridge* GetContents( 58 static AwContentsClientBridge* GetContents(
70 content::WebContents* web_contents) { 59 content::WebContents* web_contents) {
71 if (!web_contents) 60 if (!web_contents)
72 return NULL; 61 return NULL;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 117
129 AwContentsClientBridge::~AwContentsClientBridge() { 118 AwContentsClientBridge::~AwContentsClientBridge() {
130 JNIEnv* env = AttachCurrentThread(); 119 JNIEnv* env = AttachCurrentThread();
131 120
132 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 121 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
133 if (!obj.is_null()) { 122 if (!obj.is_null()) {
134 // Clear the weak reference from the java peer to the native object since 123 // Clear the weak reference from the java peer to the native object since
135 // it is possible that java object lifetime can exceed the AwContens. 124 // it is possible that java object lifetime can exceed the AwContens.
136 Java_AwContentsClientBridge_setNativeContentsClientBridge(env, obj, 0); 125 Java_AwContentsClientBridge_setNativeContentsClientBridge(env, obj, 0);
137 } 126 }
138
139 for (IDMap<content::ClientCertificateDelegate*>::iterator iter(
140 &pending_client_cert_request_delegates_);
141 !iter.IsAtEnd(); iter.Advance()) {
142 delete iter.GetCurrentValue();
143 }
144 } 127 }
145 128
146 void AwContentsClientBridge::AllowCertificateError( 129 void AwContentsClientBridge::AllowCertificateError(
147 int cert_error, 130 int cert_error,
148 net::X509Certificate* cert, 131 net::X509Certificate* cert,
149 const GURL& request_url, 132 const GURL& request_url,
150 const base::Callback<void(content::CertificateRequestResultType)>& callback, 133 const base::Callback<void(content::CertificateRequestResultType)>& callback,
151 bool* cancel_request) { 134 bool* cancel_request) {
152 DCHECK_CURRENTLY_ON(BrowserThread::UI); 135 DCHECK_CURRENTLY_ON(BrowserThread::UI);
153 JNIEnv* env = AttachCurrentThread(); 136 JNIEnv* env = AttachCurrentThread();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 pending_cert_error_callbacks_.Remove(id); 173 pending_cert_error_callbacks_.Remove(id);
191 } 174 }
192 175
193 // This method is inspired by SelectClientCertificate() in 176 // This method is inspired by SelectClientCertificate() in
194 // chrome/browser/ui/android/ssl_client_certificate_request.cc 177 // chrome/browser/ui/android/ssl_client_certificate_request.cc
195 void AwContentsClientBridge::SelectClientCertificate( 178 void AwContentsClientBridge::SelectClientCertificate(
196 net::SSLCertRequestInfo* cert_request_info, 179 net::SSLCertRequestInfo* cert_request_info,
197 std::unique_ptr<content::ClientCertificateDelegate> delegate) { 180 std::unique_ptr<content::ClientCertificateDelegate> delegate) {
198 DCHECK_CURRENTLY_ON(BrowserThread::UI); 181 DCHECK_CURRENTLY_ON(BrowserThread::UI);
199 182
200 // Add the callback to id map.
201 int request_id =
202 pending_client_cert_request_delegates_.Add(delegate.release());
203 // Make sure callback is run on error.
204 base::ScopedClosureRunner guard(base::Bind(
205 &AwContentsClientBridge::HandleErrorInClientCertificateResponse,
206 base::Unretained(this), request_id));
207
208 JNIEnv* env = base::android::AttachCurrentThread(); 183 JNIEnv* env = base::android::AttachCurrentThread();
209 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 184 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
210 if (obj.is_null()) 185 if (obj.is_null())
211 return; 186 return;
212 187
213 // Build the |key_types| JNI parameter, as a String[] 188 // Build the |key_types| JNI parameter, as a String[]
214 std::vector<std::string> key_types; 189 std::vector<std::string> key_types;
215 for (size_t i = 0; i < cert_request_info->cert_key_types.size(); ++i) { 190 for (size_t i = 0; i < cert_request_info->cert_key_types.size(); ++i) {
216 switch (cert_request_info->cert_key_types[i]) { 191 switch (cert_request_info->cert_key_types[i]) {
217 case net::CLIENT_CERT_RSA_SIGN: 192 case net::CLIENT_CERT_RSA_SIGN:
(...skipping 23 matching lines...) Expand all
241 LOG(ERROR) << "Could not create principals array (byte[][])"; 216 LOG(ERROR) << "Could not create principals array (byte[][])";
242 return; 217 return;
243 } 218 }
244 219
245 // Build the |host_name| and |port| JNI parameters, as a String and 220 // Build the |host_name| and |port| JNI parameters, as a String and
246 // a jint. 221 // a jint.
247 ScopedJavaLocalRef<jstring> host_name_ref = 222 ScopedJavaLocalRef<jstring> host_name_ref =
248 base::android::ConvertUTF8ToJavaString( 223 base::android::ConvertUTF8ToJavaString(
249 env, cert_request_info->host_and_port.host()); 224 env, cert_request_info->host_and_port.host());
250 225
226 int request_id =
227 pending_client_cert_request_delegates_.Add(std::move(delegate));
251 Java_AwContentsClientBridge_selectClientCertificate( 228 Java_AwContentsClientBridge_selectClientCertificate(
252 env, obj, request_id, key_types_ref, principals_ref, host_name_ref, 229 env, obj, request_id, key_types_ref, principals_ref, host_name_ref,
253 cert_request_info->host_and_port.port()); 230 cert_request_info->host_and_port.port());
254
255 // Release the guard.
256 ignore_result(guard.Release());
257 } 231 }
258 232
259 // This method is inspired by OnSystemRequestCompletion() in 233 // This method is inspired by OnSystemRequestCompletion() in
260 // chrome/browser/ui/android/ssl_client_certificate_request.cc 234 // chrome/browser/ui/android/ssl_client_certificate_request.cc
261 void AwContentsClientBridge::ProvideClientCertificateResponse( 235 void AwContentsClientBridge::ProvideClientCertificateResponse(
262 JNIEnv* env, 236 JNIEnv* env,
263 const JavaRef<jobject>& obj, 237 const JavaRef<jobject>& obj,
264 int request_id, 238 int request_id,
265 const JavaRef<jobjectArray>& encoded_chain_ref, 239 const JavaRef<jobjectArray>& encoded_chain_ref,
266 const JavaRef<jobject>& private_key_ref) { 240 const JavaRef<jobject>& private_key_ref) {
267 DCHECK_CURRENTLY_ON(BrowserThread::UI); 241 DCHECK_CURRENTLY_ON(BrowserThread::UI);
268 242
269 content::ClientCertificateDelegate* delegate = 243 std::unique_ptr<content::ClientCertificateDelegate> delegate =
270 pending_client_cert_request_delegates_.Lookup(request_id); 244 pending_client_cert_request_delegates_.Replace(request_id, nullptr);
245 pending_client_cert_request_delegates_.Remove(request_id);
271 DCHECK(delegate); 246 DCHECK(delegate);
272 247
273 if (encoded_chain_ref.is_null() || private_key_ref.is_null()) { 248 if (encoded_chain_ref.is_null() || private_key_ref.is_null()) {
274 LOG(ERROR) << "No client certificate selected"; 249 LOG(ERROR) << "No client certificate selected";
275 pending_client_cert_request_delegates_.Remove(request_id); 250 delegate->ContinueWithCertificate(nullptr, nullptr);
276 delegate->ContinueWithCertificate(nullptr);
277 delete delegate;
278 return; 251 return;
279 } 252 }
280 253
281 // Make sure callback is run on error.
282 base::ScopedClosureRunner guard(base::Bind(
283 &AwContentsClientBridge::HandleErrorInClientCertificateResponse,
284 base::Unretained(this), request_id));
285
286 // Convert the encoded chain to a vector of strings. 254 // Convert the encoded chain to a vector of strings.
287 std::vector<std::string> encoded_chain_strings; 255 std::vector<std::string> encoded_chain_strings;
288 if (!encoded_chain_ref.is_null()) { 256 if (!encoded_chain_ref.is_null()) {
289 base::android::JavaArrayOfByteArrayToStringVector( 257 base::android::JavaArrayOfByteArrayToStringVector(
290 env, encoded_chain_ref.obj(), &encoded_chain_strings); 258 env, encoded_chain_ref.obj(), &encoded_chain_strings);
291 } 259 }
292 260
293 std::vector<base::StringPiece> encoded_chain; 261 std::vector<base::StringPiece> encoded_chain;
294 for (size_t i = 0; i < encoded_chain_strings.size(); ++i) 262 for (size_t i = 0; i < encoded_chain_strings.size(); ++i)
295 encoded_chain.push_back(encoded_chain_strings[i]); 263 encoded_chain.push_back(encoded_chain_strings[i]);
296 264
297 // Create the X509Certificate object from the encoded chain. 265 // Create the X509Certificate object from the encoded chain.
298 scoped_refptr<net::X509Certificate> client_cert( 266 scoped_refptr<net::X509Certificate> client_cert(
299 net::X509Certificate::CreateFromDERCertChain(encoded_chain)); 267 net::X509Certificate::CreateFromDERCertChain(encoded_chain));
300 if (!client_cert.get()) { 268 if (!client_cert.get()) {
301 LOG(ERROR) << "Could not decode client certificate chain"; 269 LOG(ERROR) << "Could not decode client certificate chain";
302 return; 270 return;
303 } 271 }
304 272
305 // Create an SSLPrivateKey wrapper for the private key JNI reference. 273 // Create an SSLPrivateKey wrapper for the private key JNI reference.
306 scoped_refptr<net::SSLPrivateKey> private_key = 274 scoped_refptr<net::SSLPrivateKey> private_key =
307 net::WrapJavaPrivateKey(client_cert.get(), private_key_ref); 275 net::WrapJavaPrivateKey(client_cert.get(), private_key_ref);
308 if (!private_key) { 276 if (!private_key) {
309 LOG(ERROR) << "Could not create OpenSSL wrapper for private key"; 277 LOG(ERROR) << "Could not create OpenSSL wrapper for private key";
310 return; 278 return;
311 } 279 }
312 280
313 // Release the guard and |pending_client_cert_request_delegates_| references 281 delegate->ContinueWithCertificate(std::move(client_cert),
314 // to |delegate|. 282 std::move(private_key));
315 pending_client_cert_request_delegates_.Remove(request_id);
316 ignore_result(guard.Release());
317
318 // RecordClientCertificateKey() must be called on the I/O thread,
319 // before the delegate is called with the selected certificate on
320 // the UI thread.
321 content::BrowserThread::PostTaskAndReply(
322 content::BrowserThread::IO, FROM_HERE,
323 base::Bind(&RecordClientCertificateKey, base::RetainedRef(client_cert),
324 base::Passed(&private_key)),
325 base::Bind(&content::ClientCertificateDelegate::ContinueWithCertificate,
326 base::Owned(delegate), base::RetainedRef(client_cert)));
327 } 283 }
328 284
329 void AwContentsClientBridge::RunJavaScriptDialog( 285 void AwContentsClientBridge::RunJavaScriptDialog(
330 content::JavaScriptDialogType dialog_type, 286 content::JavaScriptDialogType dialog_type,
331 const GURL& origin_url, 287 const GURL& origin_url,
332 const base::string16& message_text, 288 const base::string16& message_text,
333 const base::string16& default_prompt_text, 289 const base::string16& default_prompt_text,
334 const content::JavaScriptDialogManager::DialogClosedCallback& callback) { 290 const content::JavaScriptDialogManager::DialogClosedCallback& callback) {
335 DCHECK_CURRENTLY_ON(BrowserThread::UI); 291 DCHECK_CURRENTLY_ON(BrowserThread::UI);
336 JNIEnv* env = AttachCurrentThread(); 292 JNIEnv* env = AttachCurrentThread();
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 content::JavaScriptDialogManager::DialogClosedCallback* callback = 525 content::JavaScriptDialogManager::DialogClosedCallback* callback =
570 pending_js_dialog_callbacks_.Lookup(id); 526 pending_js_dialog_callbacks_.Lookup(id);
571 if (!callback) { 527 if (!callback) {
572 LOG(WARNING) << "Unexpected JS dialog cancel. " << id; 528 LOG(WARNING) << "Unexpected JS dialog cancel. " << id;
573 return; 529 return;
574 } 530 }
575 callback->Run(false, base::string16()); 531 callback->Run(false, base::string16());
576 pending_js_dialog_callbacks_.Remove(id); 532 pending_js_dialog_callbacks_.Remove(id);
577 } 533 }
578 534
579 // Use to cleanup if there is an error in client certificate response.
580 void AwContentsClientBridge::HandleErrorInClientCertificateResponse(
581 int request_id) {
582 content::ClientCertificateDelegate* delegate =
583 pending_client_cert_request_delegates_.Lookup(request_id);
584 pending_client_cert_request_delegates_.Remove(request_id);
585
586 delete delegate;
587 }
588
589 bool RegisterAwContentsClientBridge(JNIEnv* env) { 535 bool RegisterAwContentsClientBridge(JNIEnv* env) {
590 return RegisterNativesImpl(env); 536 return RegisterNativesImpl(env);
591 } 537 }
592 538
593 } // namespace android_webview 539 } // namespace android_webview
OLDNEW
« no previous file with comments | « android_webview/browser/aw_contents_client_bridge.h ('k') | android_webview/browser/aw_contents_client_bridge_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698