forked from mirrors/gecko-dev
Bug 1894203 - Add a helper for popup notification security delay test. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D208989
This commit is contained in:
parent
9a2997ade9
commit
70ffe53fab
1 changed files with 209 additions and 318 deletions
|
|
@ -44,7 +44,6 @@ add_setup(async function () {
|
|||
});
|
||||
});
|
||||
|
||||
async function ensureSecurityDelayReady() {
|
||||
/**
|
||||
* The security delay calculation in PopupNotification.sys.mjs is dependent on
|
||||
* the monotonically increasing value of performance.now. This timestamp is
|
||||
|
|
@ -60,6 +59,7 @@ async function ensureSecurityDelayReady() {
|
|||
* should usually be already sufficiently high in which case this check should
|
||||
* directly resolve.
|
||||
*/
|
||||
async function ensureSecurityDelayReady() {
|
||||
await TestUtils.waitForCondition(
|
||||
() => performance.now() > TEST_SECURITY_DELAY,
|
||||
"Wait for performance.now() > SECURITY_DELAY",
|
||||
|
|
@ -68,6 +68,116 @@ async function ensureSecurityDelayReady() {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test helper for security delay tests which performs the following steps:
|
||||
* 1. Shows a test notification.
|
||||
* 2. Waits for the notification panel to be shown and checks that the initial
|
||||
* security delay blocks clicks.
|
||||
* 3. Waits for the security delay to expire. Clicks should now be allowed.
|
||||
* 4. Executes the provided onSecurityDelayExpired function. This function
|
||||
* should renew the security delay.
|
||||
* 5. Tests that the security delay was renewed.
|
||||
* 6. Ensures that after the security delay the notification can be closed.
|
||||
*
|
||||
* @param {*} options
|
||||
* @param {function} options.onSecurityDelayExpired - Function to run after the
|
||||
* security delay has expired. This function should trigger a renew of the
|
||||
* security delay.
|
||||
* @param {function} options.cleanupFn - Optional cleanup function to run after
|
||||
* the test has completed.
|
||||
* @returns {Promise<void>} - Resolves when the test has completed.
|
||||
*/
|
||||
async function runPopupNotificationSecurityDelayTest({
|
||||
onSecurityDelayExpired,
|
||||
cleanupFn = () => {},
|
||||
}) {
|
||||
await ensureSecurityDelayReady();
|
||||
|
||||
info("Open a notification.");
|
||||
let popupShownPromise = waitForNotificationPanel();
|
||||
showNotification();
|
||||
await popupShownPromise;
|
||||
ok(
|
||||
PopupNotifications.isPanelOpen,
|
||||
"PopupNotification should be open after show call."
|
||||
);
|
||||
|
||||
// Test that the initial security delay works.
|
||||
info(
|
||||
"Trigger main action via button click during the initial security delay."
|
||||
);
|
||||
triggerMainCommand(PopupNotifications.panel);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
|
||||
ok(PopupNotifications.isPanelOpen, "PopupNotification should still be open.");
|
||||
let notification = PopupNotifications.getNotification(
|
||||
"foo",
|
||||
gBrowser.selectedBrowser
|
||||
);
|
||||
ok(
|
||||
notification,
|
||||
"Notification should still be open because we clicked during the security delay."
|
||||
);
|
||||
// If the notification is no longer shown (test failure) skip the remaining
|
||||
// checks.
|
||||
if (!notification) {
|
||||
await cleanupFn();
|
||||
return;
|
||||
}
|
||||
|
||||
info("Wait for security delay to expire.");
|
||||
await new Promise(resolve =>
|
||||
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
|
||||
setTimeout(resolve, TEST_SECURITY_DELAY + 500)
|
||||
);
|
||||
|
||||
info("Run test specific actions which restarts the security delay.");
|
||||
await onSecurityDelayExpired();
|
||||
|
||||
info("Trigger main action via button click during the new security delay.");
|
||||
triggerMainCommand(PopupNotifications.panel);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
|
||||
ok(PopupNotifications.isPanelOpen, "PopupNotification should still be open.");
|
||||
notification = PopupNotifications.getNotification(
|
||||
"foo",
|
||||
gBrowser.selectedBrowser
|
||||
);
|
||||
ok(
|
||||
notification,
|
||||
"Notification should still be open because we clicked during the security delay."
|
||||
);
|
||||
// If the notification is no longer shown (test failure) skip the remaining
|
||||
// checks.
|
||||
if (!notification) {
|
||||
await cleanupFn();
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure that once the security delay has passed the notification can be
|
||||
// closed again.
|
||||
let fakeTimeShown = TEST_SECURITY_DELAY + 500;
|
||||
info(`Manually set timeShown to ${fakeTimeShown}ms in the past.`);
|
||||
notification.timeShown = performance.now() - fakeTimeShown;
|
||||
|
||||
info("Trigger main action via button click outside security delay");
|
||||
let notificationHiddenPromise = waitForNotificationPanelHidden();
|
||||
triggerMainCommand(PopupNotifications.panel);
|
||||
|
||||
info("Wait for panel to be hidden.");
|
||||
await notificationHiddenPromise;
|
||||
|
||||
ok(
|
||||
!PopupNotifications.getNotification("foo", gBrowser.selectedBrowser),
|
||||
"Should no longer see the notification."
|
||||
);
|
||||
|
||||
info("Cleanup.");
|
||||
await cleanupFn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that when we show a second notification while the panel is open the
|
||||
* timeShown attribute is correctly set and the security delay is enforced
|
||||
|
|
@ -170,7 +280,7 @@ add_task(async function test_timeShownMultipleNotifications() {
|
|||
|
||||
ok(
|
||||
!PopupNotifications.getNotification("foo", gBrowser.selectedBrowser),
|
||||
"Should not longer see the notification."
|
||||
"Should no longer see the notification."
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -179,50 +289,8 @@ add_task(async function test_timeShownMultipleNotifications() {
|
|||
* attribute is correctly reset and the security delay is enforced.
|
||||
*/
|
||||
add_task(async function test_notificationReshowTabSwitch() {
|
||||
await ensureSecurityDelayReady();
|
||||
|
||||
ok(
|
||||
!PopupNotifications.isPanelOpen,
|
||||
"PopupNotification panel should not be open initially."
|
||||
);
|
||||
|
||||
info("Open the first notification.");
|
||||
let popupShownPromise = waitForNotificationPanel();
|
||||
showNotification();
|
||||
await popupShownPromise;
|
||||
ok(
|
||||
PopupNotifications.isPanelOpen,
|
||||
"PopupNotification should be open after first show call."
|
||||
);
|
||||
|
||||
let notification = PopupNotifications.getNotification(
|
||||
"foo",
|
||||
gBrowser.selectedBrowser
|
||||
);
|
||||
is(notification?.id, "foo", "There should be a notification with id foo");
|
||||
ok(notification.timeShown, "The notification should have timeShown set");
|
||||
|
||||
info("Trigger main action via button click during security delay");
|
||||
triggerMainCommand(PopupNotifications.panel);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
|
||||
ok(PopupNotifications.isPanelOpen, "PopupNotification should still be open.");
|
||||
notification = PopupNotifications.getNotification(
|
||||
"foo",
|
||||
gBrowser.selectedBrowser
|
||||
);
|
||||
ok(
|
||||
notification,
|
||||
"Notification should still be open because we clicked during the security delay."
|
||||
);
|
||||
|
||||
// If the notification is no longer shown (test failure) skip the remaining
|
||||
// checks.
|
||||
if (!notification) {
|
||||
return;
|
||||
}
|
||||
|
||||
await runPopupNotificationSecurityDelayTest({
|
||||
onSecurityDelayExpired: async () => {
|
||||
let panelHiddenPromise = waitForNotificationPanelHidden();
|
||||
let panelShownPromise;
|
||||
|
||||
|
|
@ -230,14 +298,6 @@ add_task(async function test_notificationReshowTabSwitch() {
|
|||
await BrowserTestUtils.withNewTab("https://example.com", async () => {
|
||||
info("Wait for panel to be hidden by tab switch.");
|
||||
await panelHiddenPromise;
|
||||
info(
|
||||
"Keep the tab open until the security delay for the original notification show has expired."
|
||||
);
|
||||
await new Promise(resolve =>
|
||||
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
|
||||
setTimeout(resolve, TEST_SECURITY_DELAY + 500)
|
||||
);
|
||||
|
||||
panelShownPromise = waitForNotificationPanel();
|
||||
});
|
||||
info(
|
||||
|
|
@ -249,7 +309,7 @@ add_task(async function test_notificationReshowTabSwitch() {
|
|||
PopupNotifications.isPanelOpen,
|
||||
"PopupNotification should be shown after tab close."
|
||||
);
|
||||
notification = PopupNotifications.getNotification(
|
||||
let notification = PopupNotifications.getNotification(
|
||||
"foo",
|
||||
gBrowser.selectedBrowser
|
||||
);
|
||||
|
|
@ -259,47 +319,11 @@ add_task(async function test_notificationReshowTabSwitch() {
|
|||
"There should still be a notification with id foo"
|
||||
);
|
||||
|
||||
let notificationHiddenPromise = waitForNotificationPanelHidden();
|
||||
|
||||
info(
|
||||
"Because we re-show the panel after tab close / switch the security delay should have reset."
|
||||
);
|
||||
info("Trigger main action via button click during the new security delay.");
|
||||
triggerMainCommand(PopupNotifications.panel);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
|
||||
ok(PopupNotifications.isPanelOpen, "PopupNotification should still be open.");
|
||||
notification = PopupNotifications.getNotification(
|
||||
"foo",
|
||||
gBrowser.selectedBrowser
|
||||
);
|
||||
ok(
|
||||
notification,
|
||||
"Notification should still be open because we clicked during the security delay."
|
||||
);
|
||||
// If the notification is no longer shown (test failure) skip the remaining
|
||||
// checks.
|
||||
if (!notification) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure that once the security delay has passed the notification can be
|
||||
// closed again.
|
||||
let fakeTimeShown = TEST_SECURITY_DELAY + 500;
|
||||
info(`Manually set timeShown to ${fakeTimeShown}ms in the past.`);
|
||||
notification.timeShown = performance.now() - fakeTimeShown;
|
||||
|
||||
info("Trigger main action via button click outside security delay");
|
||||
triggerMainCommand(PopupNotifications.panel);
|
||||
|
||||
info("Wait for panel to be hidden.");
|
||||
await notificationHiddenPromise;
|
||||
|
||||
ok(
|
||||
!PopupNotifications.getNotification("foo", gBrowser.selectedBrowser),
|
||||
"Should not longer see the notification."
|
||||
);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
@ -307,47 +331,14 @@ add_task(async function test_notificationReshowTabSwitch() {
|
|||
* the PopupNotifications panel position is updated.
|
||||
*/
|
||||
add_task(async function test_notificationWindowMove() {
|
||||
await ensureSecurityDelayReady();
|
||||
|
||||
info("Open a notification.");
|
||||
let popupShownPromise = waitForNotificationPanel();
|
||||
showNotification();
|
||||
await popupShownPromise;
|
||||
ok(
|
||||
PopupNotifications.isPanelOpen,
|
||||
"PopupNotification should be open after show call."
|
||||
);
|
||||
|
||||
// Test that the initial security delay works.
|
||||
info("Trigger main action via button click during the new security delay.");
|
||||
triggerMainCommand(PopupNotifications.panel);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
|
||||
ok(PopupNotifications.isPanelOpen, "PopupNotification should still be open.");
|
||||
let notification = PopupNotifications.getNotification(
|
||||
"foo",
|
||||
gBrowser.selectedBrowser
|
||||
);
|
||||
ok(
|
||||
notification,
|
||||
"Notification should still be open because we clicked during the security delay."
|
||||
);
|
||||
// If the notification is no longer shown (test failure) skip the remaining
|
||||
// checks.
|
||||
if (!notification) {
|
||||
return;
|
||||
}
|
||||
|
||||
info("Wait for security delay to expire.");
|
||||
await new Promise(resolve =>
|
||||
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
|
||||
setTimeout(resolve, TEST_SECURITY_DELAY + 500)
|
||||
);
|
||||
let screenX, screenY;
|
||||
|
||||
await runPopupNotificationSecurityDelayTest({
|
||||
onSecurityDelayExpired: async () => {
|
||||
info("Reposition the window");
|
||||
// Remember original window position.
|
||||
let { screenX, screenY } = window;
|
||||
screenX = window.screenX;
|
||||
screenY = window.screenY;
|
||||
|
||||
let promisePopupPositioned = BrowserTestUtils.waitForEvent(
|
||||
PopupNotifications.panel,
|
||||
|
|
@ -360,47 +351,12 @@ add_task(async function test_notificationWindowMove() {
|
|||
// Wait for the panel to reposition and the PopupNotifications listener to run.
|
||||
await promisePopupPositioned;
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
|
||||
info("Trigger main action via button click during the new security delay.");
|
||||
triggerMainCommand(PopupNotifications.panel);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
|
||||
ok(PopupNotifications.isPanelOpen, "PopupNotification should still be open.");
|
||||
notification = PopupNotifications.getNotification(
|
||||
"foo",
|
||||
gBrowser.selectedBrowser
|
||||
);
|
||||
ok(
|
||||
notification,
|
||||
"Notification should still be open because we clicked during the security delay."
|
||||
);
|
||||
// If the notification is no longer shown (test failure) skip the remaining
|
||||
// checks.
|
||||
if (!notification) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure that once the security delay has passed the notification can be
|
||||
// closed again.
|
||||
let fakeTimeShown = TEST_SECURITY_DELAY + 500;
|
||||
info(`Manually set timeShown to ${fakeTimeShown}ms in the past.`);
|
||||
notification.timeShown = performance.now() - fakeTimeShown;
|
||||
|
||||
info("Trigger main action via button click outside security delay");
|
||||
let notificationHiddenPromise = waitForNotificationPanelHidden();
|
||||
triggerMainCommand(PopupNotifications.panel);
|
||||
|
||||
info("Wait for panel to be hidden.");
|
||||
await notificationHiddenPromise;
|
||||
|
||||
ok(
|
||||
!PopupNotifications.getNotification("foo", gBrowser.selectedBrowser),
|
||||
"Should not longer see the notification."
|
||||
);
|
||||
|
||||
},
|
||||
cleanupFn: async () => {
|
||||
// Reset window position
|
||||
window.moveTo(screenX, screenY);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
@ -563,6 +519,8 @@ add_task(async function test_notificationDuringFullScreenTransition() {
|
|||
info("Wait for full screen transition end.");
|
||||
await promiseFullScreenTransitionEnd;
|
||||
info("Full screen transition end");
|
||||
|
||||
await SpecialPowers.popPrefEnv();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -576,46 +534,14 @@ add_task(async function test_notificationPointerLock() {
|
|||
"https://example.com"
|
||||
);
|
||||
|
||||
await ensureSecurityDelayReady();
|
||||
|
||||
info("Open a notification.");
|
||||
let popupShownPromise = waitForNotificationPanel();
|
||||
showNotification();
|
||||
await popupShownPromise;
|
||||
ok(
|
||||
PopupNotifications.isPanelOpen,
|
||||
"PopupNotification should be open after show call."
|
||||
);
|
||||
|
||||
// Test that the initial security delay works.
|
||||
info("Trigger main action via button click during the new security delay.");
|
||||
triggerMainCommand(PopupNotifications.panel);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
|
||||
ok(PopupNotifications.isPanelOpen, "PopupNotification should still be open.");
|
||||
let notification = PopupNotifications.getNotification(
|
||||
"foo",
|
||||
gBrowser.selectedBrowser
|
||||
);
|
||||
ok(
|
||||
notification,
|
||||
"Notification should still be open because we clicked during the security delay."
|
||||
);
|
||||
// If the notification is no longer shown (test failure) skip the remaining
|
||||
// checks.
|
||||
if (!notification) {
|
||||
return;
|
||||
}
|
||||
|
||||
info("Wait for security delay to expire.");
|
||||
await new Promise(resolve =>
|
||||
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
|
||||
setTimeout(resolve, TEST_SECURITY_DELAY + 500)
|
||||
);
|
||||
|
||||
await runPopupNotificationSecurityDelayTest({
|
||||
onSecurityDelayExpired: async () => {
|
||||
info("Enter pointer lock");
|
||||
let pointerLockEnterPromise = TestUtils.topicObserved("pointer-lock-entered");
|
||||
// Move focus to the browser to ensure pointer lock request succeeds.
|
||||
gBrowser.selectedBrowser.focus();
|
||||
let pointerLockEnterPromise = TestUtils.topicObserved(
|
||||
"pointer-lock-entered"
|
||||
);
|
||||
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => {
|
||||
SpecialPowers.wrap(content.document).notifyUserGestureActivation();
|
||||
await content.document.body.requestPointerLock();
|
||||
|
|
@ -624,45 +550,8 @@ add_task(async function test_notificationPointerLock() {
|
|||
// Wait for pointer lock to be entered and the PopupNotifications listener to run.
|
||||
await pointerLockEnterPromise;
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
|
||||
info("Trigger main action via button click during the new security delay.");
|
||||
triggerMainCommand(PopupNotifications.panel);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
|
||||
ok(PopupNotifications.isPanelOpen, "PopupNotification should still be open.");
|
||||
notification = PopupNotifications.getNotification(
|
||||
"foo",
|
||||
gBrowser.selectedBrowser
|
||||
);
|
||||
ok(
|
||||
notification,
|
||||
"Notification should still be open because we clicked during the security delay."
|
||||
);
|
||||
// If the notification is no longer shown (test failure) skip the remaining
|
||||
// checks.
|
||||
if (!notification) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure that once the security delay has passed the notification can be
|
||||
// closed again.
|
||||
let fakeTimeShown = TEST_SECURITY_DELAY + 500;
|
||||
info(`Manually set timeShown to ${fakeTimeShown}ms in the past.`);
|
||||
notification.timeShown = performance.now() - fakeTimeShown;
|
||||
|
||||
info("Trigger main action via button click outside security delay");
|
||||
let notificationHiddenPromise = waitForNotificationPanelHidden();
|
||||
triggerMainCommand(PopupNotifications.panel);
|
||||
|
||||
info("Wait for panel to be hidden.");
|
||||
await notificationHiddenPromise;
|
||||
|
||||
ok(
|
||||
!PopupNotifications.getNotification("foo", gBrowser.selectedBrowser),
|
||||
"Should not longer see the notification."
|
||||
);
|
||||
|
||||
},
|
||||
cleanupFn: async () => {
|
||||
// Cleanup.
|
||||
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => {
|
||||
SpecialPowers.wrap(content.document).notifyUserGestureActivation();
|
||||
|
|
@ -673,4 +562,6 @@ add_task(async function test_notificationPointerLock() {
|
|||
"Wait for pointer lock exit."
|
||||
);
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue