summaryrefslogtreecommitdiffstats
path: root/browser/components/extensions/test/browser/browser_ExtensionControlledPopup.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/extensions/test/browser/browser_ExtensionControlledPopup.js')
-rw-r--r--browser/components/extensions/test/browser/browser_ExtensionControlledPopup.js238
1 files changed, 238 insertions, 0 deletions
diff --git a/browser/components/extensions/test/browser/browser_ExtensionControlledPopup.js b/browser/components/extensions/test/browser/browser_ExtensionControlledPopup.js
new file mode 100644
index 0000000000..c920bf75b5
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ExtensionControlledPopup.js
@@ -0,0 +1,238 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+
+"use strict";
+const { sinon } = ChromeUtils.importESModule(
+ "resource://testing-common/Sinon.sys.mjs"
+);
+
+ChromeUtils.defineESModuleGetters(this, {
+ ExtensionControlledPopup:
+ "resource:///modules/ExtensionControlledPopup.sys.mjs",
+ ExtensionSettingsStore:
+ "resource://gre/modules/ExtensionSettingsStore.sys.mjs",
+});
+
+function createMarkup(doc, popup) {
+ let panel = ExtensionControlledPopup._getAndMaybeCreatePanel(doc);
+ let popupnotification = doc.createXULElement("popupnotification");
+ let attributes = {
+ id: "extension-controlled-notification",
+ class: "extension-controlled-notification",
+ popupid: "extension-controlled",
+ hidden: "true",
+ label: "ExtControlled",
+ buttonlabel: "Keep Changes",
+ buttonaccesskey: "K",
+ secondarybuttonlabel: "Restore Settings",
+ secondarybuttonaccesskey: "R",
+ closebuttonhidden: "true",
+ dropmarkerhidden: "true",
+ checkboxhidden: "true",
+ };
+ Object.entries(attributes).forEach(([key, value]) => {
+ popupnotification.setAttribute(key, value);
+ });
+ let content = doc.createXULElement("popupnotificationcontent");
+ content.setAttribute("orient", "vertical");
+ let description = doc.createXULElement("description");
+ description.setAttribute("id", "extension-controlled-description");
+ content.appendChild(description);
+ popupnotification.appendChild(content);
+ panel.appendChild(popupnotification);
+
+ registerCleanupFunction(function removePopup() {
+ popupnotification.remove();
+ });
+
+ return { panel, popupnotification };
+}
+
+/*
+ * This function is a unit test for ExtensionControlledPopup. It is also tested
+ * where it is being used (currently New Tab and homepage). An empty extension
+ * is used along with the expected markup as an example.
+ */
+add_task(async function testExtensionControlledPopup() {
+ let id = "ext-controlled@mochi.test";
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ browser_specific_settings: { gecko: { id } },
+ name: "Ext Controlled",
+ },
+ // We need to be able to find the extension using AddonManager.
+ useAddonManager: "temporary",
+ });
+
+ await extension.startup();
+ let addon = await AddonManager.getAddonByID(id);
+ await ExtensionSettingsStore.initialize();
+
+ let confirmedType = "extension-controlled-confirmed";
+ let onObserverAdded = sinon.spy();
+ let onObserverRemoved = sinon.spy();
+ let observerTopic = "extension-controlled-event";
+ let beforeDisableAddon = sinon.spy();
+ let settingType = "extension-controlled";
+ let settingKey = "some-key";
+ let popup = new ExtensionControlledPopup({
+ confirmedType,
+ observerTopic,
+ popupnotificationId: "extension-controlled-notification",
+ settingType,
+ settingKey,
+ descriptionId: "extension-controlled-description",
+ descriptionMessageId: "newTabControlled.message2",
+ learnMoreMessageId: "newTabControlled.learnMore",
+ learnMoreLink: "extension-controlled",
+ onObserverAdded,
+ onObserverRemoved,
+ beforeDisableAddon,
+ });
+
+ let doc = Services.wm.getMostRecentWindow("navigator:browser").document;
+ let { panel, popupnotification } = createMarkup(doc, popup);
+
+ function openPopupWithEvent() {
+ let popupShown = promisePopupShown(panel);
+ Services.obs.notifyObservers(null, observerTopic);
+ return popupShown;
+ }
+
+ function closePopupWithAction(action, extensionId) {
+ let done;
+ if (action == "ignore") {
+ panel.hidePopup();
+ } else if (action == "button") {
+ done = TestUtils.waitForCondition(() => {
+ return ExtensionSettingsStore.getSetting(confirmedType, id, id).value;
+ });
+ popupnotification.button.click();
+ } else if (action == "secondarybutton") {
+ done = awaitEvent("shutdown", id);
+ popupnotification.secondaryButton.click();
+ }
+ return done;
+ }
+
+ // No callbacks are initially called.
+ ok(!onObserverAdded.called, "No observer has been added");
+ ok(!onObserverRemoved.called, "No observer has been removed");
+ ok(!beforeDisableAddon.called, "Settings have not been restored");
+
+ // Add the setting and observer.
+ await ExtensionSettingsStore.addSetting(
+ id,
+ settingType,
+ settingKey,
+ "controlled",
+ () => "init"
+ );
+ await popup.addObserver(id);
+
+ // Ensure the panel isn't open.
+ ok(onObserverAdded.called, "Observing the event");
+ onObserverAdded.resetHistory();
+ ok(!onObserverRemoved.called, "Observing the event");
+ ok(!beforeDisableAddon.called, "Settings have not been restored");
+ ok(panel.getAttribute("panelopen") != "true", "The panel is closed");
+ is(popupnotification.hidden, true, "The popup is hidden");
+ is(addon.userDisabled, false, "The extension is enabled");
+ is(
+ await popup.userHasConfirmed(id),
+ false,
+ "The user is not initially confirmed"
+ );
+
+ // The popup should opened based on the observer event.
+ await openPopupWithEvent();
+
+ ok(!onObserverAdded.called, "Only one observer has been registered");
+ ok(onObserverRemoved.called, "The observer was removed");
+ onObserverRemoved.resetHistory();
+ ok(!beforeDisableAddon.called, "Settings have not been restored");
+ is(panel.getAttribute("panelopen"), "true", "The panel is open");
+ is(popupnotification.hidden, false, "The popup content is visible");
+ is(await popup.userHasConfirmed(id), false, "The user has not confirmed yet");
+
+ // Verify the description is populated.
+ let description = doc.getElementById("extension-controlled-description");
+ is(
+ description.textContent,
+ "An extension, Ext Controlled, changed the page you see when you open a new tab.Learn more",
+ "The extension name is in the description"
+ );
+ let link = description.querySelector("label");
+ is(
+ link.href,
+ "http://127.0.0.1:8888/support-dummy/extension-controlled",
+ "The link has the href set from learnMoreLink"
+ );
+
+ // Force close the popup, as if a user clicked away from it.
+ await closePopupWithAction("ignore");
+
+ // Nothing was recorded, but we won't show it again.
+ ok(!onObserverAdded.called, "The observer hasn't changed");
+ ok(!onObserverRemoved.called, "The observer hasn't changed");
+ is(await popup.userHasConfirmed(id), false, "The user has not confirmed");
+ is(addon.userDisabled, false, "The extension is still enabled");
+
+ // Force add the observer again to keep changes.
+ await popup.addObserver(id);
+ ok(onObserverAdded.called, "The observer was added again");
+ onObserverAdded.resetHistory();
+ ok(!onObserverRemoved.called, "The observer is still registered");
+ is(await popup.userHasConfirmed(id), false, "The user has not confirmed");
+
+ // Wait for popup.
+ await openPopupWithEvent();
+
+ // Keep the changes.
+ await closePopupWithAction("button");
+
+ // The observer is removed, but the notification is saved.
+ ok(!onObserverAdded.called, "The observer wasn't added");
+ ok(onObserverRemoved.called, "The observer was removed");
+ onObserverRemoved.resetHistory();
+ is(await popup.userHasConfirmed(id), true, "The user has confirmed");
+ is(addon.userDisabled, false, "The extension is still enabled");
+
+ // Adding the observer again for this add-on won't work, since it is
+ // confirmed.
+ await popup.addObserver(id);
+ ok(!onObserverAdded.called, "The observer isn't added");
+ ok(!onObserverRemoved.called, "The observer isn't removed");
+ is(await popup.userHasConfirmed(id), true, "The user has confirmed");
+
+ // Clear that the user was notified.
+ await popup.clearConfirmation(id);
+ is(
+ await popup.userHasConfirmed(id),
+ false,
+ "The user confirmation has been cleared"
+ );
+
+ // Force add the observer again to restore changes.
+ await popup.addObserver(id);
+ ok(onObserverAdded.called, "The observer was added a third time");
+ onObserverAdded.resetHistory();
+ ok(!onObserverRemoved.called, "The observer is still active");
+ ok(!beforeDisableAddon.called, "We haven't disabled the add-on yet");
+ is(await popup.userHasConfirmed(id), false, "The user has not confirmed");
+
+ // Wait for popup.
+ await openPopupWithEvent();
+
+ // Restore the settings.
+ await closePopupWithAction("secondarybutton");
+
+ // The observer is removed and the add-on is now disabled.
+ ok(!onObserverAdded.called, "There is no observer");
+ ok(onObserverRemoved.called, "The observer has been removed");
+ ok(beforeDisableAddon.called, "The beforeDisableAddon callback was fired");
+ is(await popup.userHasConfirmed(id), false, "The user has not confirmed");
+ is(addon.userDisabled, true, "The extension is now disabled");
+
+ await extension.unload();
+});