OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |