summaryrefslogtreecommitdiffstats
path: root/browser/components/extensions/test/browser/browser_ext_settings_overrides_default_search.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/extensions/test/browser/browser_ext_settings_overrides_default_search.js')
-rw-r--r--browser/components/extensions/test/browser/browser_ext_settings_overrides_default_search.js881
1 files changed, 881 insertions, 0 deletions
diff --git a/browser/components/extensions/test/browser/browser_ext_settings_overrides_default_search.js b/browser/components/extensions/test/browser/browser_ext_settings_overrides_default_search.js
new file mode 100644
index 0000000000..74eaa6e634
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_settings_overrides_default_search.js
@@ -0,0 +1,881 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
+ AddonTestUtils: "resource://testing-common/AddonTestUtils.sys.mjs",
+ SearchTestUtils: "resource://testing-common/SearchTestUtils.sys.mjs",
+ TelemetryTestUtils: "resource://testing-common/TelemetryTestUtils.sys.mjs",
+});
+
+const EXTENSION1_ID = "extension1@mozilla.com";
+const EXTENSION2_ID = "extension2@mozilla.com";
+const DEFAULT_SEARCH_STORE_TYPE = "default_search";
+const DEFAULT_SEARCH_SETTING_NAME = "defaultSearch";
+
+AddonTestUtils.initMochitest(this);
+SearchTestUtils.init(this);
+
+const DEFAULT_ENGINE = {
+ id: "basic",
+ name: "basic",
+ loadPath: "[addon]basic@search.mozilla.org",
+ submissionUrl:
+ "https://mochi.test:8888/browser/browser/components/search/test/browser/?search=&foo=1",
+};
+const ALTERNATE_ENGINE = {
+ id: "simple",
+ name: "Simple Engine",
+ loadPath: "[addon]simple@search.mozilla.org",
+ submissionUrl: "https://example.com/?sourceId=Mozilla-search&search=",
+};
+const ALTERNATE2_ENGINE = {
+ id: "simple",
+ name: "another",
+ loadPath: "",
+ submissionUrl: "",
+};
+
+async function restoreDefaultEngine() {
+ let engine = Services.search.getEngineByName(DEFAULT_ENGINE.name);
+ await Services.search.setDefault(
+ engine,
+ Ci.nsISearchService.CHANGE_REASON_UNKNOWN
+ );
+}
+
+function clearTelemetry() {
+ Services.telemetry.clearEvents();
+ Services.fog.testResetFOG();
+}
+
+async function checkTelemetry(source, prevEngine, newEngine) {
+ TelemetryTestUtils.assertEvents(
+ [
+ {
+ object: "change_default",
+ value: source,
+ extra: {
+ prev_id: prevEngine.id,
+ new_id: newEngine.id,
+ new_name: newEngine.name,
+ new_load_path: newEngine.loadPath,
+ // Telemetry has a limit of 80 characters.
+ new_sub_url: newEngine.submissionUrl.slice(0, 80),
+ },
+ },
+ ],
+ { category: "search", method: "engine" }
+ );
+
+ let snapshot = await Glean.searchEngineDefault.changed.testGetValue();
+ delete snapshot[0].timestamp;
+ Assert.deepEqual(
+ snapshot[0],
+ {
+ category: "search.engine.default",
+ name: "changed",
+ extra: {
+ change_source: source,
+ previous_engine_id: prevEngine.id,
+ new_engine_id: newEngine.id,
+ new_display_name: newEngine.name,
+ new_load_path: newEngine.loadPath,
+ new_submission_url: newEngine.submissionUrl,
+ },
+ },
+ "Should have received the correct event details"
+ );
+}
+
+add_setup(async function () {
+ let searchExtensions = getChromeDir(getResolvedURI(gTestPath));
+ searchExtensions.append("search-engines");
+
+ await SearchTestUtils.useMochitestEngines(searchExtensions);
+
+ SearchTestUtils.useMockIdleService();
+ let response = await fetch(`resource://search-extensions/engines.json`);
+ let json = await response.json();
+ await SearchTestUtils.updateRemoteSettingsConfig(json.data);
+
+ registerCleanupFunction(async () => {
+ let settingsWritten = SearchTestUtils.promiseSearchNotification(
+ "write-settings-to-disk-complete"
+ );
+ await SearchTestUtils.updateRemoteSettingsConfig();
+ await settingsWritten;
+ });
+});
+
+/* This tests setting a default engine. */
+add_task(async function test_extension_setting_default_engine() {
+ clearTelemetry();
+
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ chrome_settings_overrides: {
+ search_provider: {
+ name: ALTERNATE_ENGINE.name,
+ search_url: "https://example.com/?q={searchTerms}",
+ is_default: true,
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE_ENGINE.name,
+ `Default engine is ${ALTERNATE_ENGINE.name}`
+ );
+
+ await checkTelemetry("addon-install", DEFAULT_ENGINE, ALTERNATE_ENGINE);
+
+ clearTelemetry();
+
+ await ext1.unload();
+
+ is(
+ (await Services.search.getDefault()).name,
+ DEFAULT_ENGINE.name,
+ `Default engine is ${DEFAULT_ENGINE.name}`
+ );
+
+ await checkTelemetry("addon-uninstall", ALTERNATE_ENGINE, DEFAULT_ENGINE);
+});
+
+/* This tests what happens when the engine you're setting it to is hidden. */
+add_task(async function test_extension_setting_default_engine_hidden() {
+ let engine = Services.search.getEngineByName(ALTERNATE_ENGINE.name);
+ engine.hidden = true;
+
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ chrome_settings_overrides: {
+ search_provider: {
+ name: ALTERNATE_ENGINE.name,
+ search_url: "https://example.com/?q={searchTerms}",
+ is_default: true,
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ is(
+ (await Services.search.getDefault()).name,
+ DEFAULT_ENGINE.name,
+ "Default engine should have remained as the default"
+ );
+ is(
+ ExtensionSettingsStore.getSetting("default_search", "defaultSearch"),
+ null,
+ "The extension should not have been recorded as having set the default search"
+ );
+
+ await ext1.unload();
+
+ is(
+ (await Services.search.getDefault()).name,
+ DEFAULT_ENGINE.name,
+ `Default engine is ${DEFAULT_ENGINE.name}`
+ );
+ engine.hidden = false;
+});
+
+// Test the popup displayed when trying to add a non-built-in default
+// search engine.
+add_task(async function test_extension_setting_default_engine_external() {
+ const NAME = "Example Engine";
+
+ // Load an extension that tries to set the default engine,
+ // and wait for the ensuing prompt.
+ async function startExtension(win = window) {
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ icons: {
+ 48: "icon.png",
+ 96: "icon@2x.png",
+ },
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION1_ID,
+ },
+ },
+ chrome_settings_overrides: {
+ search_provider: {
+ name: NAME,
+ search_url: "https://example.com/?q={searchTerms}",
+ is_default: true,
+ },
+ },
+ },
+ files: {
+ "icon.png": "",
+ "icon@2x.png": "",
+ },
+ useAddonManager: "temporary",
+ });
+
+ let [panel] = await Promise.all([
+ promisePopupNotificationShown("addon-webext-defaultsearch", win),
+ extension.startup(),
+ ]);
+
+ isnot(
+ panel,
+ null,
+ "Doorhanger was displayed for non-built-in default engine"
+ );
+
+ return { panel, extension };
+ }
+
+ // First time around, don't accept the default engine.
+ let { panel, extension } = await startExtension();
+ ok(
+ panel.getAttribute("icon").endsWith("/icon.png"),
+ "expected custom icon set on the notification"
+ );
+
+ panel.secondaryButton.click();
+
+ await TestUtils.topicObserved("webextension-defaultsearch-prompt-response");
+
+ is(
+ (await Services.search.getDefault()).name,
+ DEFAULT_ENGINE.name,
+ "Default engine was not changed after rejecting prompt"
+ );
+
+ await extension.unload();
+
+ clearTelemetry();
+
+ // Do it again, this time accept the prompt.
+ ({ panel, extension } = await startExtension());
+
+ panel.button.click();
+ await TestUtils.topicObserved("webextension-defaultsearch-prompt-response");
+
+ is(
+ (await Services.search.getDefault()).name,
+ NAME,
+ "Default engine was changed after accepting prompt"
+ );
+
+ await checkTelemetry("addon-install", DEFAULT_ENGINE, {
+ id: "other-Example Engine",
+ name: "Example Engine",
+ loadPath: "[addon]extension1@mozilla.com",
+ submissionUrl: "https://example.com/?q=",
+ });
+ clearTelemetry();
+
+ // Do this twice to make sure we're definitely handling disable/enable
+ // correctly. Disabling and enabling the addon here like this also
+ // replicates the behavior when an addon is added then removed in the
+ // blocklist.
+ let disabledPromise = awaitEvent("shutdown", EXTENSION1_ID);
+ let addon = await AddonManager.getAddonByID(EXTENSION1_ID);
+ await addon.disable();
+ await disabledPromise;
+
+ is(
+ (await Services.search.getDefault()).name,
+ DEFAULT_ENGINE.name,
+ `Default engine is ${DEFAULT_ENGINE.name} after disabling`
+ );
+
+ await checkTelemetry(
+ "addon-uninstall",
+ {
+ id: "other-Example Engine",
+ name: "Example Engine",
+ loadPath: "[addon]extension1@mozilla.com",
+ submissionUrl: "https://example.com/?q=",
+ },
+ DEFAULT_ENGINE
+ );
+ clearTelemetry();
+
+ let opened = promisePopupNotificationShown(
+ "addon-webext-defaultsearch",
+ window
+ );
+ await addon.enable();
+ panel = await opened;
+ panel.button.click();
+ await TestUtils.topicObserved("webextension-defaultsearch-prompt-response");
+
+ is(
+ (await Services.search.getDefault()).name,
+ NAME,
+ `Default engine is ${NAME} after enabling`
+ );
+
+ await checkTelemetry("addon-install", DEFAULT_ENGINE, {
+ id: "other-Example Engine",
+ name: "Example Engine",
+ loadPath: "[addon]extension1@mozilla.com",
+ submissionUrl: "https://example.com/?q=",
+ });
+
+ await extension.unload();
+
+ is(
+ (await Services.search.getDefault()).name,
+ DEFAULT_ENGINE.name,
+ "Default engine is reverted after uninstalling extension."
+ );
+
+ // One more time, this time close the window where the prompt
+ // appears instead of explicitly accepting or denying it.
+ let win = await BrowserTestUtils.openNewBrowserWindow();
+ await BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:blank");
+
+ ({ extension } = await startExtension(win));
+
+ await BrowserTestUtils.closeWindow(win);
+
+ is(
+ (await Services.search.getDefault()).name,
+ DEFAULT_ENGINE.name,
+ "Default engine is unchanged when prompt is dismissed"
+ );
+
+ await extension.unload();
+});
+
+/* This tests that uninstalling add-ons maintains the proper
+ * search default. */
+add_task(async function test_extension_setting_multiple_default_engine() {
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ chrome_settings_overrides: {
+ search_provider: {
+ name: ALTERNATE_ENGINE.name,
+ search_url: "https://example.com/?q={searchTerms}",
+ is_default: true,
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ let ext2 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ chrome_settings_overrides: {
+ search_provider: {
+ name: ALTERNATE2_ENGINE.name,
+ search_url: "https://example.com/?q={searchTerms}",
+ is_default: true,
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE_ENGINE.name,
+ `Default engine is ${ALTERNATE_ENGINE.name}`
+ );
+
+ await ext2.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext2);
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE2_ENGINE.name,
+ `Default engine is ${ALTERNATE2_ENGINE.name}`
+ );
+
+ await ext2.unload();
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE_ENGINE.name,
+ `Default engine is ${ALTERNATE_ENGINE.name}`
+ );
+
+ await ext1.unload();
+
+ is(
+ (await Services.search.getDefault()).name,
+ DEFAULT_ENGINE.name,
+ `Default engine is ${DEFAULT_ENGINE.name}`
+ );
+});
+
+/* This tests that uninstalling add-ons in reverse order maintains the proper
+ * search default. */
+add_task(
+ async function test_extension_setting_multiple_default_engine_reversed() {
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ chrome_settings_overrides: {
+ search_provider: {
+ name: ALTERNATE_ENGINE.name,
+ search_url: "https://example.com/?q={searchTerms}",
+ is_default: true,
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ let ext2 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ chrome_settings_overrides: {
+ search_provider: {
+ name: ALTERNATE2_ENGINE.name,
+ search_url: "https://example.com/?q={searchTerms}",
+ is_default: true,
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE_ENGINE.name,
+ `Default engine is ${ALTERNATE_ENGINE.name}`
+ );
+
+ await ext2.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext2);
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE2_ENGINE.name,
+ `Default engine is ${ALTERNATE2_ENGINE.name}`
+ );
+
+ await ext1.unload();
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE2_ENGINE.name,
+ `Default engine is ${ALTERNATE2_ENGINE.name}`
+ );
+
+ await ext2.unload();
+
+ is(
+ (await Services.search.getDefault()).name,
+ DEFAULT_ENGINE.name,
+ `Default engine is ${DEFAULT_ENGINE.name}`
+ );
+ }
+);
+
+/* This tests that when the user changes the search engine and the add-on
+ * is unistalled, search stays with the user's choice. */
+add_task(async function test_user_changing_default_engine() {
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ chrome_settings_overrides: {
+ search_provider: {
+ name: ALTERNATE_ENGINE.name,
+ search_url: "https://example.com/?q={searchTerms}",
+ is_default: true,
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE_ENGINE.name,
+ `Default engine is ${ALTERNATE_ENGINE.name}`
+ );
+
+ let engine = Services.search.getEngineByName(ALTERNATE2_ENGINE.name);
+ await Services.search.setDefault(
+ engine,
+ Ci.nsISearchService.CHANGE_REASON_UNKNOWN
+ );
+ // This simulates the preferences UI when the setting is changed.
+ ExtensionSettingsStore.select(
+ ExtensionSettingsStore.SETTING_USER_SET,
+ DEFAULT_SEARCH_STORE_TYPE,
+ DEFAULT_SEARCH_SETTING_NAME
+ );
+
+ await ext1.unload();
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE2_ENGINE.name,
+ `Default engine is ${ALTERNATE2_ENGINE.name}`
+ );
+ restoreDefaultEngine();
+});
+
+/* This tests that when the user changes the search engine while it is
+ * disabled, user choice is maintained when the add-on is reenabled. */
+add_task(async function test_user_change_with_disabling() {
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION1_ID,
+ },
+ },
+ chrome_settings_overrides: {
+ search_provider: {
+ name: ALTERNATE_ENGINE.name,
+ search_url: "https://example.com/?q={searchTerms}",
+ is_default: true,
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE_ENGINE.name,
+ `Default engine is ${ALTERNATE_ENGINE.name}`
+ );
+
+ let engine = Services.search.getEngineByName(ALTERNATE2_ENGINE.name);
+ await Services.search.setDefault(
+ engine,
+ Ci.nsISearchService.CHANGE_REASON_UNKNOWN
+ );
+ // This simulates the preferences UI when the setting is changed.
+ ExtensionSettingsStore.select(
+ ExtensionSettingsStore.SETTING_USER_SET,
+ DEFAULT_SEARCH_STORE_TYPE,
+ DEFAULT_SEARCH_SETTING_NAME
+ );
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE2_ENGINE.name,
+ `Default engine is ${ALTERNATE2_ENGINE.name}`
+ );
+
+ let disabledPromise = awaitEvent("shutdown", EXTENSION1_ID);
+ let addon = await AddonManager.getAddonByID(EXTENSION1_ID);
+ await addon.disable();
+ await disabledPromise;
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE2_ENGINE.name,
+ `Default engine is ${ALTERNATE2_ENGINE.name}`
+ );
+
+ let processedPromise = awaitEvent("searchEngineProcessed", EXTENSION1_ID);
+ await addon.enable();
+ await processedPromise;
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE2_ENGINE.name,
+ `Default engine is ${ALTERNATE2_ENGINE.name}`
+ );
+ await ext1.unload();
+ await restoreDefaultEngine();
+});
+
+/* This tests that when two add-ons are installed that change default
+ * search and the first one is disabled, before the second one is installed,
+ * when the first one is reenabled, the second add-on keeps the search. */
+add_task(async function test_two_addons_with_first_disabled_before_second() {
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION1_ID,
+ },
+ },
+ chrome_settings_overrides: {
+ search_provider: {
+ name: ALTERNATE_ENGINE.name,
+ search_url: "https://example.com/?q={searchTerms}",
+ is_default: true,
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ let ext2 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION2_ID,
+ },
+ },
+ chrome_settings_overrides: {
+ search_provider: {
+ name: ALTERNATE2_ENGINE.name,
+ search_url: "https://example.com/?q={searchTerms}",
+ is_default: true,
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE_ENGINE.name,
+ `Default engine is ${ALTERNATE_ENGINE.name}`
+ );
+
+ let disabledPromise = awaitEvent("shutdown", EXTENSION1_ID);
+ let addon1 = await AddonManager.getAddonByID(EXTENSION1_ID);
+ await addon1.disable();
+ await disabledPromise;
+
+ is(
+ (await Services.search.getDefault()).name,
+ DEFAULT_ENGINE.name,
+ `Default engine is ${DEFAULT_ENGINE.name}`
+ );
+
+ await ext2.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext2);
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE2_ENGINE.name,
+ `Default engine is ${ALTERNATE2_ENGINE.name}`
+ );
+
+ let enabledPromise = awaitEvent("ready", EXTENSION1_ID);
+ await addon1.enable();
+ await enabledPromise;
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE2_ENGINE.name,
+ `Default engine is ${ALTERNATE2_ENGINE.name}`
+ );
+ await ext2.unload();
+ await ext1.unload();
+
+ is(
+ (await Services.search.getDefault()).name,
+ DEFAULT_ENGINE.name,
+ `Default engine is ${DEFAULT_ENGINE.name}`
+ );
+});
+
+/* This tests that when two add-ons are installed that change default
+ * search and the first one is disabled, the second one maintains
+ * the search. */
+add_task(async function test_two_addons_with_first_disabled() {
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION1_ID,
+ },
+ },
+ chrome_settings_overrides: {
+ search_provider: {
+ name: ALTERNATE_ENGINE.name,
+ search_url: "https://example.com/?q={searchTerms}",
+ is_default: true,
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ let ext2 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION2_ID,
+ },
+ },
+ chrome_settings_overrides: {
+ search_provider: {
+ name: ALTERNATE2_ENGINE.name,
+ search_url: "https://example.com/?q={searchTerms}",
+ is_default: true,
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE_ENGINE.name,
+ `Default engine is ${ALTERNATE_ENGINE.name}`
+ );
+
+ await ext2.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext2);
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE2_ENGINE.name,
+ `Default engine is ${ALTERNATE2_ENGINE.name}`
+ );
+
+ let disabledPromise = awaitEvent("shutdown", EXTENSION1_ID);
+ let addon1 = await AddonManager.getAddonByID(EXTENSION1_ID);
+ await addon1.disable();
+ await disabledPromise;
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE2_ENGINE.name,
+ `Default engine is ${ALTERNATE2_ENGINE.name}`
+ );
+
+ let enabledPromise = awaitEvent("ready", EXTENSION1_ID);
+ await addon1.enable();
+ await enabledPromise;
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE2_ENGINE.name,
+ `Default engine is ${ALTERNATE2_ENGINE.name}`
+ );
+ await ext2.unload();
+ await ext1.unload();
+
+ is(
+ (await Services.search.getDefault()).name,
+ DEFAULT_ENGINE.name,
+ `Default engine is ${DEFAULT_ENGINE.name}`
+ );
+});
+
+/* This tests that when two add-ons are installed that change default
+ * search and the second one is disabled, the first one properly
+ * gets the search. */
+add_task(async function test_two_addons_with_second_disabled() {
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION1_ID,
+ },
+ },
+ chrome_settings_overrides: {
+ search_provider: {
+ name: ALTERNATE_ENGINE.name,
+ search_url: "https://example.com/?q={searchTerms}",
+ is_default: true,
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ let ext2 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION2_ID,
+ },
+ },
+ chrome_settings_overrides: {
+ search_provider: {
+ name: ALTERNATE2_ENGINE.name,
+ search_url: "https://example.com/?q={searchTerms}",
+ is_default: true,
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE_ENGINE.name,
+ `Default engine is ${ALTERNATE_ENGINE.name}`
+ );
+
+ await ext2.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext2);
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE2_ENGINE.name,
+ `Default engine is ${ALTERNATE2_ENGINE.name}`
+ );
+
+ let disabledPromise = awaitEvent("shutdown", EXTENSION2_ID);
+ let addon2 = await AddonManager.getAddonByID(EXTENSION2_ID);
+ await addon2.disable();
+ await disabledPromise;
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE_ENGINE.name,
+ `Default engine is ${ALTERNATE_ENGINE.name}`
+ );
+
+ let defaultPromise = SearchTestUtils.promiseSearchNotification(
+ "engine-default",
+ "browser-search-engine-modified"
+ );
+ // No prompt, because this is switching to an app-provided engine.
+ await addon2.enable();
+ await defaultPromise;
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE2_ENGINE.name,
+ `Default engine is ${ALTERNATE2_ENGINE.name}`
+ );
+ await ext2.unload();
+
+ is(
+ (await Services.search.getDefault()).name,
+ ALTERNATE_ENGINE.name,
+ `Default engine is ${ALTERNATE_ENGINE.name}`
+ );
+ await ext1.unload();
+
+ is(
+ (await Services.search.getDefault()).name,
+ DEFAULT_ENGINE.name,
+ `Default engine is ${DEFAULT_ENGINE.name}`
+ );
+});