new file mode 100644
--- /dev/null
+++ b/browser/experiments/.eslintrc.js
@@ -0,0 +1,11 @@
+"use strict";
+
+module.exports = {
+ "rules": {
+ "no-unused-vars": ["error", {
+ "vars": "all",
+ "varsIgnorePattern": "^(Cc|Ci|Cr|Cu|EXPORTED_SYMBOLS)$",
+ "args": "none"
+ }]
+ }
+};
--- a/browser/experiments/Experiments.jsm
+++ b/browser/experiments/Experiments.jsm
@@ -39,17 +39,16 @@ XPCOMUtils.defineLazyServiceGetter(this,
"nsICrashReporter");
const FILE_CACHE = "experiments.json";
const EXPERIMENTS_CHANGED_TOPIC = "experiments-changed";
const MANIFEST_VERSION = 1;
const CACHE_VERSION = 1;
const KEEP_HISTORY_N_DAYS = 180;
-const MIN_EXPERIMENT_ACTIVE_SECONDS = 60;
const PREF_BRANCH = "experiments.";
const PREF_ENABLED = "enabled"; // experiments.enabled
const PREF_ACTIVE_EXPERIMENT = "activeExperiment"; // whether we have an active experiment
const PREF_LOGGING = "logging";
const PREF_LOGGING_LEVEL = PREF_LOGGING + ".level"; // experiments.logging.level
const PREF_LOGGING_DUMP = PREF_LOGGING + ".dump"; // experiments.logging.dump
const PREF_MANIFEST_URI = "manifest.uri"; // experiments.logging.manifest.uri
@@ -1212,17 +1211,16 @@ Experiments.Experiments.prototype = {
this._log.warn("_evaluateExperiments() - unknown add-ons in AddonManager: " +
unknownAddons.map(a => a.id).join(", "));
yield uninstallAddons(unknownAddons);
}
let activeExperiment = this._getActiveExperiment();
let activeChanged = false;
- let now = this._policy.now();
if (!activeExperiment) {
// Avoid this pref staying out of sync if there were e.g. crashes.
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
@@ -1272,17 +1270,16 @@ Experiments.Experiments.prototype = {
}
catch (e) {
applicable = false;
reason = e;
}
if (!applicable && reason && reason[0] != "was-active") {
// Report this from here to avoid over-reporting.
- let desc = TELEMETRY_LOG.ACTIVATION;
let data = [TELEMETRY_LOG.ACTIVATION.REJECTED, id];
data = data.concat(reason);
const key = TELEMETRY_LOG.ACTIVATION_KEY;
TelemetryLog.log(key, data);
this._log.trace("evaluateExperiments() - added " + key + " to TelemetryLog: " + JSON.stringify(data));
}
if (!applicable) {
@@ -1338,17 +1335,17 @@ Experiments.Experiments.prototype = {
let time = null;
let now = this._policy.now().getTime();
if (this._dirty) {
// If we failed to write the cache, we should try again periodically
time = now + 1000 * CACHE_WRITE_RETRY_DELAY_SEC;
}
- for (let [id, experiment] of this._experiments) {
+ for (let [, experiment] of this._experiments) {
let scheduleTime = experiment.getScheduleTime();
if (scheduleTime > now) {
if (time !== null) {
time = Math.min(time, scheduleTime);
} else {
time = scheduleTime;
}
}
@@ -1639,17 +1636,16 @@ Experiments.ExperimentEntry.prototype =
let runtime = Cc["@mozilla.org/xre/app-info;1"]
.getService(Ci.nsIXULRuntime);
let locale = this._policy.locale();
let channel = this._policy.updatechannel();
let data = this._manifestData;
let now = this._policy.now() / 1000; // The manifest times are in seconds.
- let minActive = MIN_EXPERIMENT_ACTIVE_SECONDS;
let maxActive = data.maxActiveSeconds || 0;
let startSec = (this.startDate || 0) / 1000;
this._log.trace("isApplicable() - now=" + now
+ ", randomValue=" + this._randomValue);
// Not applicable if it already ran.
@@ -2064,20 +2060,16 @@ Experiments.ExperimentEntry.prototype =
/**
* Determine whether an active experiment should be stopped.
*/
shouldStop: function () {
if (!this._enabled) {
throw new Error("shouldStop must not be called on disabled experiments.");
}
- let data = this._manifestData;
- let now = this._policy.now() / 1000; // The manifest times are in seconds.
- let maxActiveSec = data.maxActiveSeconds || 0;
-
let deferred = Promise.defer();
this.isApplicable().then(
() => deferred.resolve({shouldStop: false}),
reason => deferred.resolve({shouldStop: true, reason: reason})
);
return deferred.promise;
},
@@ -2092,17 +2084,16 @@ Experiments.ExperimentEntry.prototype =
},
/*
* Get next date (in epoch-ms) to schedule a re-evaluation for this.
* Returns 0 if it doesn't need one.
*/
getScheduleTime: function () {
if (this._enabled) {
- let now = this._policy.now();
let startTime = this._startDate.getTime();
let maxActiveTime = startTime + 1000 * this._manifestData.maxActiveSeconds;
return Math.min(1000 * this._manifestData.endTime, maxActiveTime);
}
if (this._endDate) {
return this._endDate.getTime();
}
@@ -2223,17 +2214,17 @@ this.Experiments.PreviousExperimentProvi
let wrapper = new PreviousExperimentAddon(newMap.get(id));
AddonManagerPrivate.callInstallListeners("onExternalInstall", null, wrapper, null, false);
AddonManagerPrivate.callAddonListeners("onInstalling", wrapper, false);
}
for (let id of removed) {
this._log.trace("updateExperimentList() - removing " + id);
let wrapper = new PreviousExperimentAddon(oldMap.get(id));
- AddonManagerPrivate.callAddonListeners("onUninstalling", plugin, false);
+ AddonManagerPrivate.callAddonListeners("onUninstalling", wrapper, false);
}
this._experimentList = list;
for (let id of added) {
let wrapper = new PreviousExperimentAddon(newMap.get(id));
AddonManagerPrivate.callAddonListeners("onInstalled", wrapper);
}
--- a/browser/experiments/test/addons/experiment-racybranch/bootstrap.js
+++ b/browser/experiments/test/addons/experiment-racybranch/bootstrap.js
@@ -1,8 +1,10 @@
+/* exported startup, shutdown, install, uninstall */
+
var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource:///modules/experiments/Experiments.jsm");
var gStarted = false;
function startup(data, reasonCode) {
if (gStarted) {
--- a/browser/experiments/test/xpcshell/.eslintrc.js
+++ b/browser/experiments/test/xpcshell/.eslintrc.js
@@ -1,7 +1,15 @@
"use strict";
module.exports = {
"extends": [
"../../../../testing/xpcshell/xpcshell.eslintrc.js"
- ]
+ ],
+
+ "rules": {
+ "no-unused-vars": ["error", {
+ "vars": "all",
+ "varsIgnorePattern": "^(Cc|Ci|Cr|Cu|EXPORTED_SYMBOLS|run_test)$",
+ "args": "none"
+ }]
+ }
};
--- a/browser/experiments/test/xpcshell/head.js
+++ b/browser/experiments/test/xpcshell/head.js
@@ -1,11 +1,20 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
+/* exported PREF_EXPERIMENTS_ENABLED, PREF_LOGGING_LEVEL, PREF_LOGGING_DUMP
+ PREF_MANIFEST_URI, PREF_FETCHINTERVAL, EXPERIMENT1_ID,
+ EXPERIMENT1_NAME, EXPERIMENT1_XPI_SHA1, EXPERIMENT1A_NAME,
+ EXPERIMENT1A_XPI_SHA1, EXPERIMENT2_ID, EXPERIMENT2_XPI_SHA1,
+ EXPERIMENT3_ID, EXPERIMENT4_ID, FAKE_EXPERIMENTS_1,
+ FAKE_EXPERIMENTS_2, gAppInfo, removeCacheFile, defineNow,
+ futureDate, dateToSeconds, loadAddonManager, promiseRestartManager,
+ startAddonManagerOnly, getExperimentAddons, replaceExperiments */
+
var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
Cu.import("resource://testing-common/AddonManagerTesting.jsm");
--- a/browser/experiments/test/xpcshell/test_activate.js
+++ b/browser/experiments/test/xpcshell/test_activate.js
@@ -1,21 +1,19 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
Cu.import("resource://testing-common/httpd.js");
Cu.import("resource:///modules/experiments/Experiments.jsm");
-const FILE_MANIFEST = "experiments.manifest";
const SEC_IN_ONE_DAY = 24 * 60 * 60;
const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000;
-var gProfileDir = null;
var gHttpServer = null;
var gHttpRoot = null;
var gPolicy = null;
function ManifestEntry(data) {
this.id = data.id || EXPERIMENT1_ID;
this.xpiURL = data.xpiURL || gHttpRoot + EXPERIMENT1_XPI_NAME;
this.xpiHash = data.xpiHash || EXPERIMENT1_XPI_SHA1;
@@ -27,35 +25,32 @@ function ManifestEntry(data) {
}
function run_test() {
run_next_test();
}
add_task(function* test_setup() {
loadAddonManager();
- gProfileDir = do_get_profile();
gPolicy = new Experiments.Policy();
gHttpServer = new HttpServer();
gHttpServer.start(-1);
let port = gHttpServer.identity.primaryPort;
gHttpRoot = "http://localhost:" + port + "/";
gHttpServer.registerDirectory("/", do_get_cwd());
do_register_cleanup(() => gHttpServer.stop(() => {}));
patchPolicy(gPolicy, {
updatechannel: () => "nightly",
});
Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true);
Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0);
Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true);
-
- let experiments = new Experiments.Experiments();
});
function isApplicable(experiment) {
let deferred = Promise.defer();
experiment.isApplicable().then(
result => deferred.resolve({ applicable: true, reason: null }),
reason => deferred.resolve({ applicable: false, reason: reason })
);
--- a/browser/experiments/test/xpcshell/test_api.js
+++ b/browser/experiments/test/xpcshell/test_api.js
@@ -4,23 +4,21 @@
"use strict";
Cu.import("resource://testing-common/httpd.js");
Cu.import("resource://testing-common/AddonManagerTesting.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Experiments",
"resource:///modules/experiments/Experiments.jsm");
-const FILE_MANIFEST = "experiments.manifest";
const MANIFEST_HANDLER = "manifests/handler";
const SEC_IN_ONE_DAY = 24 * 60 * 60;
const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000;
-var gProfileDir = null;
var gHttpServer = null;
var gHttpRoot = null;
var gDataRoot = null;
var gPolicy = null;
var gManifestObject = null;
var gManifestHandlerURI = null;
var gTimerScheduleOffset = -1;
@@ -42,17 +40,16 @@ function testCleanup(experimentsInstance
}
function run_test() {
run_next_test();
}
add_task(function* test_setup() {
loadAddonManager();
- gProfileDir = do_get_profile();
gHttpServer = new HttpServer();
gHttpServer.start(-1);
let port = gHttpServer.identity.primaryPort;
gHttpRoot = "http://localhost:" + port + "/";
gDataRoot = gHttpRoot + "data/";
gManifestHandlerURI = gHttpRoot + MANIFEST_HANDLER;
gHttpServer.registerDirectory("/data/", do_get_cwd());
@@ -157,17 +154,17 @@ add_task(function* test_getExperiments()
"getActiveExperimentID should return null");
let list = yield experiments.getExperiments();
Assert.equal(list.length, 0, "Experiment list should be empty.");
let addons = yield getExperimentAddons();
Assert.equal(addons.length, 0, "Precondition: No experiment add-ons are installed.");
try {
- let b = yield experiments.getExperimentBranch();
+ yield experiments.getExperimentBranch();
Assert.ok(false, "getExperimentBranch should fail with no experiment");
}
catch (e) {
Assert.ok(true, "getExperimentBranch correctly threw");
}
// Trigger update, clock set for experiment 1 to start.
--- a/browser/experiments/test/xpcshell/test_cache.js
+++ b/browser/experiments/test/xpcshell/test_cache.js
@@ -7,32 +7,29 @@ Cu.import("resource://testing-common/htt
XPCOMUtils.defineLazyModuleGetter(this, "Experiments",
"resource:///modules/experiments/Experiments.jsm");
const MANIFEST_HANDLER = "manifests/handler";
const SEC_IN_ONE_DAY = 24 * 60 * 60;
const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000;
-var gProfileDir = null;
var gHttpServer = null;
var gHttpRoot = null;
var gDataRoot = null;
var gPolicy = null;
var gManifestObject = null;
var gManifestHandlerURI = null;
-var gTimerScheduleOffset = -1;
function run_test() {
run_next_test();
}
add_task(function* test_setup() {
loadAddonManager();
- gProfileDir = do_get_profile();
yield removeCacheFile();
gHttpServer = new HttpServer();
gHttpServer.start(-1);
let port = gHttpServer.identity.primaryPort;
gHttpRoot = "http://localhost:" + port + "/";
gDataRoot = gHttpRoot + "data/";
gManifestHandlerURI = gHttpRoot + MANIFEST_HANDLER;
@@ -49,17 +46,17 @@ add_task(function* test_setup() {
Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0);
Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true);
Services.prefs.setCharPref(PREF_MANIFEST_URI, gManifestHandlerURI);
Services.prefs.setIntPref(PREF_FETCHINTERVAL, 0);
gPolicy = new Experiments.Policy();
patchPolicy(gPolicy, {
updatechannel: () => "nightly",
- oneshotTimer: (callback, timeout, thisObj, name) => gTimerScheduleOffset = timeout,
+ oneshotTimer: (callback, timeout, thisObj, name) => {},
});
});
function checkExperimentListsEqual(list, list2) {
Assert.equal(list.length, list2.length, "Lists should have the same length.")
for (let i=0; i<list.length; ++i) {
for (let k of Object.keys(list[i])) {
--- a/browser/experiments/test/xpcshell/test_cacherace.js
+++ b/browser/experiments/test/xpcshell/test_cacherace.js
@@ -6,31 +6,29 @@
Cu.import("resource://testing-common/httpd.js");
Cu.import("resource://gre/modules/Timer.jsm");
const MANIFEST_HANDLER = "manifests/handler";
const SEC_IN_ONE_DAY = 24 * 60 * 60;
const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000;
-var gProfileDir = null;
var gHttpServer = null;
var gHttpRoot = null;
var gDataRoot = null;
var gPolicy = null;
var gManifestObject = null;
var gManifestHandlerURI = null;
function run_test() {
run_next_test();
}
add_task(function* test_setup() {
loadAddonManager();
- gProfileDir = do_get_profile();
yield removeCacheFile();
gHttpServer = new HttpServer();
gHttpServer.start(-1);
let port = gHttpServer.identity.primaryPort;
gHttpRoot = "http://localhost:" + port + "/";
gDataRoot = gHttpRoot + "data/";
gManifestHandlerURI = gHttpRoot + MANIFEST_HANDLER;
--- a/browser/experiments/test/xpcshell/test_conditions.js
+++ b/browser/experiments/test/xpcshell/test_conditions.js
@@ -2,26 +2,20 @@
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
Cu.import("resource:///modules/experiments/Experiments.jsm");
Cu.import("resource://gre/modules/TelemetryController.jsm", this);
-const FILE_MANIFEST = "experiments.manifest";
const SEC_IN_ONE_DAY = 24 * 60 * 60;
-const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000;
-var gProfileDir = null;
-var gHttpServer = null;
-var gHttpRoot = null;
var gPolicy = null;
-
function ManifestEntry(data) {
this.id = EXPERIMENT1_ID;
this.xpiURL = "http://localhost:1/dummy.xpi";
this.xpiHash = EXPERIMENT1_XPI_SHA1;
this.startTime = new Date(2010, 0, 1, 12).getTime() / 1000;
this.endTime = new Date(9001, 0, 1, 12).getTime() / 1000;
this.maxActiveSeconds = SEC_IN_ONE_DAY;
this.appName = ["XPCShell"];
@@ -45,17 +39,17 @@ function applicableFromManifestData(data
}
function run_test() {
run_next_test();
}
add_task(function* test_setup() {
createAppInfo();
- gProfileDir = do_get_profile();
+ do_get_profile();
startAddonManagerOnly();
yield TelemetryController.testSetup();
gPolicy = new Experiments.Policy();
patchPolicy(gPolicy, {
updatechannel: () => "nightly",
locale: () => "en-US",
random: () => 0.5,
--- a/browser/experiments/test/xpcshell/test_disableExperiments.js
+++ b/browser/experiments/test/xpcshell/test_disableExperiments.js
@@ -4,37 +4,34 @@
"use strict";
Cu.import("resource://testing-common/httpd.js");
Cu.import("resource://testing-common/AddonManagerTesting.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Experiments",
"resource:///modules/experiments/Experiments.jsm");
-const FILE_MANIFEST = "experiments.manifest";
const MANIFEST_HANDLER = "manifests/handler";
const SEC_IN_ONE_DAY = 24 * 60 * 60;
const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000;
-var gProfileDir = null;
var gHttpServer = null;
var gHttpRoot = null;
var gDataRoot = null;
var gPolicy = null;
var gManifestObject = null;
var gManifestHandlerURI = null;
function run_test() {
run_next_test();
}
add_task(function* test_setup() {
loadAddonManager();
- gProfileDir = do_get_profile();
gHttpServer = new HttpServer();
gHttpServer.start(-1);
let port = gHttpServer.identity.primaryPort;
gHttpRoot = "http://localhost:" + port + "/";
gDataRoot = gHttpRoot + "data/";
gManifestHandlerURI = gHttpRoot + MANIFEST_HANDLER;
gHttpServer.registerDirectory("/data/", do_get_cwd());
--- a/browser/experiments/test/xpcshell/test_fetch.js
+++ b/browser/experiments/test/xpcshell/test_fetch.js
@@ -3,24 +3,22 @@
"use strict";
Cu.import("resource://testing-common/httpd.js");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
Cu.import("resource:///modules/experiments/Experiments.jsm");
-var gProfileDir = null;
var gHttpServer = null;
var gHttpRoot = null;
var gPolicy = new Experiments.Policy();
function run_test() {
loadAddonManager();
- gProfileDir = do_get_profile();
gHttpServer = new HttpServer();
gHttpServer.start(-1);
let port = gHttpServer.identity.primaryPort;
gHttpRoot = "http://localhost:" + port + "/";
gHttpServer.registerDirectory("/", do_get_cwd());
do_register_cleanup(() => gHttpServer.stop(() => {}));
@@ -63,9 +61,8 @@ add_task(function* test_fetchInvalid() {
Assert.notEqual(ex._experiments.size, 0, "There should be experiments");
Services.prefs.setCharPref(PREF_MANIFEST_URI, gHttpRoot + "invalid.manifest");
yield ex.updateManifest()
Assert.notEqual(ex._experiments.size, 0, "There should still be experiments: fetch failure shouldn't remove them.");
yield promiseRestartManager();
});
-
--- a/browser/experiments/test/xpcshell/test_telemetry.js
+++ b/browser/experiments/test/xpcshell/test_telemetry.js
@@ -3,24 +3,22 @@
"use strict";
Cu.import("resource://testing-common/httpd.js");
Cu.import("resource://gre/modules/TelemetryLog.jsm");
var bsp = Cu.import("resource:///modules/experiments/Experiments.jsm");
-const FILE_MANIFEST = "experiments.manifest";
const MANIFEST_HANDLER = "manifests/handler";
const SEC_IN_ONE_DAY = 24 * 60 * 60;
const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000;
-var gProfileDir = null;
var gHttpServer = null;
var gHttpRoot = null;
var gDataRoot = null;
var gPolicy = null;
var gManifestObject = null;
var gManifestHandlerURI = null;
const TLOG = bsp.TELEMETRY_LOG;
@@ -43,17 +41,16 @@ function checkEvent(event, id, data)
}
function run_test() {
run_next_test();
}
add_task(function* test_setup() {
loadAddonManager();
- gProfileDir = do_get_profile();
gHttpServer = new HttpServer();
gHttpServer.start(-1);
let port = gHttpServer.identity.primaryPort;
gHttpRoot = "http://localhost:" + port + "/";
gDataRoot = gHttpRoot + "data/";
gManifestHandlerURI = gHttpRoot + MANIFEST_HANDLER;
gHttpServer.registerDirectory("/data/", do_get_cwd());
@@ -82,18 +79,16 @@ add_task(function* test_setup() {
});
// Test basic starting and stopping of experiments.
add_task(function* test_telemetryBasics() {
// Check TelemetryLog instead of TelemetrySession.getPayload().log because
// TelemetrySession gets Experiments.instance() and side-effects log entries.
- const OBSERVER_TOPIC = "experiments-changed";
- let observerFireCount = 0;
let expectedLogLength = 0;
// Dates the following tests are based on.
let baseDate = new Date(2014, 5, 1, 12);
let startDate1 = futureDate(baseDate, 50 * MS_IN_ONE_DAY);
let endDate1 = futureDate(baseDate, 100 * MS_IN_ONE_DAY);
let startDate2 = futureDate(baseDate, 150 * MS_IN_ONE_DAY);
@@ -122,31 +117,16 @@ add_task(function* test_telemetryBasics(
endTime: dateToSeconds(endDate2),
maxActiveSeconds: 10 * SEC_IN_ONE_DAY,
appName: ["XPCShell"],
channel: ["nightly"],
},
],
};
- // Data to compare the result of Experiments.getExperiments() against.
-
- let experimentListData = [
- {
- id: EXPERIMENT2_ID,
- name: "Test experiment 2",
- description: "And yet another experiment that experiments experimentally.",
- },
- {
- id: EXPERIMENT1_ID,
- name: EXPERIMENT1_NAME,
- description: "Yet another experiment that experiments experimentally.",
- },
- ];
-
let experiments = new Experiments.Experiments(gPolicy);
// Trigger update, clock set to before any activation.
// Use updateManifest() to provide for coverage of that path.
let now = baseDate;
defineNow(gPolicy, now);
--- a/browser/experiments/test/xpcshell/test_upgrade.js
+++ b/browser/experiments/test/xpcshell/test_upgrade.js
@@ -1,17 +1,14 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
Cu.import("resource:///modules/experiments/Experiments.jsm");
-const SEC_IN_ONE_DAY = 24 * 60 * 60;
-const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000;
-
var cacheData = {
_enabled: true,
_manifestData: {
id: "foobartestid",
xpiURL: "http://example.com/foo.xpi",
xpiHash: "sha256:abcde",
startTime: 0,
endTime: 2000000000,