diff options
Diffstat (limited to 'Source/WebKit/android')
13 files changed, 187 insertions, 18 deletions
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/EditorClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp index d7bfd4b..2667b71 100644 --- a/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp +++ b/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp @@ -267,7 +267,7 @@ void EditorClientAndroid::willSetInputMethodState() notImplemented(); } -void EditorClientAndroid::requestCheckingOfString(SpellChecker*, int, const String&) {} +void EditorClientAndroid::requestCheckingOfString(SpellChecker*, int, TextCheckingTypeMask, const String&) {} #if ENABLE(WEB_AUTOFILL) WebAutoFill* EditorClientAndroid::getAutoFill() diff --git a/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.h b/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.h index ab8d253..9bf6e1f 100644 --- a/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.h +++ b/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.h @@ -115,7 +115,7 @@ public: virtual void getGuessesForWord(const String&, const String& context, WTF::Vector<String>& guesses); virtual void willSetInputMethodState(); virtual void setInputMethodState(bool); - virtual void requestCheckingOfString(SpellChecker*, int, const String&); + virtual void requestCheckingOfString(SpellChecker*, int, TextCheckingTypeMask, const String&); virtual TextCheckerClient* textChecker() { return this; } diff --git a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp index 8d75dfc..99f34d5 100644 --- a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp +++ b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp @@ -287,12 +287,13 @@ void FrameLoaderClientAndroid::dispatchDidStartProvisionalLoad() { notImplemented(); } -void FrameLoaderClientAndroid::dispatchDidReceiveTitle(const String& title) { +void FrameLoaderClientAndroid::dispatchDidReceiveTitle(const StringWithDirection& title) { ASSERT(m_frame); // Used to check for FrameLoadTypeStandard but we only want to send the title for // the top frame and not sub-frames. + // FIXME: Use direction of title. if (!m_frame->tree() || !m_frame->tree()->parent()) { - m_webFrame->setTitle(title); + m_webFrame->setTitle(title.string()); } } @@ -883,7 +884,7 @@ PassRefPtr<DocumentLoader> FrameLoaderClientAndroid::createDocumentLoader( return loader.release(); } -void FrameLoaderClientAndroid::setTitle(const String& title, const KURL& url) { +void FrameLoaderClientAndroid::setTitle(const StringWithDirection& title, const KURL& url) { // Not needed. dispatchDidReceiveTitle is called immediately after this. // url is used to update the Apple port history items. verifiedOk(); diff --git a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h index 62ec9e0..e325e01 100644 --- a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h +++ b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h @@ -88,7 +88,7 @@ namespace android { virtual void dispatchWillClose(); virtual void dispatchDidReceiveIcon(); virtual void dispatchDidStartProvisionalLoad(); - virtual void dispatchDidReceiveTitle(const String& title); + virtual void dispatchDidReceiveTitle(const StringWithDirection& title); virtual void dispatchDidCommitLoad(); virtual void dispatchDidFailProvisionalLoad(const ResourceError&); virtual void dispatchDidFailLoad(const ResourceError&); @@ -167,7 +167,7 @@ namespace android { virtual void prepareForDataSourceReplacement(); virtual PassRefPtr<DocumentLoader> createDocumentLoader(const ResourceRequest&, const SubstituteData&); - virtual void setTitle(const String& title, const KURL&); + virtual void setTitle(const StringWithDirection& title, const KURL&); // This provides the userAgent to WebCore. It is used by WebCore to // populate navigator.userAgent and to set the HTTP header in 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..cd9cdba 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> @@ -112,7 +115,7 @@ #include <runtime/JSLock.h> #elif USE(V8) #include "JavaNPObjectV8.h" -#include "JavaInstanceV8.h" +#include "JavaInstanceJobjectV8.h" #include "V8Counters.h" #endif // USE(JSC) @@ -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) @@ -1708,7 +1733,11 @@ static jobject StringByEvaluatingJavaScriptFromString(JNIEnv *env, jobject obj, // Wrap the JavaInstance used when binding custom javascript interfaces. Use a // weak reference so that the gc can collect the WebView. Override virtualBegin // and virtualEnd and swap the weak reference for the real object. +#if USE(JSC) class WeakJavaInstance : public JavaInstance { +#elif USE(V8) +class WeakJavaInstance : public JavaInstanceJobject { +#endif public: #if USE(JSC) static PassRefPtr<WeakJavaInstance> create(jobject obj, PassRefPtr<RootObject> root) @@ -1728,7 +1757,7 @@ private: : JavaInstance(instance, rootObject) #elif USE(V8) WeakJavaInstance(jobject instance) - : JavaInstance(instance) + : JavaInstanceJobject(instance) #endif , m_beginEndDepth(0) { @@ -1752,7 +1781,7 @@ private: env->DeleteWeakGlobalRef(weak); } - virtual void virtualBegin() + virtual void begin() { if (m_beginEndDepth++ > 0) return; @@ -1767,15 +1796,15 @@ private: // Point to the real object m_instance->setInstance(m_realObject); // Call the base class method - INHERITED::virtualBegin(); + INHERITED::begin(); } - virtual void virtualEnd() + virtual void end() { if (--m_beginEndDepth > 0) return; // Call the base class method first to pop the local frame. - INHERITED::virtualEnd(); + INHERITED::end(); // Get rid of the local reference to the real object. getJNIEnv()->DeleteLocalRef(m_realObject); // Point back to the WeakReference. @@ -1783,7 +1812,11 @@ private: } private: +#if USE(JSC) typedef JavaInstance INHERITED; +#elif USE(V8) + typedef JavaInstanceJobject INHERITED; +#endif jobject m_realObject; jweak m_weakRef; // The current depth of nested calls to virtualBegin and virtualEnd. @@ -2107,6 +2140,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 +2240,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 +2308,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); diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index b0600ed..4e20ca1 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -434,8 +434,9 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m #endif #if USE(V8) - // FIXME: This is a work-around for a V8 bug regarding initializing the - // default isolate and should be removed when it is fixed. + // Static initialisation of certain important V8 static data gets performed at system startup when + // libwebcore gets loaded. We now need to associate the WebCore thread with V8 to complete + // initialisation. v8::V8::Initialize(); #endif } diff --git a/Source/WebKit/android/nav/SelectText.cpp b/Source/WebKit/android/nav/SelectText.cpp index f8ea799..c56c53c 100644 --- a/Source/WebKit/android/nav/SelectText.cpp +++ b/Source/WebKit/android/nav/SelectText.cpp @@ -27,6 +27,7 @@ #include "CachedPrefix.h" #include "BidiResolver.h" +#include "BidiRunList.h" #include "CachedRoot.h" #include "LayerAndroid.h" #include "ParseCanvas.h" @@ -98,13 +99,14 @@ void ReverseBidi(UChar* chars, int len) { result.reserveCapacity(len); TextRun run(chars, len); BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver; + BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs(); bidiResolver.setStatus(BidiStatus(LeftToRight, LeftToRight, LeftToRight, BidiContext::create(0, LeftToRight, false))); bidiResolver.setPosition(TextRunIterator(&run, 0)); bidiResolver.createBidiRunsForLine(TextRunIterator(&run, len)); - if (!bidiResolver.runCount()) + if (!bidiRuns.runCount()) return; - BidiCharacterRun* bidiRun = bidiResolver.firstRun(); + BidiCharacterRun* bidiRun = bidiRuns.firstRun(); while (bidiRun) { int bidiStart = bidiRun->start(); int bidiStop = bidiRun->stop(); @@ -133,7 +135,7 @@ void ReverseBidi(UChar* chars, int len) { } bidiRun = bidiRun->next(); } - bidiResolver.deleteRuns(); + bidiRuns.deleteRuns(); memcpy(chars, &result[0], len * sizeof(UChar)); } |