Bug 1134019 - Extract MLS fallback to its own class for reuse - r=jdm

This commit is contained in:
Garvan Keeley 2015-02-27 19:15:32 -05:00
parent e941340ce5
commit 8f8b1e0ac7
5 changed files with 155 additions and 45 deletions

View File

@ -0,0 +1,82 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "MLSFallback.h"
#include "nsGeoPosition.h"
#include "nsIGeolocationProvider.h"
#include "nsServiceManagerUtils.h"
NS_IMPL_ISUPPORTS(MLSFallback, nsITimerCallback)
MLSFallback::MLSFallback(uint32_t delay)
: mDelayMs(delay)
{
}
MLSFallback::~MLSFallback()
{
}
nsresult
MLSFallback::Startup(nsIGeolocationUpdate* aWatcher)
{
if (mHandoffTimer || mMLSFallbackProvider) {
return NS_OK;
}
mUpdateWatcher = aWatcher;
nsresult rv;
mHandoffTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = mHandoffTimer->InitWithCallback(this, mDelayMs, nsITimer::TYPE_ONE_SHOT);
return rv;
}
nsresult
MLSFallback::Shutdown()
{
mUpdateWatcher = nullptr;
if (mHandoffTimer) {
mHandoffTimer->Cancel();
mHandoffTimer = nullptr;
}
nsresult rv = NS_OK;
if (mMLSFallbackProvider) {
rv = mMLSFallbackProvider->Shutdown();
mMLSFallbackProvider = nullptr;
}
return rv;
}
NS_IMETHODIMP
MLSFallback::Notify(nsITimer* aTimer)
{
return CreateMLSFallbackProvider();
}
nsresult
MLSFallback::CreateMLSFallbackProvider()
{
if (mMLSFallbackProvider || !mUpdateWatcher) {
return NS_OK;
}
nsresult rv;
mMLSFallbackProvider = do_CreateInstance("@mozilla.org/geolocation/mls-provider;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
if (mMLSFallbackProvider) {
rv = mMLSFallbackProvider->Startup();
if (NS_SUCCEEDED(rv)) {
mMLSFallbackProvider->Watch(mUpdateWatcher);
}
}
mUpdateWatcher = nullptr;
return rv;
}

View File

@ -0,0 +1,47 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsCOMPtr.h"
#include "nsITimer.h"
class nsIGeolocationUpdate;
class nsIGeolocationProvider;
/*
This class wraps the NetworkGeolocationProvider in a delayed startup.
It is for providing a fallback to MLS when:
1) using another provider as the primary provider, and
2) that primary provider may fail to return a result (i.e. the error returned
is indeterminate, or no error callback occurs)
The intent is that the primary provider is started, then MLSFallback
is started with sufficient delay that the primary provider will respond first
if successful (in the majority of cases).
MLS has an average response of 3s, so with the 2s default delay, a response can
be expected in 5s.
Telemetry is recommended to monitor that the primary provider is responding
first when expected to do so.
*/
class MLSFallback : public nsITimerCallback
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSITIMERCALLBACK
explicit MLSFallback(uint32_t delayMs = 2000);
nsresult Startup(nsIGeolocationUpdate* aWatcher);
nsresult Shutdown();
private:
nsresult CreateMLSFallbackProvider();
virtual ~MLSFallback();
nsCOMPtr<nsITimer> mHandoffTimer;
nsCOMPtr<nsIGeolocationProvider> mMLSFallbackProvider;
nsCOMPtr<nsIGeolocationUpdate> mUpdateWatcher;
const uint32_t mDelayMs;
};

View File

@ -15,6 +15,7 @@ SOURCES += [
]
UNIFIED_SOURCES += [
'MLSFallback.cpp',
'nsGeoGridFuzzer.cpp',
'nsGeolocationSettings.cpp',
'nsGeoPosition.cpp',

View File

@ -6,6 +6,7 @@
#include "nsCOMPtr.h"
#include "nsIGeolocationProvider.h"
/*
* The CoreLocationObjects class contains the CoreLocation objects
* we'll need.
@ -21,6 +22,7 @@
* for nsGeolocation.cpp, which is C++-only, to include this header.
*/
class CoreLocationObjects;
class MLSFallback;
class CoreLocationLocationProvider
: public nsIGeolocationProvider
@ -36,11 +38,11 @@ public:
void CancelMLSFallbackProvider();
private:
virtual ~CoreLocationLocationProvider() {};
virtual ~CoreLocationLocationProvider();
CoreLocationObjects* mCLObjects;
nsCOMPtr<nsIGeolocationUpdate> mCallback;
nsCOMPtr<nsIGeolocationProvider> mMLSFallbackProvider;
nsRefPtr<MLSFallback> mMLSFallbackProvider;
class MLSUpdate : public nsIGeolocationUpdate
{
@ -52,6 +54,6 @@ private:
private:
CoreLocationLocationProvider& mParentLocationProvider;
virtual ~MLSUpdate() {}
virtual ~MLSUpdate();
};
};

