diff options
author | Ben Murdoch <benm@google.com> | 2011-05-13 16:40:46 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-05-16 11:35:03 +0100 |
commit | a2c606d1d8312a5d063e4a11e5911d9c8e4a3d19 (patch) | |
tree | 614d69ba96a23bc057e539a3c8a7d4961a68254b /Source/WebKit/android/jni/JavaBridge.cpp | |
parent | 65f03d4f644ce73618e5f4f50dd694b26f55ae12 (diff) | |
download | external_webkit-a2c606d1d8312a5d063e4a11e5911d9c8e4a3d19.zip external_webkit-a2c606d1d8312a5d063e4a11e5911d9c8e4a3d19.tar.gz external_webkit-a2c606d1d8312a5d063e4a11e5911d9c8e4a3d19.tar.bz2 |
Merge WebKit at r75993: Move WebKit/android files to Source
Change-Id: Ifa871f8320bdb3a09fe189fffecc23f702c394b9
Diffstat (limited to 'Source/WebKit/android/jni/JavaBridge.cpp')
-rw-r--r-- | Source/WebKit/android/jni/JavaBridge.cpp | 514 |
1 files changed, 514 insertions, 0 deletions
diff --git a/Source/WebKit/android/jni/JavaBridge.cpp b/Source/WebKit/android/jni/JavaBridge.cpp new file mode 100644 index 0000000..2fa12fc --- /dev/null +++ b/Source/WebKit/android/jni/JavaBridge.cpp @@ -0,0 +1,514 @@ +/* + * Copyright 2006, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "webcoreglue" + +#include "config.h" + +#include "MemoryCache.h" +#include "Connection.h" +#include "CookieClient.h" +#include "FileSystemClient.h" +#include "JavaSharedClient.h" +#include "KeyGeneratorClient.h" +#include "KURL.h" +#include "NetworkStateNotifier.h" +#include "PackageNotifier.h" +#include "Page.h" +#include "PluginClient.h" +#include "PluginDatabase.h" +#include "Timer.h" +#include "TimerClient.h" +#ifdef ANDROID_INSTRUMENT +#include "TimeCounter.h" +#endif +#include "WebCache.h" +#include "WebCoreJni.h" + +#include <JNIHelp.h> +#include <JNIUtility.h> +#include <SkUtils.h> +#include <jni.h> +#include <utils/misc.h> +#include <wtf/Platform.h> +#include <wtf/StdLibExtras.h> +#include <wtf/text/AtomicString.h> + +namespace android { + +// ---------------------------------------------------------------------------- + +static jfieldID gJavaBridge_ObjectID; + +// ---------------------------------------------------------------------------- + +class JavaBridge : public TimerClient, public CookieClient, public PluginClient, public KeyGeneratorClient, public FileSystemClient +{ +public: + JavaBridge(JNIEnv* env, jobject obj); + virtual ~JavaBridge(); + + /* + * WebCore -> Java API + */ + virtual void setSharedTimer(long long timemillis); + virtual void stopSharedTimer(); + + virtual void setCookies(WebCore::KURL const& url, WTF::String const& value); + virtual WTF::String cookies(WebCore::KURL const& url); + virtual bool cookiesEnabled(); + + virtual WTF::Vector<WTF::String> getPluginDirectories(); + virtual WTF::String getPluginSharedDataDirectory(); + + virtual WTF::Vector<String> getSupportedKeyStrengthList(); + virtual WTF::String getSignedPublicKeyAndChallengeString(unsigned index, + const WTF::String& challenge, const WebCore::KURL& url); + virtual WTF::String resolveFilePathForContentUri(const WTF::String& uri); + + //////////////////////////////////////////// + + virtual void setSharedTimerCallback(void (*f)()); + + //////////////////////////////////////////// + + virtual void signalServiceFuncPtrQueue(); + + // jni functions + static void Constructor(JNIEnv* env, jobject obj); + static void Finalize(JNIEnv* env, jobject obj); + static void SharedTimerFired(JNIEnv* env, jobject); + static void SetCacheSize(JNIEnv* env, jobject obj, jint bytes); + static void SetNetworkOnLine(JNIEnv* env, jobject obj, jboolean online); + static void SetNetworkType(JNIEnv* env, jobject obj, jstring type, jstring subtype); + static void SetDeferringTimers(JNIEnv* env, jobject obj, jboolean defer); + static void ServiceFuncPtrQueue(JNIEnv*); + static void UpdatePluginDirectories(JNIEnv* env, jobject obj, jobjectArray array, jboolean reload); + static void AddPackageNames(JNIEnv* env, jobject obj, jobject packageNames); + static void AddPackageName(JNIEnv* env, jobject obj, jstring packageName); + static void RemovePackageName(JNIEnv* env, jobject obj, jstring packageName); + static void UpdateProxy(JNIEnv* env, jobject obj, jstring newProxy); + + +private: + jweak mJavaObject; + jmethodID mSetSharedTimer; + jmethodID mStopSharedTimer; + jmethodID mSetCookies; + jmethodID mCookies; + jmethodID mCookiesEnabled; + jmethodID mGetPluginDirectories; + jmethodID mGetPluginSharedDataDirectory; + jmethodID mSignalFuncPtrQueue; + jmethodID mGetKeyStrengthList; + jmethodID mGetSignedPublicKey; + jmethodID mResolveFilePathForContentUri; + AutoJObject javaObject(JNIEnv* env) { return getRealObject(env, mJavaObject); } +}; + +static void (*sSharedTimerFiredCallback)(); + +JavaBridge::JavaBridge(JNIEnv* env, jobject obj) +{ + mJavaObject = env->NewWeakGlobalRef(obj); + jclass clazz = env->GetObjectClass(obj); + + mSetSharedTimer = env->GetMethodID(clazz, "setSharedTimer", "(J)V"); + mStopSharedTimer = env->GetMethodID(clazz, "stopSharedTimer", "()V"); + mSetCookies = env->GetMethodID(clazz, "setCookies", "(Ljava/lang/String;Ljava/lang/String;)V"); + mCookies = env->GetMethodID(clazz, "cookies", "(Ljava/lang/String;)Ljava/lang/String;"); + mCookiesEnabled = env->GetMethodID(clazz, "cookiesEnabled", "()Z"); + mGetPluginDirectories = env->GetMethodID(clazz, "getPluginDirectories", "()[Ljava/lang/String;"); + mGetPluginSharedDataDirectory = env->GetMethodID(clazz, "getPluginSharedDataDirectory", "()Ljava/lang/String;"); + mSignalFuncPtrQueue = env->GetMethodID(clazz, "signalServiceFuncPtrQueue", "()V"); + mGetKeyStrengthList = env->GetMethodID(clazz, "getKeyStrengthList", "()[Ljava/lang/String;"); + mGetSignedPublicKey = env->GetMethodID(clazz, "getSignedPublicKey", "(ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); + mResolveFilePathForContentUri = env->GetMethodID(clazz, "resolveFilePathForContentUri", "(Ljava/lang/String;)Ljava/lang/String;"); + env->DeleteLocalRef(clazz); + + LOG_ASSERT(mSetSharedTimer, "Could not find method setSharedTimer"); + LOG_ASSERT(mStopSharedTimer, "Could not find method stopSharedTimer"); + LOG_ASSERT(mSetCookies, "Could not find method setCookies"); + LOG_ASSERT(mCookies, "Could not find method cookies"); + LOG_ASSERT(mCookiesEnabled, "Could not find method cookiesEnabled"); + LOG_ASSERT(mGetPluginDirectories, "Could not find method getPluginDirectories"); + LOG_ASSERT(mGetPluginSharedDataDirectory, "Could not find method getPluginSharedDataDirectory"); + LOG_ASSERT(mGetKeyStrengthList, "Could not find method getKeyStrengthList"); + LOG_ASSERT(mGetSignedPublicKey, "Could not find method getSignedPublicKey"); + + JavaSharedClient::SetTimerClient(this); + JavaSharedClient::SetCookieClient(this); + JavaSharedClient::SetPluginClient(this); + JavaSharedClient::SetKeyGeneratorClient(this); + JavaSharedClient::SetFileSystemClient(this); +} + +JavaBridge::~JavaBridge() +{ + if (mJavaObject) { + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->DeleteWeakGlobalRef(mJavaObject); + mJavaObject = 0; + } + + JavaSharedClient::SetTimerClient(NULL); + JavaSharedClient::SetCookieClient(NULL); + JavaSharedClient::SetPluginClient(NULL); + JavaSharedClient::SetKeyGeneratorClient(NULL); + JavaSharedClient::SetFileSystemClient(NULL); +} + +void +JavaBridge::setSharedTimer(long long timemillis) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + AutoJObject obj = javaObject(env); + env->CallVoidMethod(obj.get(), mSetSharedTimer, timemillis); +} + +void +JavaBridge::stopSharedTimer() +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + AutoJObject obj = javaObject(env); + env->CallVoidMethod(obj.get(), mStopSharedTimer); +} + +void +JavaBridge::setCookies(WebCore::KURL const& url, WTF::String const& value) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + const WTF::String& urlStr = url.string(); + jstring jUrlStr = wtfStringToJstring(env, urlStr); + jstring jValueStr = wtfStringToJstring(env, value); + + AutoJObject obj = javaObject(env); + env->CallVoidMethod(obj.get(), mSetCookies, jUrlStr, jValueStr); + env->DeleteLocalRef(jUrlStr); + env->DeleteLocalRef(jValueStr); +} + +WTF::String +JavaBridge::cookies(WebCore::KURL const& url) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + const WTF::String& urlStr = url.string(); + jstring jUrlStr = wtfStringToJstring(env, urlStr); + + AutoJObject obj = javaObject(env); + jstring string = (jstring)(env->CallObjectMethod(obj.get(), mCookies, jUrlStr)); + + WTF::String ret = jstringToWtfString(env, string); + env->DeleteLocalRef(jUrlStr); + env->DeleteLocalRef(string); + return ret; +} + +bool +JavaBridge::cookiesEnabled() +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + AutoJObject obj = javaObject(env); + jboolean ret = env->CallBooleanMethod(obj.get(), mCookiesEnabled); + return (ret != 0); +} + +WTF::Vector<WTF::String> +JavaBridge::getPluginDirectories() +{ + WTF::Vector<WTF::String> directories; + JNIEnv* env = JSC::Bindings::getJNIEnv(); + AutoJObject obj = javaObject(env); + jobjectArray array = (jobjectArray) + env->CallObjectMethod(obj.get(), mGetPluginDirectories); + int count = env->GetArrayLength(array); + for (int i = 0; i < count; i++) { + jstring dir = (jstring) env->GetObjectArrayElement(array, i); + directories.append(jstringToWtfString(env, dir)); + env->DeleteLocalRef(dir); + } + env->DeleteLocalRef(array); + checkException(env); + return directories; +} + +WTF::String +JavaBridge::getPluginSharedDataDirectory() +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + AutoJObject obj = javaObject(env); + jstring ret = (jstring)env->CallObjectMethod(obj.get(), mGetPluginSharedDataDirectory); + WTF::String path = jstringToWtfString(env, ret); + checkException(env); + return path; +} + +void +JavaBridge::setSharedTimerCallback(void (*f)()) +{ + LOG_ASSERT(!sSharedTimerFiredCallback || sSharedTimerFiredCallback==f, + "Shared timer callback may already be set or null!"); + + sSharedTimerFiredCallback = f; +} + +void JavaBridge::signalServiceFuncPtrQueue() +{ + // In order to signal the main thread we must go through JNI. This + // is the only usage on most threads, so we need to ensure a JNI + // environment is setup. + JNIEnv* env = JSC::Bindings::getJNIEnv(); + AutoJObject obj = javaObject(env); + env->CallVoidMethod(obj.get(), mSignalFuncPtrQueue); +} + +WTF::Vector<WTF::String>JavaBridge::getSupportedKeyStrengthList() { + WTF::Vector<WTF::String> list; + JNIEnv* env = JSC::Bindings::getJNIEnv(); + AutoJObject obj = javaObject(env); + jobjectArray array = (jobjectArray) env->CallObjectMethod(obj.get(), + mGetKeyStrengthList); + int count = env->GetArrayLength(array); + for (int i = 0; i < count; ++i) { + jstring keyStrength = (jstring) env->GetObjectArrayElement(array, i); + list.append(jstringToWtfString(env, keyStrength)); + env->DeleteLocalRef(keyStrength); + } + env->DeleteLocalRef(array); + checkException(env); + return list; +} + +WTF::String JavaBridge::getSignedPublicKeyAndChallengeString(unsigned index, + const WTF::String& challenge, const WebCore::KURL& url) { + JNIEnv* env = JSC::Bindings::getJNIEnv(); + jstring jChallenge = wtfStringToJstring(env, challenge); + const WTF::String& urlStr = url.string(); + jstring jUrl = wtfStringToJstring(env, urlStr); + AutoJObject obj = javaObject(env); + jstring key = (jstring) env->CallObjectMethod(obj.get(), + mGetSignedPublicKey, index, jChallenge, jUrl); + WTF::String ret = jstringToWtfString(env, key); + env->DeleteLocalRef(jChallenge); + env->DeleteLocalRef(jUrl); + env->DeleteLocalRef(key); + return ret; +} + +WTF::String JavaBridge::resolveFilePathForContentUri(const WTF::String& uri) { + JNIEnv* env = JSC::Bindings::getJNIEnv(); + jstring jUri = wtfStringToJstring(env, uri); + AutoJObject obj = javaObject(env); + jstring path = static_cast<jstring>(env->CallObjectMethod(obj.get(), mResolveFilePathForContentUri, jUri)); + WTF::String ret = jstringToWtfString(env, path); + env->DeleteLocalRef(jUri); + env->DeleteLocalRef(path); + return ret; +} + +// ---------------------------------------------------------------------------- + +void JavaBridge::Constructor(JNIEnv* env, jobject obj) +{ + JavaBridge* javaBridge = new JavaBridge(env, obj); + env->SetIntField(obj, gJavaBridge_ObjectID, (jint)javaBridge); +} + +void JavaBridge::Finalize(JNIEnv* env, jobject obj) +{ + JavaBridge* javaBridge = (JavaBridge*) + (env->GetIntField(obj, gJavaBridge_ObjectID)); + LOG_ASSERT(javaBridge, "Finalize should not be called twice for the same java bridge!"); + LOGV("webcore_javabridge::nativeFinalize(%p)\n", javaBridge); + delete javaBridge; + env->SetIntField(obj, gJavaBridge_ObjectID, 0); +} + +// we don't use the java bridge object, as we're just looking at a global +void JavaBridge::SharedTimerFired(JNIEnv* env, jobject) +{ + if (sSharedTimerFiredCallback) + { +#ifdef ANDROID_INSTRUMENT + TimeCounter::start(TimeCounter::SharedTimerTimeCounter); +#endif + SkAutoMemoryUsageProbe mup("JavaBridge::sharedTimerFired"); + sSharedTimerFiredCallback(); +#ifdef ANDROID_INSTRUMENT + TimeCounter::record(TimeCounter::SharedTimerTimeCounter, __FUNCTION__); +#endif + } +} + +void JavaBridge::SetCacheSize(JNIEnv* env, jobject obj, jint bytes) +{ + WebCore::cache()->setCapacities(0, bytes/2, bytes); +} + +void JavaBridge::SetNetworkOnLine(JNIEnv* env, jobject obj, jboolean online) +{ + WebCore::networkStateNotifier().networkStateChange(online); +} + +void JavaBridge::SetNetworkType(JNIEnv* env, jobject obj, jstring javatype, jstring javasubtype) +{ + DEFINE_STATIC_LOCAL(AtomicString, wifi, ("wifi")); + DEFINE_STATIC_LOCAL(AtomicString, mobile, ("mobile")); + DEFINE_STATIC_LOCAL(AtomicString, mobileSupl, ("mobile_supl")); + DEFINE_STATIC_LOCAL(AtomicString, gprs, ("gprs")); + DEFINE_STATIC_LOCAL(AtomicString, edge, ("edge")); + DEFINE_STATIC_LOCAL(AtomicString, umts, ("umts")); + + String type = jstringToWtfString(env, javatype); + String subtype = jstringToWtfString(env, javasubtype); + Connection::ConnectionType connectionType = Connection::UNKNOWN; + if (type == wifi) + connectionType = Connection::WIFI; + else if (type == mobile || type == mobileSupl) { + if (subtype == edge || subtype == gprs) + connectionType = Connection::CELL_2G; + else if (subtype == umts) + connectionType = Connection::CELL_3G; + } + WebCore::networkStateNotifier().networkTypeChange(connectionType); +} + +void JavaBridge::ServiceFuncPtrQueue(JNIEnv*) +{ + JavaSharedClient::ServiceFunctionPtrQueue(); +} + +void JavaBridge::UpdatePluginDirectories(JNIEnv* env, jobject obj, + jobjectArray array, jboolean reload) { + WTF::Vector<WTF::String> directories; + int count = env->GetArrayLength(array); + for (int i = 0; i < count; i++) { + jstring dir = (jstring) env->GetObjectArrayElement(array, i); + directories.append(jstringToWtfString(env, dir)); + env->DeleteLocalRef(dir); + } + checkException(env); + WebCore::PluginDatabase *pluginDatabase = + WebCore::PluginDatabase::installedPlugins(); + pluginDatabase->setPluginDirectories(directories); + // refreshPlugins() should refresh both PluginDatabase and Page's PluginData + WebCore::Page::refreshPlugins(reload); +} + +void JavaBridge::AddPackageNames(JNIEnv* env, jobject obj, jobject packageNames) +{ + if (!packageNames) + return; + + // dalvikvm will raise exception if any of these fail + jclass setClass = env->FindClass("java/util/Set"); + jmethodID iterator = env->GetMethodID(setClass, "iterator", + "()Ljava/util/Iterator;"); + jobject iter = env->CallObjectMethod(packageNames, iterator); + + jclass iteratorClass = env->FindClass("java/util/Iterator"); + jmethodID hasNext = env->GetMethodID(iteratorClass, "hasNext", "()Z"); + jmethodID next = env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;"); + + HashSet<WTF::String> namesSet; + while (env->CallBooleanMethod(iter, hasNext)) { + jstring name = static_cast<jstring>(env->CallObjectMethod(iter, next)); + namesSet.add(jstringToWtfString(env, name)); + env->DeleteLocalRef(name); + } + + packageNotifier().addPackageNames(namesSet); + + env->DeleteLocalRef(iteratorClass); + env->DeleteLocalRef(iter); + env->DeleteLocalRef(setClass); +} + +void JavaBridge::AddPackageName(JNIEnv* env, jobject obj, jstring packageName) +{ + packageNotifier().addPackageName(jstringToWtfString(env, packageName)); +} + +void JavaBridge::RemovePackageName(JNIEnv* env, jobject obj, jstring packageName) +{ + packageNotifier().removePackageName(jstringToWtfString(env, packageName)); +} + +void JavaBridge::UpdateProxy(JNIEnv* env, jobject obj, jstring newProxy) +{ +#if USE(CHROME_NETWORK_STACK) + std::string proxy = jstringToStdString(env, newProxy); + WebCache::get(false)->proxy()->UpdateProxySettings(proxy); + WebCache::get(true)->proxy()->UpdateProxySettings(proxy); +#endif +} + + +// ---------------------------------------------------------------------------- + +/* + * JNI registration. + */ +static JNINativeMethod gWebCoreJavaBridgeMethods[] = { + /* name, signature, funcPtr */ + { "nativeConstructor", "()V", + (void*) JavaBridge::Constructor }, + { "nativeFinalize", "()V", + (void*) JavaBridge::Finalize }, + { "sharedTimerFired", "()V", + (void*) JavaBridge::SharedTimerFired }, + { "setCacheSize", "(I)V", + (void*) JavaBridge::SetCacheSize }, + { "setNetworkOnLine", "(Z)V", + (void*) JavaBridge::SetNetworkOnLine }, + { "setNetworkType", "(Ljava/lang/String;Ljava/lang/String;)V", + (void*) JavaBridge::SetNetworkType }, + { "nativeServiceFuncPtrQueue", "()V", + (void*) JavaBridge::ServiceFuncPtrQueue }, + { "nativeUpdatePluginDirectories", "([Ljava/lang/String;Z)V", + (void*) JavaBridge::UpdatePluginDirectories }, + { "addPackageNames", "(Ljava/util/Set;)V", + (void*) JavaBridge::AddPackageNames }, + { "addPackageName", "(Ljava/lang/String;)V", + (void*) JavaBridge::AddPackageName }, + { "removePackageName", "(Ljava/lang/String;)V", + (void*) JavaBridge::RemovePackageName }, + { "updateProxy", "(Ljava/lang/String;)V", + (void*) JavaBridge::UpdateProxy } +}; + +int registerJavaBridge(JNIEnv* env) +{ + jclass javaBridge = env->FindClass("android/webkit/JWebCoreJavaBridge"); + LOG_FATAL_IF(javaBridge == NULL, "Unable to find class android/webkit/JWebCoreJavaBridge"); + gJavaBridge_ObjectID = env->GetFieldID(javaBridge, "mNativeBridge", "I"); + LOG_FATAL_IF(gJavaBridge_ObjectID == NULL, "Unable to find android/webkit/JWebCoreJavaBridge.mNativeBridge"); + env->DeleteLocalRef(javaBridge); + + return jniRegisterNativeMethods(env, "android/webkit/JWebCoreJavaBridge", + gWebCoreJavaBridgeMethods, NELEM(gWebCoreJavaBridgeMethods)); +} + +} /* namespace android */ |