| 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 |