diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:35:37 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:35:37 +0000 |
commit | a90a5cba08fdf6c0ceb95101c275108a152a3aed (patch) | |
tree | 532507288f3defd7f4dcf1af49698bcb76034855 /browser/base/content/test | |
parent | Adding debian version 126.0.1-1. (diff) | |
download | firefox-a90a5cba08fdf6c0ceb95101c275108a152a3aed.tar.xz firefox-a90a5cba08fdf6c0ceb95101c275108a152a3aed.zip |
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'browser/base/content/test')
38 files changed, 945 insertions, 421 deletions
diff --git a/browser/base/content/test/about/browser.toml b/browser/base/content/test/about/browser.toml index 98961200a0..2c6dafb4dd 100644 --- a/browser/base/content/test/about/browser.toml +++ b/browser/base/content/test/about/browser.toml @@ -66,7 +66,6 @@ support-files = [ ["browser_aboutNewTab_bookmarksToolbar.js"] ["browser_aboutNewTab_bookmarksToolbarEmpty.js"] -fail-if = ["a11y_checks"] # Bug 1854233 text-link may not be focusable skip-if = ["tsan"] # Bug 1676326, highly frequent on TSan ["browser_aboutNewTab_bookmarksToolbarNewWindow.js"] diff --git a/browser/base/content/test/about/browser_aboutNetError_csp_iframe.js b/browser/base/content/test/about/browser_aboutNetError_csp_iframe.js index c8028a4cf4..d245d0cd3c 100644 --- a/browser/base/content/test/about/browser_aboutNetError_csp_iframe.js +++ b/browser/base/content/test/about/browser_aboutNetError_csp_iframe.js @@ -8,6 +8,10 @@ const BLOCKED_PAGE = "http://example.org:8000/browser/browser/base/content/test/about/csp_iframe.sjs"; add_task(async function test_csp() { + await SpecialPowers.pushPrefEnv({ + set: [["security.xfocsp.hideOpenInNewWindow", false]], + }); + let { iframePageTab, blockedPageTab } = await setupPage( "iframe_page_csp.html", BLOCKED_PAGE diff --git a/browser/base/content/test/about/browser_aboutNetError_xfo_iframe.js b/browser/base/content/test/about/browser_aboutNetError_xfo_iframe.js index f5fd240643..2373bd8b50 100644 --- a/browser/base/content/test/about/browser_aboutNetError_xfo_iframe.js +++ b/browser/base/content/test/about/browser_aboutNetError_xfo_iframe.js @@ -8,6 +8,10 @@ const BLOCKED_PAGE = "http://example.org:8000/browser/browser/base/content/test/about/xfo_iframe.sjs"; add_task(async function test_xfo_iframe() { + await SpecialPowers.pushPrefEnv({ + set: [["security.xfocsp.hideOpenInNewWindow", false]], + }); + let { iframePageTab, blockedPageTab } = await setupPage( "iframe_page_xfo.html", BLOCKED_PAGE diff --git a/browser/base/content/test/alerts/browser.toml b/browser/base/content/test/alerts/browser.toml index d0d56f7392..aaca2ba7dc 100644 --- a/browser/base/content/test/alerts/browser.toml +++ b/browser/base/content/test/alerts/browser.toml @@ -19,10 +19,6 @@ skip-if = ["os == 'win'"] # Bug 1411118 https_first_disabled = true skip-if = ["os == 'win'"] # Bug 1411118 -["browser_notification_replace.js"] -https_first_disabled = true -skip-if = ["os == 'win'"] # Bug 1422928 - ["browser_notification_tab_switching.js"] https_first_disabled = true skip-if = ["os == 'win'"] # Bug 1243263 diff --git a/browser/base/content/test/alerts/browser_notification_close.js b/browser/base/content/test/alerts/browser_notification_close.js index 7568f1cc2d..3fd50bed5b 100644 --- a/browser/base/content/test/alerts/browser_notification_close.js +++ b/browser/base/content/test/alerts/browser_notification_close.js @@ -21,17 +21,16 @@ add_task(async function test_notificationClose() { Services.prefs.setBoolPref("alerts.showFavicons", true); await PlacesTestUtils.addVisits(notificationURI); - let faviconURI = await new Promise(resolve => { - let uri = makeURI( - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC" - ); - PlacesUtils.favicons.setAndFetchFaviconForPage( + let dataURL = makeURI( + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC" + ); + await new Promise(resolve => { + PlacesUtils.favicons.setFaviconForPage( notificationURI, - uri, - true, - PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, - uriResult => resolve(uriResult), - Services.scriptSecurityManager.getSystemPrincipal() + dataURL, + dataURL, + null, + resolve ); }); @@ -67,11 +66,7 @@ add_task(async function test_notificationClose() { "Body text of notification should be present" ); let alertIcon = alertWindow.document.getElementById("alertIcon"); - is( - alertIcon.src, - faviconURI.spec, - "Icon of notification should be present" - ); + is(alertIcon.src, dataURL.spec, "Icon of notification should be present"); let alertCloseButton = alertWindow.document.querySelector(".close-icon"); is(alertCloseButton.localName, "toolbarbutton", "close button found"); diff --git a/browser/base/content/test/alerts/browser_notification_replace.js b/browser/base/content/test/alerts/browser_notification_replace.js deleted file mode 100644 index 9c72e90ab1..0000000000 --- a/browser/base/content/test/alerts/browser_notification_replace.js +++ /dev/null @@ -1,66 +0,0 @@ -"use strict"; - -let notificationURL = - // eslint-disable-next-line @microsoft/sdl/no-insecure-url - "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html"; - -add_task(async function test_notificationReplace() { - await addNotificationPermission(notificationURL); - - await BrowserTestUtils.withNewTab( - { - gBrowser, - url: notificationURL, - }, - async function dummyTabTask(aBrowser) { - await SpecialPowers.spawn(aBrowser, [], async function () { - let win = content.window.wrappedJSObject; - let notification = win.showNotification1(); - let promiseCloseEvent = ContentTaskUtils.waitForEvent( - notification, - "close" - ); - - let showEvent = await ContentTaskUtils.waitForEvent( - notification, - "show" - ); - Assert.equal( - showEvent.target.body, - "Test body 1", - "Showed tagged notification" - ); - - let newNotification = win.showNotification2(); - let newShowEvent = await ContentTaskUtils.waitForEvent( - newNotification, - "show" - ); - Assert.equal( - newShowEvent.target.body, - "Test body 2", - "Showed new notification with same tag" - ); - - let closeEvent = await promiseCloseEvent; - Assert.equal( - closeEvent.target.body, - "Test body 1", - "Closed previous tagged notification" - ); - - let promiseNewCloseEvent = ContentTaskUtils.waitForEvent( - newNotification, - "close" - ); - newNotification.close(); - let newCloseEvent = await promiseNewCloseEvent; - Assert.equal( - newCloseEvent.target.body, - "Test body 2", - "Closed new notification" - ); - }); - } - ); -}); diff --git a/browser/base/content/test/contextMenu/browser.toml b/browser/base/content/test/contextMenu/browser.toml index 660f6a955b..c7af1bc437 100644 --- a/browser/base/content/test/contextMenu/browser.toml +++ b/browser/base/content/test/contextMenu/browser.toml @@ -101,3 +101,5 @@ support-files = [ "test_view_image_inline_svg.html", ] skip-if = ["os == 'linux' && socketprocess_networking"] + +["browser_contextmenu_cross_boundary_selection.js"] diff --git a/browser/base/content/test/contextMenu/browser_contextmenu.js b/browser/base/content/test/contextMenu/browser_contextmenu.js index 00da3113c6..d8dc0ab5e0 100644 --- a/browser/base/content/test/contextMenu/browser_contextmenu.js +++ b/browser/base/content/test/contextMenu/browser_contextmenu.js @@ -41,6 +41,10 @@ let hasContainers = Services.prefs.getBoolPref("privacy.userContext.enabled") && ContextualIdentityService.getPublicIdentities().length; +const hasSelectTranslations = + Services.prefs.getBoolPref("browser.translations.enable") && + Services.prefs.getBoolPref("browser.translations.select.enable"); + const example_base = // eslint-disable-next-line @microsoft/sdl/no-insecure-url "http://example.com/browser/browser/base/content/test/contextMenu/"; @@ -112,6 +116,7 @@ add_task(async function test_xul_text_link_label() { true, "context-searchselect-private", true, + ...(hasSelectTranslations ? ["context-translate-selection", true] : []), ]); // Clean up so won't affect HTML element test cases. @@ -204,6 +209,7 @@ const kLinkItems = [ true, "context-searchselect-private", true, + ...(hasSelectTranslations ? ["context-translate-selection", true] : []), ]; add_task(async function test_link() { @@ -234,6 +240,7 @@ add_task(async function test_mailto() { true, "context-searchselect-private", true, + ...(hasSelectTranslations ? ["context-translate-selection", true] : []), ]); }); @@ -247,6 +254,7 @@ add_task(async function test_tel() { true, "context-searchselect-private", true, + ...(hasSelectTranslations ? ["context-translate-selection", true] : []), ]); }); @@ -273,6 +281,10 @@ add_task(async function test_image() { null, "context-setDesktopBackground", true, + "---", + null, + "context-take-screenshot", + true, ], { onContextMenuShown() { @@ -356,6 +368,10 @@ add_task(async function test_video_ok() { true, "context-sendvideo", true, + "---", + null, + "context-take-screenshot", + true, ]); await SpecialPowers.popPrefEnv(); @@ -404,6 +420,10 @@ add_task(async function test_video_ok() { true, "context-sendvideo", true, + "---", + null, + "context-take-screenshot", + true, ]); await SpecialPowers.popPrefEnv(); @@ -490,6 +510,10 @@ add_task(async function test_video_bad() { true, "context-sendvideo", true, + "---", + null, + "context-take-screenshot", + true, ]); await SpecialPowers.popPrefEnv(); @@ -538,6 +562,10 @@ add_task(async function test_video_bad() { true, "context-sendvideo", true, + "---", + null, + "context-take-screenshot", + true, ]); await SpecialPowers.popPrefEnv(); @@ -588,6 +616,10 @@ add_task(async function test_video_bad2() { false, "context-sendvideo", false, + "---", + null, + "context-take-screenshot", + true, ]); await SpecialPowers.popPrefEnv(); @@ -636,6 +668,10 @@ add_task(async function test_video_bad2() { false, "context-sendvideo", false, + "---", + null, + "context-take-screenshot", + true, ]); await SpecialPowers.popPrefEnv(); @@ -767,6 +803,10 @@ add_task(async function test_video_in_iframe() { true, "---", null, + "context-take-frame-screenshot", + true, + "---", + null, "context-viewframeinfo", true, ]), @@ -846,6 +886,10 @@ add_task(async function test_video_in_iframe() { true, "---", null, + "context-take-frame-screenshot", + true, + "---", + null, "context-viewframeinfo", true, ]), @@ -967,6 +1011,10 @@ add_task(async function test_image_in_iframe() { true, "---", null, + "context-take-frame-screenshot", + true, + "---", + null, "context-viewframeinfo", true, ]), @@ -1336,6 +1384,7 @@ add_task(async function test_select_text() { true, "context-searchselect-private", true, + ...(hasSelectTranslations ? ["context-translate-selection", true] : []), "---", null, "context-viewpartialsource-selection", @@ -1369,6 +1418,9 @@ add_task(async function test_select_text_search_service_not_initialized() { null, "context-take-screenshot", true, + ...(hasSelectTranslations + ? ["---", null, "context-translate-selection", true] + : []), "---", null, "context-viewpartialsource-selection", @@ -1423,6 +1475,7 @@ add_task(async function test_select_text_link() { true, "context-searchselect-private", true, + ...(hasSelectTranslations ? ["context-translate-selection", true] : []), "---", null, "context-viewpartialsource-selection", @@ -1490,6 +1543,9 @@ add_task(async function test_imagelink() { null, "context-setDesktopBackground", true, + ...(hasSelectTranslations + ? ["---", null, "context-translate-selection", true] + : []), ]); }); @@ -1591,6 +1647,10 @@ add_task(async function test_longdesc() { null, "context-setDesktopBackground", true, + "---", + null, + "context-take-screenshot", + true, ]); }); @@ -1682,6 +1742,7 @@ add_task(async function test_svg_link() { true, "context-searchselect-private", true, + ...(hasSelectTranslations ? ["context-translate-selection", true] : []), ]); await test_contextmenu("#svg-with-link2 > a", [ @@ -1711,6 +1772,7 @@ add_task(async function test_svg_link() { true, "context-searchselect-private", true, + ...(hasSelectTranslations ? ["context-translate-selection", true] : []), ]); await test_contextmenu("#svg-with-link3 > a", [ @@ -1740,6 +1802,7 @@ add_task(async function test_svg_link() { true, "context-searchselect-private", true, + ...(hasSelectTranslations ? ["context-translate-selection", true] : []), ]); }); @@ -1771,6 +1834,7 @@ add_task(async function test_svg_relative_link() { true, "context-searchselect-private", true, + ...(hasSelectTranslations ? ["context-translate-selection", true] : []), ]); await test_contextmenu("#svg-with-relative-link2 > a", [ @@ -1800,6 +1864,7 @@ add_task(async function test_svg_relative_link() { true, "context-searchselect-private", true, + ...(hasSelectTranslations ? ["context-translate-selection", true] : []), ]); await test_contextmenu("#svg-with-relative-link3 > a", [ @@ -1829,6 +1894,7 @@ add_task(async function test_svg_relative_link() { true, "context-searchselect-private", true, + ...(hasSelectTranslations ? ["context-translate-selection", true] : []), ]); }); @@ -1898,6 +1964,7 @@ add_task(async function test_background_image() { true, "context-searchselect-private", true, + ...(hasSelectTranslations ? ["context-translate-selection", true] : []), ]); // Don't show image related context menu commands when there is a selection @@ -1921,6 +1988,7 @@ add_task(async function test_background_image() { true, "context-searchselect-private", true, + ...(hasSelectTranslations ? ["context-translate-selection", true] : []), "---", null, "context-viewpartialsource-selection", @@ -1989,6 +2057,7 @@ add_task(async function test_strip_on_share_on_secure_about_page() { true, "context-searchselect-private", true, + ...(hasSelectTranslations ? ["context-translate-selection", true] : []), ]); // Clean up diff --git a/browser/base/content/test/contextMenu/browser_contextmenu_cross_boundary_selection.js b/browser/base/content/test/contextMenu/browser_contextmenu_cross_boundary_selection.js new file mode 100644 index 0000000000..3137a1e136 --- /dev/null +++ b/browser/base/content/test/contextMenu/browser_contextmenu_cross_boundary_selection.js @@ -0,0 +1,73 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const PAGE = ` + data:text/html, + <div>OuterText<div> + <div id="host"> + <template shadowrootmode="open"> + <span id="innerText">InnerText</span> + </template> + </div> + `; +/** + * Tests that right click on a cross boundary selection shows the context menu + */ +add_task(async function () { + await SpecialPowers.pushPrefEnv({ + set: [["dom.shadowdom.selection_across_boundary.enabled", true]], + }); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: PAGE, + }, + async function (browser) { + let contextMenu = document.getElementById("contentAreaContextMenu"); + let awaitPopupShown = BrowserTestUtils.waitForEvent( + contextMenu, + "popupshown" + ); + + let awaitPopupHidden = BrowserTestUtils.waitForEvent( + contextMenu, + "popuphidden" + ); + + await SpecialPowers.spawn(browser, [], () => { + let host = content.document.getElementById("host"); + content.getSelection().setBaseAndExtent( + content.document.body, + 0, + host.shadowRoot.getElementById("innerText").firstChild, + 3 // Only select the first three characters of the inner text + ); + }); + + await BrowserTestUtils.synthesizeMouseAtCenter( + "div", // Click on the div for OuterText + { + type: "contextmenu", + button: 2, + }, + browser + ); + + await awaitPopupShown; + + const allVisibleMenuItems = Array.from(contextMenu.children) + .filter(elem => { + return !elem.hidden; + }) + .map(elem => elem.id); + + ok( + allVisibleMenuItems.includes("context-copy"), + "copy button should exist" + ); + + contextMenu.hidePopup(); + await awaitPopupHidden; + } + ); +}); diff --git a/browser/base/content/test/contextMenu/browser_strip_on_share_link.js b/browser/base/content/test/contextMenu/browser_strip_on_share_link.js index 435b1aa0ff..144076cfb2 100644 --- a/browser/base/content/test/contextMenu/browser_strip_on_share_link.js +++ b/browser/base/content/test/contextMenu/browser_strip_on_share_link.js @@ -97,6 +97,18 @@ add_task(async function testQueryParamIsNotStrippedForWrongSiteSpecific() { }); }); +// Ensuring clean copy works with magnet links. We don't strip anything but copying the original URI should still work. +add_task(async function testMagneticLinks() { + let originalUrl = "magnet:?xt=urn:btih:somesha1hash"; + let shortenedUrl = "magnet:?xt=urn:btih:somesha1hash"; + await testStripOnShare({ + selectWholeUrl: true, + validUrl: originalUrl, + strippedUrl: shortenedUrl, + useTestList: true, + }); +}); + /** * Opens a new tab, opens the context menu and checks that the strip-on-share menu item is visible. * Checks that the stripped version of the url is copied to the clipboard. diff --git a/browser/base/content/test/general/browser_documentnavigation.js b/browser/base/content/test/general/browser_documentnavigation.js index 880db6110f..b68e6ec3f0 100644 --- a/browser/base/content/test/general/browser_documentnavigation.js +++ b/browser/base/content/test/general/browser_documentnavigation.js @@ -229,7 +229,7 @@ add_task(async function () { let sidebar = document.getElementById("sidebar"); let loadPromise = BrowserTestUtils.waitForEvent(sidebar, "load", true); - SidebarUI.toggle("viewBookmarksSidebar"); + SidebarController.toggle("viewBookmarksSidebar"); await loadPromise; gURLBar.focus(); @@ -278,7 +278,7 @@ add_task(async function () { "back focus with sidebar urlbar" ); - SidebarUI.toggle("viewBookmarksSidebar"); + SidebarController.toggle("viewBookmarksSidebar"); }); // Navigate when the downloads panel is open diff --git a/browser/base/content/test/performance/browser_preferences_usage.js b/browser/base/content/test/performance/browser_preferences_usage.js index b0ff140d19..9ad9a8dde8 100644 --- a/browser/base/content/test/performance/browser_preferences_usage.js +++ b/browser/base/content/test/performance/browser_preferences_usage.js @@ -70,13 +70,6 @@ function checkPrefGetters(stats, max, knownProblematicPrefs = {}) { } } - // This pref will be accessed by mozJSComponentLoader when loading modules, - // which fails TV runs since they run the test multiple times without restarting. - // We just ignore this pref, since it's for testing only anyway. - if (knownProblematicPrefs["browser.startup.record"]) { - delete knownProblematicPrefs["browser.startup.record"]; - } - let unusedPrefs = Object.keys(knownProblematicPrefs); is( unusedPrefs.length, @@ -104,18 +97,9 @@ add_task(async function startup() { let max = 40; let knownProblematicPrefs = { - "browser.startup.record": { - // This pref is accessed in Nighly and debug builds only. - min: 200, - max: 450, - }, "network.loadinfo.skip_type_assertion": { // This is accessed in debug only. }, - "chrome.override_package.global": { - min: 0, - max: 50, - }, }; let startupRecorder = @@ -135,9 +119,6 @@ add_task(async function open_10_tabs() { const max = 4 * DEFAULT_PROCESS_COUNT; let knownProblematicPrefs = { - "browser.startup.record": { - max: 20, - }, "browser.tabs.remote.logSwitchTiming": { max: 35, }, diff --git a/browser/base/content/test/popupNotifications/browser_popupNotification_security_delay.js b/browser/base/content/test/popupNotifications/browser_popupNotification_security_delay.js index 140c2be2fd..3c652b26a2 100644 --- a/browser/base/content/test/popupNotifications/browser_popupNotification_security_delay.js +++ b/browser/base/content/test/popupNotifications/browser_popupNotification_security_delay.js @@ -44,22 +44,22 @@ add_setup(async function () { }); }); +/** + * The security delay calculation in PopupNotification.sys.mjs is dependent on + * the monotonically increasing value of performance.now. This timestamp is + * not relative to a fixed date, but to runtime. + * We need to wait for the value performance.now() to be larger than the + * security delay in order to observe the bug. Only then does the + * timeSinceShown check in PopupNotifications.sys.mjs lead to a timeSinceShown + * value that is unconditionally greater than lazy.buttonDelay for + * notification.timeShown = null = 0. + * See: https://searchfox.org/mozilla-central/rev/f32d5f3949a3f4f185122142b29f2e3ab776836e/toolkit/modules/PopupNotifications.sys.mjs#1870-1872 + * + * When running in automation as part of a larger test suite performance.now() + * should usually be already sufficiently high in which case this check should + * directly resolve. + */ async function ensureSecurityDelayReady() { - /** - * The security delay calculation in PopupNotification.sys.mjs is dependent on - * the monotonically increasing value of performance.now. This timestamp is - * not relative to a fixed date, but to runtime. - * We need to wait for the value performance.now() to be larger than the - * security delay in order to observe the bug. Only then does the - * timeSinceShown check in PopupNotifications.sys.mjs lead to a timeSinceShown - * value that is unconditionally greater than lazy.buttonDelay for - * notification.timeShown = null = 0. - * See: https://searchfox.org/mozilla-central/rev/f32d5f3949a3f4f185122142b29f2e3ab776836e/toolkit/modules/PopupNotifications.sys.mjs#1870-1872 - * - * When running in automation as part of a larger test suite performance.now() - * should usually be already sufficiently high in which case this check should - * directly resolve. - */ await TestUtils.waitForCondition( () => performance.now() > TEST_SECURITY_DELAY, "Wait for performance.now() > SECURITY_DELAY", @@ -69,73 +69,73 @@ async function ensureSecurityDelayReady() { } /** - * 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 - * properly. + * 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. */ -add_task(async function test_timeShownMultipleNotifications() { +async function runPopupNotificationSecurityDelayTest({ + onSecurityDelayExpired, + cleanupFn = () => {}, +}) { await ensureSecurityDelayReady(); - ok( - !PopupNotifications.isPanelOpen, - "PopupNotification panel should not be open initially." - ); - - info("Open the first notification."); + info("Open a notification."); let popupShownPromise = waitForNotificationPanel(); showNotification(); await popupShownPromise; ok( PopupNotifications.isPanelOpen, - "PopupNotification should be open after first show call." + "PopupNotification should be open after show call." ); - is( - PopupNotifications._currentNotifications.length, - 1, - "There should only be one notification" + // 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 ); - is(notification?.id, "foo", "There should be a notification with id foo"); - ok(notification.timeShown, "The notification should have timeShown set"); - - info( - "Call show again with the same notification id while the PopupNotification panel is still open." - ); - showNotification(); ok( - PopupNotifications.isPanelOpen, - "PopupNotification should still open after second show call." - ); - notification = PopupNotifications.getNotification( - "foo", - gBrowser.selectedBrowser - ); - is( - PopupNotifications._currentNotifications.length, - 1, - "There should still only be one notification" + 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; + } - is( - notification?.id, - "foo", - "There should still be a notification with id foo" + 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) ); - ok(notification.timeShown, "The notification should have timeShown set"); - let notificationHiddenPromise = waitForNotificationPanelHidden(); - - info("Trigger main action via button click during security delay"); - - // Wait for a tick of the event loop to ensure the button we're clicking - // has been slotted into moz-button-group - await new Promise(resolve => setTimeout(resolve, 0)); + 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)); @@ -149,10 +149,10 @@ add_task(async function test_timeShownMultipleNotifications() { 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; } @@ -163,6 +163,7 @@ add_task(async function test_timeShownMultipleNotifications() { 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."); @@ -170,15 +171,19 @@ add_task(async function test_timeShownMultipleNotifications() { ok( !PopupNotifications.getNotification("foo", gBrowser.selectedBrowser), - "Should not longer see the notification." + "Should no longer see the notification." ); -}); + + info("Cleanup."); + await cleanupFn(); +} /** - * Tests that when we reshow a notification after a tab switch the timeShown - * attribute is correctly reset and the security delay is enforced. + * 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 + * properly. */ -add_task(async function test_notificationReshowTabSwitch() { +add_task(async function test_timeShownMultipleNotifications() { await ensureSecurityDelayReady(); ok( @@ -195,6 +200,12 @@ add_task(async function test_notificationReshowTabSwitch() { "PopupNotification should be open after first show call." ); + is( + PopupNotifications._currentNotifications.length, + 1, + "There should only be one notification" + ); + let notification = PopupNotifications.getNotification( "foo", gBrowser.selectedBrowser @@ -202,69 +213,39 @@ add_task(async function test_notificationReshowTabSwitch() { 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; - } - - let panelHiddenPromise = waitForNotificationPanelHidden(); - let panelShownPromise; - - info("Open a new tab which hides the notification panel."); - 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( - "Wait for the panel to show again after the tab close. We're showing the original tab again." + "Call show again with the same notification id while the PopupNotification panel is still open." ); - await panelShownPromise; - + showNotification(); ok( PopupNotifications.isPanelOpen, - "PopupNotification should be shown after tab close." + "PopupNotification should still open after second show call." ); notification = PopupNotifications.getNotification( "foo", gBrowser.selectedBrowser ); is( + PopupNotifications._currentNotifications.length, + 1, + "There should still only be one notification" + ); + + is( notification?.id, "foo", "There should still be a notification with id foo" ); + ok(notification.timeShown, "The notification should have timeShown set"); 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."); + info("Trigger main action via button click during security delay"); + + // Wait for a tick of the event loop to ensure the button we're clicking + // has been slotted into moz-button-group + await new Promise(resolve => setTimeout(resolve, 0)); + triggerMainCommand(PopupNotifications.panel); await new Promise(resolve => setTimeout(resolve, 0)); @@ -278,6 +259,7 @@ add_task(async function test_notificationReshowTabSwitch() { 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) { @@ -298,109 +280,83 @@ add_task(async function test_notificationReshowTabSwitch() { ok( !PopupNotifications.getNotification("foo", gBrowser.selectedBrowser), - "Should not longer see the notification." + "Should no longer see the notification." ); }); /** + * Tests that when we reshow a notification after a tab switch the timeShown + * attribute is correctly reset and the security delay is enforced. + */ +add_task(async function test_notificationReshowTabSwitch() { + await runPopupNotificationSecurityDelayTest({ + onSecurityDelayExpired: async () => { + let panelHiddenPromise = waitForNotificationPanelHidden(); + let panelShownPromise; + + info("Open a new tab which hides the notification panel."); + await BrowserTestUtils.withNewTab("https://example.com", async () => { + info("Wait for panel to be hidden by tab switch."); + await panelHiddenPromise; + panelShownPromise = waitForNotificationPanel(); + }); + info( + "Wait for the panel to show again after the tab close. We're showing the original tab again." + ); + await panelShownPromise; + + ok( + PopupNotifications.isPanelOpen, + "PopupNotification should be shown after tab close." + ); + let notification = PopupNotifications.getNotification( + "foo", + gBrowser.selectedBrowser + ); + is( + notification?.id, + "foo", + "There should still be a notification with id foo" + ); + + info( + "Because we re-show the panel after tab close / switch the security delay should have reset." + ); + }, + }); +}); + +/** * Tests that the security delay gets reset when a window is repositioned and * 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) - ); - - info("Reposition the window"); - // Remember original window position. - let { screenX, screenY } = window; - - let promisePopupPositioned = BrowserTestUtils.waitForEvent( - PopupNotifications.panel, - "popuppositioned" - ); - - // Move the window. - window.moveTo(200, 200); - - // 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." - ); - - // Reset window position - window.moveTo(screenX, screenY); + let screenX, screenY; + + await runPopupNotificationSecurityDelayTest({ + onSecurityDelayExpired: async () => { + info("Reposition the window"); + // Remember original window position. + screenX = window.screenX; + screenY = window.screenY; + + let promisePopupPositioned = BrowserTestUtils.waitForEvent( + PopupNotifications.panel, + "popuppositioned" + ); + + // Move the window. + window.moveTo(200, 200); + + // Wait for the panel to reposition and the PopupNotifications listener to run. + await promisePopupPositioned; + await new Promise(resolve => setTimeout(resolve, 0)); + }, + cleanupFn: async () => { + // Reset window position + window.moveTo(screenX, screenY); + }, + }); }); /** @@ -563,5 +519,49 @@ add_task(async function test_notificationDuringFullScreenTransition() { info("Wait for full screen transition end."); await promiseFullScreenTransitionEnd; info("Full screen transition end"); + + await SpecialPowers.popPrefEnv(); + }); +}); + +/** + * Tests that the security delay gets extended when pointer lock is entered. + */ +add_task(async function test_notificationPointerLock() { + // We need a tab to enter pointer lock. + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "https://example.com" + ); + + await runPopupNotificationSecurityDelayTest({ + onSecurityDelayExpired: async () => { + info("Enter pointer lock"); + // 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(); + }); + + // Wait for pointer lock to be entered and the PopupNotifications listener to run. + await pointerLockEnterPromise; + await new Promise(resolve => setTimeout(resolve, 0)); + }, + cleanupFn: async () => { + // Cleanup. + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => { + SpecialPowers.wrap(content.document).notifyUserGestureActivation(); + await content.document.exitPointerLock(); + }); + await TestUtils.waitForCondition( + () => !window.PointerLock.isActive, + "Wait for pointer lock exit." + ); + BrowserTestUtils.removeTab(tab); + }, }); }); diff --git a/browser/base/content/test/sidebar/browser_sidebar_adopt.js b/browser/base/content/test/sidebar/browser_sidebar_adopt.js index 344a71cb9b..988ac1487f 100644 --- a/browser/base/content/test/sidebar/browser_sidebar_adopt.js +++ b/browser/base/content/test/sidebar/browser_sidebar_adopt.js @@ -5,7 +5,7 @@ * during the initial browser startup - but it would be hard to do with a mochitest. */ registerCleanupFunction(() => { - SidebarUI.hide(); + SidebarController.hide(); }); function failIfSidebarFocusedFires() { @@ -26,7 +26,7 @@ add_task(async function testAdoptedTwoWindows() { info("Ensure that sidebar state is adopted only from the opener"); let win1 = await BrowserTestUtils.openNewBrowserWindow(); - await win1.SidebarUI.show("viewBookmarksSidebar"); + await win1.SidebarController.show("viewBookmarksSidebar"); await BrowserTestUtils.closeWindow(win1); let win2 = await BrowserTestUtils.openNewBrowserWindow(); @@ -34,7 +34,7 @@ add_task(async function testAdoptedTwoWindows() { !win2.document.getElementById("sidebar-button").hasAttribute("checked"), "Sidebar button isn't checked" ); - ok(!win2.SidebarUI.isOpen, "Sidebar is closed"); + ok(!win2.SidebarController.isOpen, "Sidebar is closed"); await BrowserTestUtils.closeWindow(win2); }); @@ -46,7 +46,7 @@ add_task(async function testEventsReceivedInMainWindow() { let initialShown = BrowserTestUtils.waitForEvent(window, "SidebarShown"); let initialFocus = BrowserTestUtils.waitForEvent(window, "SidebarFocused"); - await SidebarUI.show("viewBookmarksSidebar"); + await SidebarController.show("viewBookmarksSidebar"); await initialShown; await initialFocus; diff --git a/browser/base/content/test/sidebar/browser_sidebar_app_locale_changed.js b/browser/base/content/test/sidebar/browser_sidebar_app_locale_changed.js index 5b07da9839..1e52895a7d 100644 --- a/browser/base/content/test/sidebar/browser_sidebar_app_locale_changed.js +++ b/browser/base/content/test/sidebar/browser_sidebar_app_locale_changed.js @@ -8,7 +8,7 @@ add_task(function cleanup() { registerCleanupFunction(() => { - SidebarUI.hide(); + SidebarController.hide(); }); }); @@ -17,7 +17,7 @@ add_task(function cleanup() { */ async function testLiveReloading(sidebarName) { info("Showing the sidebar " + sidebarName); - await SidebarUI.show(sidebarName); + await SidebarController.show(sidebarName); function getTreeChildren() { const sidebarDoc = @@ -44,7 +44,7 @@ async function testLiveReloading(sidebarName) { ); info("Hiding the sidebar"); - SidebarUI.hide(); + SidebarController.hide(); } add_task(async function test_bookmarks_sidebar() { diff --git a/browser/base/content/test/sidebar/browser_sidebar_keys.js b/browser/base/content/test/sidebar/browser_sidebar_keys.js index f12d1cf5f7..61e4ce9737 100644 --- a/browser/base/content/test/sidebar/browser_sidebar_keys.js +++ b/browser/base/content/test/sidebar/browser_sidebar_keys.js @@ -11,11 +11,11 @@ async function testSidebarKeyToggle(key, options, expectedSidebarId) { expectedSidebarId ); EventUtils.synthesizeKey(key, options); - Assert.ok(!SidebarUI.isOpen); + Assert.ok(!SidebarController.isOpen); } add_task(async function test_sidebar_keys() { - registerCleanupFunction(() => SidebarUI.hide()); + registerCleanupFunction(() => SidebarController.hide()); await testSidebarKeyToggle("b", { accelKey: true }, "viewBookmarksSidebar"); @@ -30,7 +30,7 @@ add_task(async function test_sidebar_in_customize_mode() { let { CustomizableUI } = ChromeUtils.importESModule( "resource:///modules/CustomizableUI.sys.mjs" ); - registerCleanupFunction(() => SidebarUI.hide()); + registerCleanupFunction(() => SidebarController.hide()); let placement = CustomizableUI.getPlacementOfWidget("sidebar-button"); if (!(placement?.area == CustomizableUI.AREA_NAVBAR)) { @@ -55,7 +55,7 @@ add_task(async function test_sidebar_in_customize_mode() { ).a; let promiseShown = BrowserTestUtils.waitForEvent(window, "SidebarShown"); - SidebarUI.show("viewBookmarksSidebar"); + SidebarController.show("viewBookmarksSidebar"); await promiseShown; Assert.greater( @@ -80,8 +80,8 @@ add_task(async function test_sidebar_in_customize_mode() { ); // Attempt toggle - should fail in customize mode. - await SidebarUI.toggle(); - ok(SidebarUI.isOpen, "Sidebar is still open"); + await SidebarController.toggle(); + ok(SidebarController.isOpen, "Sidebar is still open"); // Exit customize mode. This should re-enable the toggle and make the sidebar // toggle widget appear checked again, since toggle() didn't hide the sidebar. @@ -98,8 +98,8 @@ add_task(async function test_sidebar_in_customize_mode() { "Sidebar widget background should appear checked again" ); - await SidebarUI.toggle(); - ok(!SidebarUI.isOpen, "Sidebar is closed"); + await SidebarController.toggle(); + ok(!SidebarController.isOpen, "Sidebar is closed"); Assert.equal( getBGAlpha(), 0, diff --git a/browser/base/content/test/sidebar/browser_sidebar_move.js b/browser/base/content/test/sidebar/browser_sidebar_move.js index d434b3bbd8..05ea9e3322 100644 --- a/browser/base/content/test/sidebar/browser_sidebar_move.js +++ b/browser/base/content/test/sidebar/browser_sidebar_move.js @@ -1,17 +1,17 @@ registerCleanupFunction(() => { Services.prefs.clearUserPref("sidebar.position_start"); - SidebarUI.hide(); + SidebarController.hide(); }); const EXPECTED_START_ORDINALS = [ - ["sidebar-launcher", 1], + ["sidebar-main", 1], ["sidebar-box", 2], ["sidebar-splitter", 3], ["appcontent", 4], ]; const EXPECTED_END_ORDINALS = [ - ["sidebar-launcher", 5], + ["sidebar-main", 5], ["sidebar-box", 4], ["sidebar-splitter", 3], ["appcontent", 2], @@ -25,8 +25,8 @@ function getBrowserChildrenWithOrdinals() { } add_task(async function () { - await SidebarUI.show("viewBookmarksSidebar"); - SidebarUI.showSwitcherPanel(); + await SidebarController.show("viewBookmarksSidebar"); + SidebarController.showSwitcherPanel(); let reversePositionButton = document.getElementById( "sidebar-reverse-position" @@ -43,8 +43,8 @@ add_task(async function () { ok(!box.hasAttribute("positionend"), "Positioned start"); // Moved to right - SidebarUI.reversePosition(); - SidebarUI.showSwitcherPanel(); + SidebarController.reversePosition(); + SidebarController.showSwitcherPanel(); Assert.deepEqual( getBrowserChildrenWithOrdinals(), EXPECTED_END_ORDINALS, @@ -58,8 +58,8 @@ add_task(async function () { ok(box.hasAttribute("positionend"), "Positioned end"); // Moved to back to left - SidebarUI.reversePosition(); - SidebarUI.showSwitcherPanel(); + SidebarController.reversePosition(); + SidebarController.showSwitcherPanel(); Assert.deepEqual( getBrowserChildrenWithOrdinals(), EXPECTED_START_ORDINALS, diff --git a/browser/base/content/test/sidebar/browser_sidebar_persist.js b/browser/base/content/test/sidebar/browser_sidebar_persist.js index fe67bed9e0..4977c7ef0f 100644 --- a/browser/base/content/test/sidebar/browser_sidebar_persist.js +++ b/browser/base/content/test/sidebar/browser_sidebar_persist.js @@ -18,7 +18,7 @@ add_task(async function persist_sidebar_width() { { info("Showing new window and setting sidebar box"); const win = await BrowserTestUtils.openNewBrowserWindow(); - await win.SidebarUI.show("viewBookmarksSidebar"); + await win.SidebarController.show("viewBookmarksSidebar"); win.document.getElementById("sidebar-box").style.width = "100px"; await BrowserTestUtils.closeWindow(win); } @@ -26,7 +26,7 @@ add_task(async function persist_sidebar_width() { { info("Showing new window and seeing persisted width"); const win = await BrowserTestUtils.openNewBrowserWindow(); - await win.SidebarUI.show("viewBookmarksSidebar"); + await win.SidebarController.show("viewBookmarksSidebar"); is( win.document.getElementById("sidebar-box").style.width, "100px", diff --git a/browser/base/content/test/sidebar/browser_sidebar_switcher.js b/browser/base/content/test/sidebar/browser_sidebar_switcher.js index 032c23b029..0fc9e18e01 100644 --- a/browser/base/content/test/sidebar/browser_sidebar_switcher.js +++ b/browser/base/content/test/sidebar/browser_sidebar_switcher.js @@ -1,5 +1,5 @@ registerCleanupFunction(() => { - SidebarUI.hide(); + SidebarController.hide(); }); /** @@ -9,14 +9,14 @@ registerCleanupFunction(() => { */ function showSwitcherPanelPromise() { return new Promise(resolve => { - SidebarUI._switcherPanel.addEventListener( + SidebarController._switcherPanel.addEventListener( "popupshown", () => { resolve(); }, { once: true } ); - SidebarUI.showSwitcherPanel(); + SidebarController.showSwitcherPanel(); }); } @@ -25,7 +25,10 @@ function showSwitcherPanelPromise() { * @returns Promise which resolves when the popup menu is opened */ async function waitForSwitcherPopupShown() { - return BrowserTestUtils.waitForEvent(SidebarUI._switcherPanel, "popupshown"); + return BrowserTestUtils.waitForEvent( + SidebarController._switcherPanel, + "popupshown" + ); } /** @@ -63,7 +66,7 @@ async function testSidebarMenuKeyToggle(key, sidebarTitle) { info(`Testing "${key}" key handling of sidebar menu popup items to access ${sidebarTitle} sidebar`); - Assert.ok(SidebarUI.isOpen, "Sidebar is open"); + Assert.ok(SidebarController.isOpen, "Sidebar is open"); let sidebarSwitcher = document.querySelector("#sidebar-switcher-target"); let sidebar = document.getElementById("sidebar"); @@ -89,7 +92,7 @@ async function testSidebarMenuKeyToggle(key, sidebarTitle) { "The sidebar switcher target button is focused" ); Assert.equal( - SidebarUI._switcherPanel.state, + SidebarController._switcherPanel.state, "closed", "Sidebar menu popup is closed" ); @@ -102,7 +105,7 @@ async function testSidebarMenuKeyToggle(key, sidebarTitle) { await promisePopupShown; Assert.equal( - SidebarUI._switcherPanel.state, + SidebarController._switcherPanel.state, "open", "Sidebar menu popup is open" ); @@ -111,7 +114,7 @@ async function testSidebarMenuKeyToggle(key, sidebarTitle) { let arrowDown = async (menuitemId, msg) => { let menuItemActive = BrowserTestUtils.waitForEvent( - SidebarUI._switcherPanel, + SidebarController._switcherPanel, "DOMMenuItemActive" ); EventUtils.synthesizeKey("KEY_ArrowDown", {}); @@ -149,18 +152,18 @@ async function testSidebarMenuKeyToggle(key, sidebarTitle) { info("Testing keyboard navigation when a sidebar menu popup is closed"); Assert.equal( - SidebarUI._switcherPanel.state, + SidebarController._switcherPanel.state, "closed", "Sidebar menu popup is closed" ); // Test the sidebar panel is updated Assert.equal( - SidebarUI._box.getAttribute("sidebarcommand"), + SidebarController._box.getAttribute("sidebarcommand"), `view${sidebarTitle}Sidebar` /* e.g. "viewHistorySidebar" */, `${sidebarTitle} sidebar loaded` ); Assert.equal( - SidebarUI.currentID, + SidebarController.currentID, `view${sidebarTitle}Sidebar` /* e.g. "viewHistorySidebar" */, `${sidebarTitle}'s current ID is updated to a target view` ); @@ -173,7 +176,7 @@ add_task(async function markup() { false, "Unexpected sidebar found - a previous test failed to cleanup correctly" ); - SidebarUI.hide(); + SidebarController.hide(); } let sidebarPopup = document.querySelector("#sidebarMenu-popup"); @@ -205,7 +208,7 @@ add_task(async function markup() { info("Test dynamic changes in the markup of the sidebar switcher control"); - await SidebarUI.show("viewBookmarksSidebar"); + await SidebarController.show("viewBookmarksSidebar"); await showSwitcherPanelPromise(); Assert.equal( @@ -229,25 +232,25 @@ add_task(async function markup() { "Sidebar switcher button is collapsed when a sidebar menu is dismissed" ); - SidebarUI.hide(); + SidebarController.hide(); }); add_task(async function keynav() { // If a sidebar is already open, close it. - if (SidebarUI.isOpen) { + if (SidebarController.isOpen) { Assert.ok( false, "Unexpected sidebar found - a previous test failed to cleanup correctly" ); - SidebarUI.hide(); + SidebarController.hide(); } - await SidebarUI.show("viewBookmarksSidebar"); + await SidebarController.show("viewBookmarksSidebar"); await testSidebarMenuKeyToggle("KEY_Enter", "History"); await testSidebarMenuKeyToggle(" ", "Tabs"); - SidebarUI.hide(); + SidebarController.hide(); }); add_task(async function mouse() { @@ -257,11 +260,11 @@ add_task(async function mouse() { false, "Unexpected sidebar found - a previous test failed to cleanup correctly" ); - SidebarUI.hide(); + SidebarController.hide(); } let sidebar = document.querySelector("#sidebar-box"); - await SidebarUI.show("viewBookmarksSidebar"); + await SidebarController.show("viewBookmarksSidebar"); await showSwitcherPanelPromise(); await pickSwitcherMenuitem("#sidebar-switcher-history"); diff --git a/browser/base/content/test/static/browser_all_files_referenced.js b/browser/base/content/test/static/browser_all_files_referenced.js index d73c3fe8de..9668288181 100644 --- a/browser/base/content/test/static/browser_all_files_referenced.js +++ b/browser/base/content/test/static/browser_all_files_referenced.js @@ -276,12 +276,6 @@ var allowlist = [ // find the references) { file: "chrome://browser/content/screenshots/copied-notification.svg" }, - // Bug 1875361 - { file: "chrome://global/content/ml/SummarizerModel.sys.mjs" }, - - // Bug 1886130 - { file: "chrome://global/content/ml/ModelHub.sys.mjs" }, - // toolkit/xre/MacRunFromDmgUtils.mm { file: "resource://gre/localization/en-US/toolkit/global/run-from-dmg.ftl" }, @@ -290,6 +284,12 @@ var allowlist = [ { file: "chrome://browser/content/screenshots/copy.svg" }, { file: "chrome://browser/content/screenshots/download.svg" }, { file: "chrome://browser/content/screenshots/download-white.svg" }, + + // Referenced programmatically + { file: "chrome://browser/content/backup/BackupManifest.1.schema.json" }, + + // Bug 1892002 + { file: "resource://app/modules/TopSites.sys.mjs" }, ]; if (AppConstants.NIGHTLY_BUILD) { @@ -301,6 +301,10 @@ if (AppConstants.NIGHTLY_BUILD) { // A debug tool that is only available in Nightly builds, and is accessed // directly by developers via the chrome URI (bug 1888491) { file: "chrome://browser/content/backup/debug.html" }, + + // The Transformers.js prod lib is not used in Nightly builds + { file: "chrome://global/content/ml/transformers.js" }, + { file: "chrome://global/content/ml/ort.js" }, ] ); } diff --git a/browser/base/content/test/static/browser_parsable_css.js b/browser/base/content/test/static/browser_parsable_css.js index fb91da578a..6b075fc98f 100644 --- a/browser/base/content/test/static/browser_parsable_css.js +++ b/browser/base/content/test/static/browser_parsable_css.js @@ -36,6 +36,12 @@ let ignoreList = [ errorMessage: /Unknown property.*overflow-clip-box/i, isFromDevTools: false, }, + // content: -moz-alt-content is UA-only. + { + sourceName: /\b(html)\.css$/i, + errorMessage: /Error in parsing value for ‘content’/i, + isFromDevTools: false, + }, // These variables are declared somewhere else, and error when we load the // files directly. They're all marked intermittent because their appearance // in the error console seems to not be consistent. diff --git a/browser/base/content/test/static/browser_parsable_script.js b/browser/base/content/test/static/browser_parsable_script.js index 3d8fbc1535..71a2930ddc 100644 --- a/browser/base/content/test/static/browser_parsable_script.js +++ b/browser/base/content/test/static/browser_parsable_script.js @@ -19,6 +19,7 @@ const kESModuleList = new Set([ /browser\/vpn-card.js$/, /toolkit\/content\/global\/certviewer\/components\/.*\.js$/, /toolkit\/content\/global\/certviewer\/.*\.js$/, + /toolkit\/content\/global\/ml\/transformers.*\.js$/, /chrome\/pdfjs\/content\/web\/.*\.js$/, ]); diff --git a/browser/base/content/test/static/browser_sentence_case_strings.js b/browser/base/content/test/static/browser_sentence_case_strings.js index e995f76b1a..12952c9600 100644 --- a/browser/base/content/test/static/browser_sentence_case_strings.js +++ b/browser/base/content/test/static/browser_sentence_case_strings.js @@ -103,7 +103,7 @@ function checkSubheaders(view) { } async function checkUpdateBanner(view) { - let banner = view.querySelector("#appMenu-proton-update-banner"); + let banner = view.querySelector("#appMenu-update-banner"); const notifications = [ "update-downloading", diff --git a/browser/base/content/test/sync/browser_contextmenu_sendpage.js b/browser/base/content/test/sync/browser_contextmenu_sendpage.js index a80cf8a1d0..14b5f72860 100644 --- a/browser/base/content/test/sync/browser_contextmenu_sendpage.js +++ b/browser/base/content/test/sync/browser_contextmenu_sendpage.js @@ -93,47 +93,44 @@ add_task(async function test_link_contextmenu() { "context-sendlinktodevice-popup" ); - let expectedArray = ["context-openlinkintab"]; - - if ( + const expectOpenLinkInUserContextMenu = Services.prefs.getBoolPref("privacy.userContext.enabled") && - ContextualIdentityService.getPublicIdentities().length - ) { - expectedArray.push("context-openlinkinusercontext-menu"); - } + ContextualIdentityService.getPublicIdentities().length; + + const expectStripOnShareLink = Services.prefs.getBoolPref( + "privacy.query_stripping.strip_on_share.enabled" + ); + + const expectTranslateSelection = + Services.prefs.getBoolPref("browser.translations.enable") && + Services.prefs.getBoolPref("browser.translations.select.enable"); - expectedArray.push( + const expectInspectAccessibility = + Services.prefs.getBoolPref("devtools.accessibility.enabled", true) && + (Services.prefs.getBoolPref("devtools.everOpened", false) || + Services.prefs.getIntPref("devtools.selfxss.count", 0) > 0); + + const expectedArray = [ + "context-openlinkintab", + ...(expectOpenLinkInUserContextMenu + ? ["context-openlinkinusercontext-menu"] + : []), "context-openlink", "context-openlinkprivate", "context-sep-open", "context-bookmarklink", "context-savelink", "context-savelinktopocket", - "context-copylink" - ); - - if ( - Services.prefs.getBoolPref("privacy.query_stripping.strip_on_share.enabled") - ) { - expectedArray.push("context-stripOnShareLink"); - } - - expectedArray.push( + "context-copylink", + ...(expectStripOnShareLink ? ["context-stripOnShareLink"] : []), "context-sendlinktodevice", "context-sep-sendlinktodevice", "context-searchselect", - "frame-sep" - ); - - if ( - Services.prefs.getBoolPref("devtools.accessibility.enabled", true) && - (Services.prefs.getBoolPref("devtools.everOpened", false) || - Services.prefs.getIntPref("devtools.selfxss.count", 0) > 0) - ) { - expectedArray.push("context-inspect-a11y"); - } - - expectedArray.push("context-inspect"); + ...(expectTranslateSelection ? ["context-translate-selection"] : []), + "frame-sep", + ...(expectInspectAccessibility ? ["context-inspect-a11y"] : []), + "context-inspect", + ]; let menu = document.getElementById("contentAreaContextMenu"); diff --git a/browser/base/content/test/sync/browser_sync.js b/browser/base/content/test/sync/browser_sync.js index 8f687842a4..03077ea67c 100644 --- a/browser/base/content/test/sync/browser_sync.js +++ b/browser/base/content/test/sync/browser_sync.js @@ -607,17 +607,20 @@ add_task(async function test_experiment_ui_state_unconfigured() { checkFxAAvatar("not_configured"); let expectedLabel = gSync.fluentStrings.formatValueSync( - "appmenuitem-sign-in-account" + "synced-tabs-fxa-sign-in" + ); + + let expectedDescriptionLabel = gSync.fluentStrings.formatValueSync( + "fxa-menu-sync-description" ); await openMainPanel(); checkFxaToolbarButtonPanel({ headerTitle: expectedLabel, - headerDescription: "", + headerDescription: expectedDescriptionLabel, enabledItems: [ "PanelUI-fxa-cta-menu", - "PanelUI-fxa-menu-sync-button", "PanelUI-fxa-menu-monitor-button", "PanelUI-fxa-menu-relay-button", "PanelUI-fxa-menu-vpn-button", @@ -690,7 +693,6 @@ add_task(async function test_experiment_ui_state_signedin() { "PanelUI-fxa-menu-sync-prefs-button", "PanelUI-fxa-menu-account-signout-button", "PanelUI-fxa-cta-menu", - "PanelUI-fxa-menu-sync-button", "PanelUI-fxa-menu-monitor-button", "PanelUI-fxa-menu-relay-button", "PanelUI-fxa-menu-vpn-button", diff --git a/browser/base/content/test/tabPrompts/browser.toml b/browser/base/content/test/tabPrompts/browser.toml index 037f1f0d2b..aa7d4c724e 100644 --- a/browser/base/content/test/tabPrompts/browser.toml +++ b/browser/base/content/test/tabPrompts/browser.toml @@ -39,6 +39,8 @@ support-files = ["file_beforeunload_stop.html"] https_first_disabled = true support-files = ["openPromptOffTimeout.html"] +["browser_promptDelays.js"] + ["browser_promptFocus.js"] ["browser_prompt_close_event.js"] diff --git a/browser/base/content/test/tabPrompts/browser_promptDelays.js b/browser/base/content/test/tabPrompts/browser_promptDelays.js new file mode 100644 index 0000000000..ecd01cdb69 --- /dev/null +++ b/browser/base/content/test/tabPrompts/browser_promptDelays.js @@ -0,0 +1,113 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const PERMISSION_DIALOG = + "chrome://mozapps/content/handling/permissionDialog.xhtml"; + +add_setup(async function () { + // Set a new handler as default. + const protoSvc = Cc[ + "@mozilla.org/uriloader/external-protocol-service;1" + ].getService(Ci.nsIExternalProtocolService); + let protoInfo = protoSvc.getProtocolHandlerInfo("web+testprotocol"); + protoInfo.preferredAction = protoInfo.useHelperApp; + let handler = Cc["@mozilla.org/uriloader/web-handler-app;1"].createInstance( + Ci.nsIWebHandlerApp + ); + handler.uriTemplate = "https://example.com/foobar?uri=%s"; + handler.name = "Test protocol"; + let handlers = protoInfo.possibleApplicationHandlers; + handlers.appendElement(handler); + + protoInfo.preferredApplicationHandler = handler; + protoInfo.alwaysAskBeforeHandling = false; + + const handlerSvc = Cc["@mozilla.org/uriloader/handler-service;1"].getService( + Ci.nsIHandlerService + ); + handlerSvc.store(protoInfo); + + registerCleanupFunction(() => { + handlerSvc.remove(protoInfo); + }); +}); + +add_task(async function test_promptWhileNotForeground() { + await BrowserTestUtils.withNewTab("about:blank", async browser => { + let windowOpened = BrowserTestUtils.waitForNewWindow(); + await SpecialPowers.spawn(browser, [], () => { + content.eval(`window.open('about:blank', "_blank", "height=600");`); + }); + let otherWin = await windowOpened; + info("Opened extra window, now start a prompt."); + + // To ensure we test the delay helper correctly, shorten the delay: + await SpecialPowers.pushPrefEnv({ + set: [["security.dialog_enable_delay", 50]], + }); + + let promptPromise = BrowserTestUtils.promiseAlertDialogOpen( + null, + PERMISSION_DIALOG, + { isSubDialog: true } + ); + await SpecialPowers.spawn(browser, [], () => { + content.document.location.href = "web+testprotocol:hello"; + }); + info("Started opening prompt."); + let prompt = await promptPromise; + info("Opened prompt."); + let dialog = prompt.document.querySelector("dialog"); + let button = dialog.getButton("accept"); + is(button.getAttribute("disabled"), "true", "Button should be disabled"); + + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + await new Promise(r => setTimeout(r, 500)); + is( + button.getAttribute("disabled"), + "true", + "Button should still be disabled while the dialog is in the background" + ); + + let buttonGetsEnabled = BrowserTestUtils.waitForMutationCondition( + button, + { attributeFilter: ["disabled"] }, + () => button.getAttribute("disabled") != "true" + ); + await BrowserTestUtils.closeWindow(otherWin); + info("Waiting for button to be enabled."); + await buttonGetsEnabled; + ok(true, "The button was enabled."); + dialog.cancelDialog(); + + await SpecialPowers.popPrefEnv(); + }); +}); + +add_task(async function test_promptWhileForeground() { + await BrowserTestUtils.withNewTab("about:blank", async browser => { + let promptPromise = BrowserTestUtils.promiseAlertDialogOpen( + null, + PERMISSION_DIALOG, + { isSubDialog: true } + ); + await SpecialPowers.spawn(browser, [], () => { + content.document.location.href = "web+testprotocol:hello"; + }); + info("Started opening prompt."); + let prompt = await promptPromise; + info("Opened prompt."); + let dialog = prompt.document.querySelector("dialog"); + let button = dialog.getButton("accept"); + is(button.getAttribute("disabled"), "true", "Button should be disabled"); + await BrowserTestUtils.waitForMutationCondition( + button, + { attributeFilter: ["disabled"] }, + () => button.getAttribute("disabled") != "true" + ); + ok(true, "The button was enabled."); + dialog.cancelDialog(); + }); +}); diff --git a/browser/base/content/test/tabPrompts/browser_promptFocus.js b/browser/base/content/test/tabPrompts/browser_promptFocus.js index 89ca064c10..cab812f57b 100644 --- a/browser/base/content/test/tabPrompts/browser_promptFocus.js +++ b/browser/base/content/test/tabPrompts/browser_promptFocus.js @@ -20,8 +20,7 @@ add_task(async function test_tabdialogbox_tab_switch_focus() { tabPromises.push( BrowserTestUtils.openNewForegroundTab( gBrowser, - // eslint-disable-next-line @microsoft/sdl/no-insecure-url - "http://example.com", + "https://example.com", true ) ); diff --git a/browser/base/content/test/tabs/browser.toml b/browser/base/content/test/tabs/browser.toml index fa77a8b1a4..8a95c87a6e 100644 --- a/browser/base/content/test/tabs/browser.toml +++ b/browser/base/content/test/tabs/browser.toml @@ -30,6 +30,8 @@ skip-if = [ ["browser_bfcache_exemption_about_pages.js"] skip-if = ["!fission"] +["browser_blank_tab_label.js"] + ["browser_bug580956.js"] ["browser_bug_1387976_restore_lazy_tab_browser_muted_state.js"] @@ -140,6 +142,8 @@ support-files = [ ["browser_multiselect_tabs_close.js"] +["browser_multiselect_tabs_close_duplicate_tabs.js"] + ["browser_multiselect_tabs_close_other_tabs.js"] ["browser_multiselect_tabs_close_tabs_to_the_left.js"] diff --git a/browser/base/content/test/tabs/browser_blank_tab_label.js b/browser/base/content/test/tabs/browser_blank_tab_label.js new file mode 100644 index 0000000000..9fe5f6b1b0 --- /dev/null +++ b/browser/base/content/test/tabs/browser_blank_tab_label.js @@ -0,0 +1,49 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Ensure that we don't use an entirely-blank (non-printable) document title + * as the tab label. + */ +add_task(async function test_ensure_printable_label() { + const TEST_DOC = ` + <!DOCTYPE html> + <meta charset="utf-8"> + <!-- Title is NO-BREAK SPACE, COMBINING ACUTE ACCENT, ARABIC LETTER MARK --> + <title> &%23x0301;&%23x061C;</title> + Is my title blank?`; + + let newTab; + function tabLabelChecker() { + Assert.stringMatches( + newTab.label, + /\p{L}|\p{N}|\p{P}|\p{S}/u, + "Tab label should contain printable character." + ); + } + let mutationObserver = new MutationObserver(tabLabelChecker); + registerCleanupFunction(() => mutationObserver.disconnect()); + + gBrowser.tabContainer.addEventListener( + "TabOpen", + event => { + newTab = event.target; + tabLabelChecker(); + mutationObserver.observe(newTab, { + attributeFilter: ["label"], + }); + }, + { once: true } + ); + + await BrowserTestUtils.withNewTab("data:text/html," + TEST_DOC, async () => { + // Wait another longer-than-tick to ensure more mutation observer things have + // come in. + await new Promise(executeSoon); + + // Check one last time for good measure, for the final label: + tabLabelChecker(); + }); +}); diff --git a/browser/base/content/test/tabs/browser_multiselect_tabs_close_duplicate_tabs.js b/browser/base/content/test/tabs/browser_multiselect_tabs_close_duplicate_tabs.js new file mode 100644 index 0000000000..d18795447f --- /dev/null +++ b/browser/base/content/test/tabs/browser_multiselect_tabs_close_duplicate_tabs.js @@ -0,0 +1,178 @@ +const PREF_WARN_ON_CLOSE = "browser.tabs.warnOnCloseOtherTabs"; +const PREF_SHOWN_DUPE_DIALOG = + "browser.tabs.haveShownCloseAllDuplicateTabsWarning"; + +add_task(async function setPref() { + await SpecialPowers.pushPrefEnv({ + set: [ + [PREF_WARN_ON_CLOSE, false], + [PREF_SHOWN_DUPE_DIALOG, true], + ], + }); +}); + +add_task(async function withAMultiSelectedTab() { + let initialTab = gBrowser.selectedTab; + let tab1 = await addTab(); + let tab2 = await addTab(); + let tab3 = await addTab(); + let tab4 = await addTab(); + + is(gBrowser.multiSelectedTabsCount, 0, "Zero multiselected tabs"); + + await triggerClickOn(tab1, { ctrlKey: true }); + + let tab4Pinned = BrowserTestUtils.waitForEvent(tab4, "TabPinned"); + gBrowser.pinTab(tab4); + await tab4Pinned; + + ok(initialTab.multiselected, "InitialTab is multiselected"); + ok(tab1.multiselected, "Tab1 is multiselected"); + ok(!tab2.multiselected, "Tab2 is not multiselected"); + ok(!tab3.multiselected, "Tab3 is not multiselected"); + ok(!tab4.multiselected, "Tab4 is not multiselected"); + ok(tab4.pinned, "Tab4 is pinned"); + is(gBrowser.multiSelectedTabsCount, 2, "Two multiselected tabs"); + is(gBrowser.selectedTab, initialTab, "InitialTab is the active tab"); + + let closingTabs = [tab2, tab3]; + let tabClosingPromises = []; + for (let tab of closingTabs) { + tabClosingPromises.push(BrowserTestUtils.waitForTabClosing(tab)); + } + + gBrowser.removeDuplicateTabs(tab1); + + await Promise.all(tabClosingPromises); + + ok(!initialTab.closing, "InitialTab is not closing"); + ok(!tab1.closing, "Tab1 is not closing"); + ok(tab2.closing, "Tab2 is closing"); + ok(tab3.closing, "Tab3 is closing"); + ok(!tab4.closing, "Tab4 is not closing"); + is(gBrowser.multiSelectedTabsCount, 2, "Two multiselected tabs"); + is(gBrowser.selectedTab, initialTab, "InitialTab is still the active tab"); + + gBrowser.clearMultiSelectedTabs(); + BrowserTestUtils.removeTab(tab1); + BrowserTestUtils.removeTab(tab4); +}); + +add_task(async function withNotAMultiSelectedTab() { + let initialTab = gBrowser.selectedTab; + let tab1 = await addTab("http://mochi.test:8888/"); + let tab2 = await addTab("http://mochi.test:8888/"); + let tab3 = await addTab("http://mochi.test:8888/"); + let tab4 = await addTab("http://mochi.test:8888/"); + let tab5 = await addTab("http://mochi.test:8888/"); + let tab6 = await addTab("http://mochi.test:8888/", { userContextId: 1 }); + + is(gBrowser.multiSelectedTabsCount, 0, "Zero multiselected tabs"); + + await BrowserTestUtils.switchTab(gBrowser, tab1); + await triggerClickOn(tab2, { ctrlKey: true }); + await triggerClickOn(tab5, { ctrlKey: true }); + + let tab4Pinned = BrowserTestUtils.waitForEvent(tab4, "TabPinned"); + gBrowser.pinTab(tab4); + await tab4Pinned; + + let tab5Pinned = BrowserTestUtils.waitForEvent(tab5, "TabPinned"); + gBrowser.pinTab(tab5); + await tab5Pinned; + + ok(!initialTab.multiselected, "InitialTab is not multiselected"); + ok(tab1.multiselected, "Tab1 is multiselected"); + ok(tab2.multiselected, "Tab2 is multiselected"); + ok(!tab3.multiselected, "Tab3 is not multiselected"); + ok(!tab4.multiselected, "Tab4 is not multiselected"); + ok(tab4.pinned, "Tab4 is pinned"); + ok(tab5.multiselected, "Tab5 is multiselected"); + ok(tab5.pinned, "Tab5 is pinned"); + ok(!tab6.multiselected, "Tab6 is not multiselected"); + ok(!tab6.pinned, "Tab6 is not pinned"); + is(gBrowser.multiSelectedTabsCount, 3, "Three multiselected tabs"); + is(gBrowser.selectedTab, tab1, "Tab1 is the active tab"); + + let closingTabs = [tab1, tab2]; + let tabClosingPromises = []; + for (let tab of closingTabs) { + tabClosingPromises.push(BrowserTestUtils.waitForTabClosing(tab)); + } + + await BrowserTestUtils.switchTab( + gBrowser, + gBrowser.removeDuplicateTabs(tab3) + ); + + await Promise.all(tabClosingPromises); + + ok(!initialTab.closing, "InitialTab is not closing"); + ok(tab1.closing, "Tab1 is closing"); + ok(tab2.closing, "Tab2 is closing"); + ok(!tab3.closing, "Tab3 is not closing"); + ok(!tab4.closing, "Tab4 is not closing"); + ok(!tab5.closing, "Tab5 is not closing"); + ok(!tab6.closing, "Tab6 is not closing"); + is( + gBrowser.multiSelectedTabsCount, + 0, + "Zero multiselected tabs, selection is cleared" + ); + is(gBrowser.selectedTab, tab3, "tab3 is the active tab now"); + + for (let tab of [tab3, tab4, tab5, tab6]) { + BrowserTestUtils.removeTab(tab); + } +}); + +add_task(async function closeAllDuplicateTabs() { + let initialTab = gBrowser.selectedTab; + let tab1 = await addTab("http://mochi.test:8888/one"); + let tab2 = await addTab("http://mochi.test:8888/two", { userContextId: 1 }); + let tab3 = await addTab("http://mochi.test:8888/one"); + let tab4 = await addTab("http://mochi.test:8888/two"); + let tab5 = await addTab("http://mochi.test:8888/one"); + let tab6 = await addTab("http://mochi.test:8888/two"); + + let tab1Pinned = BrowserTestUtils.waitForEvent(tab1, "TabPinned"); + gBrowser.pinTab(tab1); + await tab1Pinned; + + // So we have 1p,2c,1,2,1,2 + // We expect 1p,2c,X,2,X,X because the pinned 1 will dupe the other two 1, + // but the 2c's userContextId makes it unique against the other two 2, + // but one of the other two 2 will close. + + // Ensure tab4 remains by making it active more recently than tab6. + tab4._lastSeenActive = Date.now(); // as recent as it gets. + + // Assert some preconditions: + ok(tab1.pinned, "Tab1 is pinned"); + Assert.greater(tab4.lastSeenActive, tab6.lastSeenActive); + + let closingTabs = [tab3, tab5, tab6]; + let tabClosingPromises = []; + for (let tab of closingTabs) { + tabClosingPromises.push(BrowserTestUtils.waitForTabClosing(tab)); + } + + await BrowserTestUtils.switchTab( + gBrowser, + gBrowser.removeAllDuplicateTabs(initialTab) + ); + + await Promise.all(tabClosingPromises); + + ok(!initialTab.closing, "InitialTab is not closing"); + ok(!tab1.closing, "Tab1 is not closing"); + ok(!tab2.closing, "Tab2 is not closing"); + ok(tab3.closing, "Tab3 is closing"); + ok(!tab4.closing, "Tab4 is not closing"); + ok(tab5.closing, "Tab5 is closing"); + ok(tab6.closing, "Tab6 is closing"); + + for (let tab of [tab1, tab2, tab4]) { + BrowserTestUtils.removeTab(tab); + } +}); diff --git a/browser/base/content/test/tabs/browser_tab_preview.js b/browser/base/content/test/tabs/browser_tab_preview.js index 0f83b1e28c..19ba85b9f8 100644 --- a/browser/base/content/test/tabs/browser_tab_preview.js +++ b/browser/base/content/test/tabs/browser_tab_preview.js @@ -34,6 +34,7 @@ add_setup(async function () { set: [ ["browser.tabs.cardPreview.enabled", true], ["browser.tabs.cardPreview.showThumbnails", false], + ["browser.tabs.tooltipsShowPidAndActiveness", false], ["ui.tooltip.delay_ms", 0], ], }); @@ -82,6 +83,99 @@ add_task(async function hoverTests() { }); /** + * Verify that the pid and activeness statuses are not shown + * when the flag is not enabled. + */ +add_task(async function pidAndActivenessHiddenByDefaultTests() { + const tabUrl1 = + "data:text/html,<html><head><title>First New Tab</title></head><body>Hello</body></html>"; + const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, tabUrl1); + const previewContainer = document.getElementById("tab-preview-panel"); + + await openPreview(tab1); + Assert.equal( + previewContainer.querySelector(".tab-preview-pid").innerText, + "", + "Tab PID is not shown" + ); + Assert.equal( + previewContainer.querySelector(".tab-preview-activeness").innerText, + "", + "Tab activeness is not shown" + ); + + await closePreviews(); + + BrowserTestUtils.removeTab(tab1); + + // Move the mouse outside of the tab strip. + EventUtils.synthesizeMouseAtCenter(document.documentElement, { + type: "mouseover", + }); +}); + +add_task(async function pidAndActivenessTests() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.tabs.tooltipsShowPidAndActiveness", true]], + }); + + const tabUrl1 = + "data:text/html,<html><head><title>Single process tab</title></head><body>Hello</body></html>"; + const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, tabUrl1); + const tabUrl2 = `data:text/html,<html> + <head> + <title>Multi-process tab</title> + </head> + <body> + <iframe + id="inlineFrameExample" + title="Inline Frame Example" + width="300" + height="200" + src="https://example.com"> + </iframe> + </body> + </html>`; + const tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, tabUrl2); + const previewContainer = document.getElementById("tab-preview-panel"); + + await openPreview(tab1); + Assert.stringMatches( + previewContainer.querySelector(".tab-preview-pid").innerText, + /^pid: \d+$/, + "Tab PID is shown on single process tab" + ); + Assert.equal( + previewContainer.querySelector(".tab-preview-activeness").innerText, + "", + "Tab activeness is not shown on inactive tab" + ); + await closePreviews(); + + await openPreview(tab2); + Assert.stringMatches( + previewContainer.querySelector(".tab-preview-pid").innerText, + /^pids: \d+, \d+$/, + "Tab PIDs are shown on multi-process tab" + ); + Assert.equal( + previewContainer.querySelector(".tab-preview-activeness").innerText, + "[A]", + "Tab activeness is shown on active tab" + ); + await closePreviews(); + + BrowserTestUtils.removeTab(tab1); + BrowserTestUtils.removeTab(tab2); + await SpecialPowers.popPrefEnv(); + + // Move the mouse outside of the tab strip. + EventUtils.synthesizeMouseAtCenter(document.documentElement, { + type: "mouseover", + }); +}); + +/** * Verify that non-selected tabs display a thumbnail in their preview * when browser.tabs.cardPreview.showThumbnails is set to true, * while the currently selected tab never displays a thumbnail in its preview. diff --git a/browser/base/content/test/tabs/browser_visibleTabs_contextMenu.js b/browser/base/content/test/tabs/browser_visibleTabs_contextMenu.js index 202c43ce47..06fdd27d9c 100644 --- a/browser/base/content/test/tabs/browser_visibleTabs_contextMenu.js +++ b/browser/base/content/test/tabs/browser_visibleTabs_contextMenu.js @@ -2,11 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -const remoteClientsFixture = [ - { id: 1, name: "Foo" }, - { id: 2, name: "Bar" }, -]; - add_task(async function test() { // There should be one tab when we start the test let [origTab] = gBrowser.visibleTabs; @@ -16,9 +11,8 @@ add_task(async function test() { // Check the context menu with two tabs updateTabContextMenu(origTab); - is( - document.getElementById("context_closeTab").disabled, - false, + ok( + !document.getElementById("context_closeTab").disabled, "Close Tab is enabled" ); @@ -29,11 +23,14 @@ add_task(async function test() { // Check the context menu with one tab. updateTabContextMenu(testTab); - is( - document.getElementById("context_closeTab").disabled, - false, + ok( + !document.getElementById("context_closeTab").disabled, "Close Tab is enabled when more than one tab exists" ); + ok( + !document.getElementById("context_closeDuplicateTabs").disabled, + "Close duplicate tabs is enabled when more than one tab with the same URL exists" + ); // Add a tab that will get pinned // So now there's one pinned tab, one visible unpinned tab, and one hidden tab diff --git a/browser/base/content/test/webextensions/browser_aboutaddons_blanktab.js b/browser/base/content/test/webextensions/browser_aboutaddons_blanktab.js index 228fe71815..1e0814ea96 100644 --- a/browser/base/content/test/webextensions/browser_aboutaddons_blanktab.js +++ b/browser/base/content/test/webextensions/browser_aboutaddons_blanktab.js @@ -8,7 +8,7 @@ add_task(async function testBlankTabReusedAboutAddons() { is(browser, gBrowser.selectedBrowser, "New tab is selected"); // Opening about:addons shouldn't change the selected tab. - BrowserOpenAddonsMgr(); + BrowserAddonUI.openAddonsMgr(); is(browser, gBrowser.selectedBrowser, "No new tab was opened"); diff --git a/browser/base/content/test/webextensions/browser_extension_sideloading.js b/browser/base/content/test/webextensions/browser_extension_sideloading.js index 4e1fe07194..5d8f82a178 100644 --- a/browser/base/content/test/webextensions/browser_extension_sideloading.js +++ b/browser/base/content/test/webextensions/browser_extension_sideloading.js @@ -16,11 +16,14 @@ const kSideloaded = true; async function createWebExtension(details) { let options = { manifest: { + manifest_version: details.manifest_version ?? 2, + browser_specific_settings: { gecko: { id: details.id } }, name: details.name, permissions: details.permissions, + host_permissions: details.host_permissions, }, }; @@ -86,9 +89,10 @@ add_task(async function test_sideloading() { const ID2 = "addon2@tests.mozilla.org"; await createWebExtension({ + manifest_version: 3, id: ID2, name: "Test 2", - permissions: ["<all_urls>"], + host_permissions: ["<all_urls>"], }); const ID3 = "addon3@tests.mozilla.org"; @@ -224,7 +228,7 @@ add_task(async function test_sideloading() { // Close the hamburger menu and go directly to the addons manager await gCUITestUtils.hideMainMenu(); - win = await BrowserOpenAddonsMgr(VIEW); + win = await BrowserAddonUI.openAddonsMgr(VIEW); await waitAboutAddonsViewLoaded(win.document); // about:addons addon entry element. @@ -293,7 +297,7 @@ add_task(async function test_sideloading() { // Close the hamburger menu and go to the detail page for this addon await gCUITestUtils.hideMainMenu(); - win = await BrowserOpenAddonsMgr( + win = await BrowserAddonUI.openAddonsMgr( `addons://detail/${encodeURIComponent(ID3)}` ); diff --git a/browser/base/content/test/webextensions/browser_permissions_local_file.js b/browser/base/content/test/webextensions/browser_permissions_local_file.js index 22dff8cb38..731e8adea7 100644 --- a/browser/base/content/test/webextensions/browser_permissions_local_file.js +++ b/browser/base/content/test/webextensions/browser_permissions_local_file.js @@ -14,7 +14,9 @@ async function installFile(filename) { MockFilePicker.setFiles([file]); MockFilePicker.afterOpenCallback = MockFilePicker.cleanup; - let { document } = await BrowserOpenAddonsMgr("addons://list/extension"); + let { document } = await BrowserAddonUI.openAddonsMgr( + "addons://list/extension" + ); // Do the install... await waitAboutAddonsViewLoaded(document); diff --git a/browser/base/content/test/webextensions/browser_update_interactive_noprompt.js b/browser/base/content/test/webextensions/browser_update_interactive_noprompt.js index 0b0b912503..9ad3deaae1 100644 --- a/browser/base/content/test/webextensions/browser_update_interactive_noprompt.js +++ b/browser/base/content/test/webextensions/browser_update_interactive_noprompt.js @@ -36,7 +36,7 @@ async function testUpdateNoPrompt( is(addon.version, initialVersion, "Version 1 of the addon is installed"); // Go to Extensions in about:addons - let win = await BrowserOpenAddonsMgr("addons://list/extension"); + let win = await BrowserAddonUI.openAddonsMgr("addons://list/extension"); await waitAboutAddonsViewLoaded(win.document); diff --git a/browser/base/content/test/webextensions/head.js b/browser/base/content/test/webextensions/head.js index f1183c61b8..f364dbed88 100644 --- a/browser/base/content/test/webextensions/head.js +++ b/browser/base/content/test/webextensions/head.js @@ -508,7 +508,7 @@ async function interactiveUpdateTest(autoUpdate, checkFn) { ok(addon, "Addon was installed"); is(addon.version, "1.0", "Version 1 of the addon is installed"); - let win = await BrowserOpenAddonsMgr("addons://list/extension"); + let win = await BrowserAddonUI.openAddonsMgr("addons://list/extension"); await waitAboutAddonsViewLoaded(win.document); |