summaryrefslogtreecommitdiffstats
path: root/content/browser
diff options
context:
space:
mode:
authorjknotten@chromium.org <jknotten@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-09 12:12:09 +0000
committerjknotten@chromium.org <jknotten@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-09 12:12:09 +0000
commit5aab223f965826e7752d0f22487ed85ca2bcaa05 (patch)
tree588677002e89d620bce8359f831b426d49722ec9 /content/browser
parent61c9e8f83177bc9c4270c2d9f205e673f0f73b0f (diff)
downloadchromium_src-5aab223f965826e7752d0f22487ed85ca2bcaa05.zip
chromium_src-5aab223f965826e7752d0f22487ed85ca2bcaa05.tar.gz
chromium_src-5aab223f965826e7752d0f22487ed85ca2bcaa05.tar.bz2
Upstream Geolocation for Android.
TEST=content_unittests: GeolocationProvider.* LocationArbitrator.* There are also some integration tests downstream for the Java specific part. Review URL: https://chromiumcodereview.appspot.com/10209003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@136019 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser')
-rw-r--r--content/browser/DEPS1
-rw-r--r--content/browser/geolocation/arbitrator_dependency_factory.cc5
-rw-r--r--content/browser/geolocation/location_api_adapter_android.cc160
-rw-r--r--content/browser/geolocation/location_api_adapter_android.h83
-rw-r--r--content/browser/geolocation/location_provider.cc4
-rw-r--r--content/browser/geolocation/location_provider_android.cc48
-rw-r--r--content/browser/geolocation/location_provider_android.h35
7 files changed, 334 insertions, 2 deletions
diff --git a/content/browser/DEPS b/content/browser/DEPS
index d937ab9..9d94e0d 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -2,6 +2,7 @@ include_rules = [
"+content/gpu", # For gpu_info_collector.h and in-process GPU
"+content/port/browser",
"+content/public/browser",
+ "+jni", # For generated JNI includes
"+media/audio", # For audio input for speech input feature.
"+media/base/android", # For Android JNI registration.
diff --git a/content/browser/geolocation/arbitrator_dependency_factory.cc b/content/browser/geolocation/arbitrator_dependency_factory.cc
index 60225b6..170f6d3 100644
--- a/content/browser/geolocation/arbitrator_dependency_factory.cc
+++ b/content/browser/geolocation/arbitrator_dependency_factory.cc
@@ -33,8 +33,13 @@ DefaultGeolocationArbitratorDependencyFactory::NewNetworkLocationProvider(
net::URLRequestContextGetter* context,
const GURL& url,
const string16& access_token) {
+#if defined(OS_ANDROID)
+ // Android uses its own SystemLocationProvider.
+ return NULL;
+#else
return ::NewNetworkLocationProvider(access_token_store, context,
url, access_token);
+#endif
}
LocationProviderBase*
diff --git a/content/browser/geolocation/location_api_adapter_android.cc b/content/browser/geolocation/location_api_adapter_android.cc
new file mode 100644
index 0000000..f1c8948
--- /dev/null
+++ b/content/browser/geolocation/location_api_adapter_android.cc
@@ -0,0 +1,160 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/geolocation/location_api_adapter_android.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/bind.h"
+#include "base/location.h"
+#include "content/browser/geolocation/location_provider_android.h"
+#include "jni/location_provider_jni.h"
+
+using base::android::AttachCurrentThread;
+using base::android::CheckException;
+using base::android::ClearException;
+using base::android::GetMethodID;
+
+static void NewLocationAvailable(JNIEnv* env, jclass,
+ jdouble latitude,
+ jdouble longitude,
+ jlong time_stamp,
+ jboolean has_altitude, jdouble altitude,
+ jboolean has_accuracy, jdouble accuracy,
+ jboolean has_heading, jdouble heading,
+ jboolean has_speed, jdouble speed) {
+ AndroidLocationApiAdapter::OnNewLocationAvailable(latitude, longitude,
+ time_stamp, has_altitude, altitude, has_accuracy, accuracy,
+ has_heading, heading, has_speed, speed);
+}
+
+static void NewErrorAvailable(JNIEnv* env, jclass, jstring message) {
+ AndroidLocationApiAdapter::OnNewErrorAvailable(env, message);
+}
+
+AndroidLocationApiAdapter::AndroidLocationApiAdapter()
+ : location_provider_(NULL) {
+}
+
+AndroidLocationApiAdapter::~AndroidLocationApiAdapter() {
+ CHECK(!location_provider_);
+ CHECK(!message_loop_);
+ CHECK(java_location_provider_android_object_.is_null());
+}
+
+bool AndroidLocationApiAdapter::Start(
+ LocationProviderAndroid* location_provider, bool high_accuracy) {
+ JNIEnv* env = AttachCurrentThread();
+ if (!location_provider_) {
+ location_provider_ = location_provider;
+ CHECK(java_location_provider_android_object_.is_null());
+ CreateJavaObject(env);
+ {
+ base::AutoLock lock(lock_);
+ CHECK(!message_loop_.get());
+ message_loop_ = base::MessageLoopProxy::current();
+ }
+ }
+ // At this point we should have all our pre-conditions ready, and they'd only
+ // change in Stop() which must be called on the same thread as here.
+ CHECK(location_provider_);
+ CHECK(message_loop_.get());
+ CHECK(!java_location_provider_android_object_.is_null());
+ // We'll start receiving notifications from java in the main thread looper
+ // until Stop() is called.
+ return Java_LocationProvider_start(env,
+ java_location_provider_android_object_.obj(), high_accuracy);
+}
+
+void AndroidLocationApiAdapter::Stop() {
+ if (!location_provider_) {
+ CHECK(!message_loop_.get());
+ CHECK(java_location_provider_android_object_.is_null());
+ return;
+ }
+
+ {
+ base::AutoLock lock(lock_);
+ message_loop_ = NULL;
+ }
+
+ location_provider_ = NULL;
+
+ JNIEnv* env = AttachCurrentThread();
+ Java_LocationProvider_stop(env, java_location_provider_android_object_.obj());
+ java_location_provider_android_object_.Reset();
+}
+
+// static
+void AndroidLocationApiAdapter::NotifyProviderNewGeoposition(
+ const content::Geoposition& geoposition) {
+ // Called on the geolocation thread, safe to access location_provider_ here.
+ if (GetInstance()->location_provider_) {
+ CHECK(GetInstance()->message_loop_->BelongsToCurrentThread());
+ GetInstance()->location_provider_->NotifyNewGeoposition(geoposition);
+ }
+}
+
+// static
+void AndroidLocationApiAdapter::OnNewLocationAvailable(
+ double latitude, double longitude, long time_stamp,
+ bool has_altitude, double altitude,
+ bool has_accuracy, double accuracy,
+ bool has_heading, double heading,
+ bool has_speed, double speed) {
+ content::Geoposition position;
+ position.latitude = latitude;
+ position.longitude = longitude;
+ position.timestamp = base::Time::FromDoubleT(time_stamp / 1000.0);
+ if (has_altitude)
+ position.altitude = altitude;
+ if (has_accuracy)
+ position.accuracy = accuracy;
+ if (has_heading)
+ position.heading = heading;
+ if (has_speed)
+ position.speed = speed;
+ GetInstance()->OnNewGeopositionInternal(position);
+}
+
+// static
+void AndroidLocationApiAdapter::OnNewErrorAvailable(JNIEnv* env,
+ jstring message) {
+ content::Geoposition position_error;
+ position_error.error_code =
+ content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
+ position_error.error_message =
+ base::android::ConvertJavaStringToUTF8(env, message);
+ GetInstance()->OnNewGeopositionInternal(position_error);
+}
+
+// static
+AndroidLocationApiAdapter* AndroidLocationApiAdapter::GetInstance() {
+ return Singleton<AndroidLocationApiAdapter>::get();
+}
+
+// static
+bool AndroidLocationApiAdapter::RegisterGeolocationService(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+void AndroidLocationApiAdapter::CreateJavaObject(JNIEnv* env) {
+ // Create the Java AndroidLocationProvider object.
+ java_location_provider_android_object_.Reset(
+ Java_LocationProvider_create(env,
+ base::android::GetApplicationContext()));
+ CHECK(!java_location_provider_android_object_.is_null());
+}
+
+void AndroidLocationApiAdapter::OnNewGeopositionInternal(
+ const content::Geoposition& geoposition) {
+ base::AutoLock lock(lock_);
+ if (!message_loop_)
+ return;
+ message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &AndroidLocationApiAdapter::NotifyProviderNewGeoposition,
+ geoposition));
+}
diff --git a/content/browser/geolocation/location_api_adapter_android.h b/content/browser/geolocation/location_api_adapter_android.h
new file mode 100644
index 0000000..c2b4f85
--- /dev/null
+++ b/content/browser/geolocation/location_api_adapter_android.h
@@ -0,0 +1,83 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_GEOLOCATION_ANDROID_LOCATION_API_ADAPTER_H_
+#define CONTENT_BROWSER_GEOLOCATION_ANDROID_LOCATION_API_ADAPTER_H_
+#pragma once
+
+#include "base/android/scoped_java_ref.h"
+#include "base/synchronization/lock.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/singleton.h"
+#include "base/message_loop_proxy.h"
+#include "base/android/jni_helper.h"
+
+namespace content {
+struct Geoposition;
+}
+
+class LocationProviderAndroid;
+
+// Interacts with JNI and reports back to AndroidLocationProvider.
+// This class creates a LocationProvider java object and listens for
+// updates.
+// The simplified flow is:
+// GeolocationProvider runs in a Geolocation Thread and fetches geolocation data
+// from a LocationProvider.
+// AndroidLocationProvider access a singleton AndroidLocationApiAdapter
+// AndroidLocationApiAdapter calls via JNI and uses the main thread Looper
+// in the java side to listen for location updates. We then bounce these updates
+// to the Geolocation thread.
+// Note that AndroidLocationApiAdapter is a singleton and there's at most only
+// one AndroidLocationProvider that has called Start().
+class AndroidLocationApiAdapter {
+ public:
+ // Starts the underlying location provider, returns true if successful.
+ // Called on the Geolocation thread.
+ bool Start(LocationProviderAndroid* location_provider, bool high_accuracy);
+ // Stops the underlying location provider.
+ // Called on the Geolocation thread.
+ void Stop();
+
+ // Returns our singleton.
+ static AndroidLocationApiAdapter* GetInstance();
+
+ // Called when initializing chrome_view to obtain a pointer to the java class.
+ static bool RegisterGeolocationService(JNIEnv* env);
+
+ // Called by JNI on main thread looper.
+ static void OnNewLocationAvailable(double latitude,
+ double longitude,
+ long time_stamp,
+ bool has_altitude, double altitude,
+ bool has_accuracy, double accuracy,
+ bool has_heading, double heading,
+ bool has_speed, double speed);
+ static void OnNewErrorAvailable(JNIEnv* env, jstring message);
+
+ private:
+ friend struct DefaultSingletonTraits<AndroidLocationApiAdapter>;
+ AndroidLocationApiAdapter();
+ ~AndroidLocationApiAdapter();
+
+ void CreateJavaObject(JNIEnv* env);
+
+ // Called on the JNI main thread looper.
+ void OnNewGeopositionInternal(const content::Geoposition& geoposition);
+
+ /// Called on the Geolocation thread.
+ static void NotifyProviderNewGeoposition(
+ const content::Geoposition& geoposition);
+
+ base::android::ScopedJavaGlobalRef<jobject>
+ java_location_provider_android_object_;
+ LocationProviderAndroid* location_provider_;
+
+ // Guards against the following member which is accessed on Geolocation
+ // thread and the JNI main thread looper.
+ base::Lock lock_;
+ scoped_refptr<base::MessageLoopProxy> message_loop_;
+};
+
+#endif // CONTENT_BROWSER_GEOLOCATION_ANDROID_LOCATION_API_ADAPTER_H_
diff --git a/content/browser/geolocation/location_provider.cc b/content/browser/geolocation/location_provider.cc
index c58bf6b..d587b55 100644
--- a/content/browser/geolocation/location_provider.cc
+++ b/content/browser/geolocation/location_provider.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -56,7 +56,7 @@ void LocationProviderBase::UpdateListeners() {
}
}
-#if !defined(OS_LINUX) && !defined(OS_MACOSX) && !defined(OS_WIN)
+#if !defined(OS_LINUX) && !defined(OS_MACOSX) && !defined(OS_WIN) && !defined OS_ANDROID
LocationProviderBase* NewSystemLocationProvider() {
return NULL;
}
diff --git a/content/browser/geolocation/location_provider_android.cc b/content/browser/geolocation/location_provider_android.cc
new file mode 100644
index 0000000..8628679
--- /dev/null
+++ b/content/browser/geolocation/location_provider_android.cc
@@ -0,0 +1,48 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/geolocation/location_provider_android.h"
+
+#include "base/time.h"
+#include "content/browser/geolocation/location_api_adapter_android.h"
+#include "content/public/common/geoposition.h"
+
+// LocationProviderAndroid
+LocationProviderAndroid::LocationProviderAndroid() {
+}
+
+LocationProviderAndroid::~LocationProviderAndroid() {
+ StopProvider();
+}
+
+void LocationProviderAndroid::NotifyNewGeoposition(
+ const content::Geoposition& position) {
+ last_position_ = position;
+ UpdateListeners();
+}
+
+bool LocationProviderAndroid::StartProvider(bool high_accuracy) {
+ return AndroidLocationApiAdapter::GetInstance()->Start(this, high_accuracy);
+}
+
+void LocationProviderAndroid::StopProvider() {
+ AndroidLocationApiAdapter::GetInstance()->Stop();
+}
+
+void LocationProviderAndroid::GetPosition(content::Geoposition* position) {
+ *position = last_position_;
+}
+
+void LocationProviderAndroid::UpdatePosition() {
+ // Nothing to do here, android framework will call us back on new position.
+}
+
+void LocationProviderAndroid::OnPermissionGranted(
+ const GURL& requesting_frame) {
+ // Nothing to do here.
+}
+
+LocationProviderBase* NewSystemLocationProvider() {
+ return new LocationProviderAndroid;
+}
diff --git a/content/browser/geolocation/location_provider_android.h b/content/browser/geolocation/location_provider_android.h
new file mode 100644
index 0000000..748bca1
--- /dev/null
+++ b/content/browser/geolocation/location_provider_android.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_GEOLOCATION_LOCATION_PROVIDER_ANDROID_H_
+#define CONTENT_BROWSER_GEOLOCATION_LOCATION_PROVIDER_ANDROID_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/geolocation/location_provider.h"
+#include "content/public/common/geoposition.h"
+
+class AndroidLocationApiAdapter;
+struct Geoposition;
+
+// Location provider for Android using the platform provider over JNI.
+class LocationProviderAndroid : public LocationProviderBase {
+ public:
+ LocationProviderAndroid();
+ virtual ~LocationProviderAndroid();
+
+ // Called by the AndroidLocationApiAdapter.
+ void NotifyNewGeoposition(const content::Geoposition& position);
+
+ // LocationProviderBase.
+ virtual bool StartProvider(bool high_accuracy) OVERRIDE;
+ virtual void StopProvider() OVERRIDE;
+ virtual void GetPosition(content::Geoposition* position) OVERRIDE;
+ virtual void UpdatePosition() OVERRIDE;
+ virtual void OnPermissionGranted(const GURL& requesting_frame) OVERRIDE;
+
+ private:
+ content::Geoposition last_position_;
+};
+
+#endif // CONTENT_BROWSER_GEOLOCATION_LOCATION_PROVIDER_ANDROID_H_