Bug 978593 - refactor and cleanup NetworkLocationProvider. Prep work to enable celluar support. r=jdm

This commit is contained in:
Doug Turner 2014-03-01 23:46:02 -08:00
parent 158ac51adc
commit d9090c7201
2 changed files with 84 additions and 120 deletions

View File

@ -10,13 +10,18 @@ Components.utils.import("resource://gre/modules/Services.jsm");
const Ci = Components.interfaces;
const Cc = Components.classes;
const POSITION_UNAVAILABLE = Ci.nsIDOMGeoPositionError.POSITION_UNAVAILABLE;
let gLoggingEnabled = false;
let gTestingEnabled = false;
let gUseScanning = true;
// if we don't see any wifi responses in 5 seconds, send the request.
let gTimeToWaitBeforeSending = 5000; //ms
let gWifiScanningEnabled = true;
let gWifiResults;
function LOG(aMsg) {
if (gLoggingEnabled)
{
if (gLoggingEnabled) {
aMsg = "*** WIFI GEO: " + aMsg + "\n";
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(aMsg);
dump(aMsg);
@ -62,20 +67,16 @@ function WifiGeoPositionProvider() {
} catch (e) {}
try {
gTestingEnabled = Services.prefs.getBoolPref("geo.wifi.testing");
gTimeToWaitBeforeSending = Services.prefs.getIntPref("geo.wifi.timeToWaitBeforeSending");
} catch (e) {}
try {
gUseScanning = Services.prefs.getBoolPref("geo.wifi.scan");
gWifiScanningEnabled = Services.prefs.getBoolPref("geo.wifi.scan");
} catch (e) {}
this.wifiService = null;
this.timer = null;
this.hasSeenWiFi = false;
this.timeoutTimer = null;
this.started = false;
// this is only used when logging is enabled, to debug interactions with the
// geolocation service
this.highAccuracy = false;
}
WifiGeoPositionProvider.prototype = {
@ -87,74 +88,51 @@ WifiGeoPositionProvider.prototype = {
if (this.started)
return;
this.started = true;
this.hasSeenWiFi = false;
LOG("startup called. testing mode is" + gTestingEnabled);
// if we don't see anything in 5 seconds, kick of one IP geo lookup.
// if we are testing, just hammer this callback so that we are more or less
// always sending data. It doesn't matter if we have an access point or not.
this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
if (!gTestingEnabled)
this.timer.initWithCallback(this, 5000, this.timer.TYPE_ONE_SHOT);
else
this.timer.initWithCallback(this, 200, this.timer.TYPE_REPEATING_SLACK);
},
watch: function(c) {
LOG("watch called");
if (!this.wifiService && gUseScanning) {
if (gWifiScanningEnabled) {
this.wifiService = Cc["@mozilla.org/wifi/monitor;1"].getService(Components.interfaces.nsIWifiMonitor);
this.wifiService.startWatching(this);
}
if (this.hasSeenWiFi) {
this.hasSeenWiFi = false;
if (gUseScanning) {
this.wifiService.stopWatching(this);
this.wifiService.startWatching(this);
} else {
// For testing situations, ensure that we always trigger an update.
this.timer.initWithCallback(this, 5000, this.timer.TYPE_ONE_SHOT);
}
}
this.timeoutTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this.timeoutTimer.initWithCallback(this,
gTimeToWaitBeforeSending,
this.timeoutTimer.TYPE_REPEATING_SLACK);
LOG("startup called.");
},
shutdown: function() {
watch: function(c) {
},
shutdown: function() {
LOG("shutdown called");
if (this.started == false) {
return;
}
if (this.timeoutTimer) {
this.timeoutTimer.cancel();
this.timeoutTimer = null;
}
if(this.wifiService) {
this.wifiService.stopWatching(this);
this.wifiService = null;
}
if (this.timer != null) {
this.timer.cancel();
this.timer = null;
}
this.started = false;
},
setHighAccuracy: function(enable) {
this.highAccuracy = enable;
LOG("setting highAccuracy to " + (this.highAccuracy?"TRUE":"FALSE"));
},
onChange: function(accessPoints) {
LOG("onChange called, highAccuracy = " + (this.highAccuracy?"TRUE":"FALSE"));
this.hasSeenWiFi = true;
Cc["@mozilla.org/geolocation/service;1"].getService(Ci.nsIGeolocationUpdate)
.locationUpdatePending();
let url = Services.urlFormatter.formatURLPref("geo.wifi.uri");
function isPublic(ap) {
let mask = "_nomap"
let result = ap.ssid.indexOf(mask, ap.ssid.length - mask.length);
if (result != -1) {
LOG("Filtering out " + ap.ssid + " " + result);
}
return result;
let mask = "_nomap"
let result = ap.ssid.indexOf(mask, ap.ssid.length - mask.length);
if (result != -1) {
LOG("Filtering out " + ap.ssid + " " + result);
}
return result;
};
function sort(a, b) {
@ -162,80 +140,65 @@ WifiGeoPositionProvider.prototype = {
};
function encode(ap) {
return { 'macAddress': ap.mac, 'signalStrength': ap.signal };
return { 'macAddress': ap.mac, 'signalStrength': ap.signal };
};
var data;
if (accessPoints) {
data = JSON.stringify({wifiAccessPoints: accessPoints.filter(isPublic).sort(sort).map(encode)})
data = JSON.stringify({wifiAccessPoints: accessPoints.filter(isPublic).sort(sort).map(encode)})
}
LOG("************************************* Sending request:\n" + url + "\n");
// send our request to a wifi geolocation network provider:
let xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
// This is a background load
try {
xhr.open("POST", url, true);
} catch (e) {
triggerError();
return;
}
xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
xhr.responseType = "json";
xhr.mozBackgroundRequest = true;
xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS;
xhr.onerror = function() {
LOG("onerror: " + xhr);
triggerError();
};
xhr.onload = function() {
LOG("gls returned status: " + xhr.status + " --> " + JSON.stringify(xhr.response));
if (xhr.channel instanceof Ci.nsIHttpChannel && xhr.status != 200) {
triggerError();
return;
}
if (!xhr.response || !xhr.response.location) {
triggerError();
return;
}
let newLocation = new WifiGeoPositionObject(xhr.response.location.lat,
xhr.response.location.lng,
xhr.response.accuracy);
Cc["@mozilla.org/geolocation/service;1"].getService(Ci.nsIGeolocationUpdate)
.update(newLocation);
};
LOG("************************************* ------>>>> sending " + data);
xhr.send(data);
gWifiResults = data;
},
onError: function (code) {
LOG("wifi error: " + code);
},
notify: function (timer) {
if (gTestingEnabled || !gUseScanning) {
// if we are testing, timer is repeating
this.onChange(null);
}
else {
if (!this.hasSeenWiFi)
this.onChange(null);
this.timer = null;
notify: function (timeoutTimer) {
let url = Services.urlFormatter.formatURLPref("geo.wifi.uri");
LOG("Sending request: " + url + "\n");
let xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
getGeoService().locationUpdatePending();
try {
xhr.open("POST", url, true);
} catch (e) {
getGeoService().notifyError(POSITION_UNAVAILABLE);
return;
}
xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
xhr.responseType = "json";
xhr.mozBackgroundRequest = true;
xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS;
xhr.onerror = function() {
getGeoService().notifyError(POSITION_UNAVAILABLE);
};
xhr.onload = function() {
LOG("gls returned status: " + xhr.status + " --> " + JSON.stringify(xhr.response));
if ((xhr.channel instanceof Ci.nsIHttpChannel && xhr.status != 200) ||
!xhr.response || !xhr.response.location) {
getGeoService().notifyError(POSITION_UNAVAILABLE);
return;
}
let newLocation = new WifiGeoPositionObject(xhr.response.location.lat,
xhr.response.location.lng,
xhr.response.accuracy);
getGeoService().update(newLocation);
};
let data = gWifiResults;
LOG("sending " + data);
xhr.send(data);
},
};
function triggerError() {
Cc["@mozilla.org/geolocation/service;1"].getService(Ci.nsIGeolocationUpdate)
.notifyError(Ci.nsIDOMGeoPositionError.POSITION_UNAVAILABLE);
function getGeoService() {
return Cc["@mozilla.org/geolocation/service;1"].getService(Ci.nsIGeolocationUpdate);
}
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WifiGeoPositionProvider]);

View File

@ -61,7 +61,8 @@ user_pref("extensions.installDistroAddons", false);
user_pref("extensions.defaultProviders.enabled", true);
user_pref("geo.wifi.uri", "http://%(server)s/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs");
user_pref("geo.wifi.testing", true);
user_pref("geo.wifi.timeToWaitBeforeSending", 200);
user_pref("geo.wifi.scan", false);
user_pref("geo.wifi.logging.enabled", true);
user_pref("camino.warn_when_closing", false); // Camino-only, harmless to others