Bug 512407 - Support Windows Location API. r=jdm,jmathies
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Fri, 23 Jan 2015 18:43:46 +0900
changeset 225273 583384f8f06cbef3936880035c2d1c3d124b7a2d
parent 225272 b80d1982df588405b7715d4c77699b1da9355f26
child 225274 468c1db9e3389094980c3d3f3e464587e182334c
push id54516
push userm_kato@ga2.so-net.ne.jp
push dateFri, 23 Jan 2015 09:44:58 +0000
treeherdermozilla-inbound@583384f8f06c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdm, jmathies
bugs512407
milestone38.0a1
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 512407 - Support Windows Location API. r=jdm,jmathies
dom/geolocation/moz.build
dom/geolocation/nsGeolocation.cpp
dom/system/windows/WindowsLocationProvider.cpp
dom/system/windows/WindowsLocationProvider.h
dom/system/windows/moz.build
toolkit/library/moz.build
--- a/dom/geolocation/moz.build
+++ b/dom/geolocation/moz.build
@@ -5,19 +5,22 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS += [
     'nsGeolocationSettings.h',
     'nsGeoPosition.h',
     'nsGeoPositionIPCSerialiser.h',
 ]
 
+SOURCES += [
+    'nsGeolocation.cpp',
+]
+
 UNIFIED_SOURCES += [
     'nsGeoGridFuzzer.cpp',
-    'nsGeolocation.cpp',
     'nsGeolocationSettings.cpp',
     'nsGeoPosition.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
@@ -40,9 +43,12 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'andr
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     LOCAL_INCLUDES += [
         '/dom/system/gonk',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     LOCAL_INCLUDES += [
         '/dom/system/mac',
     ]
-
+elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
+    LOCAL_INCLUDES += [
+        '/dom/system/windows',
+    ]
--- a/dom/geolocation/nsGeolocation.cpp
+++ b/dom/geolocation/nsGeolocation.cpp
@@ -44,16 +44,20 @@ class nsIPrincipal;
 #ifdef MOZ_WIDGET_GONK
 #include "GonkGPSGeolocationProvider.h"
 #endif
 
 #ifdef MOZ_WIDGET_COCOA
 #include "CoreLocationLocationProvider.h"
 #endif
 
+#ifdef XP_WIN
+#include "WindowsLocationProvider.h"
+#endif
+
 // Some limit to the number of get or watch geolocation requests
 // that a window can make.
 #define MAX_GEO_REQUESTS_PER_WINDOW  1500
 
 // the geolocation enabled setting
 #define GEO_SETTINGS_ENABLED          "geolocation.enabled"
 
 using mozilla::unused;          // <snicker>
@@ -805,16 +809,22 @@ nsresult nsGeolocationService::Init()
 #endif
 
 #ifdef MOZ_WIDGET_COCOA
   if (Preferences::GetBool("geo.provider.use_corelocation", false)) {
     mProvider = new CoreLocationLocationProvider();
   }
 #endif
 
+#ifdef XP_WIN
+  if (Preferences::GetBool("geo.provider.ms-windows-location", false)) {
+    mProvider = new WindowsLocationProvider();
+  }
+#endif
+
   if (Preferences::GetBool("geo.provider.use_mls", false)) {
     mProvider = do_CreateInstance("@mozilla.org/geolocation/mls-provider;1");
   }
 
   // Override platform-specific providers with the default (network)
   // provider while testing. Our tests are currently not meant to exercise
   // the provider, and some tests rely on the network provider being used.
   // "geo.provider.testing" is always set for all plain and browser chrome
new file mode 100644
--- /dev/null
+++ b/dom/system/windows/WindowsLocationProvider.cpp
@@ -0,0 +1,198 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "WindowsLocationProvider.h"
+#include "nsGeoPosition.h"
+#include "nsIDOMGeoPositionError.h"
+#include "prtime.h"
+
+#include <LocationApi.h>
+
+namespace mozilla {
+namespace dom {
+
+class LocationEvent MOZ_FINAL : public ILocationEvents
+{
+public:
+  LocationEvent(nsIGeolocationUpdate* aCallback)
+    : mCallback(aCallback), mCount(0) {
+  }
+
+  // IUnknown interface
+  STDMETHODIMP_(ULONG) AddRef() MOZ_OVERRIDE;
+  STDMETHODIMP_(ULONG) Release() MOZ_OVERRIDE;
+  STDMETHODIMP QueryInterface(REFIID iid, void** ppv) MOZ_OVERRIDE;
+
+  // ILocationEvents interface
+  STDMETHODIMP OnStatusChanged(REFIID aReportType,
+                               LOCATION_REPORT_STATUS aStatus) MOZ_OVERRIDE;
+  STDMETHODIMP OnLocationChanged(REFIID aReportType,
+                                 ILocationReport *aReport) MOZ_OVERRIDE;
+
+private:
+  nsCOMPtr<nsIGeolocationUpdate> mCallback;
+  ULONG mCount;
+};
+
+STDMETHODIMP_(ULONG)
+LocationEvent::AddRef()
+{
+  return InterlockedIncrement(&mCount);
+}
+
+STDMETHODIMP_(ULONG)
+LocationEvent::Release()
+{
+  ULONG count = InterlockedDecrement(&mCount);
+  if (!count) {
+    delete this;
+    return 0;
+  }
+  return count;
+}
+
+STDMETHODIMP
+LocationEvent::QueryInterface(REFIID iid, void** ppv)
+{
+  if (iid == IID_IUnknown) {
+    *ppv = static_cast<IUnknown*>(this);
+  } else if (iid == IID_ILocationEvents) {
+    *ppv = static_cast<ILocationEvents*>(this);
+  } else {
+    return E_NOINTERFACE;
+  }
+  AddRef();
+  return S_OK;
+}
+
+
+STDMETHODIMP
+LocationEvent::OnStatusChanged(REFIID aReportType,
+                               LOCATION_REPORT_STATUS aStatus)
+{
+  if (aReportType != IID_ILatLongReport) {
+    return S_OK;
+  }
+
+  uint16_t err;
+  switch (aStatus) {
+  case REPORT_ACCESS_DENIED:
+    err = nsIDOMGeoPositionError::PERMISSION_DENIED;
+    break;
+  case REPORT_ERROR:
+    err = nsIDOMGeoPositionError::POSITION_UNAVAILABLE;
+    break;
+  default:
+    return S_OK;
+  }
+
+  mCallback->NotifyError(err);
+  return S_OK;
+}
+
+STDMETHODIMP
+LocationEvent::OnLocationChanged(REFIID aReportType,
+                                 ILocationReport *aReport)
+{
+  if (aReportType != IID_ILatLongReport) {
+    return S_OK;
+  }
+
+  nsRefPtr<ILatLongReport> latLongReport;
+  if (FAILED(aReport->QueryInterface(IID_ILatLongReport,
+                                     getter_AddRefs(latLongReport)))) {
+    return E_FAIL;
+  }
+
+  DOUBLE latitude = 0.0;
+  latLongReport->GetLatitude(&latitude);
+
+  DOUBLE longitude = 0.0;
+  latLongReport->GetLongitude(&longitude);
+
+  DOUBLE alt = 0.0;
+  latLongReport->GetAltitude(&alt);
+
+  DOUBLE herror = 0.0;
+  latLongReport->GetErrorRadius(&herror);
+
+  DOUBLE verror = 0.0;
+  latLongReport->GetAltitudeError(&verror);
+
+  nsRefPtr<nsGeoPosition> position =
+    new nsGeoPosition(latitude, longitude, alt, herror, verror, 0.0, 0.0,
+                      PR_Now());
+  mCallback->Update(position);
+
+  return S_OK;
+}
+
+NS_IMPL_ISUPPORTS(WindowsLocationProvider, nsIGeolocationProvider)
+
+WindowsLocationProvider::WindowsLocationProvider()
+{
+}
+
+NS_IMETHODIMP
+WindowsLocationProvider::Startup()
+{
+  nsRefPtr<ILocation> location;
+  if (FAILED(::CoCreateInstance(CLSID_Location, nullptr, CLSCTX_INPROC_SERVER,
+                                IID_ILocation,
+                                getter_AddRefs(location)))) {
+    return NS_ERROR_FAILURE;
+  }
+
+  IID reportTypes[] = { IID_ILatLongReport };
+  if (FAILED(location->RequestPermissions(nullptr, reportTypes, 1, FALSE))) {
+    return NS_ERROR_FAILURE;
+  }
+
+  mLocation = location;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+WindowsLocationProvider::Watch(nsIGeolocationUpdate* aCallback)
+{
+  nsRefPtr<LocationEvent> event = new LocationEvent(aCallback);
+  if (FAILED(mLocation->RegisterForReport(event, IID_ILatLongReport, 0))) {
+    return NS_ERROR_FAILURE;
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+WindowsLocationProvider::Shutdown()
+{
+  if (mLocation) {
+    mLocation->UnregisterForReport(IID_ILatLongReport);
+    mLocation = nullptr;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+WindowsLocationProvider::SetHighAccuracy(bool enable)
+{
+  if (!mLocation) {
+    return NS_ERROR_FAILURE;
+  }
+
+  LOCATION_DESIRED_ACCURACY desiredAccuracy;
+  if (enable) {
+    desiredAccuracy = LOCATION_DESIRED_ACCURACY_HIGH;
+  } else {
+    desiredAccuracy = LOCATION_DESIRED_ACCURACY_DEFAULT;
+  }
+  if (FAILED(mLocation->SetDesiredAccuracy(IID_ILatLongReport,
+                                           desiredAccuracy))) {
+    return NS_ERROR_FAILURE;
+  }
+  return NS_OK;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/system/windows/WindowsLocationProvider.h
@@ -0,0 +1,31 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_WindowsLocationProvider_h__
+#define mozilla_dom_WindowsLocationProvider_h__
+
+#include "nsAutoPtr.h"
+#include "nsIGeolocationProvider.h"
+
+#include <LocationApi.h>
+
+namespace mozilla {
+namespace dom {
+
+class WindowsLocationProvider MOZ_FINAL : public nsIGeolocationProvider
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIGEOLOCATIONPROVIDER
+
+  WindowsLocationProvider();
+
+private:
+  nsRefPtr<ILocation> mLocation;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_WindowsLocationProvider_h__
--- a/dom/system/windows/moz.build
+++ b/dom/system/windows/moz.build
@@ -1,13 +1,14 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 SOURCES += [
     'nsHapticFeedback.cpp',
+    'WindowsLocationProvider.cpp'
 ]
 
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'xul'
--- a/toolkit/library/moz.build
+++ b/toolkit/library/moz.build
@@ -345,16 +345,17 @@ if CONFIG['OS_ARCH'] == 'WINNT':
         'secur32',
         'sensorsapi',
         'portabledeviceguids',
         'windowscodecs',
         'wininet',
         'wbemuuid',
         'wintrust',
         'wtsapi32',
+        'locationapi'
     ]
     if CONFIG['ACCESSIBILITY']:
         OS_LIBS += [
             'oleacc',
         ]
     if CONFIG['MOZ_METRO']:
         OS_LIBS += [
             'uiautomationcore',