summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_extensionPreferencesManager.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/extensions/test/xpcshell/test_ext_extensionPreferencesManager.js')
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_extensionPreferencesManager.js877
1 files changed, 877 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_extensionPreferencesManager.js b/toolkit/components/extensions/test/xpcshell/test_ext_extensionPreferencesManager.js
new file mode 100644
index 0000000000..2f6e3dbe14
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_extensionPreferencesManager.js
@@ -0,0 +1,877 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ ExtensionPreferencesManager:
+ "resource://gre/modules/ExtensionPreferencesManager.sys.mjs",
+ ExtensionSettingsStore:
+ "resource://gre/modules/ExtensionSettingsStore.sys.mjs",
+ Preferences: "resource://gre/modules/Preferences.sys.mjs",
+});
+
+var { PromiseUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/PromiseUtils.sys.mjs"
+);
+
+const { createAppInfo, promiseShutdownManager, promiseStartupManager } =
+ AddonTestUtils;
+
+AddonTestUtils.init(this);
+
+createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42");
+
+let lastSetPref;
+
+const STORE_TYPE = "prefs";
+
+// Test settings to use with the preferences manager.
+const SETTINGS = {
+ multiple_prefs: {
+ prefNames: ["my.pref.1", "my.pref.2", "my.pref.3"],
+
+ initalValues: ["value1", "value2", "value3"],
+
+ valueFn(pref, value) {
+ return `${pref}-${value}`;
+ },
+
+ setCallback(value) {
+ let prefs = {};
+ for (let pref of this.prefNames) {
+ prefs[pref] = this.valueFn(pref, value);
+ }
+ return prefs;
+ },
+ },
+
+ singlePref: {
+ prefNames: ["my.single.pref"],
+
+ initalValues: ["value1"],
+
+ onPrefsChanged(item) {
+ lastSetPref = item;
+ },
+
+ valueFn(pref, value) {
+ return value;
+ },
+
+ setCallback(value) {
+ return { [this.prefNames[0]]: this.valueFn(null, value) };
+ },
+ },
+};
+
+ExtensionPreferencesManager.addSetting(
+ "multiple_prefs",
+ SETTINGS.multiple_prefs
+);
+ExtensionPreferencesManager.addSetting("singlePref", SETTINGS.singlePref);
+
+// 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);
+ }
+}
+
+function checkOnPrefsChanged(setting, value, msg) {
+ if (value) {
+ deepEqual(lastSetPref, value, msg);
+ lastSetPref = null;
+ } else {
+ ok(!lastSetPref, msg);
+ }
+}
+
+add_task(async function test_preference_manager() {
+ await promiseStartupManager();
+
+ // Create an array of test framework extension wrappers to install.
+ let testExtensions = [
+ ExtensionTestUtils.loadExtension({
+ useAddonManager: "temporary",
+ manifest: {},
+ }),
+ ExtensionTestUtils.loadExtension({
+ useAddonManager: "temporary",
+ manifest: {},
+ }),
+ ];
+
+ for (let extension of testExtensions) {
+ await extension.startup();
+ }
+
+ // Create an array actual Extension objects which correspond to the
+ // test framework extension wrappers.
+ let extensions = testExtensions.map(extension => extension.extension);
+
+ for (let setting in SETTINGS) {
+ let settingObj = SETTINGS[setting];
+ let newValue1 = "newValue1";
+ let levelOfControl = await ExtensionPreferencesManager.getLevelOfControl(
+ extensions[1].id,
+ setting
+ );
+ if (settingObj.onPrefsChanged) {
+ checkOnPrefsChanged(
+ setting,
+ null,
+ "onPrefsChanged has not been called yet"
+ );
+ }
+ equal(
+ levelOfControl,
+ "controllable_by_this_extension",
+ "getLevelOfControl returns correct levelOfControl with no settings set."
+ );
+
+ let prefsChanged = await ExtensionPreferencesManager.setSetting(
+ extensions[1].id,
+ 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."
+ );
+ if (settingObj.onPrefsChanged) {
+ checkOnPrefsChanged(
+ setting,
+ { id: extensions[1].id, value: newValue1, key: setting },
+ "onPrefsChanged is called when pref changes"
+ );
+ }
+ levelOfControl = await ExtensionPreferencesManager.getLevelOfControl(
+ extensions[1].id,
+ setting
+ );
+ equal(
+ levelOfControl,
+ "controlled_by_this_extension",
+ "getLevelOfControl returns correct levelOfControl when a pref has been set."
+ );
+
+ let checkSetting = await ExtensionPreferencesManager.getSetting(setting);
+ equal(
+ checkSetting.value,
+ newValue1,
+ "getSetting returns the expected value."
+ );
+
+ let newValue2 = "newValue2";
+ prefsChanged = await ExtensionPreferencesManager.setSetting(
+ extensions[0].id,
+ 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."
+ );
+ if (settingObj.onPrefsChanged) {
+ checkOnPrefsChanged(
+ setting,
+ null,
+ "onPrefsChanged isn't called without control change"
+ );
+ }
+
+ prefsChanged = await ExtensionPreferencesManager.disableSetting(
+ extensions[0].id,
+ 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."
+ );
+ if (settingObj.onPrefsChanged) {
+ checkOnPrefsChanged(
+ setting,
+ null,
+ "onPrefsChanged isn't called without control change on disable"
+ );
+ }
+
+ prefsChanged = await ExtensionPreferencesManager.enableSetting(
+ extensions[0].id,
+ 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."
+ );
+ if (settingObj.onPrefsChanged) {
+ checkOnPrefsChanged(
+ setting,
+ null,
+ "onPrefsChanged isn't called without control change on enable"
+ );
+ }
+
+ prefsChanged = await ExtensionPreferencesManager.removeSetting(
+ extensions[0].id,
+ 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."
+ );
+ if (settingObj.onPrefsChanged) {
+ checkOnPrefsChanged(
+ setting,
+ null,
+ "onPrefsChanged isn't called without control change on remove"
+ );
+ }
+
+ prefsChanged = await ExtensionPreferencesManager.setSetting(
+ extensions[0].id,
+ 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."
+ );
+ if (settingObj.onPrefsChanged) {
+ checkOnPrefsChanged(
+ setting,
+ null,
+ "onPrefsChanged isn't called without control change again"
+ );
+ }
+
+ prefsChanged = await ExtensionPreferencesManager.disableSetting(
+ extensions[1].id,
+ 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."
+ );
+ if (settingObj.onPrefsChanged) {
+ checkOnPrefsChanged(
+ setting,
+ { id: extensions[0].id, key: setting, value: newValue2 },
+ "onPrefsChanged is called when control changes on disable"
+ );
+ }
+
+ prefsChanged = await ExtensionPreferencesManager.enableSetting(
+ extensions[1].id,
+ 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)."
+ );
+ if (settingObj.onPrefsChanged) {
+ checkOnPrefsChanged(
+ setting,
+ { id: extensions[1].id, key: setting, value: newValue1 },
+ "onPrefsChanged is called when control changes on enable"
+ );
+ }
+
+ prefsChanged = await ExtensionPreferencesManager.removeSetting(
+ extensions[1].id,
+ 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."
+ );
+ if (settingObj.onPrefsChanged) {
+ checkOnPrefsChanged(
+ setting,
+ { id: extensions[0].id, key: setting, value: newValue2 },
+ "onPrefsChanged is called when control changes on remove"
+ );
+ }
+
+ prefsChanged = await ExtensionPreferencesManager.removeSetting(
+ extensions[0].id,
+ setting
+ );
+ ok(
+ prefsChanged,
+ "removeSetting returns true when the pref(s) have been set."
+ );
+ if (settingObj.onPrefsChanged) {
+ checkOnPrefsChanged(
+ setting,
+ { key: setting, initialValue: { "my.single.pref": "value1" } },
+ "onPrefsChanged is called when control is entirely removed"
+ );
+ }
+ for (let i = 0; i < settingObj.prefNames.length; i++) {
+ equal(
+ Preferences.get(settingObj.prefNames[i]),
+ settingObj.initalValues[i],
+ "removeSetting sets the pref(s) to the initial value(s) when removing the last extension."
+ );
+ }
+
+ checkSetting = await ExtensionPreferencesManager.getSetting(setting);
+ equal(
+ checkSetting,
+ null,
+ "getSetting returns null when nothing has been set."
+ );
+ }
+
+ // Tests for unsetAll.
+ let newValue3 = "newValue3";
+ for (let setting in SETTINGS) {
+ let settingObj = SETTINGS[setting];
+ await ExtensionPreferencesManager.setSetting(
+ extensions[0].id,
+ setting,
+ newValue3
+ );
+ checkPrefs(settingObj, newValue3, "setSetting set the pref.");
+ }
+
+ let setSettings = await ExtensionSettingsStore.getAllForExtension(
+ extensions[0].id,
+ STORE_TYPE
+ );
+ deepEqual(
+ setSettings,
+ Object.keys(SETTINGS),
+ "Expected settings were set for extension."
+ );
+ await ExtensionPreferencesManager.disableAll(extensions[0].id);
+
+ 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],
+ "disableAll unset the pref."
+ );
+ }
+ }
+
+ setSettings = await ExtensionSettingsStore.getAllForExtension(
+ extensions[0].id,
+ STORE_TYPE
+ );
+ deepEqual(
+ setSettings,
+ Object.keys(SETTINGS),
+ "disableAll retains the settings."
+ );
+
+ await ExtensionPreferencesManager.enableAll(extensions[0].id);
+ for (let setting in SETTINGS) {
+ let settingObj = SETTINGS[setting];
+ checkPrefs(settingObj, newValue3, "enableAll re-set the pref.");
+ }
+
+ await ExtensionPreferencesManager.removeAll(extensions[0].id);
+
+ 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].id,
+ STORE_TYPE
+ );
+ deepEqual(setSettings, [], "removeAll removed all settings.");
+
+ // Tests for preventing automatic changes to manually edited prefs.
+ for (let setting in SETTINGS) {
+ let apiValue = "newValue";
+ let manualValue = "something different";
+ let settingObj = SETTINGS[setting];
+ let extension = extensions[1];
+ await ExtensionPreferencesManager.setSetting(
+ extension.id,
+ setting,
+ apiValue
+ );
+
+ let checkResetPrefs = method => {
+ let prefNames = settingObj.prefNames;
+ for (let i = 0; i < prefNames.length; i++) {
+ if (i === 0) {
+ equal(
+ Preferences.get(prefNames[0]),
+ manualValue,
+ `${method} did not change a manually set pref.`
+ );
+ } else {
+ equal(
+ Preferences.get(prefNames[i]),
+ settingObj.valueFn(prefNames[i], apiValue),
+ `${method} did not change another pref when a pref was manually set.`
+ );
+ }
+ }
+ };
+
+ // Manually set the preference to a different value.
+ Preferences.set(settingObj.prefNames[0], manualValue);
+
+ await ExtensionPreferencesManager.disableAll(extension.id);
+ checkResetPrefs("disableAll");
+
+ await ExtensionPreferencesManager.enableAll(extension.id);
+ checkResetPrefs("enableAll");
+
+ await ExtensionPreferencesManager.removeAll(extension.id);
+ checkResetPrefs("removeAll");
+ }
+
+ // 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].id,
+ setting,
+ newValue
+ );
+ equal(
+ Preferences.get(pref),
+ settingObj.valueFn(pref, newValue),
+ "Uninitialized pref is set."
+ );
+ await ExtensionPreferencesManager.removeSetting(extensions[1].id, 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].id,
+ setting
+ );
+ equal(
+ levelOfControl,
+ "not_controllable",
+ "getLevelOfControl returns correct levelOfControl when a pref is locked."
+ );
+
+ for (let extension of testExtensions) {
+ await extension.unload();
+ }
+
+ await promiseShutdownManager();
+});
+
+add_task(async function test_preference_manager_set_when_disabled() {
+ await promiseStartupManager();
+
+ let id = "@set-disabled-pref";
+ let extension = ExtensionTestUtils.loadExtension({
+ useAddonManager: "temporary",
+ manifest: {
+ browser_specific_settings: { gecko: { id } },
+ },
+ });
+
+ await extension.startup();
+
+ // We test both a default pref and a user-set pref. Get the default
+ // value off the pref we'll use. We fake the default pref by setting
+ // a value on it before creating the setting.
+ Services.prefs.setBoolPref("bar", true);
+
+ function isUndefinedPref(pref) {
+ try {
+ Services.prefs.getStringPref(pref);
+ return false;
+ } catch (e) {
+ return true;
+ }
+ }
+ ok(isUndefinedPref("foo"), "test pref is not set");
+
+ await ExtensionSettingsStore.initialize();
+ let lastItemChange = PromiseUtils.defer();
+ ExtensionPreferencesManager.addSetting("some-pref", {
+ prefNames: ["foo", "bar"],
+ onPrefsChanged(item) {
+ lastItemChange.resolve(item);
+ lastItemChange = PromiseUtils.defer();
+ },
+ setCallback(value) {
+ return { [this.prefNames[0]]: value, [this.prefNames[1]]: false };
+ },
+ });
+
+ await ExtensionPreferencesManager.setSetting(id, "some-pref", "my value");
+
+ let item = ExtensionSettingsStore.getSetting("prefs", "some-pref");
+ equal(item.value, "my value", "The value has been set");
+ equal(
+ Services.prefs.getStringPref("foo"),
+ "my value",
+ "The user pref has been set"
+ );
+ equal(
+ Services.prefs.getBoolPref("bar"),
+ false,
+ "The default pref has been set"
+ );
+
+ await ExtensionPreferencesManager.disableSetting(id, "some-pref");
+
+ // test that a disabled setting has been returned to the default value. In this
+ // case the pref is not a default pref, so it will be undefined.
+ item = ExtensionSettingsStore.getSetting("prefs", "some-pref");
+ equal(item.value, undefined, "The value is back to default");
+ equal(item.initialValue.foo, undefined, "The initialValue is correct");
+ ok(isUndefinedPref("foo"), "user pref is not set");
+ equal(
+ Services.prefs.getBoolPref("bar"),
+ true,
+ "The default pref has been restored to the default"
+ );
+
+ // test that setSetting() will enable a disabled setting
+ await ExtensionPreferencesManager.setSetting(id, "some-pref", "new value");
+
+ item = ExtensionSettingsStore.getSetting("prefs", "some-pref");
+ equal(item.value, "new value", "The value is set again");
+ equal(
+ Services.prefs.getStringPref("foo"),
+ "new value",
+ "The user pref is set again"
+ );
+ equal(
+ Services.prefs.getBoolPref("bar"),
+ false,
+ "The default pref has been set again"
+ );
+
+ // Force settings to be serialized and reloaded to mimick what happens
+ // with settings through a restart of Firefox. Bug 1576266.
+ await ExtensionSettingsStore._reloadFile(true);
+
+ // Now unload the extension to test prefs are reset properly.
+ let promise = lastItemChange.promise;
+ await extension.unload();
+
+ // Test that the pref is unset when an extension is uninstalled.
+ item = await promise;
+ deepEqual(
+ item,
+ { key: "some-pref", initialValue: { bar: true } },
+ "The value has been reset"
+ );
+ ok(isUndefinedPref("foo"), "user pref is not set");
+ equal(
+ Services.prefs.getBoolPref("bar"),
+ true,
+ "The default pref has been restored to the default"
+ );
+ Services.prefs.clearUserPref("bar");
+
+ await promiseShutdownManager();
+});
+
+add_task(async function test_preference_default_upgraded() {
+ await promiseStartupManager();
+
+ let id = "@upgrade-pref";
+ let extension = ExtensionTestUtils.loadExtension({
+ useAddonManager: "temporary",
+ manifest: {
+ browser_specific_settings: { gecko: { id } },
+ },
+ });
+
+ await extension.startup();
+
+ // We set the default value for a pref here so it will be
+ // picked up by EPM.
+ let defaultPrefs = Services.prefs.getDefaultBranch(null);
+ defaultPrefs.setStringPref("bar", "initial default");
+
+ await ExtensionSettingsStore.initialize();
+ ExtensionPreferencesManager.addSetting("some-pref", {
+ prefNames: ["bar"],
+ setCallback(value) {
+ return { [this.prefNames[0]]: value };
+ },
+ });
+
+ await ExtensionPreferencesManager.setSetting(id, "some-pref", "new value");
+ let item = ExtensionSettingsStore.getSetting("prefs", "some-pref");
+ equal(item.value, "new value", "The value is set");
+
+ defaultPrefs.setStringPref("bar", "new default");
+
+ item = ExtensionSettingsStore.getSetting("prefs", "some-pref");
+ equal(item.value, "new value", "The value is still set");
+
+ let prefsChanged = await ExtensionPreferencesManager.removeSetting(
+ id,
+ "some-pref"
+ );
+ ok(prefsChanged, "pref changed on removal of setting.");
+ equal(Preferences.get("bar"), "new default", "default value is correct");
+
+ await extension.unload();
+ await promiseShutdownManager();
+});
+
+add_task(async function test_preference_select() {
+ await promiseStartupManager();
+
+ let extensionData = {
+ useAddonManager: "temporary",
+ manifest: {
+ browser_specific_settings: { gecko: { id: "@one" } },
+ },
+ };
+ let one = ExtensionTestUtils.loadExtension(extensionData);
+
+ await one.startup();
+
+ // We set the default value for a pref here so it will be
+ // picked up by EPM.
+ let defaultPrefs = Services.prefs.getDefaultBranch(null);
+ defaultPrefs.setStringPref("bar", "initial default");
+
+ await ExtensionSettingsStore.initialize();
+ ExtensionPreferencesManager.addSetting("some-pref", {
+ prefNames: ["bar"],
+ setCallback(value) {
+ return { [this.prefNames[0]]: value };
+ },
+ });
+
+ ok(
+ await ExtensionPreferencesManager.setSetting(
+ one.id,
+ "some-pref",
+ "new value"
+ ),
+ "setting was changed"
+ );
+ let item = await ExtensionPreferencesManager.getSetting("some-pref");
+ equal(item.value, "new value", "The value is set");
+
+ // User-set the setting.
+ await ExtensionPreferencesManager.selectSetting(null, "some-pref");
+ item = await ExtensionPreferencesManager.getSetting("some-pref");
+ deepEqual(
+ item,
+ { key: "some-pref", initialValue: {} },
+ "The value is user-set"
+ );
+
+ // Extensions installed before cannot gain control again.
+ let levelOfControl = await ExtensionPreferencesManager.getLevelOfControl(
+ one.id,
+ "some-pref"
+ );
+ equal(
+ levelOfControl,
+ "not_controllable",
+ "getLevelOfControl returns correct levelOfControl when user-set."
+ );
+
+ // Enabling the top-precedence addon does not take over a user-set setting.
+ await ExtensionPreferencesManager.disableSetting(one.id, "some-pref");
+ await ExtensionPreferencesManager.enableSetting(one.id, "some-pref");
+ item = await ExtensionPreferencesManager.getSetting("some-pref");
+ deepEqual(
+ item,
+ { key: "some-pref", initialValue: {} },
+ "The value is user-set"
+ );
+
+ // Upgrading does not override the user-set setting.
+ extensionData.manifest.version = "2.0";
+ extensionData.manifest.incognito = "not_allowed";
+ await one.upgrade(extensionData);
+ levelOfControl = await ExtensionPreferencesManager.getLevelOfControl(
+ one.id,
+ "some-pref"
+ );
+ equal(
+ levelOfControl,
+ "not_controllable",
+ "getLevelOfControl returns correct levelOfControl when user-set after addon upgrade."
+ );
+
+ // We can re-select the extension.
+ await ExtensionPreferencesManager.selectSetting(one.id, "some-pref");
+ item = await ExtensionPreferencesManager.getSetting("some-pref");
+ deepEqual(item.value, "new value", "The value is extension set");
+
+ // An extension installed after user-set can take over the setting.
+ await ExtensionPreferencesManager.selectSetting(null, "some-pref");
+ item = await ExtensionPreferencesManager.getSetting("some-pref");
+ deepEqual(
+ item,
+ { key: "some-pref", initialValue: {} },
+ "The value is user-set"
+ );
+
+ let two = ExtensionTestUtils.loadExtension({
+ useAddonManager: "temporary",
+ manifest: {
+ browser_specific_settings: { gecko: { id: "@two" } },
+ },
+ });
+
+ await two.startup();
+ levelOfControl = await ExtensionPreferencesManager.getLevelOfControl(
+ two.id,
+ "some-pref"
+ );
+ equal(
+ levelOfControl,
+ "controllable_by_this_extension",
+ "getLevelOfControl returns correct levelOfControl when user-set after addon install."
+ );
+
+ await ExtensionPreferencesManager.setSetting(
+ two.id,
+ "some-pref",
+ "another value"
+ );
+ item = ExtensionSettingsStore.getSetting("prefs", "some-pref");
+ equal(item.value, "another value", "The value is set");
+
+ // A new installed extension can override a user selected extension.
+ let three = ExtensionTestUtils.loadExtension({
+ useAddonManager: "temporary",
+ manifest: {
+ browser_specific_settings: { gecko: { id: "@three" } },
+ },
+ });
+
+ // user selects specific extension to take control
+ await ExtensionPreferencesManager.selectSetting(one.id, "some-pref");
+
+ // two cannot control
+ levelOfControl = await ExtensionPreferencesManager.getLevelOfControl(
+ two.id,
+ "some-pref"
+ );
+ equal(
+ levelOfControl,
+ "not_controllable",
+ "getLevelOfControl returns correct levelOfControl when user-set after addon install."
+ );
+
+ // three can control after install
+ await three.startup();
+ levelOfControl = await ExtensionPreferencesManager.getLevelOfControl(
+ three.id,
+ "some-pref"
+ );
+ equal(
+ levelOfControl,
+ "controllable_by_this_extension",
+ "getLevelOfControl returns correct levelOfControl when user-set after addon install."
+ );
+
+ await ExtensionPreferencesManager.setSetting(
+ three.id,
+ "some-pref",
+ "third value"
+ );
+ item = ExtensionSettingsStore.getSetting("prefs", "some-pref");
+ equal(item.value, "third value", "The value is set");
+
+ // We have returned to precedence based settings.
+ await ExtensionPreferencesManager.removeSetting(three.id, "some-pref");
+ await ExtensionPreferencesManager.removeSetting(two.id, "some-pref");
+ item = await ExtensionPreferencesManager.getSetting("some-pref");
+ equal(item.value, "new value", "The value is extension set");
+
+ await one.unload();
+ await two.unload();
+ await three.unload();
+ await promiseShutdownManager();
+});
+
+add_task(async function test_preference_select() {
+ let prefNames = await ExtensionPreferencesManager.getManagedPrefDetails();
+ // Just check a subset of settings that are in this test file.
+ Assert.ok(prefNames.size > 0, "some prefs exist");
+ for (let settingName in SETTINGS) {
+ let setting = SETTINGS[settingName];
+ for (let prefName of setting.prefNames) {
+ Assert.equal(
+ prefNames.get(prefName),
+ settingName,
+ "setting retrieved prefNames"
+ );
+ }
+ }
+});