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 \
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();
}
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();
}
#if PLATFORM(ANDROID)
#include "ApplicationInstalledCallback.h"
#include "Connection.h"
+#include "PackageNotifier.h"
#endif
namespace WebCore {
#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
#define Navigator_h
#include "NavigatorBase.h"
+#include "PlatformString.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
class MimeTypeArray;
class PluginData;
class PluginArray;
- class String;
#if PLATFORM(ANDROID)
class ApplicationInstalledCallback;
class Connection;
#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)
#if PLATFORM(ANDROID)
mutable RefPtr<Connection> m_connection;
#endif
+
+#if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED)
+ RefPtr<ApplicationInstalledCallback> m_applicationInstalledCallback;
+ String m_applicationNameQuery;
+#endif
};
}
#include "GeolocationController.h"
#endif
+#if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED)
+#include "PackageNotifier.h"
+#endif
+
namespace WebCore {
static HashSet<Page*>* allPages;
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))
allPages = new HashSet<Page*>;
networkStateNotifier().setNetworkStateChangedFunction(networkStateChanged);
+#if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED)
+ packageNotifier().setOnResultAvailable(onPackageResultAvailable);
+#endif
}
ASSERT(!allPages->contains(this));
--- /dev/null
+/*
+ * 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)
--- /dev/null
+/*
+ * 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
#include "KeyGeneratorClient.h"
#include "KURL.h"
#include "NetworkStateNotifier.h"
+#include "PackageNotifier.h"
#include "Page.h"
#include "PluginClient.h"
#include "PluginDatabase.h"
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;
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));
+}
+
+
// ----------------------------------------------------------------------------
/*
{ "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)