Bug 568249 - Support geolocation on Android, r=dougt
authorMichael Wu <mwu@mozilla.com>
Fri, 04 Jun 2010 14:14:43 -0700
changeset 43107 1bc9d134e4e9054e6e7331e30adb9658703e689a
parent 43106 dbfe682799ef0aa329342c3fedb8f8d2f0b44a62
child 43108 deb9cd329673ec3ebc2fd43e02ade8581ef37b4f
push id13620
push usermwu@mozilla.com
push dateFri, 04 Jun 2010 21:17:55 +0000
treeherdermozilla-central@1bc9d134e4e9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdougt
bugs568249
milestone1.9.3a5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 568249 - Support geolocation on Android, r=dougt
dom/src/geolocation/AndroidLocationProvider.cpp
dom/src/geolocation/AndroidLocationProvider.h
dom/src/geolocation/MaemoLocationProvider.cpp
dom/src/geolocation/Makefile.in
dom/src/geolocation/WinMobileLocationProvider.cpp
dom/src/geolocation/nsGeoPosition.cpp
dom/src/geolocation/nsGeoPosition.h
dom/src/geolocation/nsGeolocation.cpp
dom/src/geolocation/nsGeolocation.h
embedding/android/AndroidManifest.xml.in
embedding/android/GeckoAppShell.java
embedding/android/GeckoEvent.java
embedding/android/GeckoSurfaceView.java
widget/src/android/AndroidBridge.cpp
widget/src/android/AndroidBridge.h
widget/src/android/AndroidJavaWrappers.cpp
widget/src/android/AndroidJavaWrappers.h
widget/src/android/nsAppShell.cpp
new file mode 100644
--- /dev/null
+++ b/dom/src/geolocation/AndroidLocationProvider.cpp
@@ -0,0 +1,79 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Michael Wu <mwu@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsGeolocation.h"
+#include "nsGeoPosition.h"
+#include "AndroidBridge.h"
+#include "AndroidLocationProvider.h"
+
+using namespace mozilla;
+
+extern nsIGeolocationUpdate *gLocationCallback;
+
+NS_IMPL_ISUPPORTS1(AndroidLocationProvider, nsIGeolocationProvider)
+
+AndroidLocationProvider::AndroidLocationProvider()
+{
+}
+
+AndroidLocationProvider::~AndroidLocationProvider()
+{
+    NS_IF_RELEASE(gLocationCallback);
+}
+
+NS_IMETHODIMP
+AndroidLocationProvider::Startup()
+{
+    AndroidBridge::Bridge()->EnableLocation(true);
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+AndroidLocationProvider::Watch(nsIGeolocationUpdate* aCallback)
+{
+    NS_IF_RELEASE(gLocationCallback);
+    gLocationCallback = aCallback;
+    NS_IF_ADDREF(gLocationCallback);
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+AndroidLocationProvider::Shutdown()
+{
+    AndroidBridge::Bridge()->EnableLocation(false);
+    return NS_OK;
+}
+
new file mode 100644
--- /dev/null
+++ b/dom/src/geolocation/AndroidLocationProvider.h
@@ -0,0 +1,53 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Michael Wu <mwu@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef AndroidLocationProvider_h
+#define AndroidLocationProvider_h
+
+#include "nsIGeolocationProvider.h"
+
+class AndroidLocationProvider : public nsIGeolocationProvider
+{
+public:
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIGEOLOCATIONPROVIDER
+
+    AndroidLocationProvider();
+private:
+    ~AndroidLocationProvider();
+};
+
+#endif /* AndroidLocationProvider_h */
--- a/dom/src/geolocation/MaemoLocationProvider.cpp
+++ b/dom/src/geolocation/MaemoLocationProvider.cpp
@@ -32,157 +32,26 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include <stdio.h>
 #include <math.h>
+#include "nsGeoPosition.h"
 #include "MaemoLocationProvider.h"
 #include "nsIClassInfo.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIDOMClassInfo.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsIServiceManager.h"
 #include "nsServiceManagerUtils.h"
 
-////////////////////////////////////////////////////
-// nsGeoPositionCoords
-////////////////////////////////////////////////////
-
-class nsGeoPositionCoords : public nsIDOMGeoPositionCoords
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIDOMGEOPOSITIONCOORDS
-
-  nsGeoPositionCoords(double aLat, double aLong, double aAlt, double aHError,
-                      double aVError, double aHeading, double aSpeed) :
-    mLat(aLat), mLong(aLong), mAlt(aAlt), mHError(aHError),
-    mVError(aVError), mHeading(aHeading), mSpeed(aSpeed) { };
-private:
-  ~nsGeoPositionCoords() { }
-  double mLat, mLong, mAlt, mHError, mVError, mHeading, mSpeed;
-};
-
-NS_INTERFACE_MAP_BEGIN(nsGeoPositionCoords)
-NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPositionCoords)
-NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionCoords)
-NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoPositionCoords)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_THREADSAFE_ADDREF(nsGeoPositionCoords)
-NS_IMPL_THREADSAFE_RELEASE(nsGeoPositionCoords)
-
-NS_IMETHODIMP
-nsGeoPositionCoords::GetLatitude(double *aLatitude)
-{
-  *aLatitude = mLat;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionCoords::GetLongitude(double *aLongitude)
-{
-  *aLongitude = mLong;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionCoords::GetAltitude(double *aAltitude)
-{
-  *aAltitude = mAlt;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionCoords::GetAccuracy(double *aAccuracy)
-{
-  *aAccuracy = mHError;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionCoords::GetAltitudeAccuracy(double *aAltitudeAccuracy)
-{
-  *aAltitudeAccuracy = mVError;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionCoords::GetHeading(double *aHeading)
-{
-  *aHeading = mHeading;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionCoords::GetSpeed(double *aSpeed)
-{
-  *aSpeed = mSpeed;
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////
-// nsGeoPosition
-////////////////////////////////////////////////////
-
-class nsGeoPosition : public nsIDOMGeoPosition
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIDOMGEOPOSITION
-
-  nsGeoPosition(double aLat, double aLong, double aAlt, double aHError,
-                double aVError, double aHeading, double aSpeed,
-                long long aTimestamp): mTimestamp(aTimestamp)
-  {
-    mCoords = new nsGeoPositionCoords(aLat, aLong, aAlt, aHError,
-                                      aVError, aHeading, aSpeed);
-    NS_ASSERTION(mCoords, "null mCoords in nsGeoPosition");
-  };
-
-private:
-  ~nsGeoPosition() {}
-  long long mTimestamp;
-  nsRefPtr<nsGeoPositionCoords> mCoords;
-};
-
-NS_INTERFACE_MAP_BEGIN(nsGeoPosition)
-NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPosition)
-NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPosition)
-NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoPosition)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_THREADSAFE_ADDREF(nsGeoPosition)
-NS_IMPL_THREADSAFE_RELEASE(nsGeoPosition)
-
-NS_IMETHODIMP
-nsGeoPosition::GetTimestamp(DOMTimeStamp* aTimestamp)
-{
-  *aTimestamp = mTimestamp;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPosition::GetCoords(nsIDOMGeoPositionCoords * *aCoords)
-{
-  NS_IF_ADDREF(*aCoords = mCoords);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPosition::GetAddress(nsIDOMGeoPositionAddress** aAddress)
-{
-  *aAddress = nsnull;
-  return NS_OK;
-}
-
 NS_IMPL_ISUPPORTS2(MaemoLocationProvider, nsIGeolocationProvider, nsITimerCallback)
 
 MaemoLocationProvider::MaemoLocationProvider() :
   mLocationChanged(0),
   mControlError(0),
   mDeviceDisconnected(0),
   mControlStopped(0),
   mHasSeenLocation(PR_FALSE),
--- a/dom/src/geolocation/Makefile.in
+++ b/dom/src/geolocation/Makefile.in
@@ -57,24 +57,29 @@ EXTRA_DSO_LDOPTS = \
 		$(MOZ_COMPONENT_LIBS) \
 		$(NULL)
 
 LOCAL_INCLUDES = \
 		-I$(topsrcdir)/dom/base \
 		$(NULL)
 
 ifdef WINCE_WINDOWS_MOBILE
-CPPSRCS         += WinMobileLocationProvider.cpp
+CPPSRCS         += WinMobileLocationProvider.cpp nsGeoPosition.cpp
 endif
 
 ifdef MOZ_MAEMO_LIBLOCATION
-CPPSRCS         += MaemoLocationProvider.cpp
+CPPSRCS         += MaemoLocationProvider.cpp nsGeoPosition.cpp
 LOCAL_INCLUDES	+= $(MOZ_PLATFORM_MAEMO_CFLAGS)
 endif
 
+ifeq ($(MOZ_WIDGET_TOOLKIT),android)
+CPPSRCS         += AndroidLocationProvider.cpp nsGeoPosition.cpp
+EXPORTS         += nsGeoPosition.h
+endif
+
 EXTRA_COMPONENTS = \
                  NetworkGeolocationProvider.js \
                  GPSDGeolocationProvider.js \
                  $(NULL)
 
 
 include $(topsrcdir)/config/rules.mk
 
--- a/dom/src/geolocation/WinMobileLocationProvider.cpp
+++ b/dom/src/geolocation/WinMobileLocationProvider.cpp
@@ -31,170 +31,25 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "nsGeoPosition.h"
 #include "WinMobileLocationProvider.h"
 #include "nsGeolocation.h"
 #include "nsIClassInfo.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsIServiceManager.h"
 
-////////////////////////////////////////////////////
-// nsGeoPositionCoords
-////////////////////////////////////////////////////
-
-/**
- * Simple object that holds a single point in space.
- */
-class nsGeoPositionCoords : public nsIDOMGeoPositionCoords
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIDOMGEOPOSITIONCOORDS
-  
-  nsGeoPositionCoords(double aLat, double aLong,
-                      double aAlt, double aHError,
-                      double aVError, double aHeading,
-                      double aSpeed) :
-    mLat(aLat), mLong(aLong),
-    mAlt(aAlt), mHError(aHError),
-    mVError(aVError), mHeading(aHeading),
-    mSpeed(aSpeed) {};
-private:
-  ~nsGeoPositionCoords() {}
-  double mLat, mLong, mAlt, mHError, mVError, mHeading, mSpeed;
-};
-
-DOMCI_DATA(GeoPositionCoords, nsGeoPositionCoords)
-
-NS_INTERFACE_MAP_BEGIN(nsGeoPositionCoords)
-NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPositionCoords)
-NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionCoords)
-NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoPositionCoords)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_THREADSAFE_ADDREF(nsGeoPositionCoords)
-NS_IMPL_THREADSAFE_RELEASE(nsGeoPositionCoords)
-
-NS_IMETHODIMP
-nsGeoPositionCoords::GetLatitude(double *aLatitude)
-{
-  *aLatitude = mLat;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionCoords::GetLongitude(double *aLongitude)
-{
-  *aLongitude = mLong;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionCoords::GetAltitude(double *aAltitude)
-{
-  *aAltitude = mAlt;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionCoords::GetAccuracy(double *aAccuracy)
-{
-  *aAccuracy = mHError;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionCoords::GetAltitudeAccuracy(double *aAltitudeAccuracy)
-{
-  *aAltitudeAccuracy = mVError;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionCoords::GetHeading(double *aHeading)
-{
-  *aHeading = mHeading;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionCoords::GetSpeed(double *aSpeed)
-{
-  *aSpeed = mSpeed;
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////
-// nsGeoPosition
-////////////////////////////////////////////////////
-
-class nsGeoPosition : public nsIDOMGeoPosition
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIDOMGEOPOSITION
-  
-  nsGeoPosition(double aLat, double aLong,
-                double aAlt, double aHError,
-                double aVError, double aHeading,
-                double aSpeed, long long aTimestamp): mTimestamp(aTimestamp)
-  {
-    mCoords = new nsGeoPositionCoords(aLat, aLong,
-                                      aAlt, aHError,
-                                      aVError, aHeading,
-                                      aSpeed);
-    NS_ASSERTION(mCoords, "null mCoords in nsGeoPosition");
-  };
-  
-private:
-  ~nsGeoPosition() {}
-  long long mTimestamp;
-  nsRefPtr<nsGeoPositionCoords> mCoords;
-};
-
-DOMCI_DATA(GeoPosition, nsGeoPosition)
-
-NS_INTERFACE_MAP_BEGIN(nsGeoPosition)
-NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPosition)
-NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPosition)
-NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoPosition)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_THREADSAFE_ADDREF(nsGeoPosition)
-NS_IMPL_THREADSAFE_RELEASE(nsGeoPosition)
-
-NS_IMETHODIMP
-nsGeoPosition::GetTimestamp(DOMTimeStamp* aTimestamp)
-{
-  *aTimestamp = mTimestamp;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPosition::GetCoords(nsIDOMGeoPositionCoords * *aCoords)
-{
-  NS_IF_ADDREF(*aCoords = mCoords);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPosition::GetAddress(nsIDOMGeoPositionAddress** aAddress)
-{
-  *aAddress = nsnull;
-  return NS_OK;
-}
-
 NS_IMPL_ISUPPORTS2(WinMobileLocationProvider, nsIGeolocationProvider, nsITimerCallback)
 
 WinMobileLocationProvider::WinMobileLocationProvider() :
   mGPSDevice(nsnull), 
   mOpenDevice(nsnull),
   mCloseDevice(nsnull),
   mGetPosition(nsnull),
   mGetDeviceState(nsnull),
new file mode 100644
--- /dev/null
+++ b/dom/src/geolocation/nsGeoPosition.cpp
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Geolocation.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Doug Turner <dougt@meer.net>  (Original Author)
+ *  Nino D'Aversa <ninodaversa@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsGeoPosition.h"
+#include "nsDOMClassInfo.h"
+
+////////////////////////////////////////////////////
+// nsGeoPositionCoords
+////////////////////////////////////////////////////
+nsGeoPositionCoords::nsGeoPositionCoords(double aLat, double aLong,
+                                         double aAlt, double aHError,
+                                         double aVError, double aHeading,
+                                         double aSpeed) :
+    mLat(aLat), mLong(aLong),
+    mAlt(aAlt), mHError(aHError),
+    mVError(aVError), mHeading(aHeading),
+    mSpeed(aSpeed)
+{
+}
+
+nsGeoPositionCoords::~nsGeoPositionCoords()
+{
+}
+
+DOMCI_DATA(GeoPositionCoords, nsGeoPositionCoords)
+
+NS_INTERFACE_MAP_BEGIN(nsGeoPositionCoords)
+NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPositionCoords)
+NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionCoords)
+NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoPositionCoords)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_THREADSAFE_ADDREF(nsGeoPositionCoords)
+NS_IMPL_THREADSAFE_RELEASE(nsGeoPositionCoords)
+
+NS_IMETHODIMP
+nsGeoPositionCoords::GetLatitude(double *aLatitude)
+{
+  *aLatitude = mLat;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGeoPositionCoords::GetLongitude(double *aLongitude)
+{
+  *aLongitude = mLong;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGeoPositionCoords::GetAltitude(double *aAltitude)
+{
+  *aAltitude = mAlt;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGeoPositionCoords::GetAccuracy(double *aAccuracy)
+{
+  *aAccuracy = mHError;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGeoPositionCoords::GetAltitudeAccuracy(double *aAltitudeAccuracy)
+{
+  *aAltitudeAccuracy = mVError;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGeoPositionCoords::GetHeading(double *aHeading)
+{
+  *aHeading = mHeading;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGeoPositionCoords::GetSpeed(double *aSpeed)
+{
+  *aSpeed = mSpeed;
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////
+// nsGeoPosition
+////////////////////////////////////////////////////
+
+nsGeoPosition::nsGeoPosition(double aLat, double aLong,
+                             double aAlt, double aHError,
+                             double aVError, double aHeading,
+                             double aSpeed, long long aTimestamp) :
+    mTimestamp(aTimestamp)
+{
+    mCoords = new nsGeoPositionCoords(aLat, aLong,
+                                      aAlt, aHError,
+                                      aVError, aHeading,
+                                      aSpeed);
+    NS_ASSERTION(mCoords, "null mCoords in nsGeoPosition");
+}
+  
+nsGeoPosition::~nsGeoPosition()
+{
+}
+
+DOMCI_DATA(GeoPosition, nsGeoPosition)
+
+NS_INTERFACE_MAP_BEGIN(nsGeoPosition)
+NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPosition)
+NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPosition)
+NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoPosition)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_THREADSAFE_ADDREF(nsGeoPosition)
+NS_IMPL_THREADSAFE_RELEASE(nsGeoPosition)
+
+NS_IMETHODIMP
+nsGeoPosition::GetTimestamp(DOMTimeStamp* aTimestamp)
+{
+  *aTimestamp = mTimestamp;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGeoPosition::GetCoords(nsIDOMGeoPositionCoords * *aCoords)
+{
+  NS_IF_ADDREF(*aCoords = mCoords);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGeoPosition::GetAddress(nsIDOMGeoPositionAddress** aAddress)
+{
+  *aAddress = nsnull;
+  return NS_OK;
+}
+
new file mode 100644
--- /dev/null
+++ b/dom/src/geolocation/nsGeoPosition.h
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Geolocation.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Doug Turner <dougt@meer.net>  (Original Author)
+ *  Nino D'Aversa <ninodaversa@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsGeoPosition_h
+#define nsGeoPosition_h
+
+#include "nsAutoPtr.h"
+#include "nsIClassInfo.h"
+#include "nsDOMClassInfoID.h"
+#include "nsIDOMGeoPositionCoords.h"
+#include "nsIDOMGeoPosition.h"
+
+////////////////////////////////////////////////////
+// nsGeoPositionCoords
+////////////////////////////////////////////////////
+
+/**
+ * Simple object that holds a single point in space.
+ */
+class nsGeoPositionCoords : public nsIDOMGeoPositionCoords
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIDOMGEOPOSITIONCOORDS
+  
+  nsGeoPositionCoords(double aLat, double aLong,
+                      double aAlt, double aHError,
+                      double aVError, double aHeading,
+                      double aSpeed);
+private:
+  ~nsGeoPositionCoords();
+  double mLat, mLong, mAlt, mHError, mVError, mHeading, mSpeed;
+};
+
+
+////////////////////////////////////////////////////
+// nsGeoPosition
+////////////////////////////////////////////////////
+
+class nsGeoPosition : public nsIDOMGeoPosition
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIDOMGEOPOSITION
+  
+  nsGeoPosition(double aLat, double aLong,
+                double aAlt, double aHError,
+                double aVError, double aHeading,
+                double aSpeed, long long aTimestamp);
+  
+private:
+  ~nsGeoPosition();
+  long long mTimestamp;
+  nsRefPtr<nsGeoPositionCoords> mCoords;
+};
+
+#endif /* nsGeoPosition_h */
+
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -57,16 +57,20 @@
 #ifdef WINCE_WINDOWS_MOBILE
 #include "WinMobileLocationProvider.h"
 #endif
 
 #ifdef MOZ_MAEMO_LIBLOCATION
 #include "MaemoLocationProvider.h"
 #endif
 
+#ifdef ANDROID
+#include "AndroidLocationProvider.h"
+#endif
+
 #include "nsIDOMDocument.h"
 #include "nsIDocument.h"
 
 // Some limit to the number of get or watch geolocation requests
 // that a window can make.
 #define MAX_GEO_REQUESTS_PER_WINDOW  1500
 
 ////////////////////////////////////////////////////
@@ -421,16 +425,22 @@ nsresult nsGeolocationService::Init()
     mProviders.AppendObject(provider);
 #endif
 
 #ifdef MOZ_MAEMO_LIBLOCATION
   provider = new MaemoLocationProvider();
   if (provider)
     mProviders.AppendObject(provider);
 #endif
+
+#ifdef ANDROID
+  provider = new AndroidLocationProvider();
+  if (provider)
+    mProviders.AppendObject(provider);
+#endif
   return NS_OK;
 }
 
 nsGeolocationService::~nsGeolocationService()
 {
 }
 
 NS_IMETHODIMP
@@ -957,12 +967,12 @@ nsGeolocation::WindowOwnerStillExists()
     nsPIDOMWindow* outer = window->GetOuterWindow();
     if (!outer || outer->GetCurrentInnerWindow() != window)
       return PR_FALSE;
   }
 
   return PR_TRUE;
 }
 
-#ifndef WINCE_WINDOWS_MOBILE
+#if !defined(WINCE_WINDOWS_MOBILE) && !defined(MOZ_MAEMO_LIBLOCATION) && !defined(ANDROID)
 DOMCI_DATA(GeoPositionCoords, void)
 DOMCI_DATA(GeoPosition, void)
 #endif
--- a/dom/src/geolocation/nsGeolocation.h
+++ b/dom/src/geolocation/nsGeolocation.h
@@ -29,16 +29,18 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#ifndef nsGeoLocation_h
+#define nsGeoLocation_h
 
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsCOMArray.h"
 #include "nsTArray.h"
 #include "nsITimer.h"
 #include "nsIObserver.h"
 #include "nsIURI.h"
@@ -218,8 +220,10 @@ private:
   nsWeakPtr mOwner;
 
   // where the content was loaded from
   nsCOMPtr<nsIURI> mURI;
 
   // owning back pointer.
   nsRefPtr<nsGeolocationService> mService;
 };
+
+#endif /* nsGeoLocation_h */
--- a/embedding/android/AndroidManifest.xml.in
+++ b/embedding/android/AndroidManifest.xml.in
@@ -3,16 +3,17 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="org.mozilla.@MOZ_APP_NAME@"
       android:versionCode="1"
       android:versionName="1.9.3"
       android:sharedUserId="org.mozilla.sharedID">
     <uses-sdk android:minSdkVersion="5"
               android:targetSdkVersion="5"/>
 
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> 
     <uses-permission android:name="android.permission.INTERNET"/> 
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
 
     <application android:label="@MOZ_APP_DISPLAYNAME@"
 		 android:icon="@drawable/icon">
         <activity android:name="App"
                   android:label="@MOZ_APP_DISPLAYNAME@"
                   android:configChanges="keyboard|keyboardHidden|orientation|mcc|mnc"
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -46,16 +46,17 @@ import android.os.*;
 import android.app.*;
 import android.text.*;
 import android.view.*;
 import android.view.inputmethod.*;
 import android.content.*;
 import android.graphics.*;
 import android.widget.*;
 import android.hardware.*;
+import android.location.*;
 
 import android.util.*;
 import android.content.DialogInterface; 
 
 class GeckoAppShell
 {
     static {
         sGeckoRunning = false;
@@ -187,16 +188,34 @@ class GeckoAppShell
                 return;
 
             sm.registerListener(GeckoApp.surfaceView, accelSensor, SensorManager.SENSOR_DELAY_GAME);
         } else {
             sm.unregisterListener(GeckoApp.surfaceView);
         }
     }
 
+    public static void enableLocation(boolean enable) {
+        LocationManager lm = (LocationManager)
+            GeckoApp.surfaceView.getContext().getSystemService(Context.LOCATION_SERVICE);
+
+        if (enable) {
+            Criteria crit = new Criteria();
+            crit.setAccuracy(Criteria.ACCURACY_FINE);
+            String provider = lm.getBestProvider(crit, true);
+            if (provider == null)
+                return;
+
+            sendEventToGecko(new GeckoEvent(lm.getLastKnownLocation(provider)));
+            lm.requestLocationUpdates(provider, 100, (float).5, GeckoApp.surfaceView, Looper.getMainLooper());
+        } else {
+            lm.removeUpdates(GeckoApp.surfaceView);
+        }
+    }
+
     public static void returnIMEQueryResult(String result, int selectionStart, int selectionEnd) {
         GeckoApp.surfaceView.inputConnection.mSelectionStart = selectionStart;
         GeckoApp.surfaceView.inputConnection.mSelectionEnd = selectionEnd;
         try {
             GeckoApp.surfaceView.inputConnection.mQueryResult.put(result);
         } catch (InterruptedException e) {
         }
     }
--- a/embedding/android/GeckoEvent.java
+++ b/embedding/android/GeckoEvent.java
@@ -39,34 +39,36 @@ package org.mozilla.gecko;
 
 import android.os.*;
 import android.app.*;
 import android.view.*;
 import android.content.*;
 import android.graphics.*;
 import android.widget.*;
 import android.hardware.*;
+import android.location.*;
 
 import android.util.Log;
 
 /* We're not allowed to hold on to most events given to us
  * so we save the parts of the events we want to use in GeckoEvent.
  * Fields have different meanings depending on the event type.
  */
 
 public class GeckoEvent {
     public static final int INVALID = -1;
     public static final int NATIVE_POKE = 0;
     public static final int KEY_EVENT = 1;
     public static final int MOTION_EVENT = 2;
     public static final int SENSOR_EVENT = 3;
-    public static final int IME_EVENT = 4;
-    public static final int DRAW = 5;
-    public static final int SIZE_CHANGED = 6;
-    public static final int ACTIVITY_STOPPING = 7;
+    public static final int LOCATION_EVENT = 4;
+    public static final int IME_EVENT = 5;
+    public static final int DRAW = 6;
+    public static final int SIZE_CHANGED = 7;
+    public static final int ACTIVITY_STOPPING = 8;
 
     public static final int IME_BATCH_END = 0;
     public static final int IME_BATCH_BEGIN = 1;
     public static final int IME_SET_TEXT = 2;
     public static final int IME_GET_TEXT = 3;
     public static final int IME_DELETE_TEXT = 4;
 
     public int mType;
@@ -75,16 +77,17 @@ public class GeckoEvent {
     public Point mP0, mP1;
     public Rect mRect;
     public float mX, mY, mZ;
 
     public int mMetaState, mFlags;
     public int mKeyCode, mUnicodeChar;
     public int mCount, mCount2;
     public String mCharacters;
+    public Location mLocation;
 
     public int mNativeWindow;
 
     public GeckoEvent() {
         mType = NATIVE_POKE;
     }
 
     public GeckoEvent(int evType) {
@@ -111,16 +114,21 @@ public class GeckoEvent {
 
     public GeckoEvent(SensorEvent s) {
         mType = SENSOR_EVENT;
         mX = s.values[0] / SensorManager.GRAVITY_EARTH;
         mY = s.values[1] / SensorManager.GRAVITY_EARTH;
         mZ = s.values[2] / SensorManager.GRAVITY_EARTH;
     }
 
+    public GeckoEvent(Location l) {
+        mType = LOCATION_EVENT;
+        mLocation = l;
+    }
+
     public GeckoEvent(boolean batchEdit, String text) {
         mType = IME_EVENT;
         if (text != null)
             mAction = IME_SET_TEXT;
         else
             mAction = batchEdit ? IME_BATCH_BEGIN : IME_BATCH_END;
         mCharacters = text;
     }
--- a/embedding/android/GeckoSurfaceView.java
+++ b/embedding/android/GeckoSurfaceView.java
@@ -58,28 +58,29 @@ import android.os.*;
 import android.app.*;
 import android.text.*;
 import android.view.*;
 import android.view.inputmethod.*;
 import android.content.*;
 import android.graphics.*;
 import android.widget.*;
 import android.hardware.*;
+import android.location.*;
 
 import android.util.*;
 
 /*
  * GeckoSurfaceView implements a GL surface view,
  * similar to GLSurfaceView.  However, since we
  * already have a thread for Gecko, we don't really want
  * a separate renderer thread that GLSurfaceView provides.
  */
 class GeckoSurfaceView
     extends SurfaceView
-    implements SurfaceHolder.Callback, SensorEventListener
+    implements SurfaceHolder.Callback, SensorEventListener, LocationListener
 {
     public GeckoSurfaceView(Context context) {
         super(context);
 
         getHolder().addCallback(this);
         inputConnection = new GeckoInputConnection(this);
         setFocusable(true);
         setFocusableInTouchMode(true);
@@ -640,25 +641,44 @@ class GeckoSurfaceView
 
     @Override
     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
         outAttrs.inputType = InputType.TYPE_CLASS_TEXT |
                              InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
         return inputConnection;
     }
 
+    // accelerometer
     public void onAccuracyChanged(Sensor sensor, int accuracy)
     {
     }
 
     public void onSensorChanged(SensorEvent event)
     {
         GeckoAppShell.sendEventToGecko(new GeckoEvent(event));
     }
 
+    // geolocation
+    public void onLocationChanged(Location location)
+    {
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(location));
+    }
+
+    public void onProviderDisabled(String provider)
+    {
+    }
+
+    public void onProviderEnabled(String provider)
+    {
+    }
+
+    public void onStatusChanged(String provider, int status, Bundle extras)
+    {
+    }
+
     // event stuff
     public boolean onTouchEvent(MotionEvent event) {
         GeckoAppShell.sendEventToGecko(new GeckoEvent(event));
         return true;
     }
 
     // Is this surface valid for drawing into?
     boolean mSurfaceValid;
--- a/widget/src/android/AndroidBridge.cpp
+++ b/widget/src/android/AndroidBridge.cpp
@@ -88,16 +88,17 @@ AndroidBridge::Init(JNIEnv *jEnv,
 
     mJNIEnv = nsnull;
     mThread = nsnull;
 
     mGeckoAppShellClass = (jclass) jEnv->NewGlobalRef(jGeckoAppShellClass);
 
     jShowIME = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showIME", "(I)V");
     jEnableAccelerometer = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableAccelerometer", "(Z)V");
+    jEnableLocation = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableLocation", "(Z)V");
     jReturnIMEQueryResult = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "returnIMEQueryResult", "(Ljava/lang/String;II)V");
     jScheduleRestart = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "scheduleRestart", "()V");
     jNotifyXreExit = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "onXreExit", "()V");
 
     InitAndroidJavaWrappers(jEnv);
 
     // jEnv should NOT be cached here by anything -- the jEnv here
     // is not valid for the real gecko main thread, which is set
@@ -177,16 +178,22 @@ AndroidBridge::ShowIME(int aState)
 
 void
 AndroidBridge::EnableAccelerometer(bool aEnable)
 {
     mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jEnableAccelerometer, aEnable);
 }
 
 void
+AndroidBridge::EnableLocation(bool aEnable)
+{
+    mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jEnableLocation, aEnable);
+}
+
+void
 AndroidBridge::ReturnIMEQueryResult(const PRUnichar *result, PRUint32 len, int selectionStart, int selectionEnd)
 {
     jvalue args[3];
     args[0].l = mJNIEnv->NewString(result, len);
     args[1].i = selectionStart;
     args[2].i = selectionEnd;
     mJNIEnv->CallStaticVoidMethodA(mGeckoAppShellClass, jReturnIMEQueryResult, args);
 }
--- a/widget/src/android/AndroidBridge.h
+++ b/widget/src/android/AndroidBridge.h
@@ -86,16 +86,18 @@ public:
 
     JNIEnv* AttachThread(PRBool asDaemon = PR_TRUE);
 
     /* These are all implemented in Java */
     void ShowIME(int aState);
 
     void EnableAccelerometer(bool aEnable);
 
+    void EnableLocation(bool aEnable);
+
     void ReturnIMEQueryResult(const PRUnichar *result, PRUint32 len, int selectionStart, int selectionEnd);
 
     void NotifyXreExit();
 
     void ScheduleRestart();
 
     void SetSurfaceView(jobject jobj);
     AndroidGeckoSurfaceView& SurfaceView() { return mSurfaceView; }
@@ -136,16 +138,17 @@ protected:
     AndroidBridge() { }
     PRBool Init(JNIEnv *jEnv, jclass jGeckoApp);
 
     void EnsureJNIThread();
 
     // other things
     jmethodID jShowIME;
     jmethodID jEnableAccelerometer;
+    jmethodID jEnableLocation;
     jmethodID jReturnIMEQueryResult;
     jmethodID jNotifyXreExit;
     jmethodID jScheduleRestart;
     jmethodID jGetOutstandingDrawEvents;
 };
 
 }
 
--- a/widget/src/android/AndroidJavaWrappers.cpp
+++ b/widget/src/android/AndroidJavaWrappers.cpp
@@ -54,27 +54,37 @@ jfieldID AndroidGeckoEvent::jNativeWindo
 
 jfieldID AndroidGeckoEvent::jCharactersField = 0;
 jfieldID AndroidGeckoEvent::jKeyCodeField = 0;
 jfieldID AndroidGeckoEvent::jMetaStateField = 0;
 jfieldID AndroidGeckoEvent::jFlagsField = 0;
 jfieldID AndroidGeckoEvent::jUnicodeCharField = 0;
 jfieldID AndroidGeckoEvent::jCountField = 0;
 jfieldID AndroidGeckoEvent::jCount2Field = 0;
+jfieldID AndroidGeckoEvent::jLocationField = 0;
 
 jclass AndroidPoint::jPointClass = 0;
 jfieldID AndroidPoint::jXField = 0;
 jfieldID AndroidPoint::jYField = 0;
 
 jclass AndroidRect::jRectClass = 0;
 jfieldID AndroidRect::jBottomField = 0;
 jfieldID AndroidRect::jLeftField = 0;
 jfieldID AndroidRect::jRightField = 0;
 jfieldID AndroidRect::jTopField = 0;
 
+jclass AndroidLocation::jLocationClass = 0;
+jmethodID AndroidLocation::jGetLatitudeMethod = 0;
+jmethodID AndroidLocation::jGetLongitudeMethod = 0;
+jmethodID AndroidLocation::jGetAltitudeMethod = 0;
+jmethodID AndroidLocation::jGetAccuracyMethod = 0;
+jmethodID AndroidLocation::jGetBearingMethod = 0;
+jmethodID AndroidLocation::jGetSpeedMethod = 0;
+jmethodID AndroidLocation::jGetTimeMethod = 0;
+
 jclass AndroidGeckoSurfaceView::jGeckoSurfaceViewClass = 0;
 jmethodID AndroidGeckoSurfaceView::jBeginDrawingMethod = 0;
 jmethodID AndroidGeckoSurfaceView::jEndDrawingMethod = 0;
 jmethodID AndroidGeckoSurfaceView::jGetSoftwareDrawBufferMethod = 0;
 
 #define JNI()  (AndroidBridge::JNI())
 
 #define initInit() jclass jClass
@@ -90,16 +100,17 @@ jmethodID AndroidGeckoSurfaceView::jGetS
     ((jmethodID) jEnv->GetMethodID(jClass, fname, ftype))
 
 void
 mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv)
 {
     AndroidGeckoEvent::InitGeckoEventClass(jEnv);
     AndroidGeckoSurfaceView::InitGeckoSurfaceViewClass(jEnv);
     AndroidPoint::InitPointClass(jEnv);
+    AndroidLocation::InitLocationClass(jEnv);
 }
 
 void
 AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv)
 {
     initInit();
 
     jGeckoEventClass = getClassGlobalRef("org/mozilla/gecko/GeckoEvent");
@@ -117,31 +128,64 @@ AndroidGeckoEvent::InitGeckoEventClass(J
 
     jCharactersField = getField("mCharacters", "Ljava/lang/String;");
     jKeyCodeField = getField("mKeyCode", "I");
     jMetaStateField = getField("mMetaState", "I");
     jFlagsField = getField("mFlags", "I");
     jUnicodeCharField = getField("mUnicodeChar", "I");
     jCountField = getField("mCount", "I");
     jCount2Field = getField("mCount2", "I");
+    jLocationField = getField("mLocation", "Landroid/location/Location;");
 }
 
 void
 AndroidGeckoSurfaceView::InitGeckoSurfaceViewClass(JNIEnv *jEnv)
 {
     initInit();
 
     jGeckoSurfaceViewClass = getClassGlobalRef("org/mozilla/gecko/GeckoSurfaceView");
 
     jBeginDrawingMethod = getMethod("beginDrawing", "()I");
     jGetSoftwareDrawBufferMethod = getMethod("getSoftwareDrawBuffer", "()Ljava/nio/ByteBuffer;");
     jEndDrawingMethod = getMethod("endDrawing", "()V");
 }
 
 void
+AndroidLocation::InitLocationClass(JNIEnv *jEnv)
+{
+    initInit();
+
+    jLocationClass = getClassGlobalRef("android/location/Location");
+    jGetLatitudeMethod = getMethod("getLatitude", "()D");
+    jGetLongitudeMethod = getMethod("getLongitude", "()D");
+    jGetAltitudeMethod = getMethod("getAltitude", "()D");
+    jGetAccuracyMethod = getMethod("getAccuracy", "()F");
+    jGetBearingMethod = getMethod("getBearing", "()F");
+    jGetSpeedMethod = getMethod("getSpeed", "()F");
+    jGetTimeMethod = getMethod("getTime", "()J");
+}
+
+nsGeoPosition*
+AndroidLocation::CreateGeoPosition(JNIEnv *jenv, jobject jobj)
+{
+    double latitude  = jenv->CallDoubleMethod(jobj, jGetLatitudeMethod);
+    double longitude = jenv->CallDoubleMethod(jobj, jGetLongitudeMethod);
+    double altitude  = jenv->CallDoubleMethod(jobj, jGetAltitudeMethod);
+    float  accuracy  = jenv->CallFloatMethod (jobj, jGetAccuracyMethod);
+    float  bearing   = jenv->CallFloatMethod (jobj, jGetBearingMethod);
+    float  speed     = jenv->CallFloatMethod (jobj, jGetSpeedMethod);
+    long long time   = jenv->CallLongMethod  (jobj, jGetTimeMethod);
+
+    return new nsGeoPosition(latitude, longitude,
+                             altitude, accuracy,
+                             accuracy, bearing,
+                             speed,    time);
+}
+
+void
 AndroidPoint::InitPointClass(JNIEnv *jEnv)
 {
     initInit();
 
     jPointClass = getClassGlobalRef("android/graphics/Point");
 
     jXField = getField("x", "I");
     jYField = getField("y", "I");
@@ -254,16 +298,22 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jo
             break;
 
         case SENSOR_EVENT:
             mX = jenv->GetFloatField(jobj, jXField);
             mY = jenv->GetFloatField(jobj, jYField);
             mZ = jenv->GetFloatField(jobj, jZField);
             break;
 
+        case LOCATION_EVENT: {
+            jobject location = jenv->GetObjectField(jobj, jLocationField);
+            mGeoPosition = AndroidLocation::CreateGeoPosition(jenv, location);
+            break;
+        }
+
         default:
             break;
     }
 
 #ifndef ANDROID_DEBUG_EVENTS
     ALOG("AndroidGeckoEvent: %p : %d %p", (void*)jobj, mType, (void*)mNativeWindow);
 #endif
 }
