From e777e7663bb6cecc72754dbf56e068f5b6ea30d5 Mon Sep 17 00:00:00 2001 From: Iain Merrick Date: Fri, 7 Jan 2011 10:50:51 +0000 Subject: Report SSL certificates to WebView. In the Apache HTTP stack, this is done by LoadListener. This CL plumbs in the same logic for the Chrome HTTP stack. This fixes the WebViewTest#testAccessCertificate CTS test. Bug:3242048 Change-Id: I69a4de46ded59bfdebdd391c4731c7c1a79744fb --- .../WebCoreSupport/ResourceLoaderAndroid.cpp | 2 +- WebKit/android/WebCoreSupport/WebResponse.cpp | 2 ++ WebKit/android/WebCoreSupport/WebResponse.h | 3 ++ WebKit/android/WebCoreSupport/WebUrlLoader.cpp | 4 +-- WebKit/android/WebCoreSupport/WebUrlLoader.h | 2 +- .../android/WebCoreSupport/WebUrlLoaderClient.cpp | 41 +++++++++++++++++++++- WebKit/android/WebCoreSupport/WebUrlLoaderClient.h | 3 +- WebKit/android/jni/WebCoreFrameBridge.cpp | 23 ++++++++++++ WebKit/android/jni/WebCoreFrameBridge.h | 2 ++ 9 files changed, 76 insertions(+), 6 deletions(-) (limited to 'WebKit') diff --git a/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp b/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp index 92a59a1..3f2d9ee 100644 --- a/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp +++ b/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp @@ -44,7 +44,7 @@ PassRefPtr ResourceLoaderAndroid::start( FrameLoaderClientAndroid* clientAndroid = static_cast(client); #if USE(CHROME_NETWORK_STACK) WebViewCore* webViewCore = WebViewCore::getWebViewCore(clientAndroid->getFrame()->view()); - return WebUrlLoader::start(client, handle, request, isSync, webViewCore->webRequestContext()); + return WebUrlLoader::start(client, handle, request, isMainResource, isSync, webViewCore->webRequestContext()); #else return clientAndroid->webFrame()->startLoadingResource(handle, request, isMainResource, isSync); #endif diff --git a/WebKit/android/WebCoreSupport/WebResponse.cpp b/WebKit/android/WebCoreSupport/WebResponse.cpp index a00b52d..f4e64bb 100644 --- a/WebKit/android/WebCoreSupport/WebResponse.cpp +++ b/WebKit/android/WebCoreSupport/WebResponse.cpp @@ -50,6 +50,8 @@ WebResponse::WebResponse(URLRequest* request) request->GetCharset(&m_encoding); m_expectedSize = request->GetExpectedContentSize(); + m_sslInfo = request->ssl_info(); + net::HttpResponseHeaders* responseHeaders = request->response_headers(); if (!responseHeaders) return; diff --git a/WebKit/android/WebCoreSupport/WebResponse.h b/WebKit/android/WebCoreSupport/WebResponse.h index e30779f..baae9a0 100644 --- a/WebKit/android/WebCoreSupport/WebResponse.h +++ b/WebKit/android/WebCoreSupport/WebResponse.h @@ -54,6 +54,8 @@ public: bool getHeader(const std::string& header, std::string* result) const; long long getExpectedSize() const; + const net::SSLInfo& getSslInfo() const { return m_sslInfo; } + // The create() methods create WebCore objects. They must only be called on the WebKit thread. WebCore::KURL createKurl(); WebCore::ResourceResponse createResourceResponse(); @@ -70,6 +72,7 @@ private: long long m_expectedSize; std::string m_mime; std::string m_url; + net::SSLInfo m_sslInfo; struct CaseInsensitiveLessThan { bool operator()(const std::string& lhs, const std::string& rhs) const { diff --git a/WebKit/android/WebCoreSupport/WebUrlLoader.cpp b/WebKit/android/WebCoreSupport/WebUrlLoader.cpp index f634633..f539901 100644 --- a/WebKit/android/WebCoreSupport/WebUrlLoader.cpp +++ b/WebKit/android/WebCoreSupport/WebUrlLoader.cpp @@ -45,7 +45,7 @@ WebUrlLoader::~WebUrlLoader() } PassRefPtr WebUrlLoader::start(FrameLoaderClient* client, WebCore::ResourceHandle* resourceHandle, - const WebCore::ResourceRequest& resourceRequest, bool isSync, WebRequestContext* context) + const WebCore::ResourceRequest& resourceRequest, bool isMainResource, bool isSync, WebRequestContext* context) { FrameLoaderClientAndroid* androidClient = static_cast(client); WebFrame* webFrame = androidClient->webFrame(); @@ -58,7 +58,7 @@ PassRefPtr WebUrlLoader::start(FrameLoaderClient* client, WebCore: webFrame->maybeSavePassword(androidClient->getFrame(), resourceRequest); RefPtr loader = WebUrlLoader::create(webFrame, resourceHandle, resourceRequest); - loader->m_loaderClient->start(isSync, context); + loader->m_loaderClient->start(isMainResource, isSync, context); return loader.release(); } diff --git a/WebKit/android/WebCoreSupport/WebUrlLoader.h b/WebKit/android/WebCoreSupport/WebUrlLoader.h index d9515f8..ead7e86 100644 --- a/WebKit/android/WebCoreSupport/WebUrlLoader.h +++ b/WebKit/android/WebCoreSupport/WebUrlLoader.h @@ -39,7 +39,7 @@ class WebRequestContext; class WebUrlLoader : public ResourceLoaderAndroid { public: virtual ~WebUrlLoader(); - static PassRefPtr start(FrameLoaderClient* client, WebCore::ResourceHandle*, const WebCore::ResourceRequest&, bool sync, WebRequestContext*); + static PassRefPtr start(FrameLoaderClient* client, WebCore::ResourceHandle*, const WebCore::ResourceRequest&, bool isMainResource, bool sync, WebRequestContext*); virtual void cancel(); virtual void downloadFile(); diff --git a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp index ed7ece7..baac6f0 100644 --- a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp +++ b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp @@ -38,6 +38,7 @@ #include "WebResourceRequest.h" #include +#include namespace android { @@ -96,6 +97,7 @@ bool WebUrlLoaderClient::isActive() const WebUrlLoaderClient::WebUrlLoaderClient(WebFrame* webFrame, WebCore::ResourceHandle* resourceHandle, const WebCore::ResourceRequest& resourceRequest) : m_webFrame(webFrame) , m_resourceHandle(resourceHandle) + , m_isMainResource(false) , m_cancelling(false) , m_sync(false) , m_finished(false) @@ -156,13 +158,14 @@ WebUrlLoaderClient::WebUrlLoaderClient(WebFrame* webFrame, WebCore::ResourceHand } } -bool WebUrlLoaderClient::start(bool sync, WebRequestContext* context) +bool WebUrlLoaderClient::start(bool isMainResource, bool sync, WebRequestContext* context) { base::Thread* thread = ioThread(); if (!thread) { return false; } + m_isMainResource = isMainResource; m_sync = sync; if (m_sync) { AutoLock autoLock(*syncLock()); @@ -290,6 +293,30 @@ void WebUrlLoaderClient::maybeCallOnMainThread(Task* task) } } +namespace { +// Convert a CertPrincipal into string readable by Java code. +// The expected format is "CN=xxx, O=xxx, OU=xxx" (see SslCertificate.DName). +// If there are multiple organization names, we print them all. +static std::string certPrincipalToString(const net::CertPrincipal& cp) +{ + std::string result; + if (!cp.common_name.empty()) { + result += "CN="; + result += cp.common_name; + } + std::vector::const_iterator i; + for (i = cp.organization_names.begin(); i != cp.organization_names.end(); ++i) { + result += result.empty() ? "O=" : ", O="; + result += *i; + } + for (i = cp.organization_unit_names.begin(); i != cp.organization_unit_names.end(); ++i) { + result += result.empty() ? "OU=" : ", OU="; + result += *i; + } + return result; +} +} + // Response methods void WebUrlLoaderClient::didReceiveResponse(PassOwnPtr webResponse) { @@ -298,6 +325,18 @@ void WebUrlLoaderClient::didReceiveResponse(PassOwnPtr webResponse) m_response = webResponse; m_resourceHandle->client()->didReceiveResponse(m_resourceHandle.get(), m_response->createResourceResponse()); + + if (m_isMainResource) { + // If we got an SSL certificate, tell the WebView about it. + const net::SSLInfo& ssl = m_response->getSslInfo(); + if (ssl.cert) { + m_webFrame->setCertificate( + certPrincipalToString(ssl.cert->subject()), + certPrincipalToString(ssl.cert->issuer()), + 1000L * ssl.cert->valid_start().ToDoubleT(), + 1000L * ssl.cert->valid_expiry().ToDoubleT()); + } + } } void WebUrlLoaderClient::didReceiveData(scoped_refptr buf, int size) diff --git a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h index e5a4d8f..4294b95 100644 --- a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h +++ b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h @@ -66,7 +66,7 @@ public: WebUrlLoaderClient(WebFrame*, WebCore::ResourceHandle*, const WebCore::ResourceRequest&); // Called from WebCore, will be forwarded to the IO thread - bool start(bool sync, WebRequestContext*); + bool start(bool isMainResource, bool sync, WebRequestContext*); void cancel(); void downloadFile(); void pauseLoad(bool pause) {} // Android method, does nothing for now @@ -103,6 +103,7 @@ private: WebFrame* m_webFrame; RefPtr m_resourceHandle; + bool m_isMainResource; bool m_cancelling; bool m_sync; volatile bool m_finished; diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp index c87fb47..5468a1e 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -217,6 +217,7 @@ struct WebFrame::JavaBrowserFrame jmethodID mDidReceiveAuthenticationChallenge; jmethodID mReportSslCertError; jmethodID mDownloadStart; + jmethodID mSetCertificate; AutoJObject frame(JNIEnv* env) { return getRealObject(env, mObj); } @@ -285,6 +286,8 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* mJavaFrame->mReportSslCertError = env->GetMethodID(clazz, "reportSslCertError", "(II[B)V"); mJavaFrame->mDownloadStart = env->GetMethodID(clazz, "downloadStart", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V"); + mJavaFrame->mSetCertificate = env->GetMethodID(clazz, "setCertificate", + "(Ljava/lang/String;Ljava/lang/String;JJ)V"); env->DeleteLocalRef(clazz); LOG_ASSERT(mJavaFrame->mStartLoadingResource, "Could not find method startLoadingResource"); @@ -312,6 +315,7 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* LOG_ASSERT(mJavaFrame->mDidReceiveAuthenticationChallenge, "Could not find method didReceiveAuthenticationChallenge"); LOG_ASSERT(mJavaFrame->mReportSslCertError, "Could not find method reportSslCertError"); LOG_ASSERT(mJavaFrame->mDownloadStart, "Could not find method downloadStart"); + LOG_ASSERT(mJavaFrame->mSetCertificate, "Could not find method setCertificate"); mUserAgent = WTF::String(); mUserInitiatedAction = false; @@ -911,6 +915,25 @@ WebFrame::downloadStart(const std::string& url, const std::string& userAgent, co } #endif +#if USE(CHROME_NETWORK_STACK) +void WebFrame::setCertificate(const std::string& issuedTo, const std::string& issuedBy, long long validNotBeforeMillis, long long validNotAfterMillis) +{ +#ifdef ANDROID_INSTRUMENT + TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); +#endif + JNIEnv* env = getJNIEnv(); + jstring jIssuedTo = stdStringToJstring(env, issuedTo, true); + jstring jIssuedBy = stdStringToJstring(env, issuedBy, true); + + env->CallVoidMethod(mJavaFrame->frame(env).get(), + mJavaFrame->mSetCertificate, jIssuedTo, jIssuedBy, validNotBeforeMillis, validNotAfterMillis); + + env->DeleteLocalRef(jIssuedTo); + env->DeleteLocalRef(jIssuedBy); + checkException(env); +} +#endif + void WebFrame::maybeSavePassword(WebCore::Frame* frame, const WebCore::ResourceRequest& request) { if (request.httpMethod() != "POST") diff --git a/WebKit/android/jni/WebCoreFrameBridge.h b/WebKit/android/jni/WebCoreFrameBridge.h index b9e1f43..11e9e72 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.h +++ b/WebKit/android/jni/WebCoreFrameBridge.h @@ -121,6 +121,8 @@ class WebFrame : public WebCoreRefObject { void maybeSavePassword(WebCore::Frame* frame, const WebCore::ResourceRequest& request); + void setCertificate(const std::string& issuedTo, const std::string& issuedBy, long long validNotBeforeMillis, long long validNotAfterMillis); + /** * When the user initiates an action (via trackball, key-press, or touch), * we set mUserInitiatedAction to true. If a load happens due to this click, -- cgit v1.1