mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 16:22:00 +00:00
Bug 1589618 - Move the implementation of the region fetch to NetworkGeolocationProvider to have it close to the wifi scanning code. r=Standard8,garvan
Differential Revision: https://phabricator.services.mozilla.com/D62419 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
64d1a3665c
commit
af0051aade
@ -14,28 +14,16 @@ XPCOMUtils.defineLazyGlobalGetters(this, ["XMLHttpRequest"]);
|
||||
// GeolocationPositionError has no interface object, so we can't use that here.
|
||||
const POSITION_UNAVAILABLE = 2;
|
||||
|
||||
var gLoggingEnabled = false;
|
||||
|
||||
/*
|
||||
The gLocationRequestTimeout controls how long we wait on receiving an update
|
||||
from the Wifi subsystem. If this timer fires, we believe the Wifi scan has
|
||||
had a problem and we no longer can use Wifi to position the user this time
|
||||
around (we will continue to be hopeful that Wifi will recover).
|
||||
|
||||
This timeout value is also used when Wifi scanning is disabled (see
|
||||
gWifiScanningEnabled). In this case, we use this timer to collect cell/ip
|
||||
data and xhr it to the location server.
|
||||
*/
|
||||
|
||||
var gLocationRequestTimeout = 5000;
|
||||
|
||||
var gWifiScanningEnabled = true;
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"gLoggingEnabled",
|
||||
"geo.provider.network.logging.enabled",
|
||||
false
|
||||
);
|
||||
|
||||
function LOG(aMsg) {
|
||||
if (gLoggingEnabled) {
|
||||
aMsg = "*** WIFI GEO: " + aMsg + "\n";
|
||||
Services.console.logStringMessage(aMsg);
|
||||
dump(aMsg);
|
||||
dump("*** WIFI GEO: " + aMsg + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,19 +239,38 @@ NetworkGeoPositionObject.prototype = {
|
||||
};
|
||||
|
||||
function NetworkGeolocationProvider() {
|
||||
gLoggingEnabled = Services.prefs.getBoolPref(
|
||||
"geo.provider.network.logging.enabled",
|
||||
false
|
||||
);
|
||||
gLocationRequestTimeout = Services.prefs.getIntPref(
|
||||
this.mode = "provider";
|
||||
/*
|
||||
The _wifiMonitorTimeout controls how long we wait on receiving an update
|
||||
from the Wifi subsystem. If this timer fires, we believe the Wifi scan has
|
||||
had a problem and we no longer can use Wifi to position the user this time
|
||||
around (we will continue to be hopeful that Wifi will recover).
|
||||
|
||||
This timeout value is also used when Wifi scanning is disabled (see
|
||||
isWifiScanningEnabled). In this case, we use this timer to collect cell/ip
|
||||
data and xhr it to the location server.
|
||||
*/
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"_wifiMonitorTimeout",
|
||||
"geo.provider.network.timeToWaitBeforeSending",
|
||||
5000
|
||||
);
|
||||
gWifiScanningEnabled = Services.prefs.getBoolPref(
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"_wifiScanningEnabled",
|
||||
"geo.provider.network.scan",
|
||||
true
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"_wifiScanningEnabledCountry",
|
||||
"geo.provider-country.network.scan",
|
||||
true
|
||||
);
|
||||
|
||||
this.wifiService = null;
|
||||
this.timer = null;
|
||||
this.started = false;
|
||||
@ -279,6 +286,12 @@ NetworkGeolocationProvider.prototype = {
|
||||
]),
|
||||
listener: null,
|
||||
|
||||
get isWifiScanningEnabled() {
|
||||
return Cc["@mozilla.org/wifi/monitor;1"] && this.mode == "provider"
|
||||
? this._wifiScanningEnabled
|
||||
: this._wifiScanningEnabledCountry;
|
||||
},
|
||||
|
||||
resetTimer() {
|
||||
if (this.timer) {
|
||||
this.timer.cancel();
|
||||
@ -289,7 +302,7 @@ NetworkGeolocationProvider.prototype = {
|
||||
this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
this.timer.initWithCallback(
|
||||
this,
|
||||
gLocationRequestTimeout,
|
||||
this._wifiMonitorTimeout,
|
||||
this.timer.TYPE_REPEATING_SLACK
|
||||
);
|
||||
},
|
||||
@ -301,7 +314,7 @@ NetworkGeolocationProvider.prototype = {
|
||||
|
||||
this.started = true;
|
||||
|
||||
if (gWifiScanningEnabled && Cc["@mozilla.org/wifi/monitor;1"]) {
|
||||
if (this.isWifiScanningEnabled) {
|
||||
if (this.wifiService) {
|
||||
this.wifiService.stopWatching(this);
|
||||
}
|
||||
@ -382,53 +395,142 @@ NetworkGeolocationProvider.prototype = {
|
||||
this.sendLocationRequest(null);
|
||||
},
|
||||
|
||||
onStatus(err, statusMessage) {
|
||||
if (!this.listener) {
|
||||
return;
|
||||
}
|
||||
LOG("onStatus called." + statusMessage);
|
||||
|
||||
if (statusMessage && this.listener.notifyStatus) {
|
||||
this.listener.notifyStatus(statusMessage);
|
||||
}
|
||||
|
||||
if (err && this.listener.notifyError) {
|
||||
this.listener.notifyError(POSITION_UNAVAILABLE, statusMessage);
|
||||
}
|
||||
},
|
||||
|
||||
notify(timer) {
|
||||
this.onStatus(false, "wifi-timeout");
|
||||
this.sendLocationRequest(null);
|
||||
},
|
||||
|
||||
/**
|
||||
* One-shot country identifier fetch.
|
||||
*
|
||||
* @param {Function} statusCallback This method is called for each
|
||||
* intermediate result with the current
|
||||
* state of the request as argument.
|
||||
* @return {Promise<String>} A promise that is resolved with a country code or
|
||||
* rejected with an error.
|
||||
*/
|
||||
async getCountry(statusCallback) {
|
||||
this.mode = "provider-country";
|
||||
|
||||
let self = this;
|
||||
let promise = new Promise((resolve, reject) => {
|
||||
this.watch({
|
||||
update(country) {
|
||||
resolve(country);
|
||||
self.shutdown();
|
||||
},
|
||||
notifyError(code, message) {
|
||||
reject(message);
|
||||
self.shutdown();
|
||||
},
|
||||
notifyStatus(status) {
|
||||
if (statusCallback) {
|
||||
statusCallback(status);
|
||||
}
|
||||
},
|
||||
});
|
||||
}).finally(() => {
|
||||
this.mode = "provider";
|
||||
});
|
||||
|
||||
this.startup();
|
||||
Services.tm.dispatchToMainThread(() => this.sendLocationRequest(null));
|
||||
|
||||
return promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* After wifi (and possible cell tower) data has been gathered, this method is
|
||||
* invoked to perform the request to network geolocation provider.
|
||||
* The result of each request is sent to all registered listener (@see watch)
|
||||
* by invoking its respective `update`, `notifyError` or `notifyStatus`
|
||||
* callbacks.
|
||||
* `update` is called upon a successful request with its response data; in the
|
||||
* 'provider-country' mode this will be a country code string and in the
|
||||
* 'provider' mode - the default mode of operation for this class - this will
|
||||
* be a `NetworkGeoPositionObject` instance.
|
||||
* `notifyError` is called whenever the request gets an error from the local
|
||||
* network subsystem, the server or simply times out.
|
||||
* `notifyStatus` is called for each status change of the request that may be
|
||||
* of interest to the consumer of this class. Currently the following status
|
||||
* changes are reported: 'xhr-start', 'xhr-timeout', 'xhr-error' and
|
||||
* 'xhr-empty'.
|
||||
*
|
||||
* @param {Array} wifiData Optional set of publicly available wifi networks
|
||||
* in the following structure:
|
||||
* <code>
|
||||
* [
|
||||
* { macAddress: <mac1>, signalStrength: <signal1> },
|
||||
* { macAddress: <mac2>, signalStrength: <signal2> }
|
||||
* ]
|
||||
* </code>
|
||||
*/
|
||||
sendLocationRequest(wifiData) {
|
||||
let data = { cellTowers: undefined, wifiAccessPoints: undefined };
|
||||
if (wifiData && wifiData.length >= 2) {
|
||||
data.wifiAccessPoints = wifiData;
|
||||
}
|
||||
|
||||
let useCached = isCachedRequestMoreAccurateThanServerRequest(
|
||||
data.cellTowers,
|
||||
data.wifiAccessPoints
|
||||
);
|
||||
// The 'provider' mode is the only one that supports response caching at the
|
||||
// moment.
|
||||
if (this.mode == "provider") {
|
||||
let useCached = isCachedRequestMoreAccurateThanServerRequest(
|
||||
data.cellTowers,
|
||||
data.wifiAccessPoints
|
||||
);
|
||||
|
||||
LOG("Use request cache:" + useCached + " reason:" + gDebugCacheReasoning);
|
||||
LOG("Use request cache:" + useCached + " reason:" + gDebugCacheReasoning);
|
||||
|
||||
if (useCached) {
|
||||
gCachedRequest.location.timestamp = Date.now();
|
||||
if (this.listener) {
|
||||
this.listener.update(gCachedRequest.location);
|
||||
if (useCached) {
|
||||
gCachedRequest.location.timestamp = Date.now();
|
||||
if (this.listener) {
|
||||
this.listener.update(gCachedRequest.location);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// From here on, do a network geolocation request //
|
||||
let url = Services.urlFormatter.formatURLPref("geo.provider.network.url");
|
||||
let url = Services.urlFormatter.formatURLPref(
|
||||
"geo." + this.mode + ".network.url"
|
||||
);
|
||||
LOG("Sending request");
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
this.onStatus(false, "xhr-start");
|
||||
try {
|
||||
xhr.open("POST", url, true);
|
||||
xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS;
|
||||
} catch (e) {
|
||||
notifyPositionUnavailable(this.listener);
|
||||
this.onStatus(true, "xhr-error");
|
||||
return;
|
||||
}
|
||||
xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
|
||||
xhr.responseType = "json";
|
||||
xhr.mozBackgroundRequest = true;
|
||||
// The timeout value doesn't need to change in a different mode.
|
||||
xhr.timeout = Services.prefs.getIntPref("geo.provider.network.timeout");
|
||||
xhr.ontimeout = () => {
|
||||
LOG("Location request XHR timed out.");
|
||||
notifyPositionUnavailable(this.listener);
|
||||
this.onStatus(true, "xhr-timeout");
|
||||
};
|
||||
xhr.onerror = () => {
|
||||
notifyPositionUnavailable(this.listener);
|
||||
this.onStatus(true, "xhr-error");
|
||||
};
|
||||
xhr.onload = () => {
|
||||
LOG(
|
||||
@ -439,38 +541,39 @@ NetworkGeolocationProvider.prototype = {
|
||||
);
|
||||
if (
|
||||
(xhr.channel instanceof Ci.nsIHttpChannel && xhr.status != 200) ||
|
||||
!xhr.response ||
|
||||
!xhr.response.location
|
||||
!xhr.response
|
||||
) {
|
||||
notifyPositionUnavailable(this.listener);
|
||||
this.onStatus(true, !xhr.response ? "xhr-empty" : "xhr-error");
|
||||
return;
|
||||
}
|
||||
|
||||
let newLocation = new NetworkGeoPositionObject(
|
||||
xhr.response.location.lat,
|
||||
xhr.response.location.lng,
|
||||
xhr.response.accuracy
|
||||
);
|
||||
let newLocation;
|
||||
if (this.mode == "provider-country") {
|
||||
newLocation = xhr.response && xhr.response.country_code;
|
||||
} else {
|
||||
newLocation = new NetworkGeoPositionObject(
|
||||
xhr.response.location.lat,
|
||||
xhr.response.location.lng,
|
||||
xhr.response.accuracy
|
||||
);
|
||||
}
|
||||
|
||||
if (this.listener) {
|
||||
this.listener.update(newLocation);
|
||||
}
|
||||
gCachedRequest = new CachedRequest(
|
||||
newLocation,
|
||||
data.cellTowers,
|
||||
data.wifiAccessPoints
|
||||
);
|
||||
|
||||
if (this.mode == "provider") {
|
||||
gCachedRequest = new CachedRequest(
|
||||
newLocation,
|
||||
data.cellTowers,
|
||||
data.wifiAccessPoints
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
var requestData = JSON.stringify(data);
|
||||
LOG("sending " + requestData);
|
||||
xhr.send(requestData);
|
||||
|
||||
function notifyPositionUnavailable(listener) {
|
||||
if (listener) {
|
||||
listener.notifyError(POSITION_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -84,7 +84,7 @@ function check_geolocation(location) {
|
||||
ok(location, "Check to see if this location is non-null");
|
||||
|
||||
const timestamp = location.timestamp;
|
||||
dump(`timestamp=$timestamp}\n`);
|
||||
dump(`timestamp=${timestamp}\n`);
|
||||
ok(IsNumber(timestamp), "check timestamp type");
|
||||
ok(timestamp > 0, "check timestamp range");
|
||||
|
||||
|
@ -4051,6 +4051,10 @@ pref("network.psl.onUpdate_notify", false);
|
||||
pref("geo.provider.network.url", "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%");
|
||||
#endif
|
||||
|
||||
pref("geo.provider-country.network.url", "https://location.services.mozilla.com/v1/country?key=%MOZILLA_API_KEY%");
|
||||
pref("geo.provider-country.network.scan", false);
|
||||
// Timeout to wait before sending the location request.
|
||||
pref("geo.provider.network.timeToWaitBeforeSending", 5000);
|
||||
// Timeout for outbound network geolocation provider.
|
||||
pref("geo.provider.network.timeout", 60000);
|
||||
|
||||
@ -4496,8 +4500,6 @@ pref("browser.search.update.interval", 21600);
|
||||
pref("browser.search.suggest.enabled", true);
|
||||
pref("browser.search.suggest.enabled.private", false);
|
||||
pref("browser.search.geoSpecificDefaults", false);
|
||||
pref("browser.search.geoip.url", "https://location.services.mozilla.com/v1/country?key=%MOZILLA_API_KEY%");
|
||||
pref("browser.search.geoip.timeout", 3000);
|
||||
pref("browser.search.modernConfig", false);
|
||||
pref("browser.search.separatePrivateDefault", false);
|
||||
pref("browser.search.separatePrivateDefault.ui.enabled", false);
|
||||
|
@ -29,7 +29,6 @@ user_pref("browser.safebrowsing.provider.google4.gethashURL", "http://127.0.0.1/
|
||||
user_pref("browser.safebrowsing.provider.google4.updateURL", "http://127.0.0.1/safebrowsing4-dummy/update");
|
||||
user_pref("browser.safebrowsing.provider.mozilla.gethashURL", "http://127.0.0.1/safebrowsing-dummy/gethash");
|
||||
user_pref("browser.safebrowsing.provider.mozilla.updateURL", "http://127.0.0.1/safebrowsing-dummy/update");
|
||||
user_pref("browser.search.geoip.url", "");
|
||||
user_pref("browser.shell.checkDefaultBrowser", false);
|
||||
user_pref("browser.tabs.remote.autostart", true);
|
||||
user_pref("browser.warnOnQuit", false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/* eslint quotes: 0 */
|
||||
user_pref("app.normandy.api_url", "https://%(server)s/selfsupport-dummy/");
|
||||
user_pref("browser.safebrowsing.downloads.remote.url", "https://%(server)s/safebrowsing-dummy");
|
||||
user_pref("browser.search.geoip.url", "https://%(server)s/geoip-dummy");
|
||||
user_pref("browser.search.geoSpecificDefaults", false);
|
||||
user_pref("extensions.systemAddon.update.url", "http://%(server)s/dummy-system-addons.xml");
|
||||
// Treat WebExtension API/schema warnings as errors.
|
||||
user_pref("extensions.webextensions.warnings-as-errors", true);
|
||||
|
@ -18,8 +18,10 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
DeferredTask: "resource://gre/modules/DeferredTask.jsm",
|
||||
ExtensionParent: "resource://gre/modules/ExtensionParent.jsm",
|
||||
getVerificationHash: "resource://gre/modules/SearchEngine.jsm",
|
||||
OS: "resource://gre/modules/osfile.jsm",
|
||||
IgnoreLists: "resource://gre/modules/IgnoreLists.jsm",
|
||||
NetworkGeolocationProvider:
|
||||
"resource://gre/modules/NetworkGeolocationProvider.jsm",
|
||||
OS: "resource://gre/modules/osfile.jsm",
|
||||
SearchEngine: "resource://gre/modules/SearchEngine.jsm",
|
||||
SearchEngineSelector: "resource://gre/modules/SearchEngineSelector.jsm",
|
||||
SearchStaticData: "resource://gre/modules/SearchStaticData.jsm",
|
||||
@ -127,7 +129,7 @@ var ensureKnownRegion = async function(ss, awaitRegionCheck) {
|
||||
// If we have a region already stored in our prefs we trust it.
|
||||
let region = Services.prefs.getCharPref("browser.search.region", "");
|
||||
try {
|
||||
if (!region) {
|
||||
if (gGeoSpecificDefaultsEnabled && !region) {
|
||||
// We don't have it cached, so fetch it. fetchRegion() will call
|
||||
// storeRegion if it gets a result (even if that happens after the
|
||||
// promise resolves) and fetchRegionDefault.
|
||||
@ -148,7 +150,7 @@ var ensureKnownRegion = async function(ss, awaitRegionCheck) {
|
||||
if (expired || !hasValidHashes) {
|
||||
await new Promise(resolve => {
|
||||
let timeoutMS = Services.prefs.getIntPref(
|
||||
"browser.search.geoip.timeout"
|
||||
"geo.provider.network.timeToWaitBeforeSending"
|
||||
);
|
||||
let timerId = setTimeout(() => {
|
||||
timerId = null;
|
||||
@ -246,134 +248,87 @@ async function storeRegion(region) {
|
||||
}
|
||||
|
||||
// Get the region we are in via a XHR geoip request.
|
||||
function fetchRegion(ss, awaitRegionCheck) {
|
||||
async function fetchRegion(ss, awaitRegionCheck) {
|
||||
// values for the SEARCH_SERVICE_COUNTRY_FETCH_RESULT 'enum' telemetry probe.
|
||||
const TELEMETRY_RESULT_ENUM = {
|
||||
SUCCESS: 0,
|
||||
SUCCESS_WITHOUT_DATA: 1,
|
||||
XHRTIMEOUT: 2,
|
||||
ERROR: 3,
|
||||
success: 0,
|
||||
"xhr-empty": 1,
|
||||
"xhr-timeout": 2,
|
||||
"xhr-error": 3,
|
||||
// Note that we expect to add finer-grained error types here later (eg,
|
||||
// dns error, network error, ssl error, etc) with .ERROR remaining as the
|
||||
// generic catch-all that doesn't fit into other categories.
|
||||
};
|
||||
let endpoint = Services.urlFormatter.formatURLPref(
|
||||
"browser.search.geoip.url"
|
||||
);
|
||||
SearchUtils.log("_fetchRegion starting with endpoint " + endpoint);
|
||||
// As an escape hatch, no endpoint means no geoip.
|
||||
if (!endpoint) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
let startTime = Date.now();
|
||||
return new Promise(resolve => {
|
||||
// Instead of using a timeout on the xhr object itself, we simulate one
|
||||
// using a timer and let the XHR request complete. This allows us to
|
||||
// capture reliable telemetry on what timeout value should actually be
|
||||
// used to ensure most users don't see one while not making it so large
|
||||
// that many users end up doing a sync init of the search service and thus
|
||||
// would see the jank that implies.
|
||||
// (Note we do actually use a timeout on the XHR, but that's set to be a
|
||||
// large value just incase the request never completes - we don't want the
|
||||
// XHR object to live forever)
|
||||
let timeoutMS = Services.prefs.getIntPref("browser.search.geoip.timeout");
|
||||
let geoipTimeoutPossible = true;
|
||||
let timerId = setTimeout(() => {
|
||||
SearchUtils.log("_fetchRegion: timeout fetching region information");
|
||||
if (geoipTimeoutPossible) {
|
||||
Services.telemetry
|
||||
.getHistogramById("SEARCH_SERVICE_COUNTRY_TIMEOUT")
|
||||
.add(1);
|
||||
}
|
||||
timerId = null;
|
||||
resolve();
|
||||
}, timeoutMS);
|
||||
|
||||
let resolveAndReportSuccess = (result, reason) => {
|
||||
// Even if we timed out, we want to save the region and everything
|
||||
// related so next startup sees the value and doesn't retry this dance.
|
||||
if (result) {
|
||||
storeRegion(result).catch(Cu.reportError);
|
||||
}
|
||||
Services.telemetry
|
||||
.getHistogramById("SEARCH_SERVICE_COUNTRY_FETCH_RESULT")
|
||||
.add(reason);
|
||||
let statusCallback = status => {
|
||||
switch (status) {
|
||||
case "xhr-start":
|
||||
// This notification is just for tests...
|
||||
Services.obs.notifyObservers(
|
||||
null,
|
||||
SearchUtils.TOPIC_SEARCH_SERVICE,
|
||||
"geoip-lookup-xhr-starting"
|
||||
);
|
||||
break;
|
||||
case "wifi-timeout":
|
||||
SearchUtils.log("_fetchRegion: timeout fetching wifi information");
|
||||
// Do nothing for now.
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// This notification is just for tests...
|
||||
Services.obs.notifyObservers(
|
||||
null,
|
||||
SearchUtils.TOPIC_SEARCH_SERVICE,
|
||||
"geoip-lookup-xhr-complete"
|
||||
);
|
||||
let networkGeo = new NetworkGeolocationProvider();
|
||||
let result, errorResult;
|
||||
try {
|
||||
result = await networkGeo.getCountry(statusCallback);
|
||||
} catch (ex) {
|
||||
errorResult = ex;
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
|
||||
if (timerId) {
|
||||
Services.telemetry
|
||||
.getHistogramById("SEARCH_SERVICE_COUNTRY_TIMEOUT")
|
||||
.add(0);
|
||||
geoipTimeoutPossible = false;
|
||||
}
|
||||
let took = Date.now() - startTime;
|
||||
// Even if we timed out, we want to save the region and everything
|
||||
// related so next startup sees the value and doesn't retry this dance.
|
||||
if (result) {
|
||||
// As long as the asynchronous codepath in `storeRegion` is only used for
|
||||
// telemetry, we don't need to await its completion.
|
||||
storeRegion(result).catch(Cu.reportError);
|
||||
}
|
||||
SearchUtils.log(
|
||||
"_fetchRegion got success response in " + took + "ms: " + result
|
||||
);
|
||||
Services.telemetry
|
||||
.getHistogramById("SEARCH_SERVICE_COUNTRY_FETCH_TIME_MS")
|
||||
.add(took);
|
||||
|
||||
let callback = () => {
|
||||
// If we've already timed out then we've already resolved the promise,
|
||||
// so there's nothing else to do.
|
||||
if (timerId == null) {
|
||||
return;
|
||||
}
|
||||
clearTimeout(timerId);
|
||||
resolve();
|
||||
};
|
||||
// This notification is just for tests...
|
||||
Services.obs.notifyObservers(
|
||||
null,
|
||||
SearchUtils.TOPIC_SEARCH_SERVICE,
|
||||
"geoip-lookup-xhr-complete"
|
||||
);
|
||||
|
||||
if (result && gGeoSpecificDefaultsEnabled && gModernConfig) {
|
||||
ss._maybeReloadEngines(awaitRegionCheck).then(callback);
|
||||
} else if (result && gGeoSpecificDefaultsEnabled && !gModernConfig) {
|
||||
fetchRegionDefault(ss, awaitRegionCheck)
|
||||
.then(callback)
|
||||
.catch(err => {
|
||||
Cu.reportError(err);
|
||||
callback();
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
// Now that we know the current region, it's possible to fetch defaults,
|
||||
// which we couldn't do before in `ensureKnownRegion`.
|
||||
try {
|
||||
if (result && gModernConfig) {
|
||||
await ss._maybeReloadEngines(awaitRegionCheck);
|
||||
} else if (result && !gModernConfig) {
|
||||
await fetchRegionDefault(ss, awaitRegionCheck);
|
||||
}
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
|
||||
let request = new XMLHttpRequest();
|
||||
// This notification is just for tests...
|
||||
Services.obs.notifyObservers(
|
||||
request,
|
||||
SearchUtils.TOPIC_SEARCH_SERVICE,
|
||||
"geoip-lookup-xhr-starting"
|
||||
);
|
||||
request.timeout = 100000; // 100 seconds as the last-chance fallback
|
||||
request.onload = function(event) {
|
||||
let took = Date.now() - startTime;
|
||||
let region = event.target.response && event.target.response.country_code;
|
||||
SearchUtils.log(
|
||||
"_fetchRegion got success response in " + took + "ms: " + region
|
||||
);
|
||||
Services.telemetry
|
||||
.getHistogramById("SEARCH_SERVICE_COUNTRY_FETCH_TIME_MS")
|
||||
.add(took);
|
||||
let reason = region
|
||||
? TELEMETRY_RESULT_ENUM.SUCCESS
|
||||
: TELEMETRY_RESULT_ENUM.SUCCESS_WITHOUT_DATA;
|
||||
resolveAndReportSuccess(region, reason);
|
||||
};
|
||||
request.ontimeout = function(event) {
|
||||
SearchUtils.log(
|
||||
"_fetchRegion: XHR finally timed-out fetching region information"
|
||||
);
|
||||
resolveAndReportSuccess(null, TELEMETRY_RESULT_ENUM.XHRTIMEOUT);
|
||||
};
|
||||
request.onerror = function(event) {
|
||||
SearchUtils.log("_fetchRegion: failed to retrieve region information");
|
||||
resolveAndReportSuccess(null, TELEMETRY_RESULT_ENUM.ERROR);
|
||||
};
|
||||
request.open("POST", endpoint, true);
|
||||
request.setRequestHeader("Content-Type", "application/json");
|
||||
request.responseType = "json";
|
||||
request.send("{}");
|
||||
});
|
||||
let telemetryResult = TELEMETRY_RESULT_ENUM.success;
|
||||
if (errorResult) {
|
||||
telemetryResult =
|
||||
TELEMETRY_RESULT_ENUM[errorResult] || TELEMETRY_RESULT_ENUM["xhr-error"];
|
||||
}
|
||||
Services.telemetry
|
||||
.getHistogramById("SEARCH_SERVICE_COUNTRY_FETCH_RESULT")
|
||||
.add(telemetryResult);
|
||||
}
|
||||
|
||||
// This converts our legacy google engines to the
|
||||
@ -1498,7 +1453,7 @@ SearchService.prototype = {
|
||||
},
|
||||
|
||||
_reInit(origin, awaitRegionCheck = false) {
|
||||
SearchUtils.log("_reInit");
|
||||
SearchUtils.log("_reInit: " + awaitRegionCheck);
|
||||
// Re-entrance guard, because we're using an async lambda below.
|
||||
if (gReinitializing) {
|
||||
SearchUtils.log("_reInit: already re-initializing, bailing out.");
|
||||
|
@ -43,17 +43,6 @@ var XULRuntime = Cc["@mozilla.org/xre/runtime;1"].getService(Ci.nsIXULRuntime);
|
||||
// Expand the amount of information available in error logs
|
||||
Services.prefs.setBoolPref("browser.search.log", true);
|
||||
|
||||
// The geo-specific search tests assume certain prefs are already setup, which
|
||||
// might not be true when run in comm-central etc. So create them here.
|
||||
Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", true);
|
||||
Services.prefs.setIntPref("browser.search.geoip.timeout", 3000);
|
||||
// But still disable geoip lookups - tests that need it will re-configure this.
|
||||
Services.prefs.setCharPref("browser.search.geoip.url", "");
|
||||
// Also disable region defaults - tests using it will also re-configure it.
|
||||
Services.prefs
|
||||
.getDefaultBranch(SearchUtils.BROWSER_SEARCH_PREF)
|
||||
.setCharPref("geoSpecificDefaults.url", "");
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"gModernConfig",
|
||||
@ -449,7 +438,7 @@ async function withGeoServer(
|
||||
let geoLookupUrl = geoLookupData
|
||||
? `http://localhost:${srv.identity.primaryPort}/lookup_geoip`
|
||||
: 'data:application/json,{"country_code": "FR"}';
|
||||
Services.prefs.setCharPref("browser.search.geoip.url", geoLookupUrl);
|
||||
Services.prefs.setCharPref("geo.provider-country.network.url", geoLookupUrl);
|
||||
|
||||
try {
|
||||
await testFn(gRequests);
|
||||
@ -459,7 +448,7 @@ async function withGeoServer(
|
||||
Services.prefs.clearUserPref(
|
||||
SearchUtils.BROWSER_SEARCH_PREF + PREF_SEARCH_URL
|
||||
);
|
||||
Services.prefs.clearUserPref("browser.search.geoip.url");
|
||||
Services.prefs.clearUserPref("geo.provider-country.network.url");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,6 @@ class SearchConfigTest {
|
||||
|
||||
// Disable region checks.
|
||||
Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", false);
|
||||
Services.prefs.setCharPref("browser.search.geoip.url", "");
|
||||
|
||||
// Enable separatePrivateDefault testing. We test with this on, as we have
|
||||
// separate tests for ensuring the normal = private when this is off.
|
||||
|
@ -44,8 +44,6 @@ add_task(async function should_get_geo_defaults_only_once() {
|
||||
// (Re)initializing the search service should trigger a request,
|
||||
// and set the default engine based on it.
|
||||
// Due to the previous initialization, we expect the region to already be set.
|
||||
Assert.ok(Services.prefs.prefHasUserValue("browser.search.region"));
|
||||
Assert.equal(Services.prefs.getCharPref("browser.search.region"), "FR");
|
||||
await Promise.all([
|
||||
asyncReInit({ awaitRegionFetch: true }),
|
||||
promiseAfterCache(),
|
||||
|
@ -5,10 +5,9 @@ const kUrlPref = "geoSpecificDefaults.url";
|
||||
|
||||
add_task(async function setup() {
|
||||
await useTestEngines("simple-engines");
|
||||
|
||||
// Geo specific defaults won't be fetched if there's no country code.
|
||||
Services.prefs.setCharPref(
|
||||
"browser.search.geoip.url",
|
||||
"geo.provider-country.network.url",
|
||||
'data:application/json,{"country_code": "US"}'
|
||||
);
|
||||
|
||||
@ -22,6 +21,7 @@ add_task(async function setup() {
|
||||
visibleDefaultEngines: ["hidden"],
|
||||
},
|
||||
});
|
||||
Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", true);
|
||||
Services.prefs
|
||||
.getDefaultBranch(SearchUtils.BROWSER_SEARCH_PREF)
|
||||
.setCharPref(kUrlPref, url);
|
||||
|
@ -7,6 +7,7 @@ const SEARCH_SERVICE_TOPIC = "browser-search-service";
|
||||
const SEARCH_ENGINE_TOPIC = "browser-search-engine-modified";
|
||||
|
||||
add_task(async function setup() {
|
||||
Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", true);
|
||||
await AddonTestUtils.promiseStartupManager();
|
||||
});
|
||||
|
||||
|
@ -3,11 +3,15 @@
|
||||
|
||||
add_task(async function setup() {
|
||||
await AddonTestUtils.promiseStartupManager();
|
||||
Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", true);
|
||||
Services.prefs
|
||||
.getDefaultBranch(SearchUtils.BROWSER_SEARCH_PREF)
|
||||
.setCharPref("geoSpecificDefaults.url", "");
|
||||
});
|
||||
|
||||
add_task(async function test_location() {
|
||||
Services.prefs.setCharPref(
|
||||
"browser.search.geoip.url",
|
||||
"geo.provider-country.network.url",
|
||||
'data:application/json,{"country_code": "AU"}'
|
||||
);
|
||||
await Services.search.init(true);
|
||||
@ -18,12 +22,6 @@ add_task(async function test_location() {
|
||||
);
|
||||
// check we have "success" recorded in telemetry
|
||||
checkCountryResultTelemetry(TELEMETRY_RESULT_ENUM.SUCCESS);
|
||||
// a false value for SEARCH_SERVICE_COUNTRY_TIMEOUT
|
||||
let histogram = Services.telemetry.getHistogramById(
|
||||
"SEARCH_SERVICE_COUNTRY_TIMEOUT"
|
||||
);
|
||||
let snapshot = histogram.snapshot();
|
||||
deepEqual(snapshot.values, { 0: 1, 1: 0 }); // boolean probe so 3 buckets, expect 1 result for |0|.
|
||||
|
||||
// simple checks for our platform-specific telemetry. We can't influence
|
||||
// what they return (as we can't influence the countryCode the platform
|
||||
@ -62,8 +60,8 @@ add_task(async function test_location() {
|
||||
countryCode == "AU" ? { 0: 1, 1: 0 } : { 0: 0, 1: 1, 2: 0 };
|
||||
}
|
||||
|
||||
histogram = Services.telemetry.getHistogramById(hid);
|
||||
snapshot = histogram.snapshot();
|
||||
let histogram = Services.telemetry.getHistogramById(hid);
|
||||
let snapshot = histogram.snapshot();
|
||||
deepEqual(snapshot.values, expectedResult);
|
||||
}
|
||||
});
|
||||
|
@ -3,13 +3,14 @@
|
||||
|
||||
add_task(async function setup() {
|
||||
await AddonTestUtils.promiseStartupManager();
|
||||
Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", true);
|
||||
});
|
||||
|
||||
add_task(async function test_location_error() {
|
||||
// We use an invalid port that parses but won't open
|
||||
let url = "http://localhost:0";
|
||||
|
||||
Services.prefs.setCharPref("browser.search.geoip.url", url);
|
||||
Services.prefs.setCharPref("geo.provider-country.network.url", url);
|
||||
await Services.search.init();
|
||||
try {
|
||||
Services.prefs.getCharPref("browser.search.region");
|
||||
@ -17,10 +18,4 @@ add_task(async function test_location_error() {
|
||||
} catch (ex) {}
|
||||
// should have an error recorded.
|
||||
checkCountryResultTelemetry(TELEMETRY_RESULT_ENUM.ERROR);
|
||||
// but false values for timeout
|
||||
let histogram = Services.telemetry.getHistogramById(
|
||||
"SEARCH_SERVICE_COUNTRY_TIMEOUT"
|
||||
);
|
||||
let snapshot = histogram.snapshot();
|
||||
deepEqual(snapshot.values, { 0: 1, 1: 0 }); // boolean probe so 3 buckets, expect 1 result for |0|.
|
||||
});
|
||||
|
@ -23,12 +23,13 @@ function promiseTimezoneMessage() {
|
||||
|
||||
add_task(async function setup() {
|
||||
await AddonTestUtils.promiseStartupManager();
|
||||
Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", true);
|
||||
});
|
||||
|
||||
add_task(async function test_location_malformed_json() {
|
||||
// Here we have malformed JSON
|
||||
Services.prefs.setCharPref(
|
||||
"browser.search.geoip.url",
|
||||
"geo.provider-country.network.url",
|
||||
'data:application/json,{"country_code"'
|
||||
);
|
||||
await Services.search.init();
|
||||
@ -44,10 +45,4 @@ add_task(async function test_location_malformed_json() {
|
||||
);
|
||||
// should have recorded SUCCESS_WITHOUT_DATA
|
||||
checkCountryResultTelemetry(TELEMETRY_RESULT_ENUM.SUCCESS_WITHOUT_DATA);
|
||||
// and false values for timeout.
|
||||
let histogram = Services.telemetry.getHistogramById(
|
||||
"SEARCH_SERVICE_COUNTRY_TIMEOUT"
|
||||
);
|
||||
let snapshot = histogram.snapshot();
|
||||
deepEqual(snapshot.values, { 0: 1, 1: 0 }); // boolean probe so 3 buckets, expect 1 result for |0|.
|
||||
});
|
||||
|
@ -29,6 +29,7 @@ function getProbeSum(probe, sum) {
|
||||
|
||||
add_task(async function setup() {
|
||||
await AddonTestUtils.promiseStartupManager();
|
||||
Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", true);
|
||||
});
|
||||
|
||||
add_task(async function test_location_timeout() {
|
||||
@ -40,8 +41,8 @@ add_task(async function test_location_timeout() {
|
||||
let server = startServer(continuePromise);
|
||||
let url =
|
||||
"http://localhost:" + server.identity.primaryPort + "/lookup_country";
|
||||
Services.prefs.setCharPref("browser.search.geoip.url", url);
|
||||
Services.prefs.setIntPref("browser.search.geoip.timeout", 50);
|
||||
Services.prefs.setCharPref("geo.provider-country.network.url", url);
|
||||
Services.prefs.setIntPref("geo.provider.network.timeout", 3000);
|
||||
await Services.search.init();
|
||||
ok(
|
||||
!Services.prefs.prefHasUserValue("browser.search.region"),
|
||||
@ -50,12 +51,6 @@ add_task(async function test_location_timeout() {
|
||||
// should be no result recorded at all.
|
||||
checkCountryResultTelemetry(null);
|
||||
|
||||
// should have set the flag indicating we saw a timeout.
|
||||
let histogram = Services.telemetry.getHistogramById(
|
||||
"SEARCH_SERVICE_COUNTRY_TIMEOUT"
|
||||
);
|
||||
let snapshot = histogram.snapshot();
|
||||
deepEqual(snapshot.values, { 0: 0, 1: 1, 2: 0 });
|
||||
// should not yet have SEARCH_SERVICE_COUNTRY_FETCH_TIME_MS recorded as our
|
||||
// test server is still blocked on our promise.
|
||||
equal(getProbeSum("SEARCH_SERVICE_COUNTRY_FETCH_TIME_MS"), 0);
|
||||
@ -72,8 +67,8 @@ add_task(async function test_location_timeout() {
|
||||
// it timed out.
|
||||
// The telemetry "sum" will be the actual time in ms - just check it's non-zero.
|
||||
ok(getProbeSum("SEARCH_SERVICE_COUNTRY_FETCH_TIME_MS") != 0);
|
||||
// should have reported the fetch ended up being successful
|
||||
checkCountryResultTelemetry(TELEMETRY_RESULT_ENUM.SUCCESS);
|
||||
// should have reported the fetch ended up being successful.
|
||||
checkCountryResultTelemetry(TELEMETRY_RESULT_ENUM.success);
|
||||
|
||||
// and should have the result of the response that finally came in, and
|
||||
// everything dependent should also be updated.
|
||||
@ -81,9 +76,7 @@ add_task(async function test_location_timeout() {
|
||||
|
||||
await SearchTestUtils.promiseSearchNotification("engines-reloaded");
|
||||
|
||||
await (() => {
|
||||
return new Promise(resolve => {
|
||||
server.stop(resolve);
|
||||
});
|
||||
})();
|
||||
await new Promise(resolve => {
|
||||
server.stop(resolve);
|
||||
});
|
||||
});
|
||||
|
@ -56,13 +56,6 @@ add_task(async function test_location_timeout_xhr() {
|
||||
// should be no result recorded at all.
|
||||
checkCountryResultTelemetry(null);
|
||||
|
||||
// should have set the flag indicating we saw a timeout.
|
||||
let histogram = Services.telemetry.getHistogramById(
|
||||
"SEARCH_SERVICE_COUNTRY_TIMEOUT"
|
||||
);
|
||||
let snapshot = histogram.snapshot();
|
||||
deepEqual(snapshot.values, { 0: 0, 1: 1, 2: 0 });
|
||||
|
||||
// should not have SEARCH_SERVICE_COUNTRY_FETCH_TIME_MS recorded as our
|
||||
// test server is still blocked on our promise.
|
||||
verifyProbeSum("SEARCH_SERVICE_COUNTRY_FETCH_TIME_MS", 0);
|
||||
|
@ -8,6 +8,7 @@ const SEARCH_SERVICE_TOPIC = "browser-search-service";
|
||||
add_task(async function setup() {
|
||||
await AddonTestUtils.promiseStartupManager();
|
||||
await useTestEngines("data", "geolookup-extensions");
|
||||
Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", true);
|
||||
});
|
||||
|
||||
add_task(async function test_maybereloadengine_update() {
|
||||
|
@ -17,6 +17,7 @@ add_task(async function setup() {
|
||||
|
||||
installDistributionEngine();
|
||||
|
||||
Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", true);
|
||||
await AddonTestUtils.promiseStartupManager();
|
||||
});
|
||||
|
||||
|
@ -58,6 +58,7 @@ function listenFor(name, key) {
|
||||
|
||||
add_task(async function setup() {
|
||||
Services.prefs.setBoolPref("browser.search.separatePrivateDefault", true);
|
||||
Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", true);
|
||||
|
||||
await useTestEngines("data", null, CONFIG);
|
||||
await AddonTestUtils.promiseStartupManager();
|
||||
@ -66,7 +67,7 @@ add_task(async function setup() {
|
||||
add_task(async function test_regular_init() {
|
||||
let reloadObserved = listenFor(SEARCH_SERVICE_TOPIC, "engines-reloaded");
|
||||
let geoUrl = `data:application/json,{"country_code": "FR"}`;
|
||||
Services.prefs.setCharPref("browser.search.geoip.url", geoUrl);
|
||||
Services.prefs.setCharPref("geo.provider-country.network.url", geoUrl);
|
||||
|
||||
await Promise.all([
|
||||
Services.search.init(true),
|
||||
@ -103,7 +104,7 @@ add_task(async function test_init_with_slow_region_lookup() {
|
||||
});
|
||||
|
||||
Services.prefs.setCharPref(
|
||||
"browser.search.geoip.url",
|
||||
"geo.provider-country.network.url",
|
||||
`http://localhost:${srv.identity.primaryPort}/fetch_region`
|
||||
);
|
||||
|
||||
|
@ -8968,14 +8968,6 @@
|
||||
"n_values": 8,
|
||||
"description": "Result of XHR request fetching the country-code. 0=SUCCESS, 1=SUCCESS_WITHOUT_DATA, 2=XHRTIMEOUT, 3=ERROR (rest reserved for finer-grained error codes later)"
|
||||
},
|
||||
"SEARCH_SERVICE_COUNTRY_TIMEOUT": {
|
||||
"record_in_processes": ["main", "content"],
|
||||
"products": ["firefox", "fennec", "geckoview", "thunderbird"],
|
||||
"alert_emails": ["mdeboer@mozilla.com", "fx-search@mozilla.com"],
|
||||
"expires_in_version": "never",
|
||||
"kind": "boolean",
|
||||
"description": "True if we stopped waiting for the XHR response before it completed"
|
||||
},
|
||||
"SEARCH_SERVICE_US_COUNTRY_MISMATCHED_TIMEZONE": {
|
||||
"record_in_processes": ["main", "content"],
|
||||
"products": ["firefox", "fennec", "geckoview"],
|
||||
|
@ -815,7 +815,6 @@
|
||||
"SAFE_MODE_USAGE",
|
||||
"SEARCH_SERVICE_COUNTRY_FETCH_RESULT",
|
||||
"SEARCH_SERVICE_COUNTRY_FETCH_TIME_MS",
|
||||
"SEARCH_SERVICE_COUNTRY_TIMEOUT",
|
||||
"SEARCH_SERVICE_NONUS_COUNTRY_MISMATCHED_PLATFORM_OSX",
|
||||
"SEARCH_SERVICE_NONUS_COUNTRY_MISMATCHED_PLATFORM_WIN",
|
||||
"SEARCH_SERVICE_US_COUNTRY_MISMATCHED_PLATFORM_OSX",
|
||||
|
Loading…
Reference in New Issue
Block a user