12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "android_webview/native/aw_contents_client_bridge.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "android_webview/common/devtools_instrumentation.h" 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "android_webview/native/aw_contents.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/android/jni_android.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/android/jni_array.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/android/jni_string.h" 120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/callback_helpers.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/public/browser/render_process_host.h" 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/public/browser/render_view_host.h" 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/public/browser/web_contents.h" 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "crypto/scoped_openssl_types.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "jni/AwContentsClientBridge_jni.h" 190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "net/android/keystore_openssl.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h" 210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "net/ssl/openssl_client_key_store.h" 220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "net/ssl/ssl_cert_request_info.h" 230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "net/ssl/ssl_client_cert_type.h" 247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::android::AttachCurrentThread; 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::android::ConvertJavaStringToUTF16; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::android::ConvertUTF8ToJavaString; 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::android::ConvertUTF16ToJavaString; 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::android::JavaRef; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::android::ScopedJavaLocalRef; 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread; 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace android_webview { 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace { 370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Must be called on the I/O thread to record a client certificate 390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// and its private key in the OpenSSLClientKeyStore. 400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid RecordClientCertificateKey( 410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const scoped_refptr<net::X509Certificate>& client_cert, 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch crypto::ScopedEVP_PKEY private_key) { 430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch net::OpenSSLClientKeyStore::GetInstance()->RecordClientCertPrivateKey( 450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch client_cert.get(), private_key.get()); 460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} // namespace 490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AwContentsClientBridge::AwContentsClientBridge(JNIEnv* env, jobject obj) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : java_ref_(env, obj) { 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(obj); 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Java_AwContentsClientBridge_setNativeContentsClientBridge( 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) env, obj, reinterpret_cast<intptr_t>(this)); 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AwContentsClientBridge::~AwContentsClientBridge() { 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JNIEnv* env = AttachCurrentThread(); 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (obj.is_null()) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Clear the weak reference from the java peer to the native object since 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // it is possible that java object lifetime can exceed the AwContens. 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Java_AwContentsClientBridge_setNativeContentsClientBridge(env, obj.obj(), 0); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AwContentsClientBridge::AllowCertificateError( 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int cert_error, 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::X509Certificate* cert, 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& request_url, 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Callback<void(bool)>& callback, 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* cancel_request) { 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JNIEnv* env = AttachCurrentThread(); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (obj.is_null()) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string der_string; 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::X509Certificate::GetDEREncoded(cert->os_cert_handle(), &der_string); 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedJavaLocalRef<jbyteArray> jcert = base::android::ToJavaByteArray( 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) env, 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reinterpret_cast<const uint8*>(der_string.data()), 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) der_string.length()); 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScopedJavaLocalRef<jstring> jurl(ConvertUTF8ToJavaString( 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) env, request_url.spec())); 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We need to add the callback before making the call to java side, 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // as it may do a synchronous callback prior to returning. 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int request_id = pending_cert_error_callbacks_.Add( 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new CertErrorCallback(callback)); 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *cancel_request = !Java_AwContentsClientBridge_allowCertificateError( 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) env, obj.obj(), cert_error, jcert.obj(), jurl.obj(), request_id); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // if the request is cancelled, then cancel the stored callback 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (*cancel_request) { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_cert_error_callbacks_.Remove(request_id); 990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AwContentsClientBridge::ProceedSslError(JNIEnv* env, jobject obj, 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) jboolean proceed, jint id) { 1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CertErrorCallback* callback = pending_cert_error_callbacks_.Lookup(id); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!callback || callback->is_null()) { 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "Ignoring unexpected ssl error proceed callback"; 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback->Run(proceed); 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_cert_error_callbacks_.Remove(id); 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// This method is inspired by SelectClientCertificate() in 1150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// chrome/browser/ui/android/ssl_client_certificate_request.cc 1160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid AwContentsClientBridge::SelectClientCertificate( 1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch net::SSLCertRequestInfo* cert_request_info, 1180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const SelectCertificateCallback& callback) { 1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 1200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Add the callback to id map. 1220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int request_id = pending_client_cert_request_callbacks_.Add( 1230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new SelectCertificateCallback(callback)); 1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Make sure callback is run on error. 1250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::ScopedClosureRunner guard(base::Bind( 1260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &AwContentsClientBridge::HandleErrorInClientCertificateResponse, 1270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::Unretained(this), 1280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch request_id)); 1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch JNIEnv* env = base::android::AttachCurrentThread(); 1310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 1320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (obj.is_null()) 1330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Build the |key_types| JNI parameter, as a String[] 1360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<std::string> key_types; 1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (size_t i = 0; i < cert_request_info->cert_key_types.size(); ++i) { 1380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch switch (cert_request_info->cert_key_types[i]) { 1390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case net::CLIENT_CERT_RSA_SIGN: 1400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch key_types.push_back("RSA"); 1410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch break; 1420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case net::CLIENT_CERT_DSS_SIGN: 1430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch key_types.push_back("DSA"); 1440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch break; 1450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case net::CLIENT_CERT_ECDSA_SIGN: 1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch key_types.push_back("ECDSA"); 1470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch break; 1480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch default: 1490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Ignore unknown types. 1500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch break; 1510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ScopedJavaLocalRef<jobjectArray> key_types_ref = 1550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::android::ToJavaArrayOfStrings(env, key_types); 1560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (key_types_ref.is_null()) { 1570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch LOG(ERROR) << "Could not create key types array (String[])"; 1580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Build the |encoded_principals| JNI parameter, as a byte[][] 1620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ScopedJavaLocalRef<jobjectArray> principals_ref = 1630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::android::ToJavaArrayOfByteArray( 1640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch env, cert_request_info->cert_authorities); 1650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (principals_ref.is_null()) { 1660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch LOG(ERROR) << "Could not create principals array (byte[][])"; 1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Build the |host_name| and |port| JNI parameters, as a String and 1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // a jint. 1720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ScopedJavaLocalRef<jstring> host_name_ref = 1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::android::ConvertUTF8ToJavaString( 1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch env, cert_request_info->host_and_port.host()); 1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Java_AwContentsClientBridge_selectClientCertificate( 1770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch env, 1780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch obj.obj(), 1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch request_id, 1800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch key_types_ref.obj(), 1810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch principals_ref.obj(), 1820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch host_name_ref.obj(), 1830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch cert_request_info->host_and_port.port()); 1840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Release the guard. 1860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ignore_result(guard.Release()); 1870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// This method is inspired by OnSystemRequestCompletion() in 1900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// chrome/browser/ui/android/ssl_client_certificate_request.cc 1910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid AwContentsClientBridge::ProvideClientCertificateResponse( 1920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch JNIEnv* env, 1930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch jobject obj, 1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int request_id, 1950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch jobjectArray encoded_chain_ref, 1960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch jobject private_key_ref) { 1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 1980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch SelectCertificateCallback* callback = 2000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch pending_client_cert_request_callbacks_.Lookup(request_id); 2010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(callback); 2020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Make sure callback is run on error. 2040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::ScopedClosureRunner guard(base::Bind( 2050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &AwContentsClientBridge::HandleErrorInClientCertificateResponse, 2060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::Unretained(this), 2070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch request_id)); 2080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (encoded_chain_ref == NULL || private_key_ref == NULL) { 2090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch LOG(ERROR) << "Client certificate request cancelled"; 2100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 2110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Convert the encoded chain to a vector of strings. 2130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<std::string> encoded_chain_strings; 2140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (encoded_chain_ref) { 2150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::android::JavaArrayOfByteArrayToStringVector( 2160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch env, encoded_chain_ref, &encoded_chain_strings); 2170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<base::StringPiece> encoded_chain; 2200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (size_t i = 0; i < encoded_chain_strings.size(); ++i) 2210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch encoded_chain.push_back(encoded_chain_strings[i]); 2220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Create the X509Certificate object from the encoded chain. 2240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_refptr<net::X509Certificate> client_cert( 2250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch net::X509Certificate::CreateFromDERCertChain(encoded_chain)); 2260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!client_cert.get()) { 2270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch LOG(ERROR) << "Could not decode client certificate chain"; 2280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 2290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Create an EVP_PKEY wrapper for the private key JNI reference. 232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch crypto::ScopedEVP_PKEY private_key( 2330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch net::android::GetOpenSSLPrivateKeyWrapper(private_key_ref)); 2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!private_key.get()) { 2350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch LOG(ERROR) << "Could not create OpenSSL wrapper for private key"; 2360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 2370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // RecordClientCertificateKey() must be called on the I/O thread, 2400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // before the callback is called with the selected certificate on 2410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // the UI thread. 2420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch content::BrowserThread::PostTaskAndReply( 2430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch content::BrowserThread::IO, 2440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FROM_HERE, 2450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::Bind(&RecordClientCertificateKey, 2460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch client_cert, 2470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::Passed(&private_key)), 2480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::Bind(*callback, client_cert)); 2490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch pending_client_cert_request_callbacks_.Remove(request_id); 2500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Release the guard. 2520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ignore_result(guard.Release()); 2530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 2540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AwContentsClientBridge::RunJavaScriptDialog( 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::JavaScriptMessageType message_type, 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const GURL& origin_url, 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& message_text, 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& default_prompt_text, 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const content::JavaScriptDialogManager::DialogClosedCallback& callback) { 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) JNIEnv* env = AttachCurrentThread(); 263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (obj.is_null()) { 2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(false, base::string16()); 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int callback_id = pending_js_dialog_callbacks_.Add( 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new content::JavaScriptDialogManager::DialogClosedCallback(callback)); 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedJavaLocalRef<jstring> jurl( 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ConvertUTF8ToJavaString(env, origin_url.spec())); 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedJavaLocalRef<jstring> jmessage( 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ConvertUTF16ToJavaString(env, message_text)); 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switch (message_type) { 278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case content::JAVASCRIPT_MESSAGE_TYPE_ALERT: { 279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) devtools_instrumentation::ScopedEmbedderCallbackTask("onJsAlert"); 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Java_AwContentsClientBridge_handleJsAlert( 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) env, obj.obj(), jurl.obj(), jmessage.obj(), callback_id); 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM: { 285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) devtools_instrumentation::ScopedEmbedderCallbackTask("onJsConfirm"); 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Java_AwContentsClientBridge_handleJsConfirm( 287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) env, obj.obj(), jurl.obj(), jmessage.obj(), callback_id); 288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case content::JAVASCRIPT_MESSAGE_TYPE_PROMPT: { 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedJavaLocalRef<jstring> jdefault_value( 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ConvertUTF16ToJavaString(env, default_prompt_text)); 293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) devtools_instrumentation::ScopedEmbedderCallbackTask("onJsPrompt"); 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Java_AwContentsClientBridge_handleJsPrompt(env, 295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) obj.obj(), 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) jurl.obj(), 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) jmessage.obj(), 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) jdefault_value.obj(), 299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) callback_id); 300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) default: 303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NOTREACHED(); 304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AwContentsClientBridge::RunBeforeUnloadDialog( 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const GURL& origin_url, 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& message_text, 310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const content::JavaScriptDialogManager::DialogClosedCallback& callback) { 311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) JNIEnv* env = AttachCurrentThread(); 313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (obj.is_null()) { 3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(false, base::string16()); 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int callback_id = pending_js_dialog_callbacks_.Add( 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new content::JavaScriptDialogManager::DialogClosedCallback(callback)); 322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedJavaLocalRef<jstring> jurl( 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ConvertUTF8ToJavaString(env, origin_url.spec())); 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedJavaLocalRef<jstring> jmessage( 325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ConvertUTF16ToJavaString(env, message_text)); 326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) devtools_instrumentation::ScopedEmbedderCallbackTask("onJsBeforeUnload"); 328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Java_AwContentsClientBridge_handleJsBeforeUnload( 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) env, obj.obj(), jurl.obj(), jmessage.obj(), callback_id); 330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool AwContentsClientBridge::ShouldOverrideUrlLoading( 333a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& url) { 334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) JNIEnv* env = AttachCurrentThread(); 335a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 336a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (obj.is_null()) 337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ScopedJavaLocalRef<jstring> jurl = ConvertUTF16ToJavaString(env, url); 339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) devtools_instrumentation::ScopedEmbedderCallbackTask( 340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "shouldOverrideUrlLoading"); 341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return Java_AwContentsClientBridge_shouldOverrideUrlLoading( 342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) env, obj.obj(), 343a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) jurl.obj()); 344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AwContentsClientBridge::ConfirmJsResult(JNIEnv* env, 347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) jobject, 348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int id, 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) jstring prompt) { 350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::JavaScriptDialogManager::DialogClosedCallback* callback = 352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pending_js_dialog_callbacks_.Lookup(id); 353ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!callback) { 354ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch LOG(WARNING) << "Unexpected JS dialog confirm. " << id; 355ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 356ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 prompt_text; 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (prompt) { 359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) prompt_text = ConvertJavaStringToUTF16(env, prompt); 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 361ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch callback->Run(true, prompt_text); 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pending_js_dialog_callbacks_.Remove(id); 363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AwContentsClientBridge::CancelJsResult(JNIEnv*, jobject, int id) { 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::JavaScriptDialogManager::DialogClosedCallback* callback = 368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pending_js_dialog_callbacks_.Lookup(id); 369ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!callback) { 370ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch LOG(WARNING) << "Unexpected JS dialog cancel. " << id; 371ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 372ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback->Run(false, base::string16()); 374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pending_js_dialog_callbacks_.Remove(id); 375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Use to cleanup if there is an error in client certificate response. 3780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid AwContentsClientBridge::HandleErrorInClientCertificateResponse( 3790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int request_id) { 3800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch SelectCertificateCallback* callback = 3810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch pending_client_cert_request_callbacks_.Lookup(request_id); 3820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch callback->Run(scoped_refptr<net::X509Certificate>()); 3830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch pending_client_cert_request_callbacks_.Remove(request_id); 3840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 3850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool RegisterAwContentsClientBridge(JNIEnv* env) { 3870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return RegisterNativesImpl(env); 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace android_webview 391