OSDN Git Service

Revert "Merge "Add a method java can send proxy changes to""
[android-x86/external-webkit.git] / WebKit / android / jni / JavaBridge.cpp
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 "WebCoreJni.h"
48
49 #include <JNIHelp.h>
50 #include <JNIUtility.h>
51 #include <SkUtils.h>
52 #include <jni.h>
53 #include <utils/misc.h>
54 #include <wtf/Platform.h>
55 #include <wtf/StdLibExtras.h>
56 #include <wtf/text/AtomicString.h>
57
58 namespace android {
59
60 // ----------------------------------------------------------------------------
61
62 static jfieldID gJavaBridge_ObjectID;
63
64 // ----------------------------------------------------------------------------
65    
66 class JavaBridge : public TimerClient, public CookieClient, public PluginClient, public KeyGeneratorClient, public FileSystemClient
67 {
68 public:
69     JavaBridge(JNIEnv* env, jobject obj);
70     virtual ~JavaBridge();
71
72     /*
73      * WebCore -> Java API
74      */
75     virtual void setSharedTimer(long long timemillis);
76     virtual void stopSharedTimer();
77
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();
81
82     virtual WTF::Vector<WTF::String> getPluginDirectories();
83     virtual WTF::String getPluginSharedDataDirectory();
84
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);
89
90     ////////////////////////////////////////////
91
92     virtual void setSharedTimerCallback(void (*f)());
93
94     ////////////////////////////////////////////
95
96     virtual void signalServiceFuncPtrQueue();
97
98     // jni functions
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);
111
112
113 private:
114     jweak       mJavaObject;
115     jmethodID   mSetSharedTimer;
116     jmethodID   mStopSharedTimer;
117     jmethodID   mSetCookies;
118     jmethodID   mCookies;
119     jmethodID   mCookiesEnabled;
120     jmethodID   mGetPluginDirectories;
121     jmethodID   mGetPluginSharedDataDirectory;
122     jmethodID   mSignalFuncPtrQueue;
123     jmethodID   mGetKeyStrengthList;
124     jmethodID   mGetSignedPublicKey;
125     jmethodID   mResolveFilePathForContentUri;
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     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");
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 = getRealObject(env, mJavaObject);
185     env->CallVoidMethod(obj.get(), mSetSharedTimer, timemillis);
186 }
187
188 void
189 JavaBridge::stopSharedTimer()
190 {    
191     JNIEnv* env = JSC::Bindings::getJNIEnv();
192     AutoJObject obj = getRealObject(env, mJavaObject);
193     env->CallVoidMethod(obj.get(), mStopSharedTimer);
194 }
195
196 void
197 JavaBridge::setCookies(WebCore::KURL const& url, WTF::String const& value)
198 {
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);
203
204     AutoJObject obj = getRealObject(env, mJavaObject);
205     env->CallVoidMethod(obj.get(), mSetCookies, jUrlStr, jValueStr);
206     env->DeleteLocalRef(jUrlStr);
207     env->DeleteLocalRef(jValueStr);
208 }
209
210 WTF::String
211 JavaBridge::cookies(WebCore::KURL const& url)
212 {
213     JNIEnv* env = JSC::Bindings::getJNIEnv();
214     const WTF::String& urlStr = url.string();
215     jstring jUrlStr = WtfStringToJstring(env, urlStr);
216
217     AutoJObject obj = getRealObject(env, mJavaObject);
218     jstring string = (jstring)(env->CallObjectMethod(obj.get(), mCookies, jUrlStr));
219     
220     WTF::String ret = jstringToWtfString(env, string);
221     env->DeleteLocalRef(jUrlStr);
222     env->DeleteLocalRef(string);
223     return ret;
224 }
225
226 bool
227 JavaBridge::cookiesEnabled()
228 {
229     JNIEnv* env = JSC::Bindings::getJNIEnv();
230     AutoJObject obj = getRealObject(env, mJavaObject);
231     jboolean ret = env->CallBooleanMethod(obj.get(), mCookiesEnabled);
232     return (ret != 0);
233 }
234
235 WTF::Vector<WTF::String>
236 JavaBridge::getPluginDirectories()
237 {
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);
248     }
249     env->DeleteLocalRef(array);
250     checkException(env);
251     return directories;
252 }
253
254 WTF::String
255 JavaBridge::getPluginSharedDataDirectory()
256 {
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);
261     checkException(env);
262     return path;
263 }
264
265 void
266 JavaBridge::setSharedTimerCallback(void (*f)())
267 {
268     LOG_ASSERT(!sSharedTimerFiredCallback || sSharedTimerFiredCallback==f,
269                "Shared timer callback may already be set or null!");
270
271     sSharedTimerFiredCallback = f;
272 }
273     
274 void JavaBridge::signalServiceFuncPtrQueue()
275 {
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);
282 }
283
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);
295     }
296     env->DeleteLocalRef(array);
297     checkException(env);
298     return list;
299 }
300
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);
314     return ret;
315 }
316
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);
325     return ret;
326 }
327
328 // ----------------------------------------------------------------------------
329
330 void JavaBridge::Constructor(JNIEnv* env, jobject obj)
331 {
332     JavaBridge* javaBridge = new JavaBridge(env, obj);
333     env->SetIntField(obj, gJavaBridge_ObjectID, (jint)javaBridge);
334 }
335
336 void JavaBridge::Finalize(JNIEnv* env, jobject obj)
337 {
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);
342     delete javaBridge;
343     env->SetIntField(obj, gJavaBridge_ObjectID, 0);
344 }
345
346 // we don't use the java bridge object, as we're just looking at a global
347 void JavaBridge::SharedTimerFired(JNIEnv* env, jobject)
348 {
349     if (sSharedTimerFiredCallback)
350     {
351 #ifdef ANDROID_INSTRUMENT
352         TimeCounter::start(TimeCounter::SharedTimerTimeCounter);
353 #endif
354         SkAutoMemoryUsageProbe  mup("JavaBridge::sharedTimerFired");
355         sSharedTimerFiredCallback();
356 #ifdef ANDROID_INSTRUMENT
357         TimeCounter::record(TimeCounter::SharedTimerTimeCounter, __FUNCTION__);
358 #endif
359     }
360 }
361
362 void JavaBridge::SetCacheSize(JNIEnv* env, jobject obj, jint bytes)
363 {
364     WebCore::cache()->setCapacities(0, bytes/2, bytes);
365 }
366
367 void JavaBridge::SetNetworkOnLine(JNIEnv* env, jobject obj, jboolean online)
368 {
369         WebCore::networkStateNotifier().networkStateChange(online);
370 }
371
372 void JavaBridge::SetNetworkType(JNIEnv* env, jobject obj, jstring javatype, jstring javasubtype)
373 {
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"));
380
381     String type = jstringToWtfString(env, javatype);
382     String subtype = jstringToWtfString(env, javasubtype);
383     Connection::ConnectionType connectionType = Connection::UNKNOWN;
384     if (type == wifi)
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;
391     }
392     WebCore::networkStateNotifier().networkTypeChange(connectionType);
393 }
394
395 void JavaBridge::ServiceFuncPtrQueue(JNIEnv*)
396 {
397     JavaSharedClient::ServiceFunctionPtrQueue();
398 }
399
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);
408     }
409     checkException(env);
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);
415 }
416
417 void JavaBridge::AddPackageNames(JNIEnv* env, jobject obj, jobject packageNames)
418 {
419     if (!packageNames)
420         return;
421
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);
427
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;");
431
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);
437     }
438
439     packageNotifier().addPackageNames(namesSet);
440
441     env->DeleteLocalRef(iteratorClass);
442     env->DeleteLocalRef(iter);
443     env->DeleteLocalRef(setClass);
444 }
445
446 void JavaBridge::AddPackageName(JNIEnv* env, jobject obj, jstring packageName)
447 {
448     packageNotifier().addPackageName(jstringToWtfString(env, packageName));
449 }
450
451 void JavaBridge::RemovePackageName(JNIEnv* env, jobject obj, jstring packageName)
452 {
453     packageNotifier().removePackageName(jstringToWtfString(env, packageName));
454 }
455
456
457 // ----------------------------------------------------------------------------
458
459 /*
460  * JNI registration.
461  */
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 }
486 };
487
488 int registerJavaBridge(JNIEnv* env)
489 {
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);
495
496     return jniRegisterNativeMethods(env, "android/webkit/JWebCoreJavaBridge", 
497                                     gWebCoreJavaBridgeMethods, NELEM(gWebCoreJavaBridgeMethods));
498 }
499
500 } /* namespace android */