Bug 1129633 - part1. Use win8 geolocation with a fallback to MLS - r=m_kato

This commit is contained in:
Garvan Keeley 2015-03-10 12:47:40 -04:00
parent 3d1dca594c
commit 7ca28cc267
4 changed files with 133 additions and 12 deletions

View File

@ -51,6 +51,7 @@ class nsIPrincipal;
#ifdef XP_WIN
#include "WindowsLocationProvider.h"
#include "mozilla/WindowsVersion.h"
#endif
// Some limit to the number of get or watch geolocation requests
@ -815,7 +816,8 @@ nsresult nsGeolocationService::Init()
#endif
#ifdef XP_WIN
if (Preferences::GetBool("geo.provider.ms-windows-location", false)) {
if (Preferences::GetBool("geo.provider.ms-windows-location", false) &&
IsWin8OrLater()) {
mProvider = new WindowsLocationProvider();
}
#endif

View File

@ -5,16 +5,59 @@
#include "WindowsLocationProvider.h"
#include "nsGeoPosition.h"
#include "nsIDOMGeoPositionError.h"
#include "nsComponentManagerUtils.h"
#include "prtime.h"
#include "MLSFallback.h"
namespace mozilla {
namespace dom {
NS_IMPL_ISUPPORTS(WindowsLocationProvider::MLSUpdate, nsIGeolocationUpdate);
WindowsLocationProvider::MLSUpdate::MLSUpdate(nsIGeolocationUpdate* aCallback)
: mCallback(aCallback)
{
}
NS_IMETHODIMP
WindowsLocationProvider::MLSUpdate::Update(nsIDOMGeoPosition *aPosition)
{
if (!mCallback) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMGeoPositionCoords> coords;
aPosition->GetCoords(getter_AddRefs(coords));
if (!coords) {
return NS_ERROR_FAILURE;
}
// TODO add telemetry here to track volume of MLS vs native geo responses
return mCallback->Update(aPosition);
}
NS_IMETHODIMP
WindowsLocationProvider::MLSUpdate::LocationUpdatePending()
{
return NS_OK;
}
NS_IMETHODIMP
WindowsLocationProvider::MLSUpdate::NotifyError(uint16_t aError)
{
if (!mCallback) {
return NS_ERROR_FAILURE;
}
return mCallback->NotifyError(aError);
}
class LocationEvent MOZ_FINAL : public ILocationEvents
{
public:
LocationEvent(nsIGeolocationUpdate* aCallback)
: mCallback(aCallback), mCount(0) {
LocationEvent(nsIGeolocationUpdate* aCallback, WindowsLocationProvider *aProvider)
: mCallback(aCallback), mProvider(aProvider), mCount(0) {
}
// IUnknown interface
@ -30,6 +73,7 @@ public:
private:
nsCOMPtr<nsIGeolocationUpdate> mCallback;
nsRefPtr<WindowsLocationProvider> mProvider;
ULONG mCount;
};
@ -73,18 +117,34 @@ LocationEvent::OnStatusChanged(REFIID aReportType,
return S_OK;
}
// When registering event, REPORT_INITIALIZING is fired at first.
// Then, when the location is found, REPORT_RUNNING is fired.
if (aStatus == REPORT_RUNNING) {
// location is found by Windows Location provider, we use it.
mProvider->CancelMLSProvider();
return S_OK;
}
// Cannot get current location at this time. We use MLS instead until
// Location API returns RUNNING status.
if (NS_SUCCEEDED(mProvider->CreateAndWatchMLSProvider(mCallback))) {
return S_OK;
}
// Cannot watch location by MLS provider. We must return error by
// Location API.
uint16_t err;
switch (aStatus) {
case REPORT_ACCESS_DENIED:
err = nsIDOMGeoPositionError::PERMISSION_DENIED;
break;
case REPORT_NOT_SUPPORTED:
case REPORT_ERROR:
err = nsIDOMGeoPositionError::POSITION_UNAVAILABLE;
break;
default:
return S_OK;
}
mCallback->NotifyError(err);
return S_OK;
}
@ -132,6 +192,10 @@ WindowsLocationProvider::WindowsLocationProvider()
{
}
WindowsLocationProvider::~WindowsLocationProvider()
{
}
NS_IMETHODIMP
WindowsLocationProvider::Startup()
{
@ -139,12 +203,14 @@ WindowsLocationProvider::Startup()
if (FAILED(::CoCreateInstance(CLSID_Location, nullptr, CLSCTX_INPROC_SERVER,
IID_ILocation,
getter_AddRefs(location)))) {
return NS_ERROR_FAILURE;
// We will use MLS provider
return NS_OK;
}
IID reportTypes[] = { IID_ILatLongReport };
if (FAILED(location->RequestPermissions(nullptr, reportTypes, 1, FALSE))) {
return NS_ERROR_FAILURE;
// We will use MLS provider
return NS_OK;
}
mLocation = location;
@ -154,11 +220,17 @@ WindowsLocationProvider::Startup()
NS_IMETHODIMP
WindowsLocationProvider::Watch(nsIGeolocationUpdate* aCallback)
{
nsRefPtr<LocationEvent> event = new LocationEvent(aCallback);
if (FAILED(mLocation->RegisterForReport(event, IID_ILatLongReport, 0))) {
return NS_ERROR_FAILURE;
if (mLocation) {
nsRefPtr<LocationEvent> event = new LocationEvent(aCallback, this);
if (SUCCEEDED(mLocation->RegisterForReport(event, IID_ILatLongReport, 0))) {
return NS_OK;
}
}
return NS_OK;
// Cannot use Location API. We will use MLS instead.
mLocation = nullptr;
return CreateAndWatchMLSProvider(aCallback);
}
NS_IMETHODIMP
@ -169,6 +241,8 @@ WindowsLocationProvider::Shutdown()
mLocation = nullptr;
}
CancelMLSProvider();
return NS_OK;
}
@ -176,7 +250,8 @@ NS_IMETHODIMP
WindowsLocationProvider::SetHighAccuracy(bool enable)
{
if (!mLocation) {
return NS_ERROR_FAILURE;
// MLS provider doesn't support HighAccuracy
return NS_OK;
}
LOCATION_DESIRED_ACCURACY desiredAccuracy;
@ -192,5 +267,28 @@ WindowsLocationProvider::SetHighAccuracy(bool enable)
return NS_OK;
}
nsresult
WindowsLocationProvider::CreateAndWatchMLSProvider(
nsIGeolocationUpdate* aCallback)
{
if (mMLSProvider) {
return NS_OK;
}
mMLSProvider = new MLSFallback();
return mMLSProvider->Startup(new MLSUpdate(aCallback));
}
void
WindowsLocationProvider::CancelMLSProvider()
{
if (!mMLSProvider) {
return;
}
mMLSProvider->Shutdown();
mMLSProvider = nullptr;
}
} // namespace dom
} // namespace mozilla

View File

@ -10,6 +10,8 @@
#include <locationapi.h>
class MLSFallback;
namespace mozilla {
namespace dom {
@ -21,10 +23,25 @@ public:
WindowsLocationProvider();
nsresult CreateAndWatchMLSProvider(nsIGeolocationUpdate* aCallback);
void CancelMLSProvider();
class MLSUpdate : public nsIGeolocationUpdate
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIGEOLOCATIONUPDATE
explicit MLSUpdate(nsIGeolocationUpdate* aCallback);
private:
nsCOMPtr<nsIGeolocationUpdate> mCallback;
virtual ~MLSUpdate() {}
};
private:
~WindowsLocationProvider() {}
~WindowsLocationProvider();
nsRefPtr<ILocation> mLocation;
nsRefPtr<MLSFallback> mMLSProvider;
};
} // namespace dom

View File

@ -9,6 +9,10 @@ SOURCES += [
'WindowsLocationProvider.cpp'
]
LOCAL_INCLUDES += [
'/dom/geolocation'
]
FAIL_ON_WARNINGS = True
FINAL_LIBRARY = 'xul'