Bug 802434 - Support resetting preferences when disabling blocklisted add-ons. r=Unfocused

This commit is contained in:
Sachin Hosmani 2013-09-14 22:57:09 +05:30
parent adb59720b0
commit a29d503c6f
4 changed files with 238 additions and 9 deletions

View File

@ -371,6 +371,17 @@ Blocklist.prototype = {
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
},
/**
* Returns the set of prefs of the add-on stored in the blocklist file
* (probably to revert them on disabling).
* @param id
* ID of the add-on.
*/
_getAddonPrefs: function Blocklist_getAddonPrefs(id) {
let entry = this._findMatchingAddonEntry(this._addonEntries, id);
return entry.prefs.slice(0);
},
_findMatchingAddonEntry: function Blocklist_findMatchingAddonEntry(aAddonEntries,
aId) {
for (let entry of aAddonEntries) {
@ -602,6 +613,10 @@ Blocklist.prototype = {
# <blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
# <emItems>
# <emItem id="item_1@domain" blockID="i1">
# <prefs>
# <pref>accessibility.accesskeycausesactivation</pref>
# <pref>accessibility.blockautorefresh</pref>
# </prefs>
# <versionRange minVersion="1.0" maxVersion="2.0.*">
# <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
# <versionRange minVersion="1.5" maxVersion="1.5.*"/>
@ -721,23 +736,33 @@ Blocklist.prototype = {
let blockEntry = {
id: null,
versions: [],
prefs: [],
blockID: null
};
var versionNodes = blocklistElement.childNodes;
var childNodes = blocklistElement.childNodes;
var id = blocklistElement.getAttribute("id");
// Add-on IDs cannot contain '/', so an ID starting with '/' must be a regex
if (id.startsWith("/"))
id = parseRegExp(id);
blockEntry.id = id;
for (var x = 0; x < versionNodes.length; ++x) {
var versionRangeElement = versionNodes.item(x);
if (!(versionRangeElement instanceof Ci.nsIDOMElement) ||
versionRangeElement.localName != "versionRange")
for (let x = 0; x < childNodes.length; x++) {
var childElement = childNodes.item(x);
if (!(childElement instanceof Ci.nsIDOMElement))
continue;
blockEntry.versions.push(new BlocklistItemData(versionRangeElement));
if (childElement.localName === "prefs") {
let prefElements = childElement.childNodes;
for (let i = 0; i < prefElements.length; i++) {
let prefElement = prefElements.item(i);
if (!(prefElement instanceof Ci.nsIDOMElement) ||
prefElement.localName !== "pref")
continue;
blockEntry.prefs.push(prefElement.textContent);
}
}
else if (childElement.localName === "versionRange")
blockEntry.versions.push(new BlocklistItemData(childElement));
}
// if only the extension ID is specified block all versions of the
// extension for the current application.
@ -891,8 +916,13 @@ Blocklist.prototype = {
_blocklistUpdated: function Blocklist_blocklistUpdated(oldAddonEntries, oldPluginEntries) {
var addonList = [];
// A helper function that reverts the prefs passed to default values.
function resetPrefs(prefs) {
for (let pref of prefs)
gPref.clearUserPref(pref);
}
var self = this;
const types = ["extension", "theme", "locale", "dictionary", "service"]
const types = ["extension", "theme", "locale", "dictionary", "service"];
AddonManager.getAddonsByTypes(types, function blocklistUpdated_getAddonsByTypes(addons) {
for (let addon of addons) {
@ -909,6 +939,12 @@ Blocklist.prototype = {
if (state == oldState)
continue;
if (state === Ci.nsIBlocklistService.STATE_BLOCKED) {
// It's a hard block. We must reset certain preferences.
let prefs = self._getAddonPrefs(addon.id);
resetPrefs(prefs);
}
// Ensure that softDisabled is false if the add-on is not soft blocked
if (state != Ci.nsIBlocklistService.STATE_SOFTBLOCKED)
addon.softDisabled = false;
@ -1016,8 +1052,13 @@ Blocklist.prototype = {
if (addon.item instanceof Ci.nsIPluginTag)
addon.item.enabledState = Ci.nsIPluginTag.STATE_DISABLED;
else
else {
// This add-on is softblocked.
addon.item.softDisabled = true;
// We must revert certain prefs.
let prefs = self._getAddonPrefs(addon.item.id);
resetPrefs(prefs);
}
}
if (args.restart)

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
<emItems>
<emItem id="block1@tests.mozilla.org">
<prefs>
<pref>test.blocklist.pref1</pref>
<pref>test.blocklist.pref2</pref>
</prefs>
<versionRange severity="1">
<targetApplication id="xpcshell@tests.mozilla.org">
<versionRange minVersion="1" maxVersion="2.*"/>
</targetApplication>
</versionRange>
</emItem>
<emItem id="block2@tests.mozilla.org">
<prefs>
<pref>test.blocklist.pref3</pref>
<pref>test.blocklist.pref4</pref>
</prefs>
<versionRange severity="3">
<targetApplication id="xpcshell@tests.mozilla.org">
<versionRange minVersion="1" maxVersion="2.*"/>
</targetApplication>
</versionRange>
</emItem>
</emItems>
</blocklist>

View File

@ -0,0 +1,159 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests resetting of preferences in blocklist entry when an add-on is blocked.
// See bug 802434.
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul";
XPCOMUtils.defineLazyGetter(this, "gPref", function bls_gPref() {
return Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).
QueryInterface(Ci.nsIPrefBranch);
});
Cu.import("resource://testing-common/httpd.js");
var testserver = new HttpServer();
testserver.start(-1);
gPort = testserver.identity.primaryPort;
// register static files with server and interpolate port numbers in them
mapFile("/data/test_blocklist_prefs_1.xml", testserver);
const profileDir = gProfD.clone();
profileDir.append("extensions");
// A window watcher to handle the blocklist UI.
// Don't need the full interface, attempts to call other methods will just
// throw which is just fine
var WindowWatcher = {
openWindow: function(parent, url, name, features, arguments) {
// Should be called to list the newly blocklisted items
do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG);
// Simulate auto-disabling any softblocks
var list = arguments.wrappedJSObject.list;
list.forEach(function(aItem) {
if (!aItem.blocked)
aItem.disable = true;
});
//run the code after the blocklist is closed
Services.obs.notifyObservers(null, "addon-blocklist-closed", null);
},
QueryInterface: function(iid) {
if (iid.equals(Ci.nsIWindowWatcher)
|| iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
var WindowWatcherFactory = {
createInstance: function createInstance(outer, iid) {
if (outer != null)
throw Cr.NS_ERROR_NO_AGGREGATION;
return WindowWatcher.QueryInterface(iid);
}
};
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"),
"Fake Window Watcher",
"@mozilla.org/embedcomp/window-watcher;1",
WindowWatcherFactory);
function load_blocklist(aFile, aCallback) {
Services.obs.addObserver(function() {
Services.obs.removeObserver(arguments.callee, "blocklist-updated");
do_execute_soon(aCallback);
}, "blocklist-updated", false);
Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" +
gPort + "/data/" + aFile);
var blocklist = Cc["@mozilla.org/extensions/blocklist;1"].
getService(Ci.nsITimerCallback);
blocklist.notify(null);
}
function end_test() {
testserver.stop(do_test_finished);
}
function run_test() {
do_test_pending();
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1");
// Add 2 extensions
writeInstallRDFForExtension({
id: "block1@tests.mozilla.org",
version: "1.0",
name: "Blocked add-on-1 with to-be-reset prefs",
targetApplications: [{
id: "xpcshell@tests.mozilla.org",
minVersion: "1",
maxVersion: "3"
}]
}, profileDir);
writeInstallRDFForExtension({
id: "block2@tests.mozilla.org",
version: "1.0",
name: "Blocked add-on-2 with to-be-reset prefs",
targetApplications: [{
id: "xpcshell@tests.mozilla.org",
minVersion: "1",
maxVersion: "3"
}]
}, profileDir);
// Pre-set the preferences that we expect to get reset.
gPref.setIntPref("test.blocklist.pref1", 15);
gPref.setIntPref("test.blocklist.pref2", 15);
gPref.setBoolPref("test.blocklist.pref3", true);
gPref.setBoolPref("test.blocklist.pref4", true);
startupManager();
// Before blocklist is loaded.
AddonManager.getAddonsByIDs(["block1@tests.mozilla.org",
"block2@tests.mozilla.org"], function([a1, a2]) {
do_check_eq(a1.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED);
do_check_eq(a2.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED);
do_check_eq(gPref.getIntPref("test.blocklist.pref1"), 15);
do_check_eq(gPref.getIntPref("test.blocklist.pref2"), 15);
do_check_eq(gPref.getBoolPref("test.blocklist.pref3"), true);
do_check_eq(gPref.getBoolPref("test.blocklist.pref4"), true);
run_test_1();
});
}
function run_test_1() {
load_blocklist("test_blocklist_prefs_1.xml", function() {
restartManager();
// Blocklist changes should have applied and the prefs must be reset.
AddonManager.getAddonsByIDs(["block1@tests.mozilla.org",
"block2@tests.mozilla.org"], function([a1, a2]) {
do_check_neq(a1, null);
do_check_eq(a1.blocklistState, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
do_check_neq(a2, null);
do_check_eq(a2.blocklistState, Ci.nsIBlocklistService.STATE_BLOCKED);
// All these prefs must be reset to defaults.
do_check_eq(gPref.prefHasUserValue("test.blocklist.pref1"), false);
do_check_eq(gPref.prefHasUserValue("test.blocklist.pref2"), false);
do_check_eq(gPref.prefHasUserValue("test.blocklist.pref3"), false);
do_check_eq(gPref.prefHasUserValue("test.blocklist.pref4"), false);
end_test();
});
});
}

View File

@ -19,6 +19,7 @@ skip-if = os == "android"
[test_bad_json.js]
[test_badschema.js]
[test_blocklistchange.js]
[test_blocklist_prefs.js]
# Bug 676992: test consistently hangs on Android
skip-if = os == "android"
[test_blocklist_regexp.js]