Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit 2478891

Browse files
committed
Bug 1502921 - Record telemetry environment data about locales r=chutten
Differential Revision: https://phabricator.services.mozilla.com/D15990 --HG-- extra : moz-landing-system : lando
1 parent 467ab77 commit 2478891

15 files changed

Lines changed: 140 additions & 2 deletions

toolkit/components/telemetry/app/TelemetryEnvironment.jsm

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,21 @@ const MAX_EXPERIMENT_TYPE_LENGTH = 20;
4848
// eslint-disable-next-line no-unused-vars
4949
var Policy = {
5050
now: () => new Date(),
51+
_intlLoaded: false,
52+
_browserDelayedStartup() {
53+
if (Policy._intlLoaded) {
54+
return Promise.resolve();
55+
}
56+
return new Promise(resolve => {
57+
let startupTopic = "browser-delayed-startup-finished";
58+
Services.obs.addObserver(function observer(subject, topic) {
59+
if (topic == startupTopic) {
60+
Services.obs.removeObserver(observer, startupTopic);
61+
resolve();
62+
}
63+
}, startupTopic);
64+
});
65+
},
5166
};
5267

5368
// This is used to buffer calls to setExperimentActive and friends, so that we
@@ -320,6 +335,49 @@ function getSystemLocale() {
320335
}
321336
}
322337

