Bug 992258 - Trigger a refresh of the experiments view in the addon manager when experiments change. r=irving

This commit is contained in:
Georg Fritzsche 2014-05-06 12:18:10 +02:00
parent c8c5cf6767
commit ec0e0f4b01
3 changed files with 84 additions and 33 deletions

View File

@ -49,7 +49,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "gCrashReporter",
"nsICrashReporter");
const FILE_CACHE = "experiments.json";
const OBSERVER_TOPIC = "experiments-changed";
const EXPERIMENTS_CHANGED_TOPIC = "experiments-changed";
const MANIFEST_VERSION = 1;
const CACHE_VERSION = 1;
@ -114,6 +114,7 @@ let gLogAppenderDump = null;
let gPolicyCounter = 0;
let gExperimentsCounter = 0;
let gExperimentEntryCounter = 0;
let gPreviousProviderCounter = 0;
// Tracks active AddonInstall we know about so we can deny external
// installs.
@ -464,7 +465,7 @@ Experiments.Experiments.prototype = {
this._log.info("Completed uninitialization.");
}),
_registerWithAddonManager: function () {
_registerWithAddonManager: function (previousExperimentsProvider) {
this._log.trace("Registering instance with Addon Manager.");
AddonManager.addAddonListener(this);
@ -474,15 +475,15 @@ Experiments.Experiments.prototype = {
// The properties of this AddonType should be kept in sync with the
// experiment AddonType registered in XPIProvider.
this._log.trace("Registering previous experiment add-on provider.");
gAddonProvider = new Experiments.PreviousExperimentProvider(this, [
gAddonProvider = previousExperimentsProvider || new Experiments.PreviousExperimentProvider(this);
AddonManagerPrivate.registerProvider(gAddonProvider, [
new AddonManagerPrivate.AddonType("experiment",
URI_EXTENSION_STRINGS,
STRING_TYPE_NAME,
AddonManager.VIEW_TYPE_LIST,
11000,
AddonManager.TYPE_UI_HIDE_EMPTY),
]);
AddonManagerPrivate.registerProvider(gAddonProvider);
]);
}
},
@ -500,6 +501,15 @@ Experiments.Experiments.prototype = {
AddonManager.removeAddonListener(this);
},
/*
* Change the PreviousExperimentsProvider that this instance uses.
* For testing only.
*/
_setPreviousExperimentsProvider: function (provider) {
this._unregisterWithAddonManager();
this._registerWithAddonManager(provider);
},
/**
* Throws an exception if we've already shut down.
*/
@ -1151,7 +1161,7 @@ Experiments.Experiments.prototype = {
gPrefs.set(PREF_ACTIVE_EXPERIMENT, activeExperiment != null);
if (activeChanged) {
Services.obs.notifyObservers(null, OBSERVER_TOPIC, null);
Services.obs.notifyObservers(null, EXPERIMENTS_CHANGED_TOPIC, null);
}
if ("@mozilla.org/toolkit/crash-reporter;1" in Cc && activeExperiment) {
@ -1970,7 +1980,7 @@ ExperimentsProvider.prototype = Object.freeze({
],
_OBSERVERS: [
OBSERVER_TOPIC,
EXPERIMENTS_CHANGED_TOPIC,
],
postInit: function () {
@ -1991,7 +2001,7 @@ ExperimentsProvider.prototype = Object.freeze({
observe: function (subject, topic, data) {
switch (topic) {
case OBSERVER_TOPIC:
case EXPERIMENTS_CHANGED_TOPIC:
this.recordLastActiveExperiment();
break;
}
@ -2040,26 +2050,40 @@ ExperimentsProvider.prototype = Object.freeze({
*/
this.Experiments.PreviousExperimentProvider = function (experiments) {
this._experiments = experiments;
this._experimentList = [];
this._log = Log.repository.getLoggerWithMessagePrefix(
"Browser.Experiments.Experiments",
"PreviousExperimentProvider #" + gPreviousProviderCounter++ + "::");
}
this.Experiments.PreviousExperimentProvider.prototype = Object.freeze({
startup: function () {},
shutdown: function () {},
startup: function () {
this._log.trace("startup()");
Services.obs.addObserver(this, EXPERIMENTS_CHANGED_TOPIC, false);
},
shutdown: function () {
this._log.trace("shutdown()");
Services.obs.removeObserver(this, EXPERIMENTS_CHANGED_TOPIC);
},
observe: function (subject, topic, data) {
switch (topic) {
case EXPERIMENTS_CHANGED_TOPIC:
this._updateExperimentList();
break;
}
},
getAddonByID: function (id, cb) {
this._getPreviousExperiments().then((experiments) => {
for (let experiment of experiments) {
if (experiment.id == id) {
cb(new PreviousExperimentAddon(experiment));
return;
}
for (let experiment of this._experimentList) {
if (experiment.id == id) {
cb(new PreviousExperimentAddon(experiment));
return;
}
}
cb(null);
},
(error) => {
cb(null);
});
cb(null);
},
getAddonsByTypes: function (types, cb) {
@ -2068,17 +2092,45 @@ this.Experiments.PreviousExperimentProvider.prototype = Object.freeze({
return;
}
this._getPreviousExperiments().then((experiments) => {
cb([new PreviousExperimentAddon(e) for (e of experiments)]);
},
(error) => {
cb([]);
});
cb([new PreviousExperimentAddon(e) for (e of this._experimentList)]);
},
_getPreviousExperiments: function () {
_updateExperimentList: function () {
return this._experiments.getExperiments().then((experiments) => {
return Promise.resolve([e for (e of experiments) if (!e.active)]);
let list = [e for (e of experiments) if (!e.active)];
let newMap = new Map([[e.id, e] for (e of list)]);
let oldMap = new Map([[e.id, e] for (e of this._experimentList)]);
let added = [e.id for (e of list) if (!oldMap.has(e.id))];
let removed = [e.id for (e of this._experimentList) if (!newMap.has(e.id))];
for (let id of added) {
this._log.trace("updateExperimentList() - adding " + id);
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);
}
this._experimentList = list;
for (let id of added) {
let wrapper = new PreviousExperimentAddon(newMap.get(id));
AddonManagerPrivate.callAddonListeners("onInstalled", wrapper);
}
for (let id of removed) {
let wrapper = new PreviousExperimentAddon(oldMap.get(id));
AddonManagerPrivate.callAddonListeners("onUninstalled", wrapper);
}
return this._experimentList;
});
},
});

View File

@ -44,6 +44,8 @@ add_task(function* test_provider_basic() {
let e = Experiments.instance();
let provider = new Experiments.PreviousExperimentProvider(e);
e._setPreviousExperimentsProvider(provider);
let deferred = Promise.defer();
provider.getAddonsByTypes(["experiment"], (addons) => {
deferred.resolve(addons);
@ -124,6 +126,7 @@ add_task(function* test_active_and_previous() {
// Building on the previous test, activate experiment 2.
let e = Experiments.instance();
let provider = new Experiments.PreviousExperimentProvider(e);
e._setPreviousExperimentsProvider(provider);
gManifestObject = {
version: 1,

View File

@ -284,12 +284,8 @@ add_task(function testDeactivateExperiment() {
Assert.equal(addons[0].id, "experiment-1", "Add-on ID matches expected.");
// Verify the UI looks sane.
// TODO remove the pane cycle once the UI refreshes automatically.
yield gCategoryUtilities.openType("extension");
Assert.ok(gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab visible.");
yield gCategoryUtilities.openType("experiment");
let item = get_addon_element(gManagerWindow, "experiment-1");
Assert.ok(item, "Got add-on element.");
Assert.ok(!item.active, "Element should not be active.");