View File

@ -13,6 +13,7 @@
#include "nsCocoaFeatures.h"
#include "prtime.h"
#include "mozilla/Telemetry.h"
#include "MLSFallback.h"
#include <CoreLocation/CLError.h>
#include <CoreLocation/CLLocation.h>
@ -32,7 +33,6 @@ static const CLLocationAccuracy kDEFAULT_ACCURACY = kCLLocationAccuracyNearestTe
@interface LocationDelegate : NSObject <CLLocationManagerDelegate>
{
CoreLocationLocationProvider* mProvider;
NSTimer* mHandoffTimer;
}
- (id)init:(CoreLocationLocationProvider*)aProvider;
@ -52,23 +52,6 @@ static const CLLocationAccuracy kDEFAULT_ACCURACY = kCLLocationAccuracyNearestTe
return self;
}
- (void)shutdownHandoffTimer
{
if (!mHandoffTimer) {
return;
}
[mHandoffTimer invalidate];
[mHandoffTimer release];
mHandoffTimer = nil;
}
- (void)handoffToGeoIPProvider
{
[self shutdownHandoffTimer];
mProvider->CreateMLSFallbackProvider();
}
- (void)locationManager:(CLLocationManager*)aManager
didFailWithError:(NSError *)aError
{
@ -87,21 +70,15 @@ static const CLLocationAccuracy kDEFAULT_ACCURACY = kCLLocationAccuracyNearestTe
return;
}
if (!mHandoffTimer) {
// The CL provider does not fallback to GeoIP, so use NetworkGeolocationProvider for this.
// The concept here is: on error, hand off geolocation to MLS, which will then report
// back a location or error. We can't call this with no delay however, as this method
// is called with an error code of 0 in both failed geolocation cases, and also when
// geolocation is not immediately available.
// The 2 sec delay is arbitrarily large enough that CL has a reasonable head start and
// if it is likely to succeed, it should complete before the MLS provider.
// Take note that in locationManager:didUpdateLocations: the handoff to MLS is stopped.
mHandoffTimer = [[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:@selector(handoffToGeoIPProvider)
userInfo:nil
repeats:NO] retain];
}
// The CL provider does not fallback to GeoIP, so use NetworkGeolocationProvider for this.
// The concept here is: on error, hand off geolocation to MLS, which will then report
// back a location or error. We can't call this with no delay however, as this method
// is called with an error code of 0 in both failed geolocation cases, and also when
// geolocation is not immediately available.
// The 2 sec delay is arbitrarily large enough that CL has a reasonable head start and
// if it is likely to succeed, it should complete before the MLS provider.
// Take note that in locationManager:didUpdateLocations: the handoff to MLS is stopped.
mProvider->CreateMLSFallbackProvider();
}
- (void)locationManager:(CLLocationManager*)aManager didUpdateLocations:(NSArray*)aLocations
@ -110,7 +87,6 @@ static const CLLocationAccuracy kDEFAULT_ACCURACY = kCLLocationAccuracyNearestTe
return;
}
[self shutdownHandoffTimer];
mProvider->CancelMLSFallbackProvider();
CLLocation* location = [aLocations objectAtIndex:0];
@ -137,6 +113,10 @@ CoreLocationLocationProvider::MLSUpdate::MLSUpdate(CoreLocationLocationProvider&
{
}
CoreLocationLocationProvider::MLSUpdate::~MLSUpdate()
{
}
NS_IMETHODIMP
CoreLocationLocationProvider::MLSUpdate::Update(nsIDOMGeoPosition *position)
{
@ -200,6 +180,10 @@ CoreLocationLocationProvider::CoreLocationLocationProvider()
{
}
CoreLocationLocationProvider::~CoreLocationLocationProvider()
{
}
NS_IMETHODIMP
CoreLocationLocationProvider::Startup()
{
@ -234,7 +218,6 @@ CoreLocationLocationProvider::Shutdown()
{
NS_ENSURE_STATE(mCLObjects);
[mCLObjects->mLocationDelegate shutdownHandoffTimer];
[mCLObjects->mLocationManager stopUpdatingLocation];
delete mCLObjects;
@ -280,13 +263,8 @@ CoreLocationLocationProvider::CreateMLSFallbackProvider()
return;
}
mMLSFallbackProvider = do_CreateInstance("@mozilla.org/geolocation/mls-provider;1");
if (mMLSFallbackProvider) {
nsresult rv = mMLSFallbackProvider->Startup();
if (NS_SUCCEEDED(rv)) {
mMLSFallbackProvider->Watch(new CoreLocationLocationProvider::MLSUpdate(*this));
}
}
mMLSFallbackProvider = new MLSFallback();
mMLSFallbackProvider->Startup(new MLSUpdate(*this));
}
void