338+
/**
339+
* Get the current OS locales.
340+
* @return an array of strings with the OS locales or null on failure.
341+
*/
342+
function getSystemLocales() {
343+
try {
344+
return Cc["@mozilla.org/intl/ospreferences;1"].
345+
getService(Ci.mozIOSPreferences).
346+
systemLocales;
347+
} catch (e) {
348+
return null;
349+
}
350+
}
351+
352+
/**
353+
* Get the current OS regional preference locales.
354+
* @return an array of strings with the OS regional preference locales or null on failure.
355+
*/
356+
function getRegionalPrefsLocales() {
357+
try {
358+
return Cc["@mozilla.org/intl/ospreferences;1"].
359+
getService(Ci.mozIOSPreferences).
360+
regionalPrefsLocales;
361+
} catch (e) {
362+
return null;
363+
}
364+
}
365+
366+
function getIntlSettings() {
367+
return {
368+
requestedLocales: Services.locale.requestedLocales,
369+
availableLocales: Services.locale.availableLocales,
370+
appLocales: Services.locale.appLocalesAsBCP47,
371+
systemLocales: getSystemLocales(),
372+
regionalPrefsLocales: getRegionalPrefsLocales(),
373+
acceptLanguages:
374+
Services.prefs.getComplexValue("intl.accept_languages", Ci.nsIPrefLocalizedString)
375+
.data
376+
.split(",")
377+
.map(str => str.trim()),
378+
};
379+
}
380+
323381
/**
324382
* Safely get a sysinfo property and return its value. If the property is not
325383
* available, return aDefault.
@@ -904,6 +962,7 @@ function EnvironmentCache() {
904962
p.push(this._loadAttributionAsync());
905963
}
906964
p.push(this._loadAutoUpdateAsync());
965+
p.push(this._loadIntlData());
907966

908967
for (const [id, {branch, options}] of gActiveExperimentStartupBuffer.entries()) {
909968
this.setExperimentActive(id, branch, options);
@@ -1416,6 +1475,9 @@ EnvironmentCache.prototype = {
14161475
e10sMultiProcesses: Services.appinfo.maxWebProcessCount,
14171476
telemetryEnabled: Utils.isTelemetryEnabled,
14181477
locale: getBrowserLocale(),
1478+
// We need to wait for browser-delayed-startup-finished to ensure that the locales
1479+
// have settled, once that's happened we can get the intl data directly.
1480+
intl: Policy._intlLoaded ? getIntlSettings() : {},
14191481
update: {
14201482
channel: updateChannel,
14211483
enabled: !Services.policies || Services.policies.isAllowed("appUpdate"),
@@ -1537,6 +1599,17 @@ EnvironmentCache.prototype = {
15371599
this._currentEnvironment.settings.update.autoDownload = this._updateAutoDownloadCache;
15381600
},
15391601

1602+
/**
1603+
* Get i18n data about the system.
1604+
* @return A promise of completion.
1605+
*/
1606+
async _loadIntlData() {
1607+
// Wait for the startup topic.
1608+
await Policy._browserDelayedStartup();
1609+
this._currentEnvironment.settings.intl = getIntlSettings();
1610+
Policy._intlLoaded = true;
1611+
},
1612+
15401613
/**
15411614
* Get the partner data in object form.
15421615
* @return Object containing the partner data.

toolkit/components/telemetry/docs/data/environment.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ Structure:
4949
e10sEnabled: <bool>, // whether e10s is on, i.e. browser tabs open by default in a different process
5050
telemetryEnabled: <bool>, // false on failure
5151
locale: <string>, // e.g. "it", null on failure
52+
intl: {
53+
requestedLocales: [ <string>, ... ], // The locales that are being requested.
54+
availableLocales: [ <string>, ... ], // The locales that are available for use.
55+
appLocales: [ <string>, ... ], // The negotiated locales that are being used.
56+
systemLocales: [ <string>, ... ], // The locales for the OS.
57+
regionalPrefsLocales: [ <string>, ... ], // The regional preferences for the OS.
58+
acceptLanguages: [ <string>, ... ], // The languages for the Accept-Languages header.
59+
},
5260
update: {
5361
channel: <string>, // e.g. "release", null on failure
5462
enabled: <bool>, // true on failure
@@ -461,3 +469,4 @@ Version History
461469
- Firefox 61:
462470

463471
- Removed empty ``addons.activeExperiment`` (`bug 1452935 <https://bugzilla.mozilla.org/show_bug.cgi?id=1452935>`_).
472+

toolkit/components/telemetry/tests/unit/head.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,13 @@ function fakePrioEncode() {
294294
m.Policy.prioEncode = (batchID, prioParams) => prioParams;
295295
}
296296

297+
function fakeIntlReady() {
298+
const m = ChromeUtils.import("resource://gre/modules/TelemetryEnvironment.jsm", {});
299+
m.Policy._intlLoaded = true;
300+
// Dispatch the observer event in case the promise has been registered already.
301+
Services.obs.notifyObservers(null, "browser-delayed-startup-finished");
302+
}
303+
297304
// Return a date that is |offset| ms in the future from |date|.
298305
function futureDate(date, offset) {
299306
return new Date(date.getTime() + offset);

toolkit/components/telemetry/tests/unit/test_ChildEvents.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ add_task(async function() {
7575
do_get_profile(true);
7676
loadAddonManager(APP_ID, APP_NAME, APP_VERSION, PLATFORM_VERSION);
7777
finishAddonManagerStartup();
78+
fakeIntlReady();
7879
await TelemetryController.testSetup();
7980
// Make sure we don't generate unexpected pings due to pref changes.
8081
await setEmptyPrefWatchlist();

toolkit/components/telemetry/tests/unit/test_ChildHistograms.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ add_task(async function() {
9090
do_get_profile(true);
9191
loadAddonManager(APP_ID, APP_NAME, APP_VERSION, PLATFORM_VERSION);
9292
finishAddonManagerStartup();
93+
fakeIntlReady();
9394
await TelemetryController.testSetup();
9495
if (runningInParent) {
9596
// Make sure we don't generate unexpected pings due to pref changes.

toolkit/components/telemetry/tests/unit/test_ChildScalars.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ add_task(async function() {
140140
do_get_profile(true);
141141
loadAddonManager(APP_ID, APP_NAME, APP_VERSION, PLATFORM_VERSION);
142142
finishAddonManagerStartup();
143+
fakeIntlReady();
143144
await TelemetryController.testSetup();
144145
if (runningInParent) {
145146
setParentScalars();

toolkit/components/telemetry/tests/unit/test_SubsessionChaining.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ add_task(async function test_setup() {
8888
do_get_profile();
8989
loadAddonManager("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
9090
finishAddonManagerStartup();
91+
fakeIntlReady();
9192
// Make sure we don't generate unexpected pings due to pref changes.
9293
await setEmptyPrefWatchlist();
9394
});

toolkit/components/telemetry/tests/unit/test_TelemetryChildEvents_buildFaster.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ add_task(async function test_setup() {
4545
do_get_profile(true);
4646
loadAddonManager(APP_ID, APP_NAME, APP_VERSION, PLATFORM_VERSION);
4747
finishAddonManagerStartup();
48+
fakeIntlReady();
4849
await TelemetryController.testSetup();
4950
// Make sure we don't generate unexpected pings due to pref changes.
5051
await setEmptyPrefWatchlist();

toolkit/components/telemetry/tests/unit/test_TelemetryController.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ add_task(async function test_setup() {
9494
do_get_profile();
9595
loadAddonManager("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
9696
finishAddonManagerStartup();
97+
fakeIntlReady();
9798
// Make sure we don't generate unexpected pings due to pref changes.
9899
await setEmptyPrefWatchlist();
99100

toolkit/components/telemetry/tests/unit/test_TelemetryControllerShutdown.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ add_task(async function test_setup() {
2727
do_get_profile();
2828
loadAddonManager("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
2929
finishAddonManagerStartup();
30+
fakeIntlReady();
3031
// Make sure we don't generate unexpected pings due to pref changes.
3132
await setEmptyPrefWatchlist();
3233

0 commit comments

Comments
 (0)