2012-05-21 04:12:37 -07:00
|
|
|
/* 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/. */
|
2011-08-09 13:02:39 -07:00
|
|
|
|
2013-06-12 19:20:07 -07:00
|
|
|
// See https://developers.google.com/maps/documentation/business/geolocation/
|
2011-08-09 13:02:39 -07:00
|
|
|
|
2009-04-14 09:10:20 -07:00
|
|
|
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
2011-08-09 13:02:39 -07:00
|
|
|
Components.utils.import("resource://gre/modules/Services.jsm");
|
2009-04-14 09:10:20 -07:00
|
|
|
|
|
|
|
const Ci = Components.interfaces;
|
|
|
|
const Cc = Components.classes;
|
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
let gLoggingEnabled = false;
|
|
|
|
let gTestingEnabled = false;
|
2013-01-06 21:57:00 -08:00
|
|
|
let gUseScanning = true;
|
2009-04-14 09:10:20 -07:00
|
|
|
|
|
|
|
function LOG(aMsg) {
|
2009-08-14 16:12:09 -07:00
|
|
|
if (gLoggingEnabled)
|
|
|
|
{
|
2010-08-31 09:15:52 -07:00
|
|
|
aMsg = "*** WIFI GEO: " + aMsg + "\n";
|
2009-08-14 16:12:09 -07:00
|
|
|
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(aMsg);
|
|
|
|
dump(aMsg);
|
|
|
|
}
|
2009-04-14 09:10:20 -07:00
|
|
|
}
|
|
|
|
|
2009-08-14 16:12:09 -07:00
|
|
|
function WifiGeoCoordsObject(lat, lon, acc, alt, altacc) {
|
2011-08-09 13:02:39 -07:00
|
|
|
this.latitude = lat;
|
|
|
|
this.longitude = lon;
|
|
|
|
this.accuracy = acc;
|
|
|
|
this.altitude = alt;
|
|
|
|
this.altitudeAccuracy = altacc;
|
|
|
|
}
|
2009-04-14 09:10:20 -07:00
|
|
|
|
|
|
|
WifiGeoCoordsObject.prototype = {
|
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPositionCoords]),
|
2009-08-14 16:12:09 -07:00
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
classInfo: XPCOMUtils.generateCI({interfaces: [Ci.nsIDOMGeoPositionCoords],
|
|
|
|
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
|
|
|
classDescription: "wifi geo position coords object"}),
|
2009-04-14 09:10:20 -07:00
|
|
|
};
|
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
function WifiGeoPositionObject(lat, lng, acc) {
|
|
|
|
this.coords = new WifiGeoCoordsObject(lat, lng, acc, 0, 0);
|
|
|
|
this.address = null;
|
|
|
|
this.timestamp = Date.now();
|
|
|
|
}
|
2009-04-14 09:10:20 -07:00
|
|
|
|
|
|
|
WifiGeoPositionObject.prototype = {
|
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPosition]),
|
2009-04-14 09:10:20 -07:00
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
// Class Info is required to be able to pass objects back into the DOM.
|
|
|
|
classInfo: XPCOMUtils.generateCI({interfaces: [Ci.nsIDOMGeoPosition],
|
|
|
|
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
|
|
|
classDescription: "wifi geo location position object"}),
|
2009-04-14 09:10:20 -07:00
|
|
|
};
|
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
function WifiGeoPositionProvider() {
|
|
|
|
try {
|
|
|
|
gLoggingEnabled = Services.prefs.getBoolPref("geo.wifi.logging.enabled");
|
|
|
|
} catch (e) {}
|
|
|
|
|
|
|
|
try {
|
|
|
|
gTestingEnabled = Services.prefs.getBoolPref("geo.wifi.testing");
|
|
|
|
} catch (e) {}
|
|
|
|
|
2013-01-06 21:57:00 -08:00
|
|
|
try {
|
|
|
|
gUseScanning = Services.prefs.getBoolPref("geo.wifi.scan");
|
|
|
|
} catch (e) {}
|
|
|
|
|
2011-12-01 03:02:51 -08:00
|
|
|
this.wifiService = null;
|
|
|
|
this.timer = null;
|
|
|
|
this.hasSeenWiFi = false;
|
|
|
|
this.started = false;
|
2013-10-19 19:14:00 -07:00
|
|
|
// this is only used when logging is enabled, to debug interactions with the
|
|
|
|
// geolocation service
|
|
|
|
this.highAccuracy = false;
|
2011-08-09 13:02:39 -07:00
|
|
|
}
|
2010-02-11 11:59:55 -08:00
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
WifiGeoPositionProvider.prototype = {
|
|
|
|
classID: Components.ID("{77DA64D3-7458-4920-9491-86CC9914F904}"),
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIGeolocationProvider,
|
|
|
|
Ci.nsIWifiListener,
|
|
|
|
Ci.nsITimerCallback]),
|
|
|
|
startup: function() {
|
|
|
|
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);
|
|
|
|
},
|
|
|
|
|
2013-06-12 19:20:07 -07:00
|
|
|
watch: function(c) {
|
2011-08-09 13:02:39 -07:00
|
|
|
LOG("watch called");
|
2012-12-31 08:36:46 -08:00
|
|
|
|
2013-01-06 21:57:00 -08:00
|
|
|
if (!this.wifiService && gUseScanning) {
|
2011-08-09 13:02:39 -07:00
|
|
|
this.wifiService = Cc["@mozilla.org/wifi/monitor;1"].getService(Components.interfaces.nsIWifiMonitor);
|
|
|
|
this.wifiService.startWatching(this);
|
2010-02-11 11:59:55 -08:00
|
|
|
}
|
2012-02-29 22:58:37 -08:00
|
|
|
if (this.hasSeenWiFi) {
|
|
|
|
this.hasSeenWiFi = false;
|
2013-01-06 21:57:00 -08:00
|
|
|
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);
|
|
|
|
}
|
2012-02-29 22:58:37 -08:00
|
|
|
}
|
2011-08-09 13:02:39 -07:00
|
|
|
},
|
2010-02-11 11:59:55 -08:00
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
shutdown: function() {
|
|
|
|
LOG("shutdown called");
|
|
|
|
if(this.wifiService) {
|
|
|
|
this.wifiService.stopWatching(this);
|
|
|
|
this.wifiService = null;
|
|
|
|
}
|
|
|
|
if (this.timer != null) {
|
|
|
|
this.timer.cancel();
|
|
|
|
this.timer = null;
|
2010-02-11 11:59:55 -08:00
|
|
|
}
|
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
this.started = false;
|
|
|
|
},
|
|
|
|
|
2012-03-21 10:52:35 -07:00
|
|
|
setHighAccuracy: function(enable) {
|
2013-10-19 19:14:00 -07:00
|
|
|
this.highAccuracy = enable;
|
|
|
|
LOG("setting highAccuracy to " + (this.highAccuracy?"TRUE":"FALSE"));
|
2012-03-21 10:52:35 -07:00
|
|
|
},
|
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
onChange: function(accessPoints) {
|
2013-10-19 19:14:00 -07:00
|
|
|
LOG("onChange called, highAccuracy = " + (this.highAccuracy?"TRUE":"FALSE"));
|
2011-08-09 13:02:39 -07:00
|
|
|
this.hasSeenWiFi = true;
|
2009-08-14 16:12:09 -07:00
|
|
|
|
2013-06-12 19:20:07 -07:00
|
|
|
let url = Services.urlFormatter.formatURLPref("geo.wifi.uri");
|
2009-04-14 09:10:20 -07:00
|
|
|
|
2013-06-12 19:20:07 -07:00
|
|
|
function isPublic(ap) {
|
|
|
|
let mask = "_nomap"
|
|
|
|
let result = ap.ssid.indexOf(mask, ap.ssid.length - mask.length) == -1;
|
|
|
|
if (result != -1) {
|
|
|
|
LOG("Filtering out " + ap.ssid);
|
|
|
|
}
|
|
|
|
return result;
|
2011-08-09 13:02:39 -07:00
|
|
|
};
|
2009-05-07 10:52:39 -07:00
|
|
|
|
2013-06-12 19:20:07 -07:00
|
|
|
function sort(a, b) {
|
|
|
|
return b.signal - a.signal;
|
2013-06-13 20:20:15 -07:00
|
|
|
};
|
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
function encode(ap) {
|
2013-06-12 19:20:07 -07:00
|
|
|
return { 'macAddress': ap.mac, 'signalStrength': ap.signal };
|
2011-08-09 13:02:39 -07:00
|
|
|
};
|
|
|
|
|
2013-06-12 19:20:07 -07:00
|
|
|
var data;
|
2011-08-09 13:02:39 -07:00
|
|
|
if (accessPoints) {
|
2013-06-12 19:20:07 -07:00
|
|
|
data = JSON.stringify({wifiAccessPoints: accessPoints.filter(isPublic).sort(sort).map(encode)})
|
2011-08-09 13:02:39 -07:00
|
|
|
}
|
2009-07-10 17:03:48 -07:00
|
|
|
|
2013-06-12 19:20:07 -07:00
|
|
|
LOG("************************************* Sending request:\n" + url + "\n");
|
2009-04-14 09:10:20 -07:00
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
// send our request to a wifi geolocation network provider:
|
|
|
|
let xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
|
|
|
.createInstance(Ci.nsIXMLHttpRequest);
|
2009-04-14 09:10:20 -07:00
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
// This is a background load
|
2013-06-12 19:20:07 -07:00
|
|
|
|
2013-10-31 14:47:23 -07:00
|
|
|
xhr.open("POST", url, true);
|
2013-06-12 19:20:07 -07:00
|
|
|
xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
|
|
|
|
xhr.responseType = "json";
|
2011-08-09 13:02:39 -07:00
|
|
|
xhr.mozBackgroundRequest = true;
|
|
|
|
xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS;
|
2013-06-12 19:20:07 -07:00
|
|
|
xhr.onerror = function() {
|
|
|
|
LOG("onerror: " + xhr);
|
|
|
|
};
|
|
|
|
|
|
|
|
xhr.onload = function() {
|
|
|
|
LOG("gls returned status: " + xhr.status + " --> " + JSON.stringify(xhr.response));
|
2013-10-01 14:38:30 -07:00
|
|
|
if (xhr.channel instanceof Ci.nsIHttpChannel && xhr.status != 200) {
|
2013-06-12 19:20:07 -07:00
|
|
|
return;
|
2011-08-09 13:02:39 -07:00
|
|
|
}
|
2009-04-14 09:10:20 -07:00
|
|
|
|
2013-07-31 10:02:05 -07:00
|
|
|
if (!xhr.response || !xhr.response.location) {
|
2013-06-12 19:20:07 -07:00
|
|
|
return;
|
2011-08-09 13:02:39 -07:00
|
|
|
}
|
2009-04-14 09:10:20 -07:00
|
|
|
|
2013-06-12 19:20:07 -07:00
|
|
|
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);
|
2011-08-09 13:02:39 -07:00
|
|
|
},
|
2010-08-31 09:15:52 -07:00
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
onError: function (code) {
|
|
|
|
LOG("wifi error: " + code);
|
|
|
|
},
|
2010-08-31 09:15:52 -07:00
|
|
|
|
2011-08-09 13:02:39 -07:00
|
|
|
notify: function (timer) {
|
2013-01-06 21:57:00 -08:00
|
|
|
if (gTestingEnabled || !gUseScanning) {
|
2011-08-09 13:02:39 -07:00
|
|
|
// if we are testing, timer is repeating
|
|
|
|
this.onChange(null);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!this.hasSeenWiFi)
|
2010-08-31 09:15:52 -07:00
|
|
|
this.onChange(null);
|
2011-08-09 13:02:39 -07:00
|
|
|
this.timer = null;
|
|
|
|
}
|
|
|
|
},
|
2009-04-14 09:10:20 -07:00
|
|
|
};
|
|
|
|
|
2012-10-31 09:13:28 -07:00
|
|
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WifiGeoPositionProvider]);
|