Home | History | Annotate | Download | only in jni
      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 THE COPYRIGHT OWNER 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 
     30 #include "MemoryCache.h"
     31 #include "Connection.h"
     32 #include "CookieClient.h"
     33 #include "FileSystemClient.h"
     34 #include "JavaSharedClient.h"
     35 #include "KeyGeneratorClient.h"
     36 #include "KURL.h"
     37 #include "NetworkStateNotifier.h"
     38 #include "PackageNotifier.h"
     39 #include "Page.h"
     40 #include "PluginClient.h"
     41 #include "PluginDatabase.h"
     42 #include "Timer.h"
     43 #include "TimerClient.h"
     44 #ifdef ANDROID_INSTRUMENT
     45 #include "TimeCounter.h"
     46 #endif
     47 #include "WebCache.h"
     48 #include "WebCoreJni.h"
     49 
     50 #include <JNIHelp.h>
     51 #include <JNIUtility.h>
     52 #include <SkUtils.h>
     53 #include <jni.h>
     54 #include <utils/misc.h>
     55 #include <wtf/Platform.h>
     56 #include <wtf/StdLibExtras.h>
     57 #include <wtf/text/AtomicString.h>
     58 
     59 namespace android {
     60 
     61 // ----------------------------------------------------------------------------
     62 
     63 static jfieldID gJavaBridge_ObjectID;
     64 
     65 // ----------------------------------------------------------------------------
     66 
     67 class JavaBridge : public TimerClient, public CookieClient, public PluginClient, public KeyGeneratorClient, public FileSystemClient
     68 {
     69 public:
     70     JavaBridge(JNIEnv* env, jobject obj);
     71     virtual ~JavaBridge();
     72 
     73     /*
     74      * WebCore -> Java API
     75      */
     76     virtual void setSharedTimer(long long timemillis);
     77     virtual void stopSharedTimer();
     78 
     79     virtual void setCookies(WebCore::KURL const& url, WTF::String const& value);
     80     virtual WTF::String cookies(WebCore::KURL const& url);
     81     virtual bool cookiesEnabled();
     82 
     83     virtual WTF::Vector<WTF::String> getPluginDirectories();
     84     virtual WTF::String getPluginSharedDataDirectory();
     85 
     86     virtual WTF::Vector<String> getSupportedKeyStrengthList();
     87     virtual WTF::String getSignedPublicKeyAndChallengeString(unsigned index,
     88             const WTF::String& challenge, const WebCore::KURL& url);
     89     virtual WTF::String resolveFilePathForContentUri(const WTF::String& uri);
     90 
     91     ////////////////////////////////////////////
     92 
     93     virtual void setSharedTimerCallback(void (*f)());
     94 
     95     ////////////////////////////////////////////
     96 
     97     virtual void signalServiceFuncPtrQueue();
     98 
     99     // jni functions
    100     static void Constructor(JNIEnv* env, jobject obj);
    101     static void Finalize(JNIEnv* env, jobject obj);
    102     static void SharedTimerFired(JNIEnv* env, jobject);
    103     static void SetCacheSize(JNIEnv* env, jobject obj, jint bytes);
    104     static void SetNetworkOnLine(JNIEnv* env, jobject obj, jboolean online);
    105     static void SetNetworkType(JNIEnv* env, jobject obj, jstring type, jstring subtype);
    106     static void SetDeferringTimers(JNIEnv* env, jobject obj, jboolean defer);
    107     static void ServiceFuncPtrQueue(JNIEnv*);
    108     static void UpdatePluginDirectories(JNIEnv* env, jobject obj, jobjectArray array, jboolean reload);
    109     static void AddPackageNames(JNIEnv* env, jobject obj, jobject packageNames);
    110     static void AddPackageName(JNIEnv* env, jobject obj, jstring packageName);
    111     static void RemovePackageName(JNIEnv* env, jobject obj, jstring packageName);
    112     static void UpdateProxy(JNIEnv* env, jobject obj, jstring newProxy, jstring newExList);
    113 
    114 
    115 private:
    116     jweak       mJavaObject;
    117     jmethodID   mSetSharedTimer;
    118     jmethodID   mStopSharedTimer;
    119     jmethodID   mSetCookies;
    120     jmethodID   mCookies;
    121     jmethodID   mCookiesEnabled;
    122     jmethodID   mGetPluginDirectories;
    123     jmethodID   mGetPluginSharedDataDirectory;
    124     jmethodID   mSignalFuncPtrQueue;
    125     jmethodID   mGetKeyStrengthList;
    126     jmethodID   mGetSignedPublicKey;
    127     jmethodID   mResolveFilePathForContentUri;
    128     AutoJObject javaObject(JNIEnv* env) { return getRealObject(env, mJavaObject); }
    129 };
    130 
    131 static void (*sSharedTimerFiredCallback)();
    132 
    133 JavaBridge::JavaBridge(JNIEnv* env, jobject obj)
    134 {
    135     mJavaObject = env->NewWeakGlobalRef(obj);
    136     jclass clazz = env->GetObjectClass(obj);
    137 
    138     mSetSharedTimer = env->GetMethodID(clazz, "setSharedTimer", "(J)V");
    139     mStopSharedTimer = env->GetMethodID(clazz, "stopSharedTimer", "()V");
    140     mSetCookies = env->GetMethodID(clazz, "setCookies", "(Ljava/lang/String;Ljava/lang/String;)V");
    141     mCookies = env->GetMethodID(clazz, "cookies", "(Ljava/lang/String;)Ljava/lang/String;");
    142     mCookiesEnabled = env->GetMethodID(clazz, "cookiesEnabled", "()Z");
    143     mGetPluginDirectories = env->GetMethodID(clazz, "getPluginDirectories", "()[Ljava/lang/String;");
    144     mGetPluginSharedDataDirectory = env->GetMethodID(clazz, "getPluginSharedDataDirectory", "()Ljava/lang/String;");
    145     mSignalFuncPtrQueue = env->GetMethodID(clazz, "signalServiceFuncPtrQueue", "()V");
    146     mGetKeyStrengthList = env->GetMethodID(clazz, "getKeyStrengthList", "()[Ljava/lang/String;");
    147     mGetSignedPublicKey = env->GetMethodID(clazz, "getSignedPublicKey", "(ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
    148     mResolveFilePathForContentUri = env->GetMethodID(clazz, "resolveFilePathForContentUri", "(Ljava/lang/String;)Ljava/lang/String;");
    149     env->DeleteLocalRef(clazz);
    150 
    151     LOG_ASSERT(mSetSharedTimer, "Could not find method setSharedTimer");
    152     LOG_ASSERT(mStopSharedTimer, "Could not find method stopSharedTimer");
    153     LOG_ASSERT(mSetCookies, "Could not find method setCookies");
    154     LOG_ASSERT(mCookies, "Could not find method cookies");
    155     LOG_ASSERT(mCookiesEnabled, "Could not find method cookiesEnabled");
    156     LOG_ASSERT(mGetPluginDirectories, "Could not find method getPluginDirectories");
    157     LOG_ASSERT(mGetPluginSharedDataDirectory, "Could not find method getPluginSharedDataDirectory");
    158     LOG_ASSERT(mGetKeyStrengthList, "Could not find method getKeyStrengthList");
    159     LOG_ASSERT(mGetSignedPublicKey, "Could not find method getSignedPublicKey");
    160 
    161     JavaSharedClient::SetTimerClient(this);
    162     JavaSharedClient::SetCookieClient(this);
    163     JavaSharedClient::SetPluginClient(this);
    164     JavaSharedClient::SetKeyGeneratorClient(this);
    165     JavaSharedClient::SetFileSystemClient(this);
    166 }
    167 
    168 JavaBridge::~JavaBridge()
    169 {
    170     if (mJavaObject) {
    171         JNIEnv* env = JSC::Bindings::getJNIEnv();
    172         env->DeleteWeakGlobalRef(mJavaObject);
    173         mJavaObject = 0;
    174     }
    175 
    176     JavaSharedClient::SetTimerClient(NULL);
    177     JavaSharedClient::SetCookieClient(NULL);
    178     JavaSharedClient::SetPluginClient(NULL);
    179     JavaSharedClient::SetKeyGeneratorClient(NULL);
    180     JavaSharedClient::SetFileSystemClient(NULL);
    181 }
    182 
    183 void
    184 JavaBridge::setSharedTimer(long long timemillis)
    185 {
    186     JNIEnv* env = JSC::Bindings::getJNIEnv();
    187     AutoJObject obj = javaObject(env);
    188     if (!obj.get())
    189         return;
    190     env->CallVoidMethod(obj.get(), mSetSharedTimer, timemillis);
    191 }
    192 
    193 void
    194 JavaBridge::stopSharedTimer()
    195 {
    196     JNIEnv* env = JSC::Bindings::getJNIEnv();
    197     AutoJObject obj = javaObject(env);
    198     if (!obj.get())
    199         return;
    200     env->CallVoidMethod(obj.get(), mStopSharedTimer);
    201 }
    202 
    203 void
    204 JavaBridge::setCookies(WebCore::KURL const& url, WTF::String const& value)
    205 {
    206     JNIEnv* env = JSC::Bindings::getJNIEnv();
    207     AutoJObject obj = javaObject(env);
    208     if (!obj.get())
    209         return;
    210 
    211     const WTF::String& urlStr = url.string();
    212     jstring jUrlStr = wtfStringToJstring(env, urlStr);
    213     jstring jValueStr = wtfStringToJstring(env, value);
    214 
    215     env->CallVoidMethod(obj.get(), mSetCookies, jUrlStr, jValueStr);
    216     env->DeleteLocalRef(jUrlStr);
    217     env->DeleteLocalRef(jValueStr);
    218 }
    219 
    220 WTF::String
    221 JavaBridge::cookies(WebCore::KURL const& url)
    222 {
    223     JNIEnv* env = JSC::Bindings::getJNIEnv();
    224     AutoJObject obj = javaObject(env);
    225     if (!obj.get())
    226         return String();
    227 
    228     const WTF::String& urlStr = url.string();
    229     jstring jUrlStr = wtfStringToJstring(env, urlStr);
    230     jstring string = (jstring)(env->CallObjectMethod(obj.get(), mCookies, jUrlStr));
    231 
    232     WTF::String ret = jstringToWtfString(env, string);
    233     env->DeleteLocalRef(jUrlStr);
    234     env->DeleteLocalRef(string);
    235     return ret;
    236 }
    237 
    238 bool
    239 JavaBridge::cookiesEnabled()
    240 {
    241     JNIEnv* env = JSC::Bindings::getJNIEnv();
    242     AutoJObject obj = javaObject(env);
    243     if (!obj.get())
    244         return false;
    245     jboolean ret = env->CallBooleanMethod(obj.get(), mCookiesEnabled);
    246     return (ret != 0);
    247 }
    248 
    249 WTF::Vector<WTF::String>
    250 JavaBridge::getPluginDirectories()
    251 {
    252     WTF::Vector<WTF::String> directories;
    253     JNIEnv* env = JSC::Bindings::getJNIEnv();
    254     AutoJObject obj = javaObject(env);
    255     if (!obj.get())
    256         return directories;
    257     jobjectArray array = (jobjectArray)
    258             env->CallObjectMethod(obj.get(), mGetPluginDirectories);
    259     int count = env->GetArrayLength(array);
    260     for (int i = 0; i < count; i++) {
    261         jstring dir = (jstring) env->GetObjectArrayElement(array, i);
    262         directories.append(jstringToWtfString(env, dir));
    263         env->DeleteLocalRef(dir);
    264     }
    265     env->DeleteLocalRef(array);
    266     checkException(env);
    267     return directories;
    268 }
    269 
    270 WTF::String
    271 JavaBridge::getPluginSharedDataDirectory()
    272 {
    273     JNIEnv* env = JSC::Bindings::getJNIEnv();
    274     AutoJObject obj = javaObject(env);
    275     if (!obj.get())
    276         return String();
    277     jstring ret = (jstring)env->CallObjectMethod(obj.get(), mGetPluginSharedDataDirectory);
    278     WTF::String path = jstringToWtfString(env, ret);
    279     checkException(env);
    280     return path;
    281 }
    282 
    283 void
    284 JavaBridge::setSharedTimerCallback(void (*f)())
    285 {
    286     LOG_ASSERT(!sSharedTimerFiredCallback || sSharedTimerFiredCallback==f,
    287                "Shared timer callback may already be set or null!");
    288 
    289     sSharedTimerFiredCallback = f;
    290 }
    291 
    292 void JavaBridge::signalServiceFuncPtrQueue()
    293 {
    294     // In order to signal the main thread we must go through JNI. This
    295     // is the only usage on most threads, so we need to ensure a JNI
    296     // environment is setup.
    297     JNIEnv* env = JSC::Bindings::getJNIEnv();
    298     AutoJObject obj = javaObject(env);
    299     if (!obj.get())
    300         return;
    301     env->CallVoidMethod(obj.get(), mSignalFuncPtrQueue);
    302 }
    303 
    304 WTF::Vector<WTF::String>JavaBridge::getSupportedKeyStrengthList() {
    305     WTF::Vector<WTF::String> list;
    306     JNIEnv* env = JSC::Bindings::getJNIEnv();
    307     AutoJObject obj = javaObject(env);
    308     if (!obj.get())
    309         return list;
    310     jobjectArray array = (jobjectArray) env->CallObjectMethod(obj.get(),
    311             mGetKeyStrengthList);
    312     int count = env->GetArrayLength(array);
    313     for (int i = 0; i < count; ++i) {
    314         jstring keyStrength = (jstring) env->GetObjectArrayElement(array, i);
    315         list.append(jstringToWtfString(env, keyStrength));
    316         env->DeleteLocalRef(keyStrength);
    317     }
    318     env->DeleteLocalRef(array);
    319     checkException(env);
    320     return list;
    321 }
    322 
    323 WTF::String JavaBridge::getSignedPublicKeyAndChallengeString(unsigned index,
    324         const WTF::String& challenge, const WebCore::KURL& url) {
    325     JNIEnv* env = JSC::Bindings::getJNIEnv();
    326     AutoJObject obj = javaObject(env);
    327     if (!obj.get())
    328         return String();
    329     jstring jChallenge = wtfStringToJstring(env, challenge);
    330     const WTF::String& urlStr = url.string();
    331     jstring jUrl = wtfStringToJstring(env, urlStr);
    332     jstring key = (jstring) env->CallObjectMethod(obj.get(),
    333             mGetSignedPublicKey, index, jChallenge, jUrl);
    334     WTF::String ret = jstringToWtfString(env, key);
    335     env->DeleteLocalRef(jChallenge);
    336     env->DeleteLocalRef(jUrl);
    337     env->DeleteLocalRef(key);
    338     return ret;
    339 }
    340 
    341 WTF::String JavaBridge::resolveFilePathForContentUri(const WTF::String& uri) {
    342     JNIEnv* env = JSC::Bindings::getJNIEnv();
    343     AutoJObject obj = javaObject(env);
    344     if (!obj.get())
    345         return String();
    346     jstring jUri = wtfStringToJstring(env, uri);
    347     jstring path = static_cast<jstring>(env->CallObjectMethod(obj.get(), mResolveFilePathForContentUri, jUri));
    348     WTF::String ret = jstringToWtfString(env, path);
    349     env->DeleteLocalRef(jUri);
    350     env->DeleteLocalRef(path);
    351     return ret;
    352 }
    353 
    354 // ----------------------------------------------------------------------------
    355 
    356 void JavaBridge::Constructor(JNIEnv* env, jobject obj)
    357 {
    358     JavaBridge* javaBridge = new JavaBridge(env, obj);
    359     env->SetIntField(obj, gJavaBridge_ObjectID, (jint)javaBridge);
    360 }
    361 
    362 void JavaBridge::Finalize(JNIEnv* env, jobject obj)
    363 {
    364     JavaBridge* javaBridge = (JavaBridge*)
    365         (env->GetIntField(obj, gJavaBridge_ObjectID));
    366     LOG_ASSERT(javaBridge, "Finalize should not be called twice for the same java bridge!");
    367     LOGV("webcore_javabridge::nativeFinalize(%p)\n", javaBridge);
    368     delete javaBridge;
    369     env->SetIntField(obj, gJavaBridge_ObjectID, 0);
    370 }
    371 
    372 // we don't use the java bridge object, as we're just looking at a global
    373 void JavaBridge::SharedTimerFired(JNIEnv* env, jobject)
    374 {
    375     if (sSharedTimerFiredCallback)
    376     {
    377 #ifdef ANDROID_INSTRUMENT
    378         TimeCounter::start(TimeCounter::SharedTimerTimeCounter);
    379 #endif
    380         SkAutoMemoryUsageProbe  mup("JavaBridge::sharedTimerFired");
    381         sSharedTimerFiredCallback();
    382 #ifdef ANDROID_INSTRUMENT
    383         TimeCounter::record(TimeCounter::SharedTimerTimeCounter, __FUNCTION__);
    384 #endif
    385     }
    386 }
    387 
    388 void JavaBridge::SetCacheSize(JNIEnv* env, jobject obj, jint bytes)
    389 {
    390     WebCore::memoryCache()->setCapacities(0, bytes/2, bytes);
    391 }
    392 
    393 void JavaBridge::SetNetworkOnLine(JNIEnv* env, jobject obj, jboolean online)
    394 {
    395 	WebCore::networkStateNotifier().networkStateChange(online);
    396 }
    397 
    398 void JavaBridge::SetNetworkType(JNIEnv* env, jobject obj, jstring javatype, jstring javasubtype)
    399 {
    400     DEFINE_STATIC_LOCAL(AtomicString, wifi, ("wifi"));
    401     DEFINE_STATIC_LOCAL(AtomicString, mobile, ("mobile"));
    402     DEFINE_STATIC_LOCAL(AtomicString, mobileSupl, ("mobile_supl"));
    403     DEFINE_STATIC_LOCAL(AtomicString, gprs, ("gprs"));
    404     DEFINE_STATIC_LOCAL(AtomicString, edge, ("edge"));
    405     DEFINE_STATIC_LOCAL(AtomicString, umts, ("umts"));
    406 
    407     String type = jstringToWtfString(env, javatype);
    408     String subtype = jstringToWtfString(env, javasubtype);
    409     Connection::ConnectionType connectionType = Connection::UNKNOWN;
    410     if (type == wifi)
    411         connectionType = Connection::WIFI;
    412     else if (type == mobile || type == mobileSupl) {
    413         if (subtype == edge || subtype == gprs)
    414             connectionType = Connection::CELL_2G;
    415         else if (subtype == umts)
    416             connectionType = Connection::CELL_3G;
    417     }
    418     WebCore::networkStateNotifier().networkTypeChange(connectionType);
    419 }
    420 
    421 void JavaBridge::ServiceFuncPtrQueue(JNIEnv*)
    422 {
    423     JavaSharedClient::ServiceFunctionPtrQueue();
    424 }
    425 
    426 void JavaBridge::UpdatePluginDirectories(JNIEnv* env, jobject obj,
    427         jobjectArray array, jboolean reload) {
    428     WTF::Vector<WTF::String> directories;
    429     int count = env->GetArrayLength(array);
    430     for (int i = 0; i < count; i++) {
    431         jstring dir = (jstring) env->GetObjectArrayElement(array, i);
    432         directories.append(jstringToWtfString(env, dir));
    433         env->DeleteLocalRef(dir);
    434     }
    435     checkException(env);
    436     WebCore::PluginDatabase *pluginDatabase =
    437             WebCore::PluginDatabase::installedPlugins();
    438     pluginDatabase->setPluginDirectories(directories);
    439     // refreshPlugins() should refresh both PluginDatabase and Page's PluginData
    440     WebCore::Page::refreshPlugins(reload);
    441 }
    442 
    443 void JavaBridge::AddPackageNames(JNIEnv* env, jobject obj, jobject packageNames)
    444 {
    445     if (!packageNames)
    446         return;
    447 
    448     // dalvikvm will raise exception if any of these fail
    449     jclass setClass = env->FindClass("java/util/Set");
    450     jmethodID iterator = env->GetMethodID(setClass, "iterator",
    451             "()Ljava/util/Iterator;");
    452     jobject iter = env->CallObjectMethod(packageNames, iterator);
    453 
    454     jclass iteratorClass = env->FindClass("java/util/Iterator");
    455     jmethodID hasNext = env->GetMethodID(iteratorClass, "hasNext", "()Z");
    456     jmethodID next = env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;");
    457 
    458     HashSet<WTF::String> namesSet;
    459     while (env->CallBooleanMethod(iter, hasNext)) {
    460         jstring name = static_cast<jstring>(env->CallObjectMethod(iter, next));
    461         namesSet.add(jstringToWtfString(env, name));
    462         env->DeleteLocalRef(name);
    463     }
    464 
    465     packageNotifier().addPackageNames(namesSet);
    466 
    467     env->DeleteLocalRef(iteratorClass);
    468     env->DeleteLocalRef(iter);
    469     env->DeleteLocalRef(setClass);
    470 }
    471 
    472 void JavaBridge::AddPackageName(JNIEnv* env, jobject obj, jstring packageName)
    473 {
    474     packageNotifier().addPackageName(jstringToWtfString(env, packageName));
    475 }
    476 
    477 void JavaBridge::RemovePackageName(JNIEnv* env, jobject obj, jstring packageName)
    478 {
    479     packageNotifier().removePackageName(jstringToWtfString(env, packageName));
    480 }
    481 
    482 void JavaBridge::UpdateProxy(JNIEnv* env, jobject obj, jstring newProxy, jstring newExList)
    483 {
    484 #if USE(CHROME_NETWORK_STACK)
    485     std::string proxy = jstringToStdString(env, newProxy);
    486     std::string exList = jstringToStdString(env, newExList);
    487     WebCache::get(false)->proxy()->UpdateProxySettings(proxy, exList);
    488     WebCache::get(true)->proxy()->UpdateProxySettings(proxy, exList);
    489 #endif
    490 }
    491 
    492 
    493 // ----------------------------------------------------------------------------
    494 
    495 /*
    496  * JNI registration.
    497  */
    498 static JNINativeMethod gWebCoreJavaBridgeMethods[] = {
    499     /* name, signature, funcPtr */
    500     { "nativeConstructor", "()V",
    501         (void*) JavaBridge::Constructor },
    502     { "nativeFinalize", "()V",
    503         (void*) JavaBridge::Finalize },
    504     { "sharedTimerFired", "()V",
    505         (void*) JavaBridge::SharedTimerFired },
    506     { "setCacheSize", "(I)V",
    507         (void*) JavaBridge::SetCacheSize },
    508     { "setNetworkOnLine", "(Z)V",
    509         (void*) JavaBridge::SetNetworkOnLine },
    510     { "setNetworkType", "(Ljava/lang/String;Ljava/lang/String;)V",
    511         (void*) JavaBridge::SetNetworkType },
    512     { "nativeServiceFuncPtrQueue", "()V",
    513         (void*) JavaBridge::ServiceFuncPtrQueue },
    514     { "nativeUpdatePluginDirectories", "([Ljava/lang/String;Z)V",
    515         (void*) JavaBridge::UpdatePluginDirectories },
    516     { "addPackageNames", "(Ljava/util/Set;)V",
    517         (void*) JavaBridge::AddPackageNames },
    518     { "addPackageName", "(Ljava/lang/String;)V",
    519         (void*) JavaBridge::AddPackageName },
    520     { "removePackageName", "(Ljava/lang/String;)V",
    521         (void*) JavaBridge::RemovePackageName },
    522     { "nativeUpdateProxy", "(Ljava/lang/String;Ljava/lang/String;)V",
    523         (void*) JavaBridge::UpdateProxy }
    524 };
    525 
    526 int registerJavaBridge(JNIEnv* env)
    527 {
    528     jclass javaBridge = env->FindClass("android/webkit/JWebCoreJavaBridge");
    529     LOG_FATAL_IF(javaBridge == NULL, "Unable to find class android/webkit/JWebCoreJavaBridge");
    530     gJavaBridge_ObjectID = env->GetFieldID(javaBridge, "mNativeBridge", "I");
    531     LOG_FATAL_IF(gJavaBridge_ObjectID == NULL, "Unable to find android/webkit/JWebCoreJavaBridge.mNativeBridge");
    532     env->DeleteLocalRef(javaBridge);
    533 
    534     return jniRegisterNativeMethods(env, "android/webkit/JWebCoreJavaBridge",
    535                                     gWebCoreJavaBridgeMethods, NELEM(gWebCoreJavaBridgeMethods));
    536 }
    537 
    538 } /* namespace android */
    539