mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 1122048 - Add generic preferences collection and change detection to Telemetry Environment. r=gfritzsche
This commit is contained in:
parent
29b3d025c3
commit
0abf384b90
@ -230,6 +230,11 @@ user_pref('browser.tiles.reportURL', 'http://%(server)s/tests/robocop/robocop_ti
|
||||
// We want to collect telemetry, but we don't want to send in the results.
|
||||
user_pref('toolkit.telemetry.server', 'https://%(server)s/telemetry-dummy/');
|
||||
|
||||
// A couple of preferences with default values to test that telemetry preference
|
||||
// watching is working.
|
||||
user_pref('toolkit.telemetry.test.pref1', true);
|
||||
user_pref('toolkit.telemetry.test.pref2', false);
|
||||
|
||||
// We don't want to hit the real Firefox Accounts server for tests. We don't
|
||||
// actually need a functioning FxA server, so just set it to something that
|
||||
// resolves and accepts requests, even if they all fail.
|
||||
|
@ -13,6 +13,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/Log.jsm");
|
||||
Cu.import("resource://gre/modules/Preferences.jsm");
|
||||
|
||||
const LOGGER_NAME = "Toolkit.Telemetry";
|
||||
|
||||
@ -25,6 +26,14 @@ this.TelemetryEnvironment = {
|
||||
_collectTask: null,
|
||||
_doNotify: false,
|
||||
|
||||
// Policy to use when saving preferences. Exported for using them in tests.
|
||||
RECORD_PREF_STATE: 1, // Don't record the preference value
|
||||
RECORD_PREF_VALUE: 2, // We only record user-set prefs.
|
||||
|
||||
// A map of watched preferences which trigger an Environment change when modified.
|
||||
// Every entry contains a recording policy (RECORD_PREF_STATE or RECORD_PREF_VALUE).
|
||||
_watchedPrefs: null,
|
||||
|
||||
/**
|
||||
* Initialize TelemetryEnvironment.
|
||||
*/
|
||||
@ -37,6 +46,7 @@ this.TelemetryEnvironment = {
|
||||
this._log = Log.repository.getLoggerWithMessagePrefix(LOGGER_NAME, "TelemetryEnvironment::");
|
||||
this._log.trace("init");
|
||||
this._shutdown = false;
|
||||
this._startWatchingPrefs();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -51,6 +61,7 @@ this.TelemetryEnvironment = {
|
||||
|
||||
this._log.trace("shutdown");
|
||||
this._shutdown = true;
|
||||
this._stopWatchingPrefs();
|
||||
this._changeListeners.clear();
|
||||
yield this._collectTask;
|
||||
}),
|
||||
@ -82,6 +93,97 @@ this.TelemetryEnvironment = {
|
||||
this._changeListeners.delete(name);
|
||||
},
|
||||
|
||||
/**
|
||||
* Only used in tests, set the preferences to watch.
|
||||
* @param aPreferences A map of preferences names and their recording policy.
|
||||
*/
|
||||
_watchPreferences: function (aPreferences) {
|
||||
if (this._watchedPrefs) {
|
||||
this._stopWatchingPrefs();
|
||||
}
|
||||
|
||||
this._watchedPrefs = aPreferences;
|
||||
this._startWatchingPrefs();
|
||||
},
|
||||
|
||||
/**
|
||||
* Get an object containing the values for the watched preferences. Depending on the
|
||||
* policy, the value for a preference or whether it was changed by user is reported.
|
||||
*
|
||||
* @return An object containing the preferences values.
|
||||
*/
|
||||
_getPrefData: function () {
|
||||
if (!this._watchedPrefs) {
|
||||
return {};
|
||||
}
|
||||
|
||||
let prefData = {};
|
||||
for (let pref in this._watchedPrefs) {
|
||||
// We only want to record preferences if they are non-default.
|
||||
if (!Preferences.isSet(pref)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check the policy for the preference and decide if we need to store its value
|
||||
// or whether it changed from the default value.
|
||||
let prefValue = undefined;
|
||||
if (this._watchedPrefs[pref] == this.RECORD_PREF_STATE) {
|
||||
prefValue = null;
|
||||
} else {
|
||||
prefValue = Preferences.get(pref, null);
|
||||
}
|
||||
prefData[pref] = prefValue;
|
||||
}
|
||||
return prefData;
|
||||
},
|
||||
|
||||
/**
|
||||
* Start watching the preferences.
|
||||
*/
|
||||
_startWatchingPrefs: function () {
|
||||
this._log.trace("_startWatchingPrefs - " + this._watchedPrefs);
|
||||
|
||||
if (!this._watchedPrefs) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let pref in this._watchedPrefs) {
|
||||
Preferences.observe(pref, this._onPrefChanged, this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Do not receive any more change notifications for the preferences.
|
||||
*/
|
||||
_stopWatchingPrefs: function () {
|
||||
this._log.trace("_stopWatchingPrefs");
|
||||
|
||||
if (!this._watchedPrefs) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let pref in this._watchedPrefs) {
|
||||
Preferences.ignore(pref, this._onPrefChanged, this);
|
||||
}
|
||||
|
||||
this._watchedPrefs = null;
|
||||
},
|
||||
|
||||
_onPrefChanged: function () {
|
||||
this._log.trace("_onPrefChanged");
|
||||
this._onEnvironmentChange("pref-changed");
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the settings data in object form.
|
||||
* @return Object containing the settings.
|
||||
*/
|
||||
_getSettings: function () {
|
||||
return {
|
||||
"userPrefs": this._getPrefData(),
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the environment data in object form.
|
||||
* @return Promise<Object> Resolved with the data on success, otherwise rejected.
|
||||
@ -105,7 +207,25 @@ this.TelemetryEnvironment = {
|
||||
|
||||
_doGetEnvironmentData: Task.async(function* () {
|
||||
this._log.trace("getEnvironmentData");
|
||||
return {};
|
||||
|
||||
// Define the data collection function for each section.
|
||||
let sections = {
|
||||
"settings": () => this._getSettings(),
|
||||
};
|
||||
|
||||
let data = {};
|
||||
// Recover from exceptions in the collection functions and populate the data
|
||||
// object. We want to recover so that, in the worst-case, we only lose some data
|
||||
// sections instead of all.
|
||||
for (let s in sections) {
|
||||
try {
|
||||
data[s] = sections[s]();
|
||||
} catch (e) {
|
||||
this._log.error("getEnvironmentData - There was an exception collecting " + s, e);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}),
|
||||
|
||||
_onEnvironmentChange: function (what) {
|
||||
|
@ -4,6 +4,8 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/TelemetryEnvironment.jsm", this);
|
||||
Cu.import("resource://gre/modules/Preferences.jsm", this);
|
||||
Cu.import("resource://gre/modules/PromiseUtils.jsm", this);
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
@ -65,6 +67,72 @@ add_task(function* test_changeNotify() {
|
||||
}
|
||||
});
|
||||
|
||||
add_task(function* test_prefWatchPolicies() {
|
||||
const PREF_TEST_1 = "toolkit.telemetry.test.pref_new";
|
||||
const PREF_TEST_2 = "toolkit.telemetry.test.pref1";
|
||||
const PREF_TEST_3 = "toolkit.telemetry.test.pref2";
|
||||
|
||||
const expectedValue = "some-test-value";
|
||||
|
||||
let prefsToWatch = {};
|
||||
prefsToWatch[PREF_TEST_1] = TelemetryEnvironment.RECORD_PREF_VALUE;
|
||||
prefsToWatch[PREF_TEST_2] = TelemetryEnvironment.RECORD_PREF_STATE;
|
||||
prefsToWatch[PREF_TEST_3] = TelemetryEnvironment.RECORD_PREF_STATE;
|
||||
|
||||
yield TelemetryEnvironment.init();
|
||||
|
||||
// Set the Environment preferences to watch.
|
||||
TelemetryEnvironment._watchPreferences(prefsToWatch);
|
||||
let deferred = PromiseUtils.defer();
|
||||
TelemetryEnvironment.registerChangeListener("testWatchPrefs", deferred.resolve);
|
||||
|
||||
// Trigger a change in the watched preferences.
|
||||
Preferences.set(PREF_TEST_1, expectedValue);
|
||||
Preferences.set(PREF_TEST_2, false);
|
||||
yield deferred.promise;
|
||||
|
||||
// Unregister the listener.
|
||||
TelemetryEnvironment.unregisterChangeListener("testWatchPrefs");
|
||||
|
||||
// Check environment contains the correct data.
|
||||
let environmentData = yield TelemetryEnvironment.getEnvironmentData();
|
||||
|
||||
let userPrefs = environmentData.settings.userPrefs;
|
||||
|
||||
Assert.equal(userPrefs[PREF_TEST_1], expectedValue,
|
||||
"Environment contains the correct preference value.");
|
||||
Assert.equal(userPrefs[PREF_TEST_2], null,
|
||||
"Report that the pref was user set and has no value.");
|
||||
Assert.ok(!(PREF_TEST_3 in userPrefs),
|
||||
"Do not report if preference not user set.");
|
||||
|
||||
yield TelemetryEnvironment.shutdown();
|
||||
});
|
||||
|
||||
add_task(function* test_prefWatch_prefReset() {
|
||||
const PREF_TEST = "toolkit.telemetry.test.pref1";
|
||||
|
||||
let prefsToWatch = {};
|
||||
prefsToWatch[PREF_TEST] = TelemetryEnvironment.RECORD_PREF_STATE;
|
||||
// Set the preference to a non-default value.
|
||||
Preferences.set(PREF_TEST, false);
|
||||
|
||||
yield TelemetryEnvironment.init();
|
||||
|
||||
// Set the Environment preferences to watch.
|
||||
TelemetryEnvironment._watchPreferences(prefsToWatch);
|
||||
let deferred = PromiseUtils.defer();
|
||||
TelemetryEnvironment.registerChangeListener("testWatchPrefs_reset", deferred.resolve);
|
||||
|
||||
// Trigger a change in the watched preferences.
|
||||
Preferences.reset(PREF_TEST);
|
||||
yield deferred.promise;
|
||||
|
||||
// Unregister the listener.
|
||||
TelemetryEnvironment.unregisterChangeListener("testWatchPrefs_reset");
|
||||
yield TelemetryEnvironment.shutdown();
|
||||
});
|
||||
|
||||
add_task(function*() {
|
||||
do_test_finished();
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user