• 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 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 "KeyGeneratorClient.h"
35 #include "KURL.h"
36 #include "NetworkStateNotifier.h"
37 #include "Page.h"
38 #include "PluginClient.h"
39 #include "PluginDatabase.h"
40 #include "Timer.h"
41 #include "TimerClient.h"
42 #include "jni_utility.h"
43 #include "WebCoreJni.h"
44 
45 #ifdef ANDROID_INSTRUMENT
46 #include "TimeCounter.h"
47 #endif
48 
49 #include <jni.h>
50 #include <JNIHelp.h>
51 #include <SkUtils.h>
52 #include <utils/misc.h>
53 
54 namespace android {
55 
56 // ----------------------------------------------------------------------------
57 
58 static jfieldID gJavaBridge_ObjectID;
59 
60 // ----------------------------------------------------------------------------
61 
62 class JavaBridge : public TimerClient, public CookieClient, public PluginClient, public KeyGeneratorClient
63 {
64 public:
65     JavaBridge(JNIEnv* env, jobject obj);
66     virtual ~JavaBridge();
67 
68     /*
69      * WebCore -> Java API
70      */
71     virtual void setSharedTimer(long long timemillis);
72     virtual void stopSharedTimer();
73 
74     virtual void setCookies(WebCore::KURL const& url, WebCore::String const& value);
75     virtual WebCore::String cookies(WebCore::KURL const& url);
76     virtual bool cookiesEnabled();
77 
78     virtual WTF::Vector<WebCore::String> getPluginDirectories();
79     virtual WebCore::String getPluginSharedDataDirectory();
80 
81     virtual WTF::Vector<String> getSupportedKeyStrengthList();
82     virtual WebCore::String getSignedPublicKeyAndChallengeString(unsigned index,
83             const WebCore::String& challenge, const WebCore::KURL& url);
84 
85     ////////////////////////////////////////////
86 
87     virtual void setSharedTimerCallback(void (*f)());
88 
89     ////////////////////////////////////////////
90 
91     virtual void signalServiceFuncPtrQueue();
92 
93     // jni functions
94     static void Constructor(JNIEnv* env, jobject obj);
95     static void Finalize(JNIEnv* env, jobject obj);
96     static void SharedTimerFired(JNIEnv* env, jobject);
97     static void SetCacheSize(JNIEnv* env, jobject obj, jint bytes);
98     static void SetNetworkOnLine(JNIEnv* env, jobject obj, jboolean online);
99     static void SetDeferringTimers(JNIEnv* env, jobject obj, jboolean defer);
100     static void ServiceFuncPtrQueue(JNIEnv*);
101     static void UpdatePluginDirectories(JNIEnv* env, jobject obj, jobjectArray array, jboolean reload);
102 
103 private:
104     jobject     mJavaObject;
105     jmethodID   mSetSharedTimer;
106     jmethodID   mStopSharedTimer;
107     jmethodID   mSetCookies;
108     jmethodID   mCookies;
109     jmethodID   mCookiesEnabled;
110     jmethodID   mGetPluginDirectories;
111     jmethodID   mGetPluginSharedDataDirectory;
112     jmethodID   mSignalFuncPtrQueue;
113     jmethodID   mGetKeyStrengthList;
114     jmethodID   mGetSignedPublicKey;
115 };
116 
117 static void (*sSharedTimerFiredCallback)();
118 
JavaBridge(JNIEnv * env,jobject obj)119 JavaBridge::JavaBridge(JNIEnv* env, jobject obj)
120 {
121     mJavaObject = adoptGlobalRef(env, obj);
122     jclass clazz = env->GetObjectClass(obj);
123 
124     mSetSharedTimer = env->GetMethodID(clazz, "setSharedTimer", "(J)V");
125     mStopSharedTimer = env->GetMethodID(clazz, "stopSharedTimer", "()V");
126     mSetCookies = env->GetMethodID(clazz, "setCookies", "(Ljava/lang/String;Ljava/lang/String;)V");
127     mCookies = env->GetMethodID(clazz, "cookies", "(Ljava/lang/String;)Ljava/lang/String;");
128     mCookiesEnabled = env->GetMethodID(clazz, "cookiesEnabled", "()Z");
129     mGetPluginDirectories = env->GetMethodID(clazz, "getPluginDirectories", "()[Ljava/lang/String;");
130     mGetPluginSharedDataDirectory = env->GetMethodID(clazz, "getPluginSharedDataDirectory", "()Ljava/lang/String;");
131     mSignalFuncPtrQueue = env->GetMethodID(clazz, "signalServiceFuncPtrQueue", "()V");
132     mGetKeyStrengthList = env->GetMethodID(clazz, "getKeyStrengthList", "()[Ljava/lang/String;");
133     mGetSignedPublicKey = env->GetMethodID(clazz, "getSignedPublicKey", "(ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
134 
135     LOG_ASSERT(mSetSharedTimer, "Could not find method setSharedTimer");
136     LOG_ASSERT(mStopSharedTimer, "Could not find method stopSharedTimer");
137     LOG_ASSERT(mSetCookies, "Could not find method setCookies");
138     LOG_ASSERT(mCookies, "Could not find method cookies");
139     LOG_ASSERT(mCookiesEnabled, "Could not find method cookiesEnabled");
140     LOG_ASSERT(mGetPluginDirectories, "Could not find method getPluginDirectories");
141     LOG_ASSERT(mGetPluginSharedDataDirectory, "Could not find method getPluginSharedDataDirectory");
142     LOG_ASSERT(mGetKeyStrengthList, "Could not find method getKeyStrengthList");
143     LOG_ASSERT(mGetSignedPublicKey, "Could not find method getSignedPublicKey");
144 
145     JavaSharedClient::SetTimerClient(this);
146     JavaSharedClient::SetCookieClient(this);
147     JavaSharedClient::SetPluginClient(this);
148     JavaSharedClient::SetKeyGeneratorClient(this);
149 }
150 
~JavaBridge()151 JavaBridge::~JavaBridge()
152 {
153     if (mJavaObject) {
154         JNIEnv* env = JSC::Bindings::getJNIEnv();
155         env->DeleteGlobalRef(mJavaObject);
156         mJavaObject = 0;
157     }
158 
159     JavaSharedClient::SetTimerClient(NULL);
160     JavaSharedClient::SetCookieClient(NULL);
161     JavaSharedClient::SetPluginClient(NULL);
162     JavaSharedClient::SetKeyGeneratorClient(NULL);
163 }
164 
165 void
setSharedTimer(long long timemillis)166 JavaBridge::setSharedTimer(long long timemillis)
167 {
168     JNIEnv* env = JSC::Bindings::getJNIEnv();
169     AutoJObject obj = getRealObject(env, mJavaObject);
170     env->CallVoidMethod(obj.get(), mSetSharedTimer, timemillis);
171 }
172 
173 void
stopSharedTimer()174 JavaBridge::stopSharedTimer()
175 {
176     JNIEnv* env = JSC::Bindings::getJNIEnv();
177     AutoJObject obj = getRealObject(env, mJavaObject);
178     env->CallVoidMethod(obj.get(), mStopSharedTimer);
179 }
180 
181 void
setCookies(WebCore::KURL const & url,WebCore::String const & value)182 JavaBridge::setCookies(WebCore::KURL const& url, WebCore::String const& value)
183 {
184     JNIEnv* env = JSC::Bindings::getJNIEnv();
185     const WebCore::String& urlStr = url.string();
186     jstring jUrlStr = env->NewString(urlStr.characters(), urlStr.length());
187     jstring jValueStr = env->NewString(value.characters(), value.length());
188 
189     AutoJObject obj = getRealObject(env, mJavaObject);
190     env->CallVoidMethod(obj.get(), mSetCookies, jUrlStr, jValueStr);
191     env->DeleteLocalRef(jUrlStr);
192     env->DeleteLocalRef(jValueStr);
193 }
194 
195 WebCore::String
cookies(WebCore::KURL const & url)196 JavaBridge::cookies(WebCore::KURL const& url)
197 {
198     JNIEnv* env = JSC::Bindings::getJNIEnv();
199     const WebCore::String& urlStr = url.string();
200     jstring jUrlStr = env->NewString(urlStr.characters(), urlStr.length());
201 
202     AutoJObject obj = getRealObject(env, mJavaObject);
203     jstring string = (jstring)(env->CallObjectMethod(obj.get(), mCookies, jUrlStr));
204 
205     WebCore::String ret = to_string(env, string);
206     env->DeleteLocalRef(jUrlStr);
207     env->DeleteLocalRef(string);
208     return ret;
209 }
210 
211 bool
cookiesEnabled()212 JavaBridge::cookiesEnabled()
213 {
214     JNIEnv* env = JSC::Bindings::getJNIEnv();
215     AutoJObject obj = getRealObject(env, mJavaObject);
216     jboolean ret = env->CallBooleanMethod(obj.get(), mCookiesEnabled);
217     return (ret != 0);
218 }
219 
220 WTF::Vector<WebCore::String>
getPluginDirectories()221 JavaBridge::getPluginDirectories()
222 {
223     WTF::Vector<WebCore::String> directories;
224     JNIEnv* env = JSC::Bindings::getJNIEnv();
225     AutoJObject obj = getRealObject(env, mJavaObject);
226     jobjectArray array = (jobjectArray)
227             env->CallObjectMethod(obj.get(), mGetPluginDirectories);
228     int count = env->GetArrayLength(array);
229     for (int i = 0; i < count; i++) {
230         jstring dir = (jstring) env->GetObjectArrayElement(array, i);
231         directories.append(to_string(env, dir));
232         env->DeleteLocalRef(dir);
233     }
234     env->DeleteLocalRef(array);
235     checkException(env);
236     return directories;
237 }
238 
239 WebCore::String
getPluginSharedDataDirectory()240 JavaBridge::getPluginSharedDataDirectory()
241 {
242     JNIEnv* env = JSC::Bindings::getJNIEnv();
243     AutoJObject obj = getRealObject(env, mJavaObject);
244     jstring ret = (jstring)env->CallObjectMethod(obj.get(), mGetPluginSharedDataDirectory);
245     WebCore::String path = to_string(env, ret);
246     checkException(env);
247     return path;
248 }
249 
250 void
setSharedTimerCallback(void (* f)())251 JavaBridge::setSharedTimerCallback(void (*f)())
252 {
253     LOG_ASSERT(!sSharedTimerFiredCallback || sSharedTimerFiredCallback==f,
254                "Shared timer callback may already be set or null!");
255 
256     sSharedTimerFiredCallback = f;
257 }
258 
signalServiceFuncPtrQueue()259 void JavaBridge::signalServiceFuncPtrQueue()
260 {
261     // In order to signal the main thread we must go through JNI. This
262     // is the only usage on most threads, so we need to ensure a JNI
263     // environment is setup.
264     JNIEnv* env = JSC::Bindings::getJNIEnv();
265     AutoJObject obj = getRealObject(env, mJavaObject);
266     env->CallVoidMethod(obj.get(), mSignalFuncPtrQueue);
267 }
268 
getSupportedKeyStrengthList()269 WTF::Vector<WebCore::String>JavaBridge::getSupportedKeyStrengthList() {
270     WTF::Vector<WebCore::String> list;
271     JNIEnv* env = JSC::Bindings::getJNIEnv();
272     AutoJObject obj = getRealObject(env, mJavaObject);
273     jobjectArray array = (jobjectArray) env->CallObjectMethod(obj.get(),
274             mGetKeyStrengthList);
275     int count = env->GetArrayLength(array);
276     for (int i = 0; i < count; ++i) {
277         jstring keyStrength = (jstring) env->GetObjectArrayElement(array, i);
278         list.append(to_string(env, keyStrength));
279         env->DeleteLocalRef(keyStrength);
280     }
281     env->DeleteLocalRef(array);
282     checkException(env);
283     return list;
284 }
285 
getSignedPublicKeyAndChallengeString(unsigned index,const WebCore::String & challenge,const WebCore::KURL & url)286 WebCore::String JavaBridge::getSignedPublicKeyAndChallengeString(unsigned index,
287         const WebCore::String& challenge, const WebCore::KURL& url) {
288     JNIEnv* env = JSC::Bindings::getJNIEnv();
289     jstring jChallenge = env->NewString(challenge.characters(),
290             challenge.length());
291     const WebCore::String& urlStr = url.string();
292     jstring jUrl = env->NewString(urlStr.characters(), urlStr.length());
293     AutoJObject obj = getRealObject(env, mJavaObject);
294     jstring key = (jstring) env->CallObjectMethod(obj.get(),
295             mGetSignedPublicKey, index, jChallenge, jUrl);
296     WebCore::String ret = to_string(env, key);
297     env->DeleteLocalRef(jChallenge);
298     env->DeleteLocalRef(jUrl);
299     env->DeleteLocalRef(key);
300     return ret;
301 }
302 
303 // ----------------------------------------------------------------------------
304 
Constructor(JNIEnv * env,jobject obj)305 void JavaBridge::Constructor(JNIEnv* env, jobject obj)
306 {
307     JavaBridge* javaBridge = new JavaBridge(env, obj);
308     env->SetIntField(obj, gJavaBridge_ObjectID, (jint)javaBridge);
309 }
310 
Finalize(JNIEnv * env,jobject obj)311 void JavaBridge::Finalize(JNIEnv* env, jobject obj)
312 {
313     JavaBridge* javaBridge = (JavaBridge*)
314         (env->GetIntField(obj, gJavaBridge_ObjectID));
315     LOG_ASSERT(javaBridge, "Finalize should not be called twice for the same java bridge!");
316     LOGV("webcore_javabridge::nativeFinalize(%p)\n", javaBridge);
317     delete javaBridge;
318     env->SetIntField(obj, gJavaBridge_ObjectID, 0);
319 }
320 
321 // we don't use the java bridge object, as we're just looking at a global
SharedTimerFired(JNIEnv * env,jobject)322 void JavaBridge::SharedTimerFired(JNIEnv* env, jobject)
323 {
324     if (sSharedTimerFiredCallback)
325     {
326 #ifdef ANDROID_INSTRUMENT
327         TimeCounter::start(TimeCounter::SharedTimerTimeCounter);
328 #endif
329         SkAutoMemoryUsageProbe  mup("JavaBridge::sharedTimerFired");
330         sSharedTimerFiredCallback();
331 #ifdef ANDROID_INSTRUMENT
332         TimeCounter::record(TimeCounter::SharedTimerTimeCounter, __FUNCTION__);
333 #endif
334     }
335 }
336 
SetCacheSize(JNIEnv * env,jobject obj,jint bytes)337 void JavaBridge::SetCacheSize(JNIEnv* env, jobject obj, jint bytes)
338 {
339     WebCore::cache()->setCapacities(0, bytes/2, bytes);
340 }
341 
SetNetworkOnLine(JNIEnv * env,jobject obj,jboolean online)342 void JavaBridge::SetNetworkOnLine(JNIEnv* env, jobject obj, jboolean online)
343 {
344 	WebCore::networkStateNotifier().networkStateChange(online);
345 }
346 
ServiceFuncPtrQueue(JNIEnv *)347 void JavaBridge::ServiceFuncPtrQueue(JNIEnv*)
348 {
349     JavaSharedClient::ServiceFunctionPtrQueue();
350 }
351 
UpdatePluginDirectories(JNIEnv * env,jobject obj,jobjectArray array,jboolean reload)352 void JavaBridge::UpdatePluginDirectories(JNIEnv* env, jobject obj,
353         jobjectArray array, jboolean reload) {
354     WTF::Vector<WebCore::String> directories;
355     int count = env->GetArrayLength(array);
356     for (int i = 0; i < count; i++) {
357         jstring dir = (jstring) env->GetObjectArrayElement(array, i);
358         directories.append(to_string(env, dir));
359         env->DeleteLocalRef(dir);
360     }
361     checkException(env);
362     WebCore::PluginDatabase *pluginDatabase =
363             WebCore::PluginDatabase::installedPlugins();
364     pluginDatabase->setPluginDirectories(directories);
365     // refreshPlugins() should refresh both PluginDatabase and Page's PluginData
366     WebCore::Page::refreshPlugins(reload);
367 }
368 
369 // ----------------------------------------------------------------------------
370 
371 /*
372  * JNI registration.
373  */
374 static JNINativeMethod gWebCoreJavaBridgeMethods[] = {
375     /* name, signature, funcPtr */
376     { "nativeConstructor", "()V",
377         (void*) JavaBridge::Constructor },
378     { "nativeFinalize", "()V",
379         (void*) JavaBridge::Finalize },
380     { "sharedTimerFired", "()V",
381         (void*) JavaBridge::SharedTimerFired },
382     { "setCacheSize", "(I)V",
383         (void*) JavaBridge::SetCacheSize },
384     { "setNetworkOnLine", "(Z)V",
385         (void*) JavaBridge::SetNetworkOnLine },
386     { "nativeServiceFuncPtrQueue", "()V",
387         (void*) JavaBridge::ServiceFuncPtrQueue },
388     { "nativeUpdatePluginDirectories", "([Ljava/lang/String;Z)V",
389         (void*) JavaBridge::UpdatePluginDirectories }
390 };
391 
register_javabridge(JNIEnv * env)392 int register_javabridge(JNIEnv* env)
393 {
394     jclass javaBridge = env->FindClass("android/webkit/JWebCoreJavaBridge");
395     LOG_FATAL_IF(javaBridge == NULL, "Unable to find class android/webkit/JWebCoreJavaBridge");
396     gJavaBridge_ObjectID = env->GetFieldID(javaBridge, "mNativeBridge", "I");
397     LOG_FATAL_IF(gJavaBridge_ObjectID == NULL, "Unable to find android/webkit/JWebCoreJavaBridge.mNativeBridge");
398 
399     return jniRegisterNativeMethods(env, "android/webkit/JWebCoreJavaBridge",
400                                     gWebCoreJavaBridgeMethods, NELEM(gWebCoreJavaBridgeMethods));
401 }
402 
403 } /* namespace android */
404