зеркало из https://github.com/mozilla/gecko-dev.git
Bug 975000 - Disable updating and compatibility checking for Experiments; r=Unfocused
Experiment add-ons are installed and updated via the Experiments Manager service. With this change, the Add-ons Manager lets experiment add-ons play by their own rules without interference. --HG-- extra : rebase_source : 4a7c30f8ce36a64f91f9fee49da9061eda568b99
This commit is contained in:
Родитель
0f13ee9fef
Коммит
d5049daf81
|
@ -1376,8 +1376,9 @@ Experiments.ExperimentEntry.prototype = {
|
|||
deferred.reject(new Error(message));
|
||||
};
|
||||
|
||||
let entry = this;
|
||||
let listener = {
|
||||
onDownloadEnded: install => {
|
||||
onDownloadEnded: function (install) {
|
||||
gLogger.trace("ExperimentEntry::_installAddon() - onDownloadEnded for " + this.id);
|
||||
|
||||
if (install.existingAddon) {
|
||||
|
@ -1388,9 +1389,9 @@ Experiments.ExperimentEntry.prototype = {
|
|||
gLogger.error("ExperimentEntry::_installAddon() - onDownloadEnded, wrong addon type");
|
||||
install.cancel();
|
||||
}
|
||||
},
|
||||
}.bind(entry),
|
||||
|
||||
onInstallStarted: install => {
|
||||
onInstallStarted: function (install) {
|
||||
gLogger.trace("ExperimentEntry::_installAddon() - onInstallStarted for " + this.id);
|
||||
|
||||
if (install.existingAddon) {
|
||||
|
@ -1401,9 +1402,9 @@ Experiments.ExperimentEntry.prototype = {
|
|||
gLogger.error("ExperimentEntry::_installAddon() - onInstallStarted, wrong addon type");
|
||||
return false;
|
||||
}
|
||||
},
|
||||
}.bind(entry),
|
||||
|
||||
onInstallEnded: install => {
|
||||
onInstallEnded: function (install) {
|
||||
gLogger.trace("ExperimentEntry::_installAddon() - install ended for " + this.id);
|
||||
this._lastChangedDate = this._policy.now();
|
||||
this._startDate = this._policy.now();
|
||||
|
@ -1419,13 +1420,13 @@ Experiments.ExperimentEntry.prototype = {
|
|||
this._homepageURL = addon.homepageURL || "";
|
||||
|
||||
deferred.resolve();
|
||||
},
|
||||
};
|
||||
}.bind(entry),
|
||||
|
||||
["onDownloadCancelled", "onDownloadFailed", "onInstallCancelled", "onInstallFailed"]
|
||||
.forEach(what => {
|
||||
listener[what] = install => failureHandler(install, what)
|
||||
});
|
||||
onDownloadCancelled: failureHandler.bind(entry),
|
||||
onDownloadFailed: failureHandler.bind(entry),
|
||||
onInstallCancelled: failureHandler.bind(entry),
|
||||
onInstallFailed: failureHandler.bind(entry),
|
||||
};
|
||||
|
||||
install.addListener(listener);
|
||||
install.install();
|
||||
|
|
|
@ -2317,7 +2317,25 @@ this.AddonManagerPrivate = {
|
|||
return {
|
||||
done: () => this.recordSimpleMeasure(aName, Date.now() - startTime)
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper to call update listeners when no update is available.
|
||||
*
|
||||
* This can be used as an implementation for Addon.findUpdates() when
|
||||
* no update mechanism is available.
|
||||
*/
|
||||
callNoUpdateListeners: function (addon, listener, reason, appVersion, platformVersion) {
|
||||
if ("onNoCompatibilityUpdateAvailable" in listener) {
|
||||
safeCall(listener.onNoCompatibilityUpdateAvailable, addon);
|
||||
}
|
||||
if ("onNoUpdateAvailable" in listener) {
|
||||
safeCall(listener.onNoUpdateAvailable, addon);
|
||||
}
|
||||
if ("onUpdateFinished" in listener) {
|
||||
safeCall(listener.onUpdateFinished, addon);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -508,12 +508,7 @@ function AddonWrapper(aTheme) {
|
|||
};
|
||||
|
||||
this.findUpdates = function AddonWrapper_findUpdates(listener, reason, appVersion, platformVersion) {
|
||||
if ("onNoCompatibilityUpdateAvailable" in listener)
|
||||
listener.onNoCompatibilityUpdateAvailable(this);
|
||||
if ("onNoUpdateAvailable" in listener)
|
||||
listener.onNoUpdateAvailable(this);
|
||||
if ("onUpdateFinished" in listener)
|
||||
listener.onUpdateFinished(this);
|
||||
AddonManagerPrivate.callNoUpdateListeners(this, listener, reason, appVersion, platformVersion);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -915,6 +915,17 @@ function loadManifestFromRDF(aUri, aStream) {
|
|||
|
||||
addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT;
|
||||
|
||||
// Experiments are managed and updated through an external "experiments
|
||||
// manager." So disable some built-in mechanisms.
|
||||
if (addon.type == "experiment") {
|
||||
addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE;
|
||||
addon.updateURL = null;
|
||||
addon.updateKey = null;
|
||||
|
||||
addon.targetApplications = [];
|
||||
addon.targetPlatforms = [];
|
||||
}
|
||||
|
||||
// Load the storage service before NSS (nsIRandomGenerator),
|
||||
// to avoid a SQLite initialization error (bug 717904).
|
||||
let storage = Services.storage;
|
||||
|
@ -6014,6 +6025,17 @@ AddonInternal.prototype = {
|
|||
},
|
||||
|
||||
isCompatibleWith: function AddonInternal_isCompatibleWith(aAppVersion, aPlatformVersion) {
|
||||
// Experiments are installed through an external mechanism that
|
||||
// limits target audience to compatible clients. We trust it knows what
|
||||
// it's doing and skip compatibility checks.
|
||||
//
|
||||
// This decision does forfeit defense in depth. If the experiments system
|
||||
// is ever wrong about targeting an add-on to a specific application
|
||||
// or platform, the client will likely see errors.
|
||||
if (this.type == "experiment") {
|
||||
return true;
|
||||
}
|
||||
|
||||
let app = this.matchingTargetApplication;
|
||||
if (!app)
|
||||
return false;
|
||||
|
@ -6398,6 +6420,11 @@ function AddonWrapper(aAddon) {
|
|||
return aAddon.applyBackgroundUpdates;
|
||||
});
|
||||
this.__defineSetter__("applyBackgroundUpdates", function AddonWrapper_applyBackgroundUpdatesSetter(val) {
|
||||
if (this.type == "experiment") {
|
||||
logger.warn("Setting applyBackgroundUpdates on an experiment is not supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (val != AddonManager.AUTOUPDATE_DEFAULT &&
|
||||
val != AddonManager.AUTOUPDATE_DISABLE &&
|
||||
val != AddonManager.AUTOUPDATE_ENABLE) {
|
||||
|
@ -6498,22 +6525,33 @@ function AddonWrapper(aAddon) {
|
|||
if (!(aAddon.inDatabase))
|
||||
return permissions;
|
||||
|
||||
// Experiments can only be uninstalled. An uninstall reflects the user
|
||||
// intent of "disable this experiment." This is partially managed by the
|
||||
// experiments manager.
|
||||
if (aAddon.type == "experiment") {
|
||||
return AddonManager.PERM_CAN_UNINSTALL;
|
||||
}
|
||||
|
||||
if (!aAddon.appDisabled) {
|
||||
if (this.userDisabled)
|
||||
if (this.userDisabled) {
|
||||
permissions |= AddonManager.PERM_CAN_ENABLE;
|
||||
else if (aAddon.type != "theme")
|
||||
}
|
||||
else if (aAddon.type != "theme") {
|
||||
permissions |= AddonManager.PERM_CAN_DISABLE;
|
||||
}
|
||||
}
|
||||
|
||||
// Add-ons that are in locked install locations, or are pending uninstall
|
||||
// cannot be upgraded or uninstalled
|
||||
if (!aAddon._installLocation.locked && !aAddon.pendingUninstall) {
|
||||
// Add-ons that are installed by a file link cannot be upgraded
|
||||
if (!aAddon._installLocation.isLinkedAddon(aAddon.id))
|
||||
if (!aAddon._installLocation.isLinkedAddon(aAddon.id)) {
|
||||
permissions |= AddonManager.PERM_CAN_UPGRADE;
|
||||
}
|
||||
|
||||
permissions |= AddonManager.PERM_CAN_UNINSTALL;
|
||||
}
|
||||
|
||||
return permissions;
|
||||
});
|
||||
|
||||
|
@ -6595,6 +6633,14 @@ function AddonWrapper(aAddon) {
|
|||
};
|
||||
|
||||
this.findUpdates = function AddonWrapper_findUpdates(aListener, aReason, aAppVersion, aPlatformVersion) {
|
||||
// Short-circuit updates for experiments because updates are handled
|
||||
// through the Experiments Manager.
|
||||
if (this.type == "experiment") {
|
||||
AddonManagerPrivate.callNoUpdateListeners(this, aListener, aReason,
|
||||
aAppVersion, aPlatformVersion);
|
||||
return;
|
||||
}
|
||||
|
||||
new UpdateChecker(aAddon, aListener, aReason, aAppVersion, aPlatformVersion);
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>experiment1@tests.mozilla.org</em:id>
|
||||
<em:version>1.0</em:version>
|
||||
<em:type>128</em:type>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
|
||||
<!-- Front End MetaData -->
|
||||
<em:name>Test Experiment 1</em:name>
|
||||
<em:description>Test Description</em:description>
|
||||
|
||||
</Description>
|
||||
</RDF>
|
|
@ -50,9 +50,7 @@ add_test(function testActiveExperiment() {
|
|||
install_addon("addons/browser_experiment1.xpi", (addon) => {
|
||||
gInstalledAddons.push(addon);
|
||||
|
||||
// This may change if we remove compatibility checking from experiments.
|
||||
// Putting this check here so a test fails if preconditions change.
|
||||
Assert.equal(addon.isActive, false, "Add-on is not active.");
|
||||
Assert.ok(addon.isActive, "Add-on is active.");
|
||||
|
||||
Assert.ok(gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab visible.");
|
||||
|
||||
|
@ -133,3 +131,19 @@ add_test(function testOpenPreferences() {
|
|||
EventUtils.synthesizeMouseAtCenter(btn, {}, gManagerWindow);
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function testButtonPresence() {
|
||||
gCategoryUtilities.openType("experiment", (win) => {
|
||||
let item = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org");
|
||||
Assert.ok(item, "Got add-on element.");
|
||||
|
||||
let el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn");
|
||||
// Corresponds to the uninstall permission.
|
||||
is_element_visible(el, "Remove button is visible.");
|
||||
// Corresponds to lack of disable permission.
|
||||
el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "disable-btn");
|
||||
is_element_hidden(el, "Disable button not visible.");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test() {
|
||||
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
|
||||
startupManager();
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_test(function test_experiment() {
|
||||
AddonManager.getInstallForFile(do_get_addon("test_experiment1"), (install) => {
|
||||
completeAllInstalls([install], () => {
|
||||
AddonManager.getAddonByID("experiment1@tests.mozilla.org", (addon) => {
|
||||
Assert.ok(addon, "Addon is found.");
|
||||
|
||||
Assert.ok(addon.isActive, "Add-on is active.");
|
||||
Assert.equal(addon.updateURL, null, "No updateURL for experiments.");
|
||||
Assert.equal(addon.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE,
|
||||
"Background updates are disabled.");
|
||||
Assert.equal(addon.permissions, AddonManager.PERM_CAN_UNINSTALL,
|
||||
"Permissions are minimal.");
|
||||
|
||||
// Setting applyBackgroundUpdates should not work.
|
||||
addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_ENABLE;
|
||||
Assert.equal(addon.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE,
|
||||
"Setting applyBackgroundUpdates shouldn't do anything.");
|
||||
|
||||
let noCompatibleCalled = false;
|
||||
let noUpdateCalled = false;
|
||||
let finishedCalled = false;
|
||||
|
||||
let listener = {
|
||||
onNoCompatibilityUpdateAvailable: () => { noCompatibleCalled = true; },
|
||||
onNoUpdateAvailable: () => { noUpdateCalled = true; },
|
||||
onUpdateFinished: () => { finishedCalled = true; },
|
||||
};
|
||||
|
||||
addon.findUpdates(listener, "testing", null, null);
|
||||
Assert.ok(noCompatibleCalled, "Listener called.");
|
||||
Assert.ok(noUpdateCalled, "Listener called.");
|
||||
Assert.ok(finishedCalled, "Listener called.");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -17,7 +17,8 @@ const IGNORE_PRIVATE = ["AddonAuthor", "AddonCompatibilityOverride",
|
|||
"addStartupChange", "removeStartupChange",
|
||||
"recordTimestamp", "recordSimpleMeasure",
|
||||
"recordException", "getSimpleMeasures", "simpleTimer",
|
||||
"setTelemetryDetails", "getTelemetryDetails"];
|
||||
"setTelemetryDetails", "getTelemetryDetails",
|
||||
"callNoUpdateListeners"];
|
||||
|
||||
function test_functions() {
|
||||
for (let prop in AddonManager) {
|
||||
|
|
|
@ -163,6 +163,7 @@ fail-if = os == "android"
|
|||
# Bug 676992: test consistently hangs on Android
|
||||
skip-if = os == "android"
|
||||
[test_error.js]
|
||||
[test_experiment.js]
|
||||
[test_filepointer.js]
|
||||
# Bug 676992: test consistently hangs on Android
|
||||
skip-if = os == "android"
|
||||
|
|
Загрузка…
Ссылка в новой задаче