Source code

Revision control

Copy as Markdown

Other Tools

/* Any copyright is dedicated to the Public Domain.
/**
* Shared helpers for browser tests that exercise addon install dialogs
* (e.g. WebMIDI, WebSerial, and the toolkit xpinstall doorhanger tests).
*/
"use strict";
/* exported waitForInstallDialog, alwaysAcceptAddonPostInstallDialogs, waitForNotification, getObserverTopic, waitForTick */
async function waitForInstallDialog(id = "addon-webext-permissions") {
let panel = await waitForNotification(id);
// NOTE: the panel may intermittently still be in the "showing" state, and
// so we explicitly await for the state to become "open" before proceeding
// with asserting the visibility of the elements we expected to be in the
// panel.
if (panel.state === "showing") {
await TestUtils.waitForCondition(
() => panel.state === "open",
`Wait for ${id} panel state to become open`
);
is(panel.state, "open", "Panel.state should be open");
}
return panel.childNodes[0];
}
/**
* Adds an event listener that will listen for post-install dialog event and automatically
* close the dialogs.
*/
function alwaysAcceptAddonPostInstallDialogs() {
// Once the addon is installed, a dialog is displayed as a confirmation.
// This could interfere with tests running after this one, so we set up a listener
// that will always accept post install dialogs so we don't have to deal with them in
// the test.
const abortController = new AbortController();
const { AppMenuNotifications } = ChromeUtils.importESModule(
"resource://gre/modules/AppMenuNotifications.sys.mjs"
);
info("Start listening and accept addon post-install notifications");
PanelUI.notificationPanel.addEventListener(
"popupshown",
async function popupshown() {
let notification = AppMenuNotifications.activeNotification;
if (!notification || notification.id !== "addon-installed") {
return;
}
let popupnotificationID = PanelUI._getPopupId(notification);
if (popupnotificationID) {
info("Accept post-install dialog");
let popupnotification = document.getElementById(popupnotificationID);
popupnotification?.button.click();
}
},
{
signal: abortController.signal,
}
);
registerCleanupFunction(async () => {
// Clear the listener at the end of the test file, to prevent it to stay
// around when the same browser instance may be running other unrelated
// test files.
abortController.abort();
});
}
async function waitForNotification(
aId,
aExpectedCount = 1,
expectedAnchorID = "unified-extensions-button",
win = window
) {
const PROGRESS_NOTIFICATION = "addon-progress";
info(`Waiting for ${aId} notification`);
let topic = getObserverTopic(aId);
let observerPromise;
if (aId !== "addon-webext-permissions") {
observerPromise = new Promise(resolve => {
Services.obs.addObserver(function observer(aSubject, aTopic) {
// Ignore the progress notification unless that is the notification we want
if (
aId != PROGRESS_NOTIFICATION &&
aTopic == getObserverTopic(PROGRESS_NOTIFICATION)
) {
return;
}
Services.obs.removeObserver(observer, topic);
resolve();
}, topic);
});
}
let panelEventPromise = new Promise(resolve => {
win.PopupNotifications.panel.addEventListener(
"PanelUpdated",
function eventListener(e) {
// Skip notifications that are not the one that we are supposed to be looking for
if (!e.detail.includes(aId)) {
return;
}
win.PopupNotifications.panel.removeEventListener(
"PanelUpdated",
eventListener
);
resolve();
}
);
});
await observerPromise;
await panelEventPromise;
await waitForTick();
info(`Saw a ${aId} notification`);
ok(win.PopupNotifications.isPanelOpen, "Panel should be open");
is(
win.PopupNotifications.panel.childNodes.length,
aExpectedCount,
"Should be the right number of notifications"
);
if (win.PopupNotifications.panel.childNodes.length) {
let nodes = Array.from(win.PopupNotifications.panel.childNodes);
let notification = nodes.find(n => n.id == aId + "-notification");
ok(notification, `Should have seen the ${aId} notification`);
let n = win.PopupNotifications.getNotification(aId);
is(
n?.anchorElement?.id || n?.anchorElement?.parentElement?.id,
expectedAnchorID,
"expected the right anchor ID"
);
}
await SimpleTest.promiseFocus(win.PopupNotifications.window);
return win.PopupNotifications.panel;
}
function getObserverTopic(aNotificationId) {
let topic = aNotificationId;
if (topic == "xpinstall-disabled") {
topic = "addon-install-disabled";
} else if (topic == "addon-progress") {
topic = "addon-install-started";
} else if (topic == "addon-installed") {
topic = "webextension-install-notify";
} else if (topic == "addon-install-failed-blocklist") {
topic = "addon-install-failed";
}
return topic;
}
function waitForTick() {
return new Promise(resolve => executeSoon(resolve));
}