Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Unified Diff: content/public/android/java/src/org/chromium/content/browser/LocationProviderFactory.java

Issue 2188933002: Revert of Reland: Geolocation: move from content/browser to device/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/public/android/java/src/org/chromium/content/browser/LocationProviderFactory.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/LocationProviderFactory.java b/content/public/android/java/src/org/chromium/content/browser/LocationProviderFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..a9e74d93e09e415fee9f8dba27f42e22610617a7
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/LocationProviderFactory.java
@@ -0,0 +1,212 @@
+// Copyright 2013 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.
+
+package org.chromium.content.browser;
+
+import android.content.Context;
+import android.location.Criteria;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Bundle;
+
+import org.chromium.base.Log;
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.VisibleForTesting;
+
+import java.util.List;
+
+/**
+ * Factory to create a LocationProvider to allow us to inject
+ * a mock for tests.
+ */
+public class LocationProviderFactory {
+ private static LocationProviderFactory.LocationProvider sProviderImpl;
+
+ /**
+ * LocationProviderFactory.get() returns an instance of this interface.
+ */
+ public interface LocationProvider {
+ public void start(boolean enableHighAccuracy);
+ public void stop();
+ public boolean isRunning();
+ }
+
+ private LocationProviderFactory() {
+ }
+
+ @VisibleForTesting
+ public static void setLocationProviderImpl(LocationProviderFactory.LocationProvider provider) {
+ assert sProviderImpl == null;
+ sProviderImpl = provider;
+ }
+
+ public static LocationProvider get(Context context) {
+ if (sProviderImpl == null) {
+ sProviderImpl = new LocationProviderImpl(context);
+ }
+ return sProviderImpl;
+ }
+
+ /**
+ * This is the core of android location provider. It is a separate class for clarity
+ * so that it can manage all processing completely in the UI thread. The container class
+ * ensures that the start/stop calls into this class are done in the UI thread.
+ */
+ private static class LocationProviderImpl
+ implements LocationListener, LocationProviderFactory.LocationProvider {
+
+ // Log tag
+ private static final String TAG = "cr.LocationProvider";
+
+ private Context mContext;
+ private LocationManager mLocationManager;
+ private boolean mIsRunning;
+
+ LocationProviderImpl(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Start listening for location updates.
+ * @param enableHighAccuracy Whether or not to enable high accuracy location providers.
+ */
+ @Override
+ public void start(boolean enableHighAccuracy) {
+ unregisterFromLocationUpdates();
+ registerForLocationUpdates(enableHighAccuracy);
+ }
+
+ /**
+ * Stop listening for location updates.
+ */
+ @Override
+ public void stop() {
+ unregisterFromLocationUpdates();
+ }
+
+ /**
+ * Returns true if we are currently listening for location updates, false if not.
+ */
+ @Override
+ public boolean isRunning() {
+ return mIsRunning;
+ }
+
+ @Override
+ public void onLocationChanged(Location location) {
+ // Callbacks from the system location service are queued to this thread, so it's
+ // possible that we receive callbacks after unregistering. At this point, the
+ // native object will no longer exist.
+ if (mIsRunning) {
+ updateNewLocation(location);
+ }
+ }
+
+ private void updateNewLocation(Location location) {
+ LocationProviderAdapter.newLocationAvailable(
+ location.getLatitude(), location.getLongitude(),
+ location.getTime() / 1000.0,
+ location.hasAltitude(), location.getAltitude(),
+ location.hasAccuracy(), location.getAccuracy(),
+ location.hasBearing(), location.getBearing(),
+ location.hasSpeed(), location.getSpeed());
+ }
+
+ @Override
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ }
+
+ @Override
+ public void onProviderEnabled(String provider) {
+ }
+
+ @Override
+ public void onProviderDisabled(String provider) {
+ }
+
+ private void ensureLocationManagerCreated() {
+ if (mLocationManager != null) return;
+ mLocationManager = (LocationManager) mContext.getSystemService(
+ Context.LOCATION_SERVICE);
+ if (mLocationManager == null) {
+ Log.e(TAG, "Could not get location manager.");
+ }
+ }
+
+ /**
+ * Registers this object with the location service.
+ */
+ private void registerForLocationUpdates(boolean enableHighAccuracy) {
+ ensureLocationManagerCreated();
+ if (usePassiveOneShotLocation()) return;
+
+ assert !mIsRunning;
+ mIsRunning = true;
+
+ // We're running on the main thread. The C++ side is responsible to
+ // bounce notifications to the Geolocation thread as they arrive in the mainLooper.
+ try {
+ Criteria criteria = new Criteria();
+ if (enableHighAccuracy) criteria.setAccuracy(Criteria.ACCURACY_FINE);
+ mLocationManager.requestLocationUpdates(0, 0, criteria, this,
+ ThreadUtils.getUiThreadLooper());
+ } catch (SecurityException e) {
+ Log.e(TAG, "Caught security exception while registering for location updates "
+ + "from the system. The application does not have sufficient geolocation "
+ + "permissions.");
+ unregisterFromLocationUpdates();
+ // Propagate an error to JavaScript, this can happen in case of WebView
+ // when the embedding app does not have sufficient permissions.
+ LocationProviderAdapter.newErrorAvailable("application does not have sufficient "
+ + "geolocation permissions.");
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Caught IllegalArgumentException registering for location updates.");
+ unregisterFromLocationUpdates();
+ assert false;
+ }
+ }
+
+ /**
+ * Unregisters this object from the location service.
+ */
+ private void unregisterFromLocationUpdates() {
+ if (mIsRunning) {
+ mIsRunning = false;
+ mLocationManager.removeUpdates(this);
+ }
+ }
+
+ private boolean usePassiveOneShotLocation() {
+ if (!isOnlyPassiveLocationProviderEnabled()) return false;
+
+ // Do not request a location update if the only available location provider is
+ // the passive one. Make use of the last known location and call
+ // onLocationChanged directly.
+ final Location location = mLocationManager.getLastKnownLocation(
+ LocationManager.PASSIVE_PROVIDER);
+ if (location != null) {
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ updateNewLocation(location);
+ }
+ });
+ }
+ return true;
+ }
+
+ /*
+ * Checks if the passive location provider is the only provider available
+ * in the system.
+ */
+ private boolean isOnlyPassiveLocationProviderEnabled() {
+ List<String> providers = mLocationManager.getProviders(true);
+ return providers != null && providers.size() == 1
+ && providers.get(0).equals(LocationManager.PASSIVE_PROVIDER);
+ }
+ }
+}
+
+

Powered by Google App Engine
This is Rietveld 408576698