diff options
author | Brian Carlstrom <bdc@google.com> | 2011-06-09 12:36:44 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-06-09 12:36:44 -0700 |
commit | 9da2ed34003cdea1a8c35c2f0947bb6632d99240 (patch) | |
tree | 764a068b84eed86956cdd1a9eaf30287e8e855fc | |
parent | 700ba3f86b1e8eefe7e0efe1fa344079ec7c1e24 (diff) | |
parent | eec5cd31a627a9d05aefe27fe25ff9df92ad1a53 (diff) | |
download | external_webkit-9da2ed34003cdea1a8c35c2f0947bb6632d99240.zip external_webkit-9da2ed34003cdea1a8c35c2f0947bb6632d99240.tar.gz external_webkit-9da2ed34003cdea1a8c35c2f0947bb6632d99240.tar.bz2 |
Merge "Implement net::URLRequest::Delegate::OnCertificateRequested"
-rw-r--r-- | Source/WebKit/Android.mk | 10 | ||||
-rw-r--r-- | Source/WebKit/android/WebCoreSupport/ChromiumIncludes.h | 3 | ||||
-rw-r--r-- | Source/WebKit/android/WebCoreSupport/WebRequest.cpp | 21 | ||||
-rw-r--r-- | Source/WebKit/android/WebCoreSupport/WebRequest.h | 2 | ||||
-rw-r--r-- | Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp | 18 | ||||
-rw-r--r-- | Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h | 2 | ||||
-rw-r--r-- | Source/WebKit/android/jni/WebCoreFrameBridge.cpp | 109 | ||||
-rw-r--r-- | Source/WebKit/android/jni/WebCoreFrameBridge.h | 2 |
8 files changed, 164 insertions, 3 deletions
diff --git a/Source/WebKit/Android.mk b/Source/WebKit/Android.mk index d02557e..7a5fabf 100644 --- a/Source/WebKit/Android.mk +++ b/Source/WebKit/Android.mk @@ -34,7 +34,7 @@ LOCAL_SRC_FILES := \ android/WebCoreSupport/V8Counters.cpp ifeq ($(HTTP_STACK),chrome) -LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ +LOCAL_SRC_FILES += \ android/WebCoreSupport/ChromiumInit.cpp \ android/WebCoreSupport/CacheResult.cpp \ android/WebCoreSupport/WebCache.cpp \ @@ -48,7 +48,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ android/WebCoreSupport/WebViewClientError.cpp endif # HTTP_STACK == chrome -LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ +LOCAL_SRC_FILES += \ android/RenderSkinAndroid.cpp \ android/RenderSkinButton.cpp \ android/RenderSkinCombo.cpp \ @@ -121,11 +121,15 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ android/wds/Connection.cpp \ android/wds/DebugServer.cpp +LOCAL_C_INCLUDES += \ + external/openssl/include \ + libcore/include + # Needed for autofill. ifeq ($(ENABLE_AUTOFILL),true) LOCAL_CFLAGS += -DENABLE_WEB_AUTOFILL -LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ +LOCAL_SRC_FILES += \ android/WebCoreSupport/autofill/AutoFillHostAndroid.cpp \ android/WebCoreSupport/autofill/FormFieldAndroid.cpp \ android/WebCoreSupport/autofill/FormManagerAndroid.cpp \ diff --git a/Source/WebKit/android/WebCoreSupport/ChromiumIncludes.h b/Source/WebKit/android/WebCoreSupport/ChromiumIncludes.h index e467218..8a17656 100644 --- a/Source/WebKit/android/WebCoreSupport/ChromiumIncludes.h +++ b/Source/WebKit/android/WebCoreSupport/ChromiumIncludes.h @@ -49,6 +49,7 @@ #include <base/callback.h> #include <base/lock.h> #include <base/message_loop_proxy.h> +#include <base/openssl_util.h> #include <base/ref_counted.h> #include <base/string_util.h> #include <base/synchronization/condition_variable.h> @@ -67,6 +68,8 @@ #include <net/base/load_flags.h> #include <net/base/net_errors.h> #include <net/base/mime_util.h> +#include <net/base/openssl_private_key_store.h> +#include <net/base/ssl_cert_request_info.h> #include <net/base/ssl_config_service.h> #include <net/disk_cache/disk_cache.h> #include <net/http/http_auth_handler_factory.h> diff --git a/Source/WebKit/android/WebCoreSupport/WebRequest.cpp b/Source/WebKit/android/WebCoreSupport/WebRequest.cpp index 7c6b9ea..85460bd 100644 --- a/Source/WebKit/android/WebCoreSupport/WebRequest.cpp +++ b/Source/WebKit/android/WebCoreSupport/WebRequest.cpp @@ -36,6 +36,7 @@ #include "jni.h" #include <cutils/log.h> +#include <openssl/x509.h> #include <string> #include <utils/AssetManager.h> @@ -407,6 +408,14 @@ void WebRequest::OnSSLCertificateError(net::URLRequest* request, int cert_error, m_urlLoader.get(), &WebUrlLoaderClient::reportSslCertError, cert_error, scoped_cert)); } +void WebRequest::OnCertificateRequested(net::URLRequest* request, net::SSLCertRequestInfo* cert_request_info) +{ + scoped_refptr<net::SSLCertRequestInfo> scoped_cert_request_info = cert_request_info; + m_urlLoader->maybeCallOnMainThread(NewRunnableMethod( + m_urlLoader.get(), &WebUrlLoaderClient::requestClientCert, scoped_cert_request_info)); +} + + // After calling Start(), the delegate will receive an OnResponseStarted // callback when the request has completed. If an error occurred, the // request->status() will be set. On success, all redirects have been @@ -461,6 +470,18 @@ void WebRequest::cancelSslCertError(int cert_error) m_request->SimulateError(cert_error); } +void WebRequest::sslClientCert(EVP_PKEY* pkey, scoped_refptr<net::X509Certificate> chain) +{ + base::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> privateKey(pkey); + if (privateKey.get() == NULL || chain.get() == NULL) { + m_request->ContinueWithCertificate(NULL); + return; + } + GURL gurl(m_url); + net::OpenSSLPrivateKeyStore::GetInstance()->StorePrivateKey(gurl, privateKey.release()); + m_request->ContinueWithCertificate(chain.release()); +} + void WebRequest::startReading() { ASSERT(m_networkBuffer == 0, "startReading called with a nonzero buffer"); diff --git a/Source/WebKit/android/WebCoreSupport/WebRequest.h b/Source/WebKit/android/WebCoreSupport/WebRequest.h index 4d18599..285e577 100644 --- a/Source/WebKit/android/WebCoreSupport/WebRequest.h +++ b/Source/WebKit/android/WebCoreSupport/WebRequest.h @@ -77,6 +77,7 @@ public: virtual void OnReadCompleted(net::URLRequest*, int bytesRead); virtual void OnAuthRequired(net::URLRequest*, net::AuthChallengeInfo*); virtual void OnSSLCertificateError(net::URLRequest* request, int cert_error, net::X509Certificate* cert); + virtual void OnCertificateRequested(net::URLRequest* request, net::SSLCertRequestInfo* cert_request_info); // Methods called during a request by the UI code (via WebUrlLoaderClient). void setAuth(const string16& username, const string16& password); @@ -84,6 +85,7 @@ public: void followDeferredRedirect(); void proceedSslCertError(); void cancelSslCertError(int cert_error); + void sslClientCert(EVP_PKEY* pkey, scoped_refptr<net::X509Certificate> chain); const std::string& getUrl() const; const std::string& getUserAgent() const; diff --git a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp index b22ae26..b047379 100644 --- a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp +++ b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp @@ -320,6 +320,15 @@ void WebUrlLoaderClient::cancelSslCertError(int cert_error) this->Release(); } +void WebUrlLoaderClient::sslClientCert(EVP_PKEY* pkey, net::X509Certificate* chain) +{ + base::Thread* thread = ioThread(); + scoped_refptr<net::X509Certificate> scopedChain(chain); + if (isActive() && thread) + thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(m_request.get(), &WebRequest::sslClientCert, pkey, scopedChain)); + this->Release(); +} + void WebUrlLoaderClient::finish() { @@ -479,4 +488,13 @@ void WebUrlLoaderClient::reportSslCertError(int cert_error, net::X509Certificate m_webFrame->reportSslCertError(this, cert_error, chain_bytes[0]); } +void WebUrlLoaderClient::requestClientCert(net::SSLCertRequestInfo* cert_request_info) +{ + if (!isActive()) + return; + + std::string host_and_port = cert_request_info->host_and_port; + m_webFrame->requestClientCert(this, host_and_port); +} + } // namespace android diff --git a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h index 224fa65..dc7e8d5 100644 --- a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h +++ b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h @@ -74,6 +74,7 @@ public: void cancelAuth(); void proceedSslCertError(); void cancelSslCertError(int cert_error); + void sslClientCert(EVP_PKEY* pkey, net::X509Certificate* chain); typedef void CallbackFunction(void*); @@ -91,6 +92,7 @@ public: void willSendRequest(PassOwnPtr<WebResponse>); void authRequired(scoped_refptr<net::AuthChallengeInfo>, bool firstTime); void reportSslCertError(int cert_error, net::X509Certificate* cert); + void requestClientCert(net::SSLCertRequestInfo* cert); // Handle to the chrome IO thread static base::Thread* ioThread(); diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp index be38a16..5f30ab4 100644 --- a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -93,8 +93,11 @@ #include <JNIUtility.h> #include <JNIHelp.h> +#include <ScopedPrimitiveArray.h> +#include <ScopedLocalRef.h> #include <SkGraphics.h> #include <android_runtime/android_util_AssetManager.h> +#include <openssl/x509.h> #include <utils/misc.h> #include <utils/AssetManager.h> #include <wtf/CurrentTime.h> @@ -212,6 +215,7 @@ struct WebFrame::JavaBrowserFrame jmethodID mGetFile; jmethodID mDidReceiveAuthenticationChallenge; jmethodID mReportSslCertError; + jmethodID mRequestClientCert; jmethodID mDownloadStart; jmethodID mDidReceiveData; jmethodID mDidFinishLoading; @@ -285,6 +289,7 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* mJavaFrame->mDidReceiveAuthenticationChallenge = env->GetMethodID(clazz, "didReceiveAuthenticationChallenge", "(ILjava/lang/String;Ljava/lang/String;Z)V"); mJavaFrame->mReportSslCertError = env->GetMethodID(clazz, "reportSslCertError", "(II[B)V"); + mJavaFrame->mRequestClientCert = env->GetMethodID(clazz, "requestClientCert", "(I[B)V"); mJavaFrame->mDownloadStart = env->GetMethodID(clazz, "downloadStart", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V"); mJavaFrame->mDidReceiveData = env->GetMethodID(clazz, "didReceiveData", "([BI)V"); @@ -320,6 +325,7 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* LOG_ASSERT(mJavaFrame->mGetFile, "Could not find method getFile"); LOG_ASSERT(mJavaFrame->mDidReceiveAuthenticationChallenge, "Could not find method didReceiveAuthenticationChallenge"); LOG_ASSERT(mJavaFrame->mReportSslCertError, "Could not find method reportSslCertError"); + LOG_ASSERT(mJavaFrame->mRequestClientCert, "Could not find method requestClientCert"); LOG_ASSERT(mJavaFrame->mDownloadStart, "Could not find method downloadStart"); LOG_ASSERT(mJavaFrame->mDidReceiveData, "Could not find method didReceiveData"); LOG_ASSERT(mJavaFrame->mDidFinishLoading, "Could not find method didFinishLoading"); @@ -981,6 +987,25 @@ WebFrame::reportSslCertError(WebUrlLoaderClient* client, int cert_error, const s checkException(env); } +void +WebFrame::requestClientCert(WebUrlLoaderClient* client, const std::string& host_and_port) +{ +#ifdef ANDROID_INSTRUMENT + TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); +#endif + JNIEnv* env = getJNIEnv(); + int jHandle = reinterpret_cast<int>(client); + + int len = host_and_port.length(); + jbyteArray jHostAndPort = env->NewByteArray(len); + jbyte* bytes = env->GetByteArrayElements(jHostAndPort, NULL); + host_and_port.copy(reinterpret_cast<char*>(bytes), len); + + env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mRequestClientCert, jHandle, jHostAndPort); + env->DeleteLocalRef(jHostAndPort); + checkException(env); +} + #if USE(CHROME_NETWORK_STACK) void WebFrame::downloadStart(const std::string& url, const std::string& userAgent, const std::string& contentDisposition, const std::string& mimetype, long long contentLength) @@ -2107,6 +2132,84 @@ static void SslCertErrorCancel(JNIEnv *env, jobject obj, int handle, int cert_er client->cancelSslCertError(cert_error); } +static void SslClientCert(JNIEnv *env, jobject obj, int handle, jbyteArray pkey, jobjectArray chain) +{ + WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle); + if (pkey == NULL || chain == NULL) { + client->sslClientCert(NULL, NULL); + return; + } + + // Based on Android's NativeCrypto_SSL_use_PrivateKey + ScopedByteArrayRO pkeyBytes(env, pkey); + if (pkeyBytes.get() == NULL) { + client->sslClientCert(NULL, NULL); + return; + } + + base::ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> pkcs8; + const unsigned char* pkeyChars = reinterpret_cast<const unsigned char*>(pkeyBytes.get()); + pkcs8.reset(d2i_PKCS8_PRIV_KEY_INFO(NULL, &pkeyChars, pkeyBytes.size())); + if (!pkcs8.get()) { + client->sslClientCert(NULL, NULL); + return; + } + base::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> privateKey(EVP_PKCS82PKEY(pkcs8.get())); + if (!privateKey.get()) { + client->sslClientCert(NULL, NULL); + return; + } + + // Based on Android's NativeCrypto_SSL_use_certificate + int length = env->GetArrayLength(chain); + if (length == 0) { + client->sslClientCert(NULL, NULL); + return; + } + + base::ScopedOpenSSL<X509, X509_free> first; + ScopedVector<base::ScopedOpenSSL<X509, X509_free> > rest; + for (int i = 0; i < length; i++) { + ScopedLocalRef<jbyteArray> cert(env, + reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(chain, i))); + if (cert.get() == NULL) { + client->sslClientCert(NULL, NULL); + return; + } + ScopedByteArrayRO certBytes(env, cert.get()); + if (certBytes.get() == NULL) { + client->sslClientCert(NULL, NULL); + return; + } + const char* data = reinterpret_cast<const char*>(certBytes.get()); + int length = certBytes.size(); + X509* x509 = net::X509Certificate::CreateOSCertHandleFromBytes(data, length); + if (x509 == NULL) { + client->sslClientCert(NULL, NULL); + return; + } + if (i == 0) { + first.reset(x509); + } else { + rest.push_back(new base::ScopedOpenSSL<X509, X509_free>(x509)); + } + } + + std::vector<X509*> certChain(rest.size()); + for (size_t i = 0; i < rest.size(); i++) { + certChain[i] = rest[i]->get(); + } + net::X509Certificate* certificate + = net::X509Certificate::CreateFromHandle(first.get(), + net::X509Certificate::SOURCE_FROM_NETWORK, + certChain); + if (certificate == NULL) { + client->sslClientCert(NULL, NULL); + return; + } + client->sslClientCert(privateKey.release(), certificate); +} + #else static void AuthenticationProceed(JNIEnv *env, jobject obj, int handle, jstring jUsername, jstring jPassword) @@ -2129,6 +2232,10 @@ static void SslCertErrorCancel(JNIEnv *env, jobject obj, int handle, int cert_er LOGW("Chromium SSL API called, but libchromium is not available"); } +static void SslClientCert(JNIEnv *env, jobject obj, int handle, jbyteArray privateKey, jobjectArray chain) +{ + LOGW("Chromium SSL API called, but libchromium is not available"); +} #endif // USE(CHROME_NETWORK_STACK) // ---------------------------------------------------------------------------- @@ -2193,6 +2300,8 @@ static JNINativeMethod gBrowserFrameNativeMethods[] = { (void*) SslCertErrorProceed }, { "nativeSslCertErrorCancel", "(II)V", (void*) SslCertErrorCancel }, + { "nativeSslClientCert", "(I[B[[B)V", + (void*) SslClientCert }, }; int registerWebFrame(JNIEnv* env) diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.h b/Source/WebKit/android/jni/WebCoreFrameBridge.h index 2e2468c..d74948f 100644 --- a/Source/WebKit/android/jni/WebCoreFrameBridge.h +++ b/Source/WebKit/android/jni/WebCoreFrameBridge.h @@ -119,6 +119,8 @@ class WebFrame : public WebCoreRefObject { void reportSslCertError(WebUrlLoaderClient* client, int cert_error, const std::string& cert); + void requestClientCert(WebUrlLoaderClient* client, const std::string& host_and_port); + void downloadStart(const std::string& url, const std::string& userAgent, const std::string& contentDisposition, const std::string& mimetype, long long contentLength); void didReceiveData(const char* data, int size); |