• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
javaObject(JNIEnv * env)125     AutoJObject javaObject(JNIEnv* env) { return getRealObject(env, mJavaObject); }
126 };
127 
128 static void (*sSharedTimerFiredCallback)();
129 
JavaBridge(JNIEnv * env,jobject obj)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 
~JavaBridge()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
setSharedTimer(long long timemillis)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
stopSharedTimer()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
setCookies(WebCore::KURL const & url,WTF::String const & value)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
cookies(WebCore::KURL const & url)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
cookiesEnabled()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>
getPluginDirectories()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
getPluginSharedDataDirectory()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
setSharedTimerCallback(void (* f)())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 
signalServiceFuncPtrQueue()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 
getSupportedKeyStrengthList()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 
getSignedPublicKeyAndChallengeString(unsigned index,const WTF::String & challenge,const WebCore::KURL & url)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 
resolveFilePathForContentUri(const WTF::String & uri)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 
Constructor(JNIEnv * env,jobject obj)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 
Finalize(JNIEnv * env,jobject obj)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
SharedTimerFired(JNIEnv * env,jobject)370 void JavaBridge::SharedTimerFired(JNIEnv* env, jobject)
371 {
372     if (sSharedTimerFiredCallback)
373         sSharedTimerFiredCallback();
374 }
375 
SetCacheSize(JNIEnv * env,jobject obj,jint bytes)376 void JavaBridge::SetCacheSize(JNIEnv* env, jobject obj, jint bytes)
377 {
378     WebCore::memoryCache()->setCapacities(0, bytes/2, bytes);
379 }
380 
SetNetworkOnLine(JNIEnv * env,jobject obj,jboolean online)381 void JavaBridge::SetNetworkOnLine(JNIEnv* env, jobject obj, jboolean online)
382 {
383 	WebCore::networkStateNotifier().networkStateChange(online);
384 }
385 
SetNetworkType(JNIEnv * env,jobject obj,jstring javatype,jstring javasubtype)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 
ServiceFuncPtrQueue(JNIEnv *)409 void JavaBridge::ServiceFuncPtrQueue(JNIEnv*)
410 {
411     JavaSharedClient::ServiceFunctionPtrQueue();
412 }
413 
UpdatePluginDirectories(JNIEnv * env,jobject obj,jobjectArray array,jboolean reload)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 
AddPackageNames(JNIEnv * env,jobject obj,jobject packageNames)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 
AddPackageName(JNIEnv * env,jobject obj,jstring packageName)460 void JavaBridge::AddPackageName(JNIEnv* env, jobject obj, jstring packageName)
461 {
462     packageNotifier().addPackageName(jstringToWtfString(env, packageName));
463 }
464 
RemovePackageName(JNIEnv * env,jobject obj,jstring packageName)465 void JavaBridge::RemovePackageName(JNIEnv* env, jobject obj, jstring packageName)
466 {
467     packageNotifier().removePackageName(jstringToWtfString(env, packageName));
468 }
469 
UpdateProxy(JNIEnv * env,jobject obj,jstring newProxy,jstring newExList)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 
registerJavaBridge(JNIEnv * env)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