diff options
author | Steve Block <steveblock@google.com> | 2012-05-17 18:36:32 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2012-05-18 12:16:12 +0100 |
commit | 0769e328661adb91472349fbfa3a5474a1f7ee0d (patch) | |
tree | 6ce8f5d3ab3c6f3cfd2fb3c18826092f1bdae9ff /Source/WebKit/android | |
parent | 084a2f00a6b30ce87ec8a8eabbea3ac9cbfa6e7e (diff) | |
download | external_webkit-0769e328661adb91472349fbfa3a5474a1f7ee0d.zip external_webkit-0769e328661adb91472349fbfa3a5474a1f7ee0d.tar.gz external_webkit-0769e328661adb91472349fbfa3a5474a1f7ee0d.tar.bz2 |
Move GeolocationServiceBridge to WebKit/android/jni and extract Listener interface
Also modify GeolocationServiceBridge to take a WebViewCore rather than a Frame.
This will simplify the transition to client-based implementation, which will
re-use GeolocationServiceBridge.
No functional change.
Bug: 6511338
Change-Id: I2de9dfed51d785c85b40f362f20189f208adf6ec
Diffstat (limited to 'Source/WebKit/android')
-rw-r--r-- | Source/WebKit/android/jni/GeolocationServiceBridge.cpp | 249 | ||||
-rw-r--r-- | Source/WebKit/android/jni/GeolocationServiceBridge.h | 75 |
2 files changed, 324 insertions, 0 deletions
diff --git a/Source/WebKit/android/jni/GeolocationServiceBridge.cpp b/Source/WebKit/android/jni/GeolocationServiceBridge.cpp new file mode 100644 index 0000000..044131f --- /dev/null +++ b/Source/WebKit/android/jni/GeolocationServiceBridge.cpp @@ -0,0 +1,249 @@ +/* + * Copyright 2012, 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 "GeolocationServiceBridge.h" + +#include "GeolocationServiceAndroid.h" +#include "WebViewCore.h" + +#include <Geoposition.h> +#include <JNIHelp.h> +#include <PositionError.h> + +using JSC::Bindings::getJNIEnv; +using WebCore::Coordinates; +using WebCore::Geoposition; +using WebCore::PositionError; + +namespace android { + +static const char* javaGeolocationServiceClassName = "android/webkit/GeolocationService"; +enum javaGeolocationServiceClassMethods { + GeolocationServiceMethodInit = 0, + GeolocationServiceMethodStart, + GeolocationServiceMethodStop, + GeolocationServiceMethodSetEnableGps, + GeolocationServiceMethodCount, +}; +static jmethodID javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodCount]; + +static const JNINativeMethod javaGeolocationServiceClassNativeMethods[] = { + { "nativeNewLocationAvailable", "(JLandroid/location/Location;)V", + (void*) GeolocationServiceBridge::newLocationAvailable }, + { "nativeNewErrorAvailable", "(JLjava/lang/String;)V", + (void*) GeolocationServiceBridge::newErrorAvailable } +}; + +static const char *javaLocationClassName = "android/location/Location"; +enum javaLocationClassMethods { + LocationMethodGetLatitude = 0, + LocationMethodGetLongitude, + LocationMethodHasAltitude, + LocationMethodGetAltitude, + LocationMethodHasAccuracy, + LocationMethodGetAccuracy, + LocationMethodHasBearing, + LocationMethodGetBearing, + LocationMethodHasSpeed, + LocationMethodGetSpeed, + LocationMethodGetTime, + LocationMethodCount, +}; +static jmethodID javaLocationClassMethodIDs[LocationMethodCount]; + +GeolocationServiceBridge::GeolocationServiceBridge(Listener* listener, WebViewCore* webViewCore) + : m_listener(listener) + , m_javaGeolocationServiceObject(0) +{ + ASSERT(m_listener); + startJavaImplementation(webViewCore); +} + +GeolocationServiceBridge::~GeolocationServiceBridge() +{ + stop(); + stopJavaImplementation(); +} + +bool GeolocationServiceBridge::start() +{ + if (!m_javaGeolocationServiceObject) + return false; + return getJNIEnv()->CallBooleanMethod(m_javaGeolocationServiceObject, + javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStart]); +} + +void GeolocationServiceBridge::stop() +{ + if (!m_javaGeolocationServiceObject) + return; + getJNIEnv()->CallVoidMethod(m_javaGeolocationServiceObject, + javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStop]); +} + +void GeolocationServiceBridge::setEnableGps(bool enable) +{ + if (!m_javaGeolocationServiceObject) + return; + getJNIEnv()->CallVoidMethod(m_javaGeolocationServiceObject, + javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodSetEnableGps], + enable); +} + +void GeolocationServiceBridge::newLocationAvailable(JNIEnv* env, jclass, jlong nativeObject, jobject location) +{ + ASSERT(nativeObject); + ASSERT(location); + GeolocationServiceBridge* object = reinterpret_cast<GeolocationServiceBridge*>(nativeObject); + object->m_listener->newPositionAvailable(toGeoposition(env, location)); +} + +void GeolocationServiceBridge::newErrorAvailable(JNIEnv* env, jclass, jlong nativeObject, jstring message) +{ + GeolocationServiceBridge* object = reinterpret_cast<GeolocationServiceBridge*>(nativeObject); + RefPtr<PositionError> error = + PositionError::create(PositionError::POSITION_UNAVAILABLE, android::jstringToWtfString(env, message)); + object->m_listener->newErrorAvailable(error.release()); +} + +PassRefPtr<Geoposition> GeolocationServiceBridge::toGeoposition(JNIEnv *env, const jobject &location) +{ + // Altitude is optional and may not be supplied. + bool hasAltitude = + env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasAltitude]); + double Altitude = + hasAltitude ? + env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetAltitude]) : + 0.0; + // Accuracy is required, but is not supplied by the emulator. + double Accuracy = + env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasAccuracy]) ? + env->CallFloatMethod(location, javaLocationClassMethodIDs[LocationMethodGetAccuracy]) : + 0.0; + // heading is optional and may not be supplied. + bool hasHeading = + env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasBearing]); + double heading = + hasHeading ? + env->CallFloatMethod(location, javaLocationClassMethodIDs[LocationMethodGetBearing]) : + 0.0; + // speed is optional and may not be supplied. + bool hasSpeed = + env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasSpeed]); + double speed = + hasSpeed ? + env->CallFloatMethod(location, javaLocationClassMethodIDs[LocationMethodGetSpeed]) : + 0.0; + + RefPtr<Coordinates> newCoordinates = Coordinates::create( + env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetLatitude]), + env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetLongitude]), + hasAltitude, Altitude, + Accuracy, + false, 0.0, // AltitudeAccuracy not provided. + hasHeading, heading, + hasSpeed, speed); + + return Geoposition::create( + newCoordinates.release(), + env->CallLongMethod(location, javaLocationClassMethodIDs[LocationMethodGetTime])); +} + +void GeolocationServiceBridge::startJavaImplementation(WebViewCore* webViewCore) +{ + JNIEnv* env = getJNIEnv(); + + // Get the Java GeolocationService class. + jclass javaGeolocationServiceClass = env->FindClass(javaGeolocationServiceClassName); + ASSERT(javaGeolocationServiceClass); + + // Set up the methods we wish to call on the Java GeolocationService class. + javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodInit] = + env->GetMethodID(javaGeolocationServiceClass, "<init>", "(Landroid/content/Context;J)V"); + javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStart] = + env->GetMethodID(javaGeolocationServiceClass, "start", "()Z"); + javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStop] = + env->GetMethodID(javaGeolocationServiceClass, "stop", "()V"); + javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodSetEnableGps] = + env->GetMethodID(javaGeolocationServiceClass, "setEnableGps", "(Z)V"); + + // Create the Java GeolocationService object. + jobject context = webViewCore->getContext(); + if (!context) + return; + jlong nativeObject = reinterpret_cast<jlong>(this); + jobject object = env->NewObject(javaGeolocationServiceClass, + javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodInit], + context, + nativeObject); + + m_javaGeolocationServiceObject = getJNIEnv()->NewGlobalRef(object); + ASSERT(m_javaGeolocationServiceObject); + + // Register to handle calls to native methods of the Java GeolocationService + // object. We register once only. + static int registered = jniRegisterNativeMethods(env, + javaGeolocationServiceClassName, + javaGeolocationServiceClassNativeMethods, + NELEM(javaGeolocationServiceClassNativeMethods)); + ASSERT(registered == JNI_OK); + + // Set up the methods we wish to call on the Java Location class. + jclass javaLocationClass = env->FindClass(javaLocationClassName); + ASSERT(javaLocationClass); + javaLocationClassMethodIDs[LocationMethodGetLatitude] = + env->GetMethodID(javaLocationClass, "getLatitude", "()D"); + javaLocationClassMethodIDs[LocationMethodGetLongitude] = + env->GetMethodID(javaLocationClass, "getLongitude", "()D"); + javaLocationClassMethodIDs[LocationMethodHasAltitude] = + env->GetMethodID(javaLocationClass, "hasAltitude", "()Z"); + javaLocationClassMethodIDs[LocationMethodGetAltitude] = + env->GetMethodID(javaLocationClass, "getAltitude", "()D"); + javaLocationClassMethodIDs[LocationMethodHasAccuracy] = + env->GetMethodID(javaLocationClass, "hasAccuracy", "()Z"); + javaLocationClassMethodIDs[LocationMethodGetAccuracy] = + env->GetMethodID(javaLocationClass, "getAccuracy", "()F"); + javaLocationClassMethodIDs[LocationMethodHasBearing] = + env->GetMethodID(javaLocationClass, "hasBearing", "()Z"); + javaLocationClassMethodIDs[LocationMethodGetBearing] = + env->GetMethodID(javaLocationClass, "getBearing", "()F"); + javaLocationClassMethodIDs[LocationMethodHasSpeed] = + env->GetMethodID(javaLocationClass, "hasSpeed", "()Z"); + javaLocationClassMethodIDs[LocationMethodGetSpeed] = + env->GetMethodID(javaLocationClass, "getSpeed", "()F"); + javaLocationClassMethodIDs[LocationMethodGetTime] = + env->GetMethodID(javaLocationClass, "getTime", "()J"); +} + +void GeolocationServiceBridge::stopJavaImplementation() +{ + // Called by GeolocationServiceAndroid on WebKit thread. + if (!m_javaGeolocationServiceObject) + return; + getJNIEnv()->DeleteGlobalRef(m_javaGeolocationServiceObject); +} + +} // namespace WebCore diff --git a/Source/WebKit/android/jni/GeolocationServiceBridge.h b/Source/WebKit/android/jni/GeolocationServiceBridge.h new file mode 100644 index 0000000..1813984 --- /dev/null +++ b/Source/WebKit/android/jni/GeolocationServiceBridge.h @@ -0,0 +1,75 @@ +/* + * Copyright 2012, 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 GeolocationServiceBridge_h +#define GeolocationServiceBridge_h + +#include <JNIUtility.h> +#include <wtf/PassRefPtr.h> + +namespace WebCore { +class Geoposition; +class PositionError; +} + +namespace android { + +class WebViewCore; + +// GeolocationServiceBridge is the bridge to the Java implementation. It manages +// the lifetime of the Java object. It is an implementation detail of +// GeolocationServiceAndroid. +class GeolocationServiceBridge { +public: + class Listener { + public: + virtual ~Listener() {} + virtual void newPositionAvailable(PassRefPtr<WebCore::Geoposition>) = 0; + virtual void newErrorAvailable(PassRefPtr<WebCore::PositionError>) = 0; + }; + + GeolocationServiceBridge(Listener*, WebViewCore*); + ~GeolocationServiceBridge(); + + bool start(); + void stop(); + void setEnableGps(bool enable); + + // Static wrapper functions to hide JNI nastiness. + static void newLocationAvailable(JNIEnv *env, jclass, jlong nativeObject, jobject location); + static void newErrorAvailable(JNIEnv *env, jclass, jlong nativeObject, jstring message); + static PassRefPtr<WebCore::Geoposition> toGeoposition(JNIEnv *env, const jobject &location); + +private: + void startJavaImplementation(WebViewCore*); + void stopJavaImplementation(); + + Listener* m_listener; + jobject m_javaGeolocationServiceObject; +}; + +} // namespace android + +#endif // GeolocationServiceBridge_h |