summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test
diff options
context:
space:
mode:
Diffstat (limited to 'browser/base/content/test')
-rw-r--r--browser/base/content/test/about/browser.toml1
-rw-r--r--browser/base/content/test/about/browser_aboutNetError_csp_iframe.js4
-rw-r--r--browser/base/content/test/about/browser_aboutNetError_xfo_iframe.js4
-rw-r--r--browser/base/content/test/alerts/browser.toml4
-rw-r--r--browser/base/content/test/alerts/browser_notification_close.js25
-rw-r--r--browser/base/content/test/alerts/browser_notification_replace.js66
-rw-r--r--browser/base/content/test/contextMenu/browser.toml2
-rw-r--r--browser/base/content/test/contextMenu/browser_contextmenu.js69
-rw-r--r--browser/base/content/test/contextMenu/browser_contextmenu_cross_boundary_selection.js73
-rw-r--r--browser/base/content/test/contextMenu/browser_strip_on_share_link.js12
-rw-r--r--browser/base/content/test/general/browser_documentnavigation.js4
-rw-r--r--browser/base/content/test/performance/browser_preferences_usage.js19
-rw-r--r--browser/base/content/test/popupNotifications/browser_popupNotification_security_delay.js414
-rw-r--r--browser/base/content/test/sidebar/browser_sidebar_adopt.js8
-rw-r--r--browser/base/content/test/sidebar/browser_sidebar_app_locale_changed.js6
-rw-r--r--browser/base/content/test/sidebar/browser_sidebar_keys.js16
-rw-r--r--browser/base/content/test/sidebar/browser_sidebar_move.js18
-rw-r--r--browser/base/content/test/sidebar/browser_sidebar_persist.js4
-rw-r--r--browser/base/content/test/sidebar/browser_sidebar_switcher.js43
-rw-r--r--browser/base/content/test/static/browser_all_files_referenced.js16
-rw-r--r--browser/base/content/test/static/browser_parsable_css.js6
-rw-r--r--browser/base/content/test/static/browser_parsable_script.js1
-rw-r--r--browser/base/content/test/static/browser_sentence_case_strings.js2
-rw-r--r--browser/base/content/test/sync/browser_contextmenu_sendpage.js57
-rw-r--r--browser/base/content/test/sync/browser_sync.js10
-rw-r--r--browser/base/content/test/tabPrompts/browser.toml2
-rw-r--r--browser/base/content/test/tabPrompts/browser_promptDelays.js113
-rw-r--r--browser/base/content/test/tabPrompts/browser_promptFocus.js3
-rw-r--r--browser/base/content/test/tabs/browser.toml4
-rw-r--r--browser/base/content/test/tabs/browser_blank_tab_label.js49
-rw-r--r--browser/base/content/test/tabs/browser_multiselect_tabs_close_duplicate_tabs.js178
-rw-r--r--browser/base/content/test/tabs/browser_tab_preview.js94
-rw-r--r--browser/base/content/test/tabs/browser_visibleTabs_contextMenu.js19
-rw-r--r--browser/base/content/test/webextensions/browser_aboutaddons_blanktab.js2
-rw-r--r--browser/base/content/test/webextensions/browser_extension_sideloading.js10
-rw-r--r--browser/base/content/test/webextensions/browser_permissions_local_file.js4
-rw-r--r--browser/base/content/test/webextensions/browser_update_interactive_noprompt.js2
-rw-r--r--browser/base/content/test/webextensions/head.js2
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>&nbsp;&%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);