diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:35:37 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:35:37 +0000 |
commit | a90a5cba08fdf6c0ceb95101c275108a152a3aed (patch) | |
tree | 532507288f3defd7f4dcf1af49698bcb76034855 /toolkit/content | |
parent | Adding debian version 126.0.1-1. (diff) | |
download | firefox-a90a5cba08fdf6c0ceb95101c275108a152a3aed.tar.xz firefox-a90a5cba08fdf6c0ceb95101c275108a152a3aed.zip |
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/content')
42 files changed, 683 insertions, 552 deletions
diff --git a/toolkit/content/aboutLogging.js b/toolkit/content/aboutLogging.js index 360ab366e1..f2f4cabc62 100644 --- a/toolkit/content/aboutLogging.js +++ b/toolkit/content/aboutLogging.js @@ -114,7 +114,7 @@ const gLoggingPresets = { }, "media-playback": { modules: - "HTMLMediaElement:4,HTMLMediaElementEvents:4,cubeb:5,PlatformDecoderModule:5,AudioSink:5,AudioSinkWrapper:5,MediaDecoderStateMachine:4,MediaDecoder:4,MediaFormatReader:5,GMP:5", + "HTMLMediaElement:4,HTMLMediaElementEvents:4,cubeb:5,PlatformDecoderModule:5,AudioSink:5,AudioSinkWrapper:5,MediaDecoderStateMachine:4,MediaDecoder:4,MediaFormatReader:5,GMP:5,EME:5", l10nIds: { label: "about-logging-preset-media-playback-label", description: "about-logging-preset-media-playback-description", diff --git a/toolkit/content/aboutNetError.mjs b/toolkit/content/aboutNetError.mjs index 1c733d5dbb..935111dcca 100644 --- a/toolkit/content/aboutNetError.mjs +++ b/toolkit/content/aboutNetError.mjs @@ -396,7 +396,8 @@ function initPage() { }); longDesc = null; - document.getElementById("openInNewWindowContainer").hidden = false; + document.getElementById("openInNewWindowContainer").hidden = + RPMGetBoolPref("security.xfocsp.hideOpenInNewWindow"); const openInNewWindowButton = document.getElementById( "openInNewWindowButton" diff --git a/toolkit/content/aboutTelemetry.js b/toolkit/content/aboutTelemetry.js index 45a8488820..9cf3c3320d 100644 --- a/toolkit/content/aboutTelemetry.js +++ b/toolkit/content/aboutTelemetry.js @@ -352,6 +352,12 @@ var PingPicker = { }, _updateCurrentPingData() { + TelemetryController.ensureInitialized().then(() => + this._doUpdateCurrentPingData() + ); + }, + + _doUpdateCurrentPingData() { const subsession = document.getElementById("show-subsession-data").checked; let ping = TelemetryController.getCurrentPingData(subsession); if (!ping) { diff --git a/toolkit/content/customElements.js b/toolkit/content/customElements.js index ef58963a02..132b069326 100644 --- a/toolkit/content/customElements.js +++ b/toolkit/content/customElements.js @@ -791,7 +791,6 @@ ["button-group", "chrome://global/content/elements/named-deck.js"], ["findbar", "chrome://global/content/elements/findbar.js"], ["menulist", "chrome://global/content/elements/menulist.js"], - ["message-bar", "chrome://global/content/elements/message-bar.js"], ["named-deck", "chrome://global/content/elements/named-deck.js"], ["named-deck-button", "chrome://global/content/elements/named-deck.js"], ["panel-list", "chrome://global/content/elements/panel-list.js"], @@ -806,49 +805,32 @@ "chrome://global/content/elements/autocomplete-input.js", ], ["editor", "chrome://global/content/elements/editor.js"], + ["moz-button", "chrome://global/content/elements/moz-button.mjs"], + [ + "moz-button-group", + "chrome://global/content/elements/moz-button-group.mjs", + ], + ["moz-card", "chrome://global/content/elements/moz-card.mjs"], + ["moz-five-star", "chrome://global/content/elements/moz-five-star.mjs"], + [ + "moz-message-bar", + "chrome://global/content/elements/moz-message-bar.mjs", + ], + ["moz-page-nav", "chrome://global/content/elements/moz-page-nav.mjs"], + [ + "moz-support-link", + "chrome://global/content/elements/moz-support-link.mjs", + ], + ["moz-toggle", "chrome://global/content/elements/moz-toggle.mjs"], ]) { customElements.setElementCreationCallback(tag, () => { - Services.scriptloader.loadSubScript(script, window); + if (script.endsWith(".mjs")) { + ChromeUtils.importESModule(script, { global: "current" }); + } else { + Services.scriptloader.loadSubScript(script, window); + } }); } - // Bug 1813077: This is a workaround until Bug 1803810 lands - // which will give us the ability to load ESMs synchronously - // like the previous Services.scriptloader.loadSubscript() function - function importCustomElementFromESModule(name) { - switch (name) { - case "moz-button": - return import("chrome://global/content/elements/moz-button.mjs"); - case "moz-button-group": - return import( - "chrome://global/content/elements/moz-button-group.mjs" - ); - case "moz-message-bar": - return import("chrome://global/content/elements/moz-message-bar.mjs"); - case "moz-support-link": - return import( - "chrome://global/content/elements/moz-support-link.mjs" - ); - case "moz-toggle": - return import("chrome://global/content/elements/moz-toggle.mjs"); - case "moz-card": - return import("chrome://global/content/elements/moz-card.mjs"); - } - throw new Error(`Unknown custom element name (${name})`); - } - - /* - This function explicitly returns null so that there is no confusion - about which custom elements from ES Modules have been loaded. - */ - window.ensureCustomElements = function (...elementNames) { - return Promise.all( - elementNames - .filter(name => !customElements.get(name)) - .map(name => importCustomElementFromESModule(name)) - ) - .then(() => null) - .catch(console.error); - }; // Immediately load the following elements for (let script of [ diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn index d08037a84a..e555936a73 100644 --- a/toolkit/content/jar.mn +++ b/toolkit/content/jar.mn @@ -87,8 +87,6 @@ toolkit.jar: content/global/elements/findbar.js (widgets/findbar.js) content/global/elements/editor.js (widgets/editor.js) content/global/elements/general.js (widgets/general.js) - content/global/elements/message-bar.css (widgets/message-bar.css) - content/global/elements/message-bar.js (widgets/message-bar.js) content/global/elements/menu.js (widgets/menu.js) content/global/elements/menupopup.js (widgets/menupopup.js) content/global/elements/moz-button.css (widgets/moz-button/moz-button.css) diff --git a/toolkit/content/license.html b/toolkit/content/license.html index fe489f74d1..3f05da0118 100644 --- a/toolkit/content/license.html +++ b/toolkit/content/license.html @@ -1496,6 +1496,9 @@ licences. #ifdef MOZ_JXL <code>third_party/highway/</code><br/> #endif +#ifdef MOZ_PERFETTO + <code>third_party/perfetto/</code><br/> +#endif </p> <pre> @@ -3600,7 +3603,6 @@ SOFTWARE. <li><code>devtools/shared/natural-sort.js</code></li> <li><code>devtools/shared/node-properties/node-properties.js</code></li> <li><code>third_party/rust/ordered-float</code></li> - <li><code>third_party/rust/owning_ref</code></li> <li><code>third_party/rust/phf</code>, <code>third_party/rust/phf_codegen</code>, <code>third_party/rust/phf_generator</code>, and @@ -3625,6 +3627,7 @@ SOFTWARE. <li><code>third_party/rust/synstructure</code></li> <li><code>third_party/rust/void</code></li> <li><code>js/src/zydis</code> (unless otherwise specified)</li> + <li><code>js/src/vm/Float16.h</code>(the code contained in the half namespace)</li> </ul> See the individual LICENSE files or headers for copyright owners.</p> diff --git a/toolkit/content/preferencesBindings.js b/toolkit/content/preferencesBindings.js index b2e4070cf5..3dba0bed1e 100644 --- a/toolkit/content/preferencesBindings.js +++ b/toolkit/content/preferencesBindings.js @@ -381,6 +381,11 @@ const Preferences = (window.Preferences = (function () { if (this.locked) { aElement.disabled = true; } + if (aElement.labels?.length) { + for (let label of aElement.labels) { + label.toggleAttribute("disabled", this.locked); + } + } if (!this.isElementEditable(aElement)) { return; diff --git a/toolkit/content/tests/browser/browser_bug1693577.js b/toolkit/content/tests/browser/browser_bug1693577.js index 712749dc89..b85b9f13de 100644 --- a/toolkit/content/tests/browser/browser_bug1693577.js +++ b/toolkit/content/tests/browser/browser_bug1693577.js @@ -12,7 +12,7 @@ add_task(async function test_search_input_popupshowing() { let sidebar = document.getElementById("sidebar"); let loadPromise = BrowserTestUtils.waitForEvent(sidebar, "load", true); - SidebarUI.toggle("viewBookmarksSidebar"); + SidebarController.toggle("viewBookmarksSidebar"); await loadPromise; let inputField = @@ -45,5 +45,5 @@ add_task(async function test_search_input_popupshowing() { popup.hidePopup(); await popuphidden; - SidebarUI.toggle("viewBookmarksSidebar"); + SidebarController.toggle("viewBookmarksSidebar"); }); diff --git a/toolkit/content/tests/chrome/chrome.toml b/toolkit/content/tests/chrome/chrome.toml index 986822ac48..e037f45ecf 100644 --- a/toolkit/content/tests/chrome/chrome.toml +++ b/toolkit/content/tests/chrome/chrome.toml @@ -51,7 +51,6 @@ support-files = [ ] prefs = [ "gfx.font_rendering.fallback.async=false", - "widget.non-native-theme.enabled=false", ] ["test_about_networking.html"] diff --git a/toolkit/content/tests/chrome/file_editor_with_autocomplete.js b/toolkit/content/tests/chrome/file_editor_with_autocomplete.js index acf2c9e9df..0068440785 100644 --- a/toolkit/content/tests/chrome/file_editor_with_autocomplete.js +++ b/toolkit/content/tests/chrome/file_editor_with_autocomplete.js @@ -84,6 +84,10 @@ nsDoTestsForEditorWithAutoComplete.prototype = { Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH ); }); + if (test.popup) { + await waitForCondition(() => this._controller.input.popupOpen); + } + this._target.removeEventListener("beforeinput", onBeforeInput); this._target.removeEventListener("input", onInput); this._checkResult(test, beforeInputEvents, inputEvents); diff --git a/toolkit/content/tests/chrome/test_autocomplete_with_composition_on_input.html b/toolkit/content/tests/chrome/test_autocomplete_with_composition_on_input.html index fbcd44e830..fd484a93d1 100644 --- a/toolkit/content/tests/chrome/test_autocomplete_with_composition_on_input.html +++ b/toolkit/content/tests/chrome/test_autocomplete_with_composition_on_input.html @@ -27,7 +27,6 @@ function runTests() { .QueryInterface(Ci.nsIAutoCompleteInput); var originalFormFillTimeout = formFillController.timeout; - SpecialPowers.attachFormFillControllerTo(window); var target = document.getElementById("input"); // Register a word to the form history. @@ -53,7 +52,6 @@ function runTests() { function() { return target.value; }, function() { formFillController.timeout = originalFormFillTimeout; - SpecialPowers.detachFormFillControllerFrom(window); SimpleTest.finish(); }); }); diff --git a/toolkit/content/tests/chrome/test_editor_for_input_with_autocomplete.html b/toolkit/content/tests/chrome/test_editor_for_input_with_autocomplete.html index 91f0f159b4..f2786d47be 100644 --- a/toolkit/content/tests/chrome/test_editor_for_input_with_autocomplete.html +++ b/toolkit/content/tests/chrome/test_editor_for_input_with_autocomplete.html @@ -51,7 +51,6 @@ async function runTests() { .QueryInterface(Ci.nsIAutoCompleteInput); var originalFormFillTimeout = formFillController.timeout; - SpecialPowers.attachFormFillControllerTo(window); var target = document.getElementById("input"); // Register a word to the form history. @@ -71,7 +70,6 @@ async function runTests() { await tests2.run(); formFillController.timeout = originalFormFillTimeout; - SpecialPowers.detachFormFillControllerFrom(window); SimpleTest.finish(); } diff --git a/toolkit/content/tests/chrome/window_largemenu.xhtml b/toolkit/content/tests/chrome/window_largemenu.xhtml index 8e6b6718b4..413ab248bc 100644 --- a/toolkit/content/tests/chrome/window_largemenu.xhtml +++ b/toolkit/content/tests/chrome/window_largemenu.xhtml @@ -336,14 +336,18 @@ function testPopupMovement() var marginTop = parseFloat(getComputedStyle(popup).marginTop); var panelIsTop = SpecialPowers.getBoolPref("ui.panel.default_level_parent"); - var overlapOSChrome = !platformIsMac() && (!isPanelTest || panelIsTop); + var overlapOSChrome = canOverlapOSChrome() && (!isPanelTest || panelIsTop); popup.moveTo(1, 1); [screenX, screenY] = getScreenXY(popup); var expectedx = 1, expectedy = 1; if (!overlapOSChrome) { - if (screen.availLeft >= 1) expectedx = screen.availLeft; - if (screen.availTop >= 1) expectedy = screen.availTop; + if (screen.availLeft >= 1) { + expectedx = screen.availLeft + marginLeft; + } + if (screen.availTop >= 1) { + expectedy = screen.availTop + marginTop; + } } is(screenX, expectedx, gTests[gTestIndex] + " (1, 1) x"); is(screenY, expectedy, gTests[gTestIndex] + " (1, 1) y"); @@ -398,6 +402,11 @@ function platformIsMac() return navigator.platform.indexOf("Mac") > -1; } +function canOverlapOSChrome() +{ + return navigator.platform.startsWith("Win"); +} + window.arguments[0].SimpleTest.waitForFocus(runTests, window); ]]> diff --git a/toolkit/content/tests/widgets/mochitest.toml b/toolkit/content/tests/widgets/mochitest.toml index efd86f1208..f5bc0505bf 100644 --- a/toolkit/content/tests/widgets/mochitest.toml +++ b/toolkit/content/tests/widgets/mochitest.toml @@ -96,6 +96,8 @@ skip-if = [ ["test_videocontrols_size.html"] +["test_videocontrols_src_change.html"] + ["test_videocontrols_standalone.html"] skip-if = [ "os == 'linux'", # bug 1804621 diff --git a/toolkit/content/tests/widgets/test_moz_button.html b/toolkit/content/tests/widgets/test_moz_button.html index a849ccc956..0e64f939dc 100644 --- a/toolkit/content/tests/widgets/test_moz_button.html +++ b/toolkit/content/tests/widgets/test_moz_button.html @@ -17,6 +17,33 @@ } </style> <script> + const { AddonManager } = ChromeUtils.importESModule( + "resource://gre/modules/AddonManager.sys.mjs" + ); + // Always run tests with the light theme for consistency and to avoid from false + // test passes arising from the fact that --icon-color and --button-text-color + // have the same value in the dark theme. + add_setup(async function () { + // Developer Edition enables the wrong theme by default. Make sure + // the ordinary default theme is enabled. + let theme = await AddonManager.getAddonByID("default-theme@mozilla.org"); + await theme.enable(); + + await SpecialPowers.pushPrefEnv({ + set: [ + ["ui.systemUsesDarkTheme", 0], + ], + }); + // Triggers a refresh to ensure new theme applied. + await new Promise(resolve => requestAnimationFrame(resolve)); + ok(window.matchMedia("(prefers-color-scheme: light)").matches, "Light theme is active."); + + // Move mouse to the bottom of the test frame to prevent hover on buttons. + let mouseTrap = document.getElementById("mouse-trap"); + await synthesizeMouseAtCenter(mouseTrap, { type: "mousemove" }); + ok(mouseTrap.matches(":hover"), "The mouse trap is hovered"); + }); + function normalizeColor(val, computedStyles) { if (val.includes("currentColor")) { val = val.replaceAll("currentColor", computedStyles.color); @@ -37,7 +64,7 @@ } function assertButtonPropertiesMatch(el, propertyToCssVar) { - let elStyles = getComputedStyle(el.buttonEl); + let elStyles = el.buttonEl ? getComputedStyle(el.buttonEl) : getComputedStyle(el); for (let [property, cssVar] of Object.entries(propertyToCssVar)) { let propertyVal = elStyles[property]; let cssVarVal = cssVar.startsWith("--") ? elStyles.getPropertyValue(cssVar) : cssVar; @@ -52,13 +79,14 @@ add_task(async function testButtonTypes() { let [...buttons] = document.querySelectorAll("moz-button"); - let [one, two, three, four, five, six] = buttons; + let [one, two, three, four, five, six, seven] = buttons; await Promise.all(buttons.map(btn => btn.updateComplete)); is(one.textContent, "Test button", "Text is set"); is(two.buttonEl.textContent.trim(), "Test button", "Text is set"); is(three.textContent, "Test button", "Text is set"); + is(seven.buttonEl.textContent.trim(), "Test button", "Text is set"); assertButtonPropertiesMatch(one, { backgroundColor: "--button-background-color", @@ -79,19 +107,24 @@ width: "--button-size-icon", height: "--button-size-icon", backgroundColor: "--button-background-color", - fill: "--icon-color", + fill: "--button-text-color", }); assertButtonPropertiesMatch(five, { width: "--button-size-icon", height: "--button-size-icon", backgroundColor: "transparent", - fill: "--icon-color", + fill: "--button-text-color", }); assertButtonPropertiesMatch(six, { width: "--button-size-icon", height: "--button-size-icon", backgroundColor: "transparent", - fill: "--icon-color", + fill: "--button-text-color", + }); + assertButtonPropertiesMatch(seven, { + backgroundColor: "--button-background-color", + color: "--button-text-color", + height: "--button-min-height", }); buttons.forEach(btn => (btn.size = "small")); @@ -119,6 +152,9 @@ width: "--button-size-icon-small", height: "--button-size-icon-small", }); + assertButtonPropertiesMatch(seven, { + height: "--button-min-height-small", + }); }); add_task(async function testA11yAttributes() { @@ -144,14 +180,88 @@ await testProperty("aria-label", "ariaLabel"); }); + add_task(async function testIconButtons() { + let buttons = ["four", "five", "six", "seven", "eight", "nine"].map( + className => document.querySelector(`.${className}`) + ); + let [four, five, six, seven, eight, nine] = buttons; + await Promise.all(buttons.map(btn => btn.updateComplete)); + + function verifyBackgroundIcon(button) { + let img = button.shadowRoot.querySelector("img"); + ok(!img, "button does not use an img element to display an icon"); + assertButtonPropertiesMatch(button, { + fill: "--button-text-color", + backgroundSize: "--icon-size-default", + }); + } + + function verifyImageIcon({ button }) { + let img = button.shadowRoot.querySelector("img"); + ok(img, "button uses an inner img element to display an icon"); + is(img.src, "chrome://global/skin/icons/edit.svg", "button displays the expected icon"); + assertButtonPropertiesMatch(img, { + fill: "--button-text-color", + width: "--icon-size-default", + height: "--icon-size-default", + }); + } + + verifyBackgroundIcon(four); + verifyBackgroundIcon(five); + verifyBackgroundIcon(six); + + verifyImageIcon({ button: seven }); + verifyImageIcon({ button: eight }); + verifyImageIcon({ button: nine }); + + nine.textContent = "With text"; + // Ensure we've painted before checking styles + await new Promise(resolve => requestAnimationFrame(resolve)); + verifyImageIcon({ button: nine, isLabelled: true }); + + nine.textContent = ""; + // Ensure we've painted before checking styles + await new Promise(resolve => requestAnimationFrame(resolve)); + verifyImageIcon({ button: nine, isLabelled: false }); + }); </script> </head> <body> - <moz-button class="one">Test button</moz-button> - <moz-button class="two" label="Test button"></moz-button> - <moz-button class="three" type="primary">Test button</moz-button> - <moz-button class="four" type="icon"></moz-button> - <moz-button class="five" type="icon ghost"></moz-button> - <moz-button class="six" type="ghost icon"></moz-button> + <style> + .wrapper { + height: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; + gap: 64px; + } + </style> + <div class="wrapper"> + <div> + <moz-button class="one">Test button</moz-button> + <moz-button class="two" label="Test button"></moz-button> + <moz-button class="three" type="primary">Test button</moz-button> + <moz-button class="four" type="icon"></moz-button> + <moz-button class="five" type="icon ghost"></moz-button> + <moz-button class="six" type="ghost icon"></moz-button> + <moz-button + class="seven" + label="Test button" + iconsrc="chrome://global/skin/icons/edit.svg" + ></moz-button> + <moz-button + class="eight" + iconsrc="chrome://global/skin/icons/edit.svg" + ></moz-button> + <!-- Used to verify that empty space doesn't get treated as a label --> + <moz-button + class="nine" + type="ghost" + iconsrc="chrome://global/skin/icons/edit.svg" + > </moz-button> + </div> + <button id="mouse-trap">Mouse goes here</button> + </div> </body> </html> diff --git a/toolkit/content/tests/widgets/test_moz_button_group.html b/toolkit/content/tests/widgets/test_moz_button_group.html index 92fd7776fa..471d554599 100644 --- a/toolkit/content/tests/widgets/test_moz_button_group.html +++ b/toolkit/content/tests/widgets/test_moz_button_group.html @@ -10,6 +10,7 @@ solution for token variables for the new widgets --> <link rel="stylesheet" href="chrome://global/skin/in-content/common.css"> <script type="module" src="chrome://global/content/elements/moz-button-group.mjs"></script> + <script type="module" src="chrome://global/content/elements/moz-button.mjs"></script> </head> <body> <p id="display"></p> @@ -20,6 +21,7 @@ </div> <!-- This is here to ensure the stylesheet is loaded. It gets removed in setup. --> <moz-button-group></moz-button-group> + <moz-button>Test</moz-button> <pre id="test"> </pre> @@ -74,54 +76,80 @@ add_setup(async function setup() { ({ html, render} = await import("chrome://global/content/vendor/lit.all.mjs")); document.querySelector("moz-button-group").remove(); + document.querySelector("moz-button").remove(); }); add_task(async function testButtonOrderingSlot() { - render( + let markupOptions = [ html` <moz-button-group> <button slot="primary" id="primary-button">Primary</button> <button id="secondary-button">Secondary</button> </moz-button-group> `, - renderArea - ); + html` + <moz-button-group> + <moz-button slot="primary" id="primary-button">Primary</moz-button> + <moz-button id="secondary-button">Secondary</moz-button> + </moz-button-group> + `, + ]; + for (let markup of markupOptions) { + render(markup, renderArea); - let buttonGroup = document.querySelector("moz-button-group"); - let primaryButton = document.getElementById("primary-button"); - let secondaryButton = document.getElementById("secondary-button"); + let buttonGroup = document.querySelector("moz-button-group"); + let primaryButton = document.getElementById("primary-button"); + let secondaryButton = document.getElementById("secondary-button"); - buttonGroup.platform = "win"; - await buttonGroup.updateComplete; - await checkButtons(primaryButton, secondaryButton); - buttonGroup.platform = "macosx"; - await buttonGroup.updateComplete; - await checkButtons(secondaryButton, primaryButton); + buttonGroup.platform = "win"; + await buttonGroup.updateComplete; + await checkButtons(primaryButton, secondaryButton); + + buttonGroup.platform = "macosx"; + await buttonGroup.updateComplete; + await checkButtons(secondaryButton, primaryButton); + } }); add_task(async function testPrimaryButtonAutoSlotting() { - render( + let markupOptions = [ html` <moz-button-group> <button class="primary">Primary</button> <button class="secondary">Secondary</button> </moz-button-group> `, - renderArea - ); - - let buttonGroup = document.querySelector("moz-button-group"); - let primaryButton = buttonGroup.querySelector(".primary"); - let secondaryButton = buttonGroup.querySelector(".secondary"); - buttonGroup.platform = "win"; - await buttonGroup.updateComplete; - is(primaryButton.slot, "primary", "primary button was auto-slotted") - await checkButtons(primaryButton, secondaryButton); - - buttonGroup.platform = "macosx"; - await buttonGroup.updateComplete; - await checkButtons(secondaryButton, primaryButton); + html` + <moz-button-group> + <moz-button type="primary">Primary</moz-button> + <moz-button type="default">Secondary</moz-button> + </moz-button-group> + `, + html` + <moz-button-group> + <moz-button type="destructive">Delete</moz-button> + <moz-button type="default">Secondary</moz-button> + </moz-button-group> + `, + ]; + for (let markup of markupOptions) { + render(markup, renderArea); + + let buttonGroup = document.querySelector("moz-button-group"); + let primaryButton = buttonGroup.querySelector( + ".primary, [type=primary], [type=destructive]" + ); + let secondaryButton = buttonGroup.querySelector(".secondary, [type=default]"); + buttonGroup.platform = "win"; + await buttonGroup.updateComplete; + is(primaryButton.slot, "primary", "primary button was auto-slotted") + await checkButtons(primaryButton, secondaryButton); + + buttonGroup.platform = "macosx"; + await buttonGroup.updateComplete; + await checkButtons(secondaryButton, primaryButton); + } }); add_task(async function testSubmitButtonAutoSlotting() { @@ -197,38 +225,48 @@ }); add_task(async function testInitialButtonLightDomReordering() { - const renderPlatform = platform => render( - html` + let markupOptions = [ + platform => html` <moz-button-group .platform=${platform}> <button class="primary">First</button> <button class="secondary">Secondary</button> <button default>Default</button> </moz-button-group> `, - renderArea - ); - - renderPlatform("win"); - let buttonGroup = document.querySelector("moz-button-group"); - await buttonGroup.updateComplete; - let primaryButton = buttonGroup.querySelector(".primary"); - let defaultButton = buttonGroup.querySelector("[default]"); - let secondaryButton = buttonGroup.querySelector(".secondary"); - - is(primaryButton.slot, "primary", "primary button was auto-slotted"); - is(defaultButton.slot, "primary", "default button was auto-slotted"); - await checkButtons(primaryButton, defaultButton, secondaryButton); - - renderPlatform("macosx"); - buttonGroup = document.querySelector("moz-button-group"); - await buttonGroup.updateComplete; - primaryButton = buttonGroup.querySelector(".primary"); - defaultButton = buttonGroup.querySelector("[default]"); - secondaryButton = buttonGroup.querySelector(".secondary"); - - is(primaryButton.slot, "primary", "primary button was auto-slotted"); - is(defaultButton.slot, "primary", "default button was auto-slotted"); - await checkButtons(secondaryButton, primaryButton, defaultButton); + platform => html` + <moz-button-group .platform=${platform}> + <moz-button type="primary" class="primary">First</moz-button> + <moz-button class="secondary">Secondary</moz-button> + <moz-button type="primary" default>Default</moz-button> + </moz-button-group> + `, + ]; + + for (let markup of markupOptions) { + const renderPlatform = platform => render(markup(platform), renderArea); + + renderPlatform("win"); + let buttonGroup = document.querySelector("moz-button-group"); + await buttonGroup.updateComplete; + let primaryButton = buttonGroup.querySelector(".primary"); + let defaultButton = buttonGroup.querySelector("[default]"); + let secondaryButton = buttonGroup.querySelector(".secondary"); + + is(primaryButton.slot, "primary", "primary button was auto-slotted"); + is(defaultButton.slot, "primary", "default button was auto-slotted"); + await checkButtons(primaryButton, defaultButton, secondaryButton); + + renderPlatform("macosx"); + buttonGroup = document.querySelector("moz-button-group"); + await buttonGroup.updateComplete; + primaryButton = buttonGroup.querySelector(".primary"); + defaultButton = buttonGroup.querySelector("[default]"); + secondaryButton = buttonGroup.querySelector(".secondary"); + + is(primaryButton.slot, "primary", "primary button was auto-slotted"); + is(defaultButton.slot, "primary", "default button was auto-slotted"); + await checkButtons(secondaryButton, primaryButton, defaultButton); + } }); </script> </body> diff --git a/toolkit/content/tests/widgets/test_moz_message_bar.html b/toolkit/content/tests/widgets/test_moz_message_bar.html index 7ee6825ef3..9b48982962 100644 --- a/toolkit/content/tests/widgets/test_moz_message_bar.html +++ b/toolkit/content/tests/widgets/test_moz_message_bar.html @@ -1,27 +1,30 @@ <!DOCTYPE HTML> <html> + <head> <meta charset="utf-8"> <title>MozMessageBar tests</title> <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> - <link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="module" src="chrome://global/content/elements/moz-message-bar.mjs"></script> </head> + <body> -<p id="display"></p> -<div id="content"> - <moz-message-bar id="infoMessage" heading="Heading" message="Test message"></moz-message-bar> - <moz-message-bar id="infoMessage2" dismissable message="Test message"></moz-message-bar> - <moz-message-bar id="warningMessage" type="warning" message="Test message"></moz-message-bar> - <moz-message-bar id="successMessage" type="success" message="Test message"></moz-message-bar> - <moz-message-bar id="errorMessage" type="error" message="Test message"></moz-message-bar> -</div> -<pre id="test"> + <p id="display"></p> + <div id="content"> + <moz-message-bar id="infoMessage" heading="Heading" message="Test message"></moz-message-bar> + <moz-message-bar id="infoMessage2" dismissable message="Test message"></moz-message-bar> + <moz-message-bar id="warningMessage" type="warning" message="Test message"></moz-message-bar> + <moz-message-bar id="successMessage" type="success" message="Test message"></moz-message-bar> + <moz-message-bar id="errorMessage" type="error" message="Test message"></moz-message-bar> + </div> + <pre id="test"> <script class="testbody" type="application/javascript"> add_task(async function test_component_declaration() { const mozMessageBar = document.querySelector("#infoMessage"); ok(mozMessageBar, "moz-message-bar component is rendered."); + is(mozMessageBar.getAttribute("role"), "alert", "moz-message-bar component is marked up as alert."); const icon = mozMessageBar.shadowRoot.querySelector(".icon"); const iconUrl = icon.src; @@ -48,11 +51,11 @@ add_task(async function test_close_button() { const notDismissableComponent = document.querySelector("#infoMessage"); - let closeButton = notDismissableComponent.closeButtonEl; + let closeButton = notDismissableComponent.closeButton; ok(!closeButton, "Close button doesn't show when the message bar isn't dismissable."); let dismissableComponent = document.querySelector("#infoMessage2"); - closeButton = dismissableComponent.closeButtonEl; + closeButton = dismissableComponent.closeButton; ok(closeButton, "Close button is shown when the message bar is dismissable."); closeButton.click(); @@ -89,4 +92,5 @@ </script> </pre> </body> + </html> diff --git a/toolkit/content/tests/widgets/test_moz_page_nav.html b/toolkit/content/tests/widgets/test_moz_page_nav.html index 604df7c024..e03bfa22e2 100644 --- a/toolkit/content/tests/widgets/test_moz_page_nav.html +++ b/toolkit/content/tests/widgets/test_moz_page_nav.html @@ -37,6 +37,12 @@ body { <moz-page-nav-button view="view-five" iconSrc="chrome://mozapps/skin/extensions/category-discover.svg"> <span class="view-name">View 5</span> </moz-page-nav-button> + <moz-page-nav-button iconSrc="chrome://mozapps/skin/extensions/category-discover.svg" support-page="test" slot="secondary-nav"> + <span class="view-name">Support Link</span> + </moz-page-nav-button> + <moz-page-nav-button iconSrc="chrome://mozapps/skin/extensions/category-discover.svg" href="https://www.example.com" slot="secondary-nav"> + <span class="view-name">External Link</span> + </moz-page-nav-button> </moz-page-nav> </div> </div> @@ -121,9 +127,45 @@ function isActiveElement(expectedActiveEl) { }); /** + * Tests that footer support links have the expected attributes + */ + add_task(async function test_support_link() { + const supportLinkRootPath = "https://support.mozilla.org/"; + let supportLink = mozPageNav.secondaryNavButtons[0]; + ok(supportLink.linkEl, "The secondary nav button contains the link element."); + ok( + supportLink.linkEl.hasAttribute("is") && supportLink.linkEl.getAttribute("is") === "moz-support-link", + "The support link has the is=moz-support-link attribute." + ); + ok( + supportLink.linkEl.hasAttribute("href") && supportLink.linkEl.getAttribute("href") === `${supportLinkRootPath}test`, + "The support link has the expected href atrribute." + ); + }); + + /** + * Tests that footer external links have the expected attributes + */ + add_task(async function test_external_link() { + const externalLinkPath = "https://www.example.com"; + let externalLink = mozPageNav.secondaryNavButtons[1]; + ok(externalLink.linkEl, "The secondary nav button contains the link element."); + ok(!externalLink.linkEl.hasAttribute("is"), "The external link doesn't have the is=moz-support-link attribute."); + ok( + externalLink.linkEl.hasAttribute("href") && externalLink.linkEl.getAttribute("href") === externalLinkPath, + "The external link has the expected href atrribute." + ); + }); + + /** * Tests that categories are keyboard-navigable */ add_task(async function test_keyboard_navigation() { + const tab = async shiftKey => { + info(`Tab${shiftKey ? " + Shift" : ""}`); + synthesizeKey("KEY_Tab", { shiftKey }); + await mozPageNav.updateComplete; + }; const arrowDown = async () => { info("Arrow down"); synthesizeKey("KEY_ArrowDown", {}); @@ -155,6 +197,8 @@ function isActiveElement(expectedActiveEl) { let thirdPageNavButton = mozPageNav.pageNavButtons[2]; let fourthPageNavButton = mozPageNav.pageNavButtons[3]; let fifthPageNavButton = mozPageNav.pageNavButtons[4]; + let supportLink = mozPageNav.secondaryNavButtons[0]; + let externalLink = mozPageNav.secondaryNavButtons[1]; is( firstPageNavButton.view, @@ -196,6 +240,23 @@ function isActiveElement(expectedActiveEl) { mozPageNav.currentView, "The fifth page nav button is still selected" ) + await tab(); + ok( + isActiveElement(supportLink.linkEl), + "The support link is selected" + ) + await tab(); + ok( + isActiveElement(externalLink.linkEl), + "The external link is selected" + ) + await tab(true); + await tab(true); + is( + fifthPageNavButton.view, + mozPageNav.currentView, + "The fifth page nav button is selected" + ) await arrowUp(); is( fourthPageNavButton.view, diff --git a/toolkit/content/tests/widgets/test_videocontrols_src_change.html b/toolkit/content/tests/widgets/test_videocontrols_src_change.html new file mode 100644 index 0000000000..535b9483cd --- /dev/null +++ b/toolkit/content/tests/widgets/test_videocontrols_src_change.html @@ -0,0 +1,56 @@ +<!DOCTYPE HTML> +<!-- Any copyright is dedicated to the Public Domain. + - https://creativecommons.org/publicdomain/zero/1.0/ --> +<html> + +<head> + <title>Video controls test</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <script type="text/javascript" src="head.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css" /> +</head> + +<body> + <p id="display"></p> + + <div id="content"> + <video width="320" height="240" id="video" controls></video> + </div> + + <div id="host"></div> + + <pre id="test"> +<script class="testbody"> + add_task(async function test_src_change() { + const video = document.getElementById("video"); + + function changeMediaSource(src) { + let loaded = new Promise((resolve) => video.addEventListener("loadeddata", resolve, { once: true })); + video.src = src; + return loaded; + } + + const muteButton = getElementWithinVideo(video, "muteButton"); + + await changeMediaSource("video.webm"); + + ok(muteButton.hasAttribute("noAudio"), "noAudio attribute is present when the video has no audio track"); + ok(muteButton.disabled, "Mute button is disabled when the video has no audio track"); + + await changeMediaSource("seek_with_sound.webm"); + + ok(!muteButton.hasAttribute("noAudio"), "noAudio attribute is not present when the video has an audio track"); + ok(!muteButton.disabled, "Mute button is enabled when the video has an audio track"); + + await changeMediaSource("video.webm"); + + ok(muteButton.hasAttribute("noAudio"), "noAudio attribute is present when the video has no audio track") + ok(muteButton.disabled, "Mute button is disabled when the video has no audio track"); + }); + +</script> +</pre> +</body> + +</html> diff --git a/toolkit/content/tests/widgets/test_videocontrols_video_noaudio.html b/toolkit/content/tests/widgets/test_videocontrols_video_noaudio.html index 99d5bdad01..be28ed24c9 100644 --- a/toolkit/content/tests/widgets/test_videocontrols_video_noaudio.html +++ b/toolkit/content/tests/widgets/test_videocontrols_video_noaudio.html @@ -29,7 +29,7 @@ }); add_task(async function mute_button_icon() { - is(muteButton.getAttribute("noAudio"), "true"); + ok(muteButton.hasAttribute("noAudio"), "Mute button should have noAudio attribute"); ok(muteButton.hasAttribute("disabled"), "Mute button should be disabled"); if (volumeStack) { diff --git a/toolkit/content/widgets.css b/toolkit/content/widgets.css index d7f1b68602..16b6d5cb94 100644 --- a/toolkit/content/widgets.css +++ b/toolkit/content/widgets.css @@ -22,4 +22,4 @@ @import url("chrome://global/skin/tabbox.css"); @import url("chrome://global/skin/toolbar.css"); @import url("chrome://global/skin/toolbarbutton.css"); -@import url("chrome://global/skin/tree.css"); +@import url("chrome://global/skin/tree/tree.css"); diff --git a/toolkit/content/widgets/arrowscrollbox.js b/toolkit/content/widgets/arrowscrollbox.js index 7109891faf..5983435d06 100644 --- a/toolkit/content/widgets/arrowscrollbox.js +++ b/toolkit/content/widgets/arrowscrollbox.js @@ -21,7 +21,7 @@ return ` <html:link rel="stylesheet" href="chrome://global/skin/toolbarbutton.css"/> <html:link rel="stylesheet" href="chrome://global/skin/arrowscrollbox.css"/> - <toolbarbutton id="scrollbutton-up" part="scrollbutton-up" keyNav="false" data-l10n-id="overflow-scroll-button-up"/> + <toolbarbutton id="scrollbutton-up" part="scrollbutton-up" keyNav="false" data-l10n-id="overflow-scroll-button-backwards"/> <spacer part="overflow-start-indicator"/> <box class="scrollbox-clip" part="scrollbox-clip" flex="1"> <scrollbox part="scrollbox" flex="1"> @@ -29,7 +29,7 @@ </scrollbox> </box> <spacer part="overflow-end-indicator"/> - <toolbarbutton id="scrollbutton-down" part="scrollbutton-down" keyNav="false" data-l10n-id="overflow-scroll-button-down"/> + <toolbarbutton id="scrollbutton-down" part="scrollbutton-down" keyNav="false" data-l10n-id="overflow-scroll-button-forwards"/> `; } diff --git a/toolkit/content/widgets/autocomplete-richlistitem.js b/toolkit/content/widgets/autocomplete-richlistitem.js index b339ab1e27..0ec8a19243 100644 --- a/toolkit/content/widgets/autocomplete-richlistitem.js +++ b/toolkit/content/widgets/autocomplete-richlistitem.js @@ -832,9 +832,7 @@ setTimeout(() => { let selectedIndex = popup ? popup.selectedIndex : -1; - actor.manager - .getActor("FormAutofill") - .sendAsyncMessage("FormAutofill:PreviewProfile", { selectedIndex }); + actor.previewAutofillProfile(selectedIndex); }, 0); } diff --git a/toolkit/content/widgets/datetimebox.js b/toolkit/content/widgets/datetimebox.js index 04ed398bd7..1c63b09269 100644 --- a/toolkit/content/widgets/datetimebox.js +++ b/toolkit/content/widgets/datetimebox.js @@ -650,6 +650,10 @@ this.DateTimeBoxWidget = class { onKeyDown(aEvent) { this.log("onKeyDown key: " + aEvent.key); + if (aEvent.defaultPrevented) { + return; + } + switch (aEvent.key) { // Toggle the picker on Space/Enter on Calendar button or Space on input, // close on Escape anywhere. @@ -691,21 +695,17 @@ this.DateTimeBoxWidget = class { aEvent.preventDefault(); break; } - if (this.isEditable()) { - // TODO(emilio, bug 1571533): These functions should look at - // defaultPrevented. - // Ctrl+Backspace/Delete on non-macOS and - // Cmd+Backspace/Delete on macOS to clear the field - if (aEvent.getModifierState("Accel")) { - // Clear the input's value - this.clearInputFields(false); - } else { - let targetField = aEvent.originalTarget; - this.clearFieldValue(targetField); - this.setInputValueFromFields(); - } - aEvent.preventDefault(); + // Ctrl+Backspace/Delete on non-macOS and + // Cmd+Backspace/Delete on macOS to clear the field + if (aEvent.getModifierState("Accel")) { + // Clear the input's value + this.clearInputFields(false); + } else { + let targetField = aEvent.originalTarget; + this.clearFieldValue(targetField); + this.setInputValueFromFields(); } + aEvent.preventDefault(); break; } case "ArrowRight": diff --git a/toolkit/content/widgets/message-bar.css b/toolkit/content/widgets/message-bar.css deleted file mode 100644 index eddc5a3ae6..0000000000 --- a/toolkit/content/widgets/message-bar.css +++ /dev/null @@ -1,219 +0,0 @@ -/* 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/. */ - -:host { - --info-icon-url: url("chrome://global/skin/icons/info-filled.svg"); - --warn-icon-url: url("chrome://global/skin/icons/warning.svg"); - --success-icon-url: url("chrome://global/skin/icons/check.svg"); - --error-icon-url: url("chrome://global/skin/icons/error.svg"); - --close-icon-url: url("chrome://global/skin/icons/close-12.svg"); - --close-fill-color: var(--in-content-icon-color); - --icon-size: 16px; - --close-icon-size: 28px; -} - -:host { - --message-bar-background-color: var(--in-content-box-info-background); - --message-bar-text-color: var(--in-content-text-color); - --message-bar-icon-url: var(--info-icon-url); - /* The default values of --in-content-button* are sufficient, even for dark themes */ -} - -:host([type=warning]) { - --message-bar-icon-url: var(--warn-icon-url); -} - -:host([type=success]) { - --message-bar-icon-url: var(--success-icon-url); -} - -:host([type=error]), -:host([type=critical]) { - --message-bar-icon-url: var(--error-icon-url); -} - -:host { - border: 1px solid transparent; - border-radius: 4px; -} - -/* Make the host to behave as a block by default, but allow hidden to hide it. */ -:host(:not([hidden])) { - display: block; -} - -::slotted(button) { - /* Enforce micro-button width. */ - min-width: -moz-fit-content !important; -} - -/* MessageBar Grid Layout */ - -.container { - background: var(--message-bar-background-color); - color: var(--message-bar-text-color); - - padding: 3px 7px; - position: relative; - - border-radius: 4px; - - display: flex; - /* Ensure that the message bar shadow dom elements are vertically aligned. */ - align-items: center; -} - -:host([align="center"]) .container { - justify-content: center; -} - -.content { - margin: 0 4px; - display: inline-block; - /* Ensure that the message bar content is vertically aligned. */ - align-items: center; - /* Ensure that the message bar content is wrapped. */ - word-break: break-word; -} - -/* MessageBar icon style */ - -.icon { - padding: 4px; - width: var(--icon-size); - height: var(--icon-size); - flex-shrink: 0; -} - -.icon::after { - display: inline-block; - appearance: none; - -moz-context-properties: fill, stroke; - fill: currentColor; - stroke: currentColor; - content: ""; - background-image: var(--message-bar-icon-url); - background-size: var(--icon-size); - width: var(--icon-size); - height: var(--icon-size); -} - -/* Use a spacer to position the close button at the end, but also support - * centering if required. */ -.spacer { - flex-grow: 1; -} - -/* Close icon styles */ - -:host(:not([dismissable])) .close { - display: none; -} - -.close { - background-image: var(--close-icon-url); - background-repeat: no-repeat; - background-position: center center; - -moz-context-properties: fill; - fill: currentColor; - min-width: auto; - min-height: auto; - width: var(--close-icon-size); - height: var(--close-icon-size); - padding: 0; - flex-shrink: 0; - margin: 4px 8px; - background-size: 12px; -} - -@media (prefers-contrast) { - :host { - border-color: CanvasText; - } -} - -@media not (prefers-contrast) { - /* MessageBar colors by message type */ - /* Colors from: https://design.firefox.com/photon/components/message-bars.html#type-specific-style */ - - :host([type=warning]) { - /* Ensure colors within the bar are adjusted and controls are readable */ - color-scheme: light; - - --message-bar-background-color: var(--yellow-50); - --message-bar-text-color: var(--yellow-90); - - --in-content-button-background: var(--yellow-60); - --in-content-button-background-hover: var(--yellow-70); - --in-content-button-background-active: var(--yellow-80); - - --close-fill-color: var(--message-bar-text-color); - } - - :host([type=success]) { - /* Ensure colors within the bar are adjusted and controls are readable */ - color-scheme: light; - - --message-bar-background-color: var(--green-50); - --message-bar-text-color: var(--green-90); - - --in-content-button-background: var(--green-60); - --in-content-button-background-hover: var(--green-70); - --in-content-button-background-active: var(--green-80); - } - - :host([type=error]) { - --message-bar-background-color: var(--red-60); - --message-bar-text-color: #ffffff; - - --in-content-button-background: var(--red-70); - --in-content-button-background-hover: var(--red-80); - --in-content-button-background-active: var(--red-90); - } - - :host([type=info]) .icon { - color: rgb(0,144,237); - } - - :host([type=warning]) .icon { - color: rgb(255,164,54); - } - - :host([type=critical]) .icon { - color: rgb(226,40,80); - } - - .close { - fill: var(--close-fill-color); - } - - @media (prefers-color-scheme: dark) { - /* Don't set the background in prefers-contrast mode or macOS can end up - * with black on black text. */ - :host([type=info]) .icon { - color: rgb(128,235,255); - } - - :host([type=warning]) .icon { - color: rgb(255,189,79); - } - - :host([type=critical]) .icon { - color: rgb(255,154,162); - } - } -} - -strong { - font-weight: 600; -} - -.text-link:hover { - cursor: pointer; -} - -@keyframes spin { - from { transform: rotate(0); } - to { transform: rotate(360deg); } -} diff --git a/toolkit/content/widgets/message-bar.js b/toolkit/content/widgets/message-bar.js deleted file mode 100644 index d38347b40a..0000000000 --- a/toolkit/content/widgets/message-bar.js +++ /dev/null @@ -1,91 +0,0 @@ -/* 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/. */ - -"use strict"; - -// This is loaded into chrome windows with the subscript loader. Wrap in -// a block to prevent accidentally leaking globals onto `window`. -{ - class MessageBarElement extends HTMLElement { - constructor() { - super(); - const shadowRoot = this.attachShadow({ mode: "open" }); - window.MozXULElement?.insertFTLIfNeeded( - "toolkit/global/notification.ftl" - ); - document.l10n.connectRoot(this.shadowRoot); - const content = this.constructor.template.content.cloneNode(true); - shadowRoot.append(content); - this.closeButton.addEventListener("click", () => this.dismiss(), { - once: true, - }); - } - - disconnectedCallback() { - this.dispatchEvent(new CustomEvent("message-bar:close")); - } - - get closeButton() { - return this.shadowRoot.querySelector("button.close"); - } - - static get template() { - const template = document.createElement("template"); - - const commonStyles = document.createElement("link"); - commonStyles.rel = "stylesheet"; - commonStyles.href = "chrome://global/skin/in-content/common.css"; - const messageBarStyles = document.createElement("link"); - messageBarStyles.rel = "stylesheet"; - messageBarStyles.href = - "chrome://global/content/elements/message-bar.css"; - template.content.append(commonStyles, messageBarStyles); - - // A container for the entire message bar content, - // most of the css rules needed to provide the - // expected message bar layout is applied on this - // element. - const container = document.createElement("div"); - container.part = "container"; - container.classList.add("container"); - template.content.append(container); - - const icon = document.createElement("span"); - icon.classList.add("icon"); - icon.part = "icon"; - container.append(icon); - - const barcontent = document.createElement("span"); - barcontent.classList.add("content"); - barcontent.append(document.createElement("slot")); - container.append(barcontent); - - const spacer = document.createElement("span"); - spacer.classList.add("spacer"); - container.append(spacer); - - const closeIcon = document.createElement("button"); - closeIcon.classList.add("close", "ghost-button"); - document.l10n.setAttributes(closeIcon, "notification-close-button"); - container.append(closeIcon); - - Object.defineProperty(this, "template", { - value: template, - }); - - return template; - } - - dismiss() { - this.dispatchEvent(new CustomEvent("message-bar:user-dismissed")); - this.close(); - } - - close() { - this.remove(); - } - } - - customElements.define("message-bar", MessageBarElement); -} diff --git a/toolkit/content/widgets/moz-button-group/moz-button-group.css b/toolkit/content/widgets/moz-button-group/moz-button-group.css index ba79d69e12..5b6f7deace 100644 --- a/toolkit/content/widgets/moz-button-group/moz-button-group.css +++ b/toolkit/content/widgets/moz-button-group/moz-button-group.css @@ -11,6 +11,7 @@ margin: 0 !important; } -::slotted(button:not(:first-child, .popup-notification-dropmarker)) { +::slotted(button:not(:first-child, .popup-notification-dropmarker)), +::slotted(moz-button:not(:first-child)) { margin-inline-start: var(--space-small) !important; } diff --git a/toolkit/content/widgets/moz-button-group/moz-button-group.mjs b/toolkit/content/widgets/moz-button-group/moz-button-group.mjs index 8bf553c23d..6858367ab7 100644 --- a/toolkit/content/widgets/moz-button-group/moz-button-group.mjs +++ b/toolkit/content/widgets/moz-button-group/moz-button-group.mjs @@ -50,15 +50,22 @@ export default class MozButtonGroup extends MozLitElement { // Text nodes won't support classList or getAttribute. continue; } - // Bug 1791816: These should check moz-button instead of button. - if ( - child.localName == "button" && - (child.classList.contains("primary") || - child.getAttribute("type") == "submit" || - child.hasAttribute("autofocus") || - child.hasAttribute("default")) - ) { - child.slot = "primary"; + switch (child.localName) { + case "button": + if ( + child.classList.contains("primary") || + child.getAttribute("type") == "submit" || + child.hasAttribute("autofocus") || + child.hasAttribute("default") + ) { + child.slot = "primary"; + } + break; + case "moz-button": + if (child.type == "primary" || child.type == "destructive") { + child.slot = "primary"; + } + break; } } this.#reorderLightDom(); diff --git a/toolkit/content/widgets/moz-button/moz-button.css b/toolkit/content/widgets/moz-button/moz-button.css index 71d57ea93a..4eb6839e06 100644 --- a/toolkit/content/widgets/moz-button/moz-button.css +++ b/toolkit/content/widgets/moz-button/moz-button.css @@ -23,6 +23,10 @@ button { /* Ensure font-size isn't overridden by widget styling (e.g. in forms.css) */ font-size: var(--button-font-size); width: 100%; + display: flex; + justify-content: center; + align-items: center; + gap: var(--space-small); &[size=small] { min-height: var(--button-min-height-small); @@ -125,21 +129,33 @@ button { } } - &[type~=icon] { + &[type~=icon]:not(.labelled) { background-size: var(--icon-size-default); background-position: center; background-repeat: no-repeat; - -moz-context-properties: fill, stroke; - fill: currentColor; - stroke: currentColor; + } + + &[type~=icon]:not(.labelled), + &:not(.labelled):has(img) { width: var(--button-size-icon); height: var(--button-size-icon); padding: var(--button-padding-icon); - color: var(--icon-color); &[size=small] { width: var(--button-size-icon-small); height: var(--button-size-icon-small); } } + + img, + &[type~=icon]:not(.labelled) { + -moz-context-properties: fill, fill-opacity, stroke; + fill: currentColor; + stroke: currentColor; + } + + img { + width: var(--icon-size-default); + height: var(--icon-size-default); + } } diff --git a/toolkit/content/widgets/moz-button/moz-button.mjs b/toolkit/content/widgets/moz-button/moz-button.mjs index a951dbf5d8..9a239d4e56 100644 --- a/toolkit/content/widgets/moz-button/moz-button.mjs +++ b/toolkit/content/widgets/moz-button/moz-button.mjs @@ -2,7 +2,7 @@ * 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/. */ -import { html, ifDefined } from "../vendor/lit.all.mjs"; +import { html, ifDefined, classMap } from "../vendor/lit.all.mjs"; import { MozLitElement } from "../lit-utils.mjs"; /** @@ -19,8 +19,11 @@ import { MozLitElement } from "../lit-utils.mjs"; * @property {string} titleAttribute - Internal, map title attribute to the title JS property. * @property {string} tooltipText - Set the title property, the title attribute will be used first. * @property {string} ariaLabel - The button's arial-label attribute, used in shadow DOM and therefore not as an attribute on moz-button. + * @property {string} iconSrc - Path to the icon that should be displayed in the button. * @property {string} ariaLabelAttribute - Internal, map aria-label attribute to the ariaLabel JS property. + * @property {string} hasVisibleLabel - Internal, tracks whether or not the button has a visible label. * @property {HTMLButtonElement} buttonEl - The internal button element in the shadow DOM. + * @property {HTMLButtonElement} slotEl - The internal slot element in the shadow DOM. * @slot default - The button's content, overrides label property. * @fires click - The click event. */ @@ -44,10 +47,13 @@ export default class MozButton extends MozLitElement { reflect: true, }, ariaLabel: { type: String, state: true }, + iconSrc: { type: String }, + hasVisibleLabel: { type: Boolean, state: true }, }; static queries = { buttonEl: "button", + slotEl: "slot", }; constructor() { @@ -55,6 +61,7 @@ export default class MozButton extends MozLitElement { this.type = "default"; this.size = "default"; this.disabled = false; + this.hasVisibleLabel = !!this.label; } willUpdate(changes) { @@ -73,6 +80,12 @@ export default class MozButton extends MozLitElement { this.buttonEl.click(); } + checkForLabelText() { + this.hasVisibleLabel = this.slotEl + .assignedNodes() + .some(node => node.textContent.trim()); + } + render() { return html` <link @@ -86,8 +99,12 @@ export default class MozButton extends MozLitElement { title=${ifDefined(this.title || this.tooltipText)} aria-label=${ifDefined(this.ariaLabel)} part="button" + class=${classMap({ labelled: this.label || this.hasVisibleLabel })} > - <slot>${this.label}</slot> + ${this.iconSrc + ? html`<img src=${this.iconSrc} role="presentation" />` + : ""} + <slot @slotchange=${this.checkForLabelText}>${this.label}</slot> </button> `; } diff --git a/toolkit/content/widgets/moz-button/moz-button.stories.mjs b/toolkit/content/widgets/moz-button/moz-button.stories.mjs index 52a459e807..dd8d6369db 100644 --- a/toolkit/content/widgets/moz-button/moz-button.stories.mjs +++ b/toolkit/content/widgets/moz-button/moz-button.stories.mjs @@ -2,7 +2,7 @@ * 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/. */ -import { html } from "../vendor/lit.all.mjs"; +import { html, ifDefined } from "../vendor/lit.all.mjs"; // eslint-disable-next-line import/no-unassigned-import import "./moz-button.mjs"; @@ -22,6 +22,10 @@ export default { options: ["default", "small"], control: { type: "radio" }, }, + type: { + options: ["default", "primary", "destructive", "icon", "icon ghost"], + control: { type: "select" }, + }, }, parameters: { actions: { @@ -40,17 +44,13 @@ moz-button-aria-labelled = }, }; -const Template = ({ type, size, l10nId, iconUrl, disabled }) => html` - <style> - moz-button[type~="icon"]::part(button) { - background-image: url("${iconUrl}"); - } - </style> +const Template = ({ type, size, l10nId, iconSrc, disabled }) => html` <moz-button data-l10n-id=${l10nId} type=${type} size=${size} ?disabled=${disabled} + iconSrc=${ifDefined(iconSrc)} ></moz-button> `; @@ -59,7 +59,7 @@ Default.args = { type: "default", size: "default", l10nId: "moz-button-labelled", - iconUrl: "chrome://global/skin/icons/more.svg", + iconSrc: "", disabled: false, }; export const DefaultSmall = Template.bind({}); @@ -67,7 +67,7 @@ DefaultSmall.args = { type: "default", size: "small", l10nId: "moz-button-labelled", - iconUrl: "chrome://global/skin/icons/more.svg", + iconSrc: "", disabled: false, }; export const Primary = Template.bind({}); @@ -85,7 +85,7 @@ Destructive.args = { export const Icon = Template.bind({}); Icon.args = { ...Default.args, - type: "icon", + iconSrc: "chrome://global/skin/icons/more.svg", l10nId: "moz-button-titled", }; export const IconSmall = Template.bind({}); @@ -96,5 +96,12 @@ IconSmall.args = { export const IconGhost = Template.bind({}); IconGhost.args = { ...Icon.args, - type: "icon ghost", + type: "ghost", +}; +export const IconText = Template.bind({}); +IconText.args = { + type: "default", + size: "default", + iconSrc: "chrome://global/skin/icons/edit-copy.svg", + l10nId: "moz-button-labelled", }; diff --git a/toolkit/content/widgets/moz-message-bar/moz-message-bar.mjs b/toolkit/content/widgets/moz-message-bar/moz-message-bar.mjs index 8f0c997149..9a186b41c9 100644 --- a/toolkit/content/widgets/moz-message-bar/moz-message-bar.mjs +++ b/toolkit/content/widgets/moz-message-bar/moz-message-bar.mjs @@ -49,10 +49,10 @@ const messageTypeToIconData = { export default class MozMessageBar extends MozLitElement { static queries = { - actionsSlotEl: "slot[name=actions]", + actionsSlot: "slot[name=actions]", actionsEl: ".actions", - closeButtonEl: "moz-button.close", - supportLinkSlotEl: "slot[name=support-link]", + closeButton: "moz-button.close", + supportLinkSlot: "slot[name=support-link]", }; static properties = { @@ -72,13 +72,13 @@ export default class MozMessageBar extends MozLitElement { } onSlotchange() { - let actions = this.actionsSlotEl.assignedNodes(); + let actions = this.actionsSlot.assignedNodes(); this.actionsEl.classList.toggle("active", actions.length); } connectedCallback() { super.connectedCallback(); - this.setAttribute("role", "status"); + this.setAttribute("role", "alert"); } disconnectedCallback() { @@ -87,7 +87,7 @@ export default class MozMessageBar extends MozLitElement { } get supportLinkEls() { - return this.supportLinkSlotEl.assignedElements(); + return this.supportLinkSlot.assignedElements(); } iconTemplate() { diff --git a/toolkit/content/widgets/moz-page-nav/README.stories.md b/toolkit/content/widgets/moz-page-nav/README.stories.md index 800d446478..c2f1b37bb5 100644 --- a/toolkit/content/widgets/moz-page-nav/README.stories.md +++ b/toolkit/content/widgets/moz-page-nav/README.stories.md @@ -4,7 +4,7 @@ intended to change the selected view, provide a heading, and have links to external resources. ```html story -<moz-page-nav heading="This is a nav" style={{ '--page-nav-margin-top': 0, '--page-nav-margin-bottom': 0, height: '200px' }}> +<moz-page-nav heading="This is a nav" style={{ '--page-nav-margin-top': 0, '--page-nav-margin-bottom': 0, height: '275px' }}> <moz-page-nav-button view="view-one" iconSrc="chrome://browser/skin/preferences/category-general.svg" @@ -23,13 +23,27 @@ intended to change the selected view, provide a heading, and have links to exter > <p style={{ margin: 0 }}>Test 3</p> </moz-page-nav-button> + <moz-page-nav-button + support-page="test" + iconSrc="chrome://browser/skin/preferences/category-general.svg" + slot="secondary-nav" + > + <p style={{ margin: 0 }}>Support Link</p> + </moz-page-nav-button> + <moz-page-nav-button + href="https://www.example.com" + iconSrc="chrome://browser/skin/preferences/category-general.svg" + slot="secondary-nav" + > + <p style={{ margin: 0 }}>External Link</p> + </moz-page-nav-button> </moz-page-nav> ``` ## When to use * Use moz-page-nav for single-page navigation to switch between different views. -* moz-page-nav will also support footer buttons for external support links in the future (See [bug 1877826](https://bugzilla.mozilla.org/show_bug.cgi?id=1877826)) +* moz-page-nav also supports footer buttons for external and support links * This component will be used in about: pages such as about:firefoxview, about:preferences, about:addons, about:debugging, etc. ## When not to use @@ -53,18 +67,34 @@ And used as follows: ```html <moz-page-nav> - <moz-page-nav-button + <moz-page-nav-button view="A name for the first view" iconSrc="A url for the icon for the first navigation button"> - </moz-page-nav-button> - <moz-page-nav-button + </moz-page-nav-button> + <moz-page-nav-button view="A name for the second view" iconSrc="A url for the icon for the second navigation button"> - </moz-page-nav-button> - <moz-page-nav-button + </moz-page-nav-button> + <moz-page-nav-button view="A name for the third view" iconSrc="A url for the icon for the third navigation button"> - </moz-page-nav-button> + </moz-page-nav-button> + + <!-- Footer Links --> + + <!-- Support Link --> + <moz-page-nav-button + support-page="A name for a support link" + iconSrc="A url for the icon for the third navigation button" + slot="secondary-nav"> + </moz-page-nav-button> + + <!-- External Link --> + <moz-page-nav-button + href="A url for an external link" + iconSrc="A url for the icon for the third navigation button" + slot="secondary-nav"> + </moz-page-nav-button> </moz-page-nav> ``` diff --git a/toolkit/content/widgets/moz-page-nav/moz-page-nav-button.css b/toolkit/content/widgets/moz-page-nav/moz-page-nav-button.css index 5d00198d65..781398056a 100644 --- a/toolkit/content/widgets/moz-page-nav/moz-page-nav-button.css +++ b/toolkit/content/widgets/moz-page-nav/moz-page-nav-button.css @@ -4,11 +4,13 @@ :host { border-radius: var(--border-radius-small); + font-size: var(--font-size-large); &:focus-visible { outline-offset: var(--page-nav-focus-outline-inset); } } +a[href], button { background-color: var(--page-nav-button-background-color); border: 1px solid var(--page-nav-border-color); @@ -28,11 +30,17 @@ button { padding: var(--page-nav-button-padding); } +a[href] { + text-decoration: none; + box-sizing: border-box; +} + button:hover { cursor: pointer; } @media not (prefers-contrast) { + a[href], button { position: relative; } @@ -55,6 +63,7 @@ button:hover { background-color: var(--icon-color); } + a[href]:hover, button:hover, button[selected]:hover { background-color: var(--page-nav-button-background-color-hover); @@ -72,6 +81,7 @@ button:hover { } } +a[href]:focus-visible, button:focus-visible, button[selected]:focus-visible { outline: var(--focus-outline); @@ -86,13 +96,24 @@ button[selected]:focus-visible { fill: currentColor; } +:host(.secondary-nav-item) { + font-size: var(--font-size-small); + + & .page-nav-icon { + height: var(--icon-size-default); + width: var(--icon-size-default); + } +} + @media (prefers-contrast) { + a[href], button { transition: none; border-color: ButtonText; background-color: var(--button-background-color); } + a[href]:hover, button:hover { color: SelectedItem; } @@ -105,13 +126,13 @@ button[selected]:focus-visible { } slot { - font-size: var(--font-size-large); margin: 0; padding-inline-start: 0; user-select: none; } @media (max-width: 52rem) { + a[href], button { grid-template-columns: min-content; justify-content: center; diff --git a/toolkit/content/widgets/moz-page-nav/moz-page-nav.mjs b/toolkit/content/widgets/moz-page-nav/moz-page-nav.mjs index f998ee735f..c720e76e26 100644 --- a/toolkit/content/widgets/moz-page-nav/moz-page-nav.mjs +++ b/toolkit/content/widgets/moz-page-nav/moz-page-nav.mjs @@ -4,6 +4,8 @@ import { html } from "chrome://global/content/vendor/lit.all.mjs"; import { MozLitElement } from "chrome://global/content/lit-utils.mjs"; +// eslint-disable-next-line import/no-unassigned-import +import "chrome://global/content/elements/moz-support-link.mjs"; /** * A grouping of navigation buttons that is displayed at the page level, @@ -35,6 +37,14 @@ export default class MozPageNav extends MozLitElement { ); } + get secondaryNavButtons() { + return this.secondaryNavGroupSlot + .assignedNodes() + .filter( + node => node?.localName === "moz-page-nav-button" && !node.hidden + ); + } + onChangeView(e) { this.currentView = e.target.view; } @@ -69,6 +79,12 @@ export default class MozPageNav extends MozLitElement { } } + onSecondaryNavChange() { + this.secondaryNavGroupSlot.assignedElements()?.forEach(el => { + el.classList.add("secondary-nav-item"); + }); + } + render() { return html` <link @@ -89,7 +105,10 @@ export default class MozPageNav extends MozLitElement { ></slot> </div> <div id="secondary-nav-group" role="group"> - <slot name="secondary-nav" @keydown=${this.handleFocus}></slot> + <slot + name="secondary-nav" + @slotchange=${this.onSecondaryNavChange} + ></slot> </div> </nav> `; @@ -114,16 +133,18 @@ customElements.define("moz-page-nav", MozPageNav); * A navigation button intended to change the selected view within a page. * * @tagname moz-page-nav-button + * @property {string} href - (optional) The url for an external link if not a support page URL * @property {string} iconSrc - The chrome:// url for the icon used for the button. - * @property {string} l10nId - The fluent ID for the button's text * @property {boolean} selected - Whether or not the button is currently selected. + * @property {string} supportPage - (optional) The short name for the support page a secondary link should launch to * @slot [default] - Used to append the l10n string to the button. */ export class MozPageNavButton extends MozLitElement { static properties = { iconSrc: { type: String }, - l10nId: { type: String }, + href: { type: String }, selected: { type: Boolean }, + supportPage: { type: String, attribute: "support-page" }, }; connectedCallback() { @@ -133,6 +154,7 @@ export class MozPageNavButton extends MozLitElement { static queries = { buttonEl: "button", + linkEl: "a", }; get view() { @@ -148,12 +170,15 @@ export class MozPageNavButton extends MozLitElement { ); } - render() { + itemTemplate() { + if (this.href || this.supportPage) { + return this.linkTemplate(); + } + return this.buttonTemplate(); + } + + buttonTemplate() { return html` - <link - rel="stylesheet" - href="chrome://global/content/elements/moz-page-nav-button.css" - /> <button aria-selected=${this.selected} tabindex=${this.selected ? 0 : -1} @@ -161,10 +186,51 @@ export class MozPageNavButton extends MozLitElement { ?selected=${this.selected} @click=${this.activate} > - <img class="page-nav-icon" src=${this.iconSrc} /> - <slot></slot> + ${this.innerContentTemplate()} </button> `; } + + linkTemplate() { + if (this.supportPage) { + return html` + <a + is="moz-support-link" + class="moz-page-nav-link" + support-page=${this.supportPage} + > + ${this.innerContentTemplate()} + </a> + `; + } + return html` + <a href=${this.href} class="moz-page-nav-link" target="_blank"> + ${this.innerContentTemplate()} + </a> + `; + } + + innerContentTemplate() { + return html` + ${this.iconSrc + ? html`<img + class="page-nav-icon" + src=${this.iconSrc} + role="presentation" + />` + : ""} + <slot></slot> + `; + } + + render() { + return html` + <link + rel="stylesheet" + href="chrome://global/content/elements/moz-page-nav-button.css" + /> + ${this.itemTemplate()} + `; + } } customElements.define("moz-page-nav-button", MozPageNavButton); diff --git a/toolkit/content/widgets/moz-page-nav/moz-page-nav.stories.mjs b/toolkit/content/widgets/moz-page-nav/moz-page-nav.stories.mjs index 4ac7b455cf..d1c565efe9 100644 --- a/toolkit/content/widgets/moz-page-nav/moz-page-nav.stories.mjs +++ b/toolkit/content/widgets/moz-page-nav/moz-page-nav.stories.mjs @@ -2,7 +2,7 @@ * 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/. */ -import { html } from "../vendor/lit.all.mjs"; +import { html, when } from "../vendor/lit.all.mjs"; // eslint-disable-next-line import/no-unassigned-import import "./moz-page-nav.mjs"; @@ -21,15 +21,17 @@ moz-page-nav-button-two = View 2 .title = View 2 moz-page-nav-button-three = View 3 .title = View 3 -moz-page-link-one = Support Page - .title = Support Page +moz-page-nav-button-four = Support Link + .title = Support Link +moz-page-nav-button-five = External Link + .title = External Link moz-page-nav-heading = .heading = Heading `, }, }; -const Template = () => html` +const Template = ({ hasFooterLinks }) => html` <style> #page { height: 100%; @@ -68,10 +70,30 @@ const Template = () => html` iconSrc="chrome://browser/skin/preferences/category-general.svg" > </moz-page-nav-button> + ${when( + hasFooterLinks, + () => html` <moz-page-nav-button + support-page="test" + data-l10n-id="moz-page-nav-button-four" + iconSrc="chrome://browser/skin/preferences/category-general.svg" + slot="secondary-nav" + > + </moz-page-nav-button> + <moz-page-nav-button + href="https://www.example.com" + data-l10n-id="moz-page-nav-button-five" + iconSrc="chrome://browser/skin/preferences/category-general.svg" + slot="secondary-nav" + > + </moz-page-nav-button>` + )} </moz-page-nav> <main></main> </div> `; export const Default = Template.bind({}); -Default.args = {}; +Default.args = { hasFooterLinks: false }; + +export const WithFooterLinks = Template.bind({}); +WithFooterLinks.args = { hasFooterLinks: true }; diff --git a/toolkit/content/widgets/moz-support-link/moz-support-link.mjs b/toolkit/content/widgets/moz-support-link/moz-support-link.mjs index 9d2d6ffac2..df6ebac2a5 100644 --- a/toolkit/content/widgets/moz-support-link/moz-support-link.mjs +++ b/toolkit/content/widgets/moz-support-link/moz-support-link.mjs @@ -29,6 +29,10 @@ export default class MozSupportLink extends HTMLAnchorElement { */ #register() { if (window.document.nodePrincipal?.isSystemPrincipal) { + ChromeUtils.defineESModuleGetters(MozSupportLink, { + BrowserUtils: "resource://gre/modules/BrowserUtils.sys.mjs", + }); + // eslint-disable-next-line no-shadow let { XPCOMUtils } = window.XPCOMUtils ? window @@ -72,7 +76,7 @@ export default class MozSupportLink extends HTMLAnchorElement { handleEvent(e) { if (e.type == "click") { if (window.openTrustedLinkIn) { - let where = whereToOpenLink(e, false, true); + let where = MozSupportLink.BrowserUtils.whereToOpenLink(e, false, true); if (where == "current") { where = "tab"; } diff --git a/toolkit/content/widgets/notificationbox.js b/toolkit/content/widgets/notificationbox.js index 8cfc7b865c..fc3e553ca4 100644 --- a/toolkit/content/widgets/notificationbox.js +++ b/toolkit/content/widgets/notificationbox.js @@ -621,7 +621,7 @@ customElements.define("notification", MozElements.Notification); async function createNotificationMessageElement() { - await window.ensureCustomElements("moz-message-bar"); + document.createElement("moz-message-bar"); let MozMessageBar = await customElements.whenDefined("moz-message-bar"); class NotificationMessage extends MozMessageBar { static queries = { @@ -772,7 +772,6 @@ let buttonElem; if (button.hasOwnProperty("supportPage")) { - window.ensureCustomElements("moz-support-link"); buttonElem = document.createElement("a", { is: "moz-support-link", }); diff --git a/toolkit/content/widgets/panel-list/panel-list.js b/toolkit/content/widgets/panel-list/panel-list.js index 2e93b4ddc3..a2b6cb1a00 100644 --- a/toolkit/content/widgets/panel-list/panel-list.js +++ b/toolkit/content/widgets/panel-list/panel-list.js @@ -439,10 +439,6 @@ // using the mouse. Ignore the first focusin event if it's on the // triggering target. this.focusHasChanged = true; - } else if (!target || !inPanelList) { - // If the target isn't in the panel, hide. This will close when focus - // moves out of the panel. - this.hide(); } else { // Just record that there was a focusin event. this.focusHasChanged = true; diff --git a/toolkit/content/widgets/popupnotification.js b/toolkit/content/widgets/popupnotification.js index 835151496c..7dfa47728b 100644 --- a/toolkit/content/widgets/popupnotification.js +++ b/toolkit/content/widgets/popupnotification.js @@ -116,8 +116,6 @@ MozXULElement.insertFTLIfNeeded("toolkit/global/popupnotification.ftl"); this.appendChild(this.constructor.fragment); - window.ensureCustomElements("moz-button-group"); - this.button = this.querySelector(".popup-notification-primary-button"); if ( this.hasAttribute("buttonlabel") || diff --git a/toolkit/content/widgets/videocontrols.js b/toolkit/content/widgets/videocontrols.js index 73a32164aa..8d7b52c344 100644 --- a/toolkit/content/widgets/videocontrols.js +++ b/toolkit/content/widgets/videocontrols.js @@ -417,10 +417,9 @@ this.VideoControlsImplWidget = class { } // We have to check again if the media has audio here. - if (!this.isAudioOnly && !this.video.mozHasAudio) { - this.muteButton.setAttribute("noAudio", "true"); - this.muteButton.disabled = true; - } + let noAudio = !this.isAudioOnly && !this.video.mozHasAudio; + this.muteButton.toggleAttribute("noAudio", noAudio); + this.muteButton.disabled = noAudio; } // The video itself might not be fullscreen, but part of the @@ -755,7 +754,7 @@ this.VideoControlsImplWidget = class { ); } break; - case "loadedmetadata": + case "loadedmetadata": { // If a <video> doesn't have any video data, treat it as <audio> // and show the controls (they won't fade back out) if ( @@ -771,13 +770,13 @@ this.VideoControlsImplWidget = class { Math.round(this.video.currentTime * 1000), Math.round(this.video.duration * 1000) ); - if (!this.isAudioOnly && !this.video.mozHasAudio) { - this.muteButton.setAttribute("noAudio", "true"); - this.muteButton.disabled = true; - } + let noAudio = !this.isAudioOnly && !this.video.mozHasAudio; + this.muteButton.toggleAttribute("noAudio", noAudio); + this.muteButton.disabled = noAudio; this.adjustControlSize(); this.updatePictureInPictureToggleDisplay(); break; + } case "durationchange": this.updatePictureInPictureToggleDisplay(); break; diff --git a/toolkit/content/xul.css b/toolkit/content/xul.css index 908132d598..7f5b7aa295 100644 --- a/toolkit/content/xul.css +++ b/toolkit/content/xul.css @@ -600,20 +600,6 @@ menulist[popuponly] { padding: 0 !important; } -/********** splitter **********/ - -.tree-splitter { - margin-inline: -4px; - width: 8px; - max-width: 8px; - min-width: 8px; - appearance: none !important; - border: none !important; - background: none !important; - order: 2147483646; - z-index: 2147483646; -} - /******** scrollbar ********/ slider { |