diff options
-rw-r--r-- | WebCore/Android.mk | 1 | ||||
-rw-r--r-- | WebCore/bindings/js/JSNavigatorCustom.cpp | 3 | ||||
-rw-r--r-- | WebCore/bindings/v8/custom/V8NavigatorCustom.cpp | 4 | ||||
-rw-r--r-- | WebCore/page/Navigator.cpp | 23 | ||||
-rw-r--r-- | WebCore/page/Navigator.h | 10 | ||||
-rw-r--r-- | WebCore/page/Page.cpp | 18 | ||||
-rw-r--r-- | WebCore/platform/android/PackageNotifier.cpp | 97 | ||||
-rw-r--r-- | WebCore/platform/android/PackageNotifier.h | 69 | ||||
-rw-r--r-- | WebKit/android/jni/JavaBridge.cpp | 53 |
9 files changed, 270 insertions, 8 deletions
diff --git a/WebCore/Android.mk b/WebCore/Android.mk index de67b20..f153c9c 100644 --- a/WebCore/Android.mk +++ b/WebCore/Android.mk @@ -410,6 +410,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ platform/android/PlatformTouchPointAndroid.cpp \ platform/android/PopupMenuAndroid.cpp \ platform/android/RenderThemeAndroid.cpp \ + platform/android/PackageNotifier.cpp \ platform/android/ScreenAndroid.cpp \ platform/android/ScrollViewAndroid.cpp \ platform/android/SearchPopupMenuAndroid.cpp \ diff --git a/WebCore/bindings/js/JSNavigatorCustom.cpp b/WebCore/bindings/js/JSNavigatorCustom.cpp index b30db5a..af0c9ae 100644 --- a/WebCore/bindings/js/JSNavigatorCustom.cpp +++ b/WebCore/bindings/js/JSNavigatorCustom.cpp @@ -69,7 +69,8 @@ JSC::JSValue WebCore::JSNavigator::isApplicationInstalled(JSC::ExecState* exec, RefPtr<ApplicationInstalledCallback> callback(JSCustomApplicationInstalledCallback::create( object, static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject()))); - m_impl->isApplicationInstalled(appName, callback.release()); + if (!m_impl->isApplicationInstalled(appName, callback.release())) + setDOMException(exec, INVALID_STATE_ERR); return jsUndefined(); } diff --git a/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp b/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp index c3c406e..b6ae42d 100644 --- a/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp @@ -84,7 +84,9 @@ v8::Handle<v8::Value> V8Navigator::isApplicationInstalledCallback(const v8::Argu ASSERT(callback); Navigator* navigator = V8Navigator::toNative(args.Holder()); - navigator->isApplicationInstalled(toWebCoreString(args[0]), callback.release()); + if (!navigator->isApplicationInstalled(toWebCoreString(args[0]), callback.release())) + return throwError(INVALID_STATE_ERR); + return v8::Undefined(); } diff --git a/WebCore/page/Navigator.cpp b/WebCore/page/Navigator.cpp index 3c0424f..bb07911 100644 --- a/WebCore/page/Navigator.cpp +++ b/WebCore/page/Navigator.cpp @@ -45,6 +45,7 @@ #if PLATFORM(ANDROID) #include "ApplicationInstalledCallback.h" #include "Connection.h" +#include "PackageNotifier.h" #endif namespace WebCore { @@ -171,10 +172,26 @@ Connection* Navigator::connection() const #endif #if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED) -void Navigator::isApplicationInstalled(const String& name, PassRefPtr<ApplicationInstalledCallback> callback) + +bool Navigator::isApplicationInstalled(const String& name, PassRefPtr<ApplicationInstalledCallback> callback) +{ + if (m_applicationInstalledCallback) + return false; + + m_applicationInstalledCallback = callback; + m_applicationNameQuery = name; + + packageNotifier().requestPackageResult(); + + return true; +} + +void Navigator::onPackageResult() { - //TODO(implement); - callback->handleEvent(false); + if (m_applicationInstalledCallback) { + m_applicationInstalledCallback->handleEvent(packageNotifier().isPackageInstalled(m_applicationNameQuery)); + m_applicationInstalledCallback = 0; + } } #endif diff --git a/WebCore/page/Navigator.h b/WebCore/page/Navigator.h index 83ed83f..c6acfd5 100644 --- a/WebCore/page/Navigator.h +++ b/WebCore/page/Navigator.h @@ -21,6 +21,7 @@ #define Navigator_h #include "NavigatorBase.h" +#include "PlatformString.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> @@ -32,7 +33,6 @@ namespace WebCore { class MimeTypeArray; class PluginData; class PluginArray; - class String; #if PLATFORM(ANDROID) class ApplicationInstalledCallback; class Connection; @@ -67,7 +67,8 @@ namespace WebCore { #endif #if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED) - void isApplicationInstalled(const String& name, PassRefPtr<ApplicationInstalledCallback> callback); + bool isApplicationInstalled(const String& name, PassRefPtr<ApplicationInstalledCallback> callback); + void onPackageResult(); #endif #if ENABLE(DOM_STORAGE) @@ -87,6 +88,11 @@ namespace WebCore { #if PLATFORM(ANDROID) mutable RefPtr<Connection> m_connection; #endif + +#if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED) + RefPtr<ApplicationInstalledCallback> m_applicationInstalledCallback; + String m_applicationNameQuery; +#endif }; } diff --git a/WebCore/page/Page.cpp b/WebCore/page/Page.cpp index 1704bfb..b685e59 100644 --- a/WebCore/page/Page.cpp +++ b/WebCore/page/Page.cpp @@ -81,6 +81,10 @@ #include "GeolocationController.h" #endif +#if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED) +#include "PackageNotifier.h" +#endif + namespace WebCore { static HashSet<Page*>* allPages; @@ -105,6 +109,17 @@ static void networkStateChanged() frames[i]->document()->dispatchWindowEvent(Event::create(eventName, false, false)); } +#if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED) +static void onPackageResultAvailable() +{ + HashSet<Page*>::iterator end = allPages->end(); + for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) { + for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) + frame->domWindow()->navigator()->onPackageResult(); + } +} +#endif + Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, EditorClient* editorClient, DragClient* dragClient, InspectorClient* inspectorClient, PluginHalterClient* pluginHalterClient, GeolocationControllerClient* geolocationControllerClient) : m_chrome(new Chrome(this, chromeClient)) , m_dragCaretController(new SelectionController(0, true)) @@ -163,6 +178,9 @@ Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, Edi allPages = new HashSet<Page*>; networkStateNotifier().setNetworkStateChangedFunction(networkStateChanged); +#if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED) + packageNotifier().setOnResultAvailable(onPackageResultAvailable); +#endif } ASSERT(!allPages->contains(this)); diff --git a/WebCore/platform/android/PackageNotifier.cpp b/WebCore/platform/android/PackageNotifier.cpp new file mode 100644 index 0000000..e057cdf --- /dev/null +++ b/WebCore/platform/android/PackageNotifier.cpp @@ -0,0 +1,97 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PackageNotifier.h" + +#if ENABLE(APPLICATION_INSTALLED) + +#include <wtf/Assertions.h> +#include <wtf/StdLibExtras.h> + +namespace WebCore { + +PackageNotifier::PackageNotifier() + : m_onResultAvailable(0), m_isInitialized(false), m_timer(this, &PackageNotifier::timerFired) { } + +void PackageNotifier::setOnResultAvailable(Callback callback) +{ + m_onResultAvailable = callback; +} + +void PackageNotifier::addPackageNames(const HashSet<String>& packageNames) +{ + if (!m_isInitialized) + m_isInitialized = true; + + typedef HashSet<String>::const_iterator NamesIterator; + for (NamesIterator iter = packageNames.begin(); iter != packageNames.end(); ++iter) + m_packageNames.add(*iter); + + if (m_onResultAvailable) + m_onResultAvailable(); +} + +void PackageNotifier::addPackageName(const String& packageName) +{ + ASSERT(m_isInitialized); + m_packageNames.add(packageName); +} + +void PackageNotifier::removePackageName(const String& packageName) +{ + ASSERT(m_isInitialized); + m_packageNames.remove(packageName); +} + +void PackageNotifier::requestPackageResult() +{ + if (!m_isInitialized || m_timer.isActive()) + return; + + m_timer.startOneShot(0); +} + +void PackageNotifier::timerFired(Timer<PackageNotifier>*) +{ + m_timer.stop(); + if (m_onResultAvailable) + m_onResultAvailable(); +} + +bool PackageNotifier::isPackageInstalled(const String& packageName) +{ + return m_packageNames.contains(packageName); +} + +PackageNotifier& packageNotifier() +{ + AtomicallyInitializedStatic(PackageNotifier*, packageNotifier = new PackageNotifier); + return *packageNotifier; +} + +} + +#endif // ENABLE(APPLICATION_INSTALLED) diff --git a/WebCore/platform/android/PackageNotifier.h b/WebCore/platform/android/PackageNotifier.h new file mode 100644 index 0000000..ad44bc7 --- /dev/null +++ b/WebCore/platform/android/PackageNotifier.h @@ -0,0 +1,69 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PackageNotifier_h +#define PackageNotifier_h + +#if ENABLE(APPLICATION_INSTALLED) + +#include "PlatformString.h" +#include "StringHash.h" +#include "Timer.h" +#include <wtf/HashSet.h> +#include <wtf/Noncopyable.h> + +namespace WebCore { + +class PackageNotifier : public Noncopyable { +public: + PackageNotifier(); + + typedef void (*Callback)(); + void setOnResultAvailable(Callback); + + void addPackageNames(const HashSet<String>& packageNames); + void addPackageName(const String& packageName); + void removePackageName(const String& packageName); + + void requestPackageResult(); + bool isPackageInstalled(const String& packageName); + +private: + void timerFired(Timer<PackageNotifier>*); + + Callback m_onResultAvailable; + + HashSet<String> m_packageNames; + bool m_isInitialized; + Timer<PackageNotifier> m_timer; +}; + +PackageNotifier& packageNotifier(); + +} + +#endif + +#endif // PackageNotifier_h
\ No newline at end of file diff --git a/WebKit/android/jni/JavaBridge.cpp b/WebKit/android/jni/JavaBridge.cpp index feca297..0e65e1c 100644 --- a/WebKit/android/jni/JavaBridge.cpp +++ b/WebKit/android/jni/JavaBridge.cpp @@ -35,6 +35,7 @@ #include "KeyGeneratorClient.h" #include "KURL.h" #include "NetworkStateNotifier.h" +#include "PackageNotifier.h" #include "Page.h" #include "PluginClient.h" #include "PluginDatabase.h" @@ -102,6 +103,10 @@ public: static void SetDeferringTimers(JNIEnv* env, jobject obj, jboolean defer); static void ServiceFuncPtrQueue(JNIEnv*); static void UpdatePluginDirectories(JNIEnv* env, jobject obj, jobjectArray array, jboolean reload); + static void AddPackageNames(JNIEnv* env, jobject obj, jobject packageNames); + static void AddPackageName(JNIEnv* env, jobject obj, jstring packageName); + static void RemovePackageName(JNIEnv* env, jobject obj, jstring packageName); + private: jweak mJavaObject; @@ -392,6 +397,46 @@ void JavaBridge::UpdatePluginDirectories(JNIEnv* env, jobject obj, WebCore::Page::refreshPlugins(reload); } +void JavaBridge::AddPackageNames(JNIEnv* env, jobject obj, jobject packageNames) +{ + if (!packageNames) + return; + + // dalvikvm will raise exception if any of these fail + jclass setClass = env->FindClass("java/util/Set"); + jmethodID iterator = env->GetMethodID(setClass, "iterator", + "()Ljava/util/Iterator;"); + jobject iter = env->CallObjectMethod(packageNames, iterator); + + jclass iteratorClass = env->FindClass("java/util/Iterator"); + jmethodID hasNext = env->GetMethodID(iteratorClass, "hasNext", "()Z"); + jmethodID next = env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;"); + + HashSet<WebCore::String> namesSet; + while (env->CallBooleanMethod(iter, hasNext)) { + jstring name = static_cast<jstring>(env->CallObjectMethod(iter, next)); + namesSet.add(to_string(env, name)); + env->DeleteLocalRef(name); + } + + packageNotifier().addPackageNames(namesSet); + + env->DeleteLocalRef(iteratorClass); + env->DeleteLocalRef(iter); + env->DeleteLocalRef(setClass); +} + +void JavaBridge::AddPackageName(JNIEnv* env, jobject obj, jstring packageName) +{ + packageNotifier().addPackageName(to_string(env, packageName)); +} + +void JavaBridge::RemovePackageName(JNIEnv* env, jobject obj, jstring packageName) +{ + packageNotifier().removePackageName(to_string(env, packageName)); +} + + // ---------------------------------------------------------------------------- /* @@ -414,7 +459,13 @@ static JNINativeMethod gWebCoreJavaBridgeMethods[] = { { "nativeServiceFuncPtrQueue", "()V", (void*) JavaBridge::ServiceFuncPtrQueue }, { "nativeUpdatePluginDirectories", "([Ljava/lang/String;Z)V", - (void*) JavaBridge::UpdatePluginDirectories } + (void*) JavaBridge::UpdatePluginDirectories }, + { "addPackageNames", "(Ljava/util/Set;)V", + (void*) JavaBridge::AddPackageNames }, + { "addPackageName", "(Ljava/lang/String;)V", + (void*) JavaBridge::AddPackageName }, + { "removePackageName", "(Ljava/lang/String;)V", + (void*) JavaBridge::RemovePackageName } }; int register_javabridge(JNIEnv* env) |