mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-10 05:08:36 +02:00
151 lines
3.9 KiB
JavaScript
151 lines
3.9 KiB
JavaScript
/* 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/. */
|
|
|
|
"use strict";
|
|
|
|
const EXPORTED_SYMBOLS = ["Region"];
|
|
|
|
const { XPCOMUtils } = ChromeUtils.import(
|
|
"resource://gre/modules/XPCOMUtils.jsm"
|
|
);
|
|
|
|
XPCOMUtils.defineLazyModuleGetters(this, {
|
|
LocationHelper: "resource://gre/modules/LocationHelper.jsm",
|
|
Services: "resource://gre/modules/Services.jsm",
|
|
setTimeout: "resource://gre/modules/Timer.jsm",
|
|
});
|
|
|
|
XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
|
|
|
|
XPCOMUtils.defineLazyPreferenceGetter(
|
|
this,
|
|
"wifiScanningEnabled",
|
|
"browser.region.network.scan",
|
|
true
|
|
);
|
|
|
|
XPCOMUtils.defineLazyPreferenceGetter(
|
|
this,
|
|
"regionFetchTimeout",
|
|
"browser.region.timeout",
|
|
5000
|
|
);
|
|
|
|
XPCOMUtils.defineLazyPreferenceGetter(
|
|
this,
|
|
"loggingEnabled",
|
|
"browser.region.log",
|
|
false
|
|
);
|
|
|
|
const log = console.createInstance({
|
|
prefix: "Region.jsm",
|
|
maxLogLevel: loggingEnabled ? "All" : "Warn",
|
|
});
|
|
|
|
function timeout(ms) {
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
/**
|
|
* This module keeps track of the users current region (country).
|
|
* so the SearchService and other consumers can apply region
|
|
* specific customisations.
|
|
*/
|
|
class RegionDetector {
|
|
// Keep track of the wifi data across listener events.
|
|
wifiDataPromise = null;
|
|
// Store the AbortController for the geolocation requests so we
|
|
// can abort the request on timeout.
|
|
fetchController = null;
|
|
|
|
/**
|
|
* Fetch the region that we consider to be the users home region.
|
|
*
|
|
* @returns {object}
|
|
* JSON with country_code field defining users current region.
|
|
*/
|
|
async getHomeRegion() {
|
|
return Promise.race([this._getRegion(), this._timeout()]);
|
|
}
|
|
|
|
/**
|
|
* Implementation of the above region fetching.
|
|
*/
|
|
async _getRegion() {
|
|
log.info("getRegion called");
|
|
this.fetchController = new AbortController();
|
|
let fetchOpts = {
|
|
headers: { "Content-Type": "application/json" },
|
|
credentials: "omit",
|
|
signal: this.fetchController.signal,
|
|
};
|
|
if (wifiScanningEnabled) {
|
|
let wifiData = await this._fetchWifiData();
|
|
if (wifiData) {
|
|
let postData = JSON.stringify({ wifiAccessPoints: wifiData });
|
|
log.info("Sending wifi details: ", wifiData);
|
|
fetchOpts.method = "POST";
|
|
fetchOpts.body = postData;
|
|
}
|
|
}
|
|
let url = Services.urlFormatter.formatURLPref("browser.region.network.url");
|
|
let req = await fetch(url, fetchOpts);
|
|
|
|
try {
|
|
let res = await req.json();
|
|
this.fetchController = null;
|
|
log.info("getRegion returning " + res.country_code);
|
|
return { country_code: res.country_code };
|
|
} catch (err) {
|
|
log.error("Error fetching region", err);
|
|
throw new Error("region-fetch-no-result");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implement the timeout for region requests. This will be run for
|
|
* all region requests, but the error will only be returned if it
|
|
* completes first.
|
|
*/
|
|
async _timeout() {
|
|
await timeout(regionFetchTimeout);
|
|
if (this.fetchController) {
|
|
this.fetchController.abort();
|
|
}
|
|
throw new Error("region-fetch-timeout");
|
|
}
|
|
|
|
async _fetchWifiData() {
|
|
log.info("fetchWifiData called");
|
|
this.wifiService = Cc["@mozilla.org/wifi/monitor;1"].getService(
|
|
Ci.nsIWifiMonitor
|
|
);
|
|
this.wifiService.startWatching(this);
|
|
|
|
return new Promise(resolve => {
|
|
this.wifiDataPromise = resolve;
|
|
});
|
|
}
|
|
|
|
onChange(accessPoints) {
|
|
log.info("onChange called");
|
|
if (!accessPoints || !this.wifiDataPromise) {
|
|
return;
|
|
}
|
|
|
|
if (this.wifiService) {
|
|
this.wifiService.stopWatching(this);
|
|
this.wifiService = null;
|
|
}
|
|
|
|
if (this.wifiDataPromise) {
|
|
let data = LocationHelper.formatWifiAccessPoints(accessPoints);
|
|
this.wifiDataPromise(data);
|
|
this.wifiDataPromise = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
let Region = new RegionDetector();
|