summaryrefslogtreecommitdiffstats
path: root/browser/base/content
diff options
context:
space:
mode:
Diffstat (limited to 'browser/base/content')
-rw-r--r--browser/base/content/appmenu-viewcache.inc.xhtml40
-rw-r--r--browser/base/content/browser-context.inc6
-rw-r--r--browser/base/content/browser-ctrlTab.js13
-rw-r--r--browser/base/content/browser-places.js35
-rw-r--r--browser/base/content/browser-profiles.js99
-rw-r--r--browser/base/content/browser-sets.inc6
-rw-r--r--browser/base/content/browser-sidebar.js2
-rw-r--r--browser/base/content/browser-siteProtections.js278
-rw-r--r--browser/base/content/browser.css77
-rw-r--r--browser/base/content/browser.js155
-rw-r--r--browser/base/content/browser.js.globals305
-rw-r--r--browser/base/content/browser.xhtml2
-rw-r--r--browser/base/content/contentTheme.js2
-rw-r--r--browser/base/content/main-popupset.inc.xhtml27
-rw-r--r--browser/base/content/moz.build3
-rw-r--r--browser/base/content/navigator-toolbox.inc.xhtml6
-rw-r--r--browser/base/content/nsContextMenu.js123
-rw-r--r--browser/base/content/pageinfo/pageInfo.js2
-rw-r--r--browser/base/content/popup-notifications.inc8
-rw-r--r--browser/base/content/sanitizeDialog.js112
-rw-r--r--browser/base/content/sanitize_v2.xhtml69
-rw-r--r--browser/base/content/tabbrowser-tab.js30
-rw-r--r--browser/base/content/tabbrowser-tabs.js36
-rw-r--r--browser/base/content/tabbrowser.js15
-rw-r--r--browser/base/content/test/about/browser.toml10
-rw-r--r--browser/base/content/test/about/browser_aboutNetError.js44
-rw-r--r--browser/base/content/test/contextMenu/browser_bug1798178.js2
-rw-r--r--browser/base/content/test/contextMenu/browser_contextmenu_save_blocked.js2
-rw-r--r--browser/base/content/test/forms/browser.toml4
-rw-r--r--browser/base/content/test/forms/browser_selectpopup_minFontSize.js38
-rw-r--r--browser/base/content/test/general/browser_beforeunload_duplicate_dialogs.js27
-rw-r--r--browser/base/content/test/general/browser_bug676619.js2
-rw-r--r--browser/base/content/test/general/browser_double_close_tab.js46
-rw-r--r--browser/base/content/test/general/browser_minimize.js43
-rw-r--r--browser/base/content/test/general/browser_save_link-perwindowpb.js8
-rw-r--r--browser/base/content/test/general/browser_save_link_when_window_navigates.js4
-rw-r--r--browser/base/content/test/general/browser_save_private_link_perwindowpb.js2
-rw-r--r--browser/base/content/test/general/browser_save_video.js4
-rw-r--r--browser/base/content/test/general/browser_save_video_frame.js2
-rw-r--r--browser/base/content/test/general/browser_visibleTabs_bookmarkAllPages.js4
-rw-r--r--browser/base/content/test/general/navigating_window_with_download.html2
-rw-r--r--browser/base/content/test/outOfProcess/browser_controller.js54
-rw-r--r--browser/base/content/test/performance/browser_appmenu.js9
-rw-r--r--browser/base/content/test/performance/browser_startup_content_mainthreadio.js7
-rw-r--r--browser/base/content/test/popupNotifications/browser_popupNotification_security_delay.js165
-rw-r--r--browser/base/content/test/popups/browser_popup_blocker.js15
-rw-r--r--browser/base/content/test/privateBrowsing/browser_private_browsing_simplified_ui.js15
-rw-r--r--browser/base/content/test/protectionsUI/browser.toml7
-rw-r--r--browser/base/content/test/protectionsUI/browser_protectionsUI.js119
-rw-r--r--browser/base/content/test/protectionsUI/browser_protectionsUI_report_breakage.js415
-rw-r--r--browser/base/content/test/sanitize/browser.toml2
-rw-r--r--browser/base/content/test/sanitize/browser_sanitize-timespans.js3
-rw-r--r--browser/base/content/test/sanitize/browser_sanitizeDialog.js22
-rw-r--r--browser/base/content/test/sanitize/browser_sanitizeDialog_v2.js711
-rw-r--r--browser/base/content/test/sanitize/browser_sanitizeDialog_v2_dataSizes.js310
-rw-r--r--browser/base/content/test/sanitize/browser_sanitizeOnShutdown_migration.js26
-rw-r--r--browser/base/content/test/sanitize/head.js366
-rw-r--r--browser/base/content/test/siteIdentity/browser.toml6
-rw-r--r--browser/base/content/test/siteIdentity/browser_identity_web_controlled_blank.js128
-rw-r--r--browser/base/content/test/siteIdentity/test_web_controlled_blank.html36
-rw-r--r--browser/base/content/test/static/browser_all_files_referenced.js9
-rw-r--r--browser/base/content/test/static/browser_misused_characters_in_strings.js22
-rw-r--r--browser/base/content/test/static/browser_parsable_css.js18
-rw-r--r--browser/base/content/test/tabPrompts/browser_beforeunload_urlbar.js30
-rw-r--r--browser/base/content/test/tabPrompts/browser_confirmFolderUpload.js2
-rw-r--r--browser/base/content/test/tabPrompts/browser_contentOrigins.js6
-rw-r--r--browser/base/content/test/tabPrompts/browser_multiplePrompts.js72
-rw-r--r--browser/base/content/test/tabPrompts/browser_openPromptInBackgroundTab.js113
-rw-r--r--browser/base/content/test/tabdialogs/browser_tabdialogbox_content_prompts.js8
-rw-r--r--browser/base/content/test/tabs/browser.toml1
-rw-r--r--browser/base/content/test/tabs/browser_close_during_beforeunload.js9
-rw-r--r--browser/base/content/test/tabs/browser_multiselect_tabs_bookmark.js10
-rw-r--r--browser/base/content/test/tabs/browser_tab_preview.js71
-rw-r--r--browser/base/content/test/webextensions/browser_permissions_local_file.js2
-rw-r--r--browser/base/content/utilityOverlay.js37
-rw-r--r--browser/base/content/webext-panels.xhtml1
76 files changed, 2319 insertions, 2203 deletions
diff --git a/browser/base/content/appmenu-viewcache.inc.xhtml b/browser/base/content/appmenu-viewcache.inc.xhtml
index 07b1765f18..04bba182fb 100644
--- a/browser/base/content/appmenu-viewcache.inc.xhtml
+++ b/browser/base/content/appmenu-viewcache.inc.xhtml
@@ -38,6 +38,13 @@
</vbox>
</toolbarbutton>
</toolbaritem>
+ <toolbarbutton id="appMenu-profiles-button"
+ class="subviewbutton subviewbutton-nav"
+ data-l10n-id="appmenuitem-profiles"
+ data-l10n-args='{ "profilename": "" }'
+ closemenu="none"
+ oncommand="gProfiles.updateView(this)"
+ hidden="true"/>
<toolbarseparator id="appMenu-fxa-separator" class="proton-zap"/>
<toolbarbutton id="appMenu-new-tab-button2"
class="subviewbutton"
@@ -212,6 +219,39 @@
oncommand="PlacesCommandHook.showPlacesOrganizer('History'); CustomizableUI.hidePanelForNode(this);"/>
</panelview>
+ <panelview id="PanelUI-profiles" flex="1">
+ <vbox class="panel-subview-body">
+ <vbox id="current-profile">
+ <image id="profile-icon-image"></image>
+ <h2 id="profile-name"></h2>
+ <hbox id="this-profile-buttons">
+ <toolbarbutton id="profiles-edit-this-delete-button"
+ class="subviewbutton toolbarbutton-1"
+ oncommand="switchToTabHavingURI('about:profilemanager', true)"/>
+ <toolbarbutton id="profiles-delete-this-profile-button"
+ class="subviewbutton toolbarbutton-1"
+ oncommand="switchToTabHavingURI('about:profilemanager', true)"/>
+ </hbox>
+ </vbox>
+ <toolbarseparator/>
+ <vbox id="profiles-list"></vbox>
+ <toolbarseparator/>
+ <toolbarbutton id="profiles-close-profile-button"
+ class="subviewbutton"
+ data-l10n-id="appmenu-close-profile"
+ data-l10n-args='{ "profilename": "" }'
+ oncommand=""/>
+ <toolbarbutton id="profiles-create-profile-button"
+ class="subviewbutton"
+ data-l10n-id="appmenu-create-profile"
+ oncommand="switchToTabHavingURI('about:profilemanager', true)"/>
+ <toolbarbutton id="profiles-manage-profiles-button"
+ class="subviewbutton"
+ data-l10n-id="appmenu-manage-profiles"
+ oncommand="switchToTabHavingURI('about:profilemanager', true)"/>
+ </vbox>
+ </panelview>
+
<panelview id="appMenu-library-recentlyClosedTabs"/>
<panelview id="appMenu-library-recentlyClosedWindows"/>
diff --git a/browser/base/content/browser-context.inc b/browser/base/content/browser-context.inc
index 9230c07f6a..ff4015e3d4 100644
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -313,6 +313,9 @@
<menuitem id="context-selectall"
data-l10n-id="text-action-select-all"
command="cmd_selectAll"/>
+ <menuitem id="context-pdfjs-highlight-selection"
+ data-l10n-id="text-action-highlight-selection"
+ oncommand="gContextMenu.pdfJSCmd('highlightSelection');"/>
<menuitem id="context-reveal-password"
type="checkbox"
data-l10n-id="main-context-menu-reveal-password"
@@ -358,7 +361,8 @@
<menuitem id="context-searchselect-private"
oncommand="BrowserSearch.loadSearchFromContext(this.searchTerms, true, this.principal, this.csp, event);"/>
<menuitem id="context-translate-selection"
- data-l10n-id="main-context-menu-translate-selection"/>
+ data-l10n-id="main-context-menu-translate-selection"
+ oncommand="gContextMenu.openSelectTranslationsPanel(event);"/>
<menuseparator id="frame-sep"/>
<menu id="frame" data-l10n-id="main-context-menu-frame">
diff --git a/browser/base/content/browser-ctrlTab.js b/browser/base/content/browser-ctrlTab.js
index 31617f13a3..d4d79a6886 100644
--- a/browser/base/content/browser-ctrlTab.js
+++ b/browser/base/content/browser-ctrlTab.js
@@ -581,7 +581,7 @@ var ctrlTab = {
return;
}
- Services.els.addSystemEventListener(document, "keyup", this, false);
+ document.addEventListener("keyup", this, { mozSystemGroup: true });
let tabs = gBrowser.visibleTabs;
if (tabs.length > 2) {
@@ -706,12 +706,7 @@ var ctrlTab = {
event.stopPropagation();
if (event.keyCode === event.DOM_VK_CONTROL) {
- Services.els.removeSystemEventListener(
- document,
- "keyup",
- this,
- false
- );
+ document.removeEventListener("keyup", this, { mozSystemGroup: true });
if (this.isOpen) {
this.pick();
@@ -787,9 +782,9 @@ var ctrlTab = {
tabContainer[toggleEventListener]("TabShow", this);
if (enable) {
- Services.els.addSystemEventListener(document, "keydown", this, false);
+ document.addEventListener("keydown", this, { mozSystemGroup: true });
} else {
- Services.els.removeSystemEventListener(document, "keydown", this, false);
+ document.removeEventListener("keydown", this, { mozSystemGroup: true });
}
document[toggleEventListener]("keypress", this);
gBrowser.tabbox.handleCtrlTab = !enable;
diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js
index 6992d22069..58e61f7bf7 100644
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -392,7 +392,7 @@ var PlacesCommandHook = {
*/
async bookmarkPage() {
let browser = gBrowser.selectedBrowser;
- let url = URL.fromURI(browser.currentURI);
+ let url = URL.fromURI(Services.io.createExposableURI(browser.currentURI));
let info = await PlacesUtils.bookmarks.fetch({ url });
let isNewBookmark = !info;
let showEditUI = !isNewBookmark || StarUI.showForNewBookmarks;
@@ -490,6 +490,21 @@ var PlacesCommandHook = {
},
/**
+ * Bookmarks the given tabs loaded in the current browser.
+ * @param {Array} tabs
+ * If no given tabs, bookmark all current tabs.
+ */
+ async bookmarkTabs(tabs) {
+ tabs = tabs ?? gBrowser.visibleTabs.filter(tab => !tab.pinned);
+ let pages = PlacesCommandHook.getUniquePages(tabs).map(
+ // Bookmark exposable url.
+ page =>
+ Object.assign(page, { uri: Services.io.createExposableURI(page.uri) })
+ );
+ await PlacesUIUtils.showBookmarkPagesDialog(pages);
+ },
+
+ /**
* List of nsIURI objects characterizing tabs given in param.
* Duplicates are discarded.
*/
@@ -511,24 +526,6 @@ var PlacesCommandHook = {
},
/**
- * List of nsIURI objects characterizing the tabs currently open in the
- * browser, modulo pinned tabs. The URIs will be in the order in which their
- * corresponding tabs appeared and duplicates are discarded.
- */
- get uniqueCurrentPages() {
- let visibleUnpinnedTabs = gBrowser.visibleTabs.filter(tab => !tab.pinned);
- return this.getUniquePages(visibleUnpinnedTabs);
- },
-
- /**
- * List of nsIURI objects characterizing the tabs currently
- * selected in the window. Duplicates are discarded.
- */
- get uniqueSelectedPages() {
- return this.getUniquePages(gBrowser.selectedTabs);
- },
-
- /**
* Opens the Places Organizer.
* @param {String} item The item to select in the organizer window,
* options are (case sensitive):
diff --git a/browser/base/content/browser-profiles.js b/browser/base/content/browser-profiles.js
new file mode 100644
index 0000000000..72eca39e44
--- /dev/null
+++ b/browser/base/content/browser-profiles.js
@@ -0,0 +1,99 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+// This file is loaded into the browser window scope.
+/* eslint-env mozilla/browser-window */
+
+XPCOMUtils.defineLazyServiceGetter(
+ this,
+ "ProfileService",
+ "@mozilla.org/toolkit/profile-service;1",
+ "nsIToolkitProfileService"
+);
+
+var gProfiles = {
+ init() {
+ XPCOMUtils.defineLazyPreferenceGetter(
+ this,
+ "PROFILES_ENABLED",
+ "browser.profiles.enabled",
+ false,
+ this.toggleProfileButtonsVisibility.bind(this)
+ );
+
+ if (!this.PROFILES_ENABLED) {
+ return;
+ }
+
+ this.toggleProfileButtonsVisibility();
+ },
+
+ toggleProfileButtonsVisibility() {
+ let profilesButton = PanelMultiView.getViewNode(
+ document,
+ "appMenu-profiles-button"
+ );
+
+ profilesButton.hidden = !this.PROFILES_ENABLED;
+
+ if (this.PROFILES_ENABLED) {
+ document.l10n.setArgs(profilesButton, {
+ profilename: ProfileService.currentProfile?.name ?? "",
+ });
+ }
+ },
+
+ updateView(panel) {
+ this.populateSubView();
+ PanelUI.showSubView("PanelUI-profiles", panel);
+ },
+
+ async populateSubView() {
+ let closeProfileButton = PanelMultiView.getViewNode(
+ document,
+ "profiles-close-profile-button"
+ );
+ document.l10n.setArgs(closeProfileButton, {
+ profilename: ProfileService.currentProfile?.name ?? "",
+ });
+
+ let profileIconEl = PanelMultiView.getViewNode(
+ document,
+ "profile-icon-image"
+ );
+ profileIconEl.style.listStyleImage = `url(${
+ ProfileService.currentProfile?.iconURL ??
+ "chrome://branding/content/icon64.png"
+ })`;
+
+ let profileNameEl = PanelMultiView.getViewNode(document, "profile-name");
+ profileNameEl.textContent = ProfileService.currentProfile?.name ?? "";
+
+ let profilesList = PanelMultiView.getViewNode(
+ document,
+ "PanelUI-profiles"
+ ).querySelector("#profiles-list");
+ while (profilesList.lastElementChild) {
+ profilesList.lastElementChild.remove();
+ }
+
+ for (let profile of ProfileService.profiles) {
+ if (profile === ProfileService.currentProfile) {
+ continue;
+ }
+
+ let button = document.createXULElement("toolbarbutton");
+ button.setAttribute("label", profile.name);
+ button.className = "subviewbutton subviewbutton-iconic";
+ button.style.listStyleImage = `url(${
+ profile.iconURL ?? "chrome://branding/content/icon16.png"
+ })`;
+ button.onclick = () => {
+ Services.startup.createInstanceWithProfile(profile);
+ };
+
+ profilesList.appendChild(button);
+ }
+ },
+};
diff --git a/browser/base/content/browser-sets.inc b/browser/base/content/browser-sets.inc
index 019b3cc469..090e94b684 100644
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -52,14 +52,14 @@
<command id="cmd_findSelection" oncommand="gLazyFindCommand('onFindSelectionCommand')"/>
#endif
<command id="cmd_reportBrokenSite" oncommand="ReportBrokenSite.open(event);"/>
- <command id="cmd_translate" oncommand="TranslationsPanel.open(event);"/>
+ <command id="cmd_translate" oncommand="FullPageTranslationsPanel.open(event);"/>
<!-- work-around bug 392512 -->
<command id="Browser:AddBookmarkAs"
oncommand="PlacesCommandHook.bookmarkPage();"/>
<command id="Browser:SearchBookmarks"
oncommand="PlacesCommandHook.searchBookmarks();"/>
<command id="Browser:BookmarkAllTabs"
- oncommand="PlacesUIUtils.showBookmarkPagesDialog(PlacesCommandHook.uniqueCurrentPages);"/>
+ oncommand="PlacesCommandHook.bookmarkTabs();"/>
<command id="Browser:Back" oncommand="BrowserBack();" disabled="true"/>
<command id="Browser:BackOrBackDuplicate" oncommand="BrowserBack(event);" disabled="true">
<observes element="Browser:Back" attribute="disabled"/>
@@ -270,7 +270,7 @@
<key id="addBookmarkAsKb" data-l10n-id="bookmark-this-page-shortcut" command="Browser:AddBookmarkAs" modifiers="accel"/>
<key id="bookmarkAllTabsKb"
data-l10n-id="bookmark-this-page-shortcut"
- oncommand="PlacesUIUtils.showBookmarkPagesDialog(PlacesCommandHook.uniqueCurrentPages);"
+ oncommand="PlacesCommandHook.bookmarkTabs();"
modifiers="accel,shift"/>
<key id="manBookmarkKb" data-l10n-id="bookmark-show-library-shortcut" command="Browser:ShowAllBookmarks" modifiers="accel,shift"/>
<key id="viewBookmarksSidebarKb"
diff --git a/browser/base/content/browser-sidebar.js b/browser/base/content/browser-sidebar.js
index ea6457a5c4..2d730700a6 100644
--- a/browser/base/content/browser-sidebar.js
+++ b/browser/base/content/browser-sidebar.js
@@ -266,7 +266,7 @@ var SidebarUI = {
},
updateShortcut({ keyId }) {
- let menuitem = this._switcherPanel.querySelector(`[key="${keyId}"]`);
+ let menuitem = this._switcherPanel?.querySelector(`[key="${keyId}"]`);
if (!menuitem) {
// If the menu item doesn't exist yet then the accel text will be set correctly
// upon creation so there's nothing to do now.
diff --git a/browser/base/content/browser-siteProtections.js b/browser/base/content/browser-siteProtections.js
index 5364aa74cd..c44b4d3e8e 100644
--- a/browser/base/content/browser-siteProtections.js
+++ b/browser/base/content/browser-siteProtections.js
@@ -31,8 +31,6 @@ class ProtectionCategory {
* @param {Object} options - Category options.
* @param {string} options.prefEnabled - ID of pref which controls the
* category enabled state.
- * @param {string} [options.reportBreakageLabel] - Telemetry label to use when
- * users report TP breakage. Defaults to protection ID.
* @param {string} [options.l10nId] - Identifier l10n strings are keyed under
* for this category. Defaults to protection ID.
* @param {Object} flags - Flags for this category to look for in the content
@@ -51,7 +49,7 @@ class ProtectionCategory {
*/
constructor(
id,
- { prefEnabled, reportBreakageLabel, l10nId },
+ { prefEnabled, l10nId },
{
load,
block,
@@ -61,7 +59,6 @@ class ProtectionCategory {
) {
this._id = id;
this.prefEnabled = prefEnabled;
- this._reportBreakageLabel = reportBreakageLabel || id;
this._flags = { load, block, shim, allow };
@@ -112,10 +109,6 @@ class ProtectionCategory {
return this._enabled;
}
- get reportBreakageLabel() {
- return this._reportBreakageLabel;
- }
-
/**
* Get the category item associated with this protection from the main
* protections panel.
@@ -333,7 +326,6 @@ let Fingerprinting =
"fingerprinters",
{
prefEnabled: "privacy.trackingprotection.fingerprinting.enabled",
- reportBreakageLabel: "fingerprinting",
},
{
load: Ci.nsIWebProgressListener.STATE_LOADED_FINGERPRINTING_CONTENT,
@@ -411,7 +403,6 @@ let Cryptomining = new ProtectionCategory(
"cryptominers",
{
prefEnabled: "privacy.trackingprotection.cryptomining.enabled",
- reportBreakageLabel: "cryptomining",
},
{
load: Ci.nsIWebProgressListener.STATE_LOADED_CRYPTOMINING_CONTENT,
@@ -427,7 +418,6 @@ let TrackingProtection =
{
l10nId: "trackingContent",
prefEnabled: "privacy.trackingprotection.enabled",
- reportBreakageLabel: "trackingprotection",
},
{
load: null,
@@ -699,28 +689,6 @@ let ThirdPartyCookies =
);
}
- get reportBreakageLabel() {
- switch (this.behaviorPref) {
- case Ci.nsICookieService.BEHAVIOR_ACCEPT:
- return "nocookiesblocked";
- case Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN:
- return "allthirdpartycookiesblocked";
- case Ci.nsICookieService.BEHAVIOR_REJECT:
- return "allcookiesblocked";
- case Ci.nsICookieService.BEHAVIOR_LIMIT_FOREIGN:
- return "cookiesfromunvisitedsitesblocked";
- default:
- console.error(
- `Error: Unknown cookieBehavior pref observed: ${this.behaviorPref}`
- );
- // fall through
- case Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER:
- return "cookierestrictions";
- case Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN:
- return "cookierestrictionsforeignpartitioned";
- }
- }
-
isBlocking(state) {
return (
(state & Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_TRACKER) !=
@@ -1099,7 +1067,6 @@ let SocialTracking =
{
l10nId: "socialMediaTrackers",
prefEnabled: "privacy.socialtracking.block_cookies.enabled",
- reportBreakageLabel: "socialtracking",
},
{
load: Ci.nsIWebProgressListener.STATE_LOADED_SOCIALTRACKING_CONTENT,
@@ -1406,7 +1373,6 @@ let cookieBannerHandling = new (class {
* Utility object to handle manipulations of the protections indicators in the UI
*/
var gProtectionsHandler = {
- PREF_REPORT_BREAKAGE_URL: "browser.contentblocking.reportBreakage.url",
PREF_CB_CATEGORY: "browser.contentblocking.category",
_protectionsPopup: null,
@@ -1456,18 +1422,6 @@ var gProtectionsHandler = {
"protections-popup-mainView-panel-header-span"
));
},
- get _protectionsPopupTPSwitchBreakageLink() {
- delete this._protectionsPopupTPSwitchBreakageLink;
- return (this._protectionsPopupTPSwitchBreakageLink =
- document.getElementById("protections-popup-tp-switch-breakage-link"));
- },
- get _protectionsPopupTPSwitchBreakageFixedLink() {
- delete this._protectionsPopupTPSwitchBreakageFixedLink;
- return (this._protectionsPopupTPSwitchBreakageFixedLink =
- document.getElementById(
- "protections-popup-tp-switch-breakage-fixed-link"
- ));
- },
get _protectionsPopupTPSwitch() {
delete this._protectionsPopupTPSwitch;
return (this._protectionsPopupTPSwitch = document.getElementById(
@@ -1524,28 +1478,6 @@ var gProtectionsHandler = {
"protections-popup-footer-protection-type-label"
));
},
- get _protectionsPopupSiteNotWorkingTPSwitch() {
- delete this._protectionsPopupSiteNotWorkingTPSwitch;
- return (this._protectionsPopupSiteNotWorkingTPSwitch =
- document.getElementById("protections-popup-siteNotWorking-tp-switch"));
- },
- get _protectionsPopupSiteNotWorkingReportError() {
- delete this._protectionsPopupSiteNotWorkingReportError;
- return (this._protectionsPopupSiteNotWorkingReportError =
- document.getElementById("protections-popup-sendReportView-report-error"));
- },
- get _protectionsPopupSendReportURL() {
- delete this._protectionsPopupSendReportURL;
- return (this._protectionsPopupSendReportURL = document.getElementById(
- "protections-popup-sendReportView-collection-url"
- ));
- },
- get _protectionsPopupSendReportButton() {
- delete this._protectionsPopupSendReportButton;
- return (this._protectionsPopupSendReportButton = document.getElementById(
- "protections-popup-sendReportView-submit"
- ));
- },
get _trackingProtectionIconTooltipLabel() {
delete this._trackingProtectionIconTooltipLabel;
return (this._trackingProtectionIconTooltipLabel = document.getElementById(
@@ -1580,13 +1512,6 @@ var gProtectionsHandler = {
));
},
- get _siteNotWorkingIssueListFonts() {
- delete this._siteNotWorkingIssueListFonts;
- return (this._siteNotWorkingIssueListFonts = document.getElementById(
- "protections-panel-site-not-working-view-issue-list-fonts"
- ));
- },
-
// A list of blockers that will be displayed in the categories list
// when blockable content is detected. A blocker must be an object
// with at least the following two properties:
@@ -1811,10 +1736,6 @@ var gProtectionsHandler = {
window.addEventListener("focus", this, true);
this._protectionsPopupTPSwitch.addEventListener("toggle", this);
- this._protectionsPopupSiteNotWorkingTPSwitch.addEventListener(
- "toggle",
- this
- );
// Insert the info message if needed. This will be shown once and then
// remain collapsed.
@@ -1834,10 +1755,6 @@ var gProtectionsHandler = {
if (event.target == this._protectionsPopup) {
window.removeEventListener("focus", this, true);
this._protectionsPopupTPSwitch.removeEventListener("toggle", this);
- this._protectionsPopupSiteNotWorkingTPSwitch.removeEventListener(
- "toggle",
- this
- );
}
},
@@ -2163,7 +2080,7 @@ var gProtectionsHandler = {
let currentlyEnabled = !this.hasException;
- this.updateProtectionsToggles(currentlyEnabled);
+ this.updateProtectionsToggle(currentlyEnabled);
this._notBlockingWhyLink.setAttribute(
"tooltip",
@@ -2172,9 +2089,6 @@ var gProtectionsHandler = {
: "protections-popup-not-blocking-why-etp-off-tooltip"
);
- // Toggle the breakage link according to the current enable state.
- this.toggleBreakageLink();
-
// Update the tooltip of the blocked tracker counter.
this.maybeUpdateEarliestRecordedDateTooltip();
@@ -2196,28 +2110,23 @@ var gProtectionsHandler = {
},
/**
- * Updates the "pressed" state and labels for both toggles in the different
- * panel subviews.
+ * Updates the "pressed" state and labels for the toggle
*
- * @param {boolean} isPressed - Whether or not the toggles should be pressed.
+ * @param {boolean} isPressed - Whether or not the toggle should be pressed.
* True if ETP is enabled for a given site.
*/
- updateProtectionsToggles(isPressed) {
+ updateProtectionsToggle(isPressed) {
let host = gIdentityHandler.getHostForDisplay();
- for (let toggle of [
- this._protectionsPopupTPSwitch,
- this._protectionsPopupSiteNotWorkingTPSwitch,
- ]) {
- toggle.toggleAttribute("pressed", isPressed);
- toggle.toggleAttribute("disabled", !!this._TPSwitchCommanding);
- document.l10n.setAttributes(
- toggle,
- isPressed
- ? "protections-panel-etp-toggle-on"
- : "protections-panel-etp-toggle-off",
- { host }
- );
- }
+ let toggle = this._protectionsPopupTPSwitch;
+ toggle.toggleAttribute("pressed", isPressed);
+ toggle.toggleAttribute("disabled", !!this._TPSwitchCommanding);
+ document.l10n.setAttributes(
+ toggle,
+ isPressed
+ ? "protections-panel-etp-toggle-on"
+ : "protections-panel-etp-toggle-off",
+ { host }
+ );
},
/*
@@ -2313,10 +2222,7 @@ var gProtectionsHandler = {
let newExceptionState =
this._protectionsPopup.toggleAttribute("hasException");
- this.updateProtectionsToggles(!newExceptionState);
-
- // Toggle the breakage link if needed.
- this.toggleBreakageLink();
+ this.updateProtectionsToggle(!newExceptionState);
// Change the tooltip of the tracking protection icon.
if (newExceptionState) {
@@ -2523,158 +2429,6 @@ var gProtectionsHandler = {
).catch(console.error);
},
- showSiteNotWorkingView() {
- // Only show the Fonts item if we are restricting font visibility
- if (this._fontVisibilityTrackingProtection >= 3) {
- this._siteNotWorkingIssueListFonts.setAttribute("hidden", "true");
- } else {
- this._siteNotWorkingIssueListFonts.removeAttribute("hidden");
- }
-
- this._protectionsPopupMultiView.showSubView(
- "protections-popup-siteNotWorkingView"
- );
- },
-
- showSendReportView() {
- // Save this URI to make sure that the user really only submits the location
- // they see in the report breakage dialog.
- this.reportURI = gBrowser.currentURI;
- let urlWithoutQuery = this.reportURI.asciiSpec.replace(
- "?" + this.reportURI.query,
- ""
- );
- let commentsTextarea = document.getElementById(
- "protections-popup-sendReportView-collection-comments"
- );
- commentsTextarea.value = "";
- this._protectionsPopupSendReportURL.value = urlWithoutQuery;
- this._protectionsPopupSiteNotWorkingReportError.hidden = true;
- this._protectionsPopupMultiView.showSubView(
- "protections-popup-sendReportView"
- );
- },
-
- toggleBreakageLink() {
- // The breakage link will only be shown if tracking protection is enabled
- // for the site and the TP toggle state is on. And we won't show the
- // link as toggling TP switch to On from Off. In order to do so, we need to
- // know the previous TP state. We check the ContentBlockingAllowList instead
- // of 'hasException' attribute of the protection popup for the previous
- // since the 'hasException' will also be toggled as well as toggling the TP
- // switch. We won't be able to know the previous TP state through the
- // 'hasException' attribute. So we fallback to check the
- // ContentBlockingAllowList here.
- this._protectionsPopupTPSwitchBreakageLink.hidden =
- ContentBlockingAllowList.includes(gBrowser.selectedBrowser) ||
- !this.anyBlocking ||
- !this._protectionsPopupTPSwitch.hasAttribute("pressed");
- // The "Site Fixed?" link behaves similarly but for the opposite state.
- this._protectionsPopupTPSwitchBreakageFixedLink.hidden =
- !ContentBlockingAllowList.includes(gBrowser.selectedBrowser) ||
- this._protectionsPopupTPSwitch.hasAttribute("pressed");
- },
-
- submitBreakageReport(uri) {
- let reportEndpoint = Services.prefs.getStringPref(
- this.PREF_REPORT_BREAKAGE_URL
- );
- if (!reportEndpoint) {
- return;
- }
-
- let commentsTextarea = document.getElementById(
- "protections-popup-sendReportView-collection-comments"
- );
-
- let formData = new FormData();
- formData.set("title", uri.host);
-
- // Leave the ? at the end of the URL to signify that this URL had its query stripped.
- let urlWithoutQuery = uri.asciiSpec.replace(uri.query, "");
- let body = `Full URL: ${urlWithoutQuery}\n`;
- body += `userAgent: ${navigator.userAgent}\n`;
-
- body += "\n**Preferences**\n";
- body += `${TrackingProtection.prefEnabled}: ${Services.prefs.getBoolPref(
- TrackingProtection.prefEnabled
- )}\n`;
- body += `${
- TrackingProtection.prefEnabledInPrivateWindows
- }: ${Services.prefs.getBoolPref(
- TrackingProtection.prefEnabledInPrivateWindows
- )}\n`;
- body += `urlclassifier.trackingTable: ${Services.prefs.getStringPref(
- "urlclassifier.trackingTable"
- )}\n`;
- body += `network.http.referer.defaultPolicy: ${Services.prefs.getIntPref(
- "network.http.referer.defaultPolicy"
- )}\n`;
- body += `network.http.referer.defaultPolicy.pbmode: ${Services.prefs.getIntPref(
- "network.http.referer.defaultPolicy.pbmode"
- )}\n`;
- body += `${ThirdPartyCookies.prefEnabled}: ${Services.prefs.getIntPref(
- ThirdPartyCookies.prefEnabled
- )}\n`;
- body += `privacy.annotate_channels.strict_list.enabled: ${Services.prefs.getBoolPref(
- "privacy.annotate_channels.strict_list.enabled"
- )}\n`;
- body += `privacy.restrict3rdpartystorage.expiration: ${Services.prefs.getIntPref(
- "privacy.restrict3rdpartystorage.expiration"
- )}\n`;
- body += `${Fingerprinting.prefEnabled}: ${Services.prefs.getBoolPref(
- Fingerprinting.prefEnabled
- )}\n`;
- body += `${Cryptomining.prefEnabled}: ${Services.prefs.getBoolPref(
- Cryptomining.prefEnabled
- )}\n`;
- body += `privacy.globalprivacycontrol.enabled: ${Services.prefs.getBoolPref(
- "privacy.globalprivacycontrol.enabled"
- )}\n`;
- body += `\nhasException: ${this.hasException}\n`;
-
- body += "\n**Comments**\n" + commentsTextarea.value;
-
- formData.set("body", body);
-
- let activatedBlockers = [];
- for (let blocker of Object.values(this.blockers)) {
- if (blocker.activated) {
- activatedBlockers.push(blocker.reportBreakageLabel);
- }
- }
-
- formData.set("labels", activatedBlockers.join(","));
-
- this._protectionsPopupSendReportButton.disabled = true;
-
- fetch(reportEndpoint, {
- method: "POST",
- credentials: "omit",
- body: formData,
- })
- .then(response => {
- this._protectionsPopupSendReportButton.disabled = false;
- if (!response.ok) {
- console.error(
- `Content Blocking report to ${reportEndpoint} failed with status ${response.status}`
- );
- this._protectionsPopupSiteNotWorkingReportError.hidden = false;
- } else {
- this._protectionsPopup.hidePopup();
- ConfirmationHint.show(
- this._trackingProtectionIconContainer,
- "confirmation-hint-breakage-report-sent"
- );
- }
- })
- .catch(console.error);
- },
-
- onSendReportClicked() {
- this.submitBreakageReport(this.reportURI);
- },
-
async maybeUpdateEarliestRecordedDateTooltip(trackerCount) {
// If we've already updated or the popup isn't in the DOM yet, don't bother
// doing this:
diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css
index 8a2a202809..c9ebddb7f5 100644
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -115,6 +115,7 @@ panelview:not([visible]) {
flex-shrink: 0;
min-width: 0;
min-height: 0;
+ max-height: 100%;
}
.panel-viewcontainer[panelopen] {
@@ -934,82 +935,6 @@ toolbarpaletteitem[place="palette"] > #downloads-button > .toolbarbutton-badge-s
display: none;
}
-@media (-moz-panel-animations) and (prefers-reduced-motion: no-preference) {
-@media (-moz-platform: macos) {
- /* On Mac, use the properties "-moz-window-transform" and "-moz-window-opacity"
- instead of "transform" and "opacity" for these animations.
- The -moz-window* properties apply to the whole window including the window's
- shadow, and they don't affect the window's "shape", so the system doesn't
- have to recompute the shadow shape during the animation. This makes them a
- lot faster. In fact, Gecko no longer triggers shadow shape recomputations
- for repaints.
- These properties are not implemented on other platforms. */
- #BMB_bookmarksPopup:not([animate="false"]) {
- transition-property: -moz-window-transform, -moz-window-opacity;
- transition-duration: 0.18s, 0.18s;
- transition-timing-function:
- var(--animation-easing-function), ease-out;
- }
-
- /* Only do the fade-in animation on pre-Big Sur to avoid missing shadows on
- * Big Sur, see bug 1672091. */
- @media (-moz-mac-big-sur-theme: 0) {
- #BMB_bookmarksPopup:not([animate="false"]) {
- -moz-window-opacity: 0;
- -moz-window-transform: translateY(-70px);
- }
-
- #BMB_bookmarksPopup[side="bottom"]:not([animate="false"]) {
- -moz-window-transform: translateY(70px);
- }
- }
-
- /* [animate] is here only so that this rule has greater specificity than the
- * rule right above */
- #BMB_bookmarksPopup[animate][animate="open"] {
- -moz-window-opacity: 1.0;
- transition-duration: 0.18s, 0.18s;
- -moz-window-transform: none;
- transition-timing-function:
- var(--animation-easing-function), ease-in-out;
- }
-
- #BMB_bookmarksPopup[animate][animate="cancel"] {
- -moz-window-opacity: 0;
- -moz-window-transform: none;
- }
-}
-@media not (-moz-platform: macos) {
- #BMB_bookmarksPopup:not([animate="false"]) {
- opacity: 0;
- transform: translateY(-70px);
- transition-property: transform, opacity;
- transition-duration: 0.18s, 0.18s;
- transition-timing-function:
- var(--animation-easing-function), ease-out;
- will-change: transform, opacity;
- }
-
- #BMB_bookmarksPopup[side="bottom"]:not([animate="false"]) {
- transform: translateY(70px);
- }
-
- /* [animate] is here only so that this rule has greater specificity than the
- * rule right above */
- #BMB_bookmarksPopup[animate][animate="open"] {
- opacity: 1.0;
- transition-duration: 0.18s, 0.18s;
- transform: none;
- transition-timing-function:
- var(--animation-easing-function), ease-in-out;
- }
-
- #BMB_bookmarksPopup[animate][animate="cancel"] {
- transform: none;
- }
-}
-}
-
/* Apply crisp rendering for favicons at exactly 2dppx resolution */
@media (resolution: 2dppx) {
.PanelUI-remotetabs-clientcontainer > toolbarbutton > .toolbarbutton-icon,
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index 4f145c4949..c91a5d4db2 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -29,7 +29,6 @@ ChromeUtils.defineESModuleGetters(this, {
ContextualIdentityService:
"resource://gre/modules/ContextualIdentityService.sys.mjs",
CustomizableUI: "resource:///modules/CustomizableUI.sys.mjs",
- Deprecated: "resource://gre/modules/Deprecated.sys.mjs",
DevToolsSocketStatus:
"resource://devtools/shared/security/DevToolsSocketStatus.sys.mjs",
DownloadUtils: "resource://gre/modules/DownloadUtils.sys.mjs",
@@ -185,8 +184,13 @@ XPCOMUtils.defineLazyScriptGetter(
);
XPCOMUtils.defineLazyScriptGetter(
this,
- "TranslationsPanel",
- "chrome://browser/content/translations/translationsPanel.js"
+ "SelectTranslationsPanel",
+ "chrome://browser/content/translations/selectTranslationsPanel.js"
+);
+XPCOMUtils.defineLazyScriptGetter(
+ this,
+ "FullPageTranslationsPanel",
+ "chrome://browser/content/translations/fullPageTranslationsPanel.js"
);
XPCOMUtils.defineLazyScriptGetter(
this,
@@ -272,6 +276,11 @@ XPCOMUtils.defineLazyScriptGetter(
"gPageStyleMenu",
"chrome://browser/content/browser-pagestyle.js"
);
+XPCOMUtils.defineLazyScriptGetter(
+ this,
+ "gProfiles",
+ "chrome://browser/content/browser-profiles.js"
+);
// lazy service getters
@@ -524,13 +533,6 @@ XPCOMUtils.defineLazyPreferenceGetter(
XPCOMUtils.defineLazyPreferenceGetter(
this,
- "gBookmarksToolbarShowInPrivate",
- "browser.toolbars.bookmarks.showInPrivateBrowsing",
- false
-);
-
-XPCOMUtils.defineLazyPreferenceGetter(
- this,
"gFxaToolbarEnabled",
"identity.fxaccounts.toolbar.enabled",
false,
@@ -720,6 +722,7 @@ var gInitialPages = [
"about:welcome",
"about:welcomeback",
"chrome://browser/content/blanktab.html",
+ "about:profilemanager",
];
function isInitialPage(url) {
@@ -740,22 +743,13 @@ function browserWindows() {
}
function updateBookmarkToolbarVisibility() {
- // Bug 1846583 - hide bookmarks toolbar in PBM
- if (
- gUseFeltPrivacyUI &&
- !gBookmarksToolbarShowInPrivate &&
- PrivateBrowsingUtils.isWindowPrivate(window)
- ) {
- setToolbarVisibility(BookmarkingUI.toolbar, false, false, false);
- } else {
- BookmarkingUI.updateEmptyToolbarMessage();
- setToolbarVisibility(
- BookmarkingUI.toolbar,
- gBookmarksToolbarVisibility,
- false,
- false
- );
- }
+ BookmarkingUI.updateEmptyToolbarMessage();
+ setToolbarVisibility(
+ BookmarkingUI.toolbar,
+ gBookmarksToolbarVisibility,
+ false,
+ false
+ );
}
// This is a stringbundle-like interface to gBrowserBundle, formerly a getter for
@@ -1686,13 +1680,13 @@ var gBrowserInit = {
gBrowser.addEventListener("DOMUpdateBlockedPopups", gPopupBlockerObserver);
gBrowser.addEventListener(
"TranslationsParent:LanguageState",
- TranslationsPanel
+ FullPageTranslationsPanel
);
gBrowser.addEventListener(
"TranslationsParent:OfferTranslation",
- TranslationsPanel
+ FullPageTranslationsPanel
);
- gBrowser.addTabsProgressListener(TranslationsPanel);
+ gBrowser.addTabsProgressListener(FullPageTranslationsPanel);
window.addEventListener("AppCommand", HandleAppCommandEvent, true);
@@ -1705,12 +1699,10 @@ var gBrowserInit = {
if (!gMultiProcessBrowser) {
// There is a Content:Click message manually sent from content.
- Services.els.addSystemEventListener(
- gBrowser.tabpanels,
- "click",
- contentAreaClick,
- true
- );
+ gBrowser.tabpanels.addEventListener("click", contentAreaClick, {
+ capture: true,
+ mozSystemGroup: true,
+ });
}
// hook up UI through progress listener
@@ -2424,6 +2416,10 @@ var gBrowserInit = {
"browser-idle-startup-tasks-finished"
);
});
+
+ scheduleIdleTask(() => {
+ gProfiles.init();
+ });
},
// Returns the URI(s) to load at startup if it is immediately known, or a
@@ -3035,7 +3031,7 @@ function BrowserOpenFileWindow() {
};
fp.init(
- window,
+ window.browsingContext,
gNavigatorBundle.getString("openFile"),
nsIFilePicker.modeOpen
);
@@ -3243,15 +3239,6 @@ function BrowserPageInfo(
browsingContext,
browser
) {
- if (HTMLDocument.isInstance(documentURL)) {
- Deprecated.warning(
- "Please pass the location URL instead of the document " +
- "to BrowserPageInfo() as the first argument.",
- "https://bugzilla.mozilla.org/show_bug.cgi?id=1238180"
- );
- documentURL = documentURL.location;
- }
-
let args = { initialTab, imageElement, browsingContext, browser };
documentURL = documentURL || window.gBrowser.selectedBrowser.currentURI.spec;
@@ -4549,7 +4536,23 @@ function toOpenWindowByType(inType, uri, features) {
* @return a reference to the new window.
*/
function OpenBrowserWindow(options = {}) {
- return BrowserWindowTracker.openWindow({ openerWindow: window, ...options });
+ let telemetryObj = {};
+ TelemetryStopwatch.start("FX_NEW_WINDOW_MS", telemetryObj);
+
+ let win = BrowserWindowTracker.openWindow({
+ openerWindow: window,
+ ...options,
+ });
+
+ win.addEventListener(
+ "MozAfterPaint",
+ () => {
+ TelemetryStopwatch.finish("FX_NEW_WINDOW_MS", telemetryObj);
+ },
+ { once: true }
+ );
+
+ return win;
}
/**
@@ -6456,6 +6459,37 @@ function onViewToolbarsPopupShowing(aEvent, aInsertPoint) {
return;
}
+ // triggerNode can be a nested child element of a toolbaritem.
+ let toolbarItem = popup.triggerNode;
+ while (toolbarItem) {
+ let localName = toolbarItem.localName;
+ if (localName == "toolbar") {
+ toolbarItem = null;
+ break;
+ }
+ if (localName == "toolbarpaletteitem") {
+ toolbarItem = toolbarItem.firstElementChild;
+ break;
+ }
+ if (localName == "menupopup") {
+ aEvent.preventDefault();
+ aEvent.stopPropagation();
+ return;
+ }
+ let parent = toolbarItem.parentElement;
+ if (parent) {
+ if (
+ parent.classList.contains("customization-target") ||
+ parent.getAttribute("overflowfortoolbar") || // Needs to work in the overflow list as well.
+ parent.localName == "toolbarpaletteitem" ||
+ parent.localName == "toolbar"
+ ) {
+ break;
+ }
+ }
+ toolbarItem = parent;
+ }
+
// Empty the menu
for (var i = popup.children.length - 1; i >= 0; --i) {
var deadItem = popup.children[i];
@@ -6509,30 +6543,7 @@ function onViewToolbarsPopupShowing(aEvent, aInsertPoint) {
return;
}
- // triggerNode can be a nested child element of a toolbaritem.
- let toolbarItem = popup.triggerNode;
-
- if (toolbarItem && toolbarItem.localName == "toolbarpaletteitem") {
- toolbarItem = toolbarItem.firstElementChild;
- } else if (toolbarItem && toolbarItem.localName != "toolbar") {
- while (toolbarItem && toolbarItem.parentElement) {
- let parent = toolbarItem.parentElement;
- if (
- (parent.classList &&
- parent.classList.contains("customization-target")) ||
- parent.getAttribute("overflowfortoolbar") || // Needs to work in the overflow list as well.
- parent.localName == "toolbarpaletteitem" ||
- parent.localName == "toolbar"
- ) {
- break;
- }
- toolbarItem = parent;
- }
- } else {
- toolbarItem = null;
- }
-
- let showTabStripItems = toolbarItem && toolbarItem.id == "tabbrowser-tabs";
+ let showTabStripItems = toolbarItem?.id == "tabbrowser-tabs";
for (let node of popup.querySelectorAll(
'menuitem[contexttype="toolbaritem"]'
)) {
@@ -6588,9 +6599,7 @@ function onViewToolbarsPopupShowing(aEvent, aInsertPoint) {
}
let movable =
- toolbarItem &&
- toolbarItem.id &&
- CustomizableUI.isWidgetRemovable(toolbarItem);
+ toolbarItem?.id && CustomizableUI.isWidgetRemovable(toolbarItem);
if (movable) {
if (CustomizableUI.isSpecialWidget(toolbarItem.id)) {
moveToPanel.setAttribute("disabled", true);
diff --git a/browser/base/content/browser.js.globals b/browser/base/content/browser.js.globals
new file mode 100644
index 0000000000..c767bb5beb
--- /dev/null
+++ b/browser/base/content/browser.js.globals
@@ -0,0 +1,305 @@
+[
+ "XPCOMUtils",
+ "AppConstants",
+ "gBrowser",
+ "gContextMenu",
+ "gMultiProcessBrowser",
+ "gFissionBrowser",
+ "gBrowserAllowScriptsToCloseInitialTabs",
+ "gEditUIVisible",
+ "gReduceMotionSetting",
+ "gReduceMotionOverride",
+ "shouldSuppressPopupNotifications",
+ "gLazyFindCommand",
+ "gPageIcons",
+ "gInitialPages",
+ "isInitialPage",
+ "browserWindows",
+ "updateBookmarkToolbarVisibility",
+ "gNavigatorBundle",
+ "gScreenshots",
+ "updateFxaToolbarMenu",
+ "UpdateBackForwardCommands",
+ "updatePrintCommands",
+ "SetClickAndHoldHandlers",
+ "gClickAndHoldListenersOnElement",
+ "gSessionHistoryObserver",
+ "gStoragePressureObserver",
+ "gPopupBlockerObserver",
+ "gKeywordURIFixup",
+ "_createNullPrincipalFromTabUserContextId",
+ "_resolveDelayedStartup",
+ "delayedStartupPromise",
+ "gBrowserInit",
+ "HandleAppCommandEvent",
+ "gotoHistoryIndex",
+ "BrowserForward",
+ "BrowserBack",
+ "BrowserHandleBackspace",
+ "BrowserHandleShiftBackspace",
+ "BrowserStop",
+ "BrowserReloadOrDuplicate",
+ "BrowserReload",
+ "kSkipCacheFlags",
+ "BrowserReloadSkipCache",
+ "BrowserHome",
+ "loadOneOrMoreURIs",
+ "openLocation",
+ "BrowserOpenTab",
+ "gLastOpenDirectory",
+ "BrowserOpenFileWindow",
+ "BrowserCloseTabOrWindow",
+ "BrowserTryToCloseWindow",
+ "getLoadContext",
+ "readFromClipboard",
+ "BrowserViewSourceOfDocument",
+ "BrowserViewSource",
+ "BrowserPageInfo",
+ "UpdateUrlbarSearchSplitterState",
+ "UpdatePopupNotificationsVisibility",
+ "PageProxyClickHandler",
+ "BrowserOnClick",
+ "getMeOutOfHere",
+ "getDefaultHomePage",
+ "BrowserFullScreen",
+ "BrowserReloadWithFlags",
+ "getPEMString",
+ "browserDragAndDrop",
+ "homeButtonObserver",
+ "openHomeDialog",
+ "newTabButtonObserver",
+ "newWindowButtonObserver",
+ "BrowserSearch",
+ "CreateContainerTabMenu",
+ "FillHistoryMenu",
+ "BrowserDownloadsUI",
+ "toOpenWindowByType",
+ "OpenBrowserWindow",
+ "updateEditUIVisibility",
+ "gFileMenu",
+ "gShareUtils",
+ "openNewUserContextTab",
+ "XULBrowserWindow",
+ "LinkTargetDisplay",
+ "CombinedStopReload",
+ "TabsProgressListener",
+ "nsBrowserAccess",
+ "showFullScreenViewContextMenuItems",
+ "onViewToolbarsPopupShowing",
+ "onViewToolbarCommand",
+ "setToolbarVisibility",
+ "updateToggleControlLabel",
+ "TabletModeUpdater",
+ "gTabletModePageCounter",
+ "displaySecurityInfo",
+ "gUIDensity",
+ "nodeToTooltipMap",
+ "nodeToShortcutMap",
+ "gDynamicTooltipCache",
+ "GetDynamicShortcutTooltipText",
+ "UpdateDynamicShortcutTooltipText",
+ "hrefAndLinkNodeForClickEvent",
+ "contentAreaClick",
+ "handleLinkClick",
+ "middleMousePaste",
+ "handleDroppedLink",
+ "BrowserForceEncodingDetection",
+ "ToolbarContextMenu",
+ "BrowserOffline",
+ "CanvasPermissionPromptHelper",
+ "WebAuthnPromptHelper",
+ "CanCloseWindow",
+ "WindowIsClosing",
+ "warnAboutClosingWindow",
+ "MailIntegration",
+ "BrowserOpenAddonsMgr",
+ "AddKeywordForSearchField",
+ "restoreLastClosedTabOrWindowOrSession",
+ "undoCloseTab",
+ "undoCloseWindow",
+ "ReportFalseDeceptiveSite",
+ "ReportSiteIssue",
+ "gRemoteControl",
+ "gPrivateBrowsingUI",
+ "switchToTabHavingURI",
+ "RestoreLastSessionObserver",
+ "MenuTouchModeObserver",
+ "safeModeRestart",
+ "duplicateTabIn",
+ "MousePosTracker",
+ "ToolbarIconColor",
+ "PanicButtonNotifier",
+ "SafeBrowsingNotificationBox",
+ "TabDialogBox",
+ "TabModalPromptBox",
+ "gDialogBox",
+ "ConfirmationHint",
+ "FirefoxViewHandler",
+ "AMTelemetry",
+ "AboutNewTab",
+ "AboutReaderParent",
+ "AddonManager",
+ "BrowserSearchTelemetry",
+ "BrowserTelemetryUtils",
+ "BrowserUIUtils",
+ "BrowserUsageTelemetry",
+ "BrowserWindowTracker",
+ "CFRPageActions",
+ "Color",
+ "ContentAnalysis",
+ "ContextualIdentityService",
+ "CustomizableUI",
+ "DevToolsSocketStatus",
+ "DownloadUtils",
+ "DownloadsCommon",
+ "E10SUtils",
+ "ExtensionsUI",
+ "FirefoxViewNotificationManager",
+ "HomePage",
+ "isProductURL",
+ "LightweightThemeConsumer",
+ "LoginHelper",
+ "LoginManagerParent",
+ "MigrationUtils",
+ "NetUtil",
+ "NewTabPagePreloading",
+ "NewTabUtils",
+ "NimbusFeatures",
+ "OpenInTabsUtils",
+ "PageActions",
+ "PageThumbs",
+ "PanelMultiView",
+ "PanelView",
+ "PictureInPicture",
+ "PlacesTransactions",
+ "PlacesUIUtils",
+ "PlacesUtils",
+ "Pocket",
+ "PrivateBrowsingUtils",
+ "ProcessHangMonitor",
+ "PromptUtils",
+ "ReaderMode",
+ "ResetPBMPanel",
+ "ReportBrokenSite",
+ "SafeBrowsing",
+ "Sanitizer",
+ "SaveToPocket",
+ "ScreenshotsUtils",
+ "SearchUIUtils",
+ "SessionStartup",
+ "SessionStore",
+ "ShoppingSidebarParent",
+ "ShoppingSidebarManager",
+ "ShortcutUtils",
+ "SiteDataManager",
+ "SitePermissions",
+ "SubDialog",
+ "SubDialogManager",
+ "TabCrashHandler",
+ "TabModalPrompt",
+ "TabsSetupFlowManager",
+ "TelemetryEnvironment",
+ "TranslationsParent",
+ "UITour",
+ "UpdateUtils",
+ "URILoadingHelper",
+ "UrlbarInput",
+ "UrlbarPrefs",
+ "UrlbarProviderSearchTips",
+ "UrlbarTokenizer",
+ "UrlbarUtils",
+ "UrlbarValueFormatter",
+ "Weave",
+ "WebNavigationFrames",
+ "webrtcUI",
+ "WebsiteFilter",
+ "ZoomUI",
+ "fxAccounts",
+ "PlacesTreeView",
+ "PlacesInsertionPoint",
+ "PlacesController",
+ "PlacesControllerDragHelper",
+ "PrintUtils",
+ "ZoomManager",
+ "FullZoom",
+ "PanelUI",
+ "gViewSourceUtils",
+ "gTabsPanel",
+ "BrowserAddonUI",
+ "gExtensionsNotifications",
+ "gUnifiedExtensions",
+ "gXPInstallObserver",
+ "ctrlTab",
+ "CustomizationHandler",
+ "AutoHideMenubar",
+ "PointerLock",
+ "FullScreen",
+ "gIdentityHandler",
+ "gPermissionPanel",
+ "SelectTranslationsPanel",
+ "FullPageTranslationsPanel",
+ "gProtectionsHandler",
+ "gGestureSupport",
+ "gHistorySwipeAnimation",
+ "gSafeBrowsing",
+ "gSync",
+ "gBrowserThumbnails",
+ "openContextMenu",
+ "nsContextMenu",
+ "DownloadsPanel",
+ "DownloadsOverlayLoader",
+ "DownloadsView",
+ "DownloadsViewUI",
+ "DownloadsViewController",
+ "DownloadsSummary",
+ "DownloadsFooter",
+ "DownloadsBlockedSubview",
+ "DownloadsButton",
+ "DownloadsIndicatorView",
+ "gEditItemOverlay",
+ "gGfxUtils",
+ "pktUI",
+ "ToolbarKeyboardNavigator",
+ "A11yUtils",
+ "gSharedTabWarning",
+ "gPageStyleMenu",
+ "gProfiles",
+ "ContentPrefService2",
+ "classifierService",
+ "Favicons",
+ "WindowsUIUtils",
+ "BrowserHandler",
+ "Marionette",
+ "RemoteAgent",
+ "Marionette",
+ "RemoteAgent",
+ "RTL_UI",
+ "gBrandBundle",
+ "gBrowserBundle",
+ "gCustomizeMode",
+ "gNavToolbox",
+ "gURLBar",
+ "ReferrerInfo",
+ "gNotificationBox",
+ "InlineSpellCheckerUI",
+ "PopupNotifications",
+ "MacUserActivityUpdater",
+ "Win7Features",
+ "gToolbarKeyNavEnabled",
+ "gBookmarksToolbarVisibility",
+ "gFxaToolbarEnabled",
+ "gFxaToolbarAccessed",
+ "gAddonAbuseReportEnabled",
+ "gAlwaysOpenPanel",
+ "gMiddleClickNewTabUsesPasteboard",
+ "gScreenshotsDisabled",
+ "gPrintEnabled",
+ "gScreenshotsComponentEnabled",
+ "gTranslationsEnabled",
+ "gUseFeltPrivacyUI",
+ "gReduceMotion",
+ "gFindBar",
+ "gFindBarInitialized",
+ "gFindBarPromise",
+ "BrowserSearch"
+]
diff --git a/browser/base/content/browser.xhtml b/browser/base/content/browser.xhtml
index b4886fb5f7..1dcdd02cd1 100644
--- a/browser/base/content/browser.xhtml
+++ b/browser/base/content/browser.xhtml
@@ -98,6 +98,8 @@
<link rel="localization" href="preview/select-translations.ftl"/>
<link rel="localization" href="browser/shopping.ftl"/>
<link rel="localization" href="preview/shopping.ftl"/>
+ <link rel="localization" href="preview/profiles.ftl"/>
+ <link rel="localization" href="preview/onboarding.ftl"/>
<title data-l10n-id="browser-main-window-title"></title>
diff --git a/browser/base/content/contentTheme.js b/browser/base/content/contentTheme.js
index 805fc778c0..3c46b80bec 100644
--- a/browser/base/content/contentTheme.js
+++ b/browser/base/content/contentTheme.js
@@ -137,7 +137,7 @@
/**
* ContentThemeController handles theme updates sent by the frame script.
* To be able to use ContentThemeController, you must add your page to the whitelist
- * in LightweightThemeChildListener.jsm
+ * in LightweightThemeChild.sys.mjs
*/
const ContentThemeController = {
/**
diff --git a/browser/base/content/main-popupset.inc.xhtml b/browser/base/content/main-popupset.inc.xhtml
index 4074f35ffc..bff8d98b27 100644
--- a/browser/base/content/main-popupset.inc.xhtml
+++ b/browser/base/content/main-popupset.inc.xhtml
@@ -36,10 +36,10 @@
<menuitem id="context_bookmarkSelectedTabs"
hidden="true"
data-lazy-l10n-id="bookmark-selected-tabs"
- oncommand="PlacesUIUtils.showBookmarkPagesDialog(PlacesCommandHook.uniqueSelectedPages);"/>
+ oncommand="PlacesCommandHook.bookmarkTabs(gBrowser.selectedTabs);"/>
<menuitem id="context_bookmarkTab"
data-lazy-l10n-id="tab-context-bookmark-tab"
- oncommand="PlacesUIUtils.showBookmarkPagesDialog(PlacesCommandHook.getUniquePages([TabContextMenu.contextTab]));"/>
+ oncommand="PlacesCommandHook.bookmarkTabs([TabContextMenu.contextTab]);"/>
<menu id="context_moveTabOptions"
data-lazy-l10n-id="tab-context-move-tabs"
data-l10n-args='{"tabCount": 1}'>
@@ -326,11 +326,11 @@
data-lazy-l10n-id="toolbar-context-menu-reload-selected-tabs"/>
<menuitem id="toolbar-context-bookmarkSelectedTab"
contexttype="tabbar"
- oncommand="PlacesUIUtils.showBookmarkPagesDialog(PlacesCommandHook.uniqueSelectedPages);"
+ oncommand="PlacesCommandHook.bookmarkTabs(gBrowser.selectedTabs);"
data-lazy-l10n-id="toolbar-context-menu-bookmark-selected-tab"/>
<menuitem id="toolbar-context-bookmarkSelectedTabs"
contexttype="tabbar"
- oncommand="PlacesUIUtils.showBookmarkPagesDialog(PlacesCommandHook.uniqueSelectedPages);"
+ oncommand="PlacesCommandHook.bookmarkTabs(gBrowser.selectedTabs);"
data-lazy-l10n-id="toolbar-context-menu-bookmark-selected-tabs"/>
<menuitem id="toolbar-context-selectAllTabs"
contexttype="tabbar"
@@ -496,7 +496,8 @@
#include ../../components/controlcenter/content/permissionPanel.inc.xhtml
#include ../../components/controlcenter/content/protectionsPanel.inc.xhtml
#include ../../components/downloads/content/downloadsPanel.inc.xhtml
-#include ../../components/translations/content/translationsPanel.inc.xhtml
+#include ../../components/translations/content/selectTranslationsPanel.inc.xhtml
+#include ../../components/translations/content/fullPageTranslationsPanel.inc.xhtml
#include browser-allTabsMenu.inc.xhtml
<tooltip id="dynamic-shortcut-tooltip"
@@ -624,38 +625,38 @@
</menupopup>
<menupopup id="translations-panel-settings-menupopup"
- onpopupshown="TranslationsPanel.handleSettingsPopupShownEvent()"
- onpopuphidden="TranslationsPanel.handleSettingsPopupHiddenEvent()">
+ onpopupshown="FullPageTranslationsPanel.handleSettingsPopupShownEvent()"
+ onpopuphidden="FullPageTranslationsPanel.handleSettingsPopupHiddenEvent()">
<menuitem class="always-offer-translations-menuitem"
data-l10n-id="translations-panel-settings-always-offer-translation"
type="checkbox"
checked="false"
autocheck="false"
- oncommand="TranslationsPanel.onAlwaysOfferTranslations()"/>
+ oncommand="FullPageTranslationsPanel.onAlwaysOfferTranslations()"/>
<menuitem class="always-translate-language-menuitem"
data-l10n-id="translations-panel-settings-always-translate-unknown-language"
type="checkbox"
checked="false"
autocheck="false"
- oncommand="TranslationsPanel.onAlwaysTranslateLanguage()"/>
+ oncommand="FullPageTranslationsPanel.onAlwaysTranslateLanguage()"/>
<menuitem class="never-translate-language-menuitem"
data-l10n-id="translations-panel-settings-never-translate-unknown-language"
type="checkbox"
checked="false"
autocheck="false"
- oncommand="TranslationsPanel.onNeverTranslateLanguage()"/>
+ oncommand="FullPageTranslationsPanel.onNeverTranslateLanguage()"/>
<menuseparator/>
<menuitem class="never-translate-site-menuitem"
data-l10n-id="translations-panel-settings-never-translate-site"
type="checkbox"
checked="false"
autocheck="false"
- oncommand="TranslationsPanel.onNeverTranslateSite()"/>
+ oncommand="FullPageTranslationsPanel.onNeverTranslateSite()"/>
<menuseparator/>
<menuitem class="manage-languages-menuitem"
data-l10n-id="translations-panel-settings-manage-languages"
- oncommand="TranslationsPanel.openManageLanguages()"/>
+ oncommand="FullPageTranslationsPanel.openManageLanguages()"/>
<menuitem data-l10n-id="translations-panel-settings-about2"
- oncommand="TranslationsPanel.onAboutTranslations()"/>
+ oncommand="FullPageTranslationsPanel.onAboutTranslations()"/>
</menupopup>
</popupset>
diff --git a/browser/base/content/moz.build b/browser/base/content/moz.build
index f91487920f..1dd7dccb5f 100644
--- a/browser/base/content/moz.build
+++ b/browser/base/content/moz.build
@@ -151,6 +151,9 @@ with Files("browser-pageActions.js"):
with Files("browser-places.js"):
BUG_COMPONENT = ("Firefox", "Bookmarks & History")
+with Files("browser-profiles.js"):
+ BUG_COMPONENT = ("Firefox", "Profiles")
+
with Files("browser-safebrowsing.js"):
BUG_COMPONENT = ("Toolkit", "Safe Browsing")
diff --git a/browser/base/content/navigator-toolbox.inc.xhtml b/browser/base/content/navigator-toolbox.inc.xhtml
index dce7bacdb3..fc19910726 100644
--- a/browser/base/content/navigator-toolbox.inc.xhtml
+++ b/browser/base/content/navigator-toolbox.inc.xhtml
@@ -371,8 +371,8 @@
role="button"
data-l10n-id="urlbar-translations-button2"
hidden="true"
- onclick="TranslationsPanel.open(event);"
- onkeypress="TranslationsPanel.open(event);">
+ onclick="FullPageTranslationsPanel.open(event);"
+ onkeypress="FullPageTranslationsPanel.open(event);">
<image class="urlbar-icon" id="translations-button-icon" />
<image class="urlbar-icon" id="translations-button-circle-arrows" />
<html:span id="translations-button-locale" aria-hidden="true" />
@@ -610,7 +610,7 @@
oncommand="BookmarkingUI.onCommand(event);">
<menupopup id="BMB_bookmarksPopup"
is="places-popup-arrow"
- class="toolbar-menupopup"
+ class="toolbar-menupopup animatable-menupopup"
placespopup="true"
context="placesContext"
openInTabs="children"
diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js
index 4e313e7f01..031a32dddf 100644
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -107,6 +107,14 @@ function openContextMenu(aMessage, aBrowser, aActor) {
}
class nsContextMenu {
+ /**
+ * A promise to retrieve the translations language pair
+ * if the context menu was opened in a context relevant to
+ * open the SelectTranslationsPanel.
+ * @type {Promise<{fromLang: string, toLang: string}>}
+ */
+ #translationsLangPairPromise;
+
constructor(aXulMenu, aIsShift) {
// Get contextual info.
this.setContext();
@@ -328,7 +336,9 @@ class nsContextMenu {
InlineSpellCheckerUI.clearDictionaryListFromMenu();
InlineSpellCheckerUI.uninit();
if (
- Cu.isModuleLoaded("resource://gre/modules/LoginManagerContextMenu.jsm")
+ Cu.isESModuleLoaded(
+ "resource://gre/modules/LoginManagerContextMenu.sys.mjs"
+ )
) {
nsContextMenu.LoginManagerContextMenu.clearLoginsFromMenu(document);
}
@@ -384,6 +394,11 @@ class nsContextMenu {
this.showItem(id, this.inPDFEditor);
}
+ this.showItem(
+ "context-pdfjs-highlight-selection",
+ this.pdfEditorStates?.hasSelectedText
+ );
+
if (!this.inPDFEditor) {
return;
}
@@ -1379,9 +1394,7 @@ class nsContextMenu {
useGeneratedPassword() {
nsContextMenu.LoginManagerContextMenu.useGeneratedPassword(
- this.targetIdentifier,
- this.contentData.documentURIObject,
- this.browser
+ this.targetIdentifier
);
}
@@ -2514,9 +2527,65 @@ class nsContextMenu {
}
/**
- * Displays or hides as well as localizes the translate-selection item in the context menu.
+ * Opens the SelectTranslationsPanel singleton instance.
+ *
+ * @param {Event} event - The triggering event for opening the panel.
+ */
+ openSelectTranslationsPanel(event) {
+ SelectTranslationsPanel.open(event, this.#translationsLangPairPromise);
+ }
+
+ /**
+ * Localizes the translate-selection menuitem.
+ *
+ * The item will either be localized with a target language's display name
+ * or localized in a generic way without a target language.
+ *
+ * @param {Element} translateSelectionItem
+ * @returns {Promise<void>}
*/
- async showTranslateSelectionItem() {
+ async localizeTranslateSelectionItem(translateSelectionItem) {
+ const { toLang } = await this.#translationsLangPairPromise;
+
+ if (toLang) {
+ // A valid to-language exists, so localize the menuitem for that language.
+ let displayName;
+
+ try {
+ const displayNames = new Services.intl.DisplayNames(undefined, {
+ type: "language",
+ });
+ displayName = displayNames.of(toLang);
+ } catch {
+ // Services.intl.DisplayNames.of threw, do nothing.
+ }
+
+ if (displayName) {
+ document.l10n.setAttributes(
+ translateSelectionItem,
+ this.isTextSelected
+ ? "main-context-menu-translate-selection-to-language"
+ : "main-context-menu-translate-link-text-to-language",
+ { language: displayName }
+ );
+ return;
+ }
+ }
+
+ // Either no to-language exists, or an error occurred,
+ // so localize the menuitem without a target language.
+ document.l10n.setAttributes(
+ translateSelectionItem,
+ this.isTextSelected
+ ? "main-context-menu-translate-selection"
+ : "main-context-menu-translate-link-text"
+ );
+ }
+
+ /**
+ * Displays or hides the translate-selection item in the context menu.
+ */
+ showTranslateSelectionItem() {
const translateSelectionItem = document.getElementById(
"context-translate-selection"
);
@@ -2528,7 +2597,7 @@ class nsContextMenu {
);
// Selected text takes precedence over link text.
- const translatableText = this.isTextSelected
+ const textToTranslate = this.isTextSelected
? this.selectedText.trim()
: this.linkTextStr.trim();
@@ -2536,7 +2605,7 @@ class nsContextMenu {
// Only show the item if the feature is enabled.
!(translationsEnabled && selectTranslationsEnabled) ||
// If there is no text to translate, we have nothing to do.
- translatableText.length === 0 ||
+ textToTranslate.length === 0 ||
// We do not allow translating selections on top of Full Page Translations.
nsContextMenu.#isFullPageTranslationsActive();
@@ -2544,39 +2613,9 @@ class nsContextMenu {
return;
}
- const preferredLanguages =
- nsContextMenu.TranslationsParent.getPreferredLanguages();
- const topPreferredLanguage = preferredLanguages[0];
-
- if (topPreferredLanguage) {
- const { language } = await nsContextMenu.LanguageDetector.detectLanguage(
- translatableText
- );
- if (topPreferredLanguage !== language) {
- try {
- const dn = new Services.intl.DisplayNames(undefined, {
- type: "language",
- });
- document.l10n.setAttributes(
- translateSelectionItem,
- this.isTextSelected
- ? "main-context-menu-translate-selection-to-language"
- : "main-context-menu-translate-link-text-to-language",
- { language: dn.of(topPreferredLanguage) }
- );
- return;
- } catch {
- // Services.intl.DisplayNames.of threw, do nothing.
- }
- }
- }
-
- document.l10n.setAttributes(
- translateSelectionItem,
- this.isTextSelected
- ? "main-context-menu-translate-selection"
- : "main-context-menu-translate-link-text"
- );
+ this.#translationsLangPairPromise =
+ SelectTranslationsPanel.getLangPairPromise(textToTranslate);
+ this.localizeTranslateSelectionItem(translateSelectionItem);
}
// Formats the 'Search <engine> for "<selection or link text>"' context menu.
@@ -2681,8 +2720,6 @@ class nsContextMenu {
ChromeUtils.defineESModuleGetters(nsContextMenu, {
DevToolsShim: "chrome://devtools-startup/content/DevToolsShim.sys.mjs",
- LanguageDetector:
- "resource://gre/modules/translation/LanguageDetector.sys.mjs",
LoginManagerContextMenu:
"resource://gre/modules/LoginManagerContextMenu.sys.mjs",
TranslationsParent: "resource://gre/actors/TranslationsParent.sys.mjs",
diff --git a/browser/base/content/pageinfo/pageInfo.js b/browser/base/content/pageinfo/pageInfo.js
index 178e28ad65..f3999a7cc5 100644
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -686,7 +686,7 @@ async function selectSaveFolder(aCallback) {
}
};
- fp.init(window, titleText, nsIFilePicker.modeGetFolder);
+ fp.init(window.browsingContext, titleText, nsIFilePicker.modeGetFolder);
fp.appendFilters(nsIFilePicker.filterAll);
try {
let initialDir = Services.prefs.getComplexValue(
diff --git a/browser/base/content/popup-notifications.inc b/browser/base/content/popup-notifications.inc
index e554bca50b..daee34e6fe 100644
--- a/browser/base/content/popup-notifications.inc
+++ b/browser/base/content/popup-notifications.inc
@@ -78,7 +78,7 @@
<popupnotificationcontent orient="vertical">
<label data-l10n-id="panel-save-update-username" control="password-notification-username" class="password-notification-label"></label>
<stack>
- <html:input id="password-notification-username"
+ <html:input id="password-notification-username"
type="text"
class="ac-has-end-icon"
autocompletesearch="login-doorhanger-username"
@@ -132,7 +132,7 @@
<popupnotificationcontent id="addon-install-blocked-content" orient="vertical">
<description id="addon-install-blocked-message" class="popup-notification-description"></description>
<hbox>
- <html:a
+ <html:a
is="moz-support-link"
id="addon-install-blocked-info"
class="popup-notification-learnmore-link"
@@ -261,7 +261,7 @@
<popupnotification id="address-save-update-notification" class="address-capture-notification" hidden="true">
<popupnotificationcontent class="address-save-update-notification-content" orient="vertical">
<html:div class="address-capture-header">
- <html:p/>
+ <html:h1/>
</html:div>
<html:div class="address-capture-description">
<html:p/>
@@ -274,7 +274,7 @@
<popupnotification id="address-edit-notification" class="address-capture-notification" hidden="true">
<popupnotificationcontent class="address-edit-notification-content" orient="vertical">
<html:div class="address-capture-header">
- <html:p/>
+ <html:h1/>
</html:div>
<html:div class="address-capture-content">
</html:div>
diff --git a/browser/base/content/sanitizeDialog.js b/browser/base/content/sanitizeDialog.js
index 2be0d500d5..09a7d927df 100644
--- a/browser/base/content/sanitizeDialog.js
+++ b/browser/base/content/sanitizeDialog.js
@@ -38,6 +38,14 @@ Preferences.addAll([
{ id: "privacy.cpd.siteSettings", type: "bool" },
{ id: "privacy.sanitize.timeSpan", type: "int" },
{ id: "privacy.clearOnShutdown.history", type: "bool" },
+ { id: "privacy.clearHistory.historyFormDataAndDownloads", type: "bool" },
+ { id: "privacy.clearHistory.cookiesAndStorage", type: "bool" },
+ { id: "privacy.clearHistory.cache", type: "bool" },
+ { id: "privacy.clearHistory.siteSettings", type: "bool" },
+ { id: "privacy.clearSiteData.historyFormDataAndDownloads", type: "bool" },
+ { id: "privacy.clearSiteData.cookiesAndStorage", type: "bool" },
+ { id: "privacy.clearSiteData.cache", type: "bool" },
+ { id: "privacy.clearSiteData.siteSettings", type: "bool" },
{
id: "privacy.clearOnShutdown_v2.historyFormDataAndDownloads",
type: "bool",
@@ -76,12 +84,6 @@ var gSanitizePromptDialog = {
this.siteDataSizes = {};
this.cacheSize = [];
- if (!lazy.USE_OLD_DIALOG) {
- this._cookiesAndSiteDataCheckbox =
- document.getElementById("cookiesAndStorage");
- this._cacheCheckbox = document.getElementById("cache");
- }
-
let arg = window.arguments?.[0] || {};
// These variables decide which context the dialog has been opened in
@@ -93,17 +95,6 @@ var gSanitizePromptDialog = {
this._inClearSiteDataNewDialog = arg.mode == "clearSiteData";
}
- // Clear site data has it's own default checked boxes, all other entry points
- // follow the clear history default prefs
- this.defaultCheckedByContext = {
- clearHistory: [
- "historyFormDataAndDownloads",
- "cookiesAndStorage",
- "cache",
- ],
- clearSiteData: ["cookiesAndStorage", "cache"],
- };
-
if (arg.inBrowserWindow) {
this._dialog.setAttribute("inbrowserwindow", "true");
this._observeTitleForChanges();
@@ -119,7 +110,7 @@ var gSanitizePromptDialog = {
if (!lazy.USE_OLD_DIALOG) {
// Begin collecting how long it takes to load from here
let timerId = Glean.privacySanitize.loadTime.start();
-
+ this._dataSizesUpdated = false;
this.dataSizesFinishedUpdatingPromise = this.getAndUpdateDataSizes()
.then(() => {
// We're done loading, stop telemetry here
@@ -138,50 +129,42 @@ var gSanitizePromptDialog = {
let clearPrivateDataGroupbox = document.getElementById(
"clearPrivateDataGroupbox"
);
+ let clearSiteDataGroupbox = document.getElementById(
+ "clearSiteDataGroupbox"
+ );
let okButtonl10nID = "sanitize-button-ok";
if (this._inClearOnShutdownNewDialog) {
okButtonl10nID = "sanitize-button-ok-on-shutdown";
this._dialog.setAttribute("inClearOnShutdown", "true");
- // remove the clear private data groupbox element
- clearPrivateDataGroupbox.remove();
+ // remove the other groupbox elements that aren't related to the context
+ // the dialog is opened in
+ clearPrivateDataGroupbox.remove();
+ clearSiteDataGroupbox.remove();
// If this is the first time the user is opening the new clear on shutdown
// dialog, migrate their prefs
- Sanitizer.maybeMigrateSanitizeOnShutdownPrefs();
+ Sanitizer.maybeMigratePrefs("clearOnShutdown");
} else if (!lazy.USE_OLD_DIALOG) {
okButtonl10nID = "sanitize-button-ok2";
- // remove the clear on shutdown groupbox element
clearOnShutdownGroupbox.remove();
- }
- document.l10n.setAttributes(OKButton, okButtonl10nID);
-
- // update initial checkbox values based on the context the dialog is opened
- // from (history, site data). Categories are not remembered
- // from the last time the dialog was used.
- if (!lazy.USE_OLD_DIALOG && !this._inClearOnShutdownNewDialog) {
- let defaults = this.defaultCheckedByContext.clearHistory;
if (this._inClearSiteDataNewDialog) {
- defaults = this.defaultCheckedByContext.clearSiteData;
+ clearPrivateDataGroupbox.remove();
+ // we do not need to migrate prefs for clear site data,
+ // since we decided to keep the default options for
+ // privacy.clearSiteData.* to stay consistent with old behaviour
+ // of the clear site data dialog box
+ } else {
+ clearSiteDataGroupbox.remove();
+ Sanitizer.maybeMigratePrefs("cpd");
}
+ }
+ document.l10n.setAttributes(OKButton, okButtonl10nID);
- this._allCheckboxes = document.querySelectorAll(
- "#clearPrivateDataGroupbox .clearingItemCheckbox"
- );
- this._allCheckboxes.forEach(checkbox => {
- let pref = checkbox.id;
- let value = false;
- if (defaults.includes(pref)) {
- value = true;
- checkbox.checked = value;
- }
-
- // Add event listeners to the checkboxes to ensure that the clear button is
- // disabled if no checkboxes are checked
- checkbox.addEventListener("command", _ =>
- this.updateAcceptButtonState()
- );
- });
+ if (!lazy.USE_OLD_DIALOG) {
+ this._cookiesAndSiteDataCheckbox =
+ document.getElementById("cookiesAndStorage");
+ this._cacheCheckbox = document.getElementById("cache");
}
document.addEventListener("dialogaccept", e => {
@@ -191,10 +174,13 @@ var gSanitizePromptDialog = {
if (!lazy.USE_OLD_DIALOG) {
this.reportTelemetry("clear");
}
+
this.sanitize(e);
}
});
+ this._allCheckboxes = document.querySelectorAll("checkbox[preference]");
+
this.registerSyncFromPrefListeners();
// we want to show the warning box for all cases except clear on shutdown
@@ -222,8 +208,6 @@ var gSanitizePromptDialog = {
if (!lazy.USE_OLD_DIALOG) {
this.reportTelemetry("open");
}
-
- await this.dataSizesFinishedUpdatingPromise;
},
updateAcceptButtonState() {
@@ -306,6 +290,7 @@ var gSanitizePromptDialog = {
ignoreTimespan: !range,
range,
};
+
let itemsToClear = this.getItemsToClear();
Sanitizer.sanitize(itemsToClear, options)
.catch(console.error)
@@ -347,14 +332,9 @@ var gSanitizePromptDialog = {
* Return the boolean prefs that correspond to the checkboxes on the dialog.
*/
_getItemPrefs() {
- return Preferences.getAll().filter(pref => {
- // The timespan pref isn't a bool, so don't return it
- if (pref.id == "privacy.sanitize.timeSpan") {
- return false;
- }
- // In the old dialog, cpd.downloads isn't controlled by a checkbox
- return !(lazy.USE_OLD_DIALOG && pref.id == "privacy.cpd.downloads");
- });
+ return Array.from(this._allCheckboxes).map(checkbox =>
+ checkbox.getAttribute("preference")
+ );
},
/**
@@ -367,7 +347,7 @@ var gSanitizePromptDialog = {
// and (in the old dialog) privacy.cpd.downloads which is not controlled
// directly by a checkbox).
var found = this._getItemPrefs().some(
- pref => !!pref.value && !pref.disabled
+ pref => Preferences.get(pref).value === true
);
try {
@@ -417,6 +397,8 @@ var gSanitizePromptDialog = {
);
}
this.cacheSize = lazy.DownloadUtils.convertByteUnits(cacheSize);
+
+ this._dataSizesUpdated = true;
this.updateDataSizesInUI();
},
@@ -441,7 +423,7 @@ var gSanitizePromptDialog = {
// elements.
var prefs = this._getItemPrefs();
for (let i = 0; i < prefs.length; ++i) {
- var p = prefs[i];
+ var p = Preferences.get(prefs[i]);
Services.prefs.setBoolPref(p.id, p.value);
}
},
@@ -492,6 +474,10 @@ var gSanitizePromptDialog = {
* Updates data sizes displayed based on new selected timespan
*/
updateDataSizesInUI() {
+ if (!this._dataSizesUpdated) {
+ return;
+ }
+
const TIMESPAN_SELECTION_MAP = {
0: "TIMESPAN_EVERYTHING",
1: "TIMESPAN_HOUR",
@@ -531,11 +517,7 @@ var gSanitizePromptDialog = {
}
let items = [];
- let clearPrivateDataGroupbox = document.getElementById(
- "clearPrivateDataGroupbox"
- );
-
- for (let cb of clearPrivateDataGroupbox.querySelectorAll("checkbox")) {
+ for (let cb of this._allCheckboxes) {
if (cb.checked) {
items.push(cb.id);
}
diff --git a/browser/base/content/sanitize_v2.xhtml b/browser/base/content/sanitize_v2.xhtml
index 97ad484e5f..4d74e140a3 100644
--- a/browser/base/content/sanitize_v2.xhtml
+++ b/browser/base/content/sanitize_v2.xhtml
@@ -108,6 +108,7 @@
<checkbox
class="clearingItemCheckbox"
data-l10n-id="item-history-form-data-downloads"
+ preference="privacy.clearHistory.historyFormDataAndDownloads"
id="historyFormDataAndDownloads"
/>
<description
@@ -123,6 +124,7 @@
class="clearingItemCheckbox"
data-l10n-id="item-cookies-site-data"
aria-describedby="cookies-site-data-description"
+ preference="privacy.clearHistory.cookiesAndStorage"
id="cookiesAndStorage"
/>
<description
@@ -138,6 +140,7 @@
class="clearingItemCheckbox"
data-l10n-id="item-cached-content"
aria-describedby="cached-content-description"
+ preference="privacy.clearHistory.cache"
id="cache"
/>
<description
@@ -153,6 +156,72 @@
class="clearingItemCheckbox"
data-l10n-id="item-site-prefs"
aria-describedby="site-prefs-description"
+ preference="privacy.clearHistory.siteSettings"
+ id="siteSettings"
+ />
+ <description
+ id="site-prefs-description"
+ data-l10n-id="item-site-prefs-description"
+ class="sanitizeCheckboxDescription text-deemphasized"
+ />
+ </vbox>
+ </hbox>
+ </groupbox>
+ <groupbox id="clearSiteDataGroupbox">
+ <hbox class="checkboxWithDescription">
+ <vbox>
+ <checkbox
+ class="clearingItemCheckbox"
+ data-l10n-id="item-history-form-data-downloads"
+ preference="privacy.clearSiteData.historyFormDataAndDownloads"
+ id="historyFormDataAndDownloads"
+ />
+ <description
+ id="history-form-data-description"
+ data-l10n-id="item-history-form-data-downloads-description"
+ class="sanitizeCheckboxDescription text-deemphasized"
+ />
+ </vbox>
+ </hbox>
+ <hbox class="checkboxWithDescription">
+ <vbox>
+ <checkbox
+ class="clearingItemCheckbox"
+ data-l10n-id="item-cookies-site-data"
+ aria-describedby="cookies-site-data-description"
+ preference="privacy.clearSiteData.cookiesAndStorage"
+ id="cookiesAndStorage"
+ />
+ <description
+ id="cookies-site-data-description"
+ data-l10n-id="item-cookies-site-data-description"
+ class="sanitizeCheckboxDescription text-deemphasized"
+ />
+ </vbox>
+ </hbox>
+ <hbox class="checkboxWithDescription">
+ <vbox>
+ <checkbox
+ class="clearingItemCheckbox"
+ data-l10n-id="item-cached-content"
+ aria-describedby="cached-content-description"
+ preference="privacy.clearSiteData.cache"
+ id="cache"
+ />
+ <description
+ id="cached-content-description"
+ data-l10n-id="item-cached-content-description"
+ class="sanitizeCheckboxDescription text-deemphasized"
+ />
+ </vbox>
+ </hbox>
+ <hbox class="checkboxWithDescription">
+ <vbox>
+ <checkbox
+ class="clearingItemCheckbox"
+ data-l10n-id="item-site-prefs"
+ aria-describedby="site-prefs-description"
+ preference="privacy.clearSiteData.siteSettings"
id="siteSettings"
/>
<description
diff --git a/browser/base/content/tabbrowser-tab.js b/browser/base/content/tabbrowser-tab.js
index 01bb7ee90b..ed3d4bb727 100644
--- a/browser/base/content/tabbrowser-tab.js
+++ b/browser/base/content/tabbrowser-tab.js
@@ -350,7 +350,20 @@
count: affectedTabsLength,
});
}
- this._mouseenter();
+
+ if (this.hidden || this.closing) {
+ return;
+ }
+
+ let tabToWarm = this.mOverCloseButton
+ ? gBrowser._findTabToBlurTo(this)
+ : this;
+ gBrowser.warmupTab(tabToWarm);
+
+ // If the previous target wasn't part of this tab then this is a mouseenter event.
+ if (!this.contains(event.relatedTarget)) {
+ this._mouseenter();
+ }
}
on_mouseout(event) {
@@ -360,7 +373,11 @@
if (event.target == this.overlayIcon) {
this.setSecondaryTabTooltipLabel(null);
}
- this._mouseleave();
+
+ // If the new target is not part of this tab then this is a mouseleave event.
+ if (!this.contains(event.relatedTarget)) {
+ this._mouseleave();
+ }
}
on_dragstart(event) {
@@ -530,9 +547,6 @@
}
_mouseenter() {
- if (this.hidden || this.closing) {
- return;
- }
this._hover = true;
if (this.selected) {
@@ -545,12 +559,6 @@
// Prepare connection to host beforehand.
SessionStore.speculativeConnectOnTabHover(this);
- let tabToWarm = this;
- if (this.mOverCloseButton) {
- tabToWarm = gBrowser._findTabToBlurTo(this);
- }
- gBrowser.warmupTab(tabToWarm);
-
this.dispatchEvent(new CustomEvent("TabHoverStart", { bubbles: true }));
}
diff --git a/browser/base/content/tabbrowser-tabs.js b/browser/base/content/tabbrowser-tabs.js
index 4733e6d0b6..36b6aeb390 100644
--- a/browser/base/content/tabbrowser-tabs.js
+++ b/browser/base/content/tabbrowser-tabs.js
@@ -187,6 +187,26 @@
this.updateTabIndicatorAttr(event.target);
}
+ on_TabHoverStart(event) {
+ if (this._showCardPreviews) {
+ const previewContainer = document.getElementById(
+ "tabbrowser-tab-preview"
+ );
+ previewContainer.tab = event.target;
+ }
+ }
+
+ on_TabHoverEnd(event) {
+ if (this._showCardPreviews) {
+ const previewContainer = document.getElementById(
+ "tabbrowser-tab-preview"
+ );
+ if (previewContainer.tab === event.target) {
+ previewContainer.tab = null;
+ }
+ }
+ }
+
on_transitionend(event) {
if (event.propertyName != "max-width") {
return;
@@ -1818,22 +1838,6 @@
handleEvent(aEvent) {
switch (aEvent.type) {
- case "TabHoverStart":
- if (this._showCardPreviews) {
- const previewContainer = document.getElementById(
- "tabbrowser-tab-preview"
- );
- previewContainer.tab = aEvent.target;
- }
- break;
- case "TabHoverEnd":
- if (this._showCardPreviews) {
- const previewContainer = document.getElementById(
- "tabbrowser-tab-preview"
- );
- previewContainer.tab = null;
- }
- break;
case "mouseout":
// If the "related target" (the node to which the pointer went) is not
// a child of the current document, the mouse just left the window.
diff --git a/browser/base/content/tabbrowser.js b/browser/base/content/tabbrowser.js
index a9637ad262..54a801939a 100644
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -119,8 +119,8 @@
Services.obs.addObserver(this, "contextual-identity-updated");
- Services.els.addSystemEventListener(document, "keydown", this, false);
- Services.els.addSystemEventListener(document, "keypress", this, false);
+ document.addEventListener("keydown", this, { mozSystemGroup: true });
+ document.addEventListener("keypress", this, { mozSystemGroup: true });
document.addEventListener("visibilitychange", this);
window.addEventListener("framefocusrequested", this);
window.addEventListener("activate", this);
@@ -5948,14 +5948,11 @@
}
}
- Services.els.removeSystemEventListener(document, "keydown", this, false);
+ document.removeEventListener("keydown", this, { mozSystemGroup: true });
if (AppConstants.platform == "macosx") {
- Services.els.removeSystemEventListener(
- document,
- "keypress",
- this,
- false
- );
+ document.removeEventListener("keypress", this, {
+ mozSystemGroup: true,
+ });
}
document.removeEventListener("visibilitychange", this);
window.removeEventListener("framefocusrequested", this);
diff --git a/browser/base/content/test/about/browser.toml b/browser/base/content/test/about/browser.toml
index 900c6b7140..98961200a0 100644
--- a/browser/base/content/test/about/browser.toml
+++ b/browser/base/content/test/about/browser.toml
@@ -34,7 +34,8 @@ support-files = [
["browser_aboutHome_search_suggestion.js"]
skip-if = [
"os == 'mac'",
- "os == 'linux' && (!debug || bits == 64)",
+ "os == 'linux' && os_version == '18.04' && !debug",
+ "os == 'linux' && os_version == '18.04' && bits == 64",
"win10_2009 && bits == 64 && !debug", # Bug 1399648, bug 1402502
]
@@ -75,7 +76,7 @@ skip-if = ["tsan"] # Bug 1676326, highly frequent on TSan
["browser_aboutStopReload.js"]
["browser_aboutSupport.js"]
-skip-if = ["os == 'linux' && bits == 64 && asan && !debug"] # Bug 1713368
+skip-if = ["os == 'linux' && os_version == '18.04' && asan"] # Bug 1713368
["browser_aboutSupport_newtab_security_state.js"]
@@ -83,6 +84,9 @@ skip-if = ["os == 'linux' && bits == 64 && asan && !debug"] # Bug 1713368
skip-if = ["os == 'android'"]
["browser_bug435325.js"]
-skip-if = ["verify && !debug && os == 'mac'"]
+skip-if = [
+ "apple_catalina && !debug && verify",
+ "apple_silicon && !debug && verify",
+]
["browser_bug633691.js"]
diff --git a/browser/base/content/test/about/browser_aboutNetError.js b/browser/base/content/test/about/browser_aboutNetError.js
index 8222a0f6e8..9131f5e696 100644
--- a/browser/base/content/test/about/browser_aboutNetError.js
+++ b/browser/base/content/test/about/browser_aboutNetError.js
@@ -25,6 +25,38 @@ function resetPrefs() {
Services.prefs.clearUserPref("browser.fixup.alternate.enabled");
}
+async function resetTelemetry() {
+ Services.telemetry.clearEvents();
+ await TestUtils.waitForCondition(() => {
+ let events = Services.telemetry.snapshotEvents(
+ Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
+ true
+ ).content;
+ return !events || !events.length;
+ });
+ Services.telemetry.setEventRecordingEnabled("security.ui.tlserror", true);
+}
+
+async function checkTelemetry(errorString) {
+ let loadEvent = await TestUtils.waitForCondition(() => {
+ let events = Services.telemetry.snapshotEvents(
+ Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
+ true
+ ).content;
+ return events?.find(e => e[1] == "security.ui.tlserror" && e[2] == "load");
+ }, "recorded telemetry for the load");
+ loadEvent.shift();
+ Assert.deepEqual(loadEvent, [
+ "security.ui.tlserror",
+ "load",
+ "abouttlserror",
+ errorString,
+ {
+ is_frame: "false",
+ },
+ ]);
+}
+
add_task(async function resetToDefaultConfig() {
info(
"Change TLS config to cause page load to fail, check that reset button is shown and that it works"
@@ -34,6 +66,8 @@ add_task(async function resetToDefaultConfig() {
Services.prefs.setIntPref("security.tls.version.min", 1); // TLS 1.0
Services.prefs.setIntPref("security.tls.version.max", 1);
+ await resetTelemetry();
+
let browser;
let pageLoaded;
await BrowserTestUtils.openNewForegroundTab(
@@ -49,6 +83,8 @@ add_task(async function resetToDefaultConfig() {
info("Loading and waiting for the net error");
await pageLoaded;
+ await checkTelemetry("SSL_ERROR_PROTOCOL_VERSION_ALERT");
+
// Setup an observer for the target page.
const finalLoadComplete = BrowserTestUtils.browserLoaded(
browser,
@@ -92,6 +128,8 @@ add_task(async function checkLearnMoreLink() {
Services.prefs.setIntPref("security.tls.version.min", 3);
Services.prefs.setIntPref("security.tls.version.max", 4);
+ await resetTelemetry();
+
let browser;
let pageLoaded;
await BrowserTestUtils.openNewForegroundTab(
@@ -107,6 +145,8 @@ add_task(async function checkLearnMoreLink() {
info("Loading and waiting for the net error");
await pageLoaded;
+ await checkTelemetry("SSL_ERROR_PROTOCOL_VERSION_ALERT");
+
const baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
await SpecialPowers.spawn(browser, [baseURL], function (_baseURL) {
@@ -206,6 +246,8 @@ add_task(async function checkDomainCorrection() {
// Test that ciphersuites that use 3DES (namely, TLS_RSA_WITH_3DES_EDE_CBC_SHA)
// can only be enabled when deprecated TLS is enabled.
add_task(async function onlyAllow3DESWithDeprecatedTLS() {
+ await resetTelemetry();
+
// By default, connecting to a server that only uses 3DES should fail.
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
@@ -215,6 +257,8 @@ add_task(async function onlyAllow3DESWithDeprecatedTLS() {
}
);
+ await checkTelemetry("SSL_ERROR_NO_CYPHER_OVERLAP");
+
// Enabling deprecated TLS should also enable 3DES.
Services.prefs.setBoolPref("security.tls.version.enable-deprecated", true);
await BrowserTestUtils.withNewTab(
diff --git a/browser/base/content/test/contextMenu/browser_bug1798178.js b/browser/base/content/test/contextMenu/browser_bug1798178.js
index 529665a6f9..de8bab1820 100644
--- a/browser/base/content/test/contextMenu/browser_bug1798178.js
+++ b/browser/base/content/test/contextMenu/browser_bug1798178.js
@@ -15,7 +15,7 @@ const TEST_URL =
) + "file_bug1798178.html";
let MockFilePicker = SpecialPowers.MockFilePicker;
-MockFilePicker.init(window);
+MockFilePicker.init(window.browsingContext);
function createTemporarySaveDirectory() {
let saveDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
diff --git a/browser/base/content/test/contextMenu/browser_contextmenu_save_blocked.js b/browser/base/content/test/contextMenu/browser_contextmenu_save_blocked.js
index 5064d9a316..062fbeac08 100644
--- a/browser/base/content/test/contextMenu/browser_contextmenu_save_blocked.js
+++ b/browser/base/content/test/contextMenu/browser_contextmenu_save_blocked.js
@@ -4,7 +4,7 @@
"use strict";
var MockFilePicker = SpecialPowers.MockFilePicker;
-MockFilePicker.init(window);
+MockFilePicker.init(window.browsingContext);
function mockPromptService() {
let { prompt } = Services;
diff --git a/browser/base/content/test/forms/browser.toml b/browser/base/content/test/forms/browser.toml
index 33d73ba8bf..95b666369e 100644
--- a/browser/base/content/test/forms/browser.toml
+++ b/browser/base/content/test/forms/browser.toml
@@ -1,5 +1,5 @@
[DEFAULT]
-prefs = ["gfx.font_loader.delay=0", "dom.select.showPicker.enabled=true"]
+prefs = ["gfx.font_loader.delay=0", "dom.select.showPicker.enabled=true", "font.minimum-size.x-western=9"]
support-files = ["head.js"]
["browser_selectpopup.js"]
@@ -18,6 +18,8 @@ skip-if = ["os == 'linux'"] # Bug 1329991 - test fails intermittently on Linux b
["browser_selectpopup_large.js"]
+["browser_selectpopup_minFontSize.js"]
+
["browser_selectpopup_searchfocus.js"]
fail-if = ["a11y_checks"] # Bug 1854233 input may not be labeled
diff --git a/browser/base/content/test/forms/browser_selectpopup_minFontSize.js b/browser/base/content/test/forms/browser_selectpopup_minFontSize.js
new file mode 100644
index 0000000000..d240c2d2d0
--- /dev/null
+++ b/browser/base/content/test/forms/browser_selectpopup_minFontSize.js
@@ -0,0 +1,38 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// NOTE that this test expects "font.minimum-size.x-western=9" to be set
+// in the manifest.
+
+const PAGE = `
+<!doctype html>
+<body lang="en-US">
+<select>
+ <option style="font-size:24px">A</option>
+ <option style="font-size:6px">BCD</option>
+</select>
+`;
+
+add_task(async function () {
+ const url = "data:text/html," + encodeURI(PAGE);
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url,
+ },
+ async function (browser) {
+ let popup = await openSelectPopup("click");
+ let menuitems = popup.querySelectorAll("menuitem");
+ is(
+ getComputedStyle(menuitems[0]).fontSize,
+ "24px",
+ "font-size should be honored"
+ );
+ is(
+ getComputedStyle(menuitems[1]).fontSize,
+ "9px",
+ "minimum font-size should be honored"
+ );
+ }
+ );
+});
diff --git a/browser/base/content/test/general/browser_beforeunload_duplicate_dialogs.js b/browser/base/content/test/general/browser_beforeunload_duplicate_dialogs.js
index 8a77f01ce4..8eb07a863a 100644
--- a/browser/base/content/test/general/browser_beforeunload_duplicate_dialogs.js
+++ b/browser/base/content/test/general/browser_beforeunload_duplicate_dialogs.js
@@ -1,36 +1,11 @@
const TEST_PAGE =
"http://mochi.test:8888/browser/browser/base/content/test/general/file_double_close_tab.html";
-const CONTENT_PROMPT_SUBDIALOG = Services.prefs.getBoolPref(
- "prompts.contentPromptSubDialog",
- false
-);
-
var expectingDialog = false;
var wantToClose = true;
var resolveDialogPromise;
-function onTabModalDialogLoaded(node) {
- ok(
- !CONTENT_PROMPT_SUBDIALOG,
- "Should not be using content prompt subdialogs."
- );
- ok(expectingDialog, "Should be expecting this dialog.");
- expectingDialog = false;
- if (wantToClose) {
- // This accepts the dialog, closing it
- node.querySelector(".tabmodalprompt-button0").click();
- } else {
- // This keeps the page open
- node.querySelector(".tabmodalprompt-button1").click();
- }
- if (resolveDialogPromise) {
- resolveDialogPromise();
- }
-}
-
function onCommonDialogLoaded(promptWindow) {
- ok(CONTENT_PROMPT_SUBDIALOG, "Should be using content prompt subdialogs.");
ok(expectingDialog, "Should be expecting this dialog.");
expectingDialog = false;
let dialog = promptWindow.Dialog;
@@ -51,11 +26,9 @@ SpecialPowers.pushPrefEnv({
});
// Listen for the dialog being created
-Services.obs.addObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded");
Services.obs.addObserver(onCommonDialogLoaded, "common-dialog-loaded");
registerCleanupFunction(() => {
Services.prefs.clearUserPref("browser.tabs.warnOnClose");
- Services.obs.removeObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded");
Services.obs.removeObserver(onCommonDialogLoaded, "common-dialog-loaded");
});
diff --git a/browser/base/content/test/general/browser_bug676619.js b/browser/base/content/test/general/browser_bug676619.js
index 24d8d88447..80bbce8cb0 100644
--- a/browser/base/content/test/general/browser_bug676619.js
+++ b/browser/base/content/test/general/browser_bug676619.js
@@ -1,5 +1,5 @@
var MockFilePicker = SpecialPowers.MockFilePicker;
-MockFilePicker.init(window);
+MockFilePicker.init(window.browsingContext);
function waitForNewWindow() {
return new Promise(resolve => {
diff --git a/browser/base/content/test/general/browser_double_close_tab.js b/browser/base/content/test/general/browser_double_close_tab.js
index 554aeb8077..f5f2f1b6c7 100644
--- a/browser/base/content/test/general/browser_double_close_tab.js
+++ b/browser/base/content/test/general/browser_double_close_tab.js
@@ -4,24 +4,15 @@ const TEST_PAGE =
"http://mochi.test:8888/browser/browser/base/content/test/general/file_double_close_tab.html";
var testTab;
-const CONTENT_PROMPT_SUBDIALOG = Services.prefs.getBoolPref(
- "prompts.contentPromptSubDialog",
- false
-);
-
function waitForDialog(callback) {
function onDialogLoaded(nodeOrDialogWindow) {
- let node = CONTENT_PROMPT_SUBDIALOG
- ? nodeOrDialogWindow.document.querySelector("dialog")
- : nodeOrDialogWindow;
- Services.obs.removeObserver(onDialogLoaded, "tabmodal-dialog-loaded");
+ let node = nodeOrDialogWindow.document.querySelector("dialog");
Services.obs.removeObserver(onDialogLoaded, "common-dialog-loaded");
// Allow dialog's onLoad call to run to completion
Promise.resolve().then(() => callback(node));
}
// Listen for the dialog being created
- Services.obs.addObserver(onDialogLoaded, "tabmodal-dialog-loaded");
Services.obs.addObserver(onDialogLoaded, "common-dialog-loaded");
}
@@ -35,9 +26,7 @@ function waitForDialogDestroyed(node, callback) {
});
observer.observe(node.parentNode, { childList: true });
- if (CONTENT_PROMPT_SUBDIALOG) {
- node.ownerGlobal.addEventListener("unload", done);
- }
+ node.ownerGlobal.addEventListener("unload", done);
let failureTimeout = setTimeout(function () {
ok(false, "Dialog should have been destroyed");
@@ -49,12 +38,8 @@ function waitForDialogDestroyed(node, callback) {
observer.disconnect();
observer = null;
- if (CONTENT_PROMPT_SUBDIALOG) {
- node.ownerGlobal.removeEventListener("unload", done);
- SimpleTest.executeSoon(callback);
- } else {
- callback();
- }
+ node.ownerGlobal.removeEventListener("unload", done);
+ SimpleTest.executeSoon(callback);
}
}
@@ -76,23 +61,12 @@ add_task(async function () {
let doCompletion = () => setTimeout(resolveOuter, 0);
info("Now checking if dialog is destroyed");
- if (CONTENT_PROMPT_SUBDIALOG) {
- ok(
- !dialogNode.ownerGlobal || dialogNode.ownerGlobal.closed,
- "onbeforeunload dialog should be gone."
- );
- if (dialogNode.ownerGlobal && !dialogNode.ownerGlobal.closed) {
- dialogNode.acceptDialog();
- }
- } else {
- ok(!dialogNode.parentNode, "onbeforeunload dialog should be gone.");
- if (dialogNode.parentNode) {
- // Failed to remove onbeforeunload dialog, so do it ourselves:
- let leaveBtn = dialogNode.querySelector(".tabmodalprompt-button0");
- waitForDialogDestroyed(dialogNode, doCompletion);
- EventUtils.synthesizeMouseAtCenter(leaveBtn, {});
- return;
- }
+ ok(
+ !dialogNode.ownerGlobal || dialogNode.ownerGlobal.closed,
+ "onbeforeunload dialog should be gone."
+ );
+ if (dialogNode.ownerGlobal && !dialogNode.ownerGlobal.closed) {
+ dialogNode.acceptDialog();
}
doCompletion();
diff --git a/browser/base/content/test/general/browser_minimize.js b/browser/base/content/test/general/browser_minimize.js
index a57fea079c..3919cd7d77 100644
--- a/browser/base/content/test/general/browser_minimize.js
+++ b/browser/base/content/test/general/browser_minimize.js
@@ -12,26 +12,57 @@ add_task(async function () {
ok(isActive(), "Docshell should be active when starting the test");
ok(!document.hidden, "Top level window should be visible");
+ // When we show or hide the window (including by minimization),
+ // there are 2 signifiers that the process is complete: the
+ // sizemodechange event, and the browsing context becoming active
+ // or inactive. There is another signifier, the
+ // occlusionstatechange event, but whether or not that event
+ // is sent is platform-dependent, so it's not very useful. The
+ // safest way to check for stable state is to build promises
+ // around sizemodechange and browsing context active and then
+ // wait for them all to complete, and that's what we do here.
info("Calling window.minimize");
let promiseSizeModeChange = BrowserTestUtils.waitForEvent(
window,
"sizemodechange"
+ ).then(
+ () => ok(true, "Got sizemodechange."),
+ () => ok(false, "Rejected sizemodechange.")
+ );
+ let promiseBrowserInactive = BrowserTestUtils.waitForCondition(
+ () => !isActive(),
+ "Docshell should be inactive."
+ ).then(
+ () => ok(true, "Got inactive."),
+ () => ok(false, "Rejected inactive.")
);
window.minimize();
- await promiseSizeModeChange;
- ok(!isActive(), "Docshell should be Inactive");
+ await Promise.all([promiseSizeModeChange, promiseBrowserInactive]);
ok(document.hidden, "Top level window should be hidden");
+ // When we restore the window from minimization, we have the
+ // same concerns as above, so prepare our promises.
info("Calling window.restore");
promiseSizeModeChange = BrowserTestUtils.waitForEvent(
window,
"sizemodechange"
+ ).then(
+ () => ok(true, "Got sizemodechange."),
+ () => ok(false, "Rejected sizemodechange.")
+ );
+ let promiseBrowserActive = BrowserTestUtils.waitForCondition(
+ () => isActive(),
+ "Docshell should be active."
+ ).then(
+ () => ok(true, "Got active."),
+ () => ok(false, "Rejected active.")
);
window.restore();
+
// On Ubuntu `window.restore` doesn't seem to work, use a timer to make the
// test fail faster and more cleanly than with a test timeout.
await Promise.race([
- promiseSizeModeChange,
+ Promise.all([promiseSizeModeChange, promiseBrowserActive]),
new Promise((resolve, reject) =>
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
setTimeout(() => {
@@ -39,11 +70,5 @@ add_task(async function () {
}, 5000)
),
]);
- // The sizemodechange event can sometimes be fired before the
- // occlusionstatechange event, especially in chaos mode.
- if (window.isFullyOccluded) {
- await BrowserTestUtils.waitForEvent(window, "occlusionstatechange");
- }
- ok(isActive(), "Docshell should be active again");
ok(!document.hidden, "Top level window should be visible");
});
diff --git a/browser/base/content/test/general/browser_save_link-perwindowpb.js b/browser/base/content/test/general/browser_save_link-perwindowpb.js
index b018212280..234813ca2c 100644
--- a/browser/base/content/test/general/browser_save_link-perwindowpb.js
+++ b/browser/base/content/test/general/browser_save_link-perwindowpb.js
@@ -2,7 +2,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
var MockFilePicker = SpecialPowers.MockFilePicker;
-MockFilePicker.init(window);
+MockFilePicker.init(window.browsingContext);
// Trigger a save of a link in public mode, then trigger an identical save
// in private mode and ensure that the second request is differentiated from
@@ -14,7 +14,7 @@ function triggerSave(aWindow, aCallback) {
let testBrowser = aWindow.gBrowser.selectedBrowser;
// This page sets a cookie if and only if a cookie does not exist yet
let testURI =
- "http://mochi.test:8888/browser/browser/base/content/test/general/bug792517-2.html";
+ "https://example.com/browser/browser/base/content/test/general/bug792517-2.html";
BrowserTestUtils.startLoadingURIString(testBrowser, testURI);
BrowserTestUtils.browserLoaded(testBrowser, false, testURI).then(() => {
waitForFocus(function () {
@@ -132,7 +132,7 @@ function test() {
info("onExamineResponse with " + channel.URI.spec);
if (
channel.URI.spec !=
- "http://mochi.test:8888/browser/browser/base/content/test/general/bug792517.sjs"
+ "https://example.com/browser/browser/base/content/test/general/bug792517.sjs"
) {
info("returning");
return;
@@ -158,7 +158,7 @@ function test() {
info("onModifyRequest with " + channel.URI.spec);
if (
channel.URI.spec !=
- "http://mochi.test:8888/browser/browser/base/content/test/general/bug792517.sjs"
+ "https://example.com/browser/browser/base/content/test/general/bug792517.sjs"
) {
return;
}
diff --git a/browser/base/content/test/general/browser_save_link_when_window_navigates.js b/browser/base/content/test/general/browser_save_link_when_window_navigates.js
index e7507fcbb0..65daef5f1b 100644
--- a/browser/base/content/test/general/browser_save_link_when_window_navigates.js
+++ b/browser/base/content/test/general/browser_save_link_when_window_navigates.js
@@ -2,7 +2,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
var MockFilePicker = SpecialPowers.MockFilePicker;
-MockFilePicker.init(window);
+MockFilePicker.init(window.browsingContext);
const SAVE_PER_SITE_PREF = "browser.download.lastDir.savePerSite";
const ALWAYS_DOWNLOAD_DIR_PREF = "browser.download.useDownloadDir";
@@ -36,7 +36,7 @@ function triggerSave(aWindow, aCallback) {
var fileName;
let testBrowser = aWindow.gBrowser.selectedBrowser;
let testURI =
- "http://mochi.test:8888/browser/browser/base/content/test/general/navigating_window_with_download.html";
+ "https://example.com/browser/browser/base/content/test/general/navigating_window_with_download.html";
// Only observe the UTC dialog if it's enabled by pref
if (Services.prefs.getBoolPref(ALWAYS_ASK_PREF)) {
diff --git a/browser/base/content/test/general/browser_save_private_link_perwindowpb.js b/browser/base/content/test/general/browser_save_private_link_perwindowpb.js
index 8ede97e640..42632bdc5a 100644
--- a/browser/base/content/test/general/browser_save_private_link_perwindowpb.js
+++ b/browser/base/content/test/general/browser_save_private_link_perwindowpb.js
@@ -43,7 +43,7 @@ function promiseImageDownloaded() {
return new Promise((resolve, reject) => {
let fileName;
let MockFilePicker = SpecialPowers.MockFilePicker;
- MockFilePicker.init(window);
+ MockFilePicker.init(window.browsingContext);
function onTransferComplete(downloadSuccess) {
ok(
diff --git a/browser/base/content/test/general/browser_save_video.js b/browser/base/content/test/general/browser_save_video.js
index 276088fbb1..e9701d7023 100644
--- a/browser/base/content/test/general/browser_save_video.js
+++ b/browser/base/content/test/general/browser_save_video.js
@@ -2,7 +2,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
var MockFilePicker = SpecialPowers.MockFilePicker;
-MockFilePicker.init(window);
+MockFilePicker.init(window.browsingContext);
/**
* TestCase for bug 564387
@@ -14,7 +14,7 @@ add_task(async function () {
let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
BrowserTestUtils.startLoadingURIString(
gBrowser,
- "http://mochi.test:8888/browser/browser/base/content/test/general/web_video.html"
+ "https://example.com/browser/browser/base/content/test/general/web_video.html"
);
await loadPromise;
diff --git a/browser/base/content/test/general/browser_save_video_frame.js b/browser/base/content/test/general/browser_save_video_frame.js
index 877c33bcd3..11fe3ac80e 100644
--- a/browser/base/content/test/general/browser_save_video_frame.js
+++ b/browser/base/content/test/general/browser_save_video_frame.js
@@ -49,7 +49,7 @@ function waitForTransferComplete() {
*/
add_task(async function () {
let MockFilePicker = SpecialPowers.MockFilePicker;
- MockFilePicker.init(window);
+ MockFilePicker.init(window.browsingContext);
// Create the folder the video will be saved into.
let destDir = createTemporarySaveDirectory();
diff --git a/browser/base/content/test/general/browser_visibleTabs_bookmarkAllPages.js b/browser/base/content/test/general/browser_visibleTabs_bookmarkAllPages.js
index 2c0002fc44..2ec3b632f2 100644
--- a/browser/base/content/test/general/browser_visibleTabs_bookmarkAllPages.js
+++ b/browser/base/content/test/general/browser_visibleTabs_bookmarkAllPages.js
@@ -15,7 +15,9 @@ function test() {
is(gBrowser.visibleTabs.length, 1, "Only one tab is visible");
- let uris = PlacesCommandHook.uniqueCurrentPages;
+ let uris = PlacesCommandHook.getUniquePages(
+ gBrowser.visibleTabs.filter(tab => !tab.pinned)
+ );
is(uris.length, 1, "Only one uri is returned");
is(
diff --git a/browser/base/content/test/general/navigating_window_with_download.html b/browser/base/content/test/general/navigating_window_with_download.html
index 6b0918941f..8649168cf5 100644
--- a/browser/base/content/test/general/navigating_window_with_download.html
+++ b/browser/base/content/test/general/navigating_window_with_download.html
@@ -2,6 +2,6 @@
<html>
<head><title>This window will navigate while you're downloading something</title></head>
<body>
- <iframe src="http://mochi.test:8888/browser/browser/base/content/test/general/unknownContentType_file.pif"></iframe>
+ <iframe src="https://example.com/browser/browser/base/content/test/general/unknownContentType_file.pif"></iframe>
</body>
</html>
diff --git a/browser/base/content/test/outOfProcess/browser_controller.js b/browser/base/content/test/outOfProcess/browser_controller.js
index f9d9ca8c93..f3c0217b90 100644
--- a/browser/base/content/test/outOfProcess/browser_controller.js
+++ b/browser/base/content/test/outOfProcess/browser_controller.js
@@ -42,8 +42,19 @@ add_task(async function test_controllers_subframes() {
gURLBar.focus();
+ let canTabMoveFocusToRootElement = !SpecialPowers.getBoolPref(
+ "dom.disable_tab_focus_to_root_element"
+ );
for (let stepNum = 0; stepNum < browsingContexts.length; stepNum++) {
- await keyAndUpdate(stepNum > 0 ? "VK_TAB" : "VK_F6", {}, 6);
+ let useTab = stepNum > 0;
+ // When canTabMoveFocusToRootElement is true, this kepress will move the
+ // focus to a root element, which will trigger an extra "select" command
+ // compare to the case when canTabMoveFocusToRootElement is false.
+ await keyAndUpdate(
+ useTab ? "VK_TAB" : "VK_F6",
+ {},
+ canTabMoveFocusToRootElement ? 6 : 4
+ );
// Since focus may be switching into a separate process here,
// need to wait for the focus to have been updated.
@@ -59,22 +70,35 @@ add_task(async function test_controllers_subframes() {
goUpdateGlobalEditMenuItems(true);
}
- await SpecialPowers.spawn(browsingContexts[stepNum], [], () => {
- // Both the tab key and document navigation with F6 will focus
- // the root of the document within the frame.
- let document = content.document;
- Assert.equal(
- document.activeElement,
- document.documentElement,
- "root focused"
+ await SpecialPowers.spawn(
+ browsingContexts[stepNum],
+ [{ canTabMoveFocusToRootElement, useTab }],
+ args => {
+ // Both the tab key and document navigation with F6 will focus
+ // the root of the document within the frame.
+ // When dom.disable_tab_focus_to_root_element is true, only F6 will do this.
+ let document = content.document;
+ let expectedElement =
+ args.canTabMoveFocusToRootElement || !args.useTab
+ ? document.documentElement
+ : document.getElementById("input");
+ Assert.equal(document.activeElement, expectedElement, "root focused");
+ }
+ );
+
+ if (canTabMoveFocusToRootElement || !useTab) {
+ // XXX Currently, Copy is always enabled when the root (not an editor element)
+ // is focused. Possibly that should only be true if a listener is present?
+ checkCommandState(
+ "step " + stepNum + " root focused",
+ false,
+ true,
+ false
);
- });
- // XXX Currently, Copy is always enabled when the root (not an editor element)
- // is focused. Possibly that should only be true if a listener is present?
- checkCommandState("step " + stepNum + " root focused", false, true, false);
- // Tab to the textbox.
- await keyAndUpdate("VK_TAB", {}, 1);
+ // Tab to the textbox.
+ await keyAndUpdate("VK_TAB", {}, 1);
+ }
if (AppConstants.platform != "macosx") {
goUpdateGlobalEditMenuItems(true);
diff --git a/browser/base/content/test/performance/browser_appmenu.js b/browser/base/content/test/performance/browser_appmenu.js
index 37e7482c51..984d2b9fd8 100644
--- a/browser/base/content/test/performance/browser_appmenu.js
+++ b/browser/base/content/test/performance/browser_appmenu.js
@@ -21,15 +21,6 @@ const EXPECTED_APPMENU_OPEN_REFLOWS = [
"openPopup/this._openPopupPromise<@resource:///modules/PanelMultiView.sys.mjs",
],
},
-
- {
- stack: [
- "_calculateMaxHeight@resource:///modules/PanelMultiView.sys.mjs",
- "handleEvent@resource:///modules/PanelMultiView.sys.mjs",
- ],
-
- maxCount: 7, // This number should only ever go down - never up.
- },
];
add_task(async function () {
diff --git a/browser/base/content/test/performance/browser_startup_content_mainthreadio.js b/browser/base/content/test/performance/browser_startup_content_mainthreadio.js
index e60b95bb3c..e267363064 100644
--- a/browser/base/content/test/performance/browser_startup_content_mainthreadio.js
+++ b/browser/base/content/test/performance/browser_startup_content_mainthreadio.js
@@ -152,6 +152,13 @@ const processes = {
condition: WIN,
stat: 1,
},
+ {
+ // We should remove this in bug 1882427
+ path: "*screenshots@mozilla.org.xpi",
+ condition: true,
+ ignoreIfUnused: true,
+ close: 1,
+ },
],
};
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 4a9276512c..3b027bc1ef 100644
--- a/browser/base/content/test/popupNotifications/browser_popupNotification_security_delay.js
+++ b/browser/base/content/test/popupNotifications/browser_popupNotification_security_delay.js
@@ -5,6 +5,8 @@
const TEST_SECURITY_DELAY = 5000;
+SimpleTest.requestCompleteLog();
+
/**
* Shows a test PopupNotification.
*/
@@ -400,3 +402,166 @@ add_task(async function test_notificationWindowMove() {
// Reset window position
window.moveTo(screenX, screenY);
});
+
+/**
+ * Tests that the security delay gets extended if a notification is shown during
+ * a full screen transition.
+ */
+add_task(async function test_notificationDuringFullScreenTransition() {
+ // Log full screen transition messages.
+ let loggingObserver = {
+ observe(subject, topic) {
+ info("Observed topic: " + topic);
+ },
+ };
+ Services.obs.addObserver(loggingObserver, "fullscreen-transition-start");
+ Services.obs.addObserver(loggingObserver, "fullscreen-transition-end");
+ // Unregister observers when the test ends:
+ registerCleanupFunction(() => {
+ Services.obs.removeObserver(loggingObserver, "fullscreen-transition-start");
+ Services.obs.removeObserver(loggingObserver, "fullscreen-transition-end");
+ });
+
+ if (Services.appinfo.OS == "Linux") {
+ ok(
+ "Skipping test on Linux because of disabled full screen transition in CI."
+ );
+ return;
+ }
+ // Bug 1882527: Intermittent failures on macOS.
+ if (Services.appinfo.OS == "Darwin") {
+ ok("Skipping test on macOS because of intermittent failures.");
+ return;
+ }
+
+ await BrowserTestUtils.withNewTab("https://example.com", async browser => {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ // Set a short security delay so we can observe it being extended.
+ ["security.notification_enable_delay", 1],
+ // Set a longer full screen exit transition so the test works on slow builds.
+ ["full-screen-api.transition-duration.leave", "1000 1000"],
+ // Waive the user activation requirement for full screen requests.
+ // The PoC this test is based on relies on spam clicking which grants
+ // user activation in the popup that requests full screen.
+ // This isn't reliable in automation.
+ ["full-screen-api.allow-trusted-requests-only", false],
+ // macOS native full screen is not affected by the full screen
+ // transition overlap. Test with the old full screen implementation.
+ ["full-screen-api.macos-native-full-screen", false],
+ ],
+ });
+
+ await ensureSecurityDelayReady();
+
+ ok(
+ !PopupNotifications.isPanelOpen,
+ "PopupNotification panel should not be open initially."
+ );
+
+ info("Open a notification.");
+ let popupShownPromise = waitForNotificationPanel();
+ showNotification();
+ await popupShownPromise;
+ ok(
+ PopupNotifications.isPanelOpen,
+ "PopupNotification should be open after show call."
+ );
+
+ let notification = PopupNotifications.getNotification("foo", browser);
+ is(notification?.id, "foo", "There should be a notification with id foo");
+
+ info(
+ "Open a new tab via window.open, enter full screen and remove the tab."
+ );
+
+ // There are two transitions, one for full screen entry and one for full screen exit.
+ let transitionStartCount = 0;
+ let transitionEndCount = 0;
+ let promiseFullScreenTransitionStart = TestUtils.topicObserved(
+ "fullscreen-transition-start",
+ () => {
+ transitionStartCount++;
+ return transitionStartCount == 2;
+ }
+ );
+ let promiseFullScreenTransitionEnd = TestUtils.topicObserved(
+ "fullscreen-transition-end",
+ () => {
+ transitionEndCount++;
+ return transitionEndCount == 2;
+ }
+ );
+ let notificationShownPromise = waitForNotificationPanel();
+
+ await SpecialPowers.spawn(browser, [], () => {
+ // Use eval to execute in the privilege context of the website.
+ content.eval(`
+ let button = document.createElement("button");
+ button.id = "triggerBtn";
+ button.innerText = "Open Popup";
+ button.addEventListener("click", () => {
+ let popup = window.open("about:blank");
+ popup.document.write(
+ "<script>setTimeout(() => document.documentElement.requestFullscreen(), 500)</script>"
+ );
+ popup.document.write(
+ "<script>setTimeout(() => window.close(), 1500)</script>"
+ );
+ });
+ // Insert button at the top so the synthesized click works. Otherwise
+ // the button may be outside of the viewport.
+ document.body.prepend(button);
+ `);
+ });
+
+ let timeClick = performance.now();
+ await BrowserTestUtils.synthesizeMouseAtCenter("#triggerBtn", {}, browser);
+
+ info("Wait for the exit transition to start. It's the second transition.");
+ await promiseFullScreenTransitionStart;
+ info("Full screen transition start");
+ ok(true, "Full screen transition started");
+ ok(
+ window.isInFullScreenTransition,
+ "Full screen transition is still running."
+ );
+
+ info(
+ "Wait for notification to re-show on tab switch, after the popup has been closed"
+ );
+ await notificationShownPromise;
+ ok(
+ window.isInFullScreenTransition,
+ "Full screen transition is still running."
+ );
+ info(
+ "about to trigger notification. time between btn click and notification show: " +
+ (performance.now() - timeClick)
+ );
+
+ info(
+ "Trigger main action via button click during the extended 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."
+ );
+
+ info("Wait for full screen transition end.");
+ await promiseFullScreenTransitionEnd;
+ info("Full screen transition end");
+ });
+});
diff --git a/browser/base/content/test/popups/browser_popup_blocker.js b/browser/base/content/test/popups/browser_popup_blocker.js
index bfda12331e..d2e182b366 100644
--- a/browser/base/content/test/popups/browser_popup_blocker.js
+++ b/browser/base/content/test/popups/browser_popup_blocker.js
@@ -34,9 +34,18 @@ add_task(async function test_maximum_reported_blocks() {
);
// Wait for the popup-blocked notification.
- let notification = await TestUtils.waitForCondition(() =>
- gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked")
- );
+ let notification = await TestUtils.waitForCondition(() => {
+ let tempNotif = gBrowser
+ .getNotificationBox()
+ .getNotificationWithValue("popup-blocked");
+
+ // The textContent in the notification object is contains
+ // blank spaces as placeholder if there is no value in it
+ if (tempNotif?.messageText.textContent.trim().length) {
+ return tempNotif;
+ }
+ return false;
+ });
// Slightly hacky way to ensure we show the correct message in this case.
ok(
diff --git a/browser/base/content/test/privateBrowsing/browser_private_browsing_simplified_ui.js b/browser/base/content/test/privateBrowsing/browser_private_browsing_simplified_ui.js
index 162bf7ab5a..c52ed4187a 100644
--- a/browser/base/content/test/privateBrowsing/browser_private_browsing_simplified_ui.js
+++ b/browser/base/content/test/privateBrowsing/browser_private_browsing_simplified_ui.js
@@ -30,19 +30,4 @@ add_task(async function check_for_simplified_pbm_ui() {
);
await BrowserTestUtils.closeWindow(pbmWindow);
- await SpecialPowers.pushPrefEnv({
- set: [["browser.toolbars.bookmarks.showInPrivateBrowsing", true]],
- });
- pbmWindow = await BrowserTestUtils.openNewBrowserWindow({
- private: true,
- });
- bookmarksBar = pbmWindow.document.getElementById("PersonalToolbar");
- console.info(bookmarksBar.getAttribute("collapsed"));
- Assert.equal(
- bookmarksBar.getAttribute("collapsed").toString(),
- "false",
- "Bookmarks bar is visible in PBM window when showInPrivateBrowsing pref is true"
- );
-
- await BrowserTestUtils.closeWindow(pbmWindow);
});
diff --git a/browser/base/content/test/protectionsUI/browser.toml b/browser/base/content/test/protectionsUI/browser.toml
index 10611cbe8c..f3c64eb67f 100644
--- a/browser/base/content/test/protectionsUI/browser.toml
+++ b/browser/base/content/test/protectionsUI/browser.toml
@@ -59,13 +59,6 @@ https_first_disabled = true
["browser_protectionsUI_pbmode_exceptions.js"]
https_first_disabled = true
-["browser_protectionsUI_report_breakage.js"]
-https_first_disabled = true
-skip-if = [
- "debug", # Bug 1546797
- "asan",
-]
-
["browser_protectionsUI_shield_visibility.js"]
support-files = [
"sandboxed.html",
diff --git a/browser/base/content/test/protectionsUI/browser_protectionsUI.js b/browser/base/content/test/protectionsUI/browser_protectionsUI.js
index 98698e087e..5dc6acebf7 100644
--- a/browser/base/content/test/protectionsUI/browser_protectionsUI.js
+++ b/browser/base/content/test/protectionsUI/browser_protectionsUI.js
@@ -73,85 +73,16 @@ add_task(async function testToggleSwitch() {
console.log(buttonEvents);
is(buttonEvents.length, 1, "recorded telemetry for opening the popup");
- // Check the visibility of the "Site not working?" link.
- ok(
- BrowserTestUtils.isVisible(
- gProtectionsHandler._protectionsPopupTPSwitchBreakageLink
- ),
- "The 'Site not working?' link should be visible."
- );
-
- // The 'Site Fixed?' link should be hidden.
- ok(
- BrowserTestUtils.isHidden(
- gProtectionsHandler._protectionsPopupTPSwitchBreakageFixedLink
- ),
- "The 'Site Fixed?' link should be hidden."
- );
-
- // Navigate through the 'Site Not Working?' flow and back to the main view,
- // checking for telemetry on the way.
- let siteNotWorkingView = document.getElementById(
- "protections-popup-siteNotWorkingView"
- );
- let viewShown = BrowserTestUtils.waitForEvent(
- siteNotWorkingView,
- "ViewShown"
- );
- gProtectionsHandler._protectionsPopupTPSwitchBreakageLink.click();
- await viewShown;
-
- checkClickTelemetry("sitenotworking_link");
-
- let sendReportButton = document.getElementById(
- "protections-popup-siteNotWorkingView-sendReport"
- );
- let sendReportView = document.getElementById(
- "protections-popup-sendReportView"
- );
- viewShown = BrowserTestUtils.waitForEvent(sendReportView, "ViewShown");
- sendReportButton.click();
- await viewShown;
-
- checkClickTelemetry("send_report_link");
-
- viewShown = BrowserTestUtils.waitForEvent(siteNotWorkingView, "ViewShown");
- sendReportView.querySelector(".subviewbutton-back").click();
- await viewShown;
-
- let mainView = document.getElementById("protections-popup-mainView");
-
- viewShown = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
- siteNotWorkingView.querySelector(".subviewbutton-back").click();
- await viewShown;
+ let browserLoadedPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
- ok(
- gProtectionsHandler._protectionsPopupTPSwitch.hasAttribute("pressed"),
- "TP Switch should be on"
- );
let popuphiddenPromise = BrowserTestUtils.waitForEvent(
gProtectionsHandler._protectionsPopup,
"popuphidden"
);
- let browserLoadedPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
- await clickToggle(gProtectionsHandler._protectionsPopupTPSwitch);
-
- // The 'Site not working?' link should be hidden after clicking the TP switch.
- ok(
- BrowserTestUtils.isHidden(
- gProtectionsHandler._protectionsPopupTPSwitchBreakageLink
- ),
- "The 'Site not working?' link should be hidden after TP switch turns to off."
- );
- // Same for the 'Site Fixed?' link
- ok(
- BrowserTestUtils.isHidden(
- gProtectionsHandler._protectionsPopupTPSwitchBreakageFixedLink
- ),
- "The 'Site Fixed?' link should be hidden."
- );
+ await clickToggle(gProtectionsHandler._protectionsPopupTPSwitch);
await popuphiddenPromise;
+
checkClickTelemetry("etp_toggle_off");
// We need to wait toast's popup shown and popup hidden events. It won't fire
@@ -164,41 +95,13 @@ add_task(async function testToggleSwitch() {
// Wait until the ETP state confirmation toast is shown and hides itself.
await toastShown;
+ // Re-open the protections panel and confirm that the toggle is off, then toggle it back on.
await openProtectionsPanel();
ok(
!gProtectionsHandler._protectionsPopupTPSwitch.hasAttribute("pressed"),
"TP Switch should be off"
);
- // The 'Site not working?' link should be hidden if the TP is off.
- ok(
- BrowserTestUtils.isHidden(
- gProtectionsHandler._protectionsPopupTPSwitchBreakageLink
- ),
- "The 'Site not working?' link should be hidden if TP is off."
- );
-
- // The 'Site Fixed?' link should be shown if TP is off.
- ok(
- BrowserTestUtils.isVisible(
- gProtectionsHandler._protectionsPopupTPSwitchBreakageFixedLink
- ),
- "The 'Site Fixed?' link should be visible."
- );
-
- // Check telemetry for 'Site Fixed?' link.
- viewShown = BrowserTestUtils.waitForEvent(sendReportView, "ViewShown");
- gProtectionsHandler._protectionsPopupTPSwitchBreakageFixedLink.click();
- await viewShown;
-
- checkClickTelemetry("sitenotworking_link", "sitefixed");
-
- viewShown = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
- sendReportView.querySelector(".subviewbutton-back").click();
- await viewShown;
-
- // Click the TP switch again and check the visibility of the 'Site not
- // Working?'. It should be hidden after toggling the TP switch.
browserLoadedPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
popuphiddenPromise = BrowserTestUtils.waitForEvent(
@@ -208,20 +111,6 @@ add_task(async function testToggleSwitch() {
await clickToggle(gProtectionsHandler._protectionsPopupTPSwitch);
- ok(
- BrowserTestUtils.isHidden(
- gProtectionsHandler._protectionsPopupTPSwitchBreakageLink
- ),
- `The 'Site not working?' link should be still hidden after toggling TP
- switch to on from off.`
- );
- ok(
- BrowserTestUtils.isHidden(
- gProtectionsHandler._protectionsPopupTPSwitchBreakageFixedLink
- ),
- "The 'Site Fixed?' link should be hidden."
- );
-
// Wait for the protections panel to be hidden as the result of the ETP toggle
// on action.
await popuphiddenPromise;
diff --git a/browser/base/content/test/protectionsUI/browser_protectionsUI_report_breakage.js b/browser/base/content/test/protectionsUI/browser_protectionsUI_report_breakage.js
deleted file mode 100644
index 2ae0d5c9d9..0000000000
--- a/browser/base/content/test/protectionsUI/browser_protectionsUI_report_breakage.js
+++ /dev/null
@@ -1,415 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-const TRACKING_PAGE =
- // eslint-disable-next-line @microsoft/sdl/no-insecure-url
- "http://tracking.example.org/browser/browser/base/content/test/protectionsUI/trackingPage.html";
-const BENIGN_PAGE =
- // eslint-disable-next-line @microsoft/sdl/no-insecure-url
- "http://tracking.example.org/browser/browser/base/content/test/protectionsUI/benignPage.html";
-const COOKIE_PAGE =
- // eslint-disable-next-line @microsoft/sdl/no-insecure-url
- "http://not-tracking.example.com/browser/browser/base/content/test/protectionsUI/cookiePage.html";
-
-const CM_PREF = "privacy.trackingprotection.cryptomining.enabled";
-const FP_PREF = "privacy.trackingprotection.fingerprinting.enabled";
-const TP_PREF = "privacy.trackingprotection.enabled";
-const CB_PREF = "network.cookie.cookieBehavior";
-const GPC_PREF = "privacy.globalprivacycontrol.enabled";
-
-const PREF_REPORT_BREAKAGE_URL = "browser.contentblocking.reportBreakage.url";
-
-let { HttpServer } = ChromeUtils.importESModule(
- "resource://testing-common/httpd.sys.mjs"
-);
-let { CommonUtils } = ChromeUtils.importESModule(
- "resource://services-common/utils.sys.mjs"
-);
-let { Preferences } = ChromeUtils.importESModule(
- "resource://gre/modules/Preferences.sys.mjs"
-);
-
-add_setup(async function () {
- await UrlClassifierTestUtils.addTestTrackers();
-
- // Disable Report Broken Site, as it hides "Site not working?" when enabled.
- await SpecialPowers.pushPrefEnv({
- set: [["ui.new-webcompat-reporter.enabled", false]],
- });
-
- registerCleanupFunction(() => {
- // Clear prefs that are touched in this test again for sanity.
- Services.prefs.clearUserPref(TP_PREF);
- Services.prefs.clearUserPref(CB_PREF);
- Services.prefs.clearUserPref(FP_PREF);
- Services.prefs.clearUserPref(CM_PREF);
- Services.prefs.clearUserPref(GPC_PREF);
- Services.prefs.clearUserPref(PREF_REPORT_BREAKAGE_URL);
-
- UrlClassifierTestUtils.cleanupTestTrackers();
- });
-
- await SpecialPowers.pushPrefEnv({
- set: [
- [
- "urlclassifier.features.fingerprinting.blacklistHosts",
- "fingerprinting.example.com",
- ],
- [
- "urlclassifier.features.fingerprinting.annotate.blacklistHosts",
- "fingerprinting.example.com",
- ],
- ["privacy.trackingprotection.cryptomining.enabled", true],
- [
- "urlclassifier.features.cryptomining.blacklistHosts",
- "cryptomining.example.com",
- ],
- [
- "urlclassifier.features.cryptomining.annotate.blacklistHosts",
- "cryptomining.example.com",
- ],
- ["privacy.globalprivacycontrol.enabled", true],
- ],
- });
-});
-
-add_task(async function testReportBreakageCancel() {
- Services.prefs.setBoolPref(TP_PREF, true);
-
- await BrowserTestUtils.withNewTab(TRACKING_PAGE, async function () {
- await openProtectionsPanel();
- await TestUtils.waitForCondition(() =>
- gProtectionsHandler._protectionsPopup.hasAttribute("blocking")
- );
-
- let siteNotWorkingButton = document.getElementById(
- "protections-popup-tp-switch-breakage-link"
- );
- ok(
- BrowserTestUtils.isVisible(siteNotWorkingButton),
- "site not working button is visible"
- );
- let siteNotWorkingView = document.getElementById(
- "protections-popup-siteNotWorkingView"
- );
- let viewShown = BrowserTestUtils.waitForEvent(
- siteNotWorkingView,
- "ViewShown"
- );
- siteNotWorkingButton.click();
- await viewShown;
-
- let sendReportButton = document.getElementById(
- "protections-popup-siteNotWorkingView-sendReport"
- );
- let sendReportView = document.getElementById(
- "protections-popup-sendReportView"
- );
- viewShown = BrowserTestUtils.waitForEvent(sendReportView, "ViewShown");
- sendReportButton.click();
- await viewShown;
-
- ok(true, "Report breakage view was shown");
-
- viewShown = BrowserTestUtils.waitForEvent(siteNotWorkingView, "ViewShown");
- let cancelButton = document.getElementById(
- "protections-popup-sendReportView-cancel"
- );
- cancelButton.click();
- await viewShown;
-
- ok(true, "Main view was shown");
- });
-
- Services.prefs.clearUserPref(TP_PREF);
-});
-
-add_task(async function testReportBreakageSiteException() {
- Services.prefs.setBoolPref(TP_PREF, true);
-
- let url = TRACKING_PAGE + "?a=b&1=abc&unicode=🦊";
-
- await BrowserTestUtils.withNewTab(url, async browser => {
- let loaded = BrowserTestUtils.browserLoaded(browser, false);
- gProtectionsHandler.disableForCurrentPage();
- await loaded;
-
- await openProtectionsPanel();
-
- let siteFixedButton = document.getElementById(
- "protections-popup-tp-switch-breakage-fixed-link"
- );
- ok(
- BrowserTestUtils.isVisible(siteFixedButton),
- "site fixed button is visible"
- );
- let sendReportView = document.getElementById(
- "protections-popup-sendReportView"
- );
- let viewShown = BrowserTestUtils.waitForEvent(sendReportView, "ViewShown");
- siteFixedButton.click();
- await viewShown;
-
- ok(true, "Report breakage view was shown");
-
- await testReportBreakageSubmit(
- TRACKING_PAGE,
- "trackingprotection",
- false,
- true
- );
-
- // Pass false for shouldReload - there's no need since the tab is going away.
- gProtectionsHandler.enableForCurrentPage(false);
- });
-
- Services.prefs.clearUserPref(TP_PREF);
-});
-
-add_task(async function testNoTracking() {
- await BrowserTestUtils.withNewTab(BENIGN_PAGE, async function () {
- await openProtectionsPanel();
-
- let siteNotWorkingButton = document.getElementById(
- "protections-popup-tp-switch-breakage-link"
- );
- ok(
- BrowserTestUtils.isHidden(siteNotWorkingButton),
- "site not working button is not visible"
- );
- });
-});
-
-add_task(async function testReportBreakageError() {
- Services.prefs.setBoolPref(TP_PREF, true);
- // Make sure that we correctly strip the query.
- let url = TRACKING_PAGE + "?a=b&1=abc&unicode=🦊";
- await BrowserTestUtils.withNewTab(url, async function () {
- await openAndTestReportBreakage(TRACKING_PAGE, "trackingprotection", true);
- });
-
- Services.prefs.clearUserPref(TP_PREF);
-});
-
-add_task(async function testTP() {
- Services.prefs.setBoolPref(TP_PREF, true);
- // Make sure that we correctly strip the query.
- let url = TRACKING_PAGE + "?a=b&1=abc&unicode=🦊";
- await BrowserTestUtils.withNewTab(url, async function () {
- await openAndTestReportBreakage(TRACKING_PAGE, "trackingprotection");
- });
-
- Services.prefs.clearUserPref(TP_PREF);
-});
-
-add_task(async function testCR() {
- Services.prefs.setIntPref(
- CB_PREF,
- Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER
- );
- // Make sure that we correctly strip the query.
- let url = COOKIE_PAGE + "?a=b&1=abc&unicode=🦊";
- await BrowserTestUtils.withNewTab(url, async function () {
- await openAndTestReportBreakage(COOKIE_PAGE, "cookierestrictions");
- });
-
- Services.prefs.clearUserPref(CB_PREF);
-});
-
-add_task(async function testFP() {
- Services.prefs.setIntPref(CB_PREF, Ci.nsICookieService.BEHAVIOR_ACCEPT);
- Services.prefs.setBoolPref(FP_PREF, true);
- // Make sure that we correctly strip the query.
- let url = TRACKING_PAGE + "?a=b&1=abc&unicode=🦊";
- await BrowserTestUtils.withNewTab(url, async function (browser) {
- let promise = waitForContentBlockingEvent();
- await SpecialPowers.spawn(browser, [], function () {
- content.postMessage("fingerprinting", "*");
- });
- await promise;
-
- await openAndTestReportBreakage(TRACKING_PAGE, "fingerprinting", true);
- });
-
- Services.prefs.clearUserPref(FP_PREF);
- Services.prefs.clearUserPref(CB_PREF);
-});
-
-add_task(async function testCM() {
- Services.prefs.setIntPref(CB_PREF, Ci.nsICookieService.BEHAVIOR_ACCEPT);
- Services.prefs.setBoolPref(CM_PREF, true);
- // Make sure that we correctly strip the query.
- let url = TRACKING_PAGE + "?a=b&1=abc&unicode=🦊";
- await BrowserTestUtils.withNewTab(url, async function (browser) {
- let promise = waitForContentBlockingEvent();
- await SpecialPowers.spawn(browser, [], function () {
- content.postMessage("cryptomining", "*");
- });
- await promise;
-
- await openAndTestReportBreakage(TRACKING_PAGE, "cryptomining", true);
- });
-
- Services.prefs.clearUserPref(CM_PREF);
- Services.prefs.clearUserPref(CB_PREF);
-});
-
-async function openAndTestReportBreakage(url, tags, error = false) {
- await openProtectionsPanel();
-
- let siteNotWorkingButton = document.getElementById(
- "protections-popup-tp-switch-breakage-link"
- );
- ok(
- BrowserTestUtils.isVisible(siteNotWorkingButton),
- "site not working button is visible"
- );
- let siteNotWorkingView = document.getElementById(
- "protections-popup-siteNotWorkingView"
- );
- let viewShown = BrowserTestUtils.waitForEvent(
- siteNotWorkingView,
- "ViewShown"
- );
- siteNotWorkingButton.click();
- await viewShown;
-
- let sendReportButton = document.getElementById(
- "protections-popup-siteNotWorkingView-sendReport"
- );
- let sendReportView = document.getElementById(
- "protections-popup-sendReportView"
- );
- viewShown = BrowserTestUtils.waitForEvent(sendReportView, "ViewShown");
- sendReportButton.click();
- await viewShown;
-
- ok(true, "Report breakage view was shown");
-
- await testReportBreakageSubmit(url, tags, error, false);
-}
-
-// This function assumes that the breakage report view is ready.
-async function testReportBreakageSubmit(url, tags, error, hasException) {
- // Setup a mock server for receiving breakage reports.
- let server = new HttpServer();
- server.start(-1);
- let i = server.identity;
- let path =
- i.primaryScheme + "://" + i.primaryHost + ":" + i.primaryPort + "/";
-
- Services.prefs.setStringPref(PREF_REPORT_BREAKAGE_URL, path);
-
- let comments = document.getElementById(
- "protections-popup-sendReportView-collection-comments"
- );
- is(comments.value, "", "Comments textarea should initially be empty");
-
- let submitButton = document.getElementById(
- "protections-popup-sendReportView-submit"
- );
- let reportURL = document.getElementById(
- "protections-popup-sendReportView-collection-url"
- ).value;
-
- is(reportURL, url, "Shows the correct URL in the report UI.");
-
- // Make sure that sending the report closes the identity popup.
- let popuphidden = BrowserTestUtils.waitForEvent(
- gProtectionsHandler._protectionsPopup,
- "popuphidden"
- );
-
- // Check that we're receiving a good report.
- await new Promise(resolve => {
- server.registerPathHandler("/", async (request, response) => {
- is(request.method, "POST", "request was a post");
-
- // Extract and "parse" the form data in the request body.
- let body = CommonUtils.readBytesFromInputStream(request.bodyInputStream);
- let boundary = request
- .getHeader("Content-Type")
- .match(/boundary=-+([^-]*)/i)[1];
- let regex = new RegExp("-+" + boundary + "-*\\s+");
- let sections = body.split(regex);
-
- let prefs = [
- "privacy.trackingprotection.enabled",
- "privacy.trackingprotection.pbmode.enabled",
- "urlclassifier.trackingTable",
- "network.http.referer.defaultPolicy",
- "network.http.referer.defaultPolicy.pbmode",
- "network.cookie.cookieBehavior",
- "privacy.annotate_channels.strict_list.enabled",
- "privacy.restrict3rdpartystorage.expiration",
- "privacy.trackingprotection.fingerprinting.enabled",
- "privacy.trackingprotection.cryptomining.enabled",
- "privacy.globalprivacycontrol.enabled",
- ];
- let prefsBody = "";
-
- for (let pref of prefs) {
- prefsBody += `${pref}: ${Preferences.get(pref)}\r\n`;
- }
-
- Assert.deepEqual(
- sections,
- [
- "",
- `Content-Disposition: form-data; name=\"title\"\r\n\r\n${
- Services.io.newURI(reportURL).host
- }\r\n`,
- 'Content-Disposition: form-data; name="body"\r\n\r\n' +
- `Full URL: ${reportURL + "?"}\r\n` +
- `userAgent: ${navigator.userAgent}\r\n\r\n` +
- "**Preferences**\r\n" +
- `${prefsBody}\r\n` +
- `hasException: ${hasException}\r\n\r\n` +
- "**Comments**\r\n" +
- "This is a comment\r\n",
- 'Content-Disposition: form-data; name="labels"\r\n\r\n' +
- `${hasException ? "" : tags}\r\n`,
- "",
- ],
- "Should send the correct form data"
- );
-
- if (error) {
- response.setStatusLine(request.httpVersion, 500, "Request failed");
- } else {
- response.setStatusLine(request.httpVersion, 201, "Entry created");
- }
-
- resolve();
- });
-
- comments.value = "This is a comment";
- submitButton.click();
- });
-
- let errorMessage = document.getElementById(
- "protections-popup-sendReportView-report-error"
- );
- if (error) {
- await TestUtils.waitForCondition(() =>
- BrowserTestUtils.isVisible(errorMessage)
- );
- is(
- comments.value,
- "This is a comment",
- "Comment not cleared in case of an error"
- );
- gProtectionsHandler._protectionsPopup.hidePopup();
- } else {
- ok(BrowserTestUtils.isHidden(errorMessage), "Error message not shown");
- }
-
- await popuphidden;
-
- // Stop the server.
- await new Promise(r => server.stop(r));
-
- Services.prefs.clearUserPref(PREF_REPORT_BREAKAGE_URL);
-}
diff --git a/browser/base/content/test/sanitize/browser.toml b/browser/base/content/test/sanitize/browser.toml
index 814dc54c3d..3c53723833 100644
--- a/browser/base/content/test/sanitize/browser.toml
+++ b/browser/base/content/test/sanitize/browser.toml
@@ -36,4 +36,6 @@ support-files = [
["browser_sanitizeDialog_v2.js"]
+["browser_sanitizeDialog_v2_dataSizes.js"]
+
["browser_sanitizeOnShutdown_migration.js"]
diff --git a/browser/base/content/test/sanitize/browser_sanitize-timespans.js b/browser/base/content/test/sanitize/browser_sanitize-timespans.js
index 30ccb90666..f9be12775b 100644
--- a/browser/base/content/test/sanitize/browser_sanitize-timespans.js
+++ b/browser/base/content/test/sanitize/browser_sanitize-timespans.js
@@ -8,9 +8,6 @@ const { PlacesTestUtils } = ChromeUtils.importESModule(
var now_mSec = Date.now();
var now_uSec = now_mSec * 1000;
-const kMsecPerMin = 60 * 1000;
-const kUsecPerMin = 60 * 1000000;
-
function promiseFormHistoryRemoved() {
return new Promise(resolve => {
Services.obs.addObserver(function onfh() {
diff --git a/browser/base/content/test/sanitize/browser_sanitizeDialog.js b/browser/base/content/test/sanitize/browser_sanitizeDialog.js
index 2df7d83c6e..a1e8a5dc85 100644
--- a/browser/base/content/test/sanitize/browser_sanitizeDialog.js
+++ b/browser/base/content/test/sanitize/browser_sanitizeDialog.js
@@ -22,9 +22,6 @@ ChromeUtils.defineESModuleGetters(this, {
Timer: "resource://gre/modules/Timer.sys.mjs",
});
-const kMsecPerMin = 60 * 1000;
-const kUsecPerMin = 60 * 1000000;
-
/**
* Ensures that the specified URIs are either cleared or not.
*
@@ -694,10 +691,6 @@ DialogHelper.prototype = {
},
};
-function promiseSanitizationComplete() {
- return TestUtils.topicObserved("sanitizer-sanitization-complete");
-}
-
/**
* Adds a download to history.
*
@@ -752,21 +745,6 @@ async function formNameExists(name) {
}
/**
- * Removes all history visits, downloads, and form entries.
- */
-async function blankSlate() {
- let publicList = await Downloads.getList(Downloads.PUBLIC);
- let downloads = await publicList.getAll();
- for (let download of downloads) {
- await publicList.remove(download);
- await download.finalize(true);
- }
-
- await FormHistory.update({ op: "remove" });
- await PlacesUtils.history.clear();
-}
-
-/**
* Ensures that the given pref is the expected value.
*
* @param aPrefName
diff --git a/browser/base/content/test/sanitize/browser_sanitizeDialog_v2.js b/browser/base/content/test/sanitize/browser_sanitizeDialog_v2.js
index 29f760f57f..8ae0263c82 100644
--- a/browser/base/content/test/sanitize/browser_sanitizeDialog_v2.js
+++ b/browser/base/content/test/sanitize/browser_sanitizeDialog_v2.js
@@ -20,33 +20,9 @@ ChromeUtils.defineESModuleGetters(this, {
PlacesTestUtils: "resource://testing-common/PlacesTestUtils.sys.mjs",
Timer: "resource://gre/modules/Timer.sys.mjs",
PermissionTestUtils: "resource://testing-common/PermissionTestUtils.sys.mjs",
- FileTestUtils: "resource://testing-common/FileTestUtils.sys.mjs",
Downloads: "resource://gre/modules/Downloads.sys.mjs",
});
-const kMsecPerMin = 60 * 1000;
-const kUsecPerMin = 60 * 1000000;
-let today = Date.now() - new Date().setHours(0, 0, 0, 0);
-let nowMSec = Date.now();
-let nowUSec = nowMSec * 1000;
-let fileURL;
-
-const TEST_TARGET_FILE_NAME = "test-download.txt";
-const TEST_QUOTA_USAGE_HOST = "example.com";
-const TEST_QUOTA_USAGE_ORIGIN = "https://" + TEST_QUOTA_USAGE_HOST;
-const TEST_QUOTA_USAGE_URL =
- getRootDirectory(gTestPath).replace(
- "chrome://mochitests/content",
- TEST_QUOTA_USAGE_ORIGIN
- ) + "site_data_test.html";
-
-const siteOrigins = [
- "https://www.example.com",
- "https://example.org",
- "http://localhost:8000",
- "http://localhost:3000",
-];
-
/**
* Ensures that the specified URIs are either cleared or not.
*
@@ -167,90 +143,6 @@ async function addDownloadWithMinutesAgo(aExpectedPathList, aMinutesAgo) {
aExpectedPathList.push(name);
}
-/**
- * Adds multiple downloads to the PUBLIC download list
- */
-async function addToDownloadList() {
- const url = createFileURL();
- const downloadsList = await Downloads.getList(Downloads.PUBLIC);
- let timeOptions = [1, 2, 4, 24, 128, 128];
- let buffer = 100000;
-
- for (let i = 0; i < timeOptions.length; i++) {
- let timeDownloaded = 60 * kMsecPerMin * timeOptions[i];
- if (timeOptions[i] === 24) {
- timeDownloaded = today;
- }
-
- let download = await Downloads.createDownload({
- source: { url: url.spec, isPrivate: false },
- target: { path: FileTestUtils.getTempFile(TEST_TARGET_FILE_NAME).path },
- startTime: {
- getTime: _ => {
- return nowMSec - timeDownloaded + buffer;
- },
- },
- });
-
- Assert.ok(!!download);
- downloadsList.add(download);
- }
- let items = await downloadsList.getAll();
- Assert.equal(items.length, 6, "Items were added to the list");
-}
-
-async function addToSiteUsage() {
- // Fill indexedDB with test data.
- // Don't wait for the page to load, to register the content event handler as quickly as possible.
- // If this test goes intermittent, we might have to tell the page to wait longer before
- // firing the event.
- BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_QUOTA_USAGE_URL, false);
- await BrowserTestUtils.waitForContentEvent(
- gBrowser.selectedBrowser,
- "test-indexedDB-done",
- false,
- null,
- true
- );
- BrowserTestUtils.removeTab(gBrowser.selectedTab);
-
- let siteLastAccessed = [1, 2, 4, 24];
-
- let staticUsage = 4096 * 6;
- // Add a time buffer so the site access falls within the time range
- const buffer = 10000;
-
- // Change lastAccessed of sites
- for (let index = 0; index < siteLastAccessed.length; index++) {
- let lastAccessedTime = 60 * kMsecPerMin * siteLastAccessed[index];
- if (siteLastAccessed[index] === 24) {
- lastAccessedTime = today;
- }
-
- let site = SiteDataManager._testInsertSite(siteOrigins[index], {
- quotaUsage: staticUsage,
- lastAccessed: (nowMSec - lastAccessedTime + buffer) * 1000,
- });
- Assert.ok(site, "Site added successfully");
- }
-}
-
-/**
- * Helper function to create file URL to open
- *
- * @returns {Object} a file URL
- */
-function createFileURL() {
- if (!fileURL) {
- let file = Services.dirsvc.get("TmpD", Ci.nsIFile);
- file.append("foo.txt");
- file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
-
- fileURL = Services.io.newFileURI(file);
- }
- return fileURL;
-}
-
add_setup(async function () {
requestLongerTimeout(3);
await blankSlate();
@@ -268,248 +160,6 @@ add_setup(async function () {
});
/**
- * Removes all history visits, downloads, and form entries.
- */
-async function blankSlate() {
- let publicList = await Downloads.getList(Downloads.PUBLIC);
- let downloads = await publicList.getAll();
- for (let download of downloads) {
- await publicList.remove(download);
- await download.finalize(true);
- }
-
- await FormHistory.update({ op: "remove" });
- await PlacesUtils.history.clear();
-}
-
-/**
- * This wraps the dialog and provides some convenience methods for interacting
- * with it.
- *
- * @param browserWin (optional)
- * The browser window that the dialog is expected to open in. If not
- * supplied, the initial browser window of the test run is used.
- * @param mode (optional)
- * One of
- * clear on shutdown settings context ("clearOnShutdown"),
- * clear site data settings context ("clearSiteData"),
- * clear history context ("clearHistory"),
- * browser context ("browser")
- * "browser" by default
- */
-function DialogHelper(openContext = "browser") {
- this._browserWin = window;
- this.win = null;
- this._mode = openContext;
- this.promiseClosed = new Promise(resolve => {
- this._resolveClosed = resolve;
- });
-}
-
-DialogHelper.prototype = {
- /**
- * "Presses" the dialog's OK button.
- */
- acceptDialog() {
- let dialogEl = this.win.document.querySelector("dialog");
- is(
- dialogEl.getButton("accept").disabled,
- false,
- "Dialog's OK button should not be disabled"
- );
- dialogEl.acceptDialog();
- },
-
- /**
- * "Presses" the dialog's Cancel button.
- */
- cancelDialog() {
- this.win.document.querySelector("dialog").cancelDialog();
- },
-
- /**
- * (Un)checks a history scope checkbox (browser & download history,
- * form history, etc.).
- *
- * @param aPrefName
- * The final portion of the checkbox's privacy.cpd.* preference name
- * @param aCheckState
- * True if the checkbox should be checked, false otherwise
- */
- checkPrefCheckbox(aPrefName, aCheckState) {
- var cb = this.win.document.querySelectorAll(
- "checkbox[id='" + aPrefName + "']"
- );
- is(cb.length, 1, "found checkbox for " + aPrefName + " id");
- if (cb[0].checked != aCheckState) {
- cb[0].click();
- }
- },
-
- /**
- * @param {String} aCheckboxId
- * The checkbox id name
- * @param {Boolean} aCheckState
- * True if the checkbox should be checked, false otherwise
- */
- validateCheckbox(aCheckboxId, aCheckState) {
- let cb = this.win.document.querySelectorAll(
- "checkbox[id='" + aCheckboxId + "']"
- );
- is(cb.length, 1, `found checkbox for id=${aCheckboxId}`);
- is(
- cb[0].checked,
- aCheckState,
- `checkbox for ${aCheckboxId} is ${aCheckState}`
- );
- },
-
- /**
- * Makes sure all the checkboxes are checked.
- */
- _checkAllCheckboxesCustom(check) {
- var cb = this.win.document.querySelectorAll(".clearingItemCheckbox");
- ok(cb.length, "found checkboxes for ids");
- for (var i = 0; i < cb.length; ++i) {
- if (cb[i].checked != check) {
- cb[i].click();
- }
- }
- },
-
- checkAllCheckboxes() {
- this._checkAllCheckboxesCustom(true);
- },
-
- uncheckAllCheckboxes() {
- this._checkAllCheckboxesCustom(false);
- },
-
- /**
- * @return The dialog's duration dropdown
- */
- getDurationDropdown() {
- return this.win.document.getElementById("sanitizeDurationChoice");
- },
-
- /**
- * @return The clear-everything warning box
- */
- getWarningPanel() {
- return this.win.document.getElementById("sanitizeEverythingWarningBox");
- },
-
- /**
- * @return True if the "Everything" warning panel is visible (as opposed to
- * the tree)
- */
- isWarningPanelVisible() {
- return !this.getWarningPanel().hidden;
- },
-
- /**
- * Opens the clear recent history dialog. Before calling this, set
- * this.onload to a function to execute onload. It should close the dialog
- * when done so that the tests may continue. Set this.onunload to a function
- * to execute onunload. this.onunload is optional. If it returns true, the
- * caller is expected to call promiseAsyncUpdates at some point; if false is
- * returned, promiseAsyncUpdates is called automatically.
- */
- async open() {
- let dialogPromise = BrowserTestUtils.promiseAlertDialogOpen(
- null,
- "chrome://browser/content/sanitize_v2.xhtml",
- {
- isSubDialog: true,
- }
- );
-
- // We want to simulate opening the dialog inside preferences for clear history
- // and clear site data
- if (this._mode != "browser") {
- await openPreferencesViaOpenPreferencesAPI("privacy", {
- leaveOpen: true,
- });
- let tabWindow = gBrowser.selectedBrowser.contentWindow;
- let clearDialogOpenButtonId = this._mode + "Button";
- // the id for clear on shutdown is of a different format
- if (this._mode == "clearOnShutdown") {
- // set always clear to true to enable the clear on shutdown dialog
- let enableSettingsCheckbox =
- tabWindow.document.getElementById("alwaysClear");
- if (!enableSettingsCheckbox.checked) {
- enableSettingsCheckbox.click();
- }
- clearDialogOpenButtonId = "clearDataSettings";
- }
- // open dialog
- tabWindow.document.getElementById(clearDialogOpenButtonId).click();
- }
- // We open the dialog in the chrome context in other cases
- else {
- executeSoon(() => {
- Sanitizer.showUI(this._browserWin, this._mode);
- });
- }
-
- this.win = await dialogPromise;
- this.win.addEventListener(
- "load",
- () => {
- // Run onload on next tick so that gSanitizePromptDialog.init can run first.
- executeSoon(async () => {
- await this.win.gSanitizePromptDialog.dataSizesFinishedUpdatingPromise;
- this.onload();
- });
- },
- { once: true }
- );
- this.win.addEventListener(
- "unload",
- () => {
- // Some exceptions that reach here don't reach the test harness, but
- // ok()/is() do...
- (async () => {
- if (this.onunload) {
- await this.onunload();
- }
- if (this._mode != "browser") {
- BrowserTestUtils.removeTab(gBrowser.selectedTab);
- }
- await PlacesTestUtils.promiseAsyncUpdates();
- this._resolveClosed();
- this.win = null;
- })();
- },
- { once: true }
- );
- },
-
- /**
- * Selects a duration in the duration dropdown.
- *
- * @param aDurVal
- * One of the Sanitizer.TIMESPAN_* values
- */
- selectDuration(aDurVal) {
- this.getDurationDropdown().value = aDurVal;
- if (aDurVal === Sanitizer.TIMESPAN_EVERYTHING) {
- is(
- this.isWarningPanelVisible(),
- true,
- "Warning panel should be visible for TIMESPAN_EVERYTHING"
- );
- } else {
- is(
- this.isWarningPanelVisible(),
- false,
- "Warning panel should not be visible for non-TIMESPAN_EVERYTHING"
- );
- }
- },
-};
-
-/**
* Ensures that the given pref is the expected value.
*
* @param aPrefName
@@ -533,58 +183,6 @@ function visitTimeForMinutesAgo(aMinutesAgo) {
return nowUSec - aMinutesAgo * kUsecPerMin;
}
-function promiseSanitizationComplete() {
- return TestUtils.topicObserved("sanitizer-sanitization-complete");
-}
-
-/**
- * Helper function to validate the data sizes shown for each time selection
- *
- * @param {DialogHelper} dh - dialog object to access window and timespan
- */
-async function validateDataSizes(dialogHelper) {
- let timespans = [
- "TIMESPAN_HOUR",
- "TIMESPAN_2HOURS",
- "TIMESPAN_4HOURS",
- "TIMESPAN_TODAY",
- "TIMESPAN_EVERYTHING",
- ];
-
- // get current data sizes from siteDataManager
- let cacheUsage = await SiteDataManager.getCacheSize();
- let quotaUsage = await SiteDataManager.getQuotaUsageForTimeRanges(timespans);
-
- for (let i = 0; i < timespans.length; i++) {
- // select timespan to check
- dialogHelper.selectDuration(Sanitizer[timespans[i]]);
-
- // get the elements
- let clearCookiesAndSiteDataCheckbox =
- dialogHelper.win.document.getElementById("cookiesAndStorage");
- let clearCacheCheckbox = dialogHelper.win.document.getElementById("cache");
-
- let [convertedQuotaUsage] = DownloadUtils.convertByteUnits(
- quotaUsage[timespans[i]]
- );
- let [, convertedCacheUnit] = DownloadUtils.convertByteUnits(cacheUsage);
-
- // Ensure l10n is finished before inspecting the category labels.
- await dialogHelper.win.document.l10n.translateElements([
- clearCookiesAndSiteDataCheckbox,
- clearCacheCheckbox,
- ]);
- ok(
- clearCacheCheckbox.label.includes(convertedCacheUnit),
- "Should show the cache usage"
- );
- ok(
- clearCookiesAndSiteDataCheckbox.label.includes(convertedQuotaUsage),
- `Should show the quota usage as ${convertedQuotaUsage}`
- );
- }
-}
-
/**
*
* Opens dialog in the provided context and selects the checkboxes
@@ -602,7 +200,7 @@ async function performActionsOnDialog({
cache = false,
siteSettings = false,
}) {
- let dh = new DialogHelper(context);
+ let dh = new ClearHistoryDialogHelper({ mode: context });
dh.onload = function () {
this.selectDuration(timespan);
this.checkPrefCheckbox(
@@ -622,7 +220,7 @@ async function performActionsOnDialog({
* Initializes the dialog to its default state.
*/
add_task(async function default_state() {
- let dh = new DialogHelper();
+ let dh = new ClearHistoryDialogHelper();
dh.onload = function () {
// Select "Last Hour"
this.selectDuration(Sanitizer.TIMESPAN_HOUR);
@@ -647,7 +245,7 @@ add_task(async function test_cancel() {
}
await PlacesTestUtils.addVisits(places);
- let dh = new DialogHelper();
+ let dh = new ClearHistoryDialogHelper();
dh.onload = function () {
this.selectDuration(Sanitizer.TIMESPAN_HOUR);
this.checkPrefCheckbox("historyFormDataAndDownloads", false);
@@ -662,6 +260,72 @@ add_task(async function test_cancel() {
await dh.promiseClosed;
});
+// test remembering user options for various entry points
+add_task(async function test_pref_remembering() {
+ let dh = new ClearHistoryDialogHelper({ mode: "clearSiteData" });
+ dh.onload = function () {
+ this.checkPrefCheckbox("cookiesAndStorage", false);
+ this.checkPrefCheckbox("siteSettings", true);
+
+ this.acceptDialog();
+ };
+ dh.open();
+ await dh.promiseClosed;
+
+ // validate if prefs are remembered
+ dh = new ClearHistoryDialogHelper({ mode: "clearSiteData" });
+ dh.onload = function () {
+ this.validateCheckbox("cookiesAndStorage", false);
+ this.validateCheckbox("siteSettings", true);
+
+ this.checkPrefCheckbox("cookiesAndStorage", true);
+ this.checkPrefCheckbox("siteSettings", false);
+
+ // we will test cancelling the dialog, to make sure it doesn't remember
+ // the prefs when cancelled
+ this.cancelDialog();
+ };
+ dh.open();
+ await dh.promiseClosed;
+
+ // validate if prefs did not change since we cancelled the dialog
+ dh = new ClearHistoryDialogHelper({ mode: "clearSiteData" });
+ dh.onload = function () {
+ this.validateCheckbox("cookiesAndStorage", false);
+ this.validateCheckbox("siteSettings", true);
+
+ this.cancelDialog();
+ };
+ dh.open();
+ await dh.promiseClosed;
+
+ // test rememebering prefs from the clear history context
+ // since clear history and clear site data have seperate remembering
+ // of prefs
+ dh = new ClearHistoryDialogHelper({ mode: "clearHistory" });
+ dh.onload = function () {
+ this.checkPrefCheckbox("cookiesAndStorage", true);
+ this.checkPrefCheckbox("siteSettings", false);
+ this.checkPrefCheckbox("cache", false);
+
+ this.acceptDialog();
+ };
+ dh.open();
+ await dh.promiseClosed;
+
+ // validate if prefs are remembered across both clear history and browser
+ dh = new ClearHistoryDialogHelper({ mode: "browser" });
+ dh.onload = function () {
+ this.validateCheckbox("cookiesAndStorage", true);
+ this.validateCheckbox("siteSettings", false);
+ this.validateCheckbox("cache", false);
+
+ this.cancelDialog();
+ };
+ dh.open();
+ await dh.promiseClosed;
+});
+
/**
* Ensures that the "Everything" duration option works.
*/
@@ -681,7 +345,7 @@ add_task(async function test_everything() {
let promiseSanitized = promiseSanitizationComplete();
await PlacesTestUtils.addVisits(places);
- let dh = new DialogHelper();
+ let dh = new ClearHistoryDialogHelper();
dh.onload = function () {
is(
this.isWarningPanelVisible(),
@@ -728,7 +392,7 @@ add_task(async function test_everything_warning() {
let promiseSanitized = promiseSanitizationComplete();
await PlacesTestUtils.addVisits(places);
- let dh = new DialogHelper();
+ let dh = new ClearHistoryDialogHelper();
dh.onload = function () {
is(
this.isWarningPanelVisible(),
@@ -761,7 +425,7 @@ add_task(async function test_everything_warning() {
* and enabled when at least one checkbox is checked
*/
add_task(async function testAcceptButtonDisabled() {
- let dh = new DialogHelper();
+ let dh = new ClearHistoryDialogHelper();
dh.onload = async function () {
let clearButton = this.win.document
.querySelector("dialog")
@@ -769,12 +433,6 @@ add_task(async function testAcceptButtonDisabled() {
this.uncheckAllCheckboxes();
await new Promise(resolve => SimpleTest.executeSoon(resolve));
is(clearButton.disabled, true, "Clear button should be disabled");
- // await BrowserTestUtils.waitForMutationCondition(
- // clearButton,
- // { attributes: true },
- // () => clearButton.disabled,
- // "Clear button should be disabled"
- // );
this.checkPrefCheckbox("cache", true);
await new Promise(resolve => SimpleTest.executeSoon(resolve));
@@ -790,7 +448,7 @@ add_task(async function testAcceptButtonDisabled() {
* Tests to see if the warning box is hidden when opened in the clear on shutdown context
*/
add_task(async function testWarningBoxInClearOnShutdown() {
- let dh = new DialogHelper("clearSiteData");
+ let dh = new ClearHistoryDialogHelper({ mode: "clearSiteData" });
dh.onload = function () {
this.selectDuration(Sanitizer.TIMESPAN_EVERYTHING);
is(
@@ -803,7 +461,7 @@ add_task(async function testWarningBoxInClearOnShutdown() {
dh.open();
await dh.promiseClosed;
- dh = new DialogHelper("clearOnShutdown");
+ dh = new ClearHistoryDialogHelper({ mode: "clearOnShutdown" });
dh.onload = function () {
is(
BrowserTestUtils.isVisible(this.getWarningPanel()),
@@ -853,7 +511,7 @@ add_task(async function test_history_downloads_checked() {
await PlacesTestUtils.addVisits(places);
- let dh = new DialogHelper();
+ let dh = new ClearHistoryDialogHelper();
dh.onload = function () {
this.selectDuration(Sanitizer.TIMESPAN_HOUR);
this.checkPrefCheckbox("historyFormDataAndDownloads", true);
@@ -905,7 +563,7 @@ add_task(async function test_cannot_clear_history() {
});
let uris = [pURI];
- let dh = new DialogHelper();
+ let dh = new ClearHistoryDialogHelper();
dh.onload = function () {
var cb = this.win.document.querySelectorAll(
"checkbox[id='historyFormDataAndDownloads']"
@@ -932,7 +590,7 @@ add_task(async function test_cannot_clear_history() {
add_task(async function test_no_formdata_history_to_clear() {
let promiseSanitized = promiseSanitizationComplete();
- let dh = new DialogHelper();
+ let dh = new ClearHistoryDialogHelper();
dh.onload = function () {
var cb = this.win.document.querySelectorAll(
"checkbox[id='historyFormDataAndDownloads']"
@@ -955,7 +613,7 @@ add_task(async function test_form_entries() {
let promiseSanitized = promiseSanitizationComplete();
- let dh = new DialogHelper();
+ let dh = new ClearHistoryDialogHelper();
dh.onload = function () {
var cb = this.win.document.querySelectorAll(
"checkbox[id='historyFormDataAndDownloads']"
@@ -975,97 +633,13 @@ add_task(async function test_form_entries() {
await dh.promiseClosed;
});
-add_task(async function test_cookie_sizes() {
- await clearAndValidateDataSizes({
- clearCookies: true,
- clearCache: false,
- clearDownloads: false,
- timespan: Sanitizer.TIMESPAN_HOUR,
- });
- await clearAndValidateDataSizes({
- clearCookies: true,
- clearCache: false,
- clearDownloads: false,
- timespan: Sanitizer.TIMESPAN_4HOURS,
- });
- await clearAndValidateDataSizes({
- clearCookies: true,
- clearCache: false,
- clearDownloads: false,
- timespan: Sanitizer.TIMESPAN_EVERYTHING,
- });
-});
-
-add_task(async function test_cache_sizes() {
- await clearAndValidateDataSizes({
- clearCookies: false,
- clearCache: true,
- clearDownloads: false,
- timespan: Sanitizer.TIMESPAN_HOUR,
- });
- await clearAndValidateDataSizes({
- clearCookies: false,
- clearCache: true,
- clearDownloads: false,
- timespan: Sanitizer.TIMESPAN_4HOURS,
- });
- await clearAndValidateDataSizes({
- clearCookies: false,
- clearCache: true,
- clearDownloads: false,
- timespan: Sanitizer.TIMESPAN_EVERYTHING,
- });
-});
-
-add_task(async function test_downloads_sizes() {
- await clearAndValidateDataSizes({
- clearCookies: false,
- clearCache: false,
- clearDownloads: true,
- timespan: Sanitizer.TIMESPAN_HOUR,
- });
- await clearAndValidateDataSizes({
- clearCookies: false,
- clearCache: false,
- clearDownloads: true,
- timespan: Sanitizer.TIMESPAN_4HOURS,
- });
- await clearAndValidateDataSizes({
- clearCookies: false,
- clearCache: false,
- clearDownloads: true,
- timespan: Sanitizer.TIMESPAN_EVERYTHING,
- });
-});
-
-add_task(async function test_all_data_sizes() {
- await clearAndValidateDataSizes({
- clearCookies: true,
- clearCache: true,
- clearDownloads: true,
- timespan: Sanitizer.TIMESPAN_HOUR,
- });
- await clearAndValidateDataSizes({
- clearCookies: true,
- clearCache: true,
- clearDownloads: true,
- timespan: Sanitizer.TIMESPAN_4HOURS,
- });
- await clearAndValidateDataSizes({
- clearCookies: true,
- clearCache: true,
- clearDownloads: true,
- timespan: Sanitizer.TIMESPAN_EVERYTHING,
- });
-});
-
// test the case when we open the dialog through the clear on shutdown settings
add_task(async function test_clear_on_shutdown() {
await SpecialPowers.pushPrefEnv({
set: [["privacy.sanitize.sanitizeOnShutdown", true]],
});
- let dh = new DialogHelper("clearOnShutdown");
+ let dh = new ClearHistoryDialogHelper({ mode: "clearOnShutdown" });
dh.onload = async function () {
this.uncheckAllCheckboxes();
this.checkPrefCheckbox("historyFormDataAndDownloads", false);
@@ -1134,7 +708,7 @@ add_task(async function test_clear_on_shutdown() {
await ensureDownloadsClearedState(downloadIDs, false);
await ensureDownloadsClearedState(olderDownloadIDs, false);
- dh = new DialogHelper("clearOnShutdown");
+ dh = new ClearHistoryDialogHelper({ mode: "clearOnShutdown" });
dh.onload = async function () {
this.uncheckAllCheckboxes();
this.checkPrefCheckbox("historyFormDataAndDownloads", true);
@@ -1192,89 +766,6 @@ add_task(async function test_clear_on_shutdown() {
await SiteDataTestUtils.clear();
});
-// test default prefs for entry points
-add_task(async function test_defaults_prefs() {
- let dh = new DialogHelper("clearSiteData");
- dh.onload = function () {
- this.validateCheckbox("historyFormDataAndDownloads", false);
- this.validateCheckbox("cache", true);
- this.validateCheckbox("cookiesAndStorage", true);
- this.validateCheckbox("siteSettings", false);
-
- this.cancelDialog();
- };
- dh.open();
- await dh.promiseClosed;
-
- // We don't need to specify the mode again,
- // as the default mode is taken (browser, clear history)
-
- dh = new DialogHelper();
- dh.onload = function () {
- // Default checked for browser and clear history mode
- this.validateCheckbox("historyFormDataAndDownloads", true);
- this.validateCheckbox("cache", true);
- this.validateCheckbox("cookiesAndStorage", true);
- this.validateCheckbox("siteSettings", false);
-
- this.cancelDialog();
- };
- dh.open();
- await dh.promiseClosed;
-});
-
-/**
- * Helper function to simulate switching timespan selections and
- * validate data sizes before and after clearing
- *
- * @param {Object}
- * clearCookies - boolean
- * clearDownloads - boolean
- * clearCaches - boolean
- * timespan - one of Sanitizer.TIMESPAN_*
- */
-async function clearAndValidateDataSizes({
- clearCache,
- clearDownloads,
- clearCookies,
- timespan,
-}) {
- await blankSlate();
-
- await addToDownloadList();
- await addToSiteUsage();
- let promiseSanitized = promiseSanitizationComplete();
-
- await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
-
- let dh = new DialogHelper();
- dh.onload = async function () {
- await validateDataSizes(this);
- this.checkPrefCheckbox("cache", clearCache);
- this.checkPrefCheckbox("cookiesAndStorage", clearCookies);
- this.checkPrefCheckbox("historyFormDataAndDownloads", clearDownloads);
- this.selectDuration(timespan);
- this.acceptDialog();
- };
- dh.onunload = async function () {
- await promiseSanitized;
- };
- dh.open();
- await dh.promiseClosed;
-
- let dh2 = new DialogHelper();
- // Check if the newly cleared values are reflected
- dh2.onload = async function () {
- await validateDataSizes(this);
- this.acceptDialog();
- };
- dh2.open();
- await dh2.promiseClosed;
-
- await SiteDataTestUtils.clear();
- BrowserTestUtils.removeTab(gBrowser.selectedTab);
-}
-
add_task(async function testEntryPointTelemetry() {
Services.fog.testResetFOG();
@@ -1401,27 +892,47 @@ add_task(async function testClearingOptionsTelemetry() {
);
});
-add_task(async function testCheckboxStatesAfterMigration() {
+add_task(async function testClearHistoryCheckboxStatesAfterMigration() {
await SpecialPowers.pushPrefEnv({
set: [
- ["privacy.clearOnShutdown.history", false],
- ["privacy.clearOnShutdown.formdata", true],
- ["privacy.clearOnShutdown.cookies", true],
- ["privacy.clearOnShutdown.offlineApps", false],
- ["privacy.clearOnShutdown.sessions", false],
- ["privacy.clearOnShutdown.siteSettings", false],
- ["privacy.clearOnShutdown.cache", true],
- ["privacy.clearOnShutdown_v2.cookiesAndStorage", false],
- ["privacy.sanitize.sanitizeOnShutdown.hasMigratedToNewPrefs", false],
+ ["privacy.cpd.history", false],
+ ["privacy.cpd.formdata", true],
+ ["privacy.cpd.cookies", true],
+ ["privacy.cpd.offlineApps", false],
+ ["privacy.cpd.sessions", false],
+ ["privacy.cpd.siteSettings", false],
+ ["privacy.cpd.cache", true],
+ // Set cookiesAndStorage to verify that the pref is flipped in the test
+ ["privacy.clearHistory.cookiesAndStorage", false],
+ ["privacy.sanitize.cpd.hasMigratedToNewPrefs", false],
],
});
- let dh = new DialogHelper("clearOnShutdown");
+ let dh = new ClearHistoryDialogHelper({ mode: "clearHistory" });
dh.onload = function () {
this.validateCheckbox("cookiesAndStorage", true);
this.validateCheckbox("historyFormDataAndDownloads", false);
this.validateCheckbox("cache", true);
this.validateCheckbox("siteSettings", false);
+
+ this.checkPrefCheckbox("siteSettings", true);
+ this.checkPrefCheckbox("cookiesAndStorage", false);
+ this.acceptDialog();
+ };
+ dh.open();
+ await dh.promiseClosed;
+
+ is(
+ Services.prefs.getBoolPref("privacy.sanitize.cpd.hasMigratedToNewPrefs"),
+ true,
+ "Migration is complete for cpd branch"
+ );
+
+ // make sure the migration doesn't run again
+ dh = new ClearHistoryDialogHelper({ mode: "clearHistory" });
+ dh.onload = function () {
+ this.validateCheckbox("siteSettings", true);
+ this.validateCheckbox("cookiesAndStorage", false);
this.cancelDialog();
};
dh.open();
diff --git a/browser/base/content/test/sanitize/browser_sanitizeDialog_v2_dataSizes.js b/browser/base/content/test/sanitize/browser_sanitizeDialog_v2_dataSizes.js
new file mode 100644
index 0000000000..ccb3c7d519
--- /dev/null
+++ b/browser/base/content/test/sanitize/browser_sanitizeDialog_v2_dataSizes.js
@@ -0,0 +1,310 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+/**
+ * This tests the new clear history dialog's data size display functionality
+ */
+ChromeUtils.defineESModuleGetters(this, {
+ sinon: "resource://testing-common/Sinon.sys.mjs",
+ Sanitizer: "resource:///modules/Sanitizer.sys.mjs",
+});
+
+add_setup(async function () {
+ await blankSlate();
+ registerCleanupFunction(async function () {
+ await blankSlate();
+ await PlacesTestUtils.promiseAsyncUpdates();
+ });
+ await SpecialPowers.pushPrefEnv({
+ set: [["privacy.sanitize.useOldClearHistoryDialog", false]],
+ });
+});
+
+/**
+ * Helper function to validate the data sizes shown for each time selection
+ *
+ * @param {ClearHistoryDialogHelper} dh - dialog object to access window and timespan
+ */
+async function validateDataSizes(ClearHistoryDialogHelper) {
+ let timespans = [
+ "TIMESPAN_HOUR",
+ "TIMESPAN_2HOURS",
+ "TIMESPAN_4HOURS",
+ "TIMESPAN_TODAY",
+ "TIMESPAN_EVERYTHING",
+ ];
+
+ // get current data sizes from siteDataManager
+ let cacheUsage = await SiteDataManager.getCacheSize();
+ let quotaUsage = await SiteDataManager.getQuotaUsageForTimeRanges(timespans);
+
+ for (let i = 0; i < timespans.length; i++) {
+ // select timespan to check
+ ClearHistoryDialogHelper.selectDuration(Sanitizer[timespans[i]]);
+
+ // get the elements
+ let clearCookiesAndSiteDataCheckbox =
+ ClearHistoryDialogHelper.win.document.getElementById("cookiesAndStorage");
+ let clearCacheCheckbox =
+ ClearHistoryDialogHelper.win.document.getElementById("cache");
+
+ let [convertedQuotaUsage] = DownloadUtils.convertByteUnits(
+ quotaUsage[timespans[i]]
+ );
+ let [, convertedCacheUnit] = DownloadUtils.convertByteUnits(cacheUsage);
+
+ // Ensure l10n is finished before inspecting the category labels.
+ await ClearHistoryDialogHelper.win.document.l10n.translateElements([
+ clearCookiesAndSiteDataCheckbox,
+ clearCacheCheckbox,
+ ]);
+ ok(
+ clearCacheCheckbox.label.includes(convertedCacheUnit),
+ "Should show the cache usage"
+ );
+ ok(
+ clearCookiesAndSiteDataCheckbox.label.includes(convertedQuotaUsage),
+ `Should show the quota usage as ${convertedQuotaUsage}`
+ );
+ }
+}
+
+/**
+ * Helper function to simulate switching timespan selections and
+ * validate data sizes before and after clearing
+ *
+ * @param {Object}
+ * clearCookies - boolean
+ * clearDownloads - boolean
+ * clearCaches - boolean
+ * timespan - one of Sanitizer.TIMESPAN_*
+ */
+async function clearAndValidateDataSizes({
+ clearCache,
+ clearDownloads,
+ clearCookies,
+ timespan,
+}) {
+ await blankSlate();
+
+ await addToSiteUsage();
+ let promiseSanitized = promiseSanitizationComplete();
+
+ await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
+
+ let dh = new ClearHistoryDialogHelper({ checkingDataSizes: true });
+ dh.onload = async function () {
+ await validateDataSizes(this);
+ this.checkPrefCheckbox("cache", clearCache);
+ this.checkPrefCheckbox("cookiesAndStorage", clearCookies);
+ this.checkPrefCheckbox("historyFormDataAndDownloads", clearDownloads);
+ this.selectDuration(timespan);
+ this.acceptDialog();
+ };
+ dh.onunload = async function () {
+ await promiseSanitized;
+ };
+ dh.open();
+ await dh.promiseClosed;
+
+ let dh2 = new ClearHistoryDialogHelper({ checkingDataSizes: true });
+ // Check if the newly cleared values are reflected
+ dh2.onload = async function () {
+ await validateDataSizes(this);
+ this.acceptDialog();
+ };
+ dh2.open();
+ await dh2.promiseClosed;
+
+ await SiteDataTestUtils.clear();
+ BrowserTestUtils.removeTab(gBrowser.selectedTab);
+}
+
+add_task(async function test_cookie_sizes() {
+ await clearAndValidateDataSizes({
+ clearCookies: true,
+ clearCache: false,
+ clearDownloads: false,
+ timespan: Sanitizer.TIMESPAN_HOUR,
+ });
+ await clearAndValidateDataSizes({
+ clearCookies: true,
+ clearCache: false,
+ clearDownloads: false,
+ timespan: Sanitizer.TIMESPAN_4HOURS,
+ });
+ await clearAndValidateDataSizes({
+ clearCookies: true,
+ clearCache: false,
+ clearDownloads: false,
+ timespan: Sanitizer.TIMESPAN_EVERYTHING,
+ });
+});
+
+add_task(async function test_cache_sizes() {
+ await clearAndValidateDataSizes({
+ clearCookies: false,
+ clearCache: true,
+ clearDownloads: false,
+ timespan: Sanitizer.TIMESPAN_HOUR,
+ });
+ await clearAndValidateDataSizes({
+ clearCookies: false,
+ clearCache: true,
+ clearDownloads: false,
+ timespan: Sanitizer.TIMESPAN_4HOURS,
+ });
+ await clearAndValidateDataSizes({
+ clearCookies: false,
+ clearCache: true,
+ clearDownloads: false,
+ timespan: Sanitizer.TIMESPAN_EVERYTHING,
+ });
+});
+
+add_task(async function test_all_data_sizes() {
+ await clearAndValidateDataSizes({
+ clearCookies: true,
+ clearCache: true,
+ clearDownloads: true,
+ timespan: Sanitizer.TIMESPAN_HOUR,
+ });
+ await clearAndValidateDataSizes({
+ clearCookies: true,
+ clearCache: true,
+ clearDownloads: true,
+ timespan: Sanitizer.TIMESPAN_4HOURS,
+ });
+ await clearAndValidateDataSizes({
+ clearCookies: true,
+ clearCache: true,
+ clearDownloads: true,
+ timespan: Sanitizer.TIMESPAN_EVERYTHING,
+ });
+});
+
+// This test makes sure that the user can change their timerange option
+// even if the data sizes are not loaded yet.
+add_task(async function testUIWithDataSizesLoading() {
+ await blankSlate();
+ await addToSiteUsage();
+
+ let origGetQuotaUsageForTimeRanges =
+ SiteDataManager.getQuotaUsageForTimeRanges.bind(SiteDataManager);
+ let resolveStubFn;
+ let resolverAssigned = false;
+
+ let dh = new ClearHistoryDialogHelper();
+ // Create a sandbox for isolated stubbing within the test
+ let sandbox = sinon.createSandbox();
+ sandbox
+ .stub(SiteDataManager, "getQuotaUsageForTimeRanges")
+ .callsFake(async (...args) => {
+ info("stub called");
+
+ let dataSizesReadyToLoadPromise = new Promise(resolve => {
+ resolveStubFn = resolve;
+ info("Sending message to notify dialog that the resolver is assigned");
+ window.postMessage("resolver-assigned", "*");
+ resolverAssigned = true;
+ });
+ await dataSizesReadyToLoadPromise;
+ return origGetQuotaUsageForTimeRanges(...args);
+ });
+ dh.onload = async function () {
+ // we add this event listener in the case where init finishes before the resolver is assigned
+ if (!resolverAssigned) {
+ await new Promise(resolve => {
+ let listener = event => {
+ if (event.data === "resolver-assigned") {
+ window.removeEventListener("message", listener);
+ // we are ready to test the dialog without any data sizes loaded
+ resolve();
+ }
+ };
+ window.addEventListener("message", listener);
+ });
+ }
+
+ ok(
+ !this.win.gSanitizePromptDialog._dataSizesUpdated,
+ "Data sizes should not have loaded yet"
+ );
+ this.selectDuration(Sanitizer.TIMESPAN_2HOURS);
+
+ info("triggering loading state end");
+ resolveStubFn();
+
+ await this.win.gSanitizePromptDialog.dataSizesFinishedUpdatingPromise;
+
+ validateDataSizes(this);
+ this.cancelDialog();
+ };
+ dh.open();
+ await dh.promiseClosed;
+
+ // Restore the sandbox after the test is complete
+ sandbox.restore();
+});
+
+add_task(async function testClearingBeforeDataSizesLoad() {
+ await blankSlate();
+ await addToSiteUsage();
+
+ // add site data that we can verify if it gets cleared
+ await createDummyDataForHost("example.org");
+ await createDummyDataForHost("example.com");
+
+ ok(
+ await SiteDataTestUtils.hasIndexedDB("https://example.org"),
+ "We have indexedDB data for example.org"
+ );
+ ok(
+ await SiteDataTestUtils.hasIndexedDB("https://example.com"),
+ "We have indexedDB data for example.com"
+ );
+
+ let dh = new ClearHistoryDialogHelper();
+ let promiseSanitized = promiseSanitizationComplete();
+ // Create a sandbox for isolated stubbing within the test
+ let sandbox = sinon.createSandbox();
+ sandbox
+ .stub(SiteDataManager, "getQuotaUsageForTimeRanges")
+ .callsFake(async () => {
+ info("stub called");
+
+ info("This promise should never resolve");
+ await new Promise(resolve => {});
+ });
+ dh.onload = async function () {
+ // we don't need to initiate a event listener to wait for the resolver to be assigned for this
+ // test since we do not want the data sizes to load
+ ok(
+ !this.win.gSanitizePromptDialog._dataSizesUpdated,
+ "Data sizes should not be loaded yet"
+ );
+ this.selectDuration(Sanitizer.TIMESPAN_2HOURS);
+ this.checkPrefCheckbox("cookiesAndStorage", true);
+ this.acceptDialog();
+ };
+ dh.onunload = async () => {
+ await promiseSanitized;
+ };
+ dh.open();
+ await dh.promiseClosed;
+
+ // Data for example.org should be cleared
+ ok(
+ !(await SiteDataTestUtils.hasIndexedDB("https://example.org")),
+ "We don't have indexedDB data for example.org"
+ );
+ // Data for example.com should be cleared
+ ok(
+ !(await SiteDataTestUtils.hasIndexedDB("https://example.com")),
+ "We don't have indexedDB data for example.com"
+ );
+
+ // Restore the sandbox after the test is complete
+ sandbox.restore();
+});
diff --git a/browser/base/content/test/sanitize/browser_sanitizeOnShutdown_migration.js b/browser/base/content/test/sanitize/browser_sanitizeOnShutdown_migration.js
index 3c2af1d513..bc5c925702 100644
--- a/browser/base/content/test/sanitize/browser_sanitizeOnShutdown_migration.js
+++ b/browser/base/content/test/sanitize/browser_sanitizeOnShutdown_migration.js
@@ -17,7 +17,7 @@ add_task(async function testMigrationOfCacheAndSiteSettings() {
["privacy.clearOnShutdown.siteSettings", true],
["privacy.clearOnShutdown_v2.cache", false],
["privacy.clearOnShutdown_v2.siteSettings", false],
- ["privacy.sanitize.sanitizeOnShutdown.hasMigratedToNewPrefs", false],
+ ["privacy.sanitize.clearOnShutdown.hasMigratedToNewPrefs", false],
],
});
@@ -46,7 +46,7 @@ add_task(async function testMigrationOfCacheAndSiteSettings() {
Assert.equal(
Services.prefs.getBoolPref(
- "privacy.sanitize.sanitizeOnShutdown.hasMigratedToNewPrefs"
+ "privacy.sanitize.clearOnShutdown.hasMigratedToNewPrefs"
),
true,
"migration pref has been flipped"
@@ -59,7 +59,7 @@ add_task(async function testHistoryAndFormData_historyTrue() {
["privacy.clearOnShutdown.history", true],
["privacy.clearOnShutdown.formdata", false],
["privacy.clearOnShutdown_v2.historyFormDataAndDownloads", false],
- ["privacy.sanitize.sanitizeOnShutdown.hasMigratedToNewPrefs", false],
+ ["privacy.sanitize.clearOnShutdown.hasMigratedToNewPrefs", false],
],
});
@@ -85,7 +85,7 @@ add_task(async function testHistoryAndFormData_historyTrue() {
Assert.equal(
Services.prefs.getBoolPref(
- "privacy.sanitize.sanitizeOnShutdown.hasMigratedToNewPrefs"
+ "privacy.sanitize.clearOnShutdown.hasMigratedToNewPrefs"
),
true,
"migration pref has been flipped"
@@ -98,7 +98,7 @@ add_task(async function testHistoryAndFormData_historyFalse() {
["privacy.clearOnShutdown.history", false],
["privacy.clearOnShutdown.formdata", true],
["privacy.clearOnShutdown_v2.historyFormDataAndDownloads", true],
- ["privacy.sanitize.sanitizeOnShutdown.hasMigratedToNewPrefs", false],
+ ["privacy.sanitize.clearOnShutdown.hasMigratedToNewPrefs", false],
],
});
@@ -124,7 +124,7 @@ add_task(async function testHistoryAndFormData_historyFalse() {
Assert.equal(
Services.prefs.getBoolPref(
- "privacy.sanitize.sanitizeOnShutdown.hasMigratedToNewPrefs"
+ "privacy.sanitize.clearOnShutdown.hasMigratedToNewPrefs"
),
true,
"migration pref has been flipped"
@@ -138,7 +138,7 @@ add_task(async function testCookiesAndStorage_cookiesFalse() {
["privacy.clearOnShutdown.offlineApps", true],
["privacy.clearOnShutdown.sessions", true],
["privacy.clearOnShutdown_v2.cookiesAndStorage", true],
- ["privacy.sanitize.sanitizeOnShutdown.hasMigratedToNewPrefs", false],
+ ["privacy.sanitize.clearOnShutdown.hasMigratedToNewPrefs", false],
],
});
@@ -168,7 +168,7 @@ add_task(async function testCookiesAndStorage_cookiesFalse() {
Assert.equal(
Services.prefs.getBoolPref(
- "privacy.sanitize.sanitizeOnShutdown.hasMigratedToNewPrefs"
+ "privacy.sanitize.clearOnShutdown.hasMigratedToNewPrefs"
),
true,
"migration pref has been flipped"
@@ -182,7 +182,7 @@ add_task(async function testCookiesAndStorage_cookiesTrue() {
["privacy.clearOnShutdown.offlineApps", false],
["privacy.clearOnShutdown.sessions", false],
["privacy.clearOnShutdown_v2.cookiesAndStorage", false],
- ["privacy.sanitize.sanitizeOnShutdown.hasMigratedToNewPrefs", false],
+ ["privacy.sanitize.clearOnShutdown.hasMigratedToNewPrefs", false],
],
});
@@ -211,7 +211,7 @@ add_task(async function testCookiesAndStorage_cookiesTrue() {
Assert.equal(
Services.prefs.getBoolPref(
- "privacy.sanitize.sanitizeOnShutdown.hasMigratedToNewPrefs"
+ "privacy.sanitize.clearOnShutdown.hasMigratedToNewPrefs"
),
true,
"migration pref has been flipped"
@@ -225,7 +225,7 @@ add_task(async function testMigrationDoesNotRepeat() {
["privacy.clearOnShutdown.offlineApps", false],
["privacy.clearOnShutdown.sessions", false],
["privacy.clearOnShutdown_v2.cookiesAndStorage", false],
- ["privacy.sanitize.sanitizeOnShutdown.hasMigratedToNewPrefs", true],
+ ["privacy.sanitize.clearOnShutdown.hasMigratedToNewPrefs", true],
],
});
@@ -255,7 +255,7 @@ add_task(async function testMigrationDoesNotRepeat() {
Assert.equal(
Services.prefs.getBoolPref(
- "privacy.sanitize.sanitizeOnShutdown.hasMigratedToNewPrefs"
+ "privacy.sanitize.clearOnShutdown.hasMigratedToNewPrefs"
),
true,
"migration pref has been flipped"
@@ -273,7 +273,7 @@ add_task(async function ensureNoOldPrefsAreEffectedByMigration() {
["privacy.clearOnShutdown.siteSettings", true],
["privacy.clearOnShutdown.cache", true],
["privacy.clearOnShutdown_v2.cookiesAndStorage", false],
- ["privacy.sanitize.sanitizeOnShutdown.hasMigratedToNewPrefs", false],
+ ["privacy.sanitize.clearOnShutdown.hasMigratedToNewPrefs", false],
],
});
diff --git a/browser/base/content/test/sanitize/head.js b/browser/base/content/test/sanitize/head.js
index f5a6031b84..30d96c69f6 100644
--- a/browser/base/content/test/sanitize/head.js
+++ b/browser/base/content/test/sanitize/head.js
@@ -3,10 +3,34 @@ ChromeUtils.defineESModuleGetters(this, {
FormHistory: "resource://gre/modules/FormHistory.sys.mjs",
PermissionTestUtils: "resource://testing-common/PermissionTestUtils.sys.mjs",
PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
+ PlacesTestUtils: "resource://testing-common/PlacesTestUtils.sys.mjs",
+ FileTestUtils: "resource://testing-common/FileTestUtils.sys.mjs",
Sanitizer: "resource:///modules/Sanitizer.sys.mjs",
SiteDataTestUtils: "resource://testing-common/SiteDataTestUtils.sys.mjs",
});
+const kMsecPerMin = 60 * 1000;
+const kUsecPerMin = kMsecPerMin * 1000;
+let today = Date.now() - new Date().setHours(0, 0, 0, 0);
+let nowMSec = Date.now();
+let nowUSec = nowMSec * 1000;
+const TEST_TARGET_FILE_NAME = "test-download.txt";
+const TEST_QUOTA_USAGE_HOST = "example.com";
+const TEST_QUOTA_USAGE_ORIGIN = "https://" + TEST_QUOTA_USAGE_HOST;
+const TEST_QUOTA_USAGE_URL =
+ getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ TEST_QUOTA_USAGE_ORIGIN
+ ) + "site_data_test.html";
+const SITE_ORIGINS = [
+ "https://www.example.com",
+ "https://example.org",
+ "http://localhost:8000",
+ "http://localhost:3000",
+];
+
+let fileURL;
+
function createIndexedDB(host, originAttributes) {
let uri = Services.io.newURI("https://" + host);
let principal = Services.scriptSecurityManager.createContentPrincipal(
@@ -369,3 +393,345 @@ async function createDummyDataForHost(host) {
await SiteDataTestUtils.addToIndexedDB(origin);
await SiteDataTestUtils.addServiceWorker(dummySWURL);
}
+
+/**
+ * Helper function to create file URL to open
+ *
+ * @returns {Object} a file URL
+ */
+function createFileURL() {
+ if (!fileURL) {
+ let file = Services.dirsvc.get("TmpD", Ci.nsIFile);
+ file.append("foo.txt");
+ file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
+
+ fileURL = Services.io.newFileURI(file);
+ }
+ return fileURL;
+}
+
+/**
+ * Removes all history visits, downloads, and form entries.
+ */
+async function blankSlate() {
+ let publicList = await Downloads.getList(Downloads.PUBLIC);
+ let downloads = await publicList.getAll();
+ for (let download of downloads) {
+ await publicList.remove(download);
+ await download.finalize(true);
+ }
+
+ await FormHistory.update({ op: "remove" });
+ await PlacesUtils.history.clear();
+}
+
+/**
+ * Adds multiple downloads to the PUBLIC download list
+ */
+async function addToDownloadList() {
+ const url = createFileURL();
+ const downloadsList = await Downloads.getList(Downloads.PUBLIC);
+ let timeOptions = [1, 2, 4, 24, 128, 128];
+ let buffer = 100000;
+
+ for (let i = 0; i < timeOptions.length; i++) {
+ let timeDownloaded = 60 * kMsecPerMin * timeOptions[i];
+ if (timeOptions[i] === 24) {
+ timeDownloaded = today;
+ }
+
+ let download = await Downloads.createDownload({
+ source: { url: url.spec, isPrivate: false },
+ target: { path: FileTestUtils.getTempFile(TEST_TARGET_FILE_NAME).path },
+ startTime: {
+ getTime: _ => {
+ return nowMSec - timeDownloaded + buffer;
+ },
+ },
+ });
+
+ Assert.ok(!!download);
+ downloadsList.add(download);
+ }
+ let items = await downloadsList.getAll();
+ Assert.equal(items.length, 6, "Items were added to the list");
+}
+
+async function addToSiteUsage() {
+ // Fill indexedDB with test data.
+ // Don't wait for the page to load, to register the content event handler as quickly as possible.
+ // If this test goes intermittent, we might have to tell the page to wait longer before
+ // firing the event.
+ BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_QUOTA_USAGE_URL, false);
+ await BrowserTestUtils.waitForContentEvent(
+ gBrowser.selectedBrowser,
+ "test-indexedDB-done",
+ false,
+ null,
+ true
+ );
+ BrowserTestUtils.removeTab(gBrowser.selectedTab);
+
+ let siteLastAccessed = [1, 2, 4, 24];
+
+ let staticUsage = 4096 * 6;
+ // Add a time buffer so the site access falls within the time range
+ const buffer = 10000;
+
+ // Change lastAccessed of sites
+ for (let index = 0; index < siteLastAccessed.length; index++) {
+ let lastAccessedTime = 60 * kMsecPerMin * siteLastAccessed[index];
+ if (siteLastAccessed[index] === 24) {
+ lastAccessedTime = today;
+ }
+
+ let site = SiteDataManager._testInsertSite(SITE_ORIGINS[index], {
+ quotaUsage: staticUsage,
+ lastAccessed: (nowMSec - lastAccessedTime + buffer) * 1000,
+ });
+ Assert.ok(site, "Site added successfully");
+ }
+}
+
+function promiseSanitizationComplete() {
+ return TestUtils.topicObserved("sanitizer-sanitization-complete");
+}
+
+/**
+ * This wraps the dialog and provides some convenience methods for interacting
+ * with it.
+ *
+ * @param {Window} browserWin (optional)
+ * The browser window that the dialog is expected to open in. If not
+ * supplied, the initial browser window of the test run is used.
+ * @param {Object} {mode, checkingDataSizes}
+ * mode: context to open the dialog in
+ * One of
+ * clear on shutdown settings context ("clearOnShutdown"),
+ * clear site data settings context ("clearSiteData"),
+ * clear history context ("clearHistory"),
+ * browser context ("browser")
+ * "browser" by default
+ * checkingDataSizes: boolean check if we should wait for the data sizes
+ * to load
+ *
+ */
+function ClearHistoryDialogHelper({
+ mode = "browser",
+ checkingDataSizes = false,
+} = {}) {
+ this._browserWin = window;
+ this.win = null;
+ this._mode = mode;
+ this._checkingDataSizes = checkingDataSizes;
+ this.promiseClosed = new Promise(resolve => {
+ this._resolveClosed = resolve;
+ });
+}
+
+ClearHistoryDialogHelper.prototype = {
+ /**
+ * "Presses" the dialog's OK button.
+ */
+ acceptDialog() {
+ let dialogEl = this.win.document.querySelector("dialog");
+ is(
+ dialogEl.getButton("accept").disabled,
+ false,
+ "Dialog's OK button should not be disabled"
+ );
+ dialogEl.acceptDialog();
+ },
+
+ /**
+ * "Presses" the dialog's Cancel button.
+ */
+ cancelDialog() {
+ this.win.document.querySelector("dialog").cancelDialog();
+ },
+
+ /**
+ * (Un)checks a history scope checkbox (browser & download history,
+ * form history, etc.).
+ *
+ * @param aPrefName
+ * The final portion of the checkbox's privacy.cpd.* preference name
+ * @param aCheckState
+ * True if the checkbox should be checked, false otherwise
+ */
+ checkPrefCheckbox(aPrefName, aCheckState) {
+ var cb = this.win.document.querySelectorAll(
+ "checkbox[id='" + aPrefName + "']"
+ );
+ is(cb.length, 1, "found checkbox for " + aPrefName + " id");
+ if (cb[0].checked != aCheckState) {
+ cb[0].click();
+ }
+ },
+
+ /**
+ * @param {String} aCheckboxId
+ * The checkbox id name
+ * @param {Boolean} aCheckState
+ * True if the checkbox should be checked, false otherwise
+ */
+ validateCheckbox(aCheckboxId, aCheckState) {
+ let cb = this.win.document.querySelectorAll(
+ "checkbox[id='" + aCheckboxId + "']"
+ );
+ is(cb.length, 1, `found checkbox for id=${aCheckboxId}`);
+ is(
+ cb[0].checked,
+ aCheckState,
+ `checkbox for ${aCheckboxId} is ${aCheckState}`
+ );
+ },
+
+ /**
+ * Makes sure all the checkboxes are checked.
+ */
+ _checkAllCheckboxesCustom(check) {
+ var cb = this.win.document.querySelectorAll(".clearingItemCheckbox");
+ ok(cb.length, "found checkboxes for ids");
+ for (var i = 0; i < cb.length; ++i) {
+ if (cb[i].checked != check) {
+ cb[i].click();
+ }
+ }
+ },
+
+ checkAllCheckboxes() {
+ this._checkAllCheckboxesCustom(true);
+ },
+
+ uncheckAllCheckboxes() {
+ this._checkAllCheckboxesCustom(false);
+ },
+
+ /**
+ * @return The dialog's duration dropdown
+ */
+ getDurationDropdown() {
+ return this.win.document.getElementById("sanitizeDurationChoice");
+ },
+
+ /**
+ * @return The clear-everything warning box
+ */
+ getWarningPanel() {
+ return this.win.document.getElementById("sanitizeEverythingWarningBox");
+ },
+
+ /**
+ * @return True if the "Everything" warning panel is visible (as opposed to
+ * the tree)
+ */
+ isWarningPanelVisible() {
+ return !this.getWarningPanel().hidden;
+ },
+
+ /**
+ * Opens the clear recent history dialog. Before calling this, set
+ * this.onload to a function to execute onload. It should close the dialog
+ * when done so that the tests may continue. Set this.onunload to a function
+ * to execute onunload. this.onunload is optional. If it returns true, the
+ * caller is expected to call promiseAsyncUpdates at some point; if false is
+ * returned, promiseAsyncUpdates is called automatically.
+ */
+ async open() {
+ let dialogPromise = BrowserTestUtils.promiseAlertDialogOpen(
+ null,
+ "chrome://browser/content/sanitize_v2.xhtml",
+ {
+ isSubDialog: true,
+ }
+ );
+
+ // We want to simulate opening the dialog inside preferences for clear history
+ // and clear site data
+ if (this._mode != "browser") {
+ await openPreferencesViaOpenPreferencesAPI("privacy", {
+ leaveOpen: true,
+ });
+ let tabWindow = gBrowser.selectedBrowser.contentWindow;
+ let clearDialogOpenButtonId = this._mode + "Button";
+ // the id for clear on shutdown is of a different format
+ if (this._mode == "clearOnShutdown") {
+ // set always clear to true to enable the clear on shutdown dialog
+ let enableSettingsCheckbox =
+ tabWindow.document.getElementById("alwaysClear");
+ if (!enableSettingsCheckbox.checked) {
+ enableSettingsCheckbox.click();
+ }
+ clearDialogOpenButtonId = "clearDataSettings";
+ }
+ // open dialog
+ tabWindow.document.getElementById(clearDialogOpenButtonId).click();
+ }
+ // We open the dialog in the chrome context in other cases
+ else {
+ executeSoon(() => {
+ Sanitizer.showUI(this._browserWin, this._mode);
+ });
+ }
+
+ this.win = await dialogPromise;
+ this.win.addEventListener(
+ "load",
+ () => {
+ // Run onload on next tick so that gSanitizePromptDialog.init can run first.
+ executeSoon(async () => {
+ if (this._checkingDataSizes) {
+ // we wait for the data sizes to load to avoid async errors when validating sizes
+ await this.win.gSanitizePromptDialog
+ .dataSizesFinishedUpdatingPromise;
+ }
+ this.onload();
+ });
+ },
+ { once: true }
+ );
+ this.win.addEventListener(
+ "unload",
+ () => {
+ // Some exceptions that reach here don't reach the test harness, but
+ // ok()/is() do...
+ (async () => {
+ if (this.onunload) {
+ await this.onunload();
+ }
+ if (this._mode != "browser") {
+ BrowserTestUtils.removeTab(gBrowser.selectedTab);
+ }
+ await PlacesTestUtils.promiseAsyncUpdates();
+ this._resolveClosed();
+ this.win = null;
+ })();
+ },
+ { once: true }
+ );
+ },
+
+ /**
+ * Selects a duration in the duration dropdown.
+ *
+ * @param aDurVal
+ * One of the Sanitizer.TIMESPAN_* values
+ */
+ selectDuration(aDurVal) {
+ this.getDurationDropdown().value = aDurVal;
+ if (aDurVal === Sanitizer.TIMESPAN_EVERYTHING) {
+ is(
+ this.isWarningPanelVisible(),
+ true,
+ "Warning panel should be visible for TIMESPAN_EVERYTHING"
+ );
+ } else {
+ is(
+ this.isWarningPanelVisible(),
+ false,
+ "Warning panel should not be visible for non-TIMESPAN_EVERYTHING"
+ );
+ }
+ },
+};
diff --git a/browser/base/content/test/siteIdentity/browser.toml b/browser/base/content/test/siteIdentity/browser.toml
index f0b6191302..c075052fa5 100644
--- a/browser/base/content/test/siteIdentity/browser.toml
+++ b/browser/base/content/test/siteIdentity/browser.toml
@@ -106,6 +106,12 @@ skip-if = [
["browser_identity_UI.js"]
https_first_disabled = true
+["browser_identity_web_controlled_blank.js"]
+support-files = [
+ "test_web_controlled_blank.html",
+ "dummy_page.html",
+]
+
["browser_iframe_navigation.js"]
https_first_disabled = true
support-files = ["iframe_navigation.html"]
diff --git a/browser/base/content/test/siteIdentity/browser_identity_web_controlled_blank.js b/browser/base/content/test/siteIdentity/browser_identity_web_controlled_blank.js
new file mode 100644
index 0000000000..01eca12178
--- /dev/null
+++ b/browser/base/content/test/siteIdentity/browser_identity_web_controlled_blank.js
@@ -0,0 +1,128 @@
+/*
+ * This work is marked with CC0 1.0. To view a copy of this license,
+ * visit http://creativecommons.org/publicdomain/zero/1.0
+ *
+ *
+ * Tests for correct behaviour of web-controlled about:blank pages in identity panel.
+ * Getting into a testable state is different enough that we test all the behaviors here
+ * separately, rather than with the usual (secure, insecure, etc.) cases
+ */
+
+const TEST_HOST = "example.com";
+const TEST_ORIGIN = "https://" + TEST_HOST;
+const TEST_PATH = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ TEST_ORIGIN
+);
+const LOCALHOST_PATH = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ "http://127.0.0.1:8888"
+);
+const TEST_URI = TEST_PATH + "test_web_controlled_blank.html";
+const DUMMY_URI = LOCALHOST_PATH + "dummy_page.html";
+
+// Open a new tab of `test_web_controlled_blank.html` and click
+// an element with a particular ID to open an about:blank popup
+// that is controlled by that first tab.
+//
+// Then test that the UI elements are all correct. And make sure
+// we don't have anything odd going on after navigating away in the
+// popup.
+async function web_controlled_about_blank_helper(id_to_click) {
+ // Open a new tab that will control about:blank pages
+ await BrowserTestUtils.withNewTab(TEST_URI, async browser => {
+ // Open a new popup by clicking the provided id_to_click from the content
+ let popupWindowPromise = BrowserTestUtils.waitForNewWindow();
+ await SpecialPowers.spawn(browser, [id_to_click], async function (id) {
+ content.document.getElementById(id).click();
+ });
+ let popupWindow = await popupWindowPromise;
+
+ // Validate the icon in the urlbar
+ let identityIcon = popupWindow.document.querySelector("#identity-icon");
+ let identityIconImageURL = popupWindow
+ .getComputedStyle(identityIcon)
+ .getPropertyValue("list-style-image");
+ is(
+ identityIconImageURL,
+ `url("chrome://global/skin/icons/info.svg")`,
+ "The identity icon has a correct image url."
+ );
+
+ // Open the identity panel
+ let popupShown = BrowserTestUtils.waitForEvent(
+ popupWindow,
+ "popupshown",
+ true,
+ event => event.target == popupWindow.gIdentityHandler._identityPopup
+ );
+ popupWindow.gIdentityHandler._identityIconBox.click();
+ info("Waiting for the Control Center to be shown");
+ await popupShown;
+ ok(
+ !popupWindow.gIdentityHandler._identityPopup.hidden,
+ "Control Center is visible"
+ );
+
+ // Validate that the predecessor is shown in the identity panel
+ ok(
+ popupWindow.gIdentityHandler._identityPopupMainViewHeaderLabel.textContent.includes(
+ TEST_HOST
+ ),
+ "Identity UI header shows the host of the predecessor"
+ );
+
+ // Validate that the correct message is displayed
+ is(
+ popupWindow.gIdentityHandler._identityPopup.getAttribute("connection"),
+ "associated",
+ "Identity UI shows associated message."
+ );
+
+ // Validate that there is no additional security info
+ let securityButton = popupWindow.gBrowser.ownerDocument.querySelector(
+ "#identity-popup-security-button"
+ );
+ is(
+ securityButton.disabled,
+ true,
+ "Security button has correct disabled state"
+ );
+
+ // Navigate away to a localhost page and make sure the identity icon changes
+ let loaded = BrowserTestUtils.browserLoaded(
+ popupWindow.gBrowser.selectedBrowser,
+ false,
+ DUMMY_URI
+ );
+ await SpecialPowers.spawn(
+ popupWindow.gBrowser.selectedBrowser,
+ [DUMMY_URI],
+ async function (uri) {
+ content.location = uri;
+ }
+ );
+ info("Waiting for the navigation to a dummy page to complete.");
+ await loaded;
+
+ identityIconImageURL = popupWindow.gBrowser.ownerGlobal
+ .getComputedStyle(identityIcon)
+ .getPropertyValue("list-style-image");
+ is(
+ identityIconImageURL,
+ `url("chrome://global/skin/icons/page-portrait.svg")`,
+ "The identity icon has a correct image url after navigating away."
+ );
+
+ // Exit this test, cleaning up as we go.
+ await BrowserTestUtils.closeWindow(popupWindow);
+ });
+}
+
+add_task(async function test_document_write() {
+ await web_controlled_about_blank_helper("document_write");
+});
+
+add_task(async function test_innerHTML() {
+ await web_controlled_about_blank_helper("innerhtml");
+});
diff --git a/browser/base/content/test/siteIdentity/test_web_controlled_blank.html b/browser/base/content/test/siteIdentity/test_web_controlled_blank.html
new file mode 100644
index 0000000000..35c1fd4ca2
--- /dev/null
+++ b/browser/base/content/test/siteIdentity/test_web_controlled_blank.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Bug 1813463: Web controlled about:blank</title>
+ </head>
+ <!--
+ This work is marked with CC0 1.0. To view a copy of this license,
+ visit http://creativecommons.org/publicdomain/zero/1.0
+ -->
+ <body>
+ <p><a href="#" id="document_write">document.write example</a></p>
+ <p><a href="#" id="innerhtml">innerHTML example</a></p>
+
+ <script>
+ document.getElementById("document_write").addEventListener("click", function (aEvent) {
+ aEvent.preventDefault();
+ let popup = window.open("about:blank", "_blank", "width=800,height=600,popup");
+ popup.document.write(`
+ <h1>check security info</h1>
+ <p>initial window.location = ${popup.location}</p>
+ <script>
+ document.write("<p>new window.location = " + window.location + "</p>")
+ <${"/"}script>
+ `);
+ });
+ document.getElementById("innerhtml").addEventListener("click", function (aEvent) {
+ aEvent.preventDefault();
+ let popup = window.open("about:blank", "_blank", "width=800,height=600,popup");
+ popup.stop();
+ popup.document.body.innerHTML = `
+ <h1>check security info</h1>
+ <p>window.location = ${popup.location}</p>`;
+ });
+ </script>
+ </body>
+</html>
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 6389e59e00..5e83443ec7 100644
--- a/browser/base/content/test/static/browser_all_files_referenced.js
+++ b/browser/base/content/test/static/browser_all_files_referenced.js
@@ -76,6 +76,9 @@ var gExceptionPaths = [
// Localization file added programatically in FeatureCallout.sys.mjs
"resource://app/localization/en-US/browser/featureCallout.ftl",
+ // Localization file added programatically in ContentAnalysis.sys.mjs
+ "resource://gre/localization/en-US/toolkit/contentanalysis/",
+
// CSS files are referenced inside JS in an html template
"chrome://browser/content/aboutlogins/components/",
];
@@ -277,6 +280,9 @@ var allowlist = [
// find the references)
{ file: "chrome://browser/content/screenshots/copied-notification.svg" },
+ // Bug 1875361
+ { file: "chrome://global/content/ml/SummarizerModel.sys.mjs" },
+
// toolkit/xre/MacRunFromDmgUtils.mm
{ file: "resource://gre/localization/en-US/toolkit/global/run-from-dmg.ftl" },
@@ -871,9 +877,6 @@ add_task(async function checkAllTheFiles() {
// Wait for all manifest to be parsed
await PerfTestHelpers.throttledMapPromises(manifestURIs, parseManifest);
- for (let jsm of Components.manager.getComponentJSMs()) {
- gReferencesFromCode.set(jsm, null);
- }
for (let esModule of Components.manager.getComponentESModules()) {
gReferencesFromCode.set(esModule, null);
}
diff --git a/browser/base/content/test/static/browser_misused_characters_in_strings.js b/browser/base/content/test/static/browser_misused_characters_in_strings.js
index 4191cc966e..c234f8107e 100644
--- a/browser/base/content/test/static/browser_misused_characters_in_strings.js
+++ b/browser/base/content/test/static/browser_misused_characters_in_strings.js
@@ -68,6 +68,28 @@ let gExceptionsList = [
key: "MathML_DeprecatedMathVariantWarning",
type: "single-quote",
},
+ // These error messages contain references to the CSP keywords 'unsafe-eval'/'wasm-unsafe-eval',
+ // and those keywords contain actual single-quotes: https://w3c.github.io/webappsec-csp/#grammardef-keyword-source
+ {
+ file: "csp.properties",
+ key: "CSPEvalScriptViolation",
+ type: "single-quote",
+ },
+ {
+ file: "csp.properties",
+ key: "CSPROEvalScriptViolation",
+ type: "single-quote",
+ },
+ {
+ file: "csp.properties",
+ key: "CSPWasmEvalScriptViolation",
+ type: "single-quote",
+ },
+ {
+ file: "csp.properties",
+ key: "CSPROWasmEvalScriptViolation",
+ type: "single-quote",
+ },
];
/**
diff --git a/browser/base/content/test/static/browser_parsable_css.js b/browser/base/content/test/static/browser_parsable_css.js
index b34ae7d9c1..602cc5a7e2 100644
--- a/browser/base/content/test/static/browser_parsable_css.js
+++ b/browser/base/content/test/static/browser_parsable_css.js
@@ -68,24 +68,6 @@ if (!Services.prefs.getBoolPref("layout.css.zoom.enabled")) {
});
}
-if (!Services.prefs.getBoolPref("layout.css.math-depth.enabled")) {
- // mathml.css UA sheet rule for math-depth.
- ignoreList.push({
- sourceName: /\b(scrollbars|mathml)\.css$/i,
- errorMessage: /Unknown property .*\bmath-depth\b/i,
- isFromDevTools: false,
- });
-}
-
-if (!Services.prefs.getBoolPref("layout.css.math-style.enabled")) {
- // mathml.css UA sheet rule for math-style.
- ignoreList.push({
- sourceName: /(?:res|gre-resources)\/mathml\.css$/i,
- errorMessage: /Unknown property .*\bmath-style\b/i,
- isFromDevTools: false,
- });
-}
-
if (!Services.prefs.getBoolPref("layout.css.scroll-anchoring.enabled")) {
ignoreList.push({
sourceName: /webconsole\.css$/i,
diff --git a/browser/base/content/test/tabPrompts/browser_beforeunload_urlbar.js b/browser/base/content/test/tabPrompts/browser_beforeunload_urlbar.js
index 52044b5874..1466e9ca86 100644
--- a/browser/base/content/test/tabPrompts/browser_beforeunload_urlbar.js
+++ b/browser/base/content/test/tabPrompts/browser_beforeunload_urlbar.js
@@ -9,11 +9,6 @@ const TEST_ROOT = getRootDirectory(gTestPath).replace(
"http://example.com"
);
-const CONTENT_PROMPT_SUBDIALOG = Services.prefs.getBoolPref(
- "prompts.contentPromptSubDialog",
- false
-);
-
add_task(async function test_beforeunload_stay_clears_urlbar() {
await SpecialPowers.pushPrefEnv({
set: [["dom.require_user_interaction_for_beforeunload", false]],
@@ -27,27 +22,10 @@ add_task(async function test_beforeunload_stay_clears_urlbar() {
gURLBar.value = inputValue.slice(0, -1);
EventUtils.sendString(inputValue.slice(-1));
- if (CONTENT_PROMPT_SUBDIALOG) {
- let promptOpenedPromise =
- BrowserTestUtils.promiseAlertDialogOpen("cancel");
- EventUtils.synthesizeKey("VK_RETURN");
- await promptOpenedPromise;
- await TestUtils.waitForTick();
- } else {
- let promptOpenedPromise = TestUtils.topicObserved(
- "tabmodal-dialog-loaded"
- );
- EventUtils.synthesizeKey("VK_RETURN");
- await promptOpenedPromise;
- let promptElement = browser.parentNode.querySelector("tabmodalprompt");
-
- // Click the cancel button
- promptElement.querySelector(".tabmodalprompt-button1").click();
- await TestUtils.waitForCondition(
- () => promptElement.parentNode == null,
- "tabprompt should be removed"
- );
- }
+ let promptOpenedPromise = BrowserTestUtils.promiseAlertDialogOpen("cancel");
+ EventUtils.synthesizeKey("VK_RETURN");
+ await promptOpenedPromise;
+ await TestUtils.waitForTick();
// Can't just compare directly with TEST_URL because the URL may be trimmed.
// Just need it to not be the example.org thing we typed in.
diff --git a/browser/base/content/test/tabPrompts/browser_confirmFolderUpload.js b/browser/base/content/test/tabPrompts/browser_confirmFolderUpload.js
index 62b0ed4f2b..52596095c4 100644
--- a/browser/base/content/test/tabPrompts/browser_confirmFolderUpload.js
+++ b/browser/base/content/test/tabPrompts/browser_confirmFolderUpload.js
@@ -88,7 +88,7 @@ async function testUploadPrompt(confirmUpload) {
await ContentTask.spawn(browser, { path }, args => {
let MockFilePicker = content.SpecialPowers.MockFilePicker;
MockFilePicker.init(
- content,
+ content.browsingContext,
"A Mock File Picker",
content.SpecialPowers.Ci.nsIFilePicker.modeGetFolder
);
diff --git a/browser/base/content/test/tabPrompts/browser_contentOrigins.js b/browser/base/content/test/tabPrompts/browser_contentOrigins.js
index 10c8809490..2bf4ba6039 100644
--- a/browser/base/content/test/tabPrompts/browser_contentOrigins.js
+++ b/browser/base/content/test/tabPrompts/browser_contentOrigins.js
@@ -129,11 +129,7 @@ async function checkDialog(
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
- set: [
- ["prompts.contentPromptSubDialog", true],
- ["prompts.modalType.httpAuth", Ci.nsIPrompt.MODAL_TYPE_TAB],
- ["prompts.tabChromePromptSubDialog", true],
- ],
+ set: [["prompts.modalType.httpAuth", Ci.nsIPrompt.MODAL_TYPE_TAB]],
});
});
diff --git a/browser/base/content/test/tabPrompts/browser_multiplePrompts.js b/browser/base/content/test/tabPrompts/browser_multiplePrompts.js
index 597b7dfd6f..65c8b3eff4 100644
--- a/browser/base/content/test/tabPrompts/browser_multiplePrompts.js
+++ b/browser/base/content/test/tabPrompts/browser_multiplePrompts.js
@@ -1,13 +1,7 @@
"use strict";
-const CONTENT_PROMPT_SUBDIALOG = Services.prefs.getBoolPref(
- "prompts.contentPromptSubDialog",
- false
-);
-
/**
- * Goes through a stacked series of dialogs opened with
- * CONTENT_PROMPT_SUBDIALOG set to true, and ensures that
+ * Goes through a stacked series of dialogs and ensures that
* the oldest one is front-most and has the right type. It
* then closes the oldest to newest dialog.
*
@@ -58,64 +52,6 @@ async function closeDialogs(tab, dialogCount) {
is(dialogs.length, 0, "Dialogs should all be dismissed.");
}
-/**
- * Goes through a stacked series of tabprompt modals opened with
- * CONTENT_PROMPT_SUBDIALOG set to false, and ensures that
- * the oldest one is front-most and has the right type. It also
- * ensures that the other tabprompt modals are hidden. It
- * then closes the oldest to newest dialog.
- *
- * @param {Element} tab The <tab> that has had tabprompt modals opened
- * for it.
- * @param {Number} promptCount How many modals we expected to have been
- * opened.
- *
- * @return {Promise}
- * @resolves {undefined} Once the modals have all been closed.
- */
-async function closeTabModals(tab, promptCount) {
- let promptElementsCount = promptCount;
- while (promptElementsCount--) {
- let promptElements =
- tab.linkedBrowser.parentNode.querySelectorAll("tabmodalprompt");
- is(
- promptElements.length,
- promptElementsCount + 1,
- "There should be " + (promptElementsCount + 1) + " prompt(s)."
- );
- // The oldest should be the first.
- let i = 0;
-
- for (let promptElement of promptElements) {
- let prompt = tab.linkedBrowser.tabModalPromptBox.getPrompt(promptElement);
- let expectedType = ["alert", "prompt", "confirm"][i % 3];
- is(
- prompt.Dialog.args.text,
- expectedType + " countdown #" + i,
- "The #" + i + " alert should be labelled as such."
- );
- if (i !== promptElementsCount) {
- is(prompt.element.hidden, true, "This prompt should be hidden.");
- i++;
- continue;
- }
-
- is(prompt.element.hidden, false, "The last prompt should not be hidden.");
- prompt.onButtonClick(0);
-
- // The click is handled async; wait for an event loop turn for that to
- // happen.
- await new Promise(function (resolve) {
- Services.tm.dispatchToMainThread(resolve);
- });
- }
- }
-
- let promptElements =
- tab.linkedBrowser.parentNode.querySelectorAll("tabmodalprompt");
- is(promptElements.length, 0, "Prompts should all be dismissed.");
-}
-
/*
* This test triggers multiple alerts on one single tab, because it"s possible
* for web content to do so. The behavior is described in bug 1266353.
@@ -161,11 +97,7 @@ add_task(async function () {
await promptsOpenedPromise;
- if (CONTENT_PROMPT_SUBDIALOG) {
- await closeDialogs(tab, PROMPTCOUNT);
- } else {
- await closeTabModals(tab, PROMPTCOUNT);
- }
+ await closeDialogs(tab, PROMPTCOUNT);
BrowserTestUtils.removeTab(tab);
});
diff --git a/browser/base/content/test/tabPrompts/browser_openPromptInBackgroundTab.js b/browser/base/content/test/tabPrompts/browser_openPromptInBackgroundTab.js
index 6b116b71f9..2fa3752881 100644
--- a/browser/base/content/test/tabPrompts/browser_openPromptInBackgroundTab.js
+++ b/browser/base/content/test/tabPrompts/browser_openPromptInBackgroundTab.js
@@ -22,118 +22,7 @@ registerCleanupFunction(function () {
* the user to enable this automatically re-selecting. We then check that
* checking the checkbox does actually enable that behaviour.
*/
-add_task(async function test_old_modal_ui() {
- // We're intentionally testing the old modal mechanism, so disable the new one.
- await SpecialPowers.pushPrefEnv({
- set: [["prompts.contentPromptSubDialog", false]],
- });
-
- let firstTab = gBrowser.selectedTab;
- // load page that opens prompt when page is hidden
- let openedTab = await BrowserTestUtils.openNewForegroundTab(
- gBrowser,
- pageWithAlert,
- true
- );
- let openedTabGotAttentionPromise = BrowserTestUtils.waitForAttribute(
- "attention",
- openedTab
- );
- // switch away from that tab again - this triggers the alert.
- await BrowserTestUtils.switchTab(gBrowser, firstTab);
- // ... but that's async on e10s...
- await openedTabGotAttentionPromise;
- // check for attention attribute
- is(
- openedTab.hasAttribute("attention"),
- true,
- "Tab with alert should have 'attention' attribute."
- );
- ok(!openedTab.selected, "Tab with alert should not be selected");
-
- // switch tab back, and check the checkbox is displayed:
- await BrowserTestUtils.switchTab(gBrowser, openedTab);
- // check the prompt is there, and the extra row is present
- let promptElements =
- openedTab.linkedBrowser.parentNode.querySelectorAll("tabmodalprompt");
- is(promptElements.length, 1, "There should be 1 prompt");
- let ourPromptElement = promptElements[0];
- let checkbox = ourPromptElement.querySelector(
- "checkbox[label*='example.com']"
- );
- ok(checkbox, "The checkbox should be there");
- ok(!checkbox.checked, "Checkbox shouldn't be checked");
- // tick box and accept dialog
- checkbox.checked = true;
- let ourPrompt =
- openedTab.linkedBrowser.tabModalPromptBox.getPrompt(ourPromptElement);
- ourPrompt.onButtonClick(0);
- // Wait for that click to actually be handled completely.
- await new Promise(function (resolve) {
- Services.tm.dispatchToMainThread(resolve);
- });
- // check permission is set
- is(
- Services.perms.ALLOW_ACTION,
- PermissionTestUtils.testPermission(pageWithAlert, "focus-tab-by-prompt"),
- "Tab switching should now be allowed"
- );
-
- // Check if the control center shows the correct permission.
- let shown = BrowserTestUtils.waitForEvent(
- window,
- "popupshown",
- true,
- event => event.target == gPermissionPanel._permissionPopup
- );
- gPermissionPanel._identityPermissionBox.click();
- await shown;
- let labelText = SitePermissions.getPermissionLabel("focus-tab-by-prompt");
- let permissionsList = document.getElementById(
- "permission-popup-permission-list"
- );
- let label = permissionsList.querySelector(
- ".permission-popup-permission-label"
- );
- is(label.textContent, labelText);
- gPermissionPanel._permissionPopup.hidePopup();
-
- // Check if the identity icon signals granted permission.
- ok(
- gPermissionPanel._identityPermissionBox.hasAttribute("hasPermissions"),
- "identity-box signals granted permissions"
- );
-
- let openedTabSelectedPromise = BrowserTestUtils.waitForAttribute(
- "selected",
- openedTab,
- "true"
- );
- // switch to other tab again
- await BrowserTestUtils.switchTab(gBrowser, firstTab);
-
- // This is sync in non-e10s, but in e10s we need to wait for this, so yield anyway.
- // Note that the switchTab promise doesn't actually guarantee anything about *which*
- // tab ends up as selected when its event fires, so using that here wouldn't work.
- await openedTabSelectedPromise;
- // should be switched back
- ok(openedTab.selected, "Ta-dah, the other tab should now be selected again!");
-
- // In e10s, with the conformant promise scheduling, we have to wait for next tick
- // to ensure that the prompt is open before removing the opened tab, because the
- // promise callback of 'openedTabSelectedPromise' could be done at the middle of
- // RemotePrompt.openTabPrompt() while 'DOMModalDialogClosed' event is fired.
- await TestUtils.waitForTick();
-
- BrowserTestUtils.removeTab(openedTab);
-});
-
-add_task(async function test_new_modal_ui() {
- // We're intentionally testing the new modal mechanism, so make sure it's enabled.
- await SpecialPowers.pushPrefEnv({
- set: [["prompts.contentPromptSubDialog", true]],
- });
-
+add_task(async function test_modal_ui() {
// Make sure we clear the focus tab permission set in the previous test
PermissionTestUtils.remove(pageWithAlert, "focus-tab-by-prompt");
diff --git a/browser/base/content/test/tabdialogs/browser_tabdialogbox_content_prompts.js b/browser/base/content/test/tabdialogs/browser_tabdialogbox_content_prompts.js
index 50b94e1a36..5cac19f6af 100644
--- a/browser/base/content/test/tabdialogs/browser_tabdialogbox_content_prompts.js
+++ b/browser/base/content/test/tabdialogs/browser_tabdialogbox_content_prompts.js
@@ -3,7 +3,6 @@
"use strict";
-const CONTENT_PROMPT_PREF = "prompts.contentPromptSubDialog";
const TEST_ROOT_CHROME = getRootDirectory(gTestPath);
const TEST_DIALOG_PATH = TEST_ROOT_CHROME + "subdialog.xhtml";
@@ -41,13 +40,6 @@ var commonDialogsBundle = Services.strings.createBundle(
"chrome://global/locale/commonDialogs.properties"
);
-// Setup.
-add_setup(async function () {
- await SpecialPowers.pushPrefEnv({
- set: [[CONTENT_PROMPT_PREF, true]],
- });
-});
-
/**
* Test that a manager for content prompts is added to tab dialog box.
*/
diff --git a/browser/base/content/test/tabs/browser.toml b/browser/base/content/test/tabs/browser.toml
index 8008d70f0c..1b4a6900bf 100644
--- a/browser/base/content/test/tabs/browser.toml
+++ b/browser/base/content/test/tabs/browser.toml
@@ -236,7 +236,6 @@ support-files = [
]
["browser_overflowScroll.js"]
-fail-if = ["a11y_checks"] # Bugs 1854233 and 1873049 scrollbutton-down/up are not labeled
skip-if = [
"win11_2009", # Bug 1797751
]
diff --git a/browser/base/content/test/tabs/browser_close_during_beforeunload.js b/browser/base/content/test/tabs/browser_close_during_beforeunload.js
index 32bbb65b62..035884d713 100644
--- a/browser/base/content/test/tabs/browser_close_during_beforeunload.js
+++ b/browser/base/content/test/tabs/browser_close_during_beforeunload.js
@@ -4,14 +4,7 @@
// beforeunload confirmation ignores the beforeunload listener and
// unblocks the original close call.
-const CONTENT_PROMPT_SUBDIALOG = Services.prefs.getBoolPref(
- "prompts.contentPromptSubDialog",
- false
-);
-
-const DIALOG_TOPIC = CONTENT_PROMPT_SUBDIALOG
- ? "common-dialog-loaded"
- : "tabmodal-dialog-loaded";
+const DIALOG_TOPIC = "common-dialog-loaded";
add_task(async function () {
await SpecialPowers.pushPrefEnv({
diff --git a/browser/base/content/test/tabs/browser_multiselect_tabs_bookmark.js b/browser/base/content/test/tabs/browser_multiselect_tabs_bookmark.js
index a24e72c0bb..cd3728edcd 100644
--- a/browser/base/content/test/tabs/browser_multiselect_tabs_bookmark.js
+++ b/browser/base/content/test/tabs/browser_multiselect_tabs_bookmark.js
@@ -48,11 +48,6 @@ add_task(async function test() {
false,
"Bookmark Selected Tabs is hidden"
);
- is(
- PlacesCommandHook.uniqueSelectedPages.length,
- 1,
- "No more than one unique selected page"
- );
info("Add a different page to selection");
let tab4 = await addTab_example_com();
@@ -69,11 +64,6 @@ add_task(async function test() {
false,
"Bookmark Selected Tabs is hidden"
);
- is(
- PlacesCommandHook.uniqueSelectedPages.length,
- 2,
- "More than one unique selected page"
- );
for (let tab of [tab1, tab2, tab3, 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 e3dd1b6842..718afbb940 100644
--- a/browser/base/content/test/tabs/browser_tab_preview.js
+++ b/browser/base/content/test/tabs/browser_tab_preview.js
@@ -34,7 +34,7 @@ add_setup(async function () {
set: [
["browser.tabs.cardPreview.enabled", true],
["browser.tabs.cardPreview.showThumbnails", false],
- ["browser.tabs.cardPreview.delayMs", 0],
+ ["ui.tooltip.delay_ms", 0],
],
});
});
@@ -46,7 +46,7 @@ add_setup(async function () {
* 2. Tab preview card shows the correct preview for the tab being hovered
* 3. Tab preview card is dismissed when the mouse leaves the tab bar
*/
-add_task(async () => {
+add_task(async function hoverTests() {
const tabUrl1 =
"data:text/html,<html><head><title>First New Tab</title></head><body>Hello</body></html>";
const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, tabUrl1);
@@ -85,6 +85,11 @@ add_task(async () => {
BrowserTestUtils.removeTab(tab1);
BrowserTestUtils.removeTab(tab2);
+
+ // Move the mouse outside of the tab strip.
+ EventUtils.synthesizeMouseAtCenter(document.documentElement, {
+ type: "mouseover",
+ });
});
/**
@@ -92,7 +97,7 @@ add_task(async () => {
* when browser.tabs.cardPreview.showThumbnails is set to true,
* while the currently selected tab never displays a thumbnail in its preview.
*/
-add_task(async () => {
+add_task(async function thumbnailTests() {
await SpecialPowers.pushPrefEnv({
set: [["browser.tabs.cardPreview.showThumbnails", true]],
});
@@ -120,15 +125,28 @@ add_task(async () => {
"Tab2 (selected) does not contain thumbnail"
);
+ const previewHidden = BrowserTestUtils.waitForEvent(
+ document.getElementById("tabbrowser-tab-preview"),
+ "previewhidden"
+ );
+
BrowserTestUtils.removeTab(tab1);
BrowserTestUtils.removeTab(tab2);
await SpecialPowers.popPrefEnv();
+
+ // Removing the tab should close the preview.
+ await previewHidden;
+
+ // Move the mouse outside of the tab strip.
+ EventUtils.synthesizeMouseAtCenter(document.documentElement, {
+ type: "mouseover",
+ });
});
/**
* Wheel events at the document-level of the window should hide the preview.
*/
-add_task(async () => {
+add_task(async function wheelTests() {
const tabUrl1 = "about:blank";
const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, tabUrl1);
const tabUrl2 = "about:blank";
@@ -141,14 +159,49 @@ add_task(async () => {
document.getElementById("tabbrowser-tab-preview"),
"previewhidden"
);
- EventUtils.synthesizeMouse(tabs, 0, tabs.outerHeight + 1, {
- wheel: true,
- deltaY: -1,
- deltaMode: WheelEvent.DOM_DELTA_LINE,
- });
+
+ // Copied from apz_test_native_event_utils.js
+ let message = 0;
+ switch (AppConstants.platform) {
+ case "win":
+ message = 0x020a;
+ break;
+ case "linux":
+ message = 4;
+ break;
+ case "macosx":
+ message = 1;
+ break;
+ }
+
+ let rect = tabs.getBoundingClientRect();
+ let screenRect = window.windowUtils.toScreenRect(
+ rect.x,
+ rect.y,
+ rect.width,
+ rect.height
+ );
+ window.windowUtils.sendNativeMouseScrollEvent(
+ screenRect.left,
+ screenRect.bottom,
+ message,
+ 0,
+ 3,
+ 0,
+ 0,
+ Ci.nsIDOMWindowUtils.MOUSESCROLL_SCROLL_LINES,
+ tabs,
+ null
+ );
+
await previewHidden;
BrowserTestUtils.removeTab(tab1);
BrowserTestUtils.removeTab(tab2);
await SpecialPowers.popPrefEnv();
+
+ // Move the mouse outside of the tab strip.
+ EventUtils.synthesizeMouseAtCenter(document.documentElement, {
+ type: "mouseover",
+ });
});
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 a2fdc34db3..7f8f256e14 100644
--- a/browser/base/content/test/webextensions/browser_permissions_local_file.js
+++ b/browser/base/content/test/webextensions/browser_permissions_local_file.js
@@ -10,7 +10,7 @@ async function installFile(filename) {
file.leafName = filename;
let MockFilePicker = SpecialPowers.MockFilePicker;
- MockFilePicker.init(window);
+ MockFilePicker.init(window.browsingContext);
MockFilePicker.setFiles([file]);
MockFilePicker.afterOpenCallback = MockFilePicker.cleanup;
diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js
index ae9c1d0a9a..5967c878b3 100644
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -431,8 +431,7 @@ async function openPreferences(paneID, extraArgs) {
}
}
}
- let preferencesURL =
- "about:preferences" +
+ let preferencesURLSuffix =
(params ? "?" + params : "") +
(friendlyCategoryName ? "#" + friendlyCategoryName : "");
let newLoad = true;
@@ -444,7 +443,7 @@ async function openPreferences(paneID, extraArgs) {
let supportsStringPrefURL = Cc[
"@mozilla.org/supports-string;1"
].createInstance(Ci.nsISupportsString);
- supportsStringPrefURL.data = preferencesURL;
+ supportsStringPrefURL.data = "about:preferences" + preferencesURLSuffix;
windowArguments.appendElement(supportsStringPrefURL);
win = Services.ww.openWindow(
@@ -458,11 +457,28 @@ async function openPreferences(paneID, extraArgs) {
let shouldReplaceFragment = friendlyCategoryName
? "whenComparingAndReplace"
: "whenComparing";
- newLoad = !win.switchToTabHavingURI(preferencesURL, true, {
- ignoreFragment: shouldReplaceFragment,
- replaceQueryString: true,
- triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
- });
+ newLoad = !win.switchToTabHavingURI(
+ "about:settings" + preferencesURLSuffix,
+ false,
+ {
+ ignoreFragment: shouldReplaceFragment,
+ replaceQueryString: true,
+ triggeringPrincipal:
+ Services.scriptSecurityManager.getSystemPrincipal(),
+ }
+ );
+ if (newLoad) {
+ newLoad = !win.switchToTabHavingURI(
+ "about:preferences" + preferencesURLSuffix,
+ true,
+ {
+ ignoreFragment: shouldReplaceFragment,
+ replaceQueryString: true,
+ triggeringPrincipal:
+ Services.scriptSecurityManager.getSystemPrincipal(),
+ }
+ );
+ }
browser = win.gBrowser.selectedBrowser;
}
@@ -533,11 +549,6 @@ function buildHelpMenu() {
if (typeof gSafeBrowsing != "undefined") {
gSafeBrowsing.setReportPhishingMenu();
}
-
- if (NimbusFeatures.deviceMigration.getVariable("helpMenuHidden")) {
- let helpMenuItem = document.getElementById("helpSwitchDevice");
- helpMenuItem.hidden = true;
- }
}
function isElementVisible(aElement) {
diff --git a/browser/base/content/webext-panels.xhtml b/browser/base/content/webext-panels.xhtml
index 902fa7e7b3..f421d9bf80 100644
--- a/browser/base/content/webext-panels.xhtml
+++ b/browser/base/content/webext-panels.xhtml
@@ -28,6 +28,7 @@
<html:link rel="localization" href="toolkit/branding/brandings.ftl"/>
<html:link rel="localization" href="toolkit/global/textActions.ftl"/>
<html:link rel="localization" href="browser/browserContext.ftl"/>
+ <html:link rel="localization" href="preview/select-translations.ftl"/>
</linkset>
<commandset id="mainCommandset">