summaryrefslogtreecommitdiffstats
path: root/browser/components/extensions/test/browser/browser_ext_browserAction_popup.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/extensions/test/browser/browser_ext_browserAction_popup.js')
-rw-r--r--browser/components/extensions/test/browser/browser_ext_browserAction_popup.js370
1 files changed, 370 insertions, 0 deletions
diff --git a/browser/components/extensions/test/browser/browser_ext_browserAction_popup.js b/browser/components/extensions/test/browser/browser_ext_browserAction_popup.js
new file mode 100644
index 0000000000..136f30eb41
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_popup.js
@@ -0,0 +1,370 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+function getBrowserAction(extension) {
+ const {
+ global: { browserActionFor },
+ } = Management;
+
+ let ext = WebExtensionPolicy.getByID(extension.id)?.extension;
+ return browserActionFor(ext);
+}
+
+async function assertViewCount(extension, count, waitForPromise) {
+ let ext = WebExtensionPolicy.getByID(extension.id).extension;
+
+ if (waitForPromise) {
+ await waitForPromise;
+ }
+
+ is(
+ ext.views.size,
+ count,
+ "Should have the expected number of extension views"
+ );
+}
+
+function promiseExtensionPageClosed(extension, viewType) {
+ return new Promise(resolve => {
+ const policy = WebExtensionPolicy.getByID(extension.id);
+
+ const listener = (evtType, context) => {
+ if (context.viewType === viewType) {
+ policy.extension.off("extension-proxy-context-load", listener);
+
+ context.callOnClose({
+ close: resolve,
+ });
+ }
+ };
+ policy.extension.on("extension-proxy-context-load", listener);
+ });
+}
+
+let scriptPage = url =>
+ `<html><head><meta charset="utf-8"><script src="${url}"></script></head><body>${url}</body></html>`;
+
+async function testInArea(area) {
+ let extension = ExtensionTestUtils.loadExtension({
+ background() {
+ let middleClickShowPopup = false;
+ browser.browserAction.onClicked.addListener((tabs, info) => {
+ browser.test.sendMessage("browserAction-onClicked");
+ if (info.button === 1 && middleClickShowPopup) {
+ browser.browserAction.openPopup();
+ }
+ });
+
+ browser.test.onMessage.addListener(async msg => {
+ if (msg.type === "setBrowserActionPopup") {
+ let opts = { popup: msg.popup };
+ if (msg.onCurrentWindowId) {
+ let { id } = await browser.windows.getCurrent();
+ opts = { ...opts, windowId: id };
+ } else if (msg.onActiveTabId) {
+ let [{ id }] = await browser.tabs.query({
+ active: true,
+ currentWindow: true,
+ });
+ opts = { ...opts, tabId: id };
+ }
+ await browser.browserAction.setPopup(opts);
+ browser.test.sendMessage("setBrowserActionPopup:done");
+ } else if (msg.type === "setMiddleClickShowPopup") {
+ middleClickShowPopup = msg.show;
+ browser.test.sendMessage("setMiddleClickShowPopup:done");
+ }
+ });
+
+ browser.test.sendMessage("background-page-ready");
+ },
+ manifest: {
+ browser_action: {
+ default_popup: "popup-a.html",
+ browser_style: true,
+ },
+ },
+
+ files: {
+ "popup-a.html": scriptPage("popup-a.js"),
+ "popup-a.js": function () {
+ browser.test.onMessage.addListener(msg => {
+ if (msg == "close-popup-using-window.close") {
+ window.close();
+ }
+ });
+
+ window.onload = () => {
+ let color = window.getComputedStyle(document.body).color;
+ browser.test.assertEq("rgb(34, 36, 38)", color);
+ browser.test.sendMessage("from-popup", "popup-a");
+ };
+ },
+
+ "data/popup-b.html": scriptPage("popup-b.js"),
+ "data/popup-b.js": function () {
+ window.onload = () => {
+ browser.test.sendMessage("from-popup", "popup-b");
+ };
+ },
+
+ "data/popup-c.html": scriptPage("popup-c.js"),
+ "data/popup-c.js": function () {
+ // Close the popup before the document is fully-loaded to make sure that
+ // we handle this case sanely.
+ browser.test.sendMessage("from-popup", "popup-c");
+ window.close();
+ },
+ },
+ });
+
+ await Promise.all([
+ extension.startup(),
+ extension.awaitMessage("background-page-ready"),
+ ]);
+
+ let widget = getBrowserActionWidget(extension);
+
+ // Move the browserAction widget to the area targeted by this test.
+ CustomizableUI.addWidgetToArea(widget.id, area);
+
+ async function setBrowserActionPopup(opts) {
+ extension.sendMessage({ type: "setBrowserActionPopup", ...opts });
+ await extension.awaitMessage("setBrowserActionPopup:done");
+ }
+
+ async function setShowPopupOnMiddleClick(show) {
+ extension.sendMessage({ type: "setMiddleClickShowPopup", show });
+ await extension.awaitMessage("setMiddleClickShowPopup:done");
+ }
+
+ async function runTest({
+ actionType,
+ waitForPopupLoaded,
+ expectPopup,
+ expectOnClicked,
+ closePopup,
+ }) {
+ const oncePopupPageClosed = promiseExtensionPageClosed(extension, "popup");
+ const oncePopupLoaded = waitForPopupLoaded
+ ? awaitExtensionPanel(extension)
+ : undefined;
+
+ if (actionType === "click") {
+ clickBrowserAction(extension);
+ } else if (actionType === "trigger") {
+ getBrowserAction(extension).triggerAction(window);
+ } else if (actionType === "middleClick") {
+ clickBrowserAction(extension, window, { button: 1 });
+ }
+
+ if (expectOnClicked) {
+ await extension.awaitMessage("browserAction-onClicked");
+ }
+
+ if (expectPopup) {
+ info(`Waiting for popup: ${expectPopup}`);
+ is(
+ await extension.awaitMessage("from-popup"),
+ expectPopup,
+ "expected popup opened"
+ );
+ }
+
+ await oncePopupLoaded;
+
+ if (closePopup) {
+ info("Closing popup");
+ await closeBrowserAction(extension);
+ await assertViewCount(extension, 1, oncePopupPageClosed);
+ }
+
+ return { oncePopupPageClosed };
+ }
+
+ // Run the sequence of test cases.
+ const tests = [
+ async () => {
+ info(`Click browser action, expect popup "a".`);
+
+ await runTest({
+ actionType: "click",
+ expectPopup: "popup-a",
+ closePopup: true,
+ });
+ },
+ async () => {
+ info(`Click browser action again, expect popup "a".`);
+
+ await runTest({
+ actionType: "click",
+ expectPopup: "popup-a",
+ waitForPopupLoaded: true,
+ closePopup: true,
+ });
+ },
+ async () => {
+ info(`Call triggerAction, expect popup "a" again. Leave popup open.`);
+
+ const { oncePopupPageClosed } = await runTest({
+ actionType: "trigger",
+ expectPopup: "popup-a",
+ waitForPopupLoaded: true,
+ });
+
+ await assertViewCount(extension, 2);
+
+ info(`Call triggerAction again. Expect remaining popup closed.`);
+ getBrowserAction(extension).triggerAction(window);
+
+ await assertViewCount(extension, 1, oncePopupPageClosed);
+ },
+ async () => {
+ info(`Call triggerAction again. Expect popup "a" again.`);
+
+ await runTest({
+ actionType: "trigger",
+ expectPopup: "popup-a",
+ closePopup: true,
+ });
+ },
+ async () => {
+ info(`Set popup to "c" and click browser action. Expect popup "c".`);
+
+ await setBrowserActionPopup({ popup: "data/popup-c.html" });
+
+ const { oncePopupPageClosed } = await runTest({
+ actionType: "click",
+ expectPopup: "popup-c",
+ });
+
+ await assertViewCount(extension, 1, oncePopupPageClosed);
+ },
+ async () => {
+ info(`Set popup to "b" and click browser action. Expect popup "b".`);
+
+ await setBrowserActionPopup({ popup: "data/popup-b.html" });
+
+ await runTest({
+ actionType: "click",
+ expectPopup: "popup-b",
+ closePopup: true,
+ });
+ },
+ async () => {
+ info(`Click browser action again, expect popup "b".`);
+
+ await runTest({
+ actionType: "click",
+ expectPopup: "popup-b",
+ closePopup: true,
+ });
+ },
+ async () => {
+ info(`Middle-click browser action, expect an event only.`);
+
+ await setShowPopupOnMiddleClick(false);
+
+ await runTest({
+ actionType: "middleClick",
+ expectOnClicked: true,
+ });
+ },
+ async () => {
+ info(
+ `Middle-click browser action again, expect a click event then a popup.`
+ );
+
+ await setShowPopupOnMiddleClick(true);
+
+ await runTest({
+ actionType: "middleClick",
+ expectOnClicked: true,
+ expectPopup: "popup-b",
+ closePopup: true,
+ });
+ },
+ async () => {
+ info(`Clear popup URL. Click browser action. Expect click event.`);
+
+ await setBrowserActionPopup({ popup: "" });
+
+ await runTest({
+ actionType: "click",
+ expectOnClicked: true,
+ });
+ },
+ async () => {
+ info(`Click browser action again. Expect another click event.`);
+
+ await runTest({
+ actionType: "click",
+ expectOnClicked: true,
+ });
+ },
+ async () => {
+ info(`Call triggerAction. Expect click event.`);
+
+ await runTest({
+ actionType: "trigger",
+ expectOnClicked: true,
+ });
+ },
+ async () => {
+ info(
+ `Set window-specific popup to "b" and click browser action. Expect popup "b".`
+ );
+
+ await setBrowserActionPopup({
+ popup: "data/popup-b.html",
+ onCurrentWindowId: true,
+ });
+
+ await runTest({
+ actionType: "click",
+ expectPopup: "popup-b",
+ closePopup: true,
+ });
+ },
+ async () => {
+ info(
+ `Set tab-specific popup to "a" and click browser action. Expect popup "a", and leave open.`
+ );
+
+ await setBrowserActionPopup({
+ popup: "/popup-a.html",
+ onActiveTabId: true,
+ });
+
+ const { oncePopupPageClosed } = await runTest({
+ actionType: "click",
+ expectPopup: "popup-a",
+ });
+ assertViewCount(extension, 2);
+
+ info(`Tell popup "a" to call window.close(). Expect popup closed.`);
+ extension.sendMessage("close-popup-using-window.close");
+
+ await assertViewCount(extension, 1, oncePopupPageClosed);
+ },
+ ];
+
+ for (let test of tests) {
+ await test();
+ }
+
+ // Unload the extension and verify that the browserAction widget is gone.
+ await extension.unload();
+
+ let view = document.getElementById(widget.viewId);
+ is(view, null, "browserAction view removed from document");
+}
+
+add_task(async function testBrowserActionInToolbar() {
+ await testInArea(CustomizableUI.AREA_NAVBAR);
+});
+
+add_task(async function testBrowserActionInPanel() {
+ await testInArea(getCustomizableUIPanelID());
+});