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