GeolocationServiceBridge.cpp [plain text]
#include "config.h"
#include "GeolocationServiceBridge.h"
#include "GeolocationServiceAndroid.h"
#include "Geoposition.h"
#include "PositionError.h"
#include "WebViewCore.h"
#include <JNIHelp.h>
namespace WebCore {
using JSC::Bindings::getJNIEnv;
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(ListenerInterface* listener)
: m_listener(listener)
, m_javaGeolocationServiceObject(0)
{
ASSERT(m_listener);
startJavaImplementation();
}
GeolocationServiceBridge::~GeolocationServiceBridge()
{
stop();
stopJavaImplementation();
}
void GeolocationServiceBridge::start()
{
ASSERT(m_javaGeolocationServiceObject);
getJNIEnv()->CallVoidMethod(m_javaGeolocationServiceObject,
javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStart]);
}
void GeolocationServiceBridge::stop()
{
ASSERT(m_javaGeolocationServiceObject);
getJNIEnv()->CallVoidMethod(m_javaGeolocationServiceObject,
javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStop]);
}
void GeolocationServiceBridge::setEnableGps(bool enable)
{
ASSERT(m_javaGeolocationServiceObject);
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::to_string(env, message));
object->m_listener->newErrorAvailable(error.release());
}
PassRefPtr<Geoposition> GeolocationServiceBridge::toGeoposition(JNIEnv *env, const jobject &location)
{
bool hasAltitude =
env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasAltitude]);
double Altitude =
hasAltitude ?
env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetAltitude]) :
0.0;
double Accuracy =
env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasAccuracy]) ?
env->CallFloatMethod(location, javaLocationClassMethodIDs[LocationMethodGetAccuracy]) :
0.0;
bool hasHeading =
env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasBearing]);
double heading =
hasHeading ?
env->CallFloatMethod(location, javaLocationClassMethodIDs[LocationMethodGetBearing]) :
0.0;
bool hasSpeed =
env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasSpeed]);
double speed =
hasSpeed ?
env->CallFloatMethod(location, javaLocationClassMethodIDs[LocationMethodGetSpeed]) :
0.0;
RefPtr<Coordinates> newCoordinates = WebCore::Coordinates::create(
env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetLatitude]),
env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetLongitude]),
hasAltitude, Altitude,
Accuracy,
false, 0.0, hasHeading, heading,
hasSpeed, speed);
return WebCore::Geoposition::create(
newCoordinates.release(),
env->CallLongMethod(location, javaLocationClassMethodIDs[LocationMethodGetTime]));
}
void GeolocationServiceBridge::startJavaImplementation()
{
JNIEnv* env = getJNIEnv();
jclass javaGeolocationServiceClass = env->FindClass(javaGeolocationServiceClassName);
ASSERT(javaGeolocationServiceClass);
javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodInit] =
env->GetMethodID(javaGeolocationServiceClass, "<init>", "(J)V");
javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStart] =
env->GetMethodID(javaGeolocationServiceClass, "start", "()V");
javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStop] =
env->GetMethodID(javaGeolocationServiceClass, "stop", "()V");
javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodSetEnableGps] =
env->GetMethodID(javaGeolocationServiceClass, "setEnableGps", "(Z)V");
jlong nativeObject = reinterpret_cast<jlong>(this);
jobject object = env->NewObject(javaGeolocationServiceClass,
javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodInit],
nativeObject);
m_javaGeolocationServiceObject = getJNIEnv()->NewGlobalRef(object);
ASSERT(m_javaGeolocationServiceObject);
static int registered = jniRegisterNativeMethods(env,
javaGeolocationServiceClassName,
javaGeolocationServiceClassNativeMethods,
NELEM(javaGeolocationServiceClassNativeMethods));
ASSERT(registered == JNI_OK);
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()
{
ASSERT(m_javaGeolocationServiceObject);
getJNIEnv()->DeleteGlobalRef(m_javaGeolocationServiceObject);
}
}