--- a/widget/src/android/AndroidJavaWrappers.h
+++ b/widget/src/android/AndroidJavaWrappers.h
@@ -36,16 +36,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef AndroidJavaWrappers_h__
 #define AndroidJavaWrappers_h__
 
 #include <jni.h>
 #include <android/log.h>
 
+#include "nsGeoPosition.h"
 #include "nsPoint.h"
 #include "nsRect.h"
 #include "nsString.h"
 
 #ifndef ALOG
 #ifdef DEBUG
 #define ALOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gecko" , ## args)
 #else
@@ -317,16 +318,31 @@ public:
         SAMPLE_Y = 1,
         SAMPLE_PRESSURE = 2,
         SAMPLE_SIZE = 3,
         NUM_SAMPLE_DATA = 4,
         dummy_java_enum_list_end
     };
 };
 
+class AndroidLocation : public WrappedJavaObject
+{
+public:
+    static void InitLocationClass(JNIEnv *jEnv);
+    static nsGeoPosition* CreateGeoPosition(JNIEnv *jenv, jobject jobj);
+    static jclass jLocationClass;
+    static jmethodID jGetLatitudeMethod;
+    static jmethodID jGetLongitudeMethod;
+    static jmethodID jGetAltitudeMethod;
+    static jmethodID jGetAccuracyMethod;
+    static jmethodID jGetBearingMethod;
+    static jmethodID jGetSpeedMethod;
+    static jmethodID jGetTimeMethod;
+};
+
 class AndroidGeckoEvent : public WrappedJavaObject
 {
 public:
     static void InitGeckoEventClass(JNIEnv *jEnv);
 
     AndroidGeckoEvent() { }
     AndroidGeckoEvent(int aType) {
         Init(aType);
@@ -354,30 +370,32 @@ public:
     const nsIntRect& Rect() { return mRect; }
     nsAString& Characters() { return mCharacters; }
     int KeyCode() { return mKeyCode; }
     int MetaState() { return mMetaState; }
     int Flags() { return mFlags; }
     int UnicodeChar() { return mUnicodeChar; }
     int Count() { return mCount; }
     int Count2() { return mCount2; }
+    nsGeoPosition* GeoPosition() { return mGeoPosition; }
 
 protected:
     int mAction;
     int mType;
     int64_t mTime;
     void *mNativeWindow;
     nsIntPoint mP0;
     nsIntPoint mP1;
     nsIntRect mRect;
     int mFlags, mMetaState;
     int mKeyCode, mUnicodeChar;
     int mCount, mCount2;
     float mX, mY, mZ;
     nsString mCharacters;
+    nsRefPtr<nsGeoPosition> mGeoPosition;
 
     void ReadP0Field(JNIEnv *jenv);
     void ReadP1Field(JNIEnv *jenv);
     void ReadRectField(JNIEnv *jenv);
     void ReadCharactersField(JNIEnv *jenv);
 
     static jclass jGeckoEventClass;
     static jfieldID jActionField;
@@ -393,27 +411,29 @@ protected:
 
     static jfieldID jCharactersField;
     static jfieldID jKeyCodeField;
     static jfieldID jMetaStateField;
     static jfieldID jFlagsField;
     static jfieldID jCountField;
     static jfieldID jCount2Field;
     static jfieldID jUnicodeCharField;
+    static jfieldID jLocationField;
 
 public:
     enum {
         NATIVE_POKE = 0,
         KEY_EVENT = 1,
         MOTION_EVENT = 2,
         SENSOR_EVENT = 3,
-        IME_EVENT = 4,
-        DRAW = 5,
-        SIZE_CHANGED = 6,
-        ACTIVITY_STOPPING = 7,
+        LOCATION_EVENT = 4,
+        IME_EVENT = 5,
+        DRAW = 6,
+        SIZE_CHANGED = 7,
+        ACTIVITY_STOPPING = 8,
         dummy_java_enum_list_end
     };
 
     enum {
         IME_BATCH_END = 0,
         IME_BATCH_BEGIN = 1,
         IME_SET_TEXT = 2,
         IME_GET_TEXT = 3,
--- a/widget/src/android/nsAppShell.cpp
+++ b/widget/src/android/nsAppShell.cpp
@@ -36,16 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsAppShell.h"
 #include "nsWindow.h"
 #include "nsThreadUtils.h"
 #include "nsIObserverService.h"
 #include "nsIAppStartup.h"
+#include "nsIGeolocationProvider.h"
 
 #include "prenv.h"
 
 #include "AndroidBridge.h"
 #include "nsAccelerometerAndroid.h"
 #include <android/log.h>
 #include <pthread.h>
 
@@ -62,16 +63,17 @@
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING
 PRLogModuleInfo *gWidgetLog = nsnull;
 #endif
 
 nsAccelerometerAndroid *gAccel = nsnull;
+nsIGeolocationUpdate *gLocationCallback = nsnull;
 
 nsAppShell *nsAppShell::gAppShell = nsnull;
 AndroidGeckoEvent *nsAppShell::gEarlyEvent = nsnull;
 
 nsAppShell::nsAppShell()
     : mQueueLock(nsnull),
       mCondLock(nsnull),
       mQueueCond(nsnull),
@@ -213,16 +215,26 @@ nsAppShell::ProcessNextNativeEvent(PRBoo
     case AndroidGeckoEvent::NATIVE_POKE:
         NativeEventCallback();
         break;
 
     case AndroidGeckoEvent::SENSOR_EVENT:
         gAccel->AccelerationChanged(-curEvent->X(), curEvent->Y(), curEvent->Z());
         break;
 
+    case AndroidGeckoEvent::LOCATION_EVENT:
+        if (!gLocationCallback)
+            break;
+
+        if (curEvent->GeoPosition())
+            gLocationCallback->Update(curEvent->GeoPosition());
+        else
+            NS_WARNING("Received location event without geoposition!");
+        break;
+
     case AndroidGeckoEvent::ACTIVITY_STOPPING: {
         nsCOMPtr<nsIAppStartup> appSvc = do_GetService("@mozilla.org/toolkit/app-startup;1");
         if (appSvc)
             appSvc->Quit(nsIAppStartup::eForceQuit);
         break;
     }
 
     default: