JavaBridge.cpp revision 21afc171e6a91d82acfe777acd1531d0105e458d
1/* 2 * Copyright 2006, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#define LOG_TAG "webcoreglue" 27 28#include <config.h> 29#include <wtf/Platform.h> 30 31#include "Cache.h" 32#include "CookieClient.h" 33#include "JavaSharedClient.h" 34#include "KURL.h" 35#include "NetworkStateNotifier.h" 36#include "Timer.h" 37#include "TimerClient.h" 38#include "jni_utility.h" 39#include "WebCoreJni.h" 40 41#ifdef ANDROID_INSTRUMENT 42#include "TimeCounter.h" 43#endif 44 45#include <jni.h> 46#include <JNIHelp.h> 47#include <SkUtils.h> 48#include <utils/misc.h> 49 50namespace android { 51 52// ---------------------------------------------------------------------------- 53 54static jfieldID gJavaBridge_ObjectID; 55 56// ---------------------------------------------------------------------------- 57 58class JavaBridge : public TimerClient, public CookieClient 59{ 60public: 61 JavaBridge(JNIEnv* env, jobject obj); 62 virtual ~JavaBridge(); 63 64 /* 65 * WebCore -> Java API 66 */ 67 virtual void setSharedTimer(long long timemillis); 68 virtual void stopSharedTimer(); 69 70 virtual void setCookies(WebCore::KURL const& url, WebCore::KURL const& docURL, WebCore::String const& value); 71 virtual WebCore::String cookies(WebCore::KURL const& url); 72 virtual bool cookiesEnabled(); 73 74 //////////////////////////////////////////// 75 76 virtual void setSharedTimerCallback(void (*f)()); 77 78 //////////////////////////////////////////// 79 80 void signalServiceFuncPtrQueue(); 81 82 // jni functions 83 static void Constructor(JNIEnv* env, jobject obj); 84 static void Finalize(JNIEnv* env, jobject obj); 85 static void SharedTimerFired(JNIEnv* env, jobject); 86 static void SetCacheSize(JNIEnv* env, jobject obj, jint bytes); 87 static void SetNetworkOnLine(JNIEnv* env, jobject obj, jboolean online); 88 static void SetDeferringTimers(JNIEnv* env, jobject obj, jboolean defer); 89 static void ServiceFuncPtrQueue(JNIEnv*); 90 91private: 92 jobject mJavaObject; 93 jmethodID mSetSharedTimer; 94 jmethodID mStopSharedTimer; 95 jmethodID mSetCookies; 96 jmethodID mCookies; 97 jmethodID mCookiesEnabled; 98 jmethodID mSignalFuncPtrQueue; 99}; 100 101static void (*sSharedTimerFiredCallback)(); 102static JavaBridge* gJavaBridge; 103 104JavaBridge::JavaBridge(JNIEnv* env, jobject obj) 105{ 106 mJavaObject = adoptGlobalRef(env, obj); 107 jclass clazz = env->GetObjectClass(obj); 108 109 mSetSharedTimer = env->GetMethodID(clazz, "setSharedTimer", "(J)V"); 110 mStopSharedTimer = env->GetMethodID(clazz, "stopSharedTimer", "()V"); 111 mSetCookies = env->GetMethodID(clazz, "setCookies", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); 112 mCookies = env->GetMethodID(clazz, "cookies", "(Ljava/lang/String;)Ljava/lang/String;"); 113 mCookiesEnabled = env->GetMethodID(clazz, "cookiesEnabled", "()Z"); 114 mSignalFuncPtrQueue = env->GetMethodID(clazz, "signalServiceFuncPtrQueue", "()V"); 115 116 LOG_ASSERT(mSetSharedTimer, "Could not find method setSharedTimer"); 117 LOG_ASSERT(mStopSharedTimer, "Could not find method stopSharedTimer"); 118 LOG_ASSERT(mSetCookies, "Could not find method setCookies"); 119 LOG_ASSERT(mCookies, "Could not find method cookies"); 120 LOG_ASSERT(mCookiesEnabled, "Could not find method cookiesEnabled"); 121 122 JavaSharedClient::SetTimerClient(this); 123 JavaSharedClient::SetCookieClient(this); 124 gJavaBridge = this; 125} 126 127JavaBridge::~JavaBridge() 128{ 129 if (mJavaObject) { 130 JNIEnv* env = JSC::Bindings::getJNIEnv(); 131 env->DeleteGlobalRef(mJavaObject); 132 mJavaObject = 0; 133 } 134 135 JavaSharedClient::SetTimerClient(NULL); 136 JavaSharedClient::SetCookieClient(NULL); 137} 138 139void 140JavaBridge::setSharedTimer(long long timemillis) 141{ 142 JNIEnv* env = JSC::Bindings::getJNIEnv(); 143 AutoJObject obj = getRealObject(env, mJavaObject); 144 env->CallVoidMethod(obj.get(), mSetSharedTimer, timemillis); 145} 146 147void 148JavaBridge::stopSharedTimer() 149{ 150 JNIEnv* env = JSC::Bindings::getJNIEnv(); 151 AutoJObject obj = getRealObject(env, mJavaObject); 152 env->CallVoidMethod(obj.get(), mStopSharedTimer); 153} 154 155void 156JavaBridge::setCookies(WebCore::KURL const& url, WebCore::KURL const& docUrl, WebCore::String const& value) 157{ 158 JNIEnv* env = JSC::Bindings::getJNIEnv(); 159 const WebCore::String& urlStr = url.string(); 160 jstring jUrlStr = env->NewString(urlStr.characters(), urlStr.length()); 161 const WebCore::String& docUrlStr = docUrl.string(); 162 jstring jDocUrlStr = env->NewString(docUrlStr.characters(), docUrlStr.length()); 163 jstring jValueStr = env->NewString(value.characters(), value.length()); 164 165 AutoJObject obj = getRealObject(env, mJavaObject); 166 env->CallVoidMethod(obj.get(), mSetCookies, jUrlStr, jDocUrlStr, jValueStr); 167 env->DeleteLocalRef(jUrlStr); 168 env->DeleteLocalRef(jDocUrlStr); 169 env->DeleteLocalRef(jValueStr); 170} 171 172WebCore::String 173JavaBridge::cookies(WebCore::KURL const& url) 174{ 175 JNIEnv* env = JSC::Bindings::getJNIEnv(); 176 const WebCore::String& urlStr = url.string(); 177 jstring jUrlStr = env->NewString(urlStr.characters(), urlStr.length()); 178 179 AutoJObject obj = getRealObject(env, mJavaObject); 180 jstring string = (jstring)(env->CallObjectMethod(obj.get(), mCookies, jUrlStr)); 181 182 WebCore::String ret = to_string(env, string); 183 env->DeleteLocalRef(jUrlStr); 184 env->DeleteLocalRef(string); 185 return ret; 186} 187 188bool 189JavaBridge::cookiesEnabled() 190{ 191 JNIEnv* env = JSC::Bindings::getJNIEnv(); 192 AutoJObject obj = getRealObject(env, mJavaObject); 193 jboolean ret = env->CallBooleanMethod(obj.get(), mCookiesEnabled); 194 return (ret != 0); 195} 196 197void 198JavaBridge::setSharedTimerCallback(void (*f)()) 199{ 200 LOG_ASSERT(!sSharedTimerFiredCallback || sSharedTimerFiredCallback==f, 201 "Shared timer callback may already be set or null!"); 202 203 sSharedTimerFiredCallback = f; 204} 205 206void JavaBridge::signalServiceFuncPtrQueue() 207{ 208 // In order to signal the main thread we must go through JNI. This 209 // is the only usage on most threads, so we need to ensure a JNI 210 // environment is setup. 211 JNIEnv* env = JSC::Bindings::getJNIEnv(); 212 AutoJObject obj = getRealObject(env, mJavaObject); 213 env->CallVoidMethod(obj.get(), mSignalFuncPtrQueue); 214} 215 216// ---------------------------------------------------------------------------- 217 218// visible to Shared 219void AndroidSignalServiceFuncPtrQueue() 220{ 221 gJavaBridge->signalServiceFuncPtrQueue(); 222} 223 224// ---------------------------------------------------------------------------- 225 226void JavaBridge::Constructor(JNIEnv* env, jobject obj) 227{ 228 JavaBridge* javaBridge = new JavaBridge(env, obj); 229 env->SetIntField(obj, gJavaBridge_ObjectID, (jint)javaBridge); 230} 231 232void JavaBridge::Finalize(JNIEnv* env, jobject obj) 233{ 234 JavaBridge* javaBridge = (JavaBridge*) 235 (env->GetIntField(obj, gJavaBridge_ObjectID)); 236 LOG_ASSERT(javaBridge, "Finalize should not be called twice for the same java bridge!"); 237 LOGV("webcore_javabridge::nativeFinalize(%p)\n", javaBridge); 238 delete javaBridge; 239 env->SetIntField(obj, gJavaBridge_ObjectID, 0); 240} 241 242// we don't use the java bridge object, as we're just looking at a global 243void JavaBridge::SharedTimerFired(JNIEnv* env, jobject) 244{ 245 if (sSharedTimerFiredCallback) 246 { 247#ifdef ANDROID_INSTRUMENT 248 TimeCounter::start(TimeCounter::SharedTimerTimeCounter); 249#endif 250 SkAutoMemoryUsageProbe mup("JavaBridge::sharedTimerFired"); 251 sSharedTimerFiredCallback(); 252#ifdef ANDROID_INSTRUMENT 253 TimeCounter::record(TimeCounter::SharedTimerTimeCounter, __FUNCTION__); 254#endif 255 } 256} 257 258void JavaBridge::SetCacheSize(JNIEnv* env, jobject obj, jint bytes) 259{ 260 WebCore::cache()->setCapacities(0, bytes/2, bytes); 261} 262 263void JavaBridge::SetNetworkOnLine(JNIEnv* env, jobject obj, jboolean online) 264{ 265 WebCore::networkStateNotifier().networkStateChange(online); 266} 267 268void JavaBridge::SetDeferringTimers(JNIEnv* env, jobject obj, jboolean defer) 269{ 270 WebCore::setDeferringTimers(defer); 271} 272 273void JavaBridge::ServiceFuncPtrQueue(JNIEnv*) 274{ 275 JavaSharedClient::ServiceFunctionPtrQueue(); 276} 277 278// ---------------------------------------------------------------------------- 279 280/* 281 * JNI registration. 282 */ 283static JNINativeMethod gWebCoreJavaBridgeMethods[] = { 284 /* name, signature, funcPtr */ 285 { "nativeConstructor", "()V", 286 (void*) JavaBridge::Constructor }, 287 { "nativeFinalize", "()V", 288 (void*) JavaBridge::Finalize }, 289 { "sharedTimerFired", "()V", 290 (void*) JavaBridge::SharedTimerFired }, 291 { "setCacheSize", "(I)V", 292 (void*) JavaBridge::SetCacheSize }, 293 { "setNetworkOnLine", "(Z)V", 294 (void*) JavaBridge::SetNetworkOnLine }, 295 { "setDeferringTimers", "(Z)V", 296 (void*) JavaBridge::SetDeferringTimers }, 297 { "nativeServiceFuncPtrQueue", "()V", 298 (void*) JavaBridge::ServiceFuncPtrQueue }, 299}; 300 301int register_javabridge(JNIEnv* env) 302{ 303 jclass javaBridge = env->FindClass("android/webkit/JWebCoreJavaBridge"); 304 LOG_FATAL_IF(javaBridge == NULL, "Unable to find class android/webkit/JWebCoreJavaBridge"); 305 gJavaBridge_ObjectID = env->GetFieldID(javaBridge, "mNativeBridge", "I"); 306 LOG_FATAL_IF(gJavaBridge_ObjectID == NULL, "Unable to find android/webkit/JWebCoreJavaBridge.mNativeBridge"); 307 308 return jniRegisterNativeMethods(env, "android/webkit/JWebCoreJavaBridge", 309 gWebCoreJavaBridgeMethods, NELEM(gWebCoreJavaBridgeMethods)); 310} 311 312} /* namespace android */ 313