2 * Copyright 2006, The Android Open Source Project
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #define LOG_TAG "webcoreglue"
30 #include "MemoryCache.h"
31 #include "Connection.h"
32 #include "CookieClient.h"
33 #include "FileSystemClient.h"
34 #include "JavaSharedClient.h"
35 #include "KeyGeneratorClient.h"
37 #include "NetworkStateNotifier.h"
38 #include "PackageNotifier.h"
40 #include "PluginClient.h"
41 #include "PluginDatabase.h"
43 #include "TimerClient.h"
44 #ifdef ANDROID_INSTRUMENT
45 #include "TimeCounter.h"
47 #include "WebCoreJni.h"
50 #include <JNIUtility.h>
53 #include <utils/misc.h>
54 #include <wtf/Platform.h>
55 #include <wtf/StdLibExtras.h>
56 #include <wtf/text/AtomicString.h>
60 // ----------------------------------------------------------------------------
62 static jfieldID gJavaBridge_ObjectID;
64 // ----------------------------------------------------------------------------
66 class JavaBridge : public TimerClient, public CookieClient, public PluginClient, public KeyGeneratorClient, public FileSystemClient
69 JavaBridge(JNIEnv* env, jobject obj);
70 virtual ~JavaBridge();
75 virtual void setSharedTimer(long long timemillis);
76 virtual void stopSharedTimer();
78 virtual void setCookies(WebCore::KURL const& url, WTF::String const& value);
79 virtual WTF::String cookies(WebCore::KURL const& url);
80 virtual bool cookiesEnabled();
82 virtual WTF::Vector<WTF::String> getPluginDirectories();
83 virtual WTF::String getPluginSharedDataDirectory();
85 virtual WTF::Vector<String> getSupportedKeyStrengthList();
86 virtual WTF::String getSignedPublicKeyAndChallengeString(unsigned index,
87 const WTF::String& challenge, const WebCore::KURL& url);
88 virtual WTF::String resolveFilePathForContentUri(const WTF::String& uri);
90 ////////////////////////////////////////////
92 virtual void setSharedTimerCallback(void (*f)());
94 ////////////////////////////////////////////
96 virtual void signalServiceFuncPtrQueue();
99 static void Constructor(JNIEnv* env, jobject obj);
100 static void Finalize(JNIEnv* env, jobject obj);
101 static void SharedTimerFired(JNIEnv* env, jobject);
102 static void SetCacheSize(JNIEnv* env, jobject obj, jint bytes);
103 static void SetNetworkOnLine(JNIEnv* env, jobject obj, jboolean online);
104 static void SetNetworkType(JNIEnv* env, jobject obj, jstring type, jstring subtype);
105 static void SetDeferringTimers(JNIEnv* env, jobject obj, jboolean defer);
106 static void ServiceFuncPtrQueue(JNIEnv*);
107 static void UpdatePluginDirectories(JNIEnv* env, jobject obj, jobjectArray array, jboolean reload);
108 static void AddPackageNames(JNIEnv* env, jobject obj, jobject packageNames);
109 static void AddPackageName(JNIEnv* env, jobject obj, jstring packageName);
110 static void RemovePackageName(JNIEnv* env, jobject obj, jstring packageName);
115 jmethodID mSetSharedTimer;
116 jmethodID mStopSharedTimer;
117 jmethodID mSetCookies;
119 jmethodID mCookiesEnabled;
120 jmethodID mGetPluginDirectories;
121 jmethodID mGetPluginSharedDataDirectory;
122 jmethodID mSignalFuncPtrQueue;
123 jmethodID mGetKeyStrengthList;
124 jmethodID mGetSignedPublicKey;
125 jmethodID mResolveFilePathForContentUri;
128 static void (*sSharedTimerFiredCallback)();
130 JavaBridge::JavaBridge(JNIEnv* env, jobject obj)
132 mJavaObject = env->NewWeakGlobalRef(obj);
133 jclass clazz = env->GetObjectClass(obj);
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);
148 LOG_ASSERT(mSetSharedTimer, "Could not find method setSharedTimer");
149 LOG_ASSERT(mStopSharedTimer, "Could not find method stopSharedTimer");
150 LOG_ASSERT(mSetCookies, "Could not find method setCookies");
151 LOG_ASSERT(mCookies, "Could not find method cookies");
152 LOG_ASSERT(mCookiesEnabled, "Could not find method cookiesEnabled");
153 LOG_ASSERT(mGetPluginDirectories, "Could not find method getPluginDirectories");
154 LOG_ASSERT(mGetPluginSharedDataDirectory, "Could not find method getPluginSharedDataDirectory");
155 LOG_ASSERT(mGetKeyStrengthList, "Could not find method getKeyStrengthList");
156 LOG_ASSERT(mGetSignedPublicKey, "Could not find method getSignedPublicKey");
158 JavaSharedClient::SetTimerClient(this);
159 JavaSharedClient::SetCookieClient(this);
160 JavaSharedClient::SetPluginClient(this);
161 JavaSharedClient::SetKeyGeneratorClient(this);
162 JavaSharedClient::SetFileSystemClient(this);
165 JavaBridge::~JavaBridge()
168 JNIEnv* env = JSC::Bindings::getJNIEnv();
169 env->DeleteWeakGlobalRef(mJavaObject);
173 JavaSharedClient::SetTimerClient(NULL);
174 JavaSharedClient::SetCookieClient(NULL);
175 JavaSharedClient::SetPluginClient(NULL);
176 JavaSharedClient::SetKeyGeneratorClient(NULL);
177 JavaSharedClient::SetFileSystemClient(NULL);
181 JavaBridge::setSharedTimer(long long timemillis)
183 JNIEnv* env = JSC::Bindings::getJNIEnv();
184 AutoJObject obj = getRealObject(env, mJavaObject);
185 env->CallVoidMethod(obj.get(), mSetSharedTimer, timemillis);
189 JavaBridge::stopSharedTimer()
191 JNIEnv* env = JSC::Bindings::getJNIEnv();
192 AutoJObject obj = getRealObject(env, mJavaObject);
193 env->CallVoidMethod(obj.get(), mStopSharedTimer);
197 JavaBridge::setCookies(WebCore::KURL const& url, WTF::String const& value)
199 JNIEnv* env = JSC::Bindings::getJNIEnv();
200 const WTF::String& urlStr = url.string();
201 jstring jUrlStr = WtfStringToJstring(env, urlStr);
202 jstring jValueStr = WtfStringToJstring(env, value);
204 AutoJObject obj = getRealObject(env, mJavaObject);
205 env->CallVoidMethod(obj.get(), mSetCookies, jUrlStr, jValueStr);
206 env->DeleteLocalRef(jUrlStr);
207 env->DeleteLocalRef(jValueStr);
211 JavaBridge::cookies(WebCore::KURL const& url)
213 JNIEnv* env = JSC::Bindings::getJNIEnv();
214 const WTF::String& urlStr = url.string();
215 jstring jUrlStr = WtfStringToJstring(env, urlStr);
217 AutoJObject obj = getRealObject(env, mJavaObject);
218 jstring string = (jstring)(env->CallObjectMethod(obj.get(), mCookies, jUrlStr));
220 WTF::String ret = jstringToWtfString(env, string);
221 env->DeleteLocalRef(jUrlStr);
222 env->DeleteLocalRef(string);
227 JavaBridge::cookiesEnabled()
229 JNIEnv* env = JSC::Bindings::getJNIEnv();
230 AutoJObject obj = getRealObject(env, mJavaObject);
231 jboolean ret = env->CallBooleanMethod(obj.get(), mCookiesEnabled);
235 WTF::Vector<WTF::String>
236 JavaBridge::getPluginDirectories()
238 WTF::Vector<WTF::String> directories;
239 JNIEnv* env = JSC::Bindings::getJNIEnv();
240 AutoJObject obj = getRealObject(env, mJavaObject);
241 jobjectArray array = (jobjectArray)
242 env->CallObjectMethod(obj.get(), mGetPluginDirectories);
243 int count = env->GetArrayLength(array);
244 for (int i = 0; i < count; i++) {
245 jstring dir = (jstring) env->GetObjectArrayElement(array, i);
246 directories.append(jstringToWtfString(env, dir));
247 env->DeleteLocalRef(dir);
249 env->DeleteLocalRef(array);
255 JavaBridge::getPluginSharedDataDirectory()
257 JNIEnv* env = JSC::Bindings::getJNIEnv();
258 AutoJObject obj = getRealObject(env, mJavaObject);
259 jstring ret = (jstring)env->CallObjectMethod(obj.get(), mGetPluginSharedDataDirectory);
260 WTF::String path = jstringToWtfString(env, ret);
266 JavaBridge::setSharedTimerCallback(void (*f)())
268 LOG_ASSERT(!sSharedTimerFiredCallback || sSharedTimerFiredCallback==f,
269 "Shared timer callback may already be set or null!");
271 sSharedTimerFiredCallback = f;
274 void JavaBridge::signalServiceFuncPtrQueue()
276 // In order to signal the main thread we must go through JNI. This
277 // is the only usage on most threads, so we need to ensure a JNI
278 // environment is setup.
279 JNIEnv* env = JSC::Bindings::getJNIEnv();
280 AutoJObject obj = getRealObject(env, mJavaObject);
281 env->CallVoidMethod(obj.get(), mSignalFuncPtrQueue);
284 WTF::Vector<WTF::String>JavaBridge::getSupportedKeyStrengthList() {
285 WTF::Vector<WTF::String> list;
286 JNIEnv* env = JSC::Bindings::getJNIEnv();
287 AutoJObject obj = getRealObject(env, mJavaObject);
288 jobjectArray array = (jobjectArray) env->CallObjectMethod(obj.get(),
289 mGetKeyStrengthList);
290 int count = env->GetArrayLength(array);
291 for (int i = 0; i < count; ++i) {
292 jstring keyStrength = (jstring) env->GetObjectArrayElement(array, i);
293 list.append(jstringToWtfString(env, keyStrength));
294 env->DeleteLocalRef(keyStrength);
296 env->DeleteLocalRef(array);
301 WTF::String JavaBridge::getSignedPublicKeyAndChallengeString(unsigned index,
302 const WTF::String& challenge, const WebCore::KURL& url) {
303 JNIEnv* env = JSC::Bindings::getJNIEnv();
304 jstring jChallenge = WtfStringToJstring(env, challenge);
305 const WTF::String& urlStr = url.string();
306 jstring jUrl = WtfStringToJstring(env, urlStr);
307 AutoJObject obj = getRealObject(env, mJavaObject);
308 jstring key = (jstring) env->CallObjectMethod(obj.get(),
309 mGetSignedPublicKey, index, jChallenge, jUrl);
310 WTF::String ret = jstringToWtfString(env, key);
311 env->DeleteLocalRef(jChallenge);
312 env->DeleteLocalRef(jUrl);
313 env->DeleteLocalRef(key);
317 WTF::String JavaBridge::resolveFilePathForContentUri(const WTF::String& uri) {
318 JNIEnv* env = JSC::Bindings::getJNIEnv();
319 jstring jUri = WtfStringToJstring(env, uri);
320 AutoJObject obj = getRealObject(env, mJavaObject);
321 jstring path = static_cast<jstring>(env->CallObjectMethod(obj.get(), mResolveFilePathForContentUri, jUri));
322 WTF::String ret = jstringToWtfString(env, path);
323 env->DeleteLocalRef(jUri);
324 env->DeleteLocalRef(path);
328 // ----------------------------------------------------------------------------
330 void JavaBridge::Constructor(JNIEnv* env, jobject obj)
332 JavaBridge* javaBridge = new JavaBridge(env, obj);
333 env->SetIntField(obj, gJavaBridge_ObjectID, (jint)javaBridge);
336 void JavaBridge::Finalize(JNIEnv* env, jobject obj)
338 JavaBridge* javaBridge = (JavaBridge*)
339 (env->GetIntField(obj, gJavaBridge_ObjectID));
340 LOG_ASSERT(javaBridge, "Finalize should not be called twice for the same java bridge!");
341 LOGV("webcore_javabridge::nativeFinalize(%p)\n", javaBridge);
343 env->SetIntField(obj, gJavaBridge_ObjectID, 0);
346 // we don't use the java bridge object, as we're just looking at a global
347 void JavaBridge::SharedTimerFired(JNIEnv* env, jobject)
349 if (sSharedTimerFiredCallback)
351 #ifdef ANDROID_INSTRUMENT
352 TimeCounter::start(TimeCounter::SharedTimerTimeCounter);
354 SkAutoMemoryUsageProbe mup("JavaBridge::sharedTimerFired");
355 sSharedTimerFiredCallback();
356 #ifdef ANDROID_INSTRUMENT
357 TimeCounter::record(TimeCounter::SharedTimerTimeCounter, __FUNCTION__);
362 void JavaBridge::SetCacheSize(JNIEnv* env, jobject obj, jint bytes)
364 WebCore::cache()->setCapacities(0, bytes/2, bytes);
367 void JavaBridge::SetNetworkOnLine(JNIEnv* env, jobject obj, jboolean online)
369 WebCore::networkStateNotifier().networkStateChange(online);
372 void JavaBridge::SetNetworkType(JNIEnv* env, jobject obj, jstring javatype, jstring javasubtype)
374 DEFINE_STATIC_LOCAL(AtomicString, wifi, ("wifi"));
375 DEFINE_STATIC_LOCAL(AtomicString, mobile, ("mobile"));
376 DEFINE_STATIC_LOCAL(AtomicString, mobileSupl, ("mobile_supl"));
377 DEFINE_STATIC_LOCAL(AtomicString, gprs, ("gprs"));
378 DEFINE_STATIC_LOCAL(AtomicString, edge, ("edge"));
379 DEFINE_STATIC_LOCAL(AtomicString, umts, ("umts"));
381 String type = jstringToWtfString(env, javatype);
382 String subtype = jstringToWtfString(env, javasubtype);
383 Connection::ConnectionType connectionType = Connection::UNKNOWN;
385 connectionType = Connection::WIFI;
386 else if (type == mobile || type == mobileSupl) {
387 if (subtype == edge || subtype == gprs)
388 connectionType = Connection::CELL_2G;
389 else if (subtype == umts)
390 connectionType = Connection::CELL_3G;
392 WebCore::networkStateNotifier().networkTypeChange(connectionType);
395 void JavaBridge::ServiceFuncPtrQueue(JNIEnv*)
397 JavaSharedClient::ServiceFunctionPtrQueue();
400 void JavaBridge::UpdatePluginDirectories(JNIEnv* env, jobject obj,
401 jobjectArray array, jboolean reload) {
402 WTF::Vector<WTF::String> directories;
403 int count = env->GetArrayLength(array);
404 for (int i = 0; i < count; i++) {
405 jstring dir = (jstring) env->GetObjectArrayElement(array, i);
406 directories.append(jstringToWtfString(env, dir));
407 env->DeleteLocalRef(dir);
410 WebCore::PluginDatabase *pluginDatabase =
411 WebCore::PluginDatabase::installedPlugins();
412 pluginDatabase->setPluginDirectories(directories);
413 // refreshPlugins() should refresh both PluginDatabase and Page's PluginData
414 WebCore::Page::refreshPlugins(reload);
417 void JavaBridge::AddPackageNames(JNIEnv* env, jobject obj, jobject packageNames)
422 // dalvikvm will raise exception if any of these fail
423 jclass setClass = env->FindClass("java/util/Set");
424 jmethodID iterator = env->GetMethodID(setClass, "iterator",
425 "()Ljava/util/Iterator;");
426 jobject iter = env->CallObjectMethod(packageNames, iterator);
428 jclass iteratorClass = env->FindClass("java/util/Iterator");
429 jmethodID hasNext = env->GetMethodID(iteratorClass, "hasNext", "()Z");
430 jmethodID next = env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;");
432 HashSet<WTF::String> namesSet;
433 while (env->CallBooleanMethod(iter, hasNext)) {
434 jstring name = static_cast<jstring>(env->CallObjectMethod(iter, next));
435 namesSet.add(jstringToWtfString(env, name));
436 env->DeleteLocalRef(name);
439 packageNotifier().addPackageNames(namesSet);
441 env->DeleteLocalRef(iteratorClass);
442 env->DeleteLocalRef(iter);
443 env->DeleteLocalRef(setClass);
446 void JavaBridge::AddPackageName(JNIEnv* env, jobject obj, jstring packageName)
448 packageNotifier().addPackageName(jstringToWtfString(env, packageName));
451 void JavaBridge::RemovePackageName(JNIEnv* env, jobject obj, jstring packageName)
453 packageNotifier().removePackageName(jstringToWtfString(env, packageName));
457 // ----------------------------------------------------------------------------
462 static JNINativeMethod gWebCoreJavaBridgeMethods[] = {
463 /* name, signature, funcPtr */
464 { "nativeConstructor", "()V",
465 (void*) JavaBridge::Constructor },
466 { "nativeFinalize", "()V",
467 (void*) JavaBridge::Finalize },
468 { "sharedTimerFired", "()V",
469 (void*) JavaBridge::SharedTimerFired },
470 { "setCacheSize", "(I)V",
471 (void*) JavaBridge::SetCacheSize },
472 { "setNetworkOnLine", "(Z)V",
473 (void*) JavaBridge::SetNetworkOnLine },
474 { "setNetworkType", "(Ljava/lang/String;Ljava/lang/String;)V",
475 (void*) JavaBridge::SetNetworkType },
476 { "nativeServiceFuncPtrQueue", "()V",
477 (void*) JavaBridge::ServiceFuncPtrQueue },
478 { "nativeUpdatePluginDirectories", "([Ljava/lang/String;Z)V",
479 (void*) JavaBridge::UpdatePluginDirectories },
480 { "addPackageNames", "(Ljava/util/Set;)V",
481 (void*) JavaBridge::AddPackageNames },
482 { "addPackageName", "(Ljava/lang/String;)V",
483 (void*) JavaBridge::AddPackageName },
484 { "removePackageName", "(Ljava/lang/String;)V",
485 (void*) JavaBridge::RemovePackageName }
488 int registerJavaBridge(JNIEnv* env)
490 jclass javaBridge = env->FindClass("android/webkit/JWebCoreJavaBridge");
491 LOG_FATAL_IF(javaBridge == NULL, "Unable to find class android/webkit/JWebCoreJavaBridge");
492 gJavaBridge_ObjectID = env->GetFieldID(javaBridge, "mNativeBridge", "I");
493 LOG_FATAL_IF(gJavaBridge_ObjectID == NULL, "Unable to find android/webkit/JWebCoreJavaBridge.mNativeBridge");
494 env->DeleteLocalRef(javaBridge);
496 return jniRegisterNativeMethods(env, "android/webkit/JWebCoreJavaBridge",
497 gWebCoreJavaBridgeMethods, NELEM(gWebCoreJavaBridgeMethods));
500 } /* namespace android */