--- a/toolkit/components/extensions/ExtensionPreferencesManager.jsm
+++ b/toolkit/components/extensions/ExtensionPreferencesManager.jsm
@@ -52,32 +52,42 @@ function initialValueCallback() {
let initialValue = {};
for (let pref of this.prefNames) {
initialValue[pref] = Preferences.get(pref);
}
return initialValue;
}
/**
- * Takes an object of preferenceName:value pairs and either sets or resets the
- * preference to the value.
+ * Takes an item returned by the ExtensionSettingsStore and conditionally sets
+ * preferences based on the item's contents.
*
- * @param {Object} prefsObject
- * An object with one property per preference, which holds the value to
- * store in that preference. If the value is undefined then the
- * preference is reset.
- */
-function setPrefs(prefsObject) {
- for (let pref in prefsObject) {
- if (prefsObject[pref] === undefined) {
- Preferences.reset(pref);
- } else {
- Preferences.set(pref, prefsObject[pref]);
+ * @param {string} name
+ * The name of the setting being processed.
+ * @param {Object|null} item
+ * Either null, or an object with a value property which indicates the
+ * value stored for the setting in the settings store.
+
+ * @returns {Promise}
+ * Resolves to true if the preferences were changed and to false if
+ * the preferences were not changed.
+*/
+async function processItem(name, item) {
+ if (item) {
+ let prefs = item.initialValue || await settingsMap.get(name).setCallback(item.value);
+ for (let pref in prefs) {
+ if (prefs[pref] === undefined) {
+ Preferences.reset(pref);
+ } else {
+ Preferences.set(pref, prefs[pref]);
+ }
}
+ return true;
}
+ return false;
}
this.ExtensionPreferencesManager = {
/**
* Adds a setting to the settingsMap. This is how an API tells the
* preferences manager what its setting object is. The preferences
* manager needs to know this when settings need to be removed
* automatically.
@@ -117,52 +127,119 @@ this.ExtensionPreferencesManager = {
* @returns {Promise}
* Resolves to true if the preferences were changed and to false if
* the preferences were not changed.
*/
async setSetting(extension, name, value) {
let setting = settingsMap.get(name);
let item = await ExtensionSettingsStore.addSetting(
extension, STORE_TYPE, name, value, initialValueCallback.bind(setting));
- if (item) {
- let prefs = await setting.setCallback(item.value);
- setPrefs(prefs);
- return true;
- }
- return false;
+ return await processItem(name, item);
},
/**
- * Indicates that this extension no longer wants to set the given preference.
+ * Indicates that this extension wants to temporarily cede control over the
+ * given setting.
+ *
+ * @param {Extension} extension
+ * The extension for which a preference setting is being removed.
+ * @param {string} name
+ * The unique id of the setting.
+ *
+ * @returns {Promise}
+ * Resolves to true if the preferences were changed and to false if
+ * the preferences were not changed.
+ */
+ async disableSetting(extension, name) {
+ let item = await ExtensionSettingsStore.disable(
+ extension, STORE_TYPE, name);
+ return await processItem(name, item);
+ },
+
+ /**
+ * Enable a setting that has been disabled.
+ *
+ * @param {Extension} extension
+ * The extension for which a setting is being enabled.
+ * @param {string} name
+ * The unique id of the setting.
+ *
+ * @returns {Promise}
+ * Resolves to true if the preferences were changed and to false if
+ * the preferences were not changed.
+ */
+ async enableSetting(extension, name) {
+ let item = await ExtensionSettingsStore.enable(extension, STORE_TYPE, name);
+ return await processItem(name, item);
+ },
+
+ /**
+ * Indicates that this extension no longer wants to set the given setting.
*
* @param {Extension} extension
* The extension for which a preference setting is being removed.
* @param {string} name
* The unique id of the setting.
+ *
+ * @returns {Promise}
+ * Resolves to true if the preferences were changed and to false if
+ * the preferences were not changed.
*/
- async unsetSetting(extension, name) {
+ async removeSetting(extension, name) {
let item = await ExtensionSettingsStore.removeSetting(
extension, STORE_TYPE, name);
- if (item) {
- let prefs = item.initialValue || await settingsMap.get(name).setCallback(item.value);
- setPrefs(prefs);
+ return await processItem(name, item);
+ },
+
+ /**
+ * Disables all previously set settings for an extension. This can be called when
+ * an extension is being disabled, for example.
+ *
+ * @param {Extension} extension
+ * The extension for which all settings are being unset.
+ */
+ async disableAll(extension) {
+ let settings = await ExtensionSettingsStore.getAllForExtension(extension, STORE_TYPE);
+ let disablePromises = [];
+ for (let name of settings) {
+ disablePromises.push(this.disableSetting(extension, name));
}
+ await Promise.all(disablePromises);
},
/**
- * Unsets all previously set settings for an extension. This can be called when
- * an extension is being uninstalled or disabled, for example.
+ * Enables all disabled settings for an extension. This can be called when
+ * an extension has finsihed updating or is being re-enabled, for example.
*
- * @param {Extension} extension The extension for which all settings are being unset.
+ * @param {Extension} extension
+ * The extension for which all settings are being enabled.
*/
- async unsetAll(extension) {
+ async enableAll(extension) {
let settings = await ExtensionSettingsStore.getAllForExtension(extension, STORE_TYPE);
+ let enablePromises = [];
for (let name of settings) {
- await this.unsetSetting(extension, name);
+ enablePromises.push(this.enableSetting(extension, name));
}
+ await Promise.all(enablePromises);
+ },
+
+ /**
+ * Removes all previously set settings for an extension. This can be called when
+ * an extension is being uninstalled, for example.
+ *
+ * @param {Extension} extension
+ * The extension for which all settings are being unset.
+ */
+ async removeAll(extension) {
+ let settings = await ExtensionSettingsStore.getAllForExtension(extension, STORE_TYPE);
+ let removePromises = [];
+ for (let name of settings) {
+ removePromises.push(this.removeSetting(extension, name));
+ }
+ await Promise.all(removePromises);
},
/**
* Return the levelOfControl for a setting / extension combo.
* This queries the levelOfControl from the ExtensionSettingsStore and also
* takes into account whether any of the setting's preferences are locked.
*
* @param {Extension} extension
--- a/toolkit/components/extensions/test/xpcshell/test_ext_extensionPreferencesManager.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_extensionPreferencesManager.js
@@ -66,16 +66,22 @@ ExtensionPreferencesManager.addSetting("
// Set initial values for prefs.
for (let setting in SETTINGS) {
setting = SETTINGS[setting];
for (let i = 0; i < setting.prefNames.length; i++) {
Preferences.set(setting.prefNames[i], setting.initalValues[i]);
}
}
+function checkPrefs(settingObj, value, msg) {
+ for (let pref of settingObj.prefNames) {
+ equal(Preferences.get(pref), settingObj.valueFn(pref, value), msg);
+ }
+}
+
add_task(async function test_preference_manager() {
// Create an array of test framework extension wrappers to install.
let testExtensions = [
ExtensionTestUtils.loadExtension({
useAddonManager: "temporary",
manifest: {},
}),
ExtensionTestUtils.loadExtension({
@@ -92,100 +98,134 @@ add_task(async function test_preference_
// Create an array actual Extension objects which correspond to the
// test framework extension wrappers.
let extensions = testExtensions.map(extension => extension.extension._extension);
for (let setting in SETTINGS) {
let settingObj = SETTINGS[setting];
let newValue1 = "newValue1";
- let levelOfControl = await ExtensionPreferencesManager.getLevelOfControl(extensions[1], setting);
+ let levelOfControl = await ExtensionPreferencesManager.getLevelOfControl(
+ extensions[1], setting);
equal(levelOfControl, "controllable_by_this_extension",
"getLevelOfControl returns correct levelOfControl with no settings set.");
- let settingSet = await ExtensionPreferencesManager.setSetting(extensions[1], setting, newValue1);
- ok(settingSet, "setSetting returns true when the pref(s) have been set.");
- for (let pref of settingObj.prefNames) {
- equal(Preferences.get(pref), settingObj.valueFn(pref, newValue1),
- "setSetting sets the prefs for the first extension.");
- }
+
+ let prefsChanged = await ExtensionPreferencesManager.setSetting(
+ extensions[1], setting, newValue1);
+ ok(prefsChanged, "setSetting returns true when the pref(s) have been set.");
+ checkPrefs(settingObj, newValue1,
+ "setSetting sets the prefs for the first extension.");
levelOfControl = await ExtensionPreferencesManager.getLevelOfControl(extensions[1], setting);
equal(
levelOfControl,
"controlled_by_this_extension",
"getLevelOfControl returns correct levelOfControl when a pref has been set.");
let newValue2 = "newValue2";
- settingSet = await ExtensionPreferencesManager.setSetting(extensions[0], setting, newValue2);
- ok(!settingSet, "setSetting returns false when the pref(s) have not been set.");
- for (let pref of settingObj.prefNames) {
- equal(Preferences.get(pref), settingObj.valueFn(pref, newValue1),
- "setSetting does not set the pref(s) for an earlier extension.");
- }
+ prefsChanged = await ExtensionPreferencesManager.setSetting(extensions[0], setting, newValue2);
+ ok(!prefsChanged, "setSetting returns false when the pref(s) have not been set.");
+ checkPrefs(settingObj, newValue1,
+ "setSetting does not set the pref(s) for an earlier extension.");
+
+ prefsChanged = await ExtensionPreferencesManager.disableSetting(extensions[0], setting);
+ ok(!prefsChanged, "disableSetting returns false when the pref(s) have not been set.");
+ checkPrefs(settingObj, newValue1,
+ "disableSetting does not change the pref(s) for the non-top extension.");
- await ExtensionPreferencesManager.unsetSetting(extensions[0], setting);
- for (let pref of settingObj.prefNames) {
- equal(Preferences.get(pref), settingObj.valueFn(pref, newValue1),
- "unsetSetting does not change the pref(s) for the non-top extension.");
- }
+ prefsChanged = await ExtensionPreferencesManager.enableSetting(extensions[0], setting);
+ ok(!prefsChanged, "enableSetting returns false when the pref(s) have not been set.");
+ checkPrefs(settingObj, newValue1,
+ "enableSetting does not change the pref(s) for the non-top extension.");
+
+ prefsChanged = await ExtensionPreferencesManager.removeSetting(extensions[0], setting);
+ ok(!prefsChanged, "removeSetting returns false when the pref(s) have not been set.");
+ checkPrefs(settingObj, newValue1,
+ "removeSetting does not change the pref(s) for the non-top extension.");
- await ExtensionPreferencesManager.setSetting(extensions[0], setting, newValue2);
- for (let pref of settingObj.prefNames) {
- equal(Preferences.get(pref), settingObj.valueFn(pref, newValue1),
- "setSetting does not set the pref(s) for an earlier extension.");
- }
+ prefsChanged = await ExtensionPreferencesManager.setSetting(extensions[0], setting, newValue2);
+ ok(!prefsChanged, "setSetting returns false when the pref(s) have not been set.");
+ checkPrefs(settingObj, newValue1,
+ "setSetting does not set the pref(s) for an earlier extension.");
+
+ prefsChanged = await ExtensionPreferencesManager.disableSetting(extensions[1], setting);
+ ok(prefsChanged, "disableSetting returns true when the pref(s) have been set.");
+ checkPrefs(settingObj, newValue2,
+ "disableSetting sets the pref(s) to the next value when disabling the top extension.");
- await ExtensionPreferencesManager.unsetSetting(extensions[1], setting);
- for (let pref of settingObj.prefNames) {
- equal(Preferences.get(pref), settingObj.valueFn(pref, newValue2),
- "unsetSetting sets the pref(s) to the next value when removing the top extension.");
- }
+ prefsChanged = await ExtensionPreferencesManager.enableSetting(extensions[1], setting);
+ ok(prefsChanged, "enableSetting returns true when the pref(s) have been set.");
+ checkPrefs(settingObj, newValue1,
+ "enableSetting sets the pref(s) to the previous value(s).");
- await ExtensionPreferencesManager.unsetSetting(extensions[0], setting);
+ prefsChanged = await ExtensionPreferencesManager.removeSetting(extensions[1], setting);
+ ok(prefsChanged, "removeSetting returns true when the pref(s) have been set.");
+ checkPrefs(settingObj, newValue2,
+ "removeSetting sets the pref(s) to the next value when removing the top extension.");
+
+ prefsChanged = await ExtensionPreferencesManager.removeSetting(extensions[0], setting);
+ ok(prefsChanged, "removeSetting returns true when the pref(s) have been set.");
for (let i = 0; i < settingObj.prefNames.length; i++) {
equal(Preferences.get(settingObj.prefNames[i]), settingObj.initalValues[i],
- "unsetSetting sets the pref(s) to the initial value(s) when removing the last extension.");
+ "removeSetting sets the pref(s) to the initial value(s) when removing the last extension.");
}
}
// Tests for unsetAll.
let newValue3 = "newValue3";
for (let setting in SETTINGS) {
let settingObj = SETTINGS[setting];
await ExtensionPreferencesManager.setSetting(extensions[0], setting, newValue3);
- for (let pref of settingObj.prefNames) {
- equal(Preferences.get(pref), settingObj.valueFn(pref, newValue3), `setSetting set the pref for ${pref}.`);
- }
+ checkPrefs(settingObj, newValue3, "setSetting set the pref.");
}
let setSettings = await ExtensionSettingsStore.getAllForExtension(extensions[0], STORE_TYPE);
deepEqual(setSettings, Object.keys(SETTINGS), "Expected settings were set for extension.");
- await ExtensionPreferencesManager.unsetAll(extensions[0]);
+ await ExtensionPreferencesManager.disableAll(extensions[0]);
for (let setting in SETTINGS) {
let settingObj = SETTINGS[setting];
for (let i = 0; i < settingObj.prefNames.length; i++) {
equal(Preferences.get(settingObj.prefNames[i]), settingObj.initalValues[i],
- "unsetAll unset the pref.");
+ "disableAll unset the pref.");
}
}
setSettings = await ExtensionSettingsStore.getAllForExtension(extensions[0], STORE_TYPE);
- deepEqual(setSettings, [], "unsetAll removed all settings.");
+ deepEqual(setSettings, Object.keys(SETTINGS), "disableAll retains the settings.");
+
+ await ExtensionPreferencesManager.enableAll(extensions[0]);
+ for (let setting in SETTINGS) {
+ let settingObj = SETTINGS[setting];
+ checkPrefs(settingObj, newValue3, "enableAll re-set the pref.");
+ }
+
+ await ExtensionPreferencesManager.removeAll(extensions[0]);
+
+ for (let setting in SETTINGS) {
+ let settingObj = SETTINGS[setting];
+ for (let i = 0; i < settingObj.prefNames.length; i++) {
+ equal(Preferences.get(settingObj.prefNames[i]), settingObj.initalValues[i],
+ "removeAll unset the pref.");
+ }
+ }
+
+ setSettings = await ExtensionSettingsStore.getAllForExtension(extensions[0], STORE_TYPE);
+ deepEqual(setSettings, [], "removeAll removed all settings.");
// Test with an uninitialized pref.
let setting = "singlePref";
let settingObj = SETTINGS[setting];
let pref = settingObj.prefNames[0];
let newValue = "newValue";
Preferences.reset(pref);
await ExtensionPreferencesManager.setSetting(extensions[1], setting, newValue);
equal(Preferences.get(pref), settingObj.valueFn(pref, newValue),
"Uninitialized pref is set.");
- await ExtensionPreferencesManager.unsetSetting(extensions[1], setting);
- ok(!Preferences.has(pref), "unsetSetting removed the pref.");
+ await ExtensionPreferencesManager.removeSetting(extensions[1], setting);
+ ok(!Preferences.has(pref), "removeSetting removed the pref.");
// Test levelOfControl with a locked pref.
setting = "multiple_prefs";
let prefToLock = SETTINGS[setting].prefNames[0];
Preferences.lock(prefToLock, 1);
ok(Preferences.locked(prefToLock), `Preference ${prefToLock} is locked.`);
let levelOfControl = await ExtensionPreferencesManager.getLevelOfControl(extensions[1], setting);
equal(