mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 989137 - Part 12: Refactor experiment and add-on state management. r=gfritzsche
This commit is contained in:
parent
500abbb9fa
commit
6f0f2c7b08
@ -42,11 +42,9 @@ XPCOMUtils.defineLazyGetter(this, "CertUtils",
|
||||
return mod;
|
||||
});
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gCrashReporter",
|
||||
"@mozilla.org/xre/app-info;1",
|
||||
"nsICrashReporter");
|
||||
#endif
|
||||
|
||||
const FILE_CACHE = "experiments.json";
|
||||
const OBSERVER_TOPIC = "experiments-changed";
|
||||
@ -76,20 +74,29 @@ const TELEMETRY_LOG = {
|
||||
// log(key, [kind, experimentId, details])
|
||||
ACTIVATION_KEY: "EXPERIMENT_ACTIVATION",
|
||||
ACTIVATION: {
|
||||
ACTIVATED: "ACTIVATED", // successfully activated
|
||||
INSTALL_FAILURE: "INSTALL_FAILURE", // failed to install the extension
|
||||
REJECTED: "REJECTED", // experiment was rejected because of it's conditions,
|
||||
// provides details on which
|
||||
// Successfully activated.
|
||||
ACTIVATED: "ACTIVATED",
|
||||
// Failed to install the add-on.
|
||||
INSTALL_FAILURE: "INSTALL_FAILURE",
|
||||
// Experiment does not meet activation requirements. Details will
|
||||
// be provided.
|
||||
REJECTED: "REJECTED",
|
||||
},
|
||||
|
||||
// log(key, [kind, experimentId, optionalDetails...])
|
||||
TERMINATION_KEY: "EXPERIMENT_TERMINATION",
|
||||
TERMINATION: {
|
||||
USERDISABLED: "USERDISABLED", // the user disabled this experiment
|
||||
FROM_API: "FROM_API", // the experiment disabled itself
|
||||
EXPIRED: "EXPIRED", // experiment expired e.g. by exceeding the end-date
|
||||
RECHECK: "RECHECK", // disabled after re-evaluating conditions,
|
||||
// provides details on which
|
||||
// The Experiments service was disabled.
|
||||
SERVICE_DISABLED: "SERVICE_DISABLED",
|
||||
// Add-on uninstalled.
|
||||
ADDON_UNINSTALLED: "ADDON_UNINSTALLED",
|
||||
// The experiment disabled itself.
|
||||
FROM_API: "FROM_API",
|
||||
// The experiment expired (e.g. by exceeding the end date).
|
||||
EXPIRED: "EXPIRED",
|
||||
// Disabled after re-evaluating conditions. If this is specified,
|
||||
// details will be provided.
|
||||
RECHECK: "RECHECK",
|
||||
},
|
||||
};
|
||||
|
||||
@ -106,6 +113,10 @@ let gExperimentEntryCounter = 0;
|
||||
// installs.
|
||||
let gActiveInstallURLs = new Set();
|
||||
|
||||
// Tracks add-on IDs that are being uninstalled by us. This allows us
|
||||
// to differentiate between expected uninstalled and user-driven uninstalls.
|
||||
let gActiveUninstallAddonIDs = new Set();
|
||||
|
||||
let gLogger;
|
||||
let gLogDumping = false;
|
||||
|
||||
@ -336,9 +347,6 @@ Experiments.Experiments = function (policy=new Experiments.Policy()) {
|
||||
// Loading the cache happens once asynchronously on startup
|
||||
this._loadTask = null;
|
||||
|
||||
// Ignore addon-manager notifications for addons that we are uninstalling ourself
|
||||
this._pendingUninstall = null;
|
||||
|
||||
// The _main task handles all other actions:
|
||||
// * refreshing the manifest off the network (if _refresh)
|
||||
// * disabling/enabling experiments
|
||||
@ -457,7 +465,7 @@ Experiments.Experiments.prototype = {
|
||||
gPrefs.set(PREF_ENABLED, enabled);
|
||||
},
|
||||
|
||||
_toggleExperimentsEnabled: function (enabled) {
|
||||
_toggleExperimentsEnabled: Task.async(function* (enabled) {
|
||||
this._log.trace("_toggleExperimentsEnabled(" + enabled + ")");
|
||||
let wasEnabled = gExperimentsEnabled;
|
||||
gExperimentsEnabled = enabled && telemetryEnabled();
|
||||
@ -467,14 +475,14 @@ Experiments.Experiments.prototype = {
|
||||
}
|
||||
|
||||
if (gExperimentsEnabled) {
|
||||
this.updateManifest();
|
||||
yield this.updateManifest();
|
||||
} else {
|
||||
this.disableExperiment();
|
||||
yield this.disableExperiment(TELEMETRY_LOG.TERMINATION.SERVICE_DISABLED);
|
||||
if (this._timer) {
|
||||
this._timer.clear();
|
||||
}
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
_telemetryStatusChanged: function () {
|
||||
this._toggleExperimentsEnabled(gExperimentsEnabled);
|
||||
@ -656,21 +664,9 @@ Experiments.Experiments.prototype = {
|
||||
|
||||
// START OF ADD-ON LISTENERS
|
||||
|
||||
onDisabled: function (addon) {
|
||||
this._log.trace("onDisabled() - addon id: " + addon.id);
|
||||
if (addon.id == this._pendingUninstall) {
|
||||
return;
|
||||
}
|
||||
let activeExperiment = this._getActiveExperiment();
|
||||
if (!activeExperiment || activeExperiment._addonId != addon.id) {
|
||||
return;
|
||||
}
|
||||
this.disableExperiment();
|
||||
},
|
||||
|
||||
onUninstalled: function (addon) {
|
||||
this._log.trace("onUninstalled() - addon id: " + addon.id);
|
||||
if (addon.id == this._pendingUninstall) {
|
||||
if (gActiveUninstallAddonIDs.has(addon.id)) {
|
||||
this._log.trace("matches pending uninstall");
|
||||
return;
|
||||
}
|
||||
@ -678,7 +674,8 @@ Experiments.Experiments.prototype = {
|
||||
if (!activeExperiment || activeExperiment._addonId != addon.id) {
|
||||
return;
|
||||
}
|
||||
this.disableExperiment();
|
||||
|
||||
this.disableExperiment(TELEMETRY_LOG.TERMINATION.ADDON_UNINSTALLED);
|
||||
},
|
||||
|
||||
onInstallStarted: function (install) {
|
||||
@ -916,15 +913,17 @@ Experiments.Experiments.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Disable an experiment by id.
|
||||
* @param experimentId The id of the experiment.
|
||||
* @param userDisabled (optional) Whether this is disabled as a result of a user action.
|
||||
* Disables all active experiments.
|
||||
*
|
||||
* @return Promise<> Promise that will get resolved once the task is done or failed.
|
||||
*/
|
||||
disableExperiment: function (userDisabled=true) {
|
||||
this._log.trace("disableExperiment()");
|
||||
disableExperiment: function (reason) {
|
||||
if (!reason) {
|
||||
throw new Error("Must specify a termination reason.");
|
||||
}
|
||||
|
||||
this._terminateReason = userDisabled ? TELEMETRY_LOG.TERMINATION.USERDISABLED : TELEMETRY_LOG.TERMINATION.FROM_API;
|
||||
this._log.trace("disableExperiment()");
|
||||
this._terminateReason = reason;
|
||||
return this._run();
|
||||
},
|
||||
|
||||
@ -981,44 +980,43 @@ Experiments.Experiments.prototype = {
|
||||
gPrefs.set(PREF_ACTIVE_EXPERIMENT, false);
|
||||
}
|
||||
|
||||
// Ensure the active experiment is in the proper state. This may install,
|
||||
// uninstall, upgrade, or enable the experiment add-on. What exactly is
|
||||
// abstracted away from us by design.
|
||||
if (activeExperiment) {
|
||||
this._pendingUninstall = activeExperiment._addonId;
|
||||
try {
|
||||
let wasStopped;
|
||||
if (this._terminateReason) {
|
||||
yield activeExperiment.stop(this._terminateReason);
|
||||
wasStopped = true;
|
||||
let changes;
|
||||
let shouldStopResult = yield activeExperiment.shouldStop();
|
||||
if (shouldStopResult.shouldStop) {
|
||||
let expireReasons = ["endTime", "maxActiveSeconds"];
|
||||
let kind, reason;
|
||||
|
||||
if (expireReasons.indexOf(shouldStopResult.reason[0]) != -1) {
|
||||
kind = TELEMETRY_LOG.TERMINATION.EXPIRED;
|
||||
reason = null;
|
||||
} else {
|
||||
wasStopped = yield activeExperiment.maybeStop();
|
||||
kind = TELEMETRY_LOG.TERMINATION.RECHECK;
|
||||
reason = shouldStopResult.reason;
|
||||
}
|
||||
if (wasStopped) {
|
||||
this._dirty = true;
|
||||
this._log.debug("evaluateExperiments() - stopped experiment "
|
||||
+ activeExperiment.id);
|
||||
activeExperiment = null;
|
||||
activeChanged = true;
|
||||
} else if (!gExperimentsEnabled) {
|
||||
// No further actions if the feature is disabled.
|
||||
} else if (activeExperiment.needsUpdate) {
|
||||
this._log.debug("evaluateExperiments() - updating experiment "
|
||||
+ activeExperiment.id);
|
||||
try {
|
||||
yield activeExperiment.stop();
|
||||
yield activeExperiment.start();
|
||||
} catch (e) {
|
||||
this._log.error(e);
|
||||
// On failure try the next experiment.
|
||||
activeExperiment = null;
|
||||
}
|
||||
this._dirty = true;
|
||||
activeChanged = true;
|
||||
} else {
|
||||
yield activeExperiment.ensureActive();
|
||||
}
|
||||
} finally {
|
||||
this._pendingUninstall = null;
|
||||
changes = yield activeExperiment.stop(kind, reason);
|
||||
}
|
||||
else if (this._terminateReason) {
|
||||
changes = yield activeExperiment.stop(this._terminateReason);
|
||||
}
|
||||
else {
|
||||
changes = yield activeExperiment.reconcileAddonState();
|
||||
}
|
||||
|
||||
if (changes) {
|
||||
this._dirty = true;
|
||||
activeChanged = true;
|
||||
}
|
||||
|
||||
if (!activeExperiment._enabled) {
|
||||
activeExperiment = null;
|
||||
activeChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
this._terminateReason = null;
|
||||
|
||||
if (!activeExperiment && gExperimentsEnabled) {
|
||||
@ -1041,30 +1039,35 @@ Experiments.Experiments.prototype = {
|
||||
TelemetryLog.log(TELEMETRY_LOG.ACTIVATION_KEY, data);
|
||||
}
|
||||
|
||||
if (applicable) {
|
||||
this._log.debug("evaluateExperiments() - activating experiment " + id);
|
||||
try {
|
||||
yield experiment.start();
|
||||
activeChanged = true;
|
||||
activeExperiment = experiment;
|
||||
this._dirty = true;
|
||||
break;
|
||||
} catch (e) {
|
||||
// On failure try the next experiment.
|
||||
}
|
||||
if (!applicable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this._log.debug("evaluateExperiments() - activating experiment " + id);
|
||||
try {
|
||||
yield experiment.start();
|
||||
activeChanged = true;
|
||||
activeExperiment = experiment;
|
||||
this._dirty = true;
|
||||
break;
|
||||
} catch (e) {
|
||||
// On failure, clean up the best we can and try the next experiment.
|
||||
this._log.error("evaluateExperiments() - Unable to start experiment: " + e.message);
|
||||
experiment._enabled = false;
|
||||
yield experiment.reconcileAddonState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gPrefs.set(PREF_ACTIVE_EXPERIMENT, activeExperiment != null);
|
||||
|
||||
if (activeChanged) {
|
||||
Services.obs.notifyObservers(null, OBSERVER_TOPIC, null);
|
||||
}
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
if (activeExperiment) {
|
||||
if ("@mozilla.org/toolkit/crash-reporter;1" in Cc && activeExperiment) {
|
||||
gCrashReporter.annotateCrashReport("ActiveExperiment", activeExperiment.id);
|
||||
}
|
||||
#endif
|
||||
},
|
||||
|
||||
/*
|
||||
@ -1116,7 +1119,7 @@ Experiments.ExperimentEntry = function (policy) {
|
||||
"Browser.Experiments.Experiments",
|
||||
"ExperimentEntry #" + gExperimentEntryCounter++ + "::");
|
||||
|
||||
// Is this experiment running?
|
||||
// Is the experiment supposed to be running.
|
||||
this._enabled = false;
|
||||
// When this experiment was started, if ever.
|
||||
this._startDate = null;
|
||||
@ -1187,6 +1190,11 @@ Experiments.ExperimentEntry.prototype = {
|
||||
"_endDate",
|
||||
]),
|
||||
|
||||
ADDON_CHANGE_NONE: 0,
|
||||
ADDON_CHANGE_INSTALL: 1,
|
||||
ADDON_CHANGE_UNINSTALL: 2,
|
||||
ADDON_CHANGE_ENABLE: 4,
|
||||
|
||||
/*
|
||||
* Initialize entry from the manifest.
|
||||
* @param data The experiment data from the manifest.
|
||||
@ -1476,26 +1484,18 @@ Experiments.ExperimentEntry.prototype = {
|
||||
|
||||
/*
|
||||
* Start running the experiment.
|
||||
*
|
||||
* @return Promise<> Resolved when the operation is complete.
|
||||
*/
|
||||
start: function () {
|
||||
start: Task.async(function* () {
|
||||
this._log.trace("start() for " + this.id);
|
||||
|
||||
return Task.spawn(function* ExperimentEntry_start_task() {
|
||||
let addons = yield installedExperimentAddons();
|
||||
if (addons.length > 0) {
|
||||
this._log.error("start() - there are already "
|
||||
+ addons.length + " experiment addons installed");
|
||||
yield uninstallAddons(addons);
|
||||
}
|
||||
|
||||
yield this._installAddon();
|
||||
gPrefs.set(PREF_ACTIVE_EXPERIMENT, true);
|
||||
}.bind(this));
|
||||
},
|
||||
this._enabled = true;
|
||||
return yield this.reconcileAddonState();
|
||||
}),
|
||||
|
||||
// Async install of the addon for this experiment, part of the start task above.
|
||||
_installAddon: function* () {
|
||||
_installAddon: Task.async(function* () {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
let install = yield addonInstallForURL(this._manifestData.xpiURL,
|
||||
@ -1593,75 +1593,105 @@ Experiments.ExperimentEntry.prototype = {
|
||||
install.addListener(listener);
|
||||
install.install();
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
return yield deferred.promise;
|
||||
}),
|
||||
|
||||
/*
|
||||
/**
|
||||
* Stop running the experiment if it is active.
|
||||
* @param terminationKind (optional) The termination kind, e.g. USERDISABLED or EXPIRED.
|
||||
* @param terminationReason (optional) The termination reason details for
|
||||
* termination kind RECHECK.
|
||||
*
|
||||
* @param terminationKind (optional)
|
||||
* The termination kind, e.g. ADDON_UNINSTALLED or EXPIRED.
|
||||
* @param terminationReason (optional)
|
||||
* The termination reason details for termination kind RECHECK.
|
||||
* @return Promise<> Resolved when the operation is complete.
|
||||
*/
|
||||
stop: function (terminationKind, terminationReason) {
|
||||
stop: Task.async(function* (terminationKind, terminationReason) {
|
||||
this._log.trace("stop() - id=" + this.id + ", terminationKind=" + terminationKind);
|
||||
if (!this._enabled) {
|
||||
this._log.warning("stop() - experiment not enabled: " + id);
|
||||
return Promise.reject();
|
||||
throw new Error("Must not call stop() on an inactive experiment.");
|
||||
}
|
||||
|
||||
this._enabled = false;
|
||||
gPrefs.set(PREF_ACTIVE_EXPERIMENT, false);
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let updateDates = () => {
|
||||
let now = this._policy.now();
|
||||
this._lastChangedDate = now;
|
||||
this._endDate = now;
|
||||
};
|
||||
let changes = yield this.reconcileAddonState();
|
||||
let now = this._policy.now();
|
||||
this._lastChangedDate = now;
|
||||
this._endDate = now;
|
||||
this._logTermination(terminationKind, terminationReason);
|
||||
|
||||
this._getAddon().then((addon) => {
|
||||
if (!addon) {
|
||||
let message = "could not get Addon for " + this.id;
|
||||
this._log.warn("stop() - " + message);
|
||||
updateDates();
|
||||
deferred.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
updateDates();
|
||||
this._logTermination(terminationKind, terminationReason);
|
||||
deferred.resolve(uninstallAddons([addon]));
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
return changes;
|
||||
}),
|
||||
|
||||
/**
|
||||
* Try to ensure this experiment is active.
|
||||
* Reconcile the state of the add-on against what it's supposed to be.
|
||||
*
|
||||
* The returned promise will be resolved if the experiment is active
|
||||
* in the Addon Manager or rejected if it isn't.
|
||||
* If we are active, ensure the add-on is enabled and up to date.
|
||||
*
|
||||
* @return Promise<>
|
||||
* If we are inactive, ensure the add-on is not installed.
|
||||
*/
|
||||
ensureActive: Task.async(function* () {
|
||||
this._log.trace("ensureActive() for " + this.id);
|
||||
reconcileAddonState: Task.async(function* () {
|
||||
this._log.trace("reconcileAddonState()");
|
||||
|
||||
if (!this._enabled) {
|
||||
if (!this._addonId) {
|
||||
this._log.trace("reconcileAddonState() - Experiment is not enabled and " +
|
||||
"has no add-on. Doing nothing.");
|
||||
return this.ADDON_CHANGE_NONE;
|
||||
}
|
||||
|
||||
let addon = yield this._getAddon();
|
||||
if (!addon) {
|
||||
this._log.trace("reconcileAddonState() - Inactive experiment has no " +
|
||||
"add-on. Doing nothing.");
|
||||
return this.ADDON_CHANGE_NONE;
|
||||
}
|
||||
|
||||
this._log.info("reconcileAddonState() - Uninstalling add-on for inactive " +
|
||||
"experiment: " + addon.id);
|
||||
gActiveUninstallAddonIDs.add(addon.id);
|
||||
yield uninstallAddons([addon]);
|
||||
gActiveUninstallAddonIDs.delete(addon.id);
|
||||
return this.ADDON_CHANGE_UNINSTALL;
|
||||
}
|
||||
|
||||
// If we get here, we're supposed to be active.
|
||||
|
||||
let changes = 0;
|
||||
|
||||
// That requires an add-on.
|
||||
let currentAddon = yield this._getAddon();
|
||||
|
||||
// If we have an add-on but it isn't up to date, uninstall it
|
||||
// (to prepare for reinstall).
|
||||
if (currentAddon && this._needsUpdate) {
|
||||
this._log.info("reconcileAddonState() - Uninstalling add-on because update " +
|
||||
"needed: " + currentAddon.id);
|
||||
gActiveUninstallAddonIDs.add(currentAddon.id);
|
||||
yield uninstallAddons([currentAddon]);
|
||||
gActiveUninstallAddonIDs.delete(currentAddon.id);
|
||||
changes |= this.ADDON_CHANGE_UNINSTALL;
|
||||
}
|
||||
|
||||
if (!currentAddon || this._needsUpdate) {
|
||||
this._log.info("reconcileAddonState() - Installing add-on.");
|
||||
yield this._installAddon();
|
||||
changes |= this.ADDON_CHANGE_INSTALL;
|
||||
}
|
||||
|
||||
let addon = yield this._getAddon();
|
||||
if (!addon) {
|
||||
this._log.warn("Experiment is not installed: " + this._addonId);
|
||||
throw new Error("Experiment is not installed: " + this._addonId);
|
||||
throw new Error("Could not obtain add-on for experiment that should be " +
|
||||
"enabled.");
|
||||
}
|
||||
|
||||
// User disabled likely means the experiment is disabled at startup,
|
||||
// since the permissions don't allow it to be disabled by the user.
|
||||
// If we have the add-on and it is enabled, we are done.
|
||||
if (!addon.userDisabled) {
|
||||
return;
|
||||
return changes;
|
||||
}
|
||||
|
||||
let deferred = Promise.defer();
|
||||
|
||||
// Else we need to enable it.
|
||||
let listener = {
|
||||
onEnabled: enabledAddon => {
|
||||
if (enabledAddon.id != addon.id) {
|
||||
@ -1677,7 +1707,11 @@ Experiments.ExperimentEntry.prototype = {
|
||||
AddonManager.addAddonListener(listener);
|
||||
addon.userDisabled = false;
|
||||
yield deferred.promise;
|
||||
}),
|
||||
changes |= this.ADDON_CHANGE_ENABLE;
|
||||
|
||||
this._log.info("Add-on has been enabled: " + addon.id);
|
||||
return changes;
|
||||
}),
|
||||
|
||||
/**
|
||||
* Obtain the underlying Addon from the Addon Manager.
|
||||
@ -1685,6 +1719,10 @@ Experiments.ExperimentEntry.prototype = {
|
||||
* @return Promise<Addon|null>
|
||||
*/
|
||||
_getAddon: function () {
|
||||
if (!this._addonId) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
let deferred = Promise.defer();
|
||||
|
||||
AddonManager.getAddonByID(this._addonId, deferred.resolve);
|
||||
@ -1710,43 +1748,18 @@ Experiments.ExperimentEntry.prototype = {
|
||||
TelemetryLog.log(TELEMETRY_LOG.TERMINATION_KEY, data);
|
||||
},
|
||||
|
||||
/*
|
||||
* Stop if experiment stop criteria are met.
|
||||
* @return Promise<boolean> Resolved when done stopping or checking,
|
||||
* the value indicates whether it was stopped.
|
||||
/**
|
||||
* Determine whether an active experiment should be stopped.
|
||||
*/
|
||||
maybeStop: function () {
|
||||
this._log.trace("maybeStop()");
|
||||
return Task.spawn(function* ExperimentEntry_maybeStop_task() {
|
||||
if (!gExperimentsEnabled) {
|
||||
this._log.warn("maybeStop() - should not get here");
|
||||
yield this.stop(TELEMETRY_LOG.TERMINATION.FROM_API);
|
||||
return true;
|
||||
}
|
||||
shouldStop: function () {
|
||||
if (!this._enabled) {
|
||||
throw new Error("shouldStop must not be called on disabled experiments.");
|
||||
}
|
||||
|
||||
let result = yield this._shouldStop();
|
||||
if (result.shouldStop) {
|
||||
let expireReasons = ["endTime", "maxActiveSeconds"];
|
||||
if (expireReasons.indexOf(result.reason[0]) != -1) {
|
||||
yield this.stop(TELEMETRY_LOG.TERMINATION.EXPIRED);
|
||||
} else {
|
||||
yield this.stop(TELEMETRY_LOG.TERMINATION.RECHECK, result.reason);
|
||||
}
|
||||
}
|
||||
|
||||
return result.shouldStop;
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
_shouldStop: function () {
|
||||
let data = this._manifestData;
|
||||
let now = this._policy.now() / 1000; // The manifest times are in seconds.
|
||||
let maxActiveSec = data.maxActiveSeconds || 0;
|
||||
|
||||
if (!this._enabled) {
|
||||
return Promise.resolve({shouldStop: false});
|
||||
}
|
||||
|
||||
let deferred = Promise.defer();
|
||||
this.isApplicable().then(
|
||||
() => deferred.resolve({shouldStop: false}),
|
||||
|
@ -9,7 +9,7 @@ EXTRA_COMPONENTS += [
|
||||
|
||||
JS_MODULES_PATH = 'modules/experiments'
|
||||
|
||||
EXTRA_PP_JS_MODULES += [
|
||||
EXTRA_JS_MODULES += [
|
||||
'Experiments.jsm',
|
||||
]
|
||||
|
||||
|
@ -102,7 +102,8 @@ add_task(function* test_startStop() {
|
||||
Assert.equal(result.applicable, true, "Experiment should now be applicable.");
|
||||
Assert.equal(experiment.enabled, false, "Experiment should not be enabled.");
|
||||
|
||||
yield experiment.start();
|
||||
let changes = yield experiment.start();
|
||||
Assert.equal(changes, experiment.ADDON_CHANGE_INSTALL, "Add-on was installed.");
|
||||
addons = yield getExperimentAddons();
|
||||
Assert.equal(experiment.enabled, true, "Experiment should now be enabled.");
|
||||
Assert.equal(addons.length, 1, "1 experiment add-on is installed.");
|
||||
@ -110,12 +111,14 @@ add_task(function* test_startStop() {
|
||||
Assert.equal(addons[0].userDisabled, false, "The add-on is not userDisabled.");
|
||||
Assert.ok(addons[0].isActive, "The add-on is active.");
|
||||
|
||||
yield experiment.stop();
|
||||
changes = yield experiment.stop();
|
||||
Assert.equal(changes, experiment.ADDON_CHANGE_UNINSTALL, "Add-on was uninstalled.");
|
||||
addons = yield getExperimentAddons();
|
||||
Assert.equal(experiment.enabled, false, "Experiment should not be enabled.");
|
||||
Assert.equal(addons.length, 0, "Experiment should be uninstalled from the Addon Manager.");
|
||||
|
||||
yield experiment.start();
|
||||
changes = yield experiment.start();
|
||||
Assert.equal(changes, experiment.ADDON_CHANGE_INSTALL, "Add-on was installed.");
|
||||
addons = yield getExperimentAddons();
|
||||
Assert.equal(experiment.enabled, true, "Experiment should now be enabled.");
|
||||
Assert.equal(addons.length, 1, "1 experiment add-on is installed.");
|
||||
@ -123,20 +126,18 @@ add_task(function* test_startStop() {
|
||||
Assert.equal(addons[0].userDisabled, false, "The add-on is not userDisabled.");
|
||||
Assert.ok(addons[0].isActive, "The add-on is active.");
|
||||
|
||||
let result = yield experiment._shouldStop();
|
||||
let result = yield experiment.shouldStop();
|
||||
Assert.equal(result.shouldStop, false, "shouldStop should be false.");
|
||||
let maybeStop = yield experiment.maybeStop();
|
||||
Assert.equal(maybeStop, false, "Experiment should not have been stopped.");
|
||||
Assert.equal(experiment.enabled, true, "Experiment should be enabled.");
|
||||
addons = yield getExperimentAddons();
|
||||
Assert.equal(addons.length, 1, "Experiment still in add-ons manager.");
|
||||
Assert.ok(addons[0].isActive, "The add-on is still active.");
|
||||
|
||||
defineNow(gPolicy, futureDate(endDate, MS_IN_ONE_DAY));
|
||||
result = yield experiment._shouldStop();
|
||||
result = yield experiment.shouldStop();
|
||||
Assert.equal(result.shouldStop, true, "shouldStop should now be true.");
|
||||
maybeStop = yield experiment.maybeStop();
|
||||
Assert.equal(maybeStop, true, "Experiment should have been stopped.");
|
||||
changes = yield experiment.stop();
|
||||
Assert.equal(changes, experiment.ADDON_CHANGE_UNINSTALL, "Add-on should be uninstalled.");
|
||||
Assert.equal(experiment.enabled, false, "Experiment should be disabled.");
|
||||
addons = yield getExperimentAddons();
|
||||
Assert.equal(addons.length, 0, "Experiment add-on is uninstalled.");
|
||||
|
@ -424,7 +424,7 @@ add_task(function* test_disableExperiment() {
|
||||
|
||||
now = futureDate(now, 1 * MS_IN_ONE_DAY);
|
||||
defineNow(gPolicy, now);
|
||||
yield experiments.disableExperiment();
|
||||
yield experiments.disableExperiment("foo");
|
||||
|
||||
list = yield experiments.getExperiments();
|
||||
Assert.equal(list.length, 1, "Experiment list should have 1 entry.");
|
||||
@ -749,7 +749,7 @@ add_task(function* test_userDisabledAndUpdated() {
|
||||
|
||||
now = futureDate(now, 20 * MS_IN_ONE_DAY);
|
||||
defineNow(gPolicy, now);
|
||||
yield experiments.disableExperiment();
|
||||
yield experiments.disableExperiment("foo");
|
||||
Assert.equal(observerFireCount, ++expectedObserverFireCount,
|
||||
"Experiments observer should have been called.");
|
||||
|
||||
@ -1405,7 +1405,7 @@ add_task(function* testForeignExperimentInstall() {
|
||||
let addons = yield getExperimentAddons();
|
||||
Assert.equal(addons.length, 0, "Precondition: No experiment add-ons present.");
|
||||
|
||||
let failed;
|
||||
let failed = false;
|
||||
try {
|
||||
yield AddonTestUtils.installXPIFromURL(gDataRoot + EXPERIMENT1_XPI_NAME, EXPERIMENT1_XPI_SHA1);
|
||||
} catch (ex) {
|
||||
|
@ -243,7 +243,7 @@ add_task(function* test_cache() {
|
||||
|
||||
// Cleanup.
|
||||
|
||||
yield experiments.disableExperiment();
|
||||
yield experiments._toggleExperimentsEnabled(false);
|
||||
yield experiments.uninit();
|
||||
yield removeCacheFile();
|
||||
});
|
||||
|
@ -6,7 +6,7 @@
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
Cu.import("resource://gre/modules/TelemetryLog.jsm");
|
||||
Cu.import("resource://gre/modules/TelemetryPing.jsm");
|
||||
Cu.import("resource:///modules/experiments/Experiments.jsm");
|
||||
let bsp = Cu.import("resource:///modules/experiments/Experiments.jsm");
|
||||
|
||||
|
||||
const FILE_MANIFEST = "experiments.manifest";
|
||||
@ -25,25 +25,7 @@ let gPolicy = null;
|
||||
let gManifestObject = null;
|
||||
let gManifestHandlerURI = null;
|
||||
|
||||
const TLOG = {
|
||||
// log(key, [kind, experimentId, details])
|
||||
ACTIVATION_KEY: "EXPERIMENT_ACTIVATION",
|
||||
ACTIVATION: {
|
||||
ACTIVATED: "ACTIVATED",
|
||||
INSTALL_FAILURE: "INSTALL_FAILURE",
|
||||
REJECTED: "REJECTED",
|
||||
},
|
||||
|
||||
// log(key, [kind, experimentId, optionalDetails...])
|
||||
TERMINATION_KEY: "EXPERIMENT_TERMINATION",
|
||||
TERMINATION: {
|
||||
USERDISABLED: "USERDISABLED",
|
||||
FROM_API: "FROM_API",
|
||||
EXPIRED: "EXPIRED",
|
||||
RECHECK: "RECHECK",
|
||||
},
|
||||
};
|
||||
|
||||
const TLOG = bsp.TELEMETRY_LOG;
|
||||
|
||||
let gGlobalScope = this;
|
||||
function loadAddonManager() {
|
||||
@ -263,12 +245,12 @@ add_task(function* test_telemetryBasics() {
|
||||
checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
|
||||
[TLOG.ACTIVATION.ACTIVATED, EXPERIMENT2_ID]);
|
||||
|
||||
// Fake user-disable of an experiment.
|
||||
// Fake user uninstall of experiment via add-on manager.
|
||||
|
||||
now = futureDate(now, MS_IN_ONE_DAY);
|
||||
defineNow(gPolicy, now);
|
||||
|
||||
yield experiments.disableExperiment();
|
||||
yield experiments.disableExperiment(TLOG.TERMINATION.ADDON_UNINSTALLED);
|
||||
list = yield experiments.getExperiments();
|
||||
Assert.equal(list.length, 2, "Experiment list should have 2 entries.");
|
||||
|
||||
@ -276,7 +258,7 @@ add_task(function* test_telemetryBasics() {
|
||||
log = TelemetryPing.getPayload().log;
|
||||
Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
|
||||
checkEvent(log[log.length-1], TLOG.TERMINATION_KEY,
|
||||
[TLOG.TERMINATION.USERDISABLED, EXPERIMENT2_ID]);
|
||||
[TLOG.TERMINATION.ADDON_UNINSTALLED, EXPERIMENT2_ID]);
|
||||
|
||||
// Trigger update with experiment 1a ready to start.
|
||||
|
||||
@ -295,12 +277,12 @@ add_task(function* test_telemetryBasics() {
|
||||
checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
|
||||
[TLOG.ACTIVATION.ACTIVATED, EXPERIMENT3_ID]);
|
||||
|
||||
// Trigger non-user-disable of an experiment via the API
|
||||
// Trigger disable of an experiment via the API.
|
||||
|
||||
now = futureDate(now, MS_IN_ONE_DAY);
|
||||
defineNow(gPolicy, now);
|
||||
|
||||
yield experiments.disableExperiment(false);
|
||||
yield experiments.disableExperiment(TLOG.TERMINATION.FROM_API);
|
||||
list = yield experiments.getExperiments();
|
||||
Assert.equal(list.length, 3, "Experiment list should have 3 entries.");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user