diff options
Diffstat (limited to 'toolkit/content')
105 files changed, 1262 insertions, 819 deletions
diff --git a/toolkit/content/aboutLogging.js b/toolkit/content/aboutLogging.js index daff10fbec..360ab366e1 100644 --- a/toolkit/content/aboutLogging.js +++ b/toolkit/content/aboutLogging.js @@ -234,7 +234,7 @@ function populatePresets() { $("#log-modules").value = gLoggingPresets[dropdown.value].modules; setPresetAndDescription(dropdown.value); // When changing the list switch to custom. - $("#log-modules").oninput = e => { + $("#log-modules").oninput = () => { dropdown.value = "custom"; }; } @@ -534,7 +534,7 @@ function updateLogFile(file) { if (file.exists()) { openLogFileButton.disabled = false; - openLogFileButton.onclick = function (e) { + openLogFileButton.onclick = function () { file.reveal(); }; } diff --git a/toolkit/content/aboutNetError.mjs b/toolkit/content/aboutNetError.mjs index 554553fd62..1c733d5dbb 100644 --- a/toolkit/content/aboutNetError.mjs +++ b/toolkit/content/aboutNetError.mjs @@ -498,7 +498,7 @@ function initPage() { trrExceptionButton.addEventListener("click", () => { RPMSendQuery("Browser:AddTRRExcludedDomain", { hostname: HOST_NAME, - }).then(msg => { + }).then(() => { retryThis(trrExceptionButton); }); }); @@ -1061,15 +1061,15 @@ function addCertException() { () => { location.reload(); }, - err => {} + () => {} ); } -function onReturnButtonClick(e) { +function onReturnButtonClick() { RPMSendAsyncMessage("Browser:SSLErrorGoBack"); } -function copyPEMToClipboard(e) { +function copyPEMToClipboard() { const errorText = document.getElementById("certificateErrorText"); navigator.clipboard.writeText(errorText.textContent); } diff --git a/toolkit/content/aboutProfiles.js b/toolkit/content/aboutProfiles.js index 15c0419a11..38dc86c31f 100644 --- a/toolkit/content/aboutProfiles.js +++ b/toolkit/content/aboutProfiles.js @@ -139,7 +139,7 @@ function display(profileData) { td.appendChild(button); - button.addEventListener("click", function (e) { + button.addEventListener("click", function () { value.reveal(); }); } diff --git a/toolkit/content/aboutSupport.js b/toolkit/content/aboutSupport.js index f9f35e7e76..6b75776bd6 100644 --- a/toolkit/content/aboutSupport.js +++ b/toolkit/content/aboutSupport.js @@ -20,7 +20,7 @@ ChromeUtils.defineESModuleGetters(this, { ProcessType: "resource://gre/modules/ProcessType.sys.mjs", }); -window.addEventListener("load", function onload(event) { +window.addEventListener("load", function onload() { try { window.removeEventListener("load", onload); Troubleshoot.snapshot().then(async snapshot => { @@ -1051,7 +1051,7 @@ var snapshotFormatters = { } let button = $("enumerate-database-button"); if (button) { - button.addEventListener("click", function (event) { + button.addEventListener("click", function () { let { KeyValueService } = ChromeUtils.importESModule( "resource://gre/modules/kvstore.sys.mjs" ); @@ -1074,7 +1074,7 @@ var snapshotFormatters = { $("enumerate-database-result").textContent += logs.join("\n") + "\n"; }) - .catch(err => { + .catch(() => { $("enumerate-database-result").textContent += `${name}:\n`; }); } @@ -1105,7 +1105,7 @@ var snapshotFormatters = { 'th[data-l10n-id="roundtrip-latency"]' ).nextSibling.textContent = latencyString; }) - .catch(e => {}); + .catch(() => {}); } function createCDMInfoRow(cdmInfo) { @@ -1369,6 +1369,17 @@ var snapshotFormatters = { $("remote-debugging-url").textContent = data.url; }, + contentAnalysis(data) { + $("content-analysis-active").textContent = data.active; + if (data.active) { + $("content-analysis-connected-to-agent").textContent = data.connected; + $("content-analysis-agent-path").textContent = data.agentPath; + $("content-analysis-agent-failed-signature-verification").textContent = + data.failedSignatureVerification; + $("content-analysis-request-count").textContent = data.requestCount; + } + }, + accessibility(data) { $("a11y-activated").textContent = data.isActive; $("a11y-force-disabled").textContent = data.forceDisabled || 0; @@ -1606,7 +1617,7 @@ function sortedArrayFromObject(obj) { for (let prop in obj) { tuples.push([prop, obj[prop]]); } - tuples.sort(([prop1, v1], [prop2, v2]) => prop1.localeCompare(prop2)); + tuples.sort(([prop1], [prop2]) => prop1.localeCompare(prop2)); return tuples; } @@ -1757,7 +1768,7 @@ Serializer.prototype = { } }, - _startNewLine(lines) { + _startNewLine() { let currLine = this._currentLine; if (currLine) { // The current line is not empty. Trim it. @@ -1770,7 +1781,7 @@ Serializer.prototype = { this._lines.push(""); }, - _appendText(text, lines) { + _appendText(text) { this._currentLine += text; }, @@ -1926,13 +1937,13 @@ function safeModeRestart() { function setupEventListeners() { let button = $("reset-box-button"); if (button) { - button.addEventListener("click", function (event) { + button.addEventListener("click", function () { ResetProfile.openConfirmationDialog(window); }); } button = $("clear-startup-cache-button"); if (button) { - button.addEventListener("click", async function (event) { + button.addEventListener("click", async function () { const [promptTitle, promptBody, restartButtonLabel] = await document.l10n.formatValues([ { id: "startup-cache-dialog-title2" }, @@ -1965,7 +1976,7 @@ function setupEventListeners() { } button = $("restart-in-safe-mode-button"); if (button) { - button.addEventListener("click", function (event) { + button.addEventListener("click", function () { if ( Services.obs .enumerateObservers("restart-in-safe-mode") @@ -1983,7 +1994,7 @@ function setupEventListeners() { if (AppConstants.MOZ_UPDATER) { button = $("update-dir-button"); if (button) { - button.addEventListener("click", function (event) { + button.addEventListener("click", function () { // Get the update directory. let updateDir = Services.dirsvc.get("UpdRootD", Ci.nsIFile); if (!updateDir.exists()) { @@ -2001,7 +2012,7 @@ function setupEventListeners() { } button = $("show-update-history-button"); if (button) { - button.addEventListener("click", function (event) { + button.addEventListener("click", function () { window.browsingContext.topChromeWindow.openDialog( "chrome://mozapps/content/update/history.xhtml", "Update:History", @@ -2012,7 +2023,7 @@ function setupEventListeners() { } button = $("verify-place-integrity-button"); if (button) { - button.addEventListener("click", function (event) { + button.addEventListener("click", function () { PlacesDBUtils.checkAndFixDatabase().then(tasksStatusMap => { let logs = []; for (let [key, value] of tasksStatusMap) { @@ -2027,13 +2038,13 @@ function setupEventListeners() { }); } - $("copy-raw-data-to-clipboard").addEventListener("click", function (event) { + $("copy-raw-data-to-clipboard").addEventListener("click", function () { copyRawDataToClipboard(this); }); - $("copy-to-clipboard").addEventListener("click", function (event) { + $("copy-to-clipboard").addEventListener("click", function () { copyContentsToClipboard(); }); - $("profile-dir-button").addEventListener("click", function (event) { + $("profile-dir-button").addEventListener("click", function () { openProfileDirectory(); }); } diff --git a/toolkit/content/aboutSupport.xhtml b/toolkit/content/aboutSupport.xhtml index d19fb64d56..f815ab77f4 100644 --- a/toolkit/content/aboutSupport.xhtml +++ b/toolkit/content/aboutSupport.xhtml @@ -902,6 +902,38 @@ </table> #endif +#ifndef ANDROID + <!-- - - - - - - - - - - - - - - - - - - - - --> + + <h2 class="major-section" id="content-analysis" data-l10n-id="content-analysis-title"/> + + <table> + <tbody> + <tr> + <th class="column" data-l10n-id="content-analysis-active"/> + <td id="content-analysis-active"/> + </tr> + <tr> + <th class="column" data-l10n-id="content-analysis-connected-to-agent"/> + <td id="content-analysis-connected-to-agent"/> + </tr> + <tr> + <th class="column" data-l10n-id="content-analysis-agent-path"/> + <td id="content-analysis-agent-path"/> + </tr> + <tr> + <th class="column" data-l10n-id="content-analysis-agent-failed-signature-verification"/> + <td id="content-analysis-agent-failed-signature-verification"/> + </tr> + <tr> + <th class="column" data-l10n-id="content-analysis-request-count"/> + <td id="content-analysis-request-count"/> + </tr> + </tbody> + </table> + +#endif + </div> </body> diff --git a/toolkit/content/aboutTelemetry.js b/toolkit/content/aboutTelemetry.js index b25c2687d9..45a8488820 100644 --- a/toolkit/content/aboutTelemetry.js +++ b/toolkit/content/aboutTelemetry.js @@ -257,7 +257,7 @@ var PingPicker = { "mouseleave", () => (pingPickerNeedHide = true) ); - document.addEventListener("click", ev => { + document.addEventListener("click", () => { if (pingPickerNeedHide) { pingPicker.classList.add("hidden"); } @@ -966,7 +966,7 @@ var RawPayloadData = { attachObservers() { document .getElementById("payload-json-viewer") - .addEventListener("click", e => { + .addEventListener("click", () => { openJsonInFirefoxJsonViewer(JSON.stringify(gPingData.payload, null, 2)); }); }, @@ -1121,7 +1121,7 @@ var Histogram = { return outerDiv; }, - processHistogram(aHgram, aName) { + processHistogram(aHgram) { const values = Object.keys(aHgram.values).map(k => aHgram.values[k]); if (!values.length) { // If we have no values collected for this histogram, just return diff --git a/toolkit/content/aboutUrlClassifier.js b/toolkit/content/aboutUrlClassifier.js index 14b34c7e89..cc88e3bf73 100644 --- a/toolkit/content/aboutUrlClassifier.js +++ b/toolkit/content/aboutUrlClassifier.js @@ -429,7 +429,7 @@ var Cache = { createCacheEntries() { function createRow(tds, body, cols) { let tr = document.createElement("tr"); - tds.forEach(function (v, i, a) { + tds.forEach(function (v, i) { let td = document.createElement("td"); if (i == 0 && tds.length != cols) { td.setAttribute("colspan", cols - tds.length + 1); diff --git a/toolkit/content/aboutwebrtc/aboutWebrtc.mjs b/toolkit/content/aboutwebrtc/aboutWebrtc.mjs index 7e2c92a4bd..5aa8119c5a 100644 --- a/toolkit/content/aboutwebrtc/aboutWebrtc.mjs +++ b/toolkit/content/aboutwebrtc/aboutWebrtc.mjs @@ -53,7 +53,7 @@ class Renderer { // adding elements more readable, e.g. elemRenderer.elem_h4(...) instead of // elemRenderer.elem("h4", ...). const elemRenderer = new Proxy(new Renderer(), { - get(target, prop, receiver) { + get(target, prop) { // Function prefixes to proxy. const proxied = { elem_: (...args) => target.elem(...args), @@ -502,7 +502,7 @@ async function renderPeerConnectionSection() { return body; }, // Creates the filling for the disclosure - updateFn: async section => { + updateFn: async () => { let statsReports = await getStats(needsFullUpdate); needsFullUpdate = REQUEST_UPDATE_ONLY_REFRESH; @@ -1828,7 +1828,7 @@ class PrimarySection { disclosureHideL10nId, autoRefreshPref, renderFn = async () => {}, // Creates the filling for the disclosure - updateFn = async section => {}, // Updates the contents. + updateFn = async () => {}, // Updates the contents. headerElementsFn = async () => [], // Accessory elements for the heading }) { const newSect = new PrimarySection(); @@ -1937,7 +1937,7 @@ async function renderMediaCtx(rndr) { hasH264Hardware.dataset.value = ctx.hasH264Hardware; const renderFn = async () => rndr.elems_div({}, [hasH264Hardware, rndr.elem_hr(), confList.view()]); - const updateFn = async section => { + const updateFn = async () => { const newCtx = WGI.getMediaContext(); if (hasH264Hardware.dataset.value != newCtx.hasH264Hardware) { hasH264Hardware.dataset.value = newCtx.hasH264Hardware; diff --git a/toolkit/content/aboutwebrtc/graph.mjs b/toolkit/content/aboutwebrtc/graph.mjs index f2c93f0709..002b3c9d28 100644 --- a/toolkit/content/aboutwebrtc/graph.mjs +++ b/toolkit/content/aboutwebrtc/graph.mjs @@ -35,14 +35,14 @@ class GraphImpl { // The color to use for average graph lines and text averageLineColor = () => "green"; // The color to use for the max value - maxColor = ({ time, value }) => "grey"; + maxColor = () => "grey"; // The color to use for the min value - minColor = ({ time, value }) => "grey"; + minColor = () => "grey"; // Title color - titleColor = title => compStyle("--in-content-page-color"); + titleColor = () => compStyle("--in-content-page-color"); // The color to use for a data point at a time. // The destination x coordinate and graph width are also provided. - datumColor = ({ time, value, x, width }) => "red"; + datumColor = () => "red"; // Returns an SVG element that needs to be inserted into the DOM for display drawSparseValues = (dataSet, title, config) => { diff --git a/toolkit/content/contentAreaUtils.js b/toolkit/content/contentAreaUtils.js index 983fd9890d..0e7d072e6b 100644 --- a/toolkit/content/contentAreaUtils.js +++ b/toolkit/content/contentAreaUtils.js @@ -1180,10 +1180,10 @@ function openURL(aURL) { var appstartup = Services.startup; var loadListener = { - onStartRequest: function ll_start(aRequest) { + onStartRequest: function ll_start() { appstartup.enterLastWindowClosingSurvivalArea(); }, - onStopRequest: function ll_stop(aRequest, aStatusCode) { + onStopRequest: function ll_stop() { appstartup.exitLastWindowClosingSurvivalArea(); }, QueryInterface: ChromeUtils.generateQI([ @@ -1194,13 +1194,13 @@ function openURL(aURL) { loadgroup.groupObserver = loadListener; var uriListener = { - doContent(ctype, preferred, request, handler) { + doContent() { return false; }, - isPreferred(ctype, desired) { + isPreferred() { return false; }, - canHandleContent(ctype, preferred, desired) { + canHandleContent() { return false; }, loadCookie: null, diff --git a/toolkit/content/customElements.js b/toolkit/content/customElements.js index b0a8f33fe6..ef58963a02 100644 --- a/toolkit/content/customElements.js +++ b/toolkit/content/customElements.js @@ -732,7 +732,7 @@ } get label() { - return this.getAttribute("label"); + return this.getAttribute("label") || ""; } set image(val) { @@ -762,9 +762,7 @@ } get accessKey() { - return this.labelElement - ? this.labelElement.accessKey - : this.getAttribute("accesskey"); + return this.labelElement?.accessKey || this.getAttribute("accesskey"); } }; MozElements.BaseTextMixin = BaseTextMixin; diff --git a/toolkit/content/gmp-sources/openh264.json b/toolkit/content/gmp-sources/openh264.json index 9e6e9b875c..0f857866d7 100644 --- a/toolkit/content/gmp-sources/openh264.json +++ b/toolkit/content/gmp-sources/openh264.json @@ -1,54 +1,47 @@ { + "hashFunction": "sha512", + "name": "OpenH264-2.3.2", + "schema_version": 1000, "vendors": { "gmp-gmpopenh264": { "platforms": { - "Android_aarch64-gcc3": { - "fileUrl": "http://ciscobinary.openh264.org/openh264-android-aarch64-42954cf0fe8a2bdc97fdc180462a3eaefceb035f.zip", - "filesize": 557884, - "hashValue": "307d188876f3612a9168c0b4ed191db2132f2e3193bdd3024ce50adcb9c1e085ab43008531a25e93d570a377283336cda9bcd7609ee6b702c5292f12d20b616b" - }, - "Android_arm-eabi-gcc3": { - "fileUrl": "http://ciscobinary.openh264.org/openh264-android-arm-42954cf0fe8a2bdc97fdc180462a3eaefceb035f.zip", - "filesize": 539311, - "hashValue": "f4f0bfe333b7e0cd0453e787dc3c15bebe9cc771cb3e57540d53f0ac9a37eee4ea8559a45a51824ee4d706ee0b3d80b2d331468a0aa533cd958081f23ee0aaae" - }, - "Android_x86-gcc3": { - "fileUrl": "http://ciscobinary.openh264.org/openh264-android-x86-42954cf0fe8a2bdc97fdc180462a3eaefceb035f.zip", - "filesize": 589947, - "hashValue": "eb7a1c9c2d29a2fd12dfe82d0f575f1d855478640816a7fb9402ce82c65878ffc5aa3d5f8bb46cd01231005c37d86984d7a631cfe45c7d56a6d4dabc427b15a0" - }, "Darwin_aarch64-gcc3": { - "fileUrl": "http://ciscobinary.openh264.org/openh264-macosx64-aarch64-2e1774ab6dc6c43debb0b5b628bdf122a391d521-2.zip", - "filesize": 395414, - "hashValue": "d0905cd3c23541f67f9ff29ce392afdb7a5dd111906e1b5fa8fad4743b227acd7bd83d50e13ed029118a764983cf9e0a24c5321ecb9e5b88740dfbefcf34864c" + "fileUrl": "http://ciscobinary.openh264.org/openh264-macosx64-aarch64-31c4d2e4a037526fd30d4e5c39f60885986cf865.zip", + "filesize": 477938, + "hashValue": "391efb184373d533713a9e99a9e63c3bbaf614e8d8bdfdd84d4d5e53b9a737e75032187309dd00e58b58bb1033ab68d199f994744f6add57dd08f5fbb654d2f3" }, "Darwin_x86_64-gcc3": { - "fileUrl": "http://ciscobinary.openh264.org/openh264-macosx64-2e1774ab6dc6c43debb0b5b628bdf122a391d521-2.zip", - "filesize": 488639, - "hashValue": "d847b153f8ef2b4b095fbaf9f64b6d08658720ca1e4dc7288622c56d00858d038fe0fd07bc1efb0afc8f02dbd07818416ecc2555db8ed1199872b0d165f4eb62" + "fileUrl": "http://ciscobinary.openh264.org/openh264-macosx64-31c4d2e4a037526fd30d4e5c39f60885986cf865.zip", + "filesize": 552074, + "hashValue": "c649bfa20c48406ccbae1917d7478773cd5250ef995828b58cc56cc4db0a3c7ce3f89eb187bd1b3d26cda0e5e65322b710cfd66a2953adeea0e4361c51488add" + }, + "Linux_aarch64-gcc3": { + "fileUrl": "http://ciscobinary.openh264.org/openh264-linux64-aarch64-31c4d2e4a037526fd30d4e5c39f60885986cf865.zip", + "filesize": 537296, + "hashValue": "eab3fca253c10739c4930bdaf83ca7a9a0a3580937e0e945dde3a45bcdb39b6240ae0d7133ebfb10029442322f4ce6e8647917d15afea601351dc8a5f0dbf3ec" }, "Linux_x86-gcc3": { - "fileUrl": "http://ciscobinary.openh264.org/openh264-linux32-2e1774ab6dc6c43debb0b5b628bdf122a391d521.zip", - "filesize": 527704, - "hashValue": "903aecd631624db3047fc477363ac076794517bbc72b33a88a73627066b5997d9c1194975729ef2acbabba19e93574333b54e32763a5a834b8d9431b99181fd1" + "fileUrl": "http://ciscobinary.openh264.org/openh264-linux32-31c4d2e4a037526fd30d4e5c39f60885986cf865.zip", + "filesize": 623151, + "hashValue": "d80508260c6419acc09c9fde539b18e9231899786df549bc8c86e564d1fb8c500327adb96bba204a386326dd5213ae907108c9ca4fc64ae385fbb2291e0e8cc5" }, "Linux_x86_64-gcc3": { - "fileUrl": "http://ciscobinary.openh264.org/openh264-linux64-2e1774ab6dc6c43debb0b5b628bdf122a391d521.zip", - "filesize": 511815, - "hashValue": "94531e267314de661b2205c606283fb066d781e5c11027578f2a3c3aa353437c2289544074a28101b6b6f0179f0fe6bd890a0ae2bb6e1cf9053650472576366c" + "fileUrl": "http://ciscobinary.openh264.org/openh264-linux64-31c4d2e4a037526fd30d4e5c39f60885986cf865.zip", + "filesize": 583674, + "hashValue": "53a58bfb4c8124ad4f7655b99bfdea290033a085e0796b19245b33b91c0948fdac9f0c3e817130b352493a65d9a7a0fc8a7c1eedc618cdaa2b4580734a11cd9c" }, "Linux_x86_64-gcc3-asan": { "alias": "Linux_x86_64-gcc3" }, "WINNT_aarch64-msvc-aarch64": { - "fileUrl": "http://ciscobinary.openh264.org/openh264-win64-aarch64-2e1774ab6dc6c43debb0b5b628bdf122a391d521.zip", - "filesize": 558607, - "hashValue": "8d936bca08dcf3538c5c118c0f468d672c556ac2ac828a4b9d1fcbb4339885d17ebcc748a918457abbea87d21c5cab2c007ca5b4ef87f04a52d44f42ee5fdbb9" + "fileUrl": "http://ciscobinary.openh264.org/openh264-win64-aarch64-31c4d2e4a037526fd30d4e5c39f60885986cf865.zip", + "filesize": 412806, + "hashValue": "cc3306873d6ad8ea6a27096c8ce75831463633a530d8f1794ae3eba3efd4a572459b6b0f3ac73f46552a7d6c7a29b152e299d862a2f76420eee07d1d39979182" }, "WINNT_x86-msvc": { - "fileUrl": "http://ciscobinary.openh264.org/openh264-win32-2e1774ab6dc6c43debb0b5b628bdf122a391d521.zip", - "filesize": 491261, - "hashValue": "9ed5b4c27c2c159b83a1b887a1215d0472171cff422d2bc1962312f90e62d1b212955fe68bc88f826d613c9fb58b86f6fa16ebc1533e863f6a5648dcb1319bcb" + "fileUrl": "http://ciscobinary.openh264.org/openh264-win32-31c4d2e4a037526fd30d4e5c39f60885986cf865.zip", + "filesize": 472465, + "hashValue": "b5c8290bbee9503b6f9d2fcc3cbcf94f9b2d4e8ee143e37cfc8c68de593c8189aecfe447b811accecdb564c8788bd05e116f4eda62ac29b3c6b8a6fa5f564ee0" }, "WINNT_x86-msvc-x64": { "alias": "WINNT_x86-msvc" @@ -57,26 +50,18 @@ "alias": "WINNT_x86-msvc" }, "WINNT_x86_64-msvc": { - "fileUrl": "http://ciscobinary.openh264.org/openh264-win64-2e1774ab6dc6c43debb0b5b628bdf122a391d521.zip", - "filesize": 453023, - "hashValue": "06511f1f6c6d44d076b3c593528c26a602348d9c41689dbf5ff716b671c3ca5756b12cb2e5869f836dedce27b1a5cfe79b93c707fd01f8e84b620923bb61b5f1" + "fileUrl": "http://ciscobinary.openh264.org/openh264-win64-31c4d2e4a037526fd30d4e5c39f60885986cf865.zip", + "filesize": 491284, + "hashValue": "b667086ed49579592d435df2b486fe30ba1b62ddd169f19e700cd079239747dd3e20058c285fa9c10a533e34f22b5198ed9b1f92ae560a3067f3e3feacc724f1" }, "WINNT_x86_64-msvc-x64": { "alias": "WINNT_x86_64-msvc" }, "WINNT_x86_64-msvc-x64-asan": { "alias": "WINNT_x86_64-msvc" - }, - "android-x86_64": { - "fileUrl": "http://ciscobinary.openh264.org/openh264-android-x86_64-42954cf0fe8a2bdc97fdc180462a3eaefceb035f.zip", - "filesize": 539311, - "hashValue": "2c80df83c84841477cf5489e4109a0913cf3ca801063d788e100a511c9226d46059e4d28ea76496c3208c046cc44c5ce0b5263b1bfda5b731f8461ce8ce7d1b7" } }, - "version": "1.8.1.2" + "version": "2.3.2" } - }, - "hashFunction": "sha512", - "name": "OpenH264-1.8.1.2", - "schema_version": 1000 + } } diff --git a/toolkit/content/license.html b/toolkit/content/license.html index e9d2642354..fe489f74d1 100644 --- a/toolkit/content/license.html +++ b/toolkit/content/license.html @@ -1682,7 +1682,15 @@ licences. <h1><a id="apple"></a>Apple License</h1> - <p>This license applies to certain files in the directories <code>dom/media/webaudio/blink</code>, and <code>widget/cocoa</code>.</p> + <p>This license applies to parts of the code in:</p> + <ul> + <li><code>xpcom/base/DarwinObjectPtr.h</code></li> + </ul> + <p>and also some files in these directories:</p> + <ul> + <li><code>dom/media/webaudio/blink</code></li> + <li><code>widget/cocoa</code></li> + </ul> <pre> Copyright (C) 2008, 2009 Apple Inc. All rights reserved. @@ -1897,6 +1905,7 @@ into source code and to files in the following directories: <li><code>third_party/jpeg-xl/</code></li> #endif <li><code>third_party/xsimd/</code></li> + <li><code>third_party/zstd/</code></li> </ul> See the individual LICENSE files for copyright owners.</p> @@ -5147,7 +5156,6 @@ ICU 1.8.1 to ICU 57.1 © 1995-2016 International Business Machines Corporation a <ul> <li><code>security/nss/lib/dbm</code></li> - <li><code>xpcom/ds/nsQuickSort.cpp</code></li> <li><code>nsprpub/pr/src/misc/praton.c</code></li> <li><code>dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs.c</code></li> </ul> diff --git a/toolkit/content/tests/browser/browser_about_logging.js b/toolkit/content/tests/browser/browser_about_logging.js index fdf8eab57b..d9a2459c12 100644 --- a/toolkit/content/tests/browser/browser_about_logging.js +++ b/toolkit/content/tests/browser/browser_about_logging.js @@ -201,7 +201,7 @@ add_task(async function testURLParameters() { url: PAGE + "?invalid-param", }, async browser => { - await SpecialPowers.spawn(browser, [profilerPresetInURL], async inURL => { + await SpecialPowers.spawn(browser, [profilerPresetInURL], async () => { let $ = content.document.querySelector.bind(content.document); Assert.ok( !$("#error").hidden, @@ -368,7 +368,7 @@ add_task(async function testProfilerOpens() { "https://example.com/", false ); - SpecialPowers.spawn(browser, [], async savedLogModules => { + SpecialPowers.spawn(browser, [], async () => { let $ = content.document.querySelector.bind(content.document); // Override the URL the profiler uses to avoid hitting external // resources (and crash). diff --git a/toolkit/content/tests/browser/browser_bug982298.js b/toolkit/content/tests/browser/browser_bug982298.js index ffbc916a5e..9b6f636db3 100644 --- a/toolkit/content/tests/browser/browser_bug982298.js +++ b/toolkit/content/tests/browser/browser_bug982298.js @@ -50,7 +50,7 @@ add_task(async function () { let awaitFindResult2 = new Promise(resolve => { let listener = { - onFindResult(aData) { + onFindResult() { info("got find result #2"); browser.finder.removeResultListener(listener); resolve(); diff --git a/toolkit/content/tests/browser/browser_f7_caret_browsing.js b/toolkit/content/tests/browser/browser_f7_caret_browsing.js index be6ae7d1f7..c0413c459b 100644 --- a/toolkit/content/tests/browser/browser_f7_caret_browsing.js +++ b/toolkit/content/tests/browser/browser_f7_caret_browsing.js @@ -37,7 +37,7 @@ registerCleanupFunction(function () { let gCaretPromptOpeningObserver; function promiseCaretPromptOpened() { return new Promise(resolve => { - function observer(subject, topic, data) { + function observer(subject) { info("Dialog opened."); resolve(subject); gCaretPromptOpeningObserver(); diff --git a/toolkit/content/tests/browser/browser_isSynthetic.js b/toolkit/content/tests/browser/browser_isSynthetic.js index 21b22fe171..3473dfc915 100644 --- a/toolkit/content/tests/browser/browser_isSynthetic.js +++ b/toolkit/content/tests/browser/browser_isSynthetic.js @@ -11,7 +11,7 @@ LocationChangeListener.prototype = { this.browser.removeProgressListener(this); }, - onLocationChange(webProgress, request, location, flags) { + onLocationChange() { this.wasSynthetic = this.browser.isSyntheticDocument; }, diff --git a/toolkit/content/tests/browser/browser_media_wakelock_webaudio.js b/toolkit/content/tests/browser/browser_media_wakelock_webaudio.js index 7c40b5fe1a..9e18cc89f3 100644 --- a/toolkit/content/tests/browser/browser_media_wakelock_webaudio.js +++ b/toolkit/content/tests/browser/browser_media_wakelock_webaudio.js @@ -56,7 +56,6 @@ async function checkWakelockWhenChangeTabVisibility({ description, additionalParams, needLock, - elementIdForEnteringPIPMode, }) { const originalTab = gBrowser.selectedTab; info(`start a new tab for '${description}'`); diff --git a/toolkit/content/tests/browser/browser_save_folder_standalone_image.js b/toolkit/content/tests/browser/browser_save_folder_standalone_image.js index 073e71a88b..6bcc95ae65 100644 --- a/toolkit/content/tests/browser/browser_save_folder_standalone_image.js +++ b/toolkit/content/tests/browser/browser_save_folder_standalone_image.js @@ -49,7 +49,7 @@ add_task(async function () { const IMAGE_URL = "http://mochi.test:8888/browser/toolkit/content/tests/browser/doggy.png"; - await BrowserTestUtils.withNewTab(IMAGE_URL, async function (browser) { + await BrowserTestUtils.withNewTab(IMAGE_URL, async function () { let tmpDir = FileUtils.getDir("TmpD", []); let dir = newDirectory(); let downloadLastDir = new DownloadLastDir(null); diff --git a/toolkit/content/tests/browser/browser_save_resend_postdata.js b/toolkit/content/tests/browser/browser_save_resend_postdata.js index 3f3e729dab..b028cac4ae 100644 --- a/toolkit/content/tests/browser/browser_save_resend_postdata.js +++ b/toolkit/content/tests/browser/browser_save_resend_postdata.js @@ -59,7 +59,7 @@ function test() { var file = destDir.clone(); file.append("no_default_file_name"); MockFilePicker.setFiles([file]); - MockFilePicker.showCallback = function (fp) { + MockFilePicker.showCallback = function () { MockFilePicker.filterIndex = 1; // kSaveAsType_URL }; diff --git a/toolkit/content/tests/browser/common/mockTransfer.js b/toolkit/content/tests/browser/common/mockTransfer.js index f4afa44903..0240d9c14b 100644 --- a/toolkit/content/tests/browser/common/mockTransfer.js +++ b/toolkit/content/tests/browser/common/mockTransfer.js @@ -51,8 +51,7 @@ MockTransfer.prototype = { onStatusChange: function MTFC_onStatusChange( aWebProgress, aRequest, - aStatus, - aMessage + aStatus ) { // If at least one notification reported an error, the download failed. if (!Components.isSuccessCode(aStatus)) { diff --git a/toolkit/content/tests/browser/datetime/head.js b/toolkit/content/tests/browser/datetime/head.js index 46e2c78af5..532f7743b2 100644 --- a/toolkit/content/tests/browser/datetime/head.js +++ b/toolkit/content/tests/browser/datetime/head.js @@ -69,7 +69,7 @@ class DateTimeTestHelper { [selector], async selector => { let input = content.document.querySelector(selector); - await ContentTaskUtils.waitForEvent(input, "change", false, e => { + await ContentTaskUtils.waitForEvent(input, "change", false, () => { ok( content.window.windowUtils.isHandlingUserInput, "isHandlingUserInput should be true" diff --git a/toolkit/content/tests/browser/head.js b/toolkit/content/tests/browser/head.js index be15cd9684..03a239463d 100644 --- a/toolkit/content/tests/browser/head.js +++ b/toolkit/content/tests/browser/head.js @@ -177,7 +177,7 @@ function leave_icon(icon) { * Used to listen events if you just need it once */ function once(target, name) { - var p = new Promise(function (resolve, reject) { + var p = new Promise(function (resolve) { target.addEventListener( name, function () { diff --git a/toolkit/content/tests/chrome/bug263683_window.xhtml b/toolkit/content/tests/chrome/bug263683_window.xhtml index b124361fd7..74846e3c27 100644 --- a/toolkit/content/tests/chrome/bug263683_window.xhtml +++ b/toolkit/content/tests/chrome/bug263683_window.xhtml @@ -176,7 +176,7 @@ const matches = JSON.parse(gFindBar._foundMatches.dataset.l10nArgs); is(matches.total, 2, "Found correct amount of matches") - await SpecialPowers.spawn(gBrowser, [], async function(args) { + await SpecialPowers.spawn(gBrowser, [], async function() { function getSelection(docShell) { let controller = docShell.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsISelectionDisplay) diff --git a/toolkit/content/tests/chrome/bug366992_window.xhtml b/toolkit/content/tests/chrome/bug366992_window.xhtml index 698d26b43a..ee595706f5 100644 --- a/toolkit/content/tests/chrome/bug366992_window.xhtml +++ b/toolkit/content/tests/chrome/bug366992_window.xhtml @@ -46,7 +46,7 @@ isCommandEnabled(aCommand) { return aCommand == "cmd_delete"; }, - doCommand(aCommand) { } + doCommand() { } } function ok(condition, message) { diff --git a/toolkit/content/tests/chrome/chrome.toml b/toolkit/content/tests/chrome/chrome.toml index 3391a2923d..986822ac48 100644 --- a/toolkit/content/tests/chrome/chrome.toml +++ b/toolkit/content/tests/chrome/chrome.toml @@ -226,6 +226,8 @@ support-files = [ ["test_menulist_initial_selection.xhtml"] +["test_menulist_initial_selection_with_connected_callback.xhtml"] + ["test_menulist_keynav.xhtml"] ["test_menulist_null_value.xhtml"] diff --git a/toolkit/content/tests/chrome/file_editor_with_autocomplete.js b/toolkit/content/tests/chrome/file_editor_with_autocomplete.js index 78611efc70..acf2c9e9df 100644 --- a/toolkit/content/tests/chrome/file_editor_with_autocomplete.js +++ b/toolkit/content/tests/chrome/file_editor_with_autocomplete.js @@ -195,7 +195,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text exactly matches the case: type 'Mo'", completeDefaultIndex: false, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("M", { shiftKey: true }, aWindow); synthesizeKey("o", {}, aWindow); return true; @@ -212,7 +212,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text exactly matches the case: select 'Mozilla' to complete the word", completeDefaultIndex: false, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("KEY_ArrowDown", {}, aWindow); synthesizeKey("KEY_Enter", {}, aWindow); return true; @@ -226,7 +226,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text exactly matches the case: undo the word, but typed text shouldn't be canceled", completeDefaultIndex: false, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("z", { accelKey: true }, aWindow); return true; }, @@ -239,7 +239,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text exactly matches the case: undo the typed text", completeDefaultIndex: false, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("z", { accelKey: true }, aWindow); return true; }, @@ -252,7 +252,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text exactly matches the case: redo the typed text", completeDefaultIndex: false, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("Z", { accelKey: true, shiftKey: true }, aWindow); return true; }, @@ -265,7 +265,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text exactly matches the case: redo the word", completeDefaultIndex: false, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("Z", { accelKey: true, shiftKey: true }, aWindow); return true; }, @@ -278,7 +278,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text exactly matches the case: removing all text for next test...", completeDefaultIndex: false, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("a", { accelKey: true }, aWindow); synthesizeKey("KEY_Backspace", {}, aWindow); return true; @@ -293,7 +293,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case: type 'mo'", completeDefaultIndex: false, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("m", {}, aWindow); synthesizeKey("o", {}, aWindow); return true; @@ -310,7 +310,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case: select 'Mozilla' to complete the word", completeDefaultIndex: false, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("KEY_ArrowDown", {}, aWindow); synthesizeKey("KEY_Enter", {}, aWindow); return true; @@ -324,7 +324,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case: undo the word, but typed text shouldn't be canceled", completeDefaultIndex: false, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("z", { accelKey: true }, aWindow); return true; }, @@ -337,7 +337,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case: undo the typed text", completeDefaultIndex: false, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("z", { accelKey: true }, aWindow); return true; }, @@ -350,7 +350,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case: redo the typed text", completeDefaultIndex: false, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("Z", { accelKey: true, shiftKey: true }, aWindow); return true; }, @@ -363,7 +363,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case: redo the word", completeDefaultIndex: false, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("Z", { accelKey: true, shiftKey: true }, aWindow); return true; }, @@ -376,7 +376,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case: removing all text for next test...", completeDefaultIndex: false, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("a", { accelKey: true }, aWindow); synthesizeKey("KEY_Backspace", {}, aWindow); return true; @@ -392,7 +392,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text exactly matches the case (completeDefaultIndex is true): type 'Mo'", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("M", { shiftKey: true }, aWindow); synthesizeKey("o", {}, aWindow); return true; @@ -410,7 +410,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text exactly matches the case (completeDefaultIndex is true): select 'Mozilla' to complete the word", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("KEY_ArrowDown", {}, aWindow); synthesizeKey("KEY_Enter", {}, aWindow); return true; @@ -424,7 +424,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text exactly matches the case (completeDefaultIndex is true): undo the word, but typed text shouldn't be canceled", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("z", { accelKey: true }, aWindow); return true; }, @@ -437,7 +437,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text exactly matches the case (completeDefaultIndex is true): undo the typed text", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("z", { accelKey: true }, aWindow); return true; }, @@ -450,7 +450,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text exactly matches the case (completeDefaultIndex is true): redo the typed text", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("Z", { accelKey: true, shiftKey: true }, aWindow); return true; }, @@ -466,7 +466,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text exactly matches the case (completeDefaultIndex is true): redo the word", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("Z", { accelKey: true, shiftKey: true }, aWindow); return true; }, @@ -479,7 +479,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text exactly matches the case (completeDefaultIndex is true): removing all text for next test...", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("a", { accelKey: true }, aWindow); synthesizeKey("KEY_Backspace", {}, aWindow); return true; @@ -494,7 +494,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case (completeDefaultIndex is true): type 'mo'", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("m", {}, aWindow); synthesizeKey("o", {}, aWindow); return true; @@ -512,7 +512,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case (completeDefaultIndex is true): select 'Mozilla' to complete the word", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("KEY_ArrowDown", {}, aWindow); synthesizeKey("KEY_Enter", {}, aWindow); return true; @@ -528,7 +528,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case (completeDefaultIndex is true): undo the selected word, but typed text shouldn't be canceled", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("z", { accelKey: true }, aWindow); return true; }, @@ -541,7 +541,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case (completeDefaultIndex is true): undo the word, but typed text shouldn't be canceled", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("z", { accelKey: true }, aWindow); return true; }, @@ -554,7 +554,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case (completeDefaultIndex is true): undo the typed text", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("z", { accelKey: true }, aWindow); return true; }, @@ -571,7 +571,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case (completeDefaultIndex is true): redo the typed text", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("Z", { accelKey: true, shiftKey: true }, aWindow); return true; }, @@ -587,7 +587,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case (completeDefaultIndex is true): redo the default index word", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("Z", { accelKey: true, shiftKey: true }, aWindow); return true; }, @@ -600,7 +600,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case (completeDefaultIndex is true): redo the word", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("Z", { accelKey: true, shiftKey: true }, aWindow); return true; }, @@ -613,7 +613,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = { description: "Undo/Redo behavior check when typed text does not match the case (completeDefaultIndex is true): removing all text for next test...", completeDefaultIndex: true, - execute(aWindow, aTarget) { + execute(aWindow) { synthesizeKey("a", { accelKey: true }, aWindow); synthesizeKey("KEY_Backspace", {}, aWindow); return true; diff --git a/toolkit/content/tests/chrome/popup_trigger.js b/toolkit/content/tests/chrome/popup_trigger.js index 003af044e5..71846a01ea 100644 --- a/toolkit/content/tests/chrome/popup_trigger.js +++ b/toolkit/content/tests/chrome/popup_trigger.js @@ -238,7 +238,7 @@ var popupTests = [ // rollup this way. // synthesizeMouse(gTrigger, 0, -12, { }); }, - result(testname, step) { + result(testname) { is(gMenuPopup.anchorNode, null, testname + " anchorNode"); is(gMenuPopup.triggerNode, null, testname + " triggerNode"); checkClosed("trigger", testname); @@ -532,7 +532,7 @@ var popupTests = [ // event to openPopup to check the trigger node. testname: "open popup anchored with override", events: ["popupshowing thepopup 0010", "popupshown thepopup"], - test(testname, step) { + test() { // attribute overrides the position passed in gMenuPopup.setAttribute("position", "end_after"); gExpectedTriggerNode = gCachedEvent.target; @@ -546,7 +546,7 @@ var popupTests = [ gCachedEvent ); }, - result(testname, step) { + result(testname) { gExpectedTriggerNode = null; is(gMenuPopup.anchorNode, gTrigger, testname + " anchorNode"); is( @@ -564,7 +564,7 @@ var popupTests = [ "popuphidden thepopup", "DOMMenuInactive thepopup", ], - test(testname, step) { + test(testname) { synthesizeKey("KEY_Escape"); checkClosed("trigger", testname); }, @@ -574,12 +574,12 @@ var popupTests = [ testname: "open popup anchored with offsets", events: ["popupshowing thepopup", "popupshown thepopup"], autohide: "thepopup", - test(testname, step) { + test() { // attribute is empty so does not override gMenuPopup.setAttribute("position", ""); gMenuPopup.openPopup(gTrigger, "before_start", 5, 10, true, true); }, - result(testname, step) { + result(testname) { compareEdge(gTrigger, gMenuPopup, "before_start", 5, 10, testname); }, }, @@ -588,10 +588,10 @@ var popupTests = [ // to the viewport. testname: "open popup unanchored", events: ["popupshowing thepopup", "popupshown thepopup"], - test(testname, step) { + test() { gMenuPopup.openPopup(null, "after_start", 6, 8, false); }, - result(testname, step) { + result(testname) { var rect = gMenuPopup.getBoundingClientRect(); ok( rect.left == 6 && rect.top == 8 && rect.right && rect.bottom, @@ -607,11 +607,11 @@ var popupTests = [ "popuphiding thepopup", "popuphidden thepopup", ], - test(testname, step) { + test() { var item3 = document.getElementById("item3"); synthesizeMouse(item3, 4, 4, {}); }, - result(testname, step) { + result(testname) { checkClosed("trigger", testname); }, }, @@ -625,18 +625,18 @@ var popupTests = [ "popuphidden thepopup", "DOMMenuInactive thepopup", ], - test(testname, step) { + test() { gMenuPopup.hidePopup(); }, }, { testname: "open popup at screen", events: ["popupshowing thepopup", "popupshown thepopup"], - test(testname, step) { + test() { gExpectedTriggerNode = "notset"; gMenuPopup.openPopupAtScreen(gScreenX + 24, gScreenY + 20, false); }, - result(testname, step) { + result(testname) { gExpectedTriggerNode = null; is(gMenuPopup.anchorNode, null, testname + " anchorNode"); is(gMenuPopup.triggerNode, null, testname + " triggerNode"); @@ -670,7 +670,7 @@ var popupTests = [ { testname: "open context popup at screen", events: ["popupshowing thepopup 0010", "popupshown thepopup"], - test(testname, step) { + test() { gExpectedTriggerNode = gCachedEvent.target; gMenuPopup.openPopupAtScreen( gScreenX + 8, @@ -679,7 +679,7 @@ var popupTests = [ gCachedEvent ); }, - result(testname, step) { + result(testname) { gExpectedTriggerNode = null; is(gMenuPopup.anchorNode, null, testname + " anchorNode"); is( @@ -873,7 +873,7 @@ var popupTests = [ testname: "open context popup at screen with all modifiers set", events: ["popupshowing thepopup 1111", "popupshown thepopup"], autohide: "thepopup", - test(testname, step) { + test() { gMenuPopup.openPopupAtScreen( gScreenX + 8, gScreenY + 16, @@ -885,10 +885,10 @@ var popupTests = [ { testname: "open popup with open property", events: ["popupshowing thepopup", "popupshown thepopup"], - test(testname, step) { + test() { openMenu(gTrigger); }, - result(testname, step) { + result(testname) { checkOpen("trigger", testname); if (gIsMenu) { compareEdge(gTrigger, gMenuPopup, "after_start", 0, 0, testname); @@ -902,10 +902,10 @@ var popupTests = [ "DOMMenuItemActive submenu", "popupshown submenupopup", ], - test(testname, step) { + test() { openMenu(document.getElementById("submenu")); }, - result(testname, step) { + result(testname) { checkOpen("trigger", testname); checkOpen("submenu", testname); // XXXndeakin @@ -929,17 +929,17 @@ var popupTests = [ test() { gMenuPopup.hidePopup(); }, - result(testname, step) { + result(testname) { checkClosed("trigger", testname); checkClosed("submenu", testname); }, }, { testname: "open submenu with open property without parent open", - test(testname, step) { + test() { openMenu(document.getElementById("submenu")); }, - result(testname, step) { + result(testname) { checkClosed("trigger", testname); checkClosed("submenu", testname); }, @@ -950,11 +950,11 @@ var popupTests = [ return gIsMenu; }, events: ["popupshowing thepopup", "popupshown thepopup"], - test(testname, step) { + test() { gMenuPopup.setAttribute("position", "before_start"); openMenu(gTrigger); }, - result(testname, step) { + result(testname) { compareEdge(gTrigger, gMenuPopup, "before_start", 0, 0, testname); }, }, @@ -968,10 +968,10 @@ var popupTests = [ "popuphidden thepopup", "DOMMenuInactive thepopup", ], - test(testname, step) { + test() { closeMenu(gTrigger, gMenuPopup); }, - result(testname, step) { + result(testname) { checkClosed("trigger", testname); }, }, @@ -982,13 +982,13 @@ var popupTests = [ }, events: ["popupshowing thepopup", "popupshown thepopup"], autohide: "thepopup", - test(testname, step) { + test() { gMenuPopup.setAttribute("position", "start_after"); gMenuPopup.setAttribute("popupanchor", "topright"); gMenuPopup.setAttribute("popupalign", "bottomright"); openMenu(gTrigger); }, - result(testname, step) { + result(testname) { compareEdge(gTrigger, gMenuPopup, "start_after", 0, 0, testname); }, }, @@ -999,13 +999,13 @@ var popupTests = [ }, events: ["popupshowing thepopup", "popupshown thepopup"], autohide: "thepopup", - test(testname, step) { + test() { gMenuPopup.removeAttribute("position"); gMenuPopup.setAttribute("popupanchor", "bottomright"); gMenuPopup.setAttribute("popupalign", "topright"); openMenu(gTrigger); }, - result(testname, step) { + result(testname) { compareEdge(gTrigger, gMenuPopup, "after_end", 0, 0, testname); gMenuPopup.removeAttribute("popupanchor"); gMenuPopup.removeAttribute("popupalign"); @@ -1018,11 +1018,11 @@ var popupTests = [ }, events: ["popupshowing thepopup", "popupshown thepopup"], autohide: "thepopup", - test(testname, step) { + test() { gTrigger.focus(); synthesizeKey("KEY_ArrowDown", { altKey: !platformIsMac() }); }, - result(testname, step) { + result(testname) { checkOpen("trigger", testname); checkActive(gMenuPopup, "", testname); }, @@ -1033,11 +1033,11 @@ var popupTests = [ return gIsMenu; }, events: ["popupshowing thepopup", "popupshown thepopup"], - test(testname, step) { + test() { gTrigger.focus(); synthesizeKey("KEY_ArrowUp", { altKey: !platformIsMac() }); }, - result(testname, step) { + result(testname) { checkOpen("trigger", testname); checkActive(gMenuPopup, "", testname); }, @@ -1055,11 +1055,11 @@ var popupTests = [ "popuphiding thepopup", "popuphidden thepopup", ], - test(testname, step) { + test() { synthesizeKey("KEY_ArrowDown"); synthesizeKey("KEY_Enter"); }, - result(testname, step) { + result(testname) { checkClosed("trigger", testname); }, }, @@ -1070,11 +1070,11 @@ var popupTests = [ }, events: ["popupshowing thepopup", "popupshown thepopup"], autohide: "thepopup", - test(testname, step) { + test() { gTrigger.focus(); synthesizeKey(platformIsMac() ? " " : "KEY_F4"); }, - result(testname, step) { + result(testname) { checkOpen("trigger", testname); checkActive(gMenuPopup, "", testname); }, @@ -1085,7 +1085,7 @@ var popupTests = [ condition() { return gIsMenu; }, - test(testname, step) { + test() { gTrigger.focus(); if (platformIsMac()) { synthesizeKey("KEY_F4", { altKey: true }); @@ -1093,7 +1093,7 @@ var popupTests = [ synthesizeKey("", { metaKey: true }); } }, - result(testname, step) { + result(testname) { checkClosed("trigger", testname); }, }, @@ -1102,11 +1102,11 @@ var popupTests = [ condition() { return gIsMenu; }, - test(testname, step) { + test() { gTrigger.setAttribute("disabled", "true"); synthesizeMouse(gTrigger, 4, 4, {}); }, - result(testname, step) { + result(testname) { checkClosed("trigger", testname); gTrigger.removeAttribute("disabled"); }, @@ -1116,11 +1116,11 @@ var popupTests = [ testname: "openPopup with object argument", events: ["popupshowing thepopup 0000", "popupshown thepopup"], autohide: "thepopup", - test(testname, step) { + test(testname) { gMenuPopup.openPopup(gTrigger, { position: "before_start", x: 5, y: 7 }); checkOpen("trigger", testname); }, - result(testname, step) { + result(testname) { var triggerrect = gTrigger.getBoundingClientRect(); var popuprect = gMenuPopup.getBoundingClientRect(); is( @@ -1139,7 +1139,7 @@ var popupTests = [ testname: "openPopup with object argument with event", events: ["popupshowing thepopup 1000", "popupshown thepopup"], autohide: "thepopup", - test(testname, step) { + test(testname) { gMenuPopup.openPopup(gTrigger, { position: "after_start", x: 0, @@ -1153,10 +1153,10 @@ var popupTests = [ testname: "openPopup with no arguments", events: ["popupshowing thepopup", "popupshown thepopup"], autohide: "thepopup", - test(testname, step) { + test() { gMenuPopup.openPopup(); }, - result(testname, step) { + result(testname) { let isMenu = gTrigger.type == "menu"; // With no arguments, open in default menu position var triggerrect = gTrigger.getBoundingClientRect(); @@ -1184,7 +1184,7 @@ var popupTests = [ "DOMMenuItemActive submenu", "popupshown submenupopup", ], - test(testname, step) { + test(testname) { gMenuPopup.openPopup(gTrigger, "after_start", 0, 0, false, true); document .getElementById("submenupopup") @@ -1196,7 +1196,7 @@ var popupTests = [ { // remove the content nodes for the popup testname: "remove content", - test(testname, step) { + test() { var submenupopup = document.getElementById("submenupopup"); submenupopup.remove(); var popup = document.getElementById("thepopup"); diff --git a/toolkit/content/tests/chrome/test_arrowpanel.xhtml b/toolkit/content/tests/chrome/test_arrowpanel.xhtml index cd8d312e1d..f9f8a0eaf5 100644 --- a/toolkit/content/tests/chrome/test_arrowpanel.xhtml +++ b/toolkit/content/tests/chrome/test_arrowpanel.xhtml @@ -201,7 +201,7 @@ function* nextTest() // Test that a transition occurs when opening or closing the popup. if (matchMedia("(-moz-panel-animations").matches) { - function transitionEnded(event) { + function transitionEnded() { if ($("animatepanel").state != "open") { is($("animatepanel").state, "showing", "state is showing during transitionend"); ok(!animatedPopupShown, "popupshown not fired yet") diff --git a/toolkit/content/tests/chrome/test_labelcontrol.xhtml b/toolkit/content/tests/chrome/test_labelcontrol.xhtml index 06e7f96105..937d3e7403 100644 --- a/toolkit/content/tests/chrome/test_labelcontrol.xhtml +++ b/toolkit/content/tests/chrome/test_labelcontrol.xhtml @@ -40,7 +40,7 @@ function runTests() let checkboxLabel = $("checkbox-label"); is(checkboxLabel.control, "checkbox", "checkbox control"); is(checkboxLabel.labeledControlElement, checkbox, "checkbox labeledControlElement"); - is(checkbox.accessKey, "", "checkbox accessKey not set"); + is(checkbox.accessKey, null, "checkbox accessKey not set"); checkboxLabel.accessKey = "C"; is(checkbox.accessKey, "C", "checkbox accessKey set"); diff --git a/toolkit/content/tests/chrome/test_menuitem_blink.xhtml b/toolkit/content/tests/chrome/test_menuitem_blink.xhtml index 700a8a7465..ad76eee8bf 100644 --- a/toolkit/content/tests/chrome/test_menuitem_blink.xhtml +++ b/toolkit/content/tests/chrome/test_menuitem_blink.xhtml @@ -32,7 +32,7 @@ function test_crash() { var menupopup = document.getElementById("menupopup"); var menuitem = document.getElementById("menuitem"); menupopup.addEventListener("popupshown", function () { - menuitem.addEventListener("mouseup", function (e) { + menuitem.addEventListener("mouseup", function () { const observer = new MutationObserver((aMutationList, aObserver) => { for (const mutation of aMutationList) { if (mutation.attributeName != "_moz-menuactive") { diff --git a/toolkit/content/tests/chrome/test_menuitem_commands.xhtml b/toolkit/content/tests/chrome/test_menuitem_commands.xhtml index 60a35b36c5..a342b9d1d5 100644 --- a/toolkit/content/tests/chrome/test_menuitem_commands.xhtml +++ b/toolkit/content/tests/chrome/test_menuitem_commands.xhtml @@ -49,10 +49,10 @@ function runTestSet(suffix) var three = $("three" + suffix); var four = $("four" + suffix); - checkAttributes(one, "One", "", "", true, false); - checkAttributes(two, "", "", "false", false, false); + checkAttributes(one, "One", null, null, true, false); + checkAttributes(two, null, null, "false", false, false); checkAttributes(three, "Three", "T", "true", false, false); - checkAttributes(four, "Four", "F", "", false, false); + checkAttributes(four, "Four", "F", null, false, false); if (isMac && suffix) { var utils = window.windowUtils; @@ -62,8 +62,8 @@ function runTestSet(suffix) $("menu" + suffix).open = true; } - checkAttributes(one, "One", "", "", false, true); - checkAttributes(two, "Cat", "C", "", false, true); + checkAttributes(one, "One", null, null, false, true); + checkAttributes(two, "Cat", "C", null, false, true); checkAttributes(three, "Dog", "D", "false", true, true); checkAttributes(four, "Four", "F", "true", false, true); diff --git a/toolkit/content/tests/chrome/test_menulist_in_popup.xhtml b/toolkit/content/tests/chrome/test_menulist_in_popup.xhtml index 971fe90322..75fb19adcf 100644 --- a/toolkit/content/tests/chrome/test_menulist_in_popup.xhtml +++ b/toolkit/content/tests/chrome/test_menulist_in_popup.xhtml @@ -17,7 +17,7 @@ async function runTest() { let menulist = document.getElementById("menulist"); let menulistPopup = document.getElementById("menulistpopup"); - menulistPopup.addEventListener("popupshown", function(e) { + menulistPopup.addEventListener("popupshown", function() { ok(false, "Menulist popup shown"); }); diff --git a/toolkit/content/tests/chrome/test_menulist_initial_selection.xhtml b/toolkit/content/tests/chrome/test_menulist_initial_selection.xhtml index 19e9beae67..255318f5a7 100644 --- a/toolkit/content/tests/chrome/test_menulist_initial_selection.xhtml +++ b/toolkit/content/tests/chrome/test_menulist_initial_selection.xhtml @@ -29,6 +29,9 @@ async function runTest() { is(menulist2.value, "", "menulist2 should not be selected to the first item's value"); is(menulist2.label, "None", "menulist2 should not be selected to the first item's value"); + is(menulist1.menupopup.querySelectorAll('menuitem[selected="true"]').length, 1, "menulist1 should have only one selected item."); + is(menulist2.menupopup.querySelectorAll('menuitem[selected="true"]').length, 0, "menulist2 should have no selected items."); + SimpleTest.finish(); } @@ -37,17 +40,17 @@ async function runTest() { <panel> <menulist id="menulist1" value="" label="None"> - <menupopup id="menulistpopup"> + <menupopup id="menulistpopup1"> <menuitem value="1" label="One"/> <menuitem value="2" label="Two"/> <menuitem value="3" label="Three"/> </menupopup> </menulist> <menulist id="menulist2" value="" label="None" noinitialselection="true"> - <menupopup id="menulistpopup"> - <menuitem value="1" label="One"/> - <menuitem value="2" label="Two"/> - <menuitem value="3" label="Three"/> + <menupopup id="menulistpopup2"> + <menuitem value="4" label="Four"/> + <menuitem value="5" label="Five"/> + <menuitem value="6" label="Six"/> </menupopup> </menulist> </panel> diff --git a/toolkit/content/tests/chrome/test_menulist_initial_selection_with_connected_callback.xhtml b/toolkit/content/tests/chrome/test_menulist_initial_selection_with_connected_callback.xhtml new file mode 100644 index 0000000000..2c9b462948 --- /dev/null +++ b/toolkit/content/tests/chrome/test_menulist_initial_selection_with_connected_callback.xhtml @@ -0,0 +1,80 @@ +<window title="Menulist Initial Selection Connected Callback Test" + onload="setTimeout(runTest, 0)" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> +<script> +<![CDATA[ +SimpleTest.waitForExplicitFinish(); + +async function runTest() { + const panel = document.querySelector("panel"); + + // Dynamically initialize two menulists, one with the noinitialselection + // attribute and one without, but ensure that their delayConnectedCallback + // functions always return true to ensure that connectedCallback will not run yet. + const menulist1 = document.createXULElement("menulist"); + menulist1.delayConnectedCallback = () => true; + menulist1.setAttribute("id", "menulist1"); + menulist1.appendItem(/* label */ "One", /* id */ "1"); + menulist1.appendItem(/* label */ "Two", /* id */ "2"); + menulist1.appendItem(/* label */ "Three", /* id */ "3"); + is(menulist1.menupopup.querySelectorAll('menuitem[selected="true"]').length, 0, "menulist1 should have no selected items yet."); + + const menulist2 = document.createXULElement("menulist"); + menulist2.delayConnectedCallback = () => true; + menulist2.setAttribute("id", "menulist2"); + menulist2.setAttribute("noinitialselection", "true"); + menulist2.appendItem(/* label */ "Four", /* id */ "4"); + menulist2.appendItem(/* label */ "Five", /* id */ "5"); + menulist2.appendItem(/* label */ "Six", /* id */ "6"); + is(menulist2.menupopup.querySelectorAll('menuitem[selected="true"]').length, 0, "menulist2 should have no selected items yet."); + + // Set their values before allowing connectedCallback to run, simulating + // a race condition where an initial value is manually set before the + // connectedCallback is invoked. + menulist1.value = "2"; + panel.appendChild(menulist1); + menulist1.delayConnectedCallback = () => false; + menulist1.connectedCallback(); + + menulist2.value = "5"; + panel.appendChild(menulist2); + menulist2.delayConnectedCallback = () => false; + menulist2.connectedCallback(); + + const panelShown = new Promise(r => panel.addEventListener("popupshown", r, { once: true })); + info("opening panel"); + panel.openPopup(null, { x: 0, y: 0 }); + await panelShown; + info("panel opened"); + + is(menulist1.value, "2", "menulist1 should have the second menuitem's value"); + is(menulist1.label, "Two", "menulist1 should have the second menuitem's label"); + is(menulist1.menupopup.querySelectorAll('menuitem[selected="true"]').length, 1, "menulist1 should have only one selected item."); + + is(menulist2.value, "5", "menulist2 should not be selected to the second item's value"); + is(menulist2.label, "Five", "menulist2 should not be selected to the second item's value"); + is(menulist2.menupopup.querySelectorAll('menuitem[selected="true"]').length, 1, "menulist2 should have only one selected item."); + + menulist1.value = "3"; + menulist2.value = "6"; + + is(menulist1.value, "3", "menulist1 should have the third menuitem's value"); + is(menulist1.label, "Three", "menulist1 should have the third menuitem's label"); + is(menulist1.menupopup.querySelectorAll('menuitem[selected="true"]').length, 1, "menulist1 should have only one selected item."); + + is(menulist2.value, "6", "menulist2 should not be selected to the third item's value"); + is(menulist2.label, "Six", "menulist2 should not be selected to the third item's value"); + is(menulist2.menupopup.querySelectorAll('menuitem[selected="true"]').length, 1, "menulist2 should have only one selected item."); + + SimpleTest.finish(); +} + +]]> +</script> +<panel></panel> +</window> + + diff --git a/toolkit/content/tests/chrome/test_menulist_null_value.xhtml b/toolkit/content/tests/chrome/test_menulist_null_value.xhtml index 9312c236dc..e0ef42f5bd 100644 --- a/toolkit/content/tests/chrome/test_menulist_null_value.xhtml +++ b/toolkit/content/tests/chrome/test_menulist_null_value.xhtml @@ -34,7 +34,7 @@ function runTests() list.selectedItem = null; is(list.value, "", "Check list value after setting selectedItem to null"); - is(list.getAttribute("label"), "", "Check list label after setting selectedItem to null"); + is(list.getAttribute("label"), null, "Check list label after setting selectedItem to null"); // select something again to make sure the label is not already empty list.selectedIndex = 1; @@ -61,14 +61,14 @@ function runTests() // set the value to null and test it (bug 408940) list.value = null; is(list.value, "", "Check list value after setting value to null"); - is(list.getAttribute("label"), "", "Check list label after setting value to null"); + is(list.getAttribute("label"), null, "Check list label after setting value to null"); // select something again to make sure the label is not already empty list.selectedIndex = 1; // set the value to undefined and test it (bug 408940) list.value = undefined; is(list.value, "", "Check list value after setting value to undefined"); - is(list.getAttribute("label"), "", "Check list label after setting value to undefined"); + is(list.getAttribute("label"), null, "Check list label after setting value to undefined"); // select something again to make sure the label is not already empty list.selectedIndex = 1; @@ -76,7 +76,7 @@ function runTests() // and make sure the previous label is removed list.value = "this does not exist"; is(list.value, "this does not exist", "Check the list value after setting it to something not associated witn an existing menuitem"); - is(list.getAttribute("label"), "", "Check that the list label is empty after selecting a nonexistent item"); + is(list.getAttribute("label"), null, "Check that the list label is empty after selecting a nonexistent item"); SimpleTest.finish(); } diff --git a/toolkit/content/tests/chrome/test_notificationbox.xhtml b/toolkit/content/tests/chrome/test_notificationbox.xhtml index 8de985175a..9a2bc9d888 100644 --- a/toolkit/content/tests/chrome/test_notificationbox.xhtml +++ b/toolkit/content/tests/chrome/test_notificationbox.xhtml @@ -89,8 +89,8 @@ function testtag_notificationbox_buttonpressed(notification, button) } let buttonsPressedLog = ""; -function testtag_notificationbox_button1pressed(notification, button) { buttonsPressedLog += "button1"; return true; } -function testtag_notificationbox_button2pressed(notification, button) { buttonsPressedLog += "button2"; return true; } +function testtag_notificationbox_button1pressed() { buttonsPressedLog += "button1"; return true; } +function testtag_notificationbox_button2pressed() { buttonsPressedLog += "button2"; return true; } function testtag_notificationbox(nb) { @@ -227,7 +227,7 @@ var tests = nb.removeNotification(ntf); return ntf; }, - result(nb, ntf) { + result(nb) { testtag_notificationbox_State(nb, "removeNotification", null, 0); } }, @@ -394,7 +394,7 @@ var tests = nb.removeCurrentNotification(); return ntf; }, - result(nb, ntf) { + result(nb) { testtag_notificationbox_State(nb, "removeCurrentNotification", null, 0); } }, @@ -451,7 +451,7 @@ var tests = }, testtag_notificationbox_buttons_nopopup); return ntf; }, - result(nb, ntf) { + result(nb) { let buttons = nb.currentNotification.buttonContainer.querySelectorAll("* button"); buttons[0].focus(); @@ -510,7 +510,7 @@ var tests = } }, { - async test(nb, unused) { + async test(nb) { // add a number of notifications and check that they are added in order await nb.appendNotification("4", { label: "Four", priority: nb.PRIORITY_INFO_HIGH }, testtag_notificationbox_buttons); @@ -537,11 +537,11 @@ var tests = { // test closing notifications to make sure that the current notification is still set properly repeat: true, - test(nb, testidx) { + test() { this.repeat = false; return undefined; }, - result(nb, arr) { + result(nb) { let notificationOrder = [4, 7, 2, 8, 5, 6, 1, 9, 10, 3]; let allNotificationValues = [...nb.stack.children].map(n => n.getAttribute("value")); is(allNotificationValues.length, notificationOrder.length, "Expected number of notifications"); @@ -556,7 +556,7 @@ var tests = } }, { - async test(nb, ntf) { + async test(nb) { var exh = false; try { await nb.appendNotification("no", { label: "no", priority: -1 }); diff --git a/toolkit/content/tests/chrome/test_popup_keys.xhtml b/toolkit/content/tests/chrome/test_popup_keys.xhtml index 6b8dd31143..e72c496a59 100644 --- a/toolkit/content/tests/chrome/test_popup_keys.xhtml +++ b/toolkit/content/tests/chrome/test_popup_keys.xhtml @@ -37,7 +37,7 @@ let gLastFirstMenuActiveValue = null; function waitForEvent(target, eventName) { return new Promise(resolve => { - target.addEventListener(eventName, function eventOccurred(event) { + target.addEventListener(eventName, function eventOccurred() { resolve(); }, { once: true}); }); diff --git a/toolkit/content/tests/chrome/test_popup_moveToAnchor.xhtml b/toolkit/content/tests/chrome/test_popup_moveToAnchor.xhtml index a7800caaad..628ff2a851 100644 --- a/toolkit/content/tests/chrome/test_popup_moveToAnchor.xhtml +++ b/toolkit/content/tests/chrome/test_popup_moveToAnchor.xhtml @@ -20,7 +20,7 @@ <script> SimpleTest.waitForExplicitFinish(); -function runTest(id) +function runTest() { $("popup").openPopup($("button1"), "after_start"); } diff --git a/toolkit/content/tests/chrome/test_richlistbox.xhtml b/toolkit/content/tests/chrome/test_richlistbox.xhtml index 48303e0172..65f3626a8c 100644 --- a/toolkit/content/tests/chrome/test_richlistbox.xhtml +++ b/toolkit/content/tests/chrome/test_richlistbox.xhtml @@ -5,7 +5,6 @@ XUL Widget Test for listbox direction --> <window title="Listbox direction test" - onload="test_richlistbox()" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> @@ -26,8 +25,7 @@ function getScrollIndexAmount(aDirection) { return (4 * aDirection + richListBox.currentIndex); } -function test_richlistbox() -{ +add_task(function test_richlistbox() { var height = richListBox.clientHeight; var item; do { @@ -93,9 +91,22 @@ function test_richlistbox() richListBox.selectedItem = richListBox.firstChild; richListBox.firstChild.nextSibling.setAttribute("disabled", true); richListBox.focus(); + synthesizeKey("KEY_ArrowDown", {}, window); is(richListBox.selectedItems.length, 1, "one item selected"); - is(richListBox.selectedItems[0], richListBox.firstChild, "first item selected"); + is(richListBox.selectedItems[0], richListBox.getItemAtIndex(2), "skipped over disabled item on keydown"); + + synthesizeKey("KEY_ArrowUp", {}, window); + is(richListBox.selectedItems.length, 1, "one item selected"); + is(richListBox.selectedItems[0], richListBox.firstChild, "skipped over disabled item on keyup"); + + synthesizeMouseAtCenter(richListBox.getItemAtIndex(1), {}); + is(richListBox.selectedItems.length, 1, "one item selected"); + is(richListBox.selectedItems[0], richListBox.firstChild, "cannot select disabled item"); + + synthesizeMouseAtCenter(richListBox.getItemAtIndex(2), {}); + is(richListBox.selectedItems.length, 1, "one item selected"); + is(richListBox.selectedItems[0], richListBox.getItemAtIndex(2), "can select enabled item"); // Selected item re-insertion should keep the item selected. richListBox.clearSelection(); @@ -107,9 +118,7 @@ function test_richlistbox() richListBox.append(item); is(richListBox.selectedItems.length, 1, "one item selected"); is(richListBox.selectedItems[0], item, "last (previosly first) item selected"); - - SimpleTest.finish(); -} +}); ]]> </script> diff --git a/toolkit/content/tests/chrome/test_tree_view.xhtml b/toolkit/content/tests/chrome/test_tree_view.xhtml index 5e45161c6c..c9ec889995 100644 --- a/toolkit/content/tests/chrome/test_tree_view.xhtml +++ b/toolkit/content/tests/chrome/test_tree_view.xhtml @@ -24,23 +24,23 @@ var view = value: "", rowCount: 8, getCellText(row, column) { return this.treeData[row % 4][column.index]; }, - getCellValue(row, column) { return this.value; }, + getCellValue() { return this.value; }, setCellText(row, column, val) { this.treeData[row % 4][column.index] = val; }, setCellValue(row, column, val) { this.value = val; }, setTree(tree) { this.tree = tree; }, - isContainer(row) { return false; }, - isContainerOpen(row) { return false; }, - isContainerEmpty(row) { return false; }, - isSeparator(row) { return false; }, - isSorted(row) { return false; }, + isContainer() { return false; }, + isContainerOpen() { return false; }, + isContainerEmpty() { return false; }, + isSeparator() { return false; }, + isSorted() { return false; }, isEditable(row, column) { return row != 2 || column.index != 1; }, - getParentIndex(row, column) { return -1; }, - getLevel(row) { return 0; }, - hasNextSibling(row, column) { return row != this.rowCount - 1; }, - getImageSrc(row, column) { return ""; }, - cycleHeader(column) { }, - getRowProperties(row) { return ""; }, - getCellProperties(row, column) { return ""; }, + getParentIndex() { return -1; }, + getLevel() { return 0; }, + hasNextSibling(row) { return row != this.rowCount - 1; }, + getImageSrc() { return ""; }, + cycleHeader() { }, + getRowProperties() { return ""; }, + getCellProperties() { return ""; }, getColumnProperties(column) { if (!column.index) { diff --git a/toolkit/content/tests/chrome/window_chromemargin.xhtml b/toolkit/content/tests/chrome/window_chromemargin.xhtml index 81bcba62fe..8c7cf5c0d3 100644 --- a/toolkit/content/tests/chrome/window_chromemargin.xhtml +++ b/toolkit/content/tests/chrome/window_chromemargin.xhtml @@ -16,15 +16,19 @@ function ok(condition, message) { window.arguments[0].SimpleTest.ok(condition, message); } +function is(a, b, message) { + window.arguments[0].SimpleTest.is(a, b, message); +} + function doSingleTest(param) { var exception = null; try { document.documentElement.removeAttribute("chromemargin"); document.documentElement.setAttribute("chromemargin", param); - ok(document. + is(document. documentElement. - getAttribute("chromemargin") == param, "couldn't set/get chromemargin?"); + getAttribute("chromemargin"), param, "couldn't set/get chromemargin?"); } catch (ex) { exception = ex; } @@ -44,7 +48,7 @@ function runTests() // test remove doc.removeAttribute("chromemargin"); - ok(doc.getAttribute("chromemargin") == "", "couldn't remove chromemargin?"); + is(doc.getAttribute("chromemargin"), null, "couldn't remove chromemargin?"); // we already test these really well in a c++ test in widget doSingleTest("1,2,3,4"); diff --git a/toolkit/content/tests/chrome/window_cursorsnap_dialog.xhtml b/toolkit/content/tests/chrome/window_cursorsnap_dialog.xhtml index d5c0e2753e..fa239a87af 100644 --- a/toolkit/content/tests/chrome/window_cursorsnap_dialog.xhtml +++ b/toolkit/content/tests/chrome/window_cursorsnap_dialog.xhtml @@ -60,7 +60,7 @@ function finish() window.close(); } -function onMouseMove(aEvent) +function onMouseMove() { var button = document.getElementById("dialog").getButton("accept"); if (button.disabled) diff --git a/toolkit/content/tests/chrome/window_keys.xhtml b/toolkit/content/tests/chrome/window_keys.xhtml index 77a098ef0b..51f3be0a33 100644 --- a/toolkit/content/tests/chrome/window_keys.xhtml +++ b/toolkit/content/tests/chrome/window_keys.xhtml @@ -82,7 +82,7 @@ function runTest() document.documentElement.appendChild(keyset); iterateKeys(true, "appended"); - var accelText = menuitem => menuitem.getAttribute("acceltext").toLowerCase(); + var accelText = menuitem => (menuitem.getAttribute("acceltext") || "").toLowerCase(); $("menubutton").open = true; diff --git a/toolkit/content/tests/chrome/window_largemenu.xhtml b/toolkit/content/tests/chrome/window_largemenu.xhtml index d84b045e78..8e6b6718b4 100644 --- a/toolkit/content/tests/chrome/window_largemenu.xhtml +++ b/toolkit/content/tests/chrome/window_largemenu.xhtml @@ -363,8 +363,8 @@ function testPopupMovement() is(screenX, expectedx, gTests[gTestIndex] + " (6000, 100) x"); is(screenY, 100, gTests[gTestIndex] + " (6000, 100) y"); - is(popup.getAttribute("left"), "", gTests[gTestIndex] + " left is empty after moving"); - is(popup.getAttribute("top"), "", gTests[gTestIndex] + " top is empty after moving"); + is(popup.getAttribute("left"), null, gTests[gTestIndex] + " left is empty after moving"); + is(popup.getAttribute("top"), null, gTests[gTestIndex] + " top is empty after moving"); popup.setAttribute("left", "80"); popup.setAttribute("top", "82"); [screenX, screenY] = getScreenXY(popup); @@ -387,8 +387,8 @@ function testPopupMovement() is(screenX, expectedx, gTests[gTestIndex] + " move after set left and top x to -1"); is(screenY, expectedy, gTests[gTestIndex] + " move after set left and top y to -1"); - is(popup.getAttribute("left"), "", gTests[gTestIndex] + " left is not set after moving to -1"); - is(popup.getAttribute("top"), "", gTests[gTestIndex] + " top is not set after moving to -1"); + is(popup.getAttribute("left"), null, gTests[gTestIndex] + " left is not set after moving to -1"); + is(popup.getAttribute("top"), null, gTests[gTestIndex] + " top is not set after moving to -1"); popup.hidePopup(); } diff --git a/toolkit/content/tests/chrome/window_maximized_persist.xhtml b/toolkit/content/tests/chrome/window_maximized_persist.xhtml index f7eb695f0f..10f7d36d07 100644 --- a/toolkit/content/tests/chrome/window_maximized_persist.xhtml +++ b/toolkit/content/tests/chrome/window_maximized_persist.xhtml @@ -8,7 +8,7 @@ id="window" persist="height width sizemode"> <script type="application/javascript"><![CDATA[ - window.addEventListener("sizemodechange", evt => { + window.addEventListener("sizemodechange", () => { window.arguments[0].postMessage("sizemodechange", "*"); }); ]]></script> diff --git a/toolkit/content/tests/chrome/window_maximized_persist_with_no_titlebar.xhtml b/toolkit/content/tests/chrome/window_maximized_persist_with_no_titlebar.xhtml index 83fede7fae..e104dfa652 100644 --- a/toolkit/content/tests/chrome/window_maximized_persist_with_no_titlebar.xhtml +++ b/toolkit/content/tests/chrome/window_maximized_persist_with_no_titlebar.xhtml @@ -9,7 +9,7 @@ id="window" persist="height width sizemode"> <script type="application/javascript"><![CDATA[ - window.addEventListener("sizemodechange", evt => { + window.addEventListener("sizemodechange", () => { window.arguments[0].postMessage("sizemodechange", "*"); }); ]]></script> diff --git a/toolkit/content/tests/chrome/window_popup_anchoratrect.xhtml b/toolkit/content/tests/chrome/window_popup_anchoratrect.xhtml index 524a95b643..2262ba08e9 100644 --- a/toolkit/content/tests/chrome/window_popup_anchoratrect.xhtml +++ b/toolkit/content/tests/chrome/window_popup_anchoratrect.xhtml @@ -79,7 +79,7 @@ let tests = [ }, ]; -function runTest(id) +function runTest() { menupopup = $("popup"); nextTest(); diff --git a/toolkit/content/tests/chrome/window_tooltip.xhtml b/toolkit/content/tests/chrome/window_tooltip.xhtml index b78075de45..e6ee5c6b42 100644 --- a/toolkit/content/tests/chrome/window_tooltip.xhtml +++ b/toolkit/content/tests/chrome/window_tooltip.xhtml @@ -30,6 +30,8 @@ var gOriginalWidth = -1; var gOriginalHeight = -1; var gButton = null; +const kTooltipOffsetVertical = 10; + function runTest() { startPopupTests(popupTests); @@ -112,7 +114,7 @@ var popupTests = [ Math.round(buttonrect.left + parseFloat(popupstyle.marginLeft) + 6), testname + " left position of tooltip"); is(Math.round(rect.top), - Math.round(buttonrect.top + parseFloat(popupstyle.marginTop) + 6), + Math.round(buttonrect.top + parseFloat(popupstyle.marginTop) + 6 + kTooltipOffsetVertical), testname + " top position of tooltip"); var labelrect = document.getElementById("label").getBoundingClientRect(); @@ -159,7 +161,7 @@ var popupTests = [ Math.round(buttonrect.left + parseFloat(popupstyle.marginLeft) + 4), testname + " left position of tooltip"); is(Math.round(rect.top), - Math.round(buttonrect.top + parseFloat(popupstyle.marginTop) + 4), + Math.round(buttonrect.top + parseFloat(popupstyle.marginTop) + 4 + kTooltipOffsetVertical), testname + " top position of tooltip"); var labelrect = document.getElementById("label").getBoundingClientRect(); @@ -204,7 +206,7 @@ var popupTests = [ Math.round(buttonrect.left + parseFloat(popupstyle.marginLeft) + 6), testname + " left position of tooltip"); is(Math.round(rect.top), - Math.round(buttonrect.top + parseFloat(popupstyle.marginTop) + 6), + Math.round(buttonrect.top + parseFloat(popupstyle.marginTop) + 6 + kTooltipOffsetVertical), testname + " top position of tooltip"); var labelrect = document.getElementById("label").getBoundingClientRect(); @@ -327,7 +329,43 @@ var popupTests = [ // that the original height has increased by at least 10 pixels ok(gOriginalHeight + 10 < rect.bottom - rect.top, testname + " tooltip is wrapped"); } -} +}, +{ + testname: "anchored tooltip with no offset", + events: ["popupshowing thetooltip", "popupshown thetooltip"], + autohide: "thetooltip", + test() { + gButton = document.getElementById("withtooltip"); + document + .getElementById("thetooltip") + .setAttribute( + "onpopupshowing", + "this.moveToAnchor(this.triggerNode, 'after_start');" + ); + disableNonTestMouse(true); + synthesizeMouse(gButton, 2, 2, { type: "mouseover" }); + synthesizeMouse(gButton, 4, 4, { type: "mousemove" }); + synthesizeMouse(gButton, 6, 6, { type: "mousemove" }); + disableNonTestMouse(false); + }, + result(testname) { + var buttonrect = document + .getElementById("withtooltip") + .getBoundingClientRect(); + var tooltip = document.getElementById("thetooltip"); + var rect = tooltip.getBoundingClientRect(); + var popupstyle = window.getComputedStyle(tooltip); + + // Offset does not apply to anchored tooltips + is( + Math.round(rect.top), + Math.round(buttonrect.bottom + parseFloat(popupstyle.marginTop)), + testname + " top position of tooltip" + ); + + tooltip.removeAttribute("onpopupshowing"); + }, +}, ]; var waitSteps = 0; @@ -359,7 +397,14 @@ function moveWindowTo(x, y, callback, arg) } } -window.arguments[0].SimpleTest.waitForFocus(runTest, window); +(async function() { + let parent = window.arguments[0]; + await Promise.all([ + parent.SimpleTest.promiseFocus(window), + parent.SpecialPowers.pushPrefEnv({set: [["ui.tooltipOffsetVertical", kTooltipOffsetVertical]]}), + ]); + runTest(); +})(); ]]> </script> diff --git a/toolkit/content/tests/widgets/chrome.toml b/toolkit/content/tests/widgets/chrome.toml index 18fe0d153a..fa10249e89 100644 --- a/toolkit/content/tests/widgets/chrome.toml +++ b/toolkit/content/tests/widgets/chrome.toml @@ -5,7 +5,7 @@ support-files = [ "popup_shared.js", "window_label_checkbox.xhtml", "window_menubar.xhtml", - "seek_with_sound.ogg", + "seek_with_sound.webm", ] prefs = ["app.support.baseURL='https://support.mozilla.org/'"] @@ -63,7 +63,7 @@ skip-if = [ ["test_videocontrols_focus.html"] support-files = [ "head.js", - "video.ogg", + "video.webm", ] skip-if = [ "os == 'android'", diff --git a/toolkit/content/tests/widgets/file_videocontrols_jsdisabled.html b/toolkit/content/tests/widgets/file_videocontrols_jsdisabled.html index 56917b69ac..95dba91eea 100644 --- a/toolkit/content/tests/widgets/file_videocontrols_jsdisabled.html +++ b/toolkit/content/tests/widgets/file_videocontrols_jsdisabled.html @@ -1,2 +1,2 @@ -<video src="seek_with_sound.ogg" controls autoplay=true></video> +<video src="seek_with_sound.webm" controls autoplay=true></video> <script>window.testExpando = true;</script> diff --git a/toolkit/content/tests/widgets/head.js b/toolkit/content/tests/widgets/head.js index d7473fa92d..2a72845a27 100644 --- a/toolkit/content/tests/widgets/head.js +++ b/toolkit/content/tests/widgets/head.js @@ -51,7 +51,7 @@ function executeTests() { } function once(target, name, cb) { - let p = new Promise(function (resolve, reject) { + let p = new Promise(function (resolve) { target.addEventListener( name, function () { diff --git a/toolkit/content/tests/widgets/mochitest.toml b/toolkit/content/tests/widgets/mochitest.toml index 7e20352256..efd86f1208 100644 --- a/toolkit/content/tests/widgets/mochitest.toml +++ b/toolkit/content/tests/widgets/mochitest.toml @@ -5,8 +5,8 @@ support-files = [ "file_videocontrols_jsdisabled.html", "image.png", "image-zh.png", - "seek_with_sound.ogg", - "video.ogg", + "seek_with_sound.webm", + "video.webm", "head.js", "tree_shared.js", "test-webvtt-1.vtt", @@ -97,7 +97,10 @@ skip-if = [ ["test_videocontrols_size.html"] ["test_videocontrols_standalone.html"] -skip-if = ["os == 'android'"] # bug 1075573 +skip-if = [ + "os == 'linux'", # bug 1804621 + "os == 'android'", # bug 1075573 +] ["test_videocontrols_video_direction.html"] skip-if = [ diff --git a/toolkit/content/tests/widgets/seek_with_sound.ogg b/toolkit/content/tests/widgets/seek_with_sound.ogg Binary files differdeleted file mode 100644 index c86d9946bd..0000000000 --- a/toolkit/content/tests/widgets/seek_with_sound.ogg +++ /dev/null diff --git a/toolkit/content/tests/widgets/seek_with_sound.webm b/toolkit/content/tests/widgets/seek_with_sound.webm Binary files differnew file mode 100644 index 0000000000..dd60cc5a0a --- /dev/null +++ b/toolkit/content/tests/widgets/seek_with_sound.webm diff --git a/toolkit/content/tests/widgets/test_moz_button.html b/toolkit/content/tests/widgets/test_moz_button.html index 473b2d1a1c..a849ccc956 100644 --- a/toolkit/content/tests/widgets/test_moz_button.html +++ b/toolkit/content/tests/widgets/test_moz_button.html @@ -75,24 +75,23 @@ color: "--button-text-color-primary", height: "--button-min-height", }); - assertButtonPropertiesMatch(four, { width: "--button-size-icon", height: "--button-size-icon", backgroundColor: "--button-background-color", - fill: "--button-text-color", + fill: "--icon-color", }); assertButtonPropertiesMatch(five, { width: "--button-size-icon", height: "--button-size-icon", backgroundColor: "transparent", - fill: "--button-text-color", + fill: "--icon-color", }); assertButtonPropertiesMatch(six, { width: "--button-size-icon", height: "--button-size-icon", backgroundColor: "transparent", - fill: "--button-text-color", + fill: "--icon-color", }); buttons.forEach(btn => (btn.size = "small")); diff --git a/toolkit/content/tests/widgets/test_moz_card.html b/toolkit/content/tests/widgets/test_moz_card.html index ef4e67d0fa..aa9ecfde31 100644 --- a/toolkit/content/tests/widgets/test_moz_card.html +++ b/toolkit/content/tests/widgets/test_moz_card.html @@ -13,6 +13,11 @@ <body> <p id="display"></p> + <style> + moz-card.withHeadingIcon::part(icon) { + background-image: url("chrome://browser/skin/preferences/category-general.svg"); + } + </style> <div id="content"> <moz-card id="default-card" data-l10n-id="test-id-1" data-l10n-attrs="heading"> <div>TEST</div> @@ -25,6 +30,12 @@ </moz-card> <hr /> + <moz-card id="heading-icon-card" data-l10n-id="test-id-3" data-l10n-attrs="heading" heading="heading with icon" + type="accordion" icon class="withHeadingIcon"> + <div>heading icon test content</div> + </moz-card> + <hr /> + </div> <pre id="test"></pre> <script> @@ -58,12 +69,16 @@ } - function assertAccordionCardProperties(card, expectedValues) { + function assertAccordionCardProperties(card) { ok(card.detailsEl, "The details element should exist"); ok(card.detailsEl.querySelector("summary"), "There should be a summary element within the details element"); ok(card.detailsEl.querySelector("summary").querySelector(".chevron-icon"), "There should be a chevron icon div within the summary element"); } + function assertHeadingIconCardProperties(card) { + ok(card.shadowRoot.querySelector("#heading-wrapper").querySelector("#heading-icon"), "The heading icon element should exist"); + } + async function generateCard(values) { let card = document.createElement("moz-card"); for (let [key, value] of Object.entries(values)) { @@ -152,6 +167,54 @@ ); }); + add_task(async function testHeadingIconCard() { + assertBasicProperties(document.getElementById("heading-icon-card"), + { + "data-l10n-id": "test-id-3", + "data-l10n-attrs": "heading", + contentText: "heading icon test content", + headingText: "heading with icon", + } + ); + assertHeadingIconCardProperties(document.getElementById("heading-icon-card"), + { + "data-l10n-id": "test-id-3", + "data-l10n-attrs": "heading", + contentText: "heading icon test content", + headingText: "heading with icon", + } + ); + + let headingIconCard = await generateCard( + { + class: "heading-icon-class", + type: "accordion", + icon: "", + id: "generated-heading-icon-card", + "data-l10n-id": "generated-id-3", + "data-l10n-attrs": "heading", + heading: testHeading + } + ); + + assertBasicProperties(headingIconCard, + { + "data-l10n-id": "generated-id-3", + "data-l10n-attrs": "heading", + headingText: testHeading, + contentText: generatedSlotText, + } + ); + assertHeadingIconCardProperties(headingIconCard, + { + "data-l10n-id": "generated-id-3", + "data-l10n-attrs": "heading", + headingText: testHeading, + contentText: generatedSlotText, + } + ); + }); + </script> </body> diff --git a/toolkit/content/tests/widgets/test_popupreflows.xhtml b/toolkit/content/tests/widgets/test_popupreflows.xhtml index c3f8068779..c014d6bee4 100644 --- a/toolkit/content/tests/widgets/test_popupreflows.xhtml +++ b/toolkit/content/tests/widgets/test_popupreflows.xhtml @@ -20,7 +20,7 @@ let panel, anchor; // done by the panel. let observer = { reflows: [], - reflow (start, end) { + reflow () { // Ignore reflows triggered by native code // (Reflows from native code only have an empty stack after the first frame) var path = (new Error().stack).split("\n").slice(1).join(""); @@ -31,7 +31,7 @@ let observer = { this.reflows.push(new Error().stack); }, - reflowInterruptible (start, end) { + reflowInterruptible () { // We're not interested in interruptible reflows. Why, you ask? Because // we've simply cargo-culted this test from browser_tabopen_reflows.js! }, diff --git a/toolkit/content/tests/widgets/test_videocontrols.html b/toolkit/content/tests/widgets/test_videocontrols.html index 076b4350fd..f2fc53a1cc 100644 --- a/toolkit/content/tests/widgets/test_videocontrols.html +++ b/toolkit/content/tests/widgets/test_videocontrols.html @@ -184,7 +184,7 @@ add_task(async function setup() { ]}); await new Promise(resolve => { video.addEventListener("canplaythrough", resolve, {once: true}); - video.src = "seek_with_sound.ogg"; + video.src = "seek_with_sound.webm"; }); video.addEventListener("play", captureEventThenCheck); @@ -437,7 +437,7 @@ add_task(async function click_and_hold_slider() { * Bug 1402877: Don't let click event dispatch through media controls to video element. */ add_task(async function click_event_dispatch() { - const clientScriptClickHandler = (e) => { + const clientScriptClickHandler = () => { ok(false, "Should not receive the event"); }; video.addEventListener("click", clientScriptClickHandler); diff --git a/toolkit/content/tests/widgets/test_videocontrols_audio.html b/toolkit/content/tests/widgets/test_videocontrols_audio.html index ad528f4c27..0a7a2dcbc3 100644 --- a/toolkit/content/tests/widgets/test_videocontrols_audio.html +++ b/toolkit/content/tests/widgets/test_videocontrols_audio.html @@ -18,7 +18,7 @@ <script> const video = document.getElementById("video"); - function loadedmetadata(event) { + function loadedmetadata() { SimpleTest.executeSoon(function() { const controlBar = SpecialPowers.wrap(video).openOrClosedShadowRoot.querySelector(".controlBar"); is(controlBar.getAttribute("fullscreen-unavailable"), "true", "Fullscreen button is hidden"); diff --git a/toolkit/content/tests/widgets/test_videocontrols_closed_caption_menu.html b/toolkit/content/tests/widgets/test_videocontrols_closed_caption_menu.html index 39d6ff494f..5a2602d204 100644 --- a/toolkit/content/tests/widgets/test_videocontrols_closed_caption_menu.html +++ b/toolkit/content/tests/widgets/test_videocontrols_closed_caption_menu.html @@ -49,7 +49,7 @@ ["media.videocontrols.keyboard-tab-to-all-controls", true], ]}, done); }, done => { - video.src = "seek_with_sound.ogg"; + video.src = "seek_with_sound.webm"; video.addEventListener("loadedmetadata", done); }, cleanup); diff --git a/toolkit/content/tests/widgets/test_videocontrols_error.html b/toolkit/content/tests/widgets/test_videocontrols_error.html index af90a4672a..922726d5be 100644 --- a/toolkit/content/tests/widgets/test_videocontrols_error.html +++ b/toolkit/content/tests/widgets/test_videocontrols_error.html @@ -27,7 +27,7 @@ add_task(async function check_normal_status() { await new Promise(resolve => { - video.src = "seek_with_sound.ogg"; + video.src = "seek_with_sound.webm"; video.addEventListener("loadedmetadata", () => SimpleTest.executeSoon(resolve)); }); @@ -44,7 +44,7 @@ const errorType = "errorNoSource"; await new Promise(resolve => { - video.src = "invalid_source.ogg"; + video.src = "invalid_source.webm"; video.addEventListener("error", () => SimpleTest.executeSoon(resolve)); }); diff --git a/toolkit/content/tests/widgets/test_videocontrols_focus.html b/toolkit/content/tests/widgets/test_videocontrols_focus.html index 0982947ffe..e19262bf6e 100644 --- a/toolkit/content/tests/widgets/test_videocontrols_focus.html +++ b/toolkit/content/tests/widgets/test_videocontrols_focus.html @@ -36,7 +36,7 @@ add_task(async function setup() { video.controls = true; video.preload = "auto"; video.loop = true; - video.src = "video.ogg"; + video.src = "video.webm"; const caption = video.addTextTrack("captions", "English", "en"); caption.mode = "showing"; const content = document.getElementById("content"); diff --git a/toolkit/content/tests/widgets/test_videocontrols_iframe_fullscreen.html b/toolkit/content/tests/widgets/test_videocontrols_iframe_fullscreen.html index 0a74b25609..d30d10b8bc 100644 --- a/toolkit/content/tests/widgets/test_videocontrols_iframe_fullscreen.html +++ b/toolkit/content/tests/widgets/test_videocontrols_iframe_fullscreen.html @@ -30,7 +30,7 @@ ifr.addEventListener("load", resolve); }).then(() => new Promise(resolve => { video = ifr.contentDocument.getElementById("video"); - video.src = "seek_with_sound.ogg"; + video.src = "seek_with_sound.webm"; video.addEventListener("loadedmetadata", resolve); })).then(() => new Promise(resolve => { const available = video.ownerDocument.fullscreenEnabled; diff --git a/toolkit/content/tests/widgets/test_videocontrols_jsdisabled.html b/toolkit/content/tests/widgets/test_videocontrols_jsdisabled.html index f3fdecc47f..16cf2b92e0 100644 --- a/toolkit/content/tests/widgets/test_videocontrols_jsdisabled.html +++ b/toolkit/content/tests/widgets/test_videocontrols_jsdisabled.html @@ -45,7 +45,7 @@ SpecialPowers.pushPrefEnv({"set": [["javascript.enabled", false]]}, startTest); var testnum = 1; var video; -function loadevent(event) { +function loadevent() { is(win.testExpando, undefined, "expando shouldn't exist because js is disabled"); video = win.document.querySelector("video"); // Other events expected by the test. diff --git a/toolkit/content/tests/widgets/test_videocontrols_keyhandler.html b/toolkit/content/tests/widgets/test_videocontrols_keyhandler.html index 5b771fc745..9737a9fff2 100644 --- a/toolkit/content/tests/widgets/test_videocontrols_keyhandler.html +++ b/toolkit/content/tests/widgets/test_videocontrols_keyhandler.html @@ -31,7 +31,7 @@ ["media.videocontrols.keyboard-tab-to-all-controls", true], ]}, done); }, done => { - video.src = "seek_with_sound.ogg"; + video.src = "seek_with_sound.webm"; video.addEventListener("loadedmetadata", done); }); diff --git a/toolkit/content/tests/widgets/test_videocontrols_onclickplay.html b/toolkit/content/tests/widgets/test_videocontrols_onclickplay.html index 9023512ab7..3b1bd4653c 100644 --- a/toolkit/content/tests/widgets/test_videocontrols_onclickplay.html +++ b/toolkit/content/tests/widgets/test_videocontrols_onclickplay.html @@ -22,11 +22,11 @@ var video = document.getElementById("video"); function startMediaLoad() { // Kick off test once video has loaded, in its canplaythrough event handler. - video.src = "seek_with_sound.ogg"; + video.src = "seek_with_sound.webm"; video.addEventListener("canplaythrough", runTest); } -function loadevent(event) { +function loadevent() { SpecialPowers.pushPrefEnv({"set": [["media.cache_size", 40000]]}, startMediaLoad); } diff --git a/toolkit/content/tests/widgets/test_videocontrols_scrubber_position.html b/toolkit/content/tests/widgets/test_videocontrols_scrubber_position.html index b1d2ab9e74..51117e7955 100644 --- a/toolkit/content/tests/widgets/test_videocontrols_scrubber_position.html +++ b/toolkit/content/tests/widgets/test_videocontrols_scrubber_position.html @@ -26,7 +26,7 @@ const video = document.getElementById("video"); add_task(async function setup() { await new Promise(resolve => { video.addEventListener("canplaythrough", resolve, {once: true}); - video.src = "seek_with_sound.ogg"; + video.src = "seek_with_sound.webm"; }); // Check initial state upon load diff --git a/toolkit/content/tests/widgets/test_videocontrols_scrubber_position_nopreload.html b/toolkit/content/tests/widgets/test_videocontrols_scrubber_position_nopreload.html index 9fbb6fbcb5..968ba5db96 100644 --- a/toolkit/content/tests/widgets/test_videocontrols_scrubber_position_nopreload.html +++ b/toolkit/content/tests/widgets/test_videocontrols_scrubber_position_nopreload.html @@ -13,7 +13,7 @@ <p id="display"></p> <div id="content"> - <video width="320" height="240" id="video" mozNoDynamicControls controls="true" preload="none" src="seek_with_sound.ogg"></video> + <video width="320" height="240" id="video" mozNoDynamicControls controls="true" preload="none" src="seek_with_sound.webm"></video> </div> <div id="host"></div> diff --git a/toolkit/content/tests/widgets/test_videocontrols_size.html b/toolkit/content/tests/widgets/test_videocontrols_size.html index 559cc66e86..d940b1d295 100644 --- a/toolkit/content/tests/widgets/test_videocontrols_size.html +++ b/toolkit/content/tests/widgets/test_videocontrols_size.html @@ -148,7 +148,7 @@ testCases.push(() => Promise.all(videoElems.map(video => new Promise(resolve => { video.addEventListener("loadedmetadata", resolve); - video.src = "seek_with_sound.ogg"; + video.src = "seek_with_sound.webm"; })))); videoElems.forEach(video => { diff --git a/toolkit/content/tests/widgets/test_videocontrols_standalone.html b/toolkit/content/tests/widgets/test_videocontrols_standalone.html index 14208923dd..1eaa026cdc 100644 --- a/toolkit/content/tests/widgets/test_videocontrols_standalone.html +++ b/toolkit/content/tests/widgets/test_videocontrols_standalone.html @@ -22,7 +22,7 @@ function getMediaElement(aWindow) { return aWindow.document.getElementsByTagName("video")[0]; } -var popup = window.open("seek_with_sound.ogg"); +var popup = window.open("seek_with_sound.webm"); popup.addEventListener("load", function() { var video = getMediaElement(popup); diff --git a/toolkit/content/tests/widgets/test_videocontrols_video_noaudio.html b/toolkit/content/tests/widgets/test_videocontrols_video_noaudio.html index bfc8018466..99d5bdad01 100644 --- a/toolkit/content/tests/widgets/test_videocontrols_video_noaudio.html +++ b/toolkit/content/tests/widgets/test_videocontrols_video_noaudio.html @@ -23,7 +23,7 @@ add_task(async function setup() { await SpecialPowers.pushPrefEnv({"set": [["media.cache_size", 40000]]}); await new Promise(resolve => { - video.src = "video.ogg"; + video.src = "video.webm"; video.addEventListener("loadedmetadata", () => SimpleTest.executeSoon(resolve)); }); }); diff --git a/toolkit/content/tests/widgets/test_videocontrols_vtt.html b/toolkit/content/tests/widgets/test_videocontrols_vtt.html index 2f8d70f35a..33b8bcf24e 100644 --- a/toolkit/content/tests/widgets/test_videocontrols_vtt.html +++ b/toolkit/content/tests/widgets/test_videocontrols_vtt.html @@ -26,7 +26,7 @@ add_task(async function wait_for_media_ready() { await SpecialPowers.pushPrefEnv({"set": [["media.cache_size", 40000]]}); await new Promise(resolve => { - video.src = "seek_with_sound.ogg"; + video.src = "seek_with_sound.webm"; video.addEventListener("loadedmetadata", resolve); }); }); diff --git a/toolkit/content/tests/widgets/tree_shared.js b/toolkit/content/tests/widgets/tree_shared.js index ba52bf828e..2cc40686ec 100644 --- a/toolkit/content/tests/widgets/tree_shared.js +++ b/toolkit/content/tests/widgets/tree_shared.js @@ -321,11 +321,7 @@ function testtag_tree_columns(tree, expectedColumns, testid) { // check the view's getColumnProperties method var properties = tree.view.getColumnProperties(column); var expectedProperties = expectedColumn.properties; - is( - properties, - expectedProperties ? expectedProperties : "", - adjtestid + "getColumnProperties" - ); + is(properties, expectedProperties || "", adjtestid + "getColumnProperties"); } is(columns.getFirstColumn(), columns[0], testid + "getFirstColumn"); @@ -574,10 +570,10 @@ function testtag_tree_TreeSelection_UI(tree, testid, multiple) { var keydownFired = 0; var keypressFired = 0; - function keydownListener(event) { + function keydownListener() { keydownFired++; } - function keypressListener(event) { + function keypressListener() { keypressFired++; } @@ -1307,7 +1303,7 @@ function testtag_tree_TreeView_rows(tree, testid, rowInfo, startRow) { isContainer(row) { return row.container; }, - isContainerOpen(row) { + isContainerOpen() { return false; }, isContainerEmpty(row) { @@ -1325,7 +1321,7 @@ function testtag_tree_TreeView_rows(tree, testid, rowInfo, startRow) { getParentIndex(row) { return row.parent; }, - hasNextSibling(row) { + hasNextSibling() { return r < startRow + length - 1; }, }; @@ -1433,7 +1429,7 @@ function testtag_tree_TreeView_rows(tree, testid, rowInfo, startRow) { } } -function testtag_tree_TreeView_rows_sort(tree, testid, rowInfo) { +function testtag_tree_TreeView_rows_sort(tree) { // check if cycleHeader sorts the columns var columnIndex = 0; var view = tree.view; @@ -1734,7 +1730,7 @@ function testtag_tree_wheel(aTree) { var defaultPrevented = 0; - function wheelListener(event) { + function wheelListener() { defaultPrevented++; } window.addEventListener("wheel", wheelListener); @@ -2109,7 +2105,7 @@ function mouseClickOnColumnHeader( } } -function mouseDblClickOnCell(tree, row, column, testname) { +function mouseDblClickOnCell(tree, row, column) { // select the row we will edit var selection = tree.view.selection; selection.select(row); @@ -2151,12 +2147,12 @@ function convertDOMtoTreeRowInfo(treechildren, level, rowidx) { for (var c = 0; c < treerow.childNodes.length; c++) { var cell = treerow.childNodes[c]; cellInfo.push({ - label: "" + cell.getAttribute("label"), - value: cell.getAttribute("value"), - properties: cell.getAttribute("properties"), + label: cell.getAttribute("label") || "", + value: cell.getAttribute("value") || "", + properties: cell.getAttribute("properties") || "", editable: cell.getAttribute("editable") != "false", selectable: cell.getAttribute("selectable") != "false", - image: cell.getAttribute("src"), + image: cell.getAttribute("src") || "", mode: cell.hasAttribute("mode") ? parseInt(cell.getAttribute("mode")) : 3, @@ -2170,7 +2166,7 @@ function convertDOMtoTreeRowInfo(treechildren, level, rowidx) { : convertDOMtoTreeRowInfo(descendants, level + 1, rowidx); obj.rows.push({ cells: cellInfo, - properties: treerow.getAttribute("properties"), + properties: treerow.getAttribute("properties") || "", container: treeitem.getAttribute("container") == "true", separator: treeitem.localName == "treeseparator", children, diff --git a/toolkit/content/tests/widgets/video.ogg b/toolkit/content/tests/widgets/video.ogg Binary files differdeleted file mode 100644 index ac7ece3519..0000000000 --- a/toolkit/content/tests/widgets/video.ogg +++ /dev/null diff --git a/toolkit/content/tests/widgets/video.webm b/toolkit/content/tests/widgets/video.webm Binary files differnew file mode 100644 index 0000000000..87a8d837a8 --- /dev/null +++ b/toolkit/content/tests/widgets/video.webm diff --git a/toolkit/content/tests/widgets/videocontrols_direction_test.js b/toolkit/content/tests/widgets/videocontrols_direction_test.js index e937f06b3f..608a39cc5b 100644 --- a/toolkit/content/tests/widgets/videocontrols_direction_test.js +++ b/toolkit/content/tests/widgets/videocontrols_direction_test.js @@ -26,7 +26,7 @@ RemoteCanvas.prototype.load = function (callback) { var m = iframe.contentDocument.getElementById("av"); m.addEventListener( "suspend", - function (aEvent) { + function () { setTimeout(function () { let mediaElement = iframe.contentDocument.querySelector("audio, video"); diff --git a/toolkit/content/tests/widgets/window_menubar.xhtml b/toolkit/content/tests/widgets/window_menubar.xhtml index c4ced844ad..ded1361365 100644 --- a/toolkit/content/tests/widgets/window_menubar.xhtml +++ b/toolkit/content/tests/widgets/window_menubar.xhtml @@ -426,7 +426,7 @@ var popupTests = [ test() { synthesizeKey("KEY_Escape"); }, - result(testname) { + result() { }, }, { @@ -504,14 +504,14 @@ var popupTests = [ testname: "cursor up wrap", events: [ "DOMMenuItemInactive contents", "DOMMenuItemActive about" ], test() { synthesizeKey("KEY_ArrowUp"); }, - result(testname) { } + result() { } }, { // check that pressing cursor down skips non menuitems testname: "cursor down wrap", events: [ "DOMMenuItemInactive about", "DOMMenuItemActive contents" ], test() { synthesizeKey("KEY_ArrowDown"); }, - result(testname) { } + result() { } }, { // check that pressing a menuitem's accelerator selects it @@ -617,7 +617,7 @@ var popupTests = [ condition() { return kIsWindows; }, events: [ "DOMMenuItemInactive only", "DOMMenuItemActive other" ], test() { sendChar("o"); }, - result(testname) { } + result() { } }, { // when only one menuitem starting with that letter exists, it should be diff --git a/toolkit/content/widgets/autocomplete-popup.js b/toolkit/content/widgets/autocomplete-popup.js index a13ba1bc62..8bbd012f31 100644 --- a/toolkit/content/widgets/autocomplete-popup.js +++ b/toolkit/content/widgets/autocomplete-popup.js @@ -211,24 +211,32 @@ return -1; } - var newIdx = aIndex + (aReverse ? -1 : 1) * aAmount; - if ( - (aReverse && aIndex == -1) || - (newIdx > aMaxRow && aIndex != aMaxRow) - ) { - newIdx = aMaxRow; - } else if ((!aReverse && aIndex == -1) || (newIdx < 0 && aIndex != 0)) { - newIdx = 0; - } + do { + var newIdx = aIndex + (aReverse ? -1 : 1) * aAmount; + if ( + (aReverse && aIndex == -1) || + (newIdx > aMaxRow && aIndex != aMaxRow) + ) { + newIdx = aMaxRow; + } else if ((!aReverse && aIndex == -1) || (newIdx < 0 && aIndex != 0)) { + newIdx = 0; + } - if ( - (newIdx < 0 && aIndex == 0) || - (newIdx > aMaxRow && aIndex == aMaxRow) - ) { - aIndex = -1; - } else { - aIndex = newIdx; - } + if ( + (newIdx < 0 && aIndex == 0) || + (newIdx > aMaxRow && aIndex == aMaxRow) + ) { + aIndex = -1; + } else { + aIndex = newIdx; + } + + if (aIndex == -1) { + return -1; + } + } while ( + !this.richlistbox.canUserSelect(this.richlistbox.getItemAtIndex(aIndex)) + ); return aIndex; } @@ -313,12 +321,7 @@ _collapseUnusedItems() { let existingItemsCount = this.richlistbox.children.length; for (let i = this.matchCount; i < existingItemsCount; ++i) { - let item = this.richlistbox.children[i]; - - item.collapsed = true; - if (typeof item._onCollapse == "function") { - item._onCollapse(); - } + this.richlistbox.children[i].collapsed = true; } } @@ -408,10 +411,9 @@ // The styles on the list which have different <content> structure and overrided // _adjustAcItem() are unreusable. const UNREUSEABLE_STYLES = [ - "autofill-profile", - "autofill-footer", - "autofill-clear-button", - "autofill-insecureWarning", + "autofill", + "action", + "status", "generatedPassword", "generic", "importableLearnMore", @@ -434,17 +436,14 @@ if (!reusable) { let options = null; switch (style) { - case "autofill-profile": - options = { is: "autocomplete-profile-listitem" }; - break; - case "autofill-footer": - options = { is: "autocomplete-profile-listitem-footer" }; + case "autofill": + options = { is: "autocomplete-autofill-richlistitem" }; break; - case "autofill-clear-button": - options = { is: "autocomplete-profile-listitem-clear-button" }; + case "action": + options = { is: "autocomplete-action-richlistitem" }; break; - case "autofill-insecureWarning": - options = { is: "autocomplete-creditcard-insecure-field" }; + case "status": + options = { is: "autocomplete-status-richlistitem" }; break; case "generic": options = { is: "autocomplete-two-line-richlistitem" }; diff --git a/toolkit/content/widgets/autocomplete-richlistitem.js b/toolkit/content/widgets/autocomplete-richlistitem.js index fddd5b4029..b339ab1e27 100644 --- a/toolkit/content/widgets/autocomplete-richlistitem.js +++ b/toolkit/content/widgets/autocomplete-richlistitem.js @@ -522,6 +522,11 @@ return; } + let label = this.getAttribute("ac-label"); + if (label && JSON.parse(label)?.noLearnMore) { + return; + } + let baseURL = Services.urlFormatter.formatURLPref( "app.support.baseURL" ); @@ -715,6 +720,129 @@ } } + // This type has an action that is triggered when activated. The comment + // for that result should contain a fillMessageName -- the message to send -- + // and, optionally a secondary label, for example: + // { "fillMessageName": "Fill:Clear", secondary: "Second Label" } + class MozAutocompleteActionRichlistitem extends MozAutocompleteTwoLineRichlistitem { + constructor() { + super(); + this.selectedByMouseOver = true; + } + + _adjustAcItem() { + super._adjustAcItem(); + + let comment = JSON.parse(this.getAttribute("ac-label")); + this.querySelector(".line2-label").textContent = comment?.secondary || ""; + this.querySelector(".ac-site-icon").collapsed = + this.getAttribute("ac-image") == ""; + } + } + + // A row that conveys status information assigned from the status field + // within the comment associated with the selected item in the list. + class MozAutocompleteStatusRichlistitem extends MozAutocompleteTwoLineRichlistitem { + static get markup() { + return `<div class="ac-status" xmlns="http://www.w3.org/1999/xhtml"></div>`; + } + + connectedCallback() { + super.connectedCallback(); + this.parentNode.addEventListener("select", this); + this.eventListenerParentNode = this.parentNode; + } + + disconnectedCallback() { + this.eventListenerParentNode?.removeEventListener("select", this); + this.eventListenerParentNode = null; + } + + handleEvent(event) { + if (event.type == "select") { + let selectedItem = event.target.selectedItem; + if (selectedItem) { + this.#setStatus(selectedItem); + } + } + } + + #setStatus(item) { + // For normal rows, use that row's comment, otherwise use the status's + // comment which serves as the default label. + let target = + !item || item instanceof MozAutocompleteActionRichlistitem + ? this + : item; + + let comment = JSON.parse(target.getAttribute("ac-comment")); + let statusBox = this.querySelector(".ac-status"); + statusBox.textContent = comment?.status || ""; + } + + _adjustAcItem() { + super._adjustAcItem(); + this.#setStatus(this); + this.setAttribute("disabled", "true"); + } + } + + class MozAutocompleteAutoFillRichlistitem extends MozAutocompleteTwoLineRichlistitem { + constructor() { + super(); + this.selectedByMouseOver = true; + } + + _adjustAcItem() { + let { primary, secondary, ariaLabel } = JSON.parse( + this.getAttribute("ac-value") + ); + + let line1Label = this.querySelector(".line1-label"); + line1Label.textContent = primary.toString(); + + let line2Label = this.querySelector(".line2-label"); + line2Label.textContent = secondary.toString(); + + if (ariaLabel) { + this.setAttribute("aria-label", ariaLabel); + } + + this.querySelector(".ac-site-icon").collapsed = + this.getAttribute("ac-image") == ""; + } + + set selected(val) { + if (val) { + this.setAttribute("selected", "true"); + } else { + this.removeAttribute("selected"); + } + + let { AutoCompleteParent } = ChromeUtils.importESModule( + "resource://gre/actors/AutoCompleteParent.sys.mjs" + ); + + let actor = AutoCompleteParent.getCurrentActor(); + if (!actor) { + return; + } + + let popup = actor.openedPopup; + + setTimeout(() => { + let selectedIndex = popup ? popup.selectedIndex : -1; + actor.manager + .getActor("FormAutofill") + .sendAsyncMessage("FormAutofill:PreviewProfile", { selectedIndex }); + }, 0); + } + + get selected() { + return this.getAttribute("selected") == "true"; + } + } + class MozAutocompleteGeneratedPasswordRichlistitem extends MozAutocompleteTwoLineRichlistitem { constructor() { super(); @@ -840,6 +968,14 @@ ); customElements.define( + "autocomplete-autofill-richlistitem", + MozAutocompleteAutoFillRichlistitem, + { + extends: "richlistitem", + } + ); + + customElements.define( "autocomplete-login-richlistitem", MozAutocompleteLoginRichlistitem, { @@ -848,6 +984,22 @@ ); customElements.define( + "autocomplete-action-richlistitem", + MozAutocompleteActionRichlistitem, + { + extends: "richlistitem", + } + ); + + customElements.define( + "autocomplete-status-richlistitem", + MozAutocompleteStatusRichlistitem, + { + extends: "richlistitem", + } + ); + + customElements.define( "autocomplete-generated-password-richlistitem", MozAutocompleteGeneratedPasswordRichlistitem, { diff --git a/toolkit/content/widgets/button.js b/toolkit/content/widgets/button.js index ce48fac1e9..7ca2eddbed 100644 --- a/toolkit/content/widgets/button.js +++ b/toolkit/content/widgets/button.js @@ -84,7 +84,7 @@ ).toLowerCase(); // If the accesskey of the current button is pressed, just activate it - if (this.accessKey.toLowerCase() == charPressedLower) { + if (this.accessKey?.toLowerCase() == charPressedLower) { this.click(); return; } @@ -201,7 +201,7 @@ while (iterator.nextNode()) { var test = iterator.currentNode; if ( - test.accessKey.toLowerCase() == aAccessKeyLower && + test.accessKey?.toLowerCase() == aAccessKeyLower && !test.disabled && !test.collapsed && !test.hidden diff --git a/toolkit/content/widgets/infobar.css b/toolkit/content/widgets/infobar.css index ee811818b5..7818f1ef1d 100644 --- a/toolkit/content/widgets/infobar.css +++ b/toolkit/content/widgets/infobar.css @@ -32,11 +32,8 @@ } .close { - margin-block: 4px; + margin-block: 2px; margin-inline-start: 8px; - background-size: 12px; - height: 24px; - width: 24px; align-self: flex-start; } } diff --git a/toolkit/content/widgets/mach_commands.py b/toolkit/content/widgets/mach_commands.py index 58a8b8fcda..79398ab11a 100644 --- a/toolkit/content/widgets/mach_commands.py +++ b/toolkit/content/widgets/mach_commands.py @@ -206,3 +206,16 @@ def addstory(command_context, name, project_name, path): html_lit_import=html_lit_import, ) ) + + +@Command( + "buildtokens", + category="misc", + description="Build the design tokens CSS files", +) +def buildtokens(command_context): + run_mach( + command_context, + "npm", + args=["run", "build", "--prefix=toolkit/themes/shared/design-system"], + ) diff --git a/toolkit/content/widgets/marquee.css b/toolkit/content/widgets/marquee.css index b898cd0dce..6cdb52ca02 100644 --- a/toolkit/content/widgets/marquee.css +++ b/toolkit/content/widgets/marquee.css @@ -2,25 +2,19 @@ * 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/. */ -.outerDiv { - overflow: hidden; - width: -moz-available; +slot { + display: block; + will-change: translate; } -.horizontal > .innerDiv { - width: max-content; - /* We want to create overflow of twice our available space. */ - padding: 0 100%; -} - -/* disable scrolling in contenteditable */ -:host(:read-write) .innerDiv { - padding: 0 !important; +/* Disable the animation on contenteditable */ +:host(:read-write) > slot { + translate: none !important; } /* When printing or when the user doesn't want movement, we disable scrolling */ @media print, (prefers-reduced-motion) { - .innerDiv { - padding: 0 !important; + slot { + translate: none !important; } } diff --git a/toolkit/content/widgets/marquee.js b/toolkit/content/widgets/marquee.js index 8b18703b92..a694ffdca1 100644 --- a/toolkit/content/widgets/marquee.js +++ b/toolkit/content/widgets/marquee.js @@ -4,87 +4,25 @@ "use strict"; -/* - * This is the class of entry. It will construct the actual implementation - * according to the value of the "direction" property. - */ this.MarqueeWidget = class { constructor(shadowRoot) { this.shadowRoot = shadowRoot; this.element = shadowRoot.host; - } - - /* - * Callback called by UAWidgets right after constructor. - */ - onsetup() { - this.switchImpl(); - } - - /* - * Callback called by UAWidgetsChild wheen the direction property - * changes. - */ - onchange() { - this.switchImpl(); - } - - switchImpl() { - let newImpl; - switch (this.element.direction) { - case "up": - case "down": - newImpl = MarqueeVerticalImplWidget; - break; - case "left": - case "right": - newImpl = MarqueeHorizontalImplWidget; - break; - } - - // Skip if we are asked to load the same implementation. - // This can happen if the property is set again w/o value change. - if (this.impl && this.impl.constructor == newImpl) { - return; - } - this.teardown(); - if (newImpl) { - this.impl = new newImpl(this.shadowRoot); - this.impl.onsetup(); - } - } - - teardown() { - if (!this.impl) { - return; - } - this.impl.teardown(); - this.shadowRoot.firstChild.remove(); - delete this.impl; - } -}; - -this.MarqueeBaseImplWidget = class { - constructor(shadowRoot) { - this.shadowRoot = shadowRoot; - this.element = shadowRoot.host; this.document = this.element.ownerDocument; this.window = this.document.defaultView; + // This needed for behavior=alternate, in order to know in which of the two + // directions we're going. + this.dirsign = 1; + this._currentLoop = this.element.loop; + this.animation = null; + this._restartScheduled = null; } onsetup() { - this.generateContent(); - - // Set up state. - this._currentDirection = this.element.direction || "left"; - this._currentLoop = this.element.loop; - this.dirsign = 1; - this.startAt = 0; - this.stopAt = 0; - this.newPosition = 0; - this.runId = 0; - this.originalHeight = 0; - this.invalidateCache = true; + // White-space isn't allowed because a marquee could be + // inside 'white-space: pre' + this.shadowRoot.innerHTML = `<link rel="stylesheet" href="chrome://global/content/elements/marquee.css" + /><slot></slot>`; this._mutationObserver = new this.window.MutationObserver(aMutations => this._mutationActor(aMutations) @@ -92,7 +30,7 @@ this.MarqueeBaseImplWidget = class { this._mutationObserver.observe(this.element, { attributes: true, attributeOldValue: true, - attributeFilter: ["loop", "", "behavior", "direction", "width", "height"], + attributeFilter: ["loop", "direction", "behavior"], }); // init needs to be run after the page has loaded in order to calculate @@ -108,12 +46,13 @@ this.MarqueeBaseImplWidget = class { } teardown() { + this.doStop(); this._mutationObserver.disconnect(); - this.window.clearTimeout(this.runId); this.window.removeEventListener("load", this); this.shadowRoot.removeEventListener("marquee-start", this); this.shadowRoot.removeEventListener("marquee-stop", this); + this.shadowRoot.replaceChildren(); } handleEvent(aEvent) { @@ -131,15 +70,26 @@ this.MarqueeBaseImplWidget = class { case "marquee-stop": this.doStop(); break; + case "finish": + this._animationFinished(); + break; } } - get outerDiv() { - return this.shadowRoot.firstChild; - } - - get innerDiv() { - return this.shadowRoot.getElementById("innerDiv"); + _animationFinished() { + let behavior = this.element.behavior; + let shouldLoop = + this._currentLoop > 1 || (this._currentLoop == -1 && behavior != "slide"); + if (shouldLoop) { + if (this._currentLoop > 0) { + this._currentLoop--; + } + if (behavior == "alternate") { + this.dirsign = -this.dirsign; + } + this.doStop(); + this.doStart(); + } } get scrollDelayWithTruespeed() { @@ -149,269 +99,249 @@ this.MarqueeBaseImplWidget = class { return this.element.scrollDelay; } - doStart() { - if (this.runId == 0) { - var lambda = () => this._doMove(false); - this.runId = this.window.setTimeout( - lambda, - this.scrollDelayWithTruespeed - this._deltaStartStop - ); - this._deltaStartStop = 0; - } - } - - doStop() { - if (this.runId != 0) { - this._deltaStartStop = Date.now() - this._lastMoveDate; - this.window.clearTimeout(this.runId); - } - - this.runId = 0; + get slot() { + return this.shadowRoot.lastChild; } - _fireEvent(aName, aBubbles, aCancelable) { - var e = this.document.createEvent("Events"); - e.initEvent(aName, aBubbles, aCancelable); - this.element.dispatchEvent(e); + /** + * Computes CSS-derived values needed to compute the transform of the + * contents. + * + * In particular, it measures the auto width and height of the contents, + * and the effective width and height of the marquee itself, along with its + * css directionality (which affects the effective direction). + */ + getMetrics() { + let slot = this.slot; + slot.style.width = "max-content"; + let slotCS = this.window.getComputedStyle(slot); + let marqueeCS = this.window.getComputedStyle(this.element); + let contentWidth = parseFloat(slotCS.width) || 0; + let contentHeight = parseFloat(slotCS.height) || 0; + let marqueeWidth = parseFloat(marqueeCS.width) || 0; + let marqueeHeight = parseFloat(marqueeCS.height) || 0; + slot.style.width = ""; + return { + contentWidth, + contentHeight, + marqueeWidth, + marqueeHeight, + cssDirection: marqueeCS.direction, + }; } - _doMove(aResetPosition) { - this._lastMoveDate = Date.now(); - - // invalidateCache is true at first load and whenever an attribute - // is changed - if (this.invalidateCache) { - this.invalidateCache = false; // we only want this to run once every scroll direction change - - var corrvalue = 0; - - switch (this._currentDirection) { - case "up": - case "down": { - let height = this.window.getComputedStyle(this.element).height; - this.outerDiv.style.height = height; - if (this.originalHeight > this.outerDiv.offsetHeight) { - corrvalue = this.originalHeight - this.outerDiv.offsetHeight; + /** + * Gets the layout metrics from getMetrics(), and returns an object + * describing the start, end, and axis of the animation for the given marquee + * behavior and direction. + */ + getTransformParameters({ + contentWidth, + contentHeight, + marqueeWidth, + marqueeHeight, + cssDirection, + }) { + const innerWidth = marqueeWidth - contentWidth; + const innerHeight = marqueeHeight - contentHeight; + const dir = this.element.direction; + + let start = 0; + let end = 0; + const axis = dir == "up" || dir == "down" ? "y" : "x"; + switch (this.element.behavior) { + case "alternate": + switch (dir) { + case "up": + case "down": { + if (innerHeight >= 0) { + start = innerHeight; + end = 0; + } else { + start = 0; + end = innerHeight; + } + if (dir == "down") { + [start, end] = [end, start]; + } + if (this.dirsign == -1) { + [start, end] = [end, start]; + } + break; } - this.innerDiv.style.padding = height + " 0"; - let isUp = this._currentDirection == "up"; - if (isUp) { - this.dirsign = 1; - this.startAt = - this.element.behavior == "alternate" - ? this.originalHeight - corrvalue - : 0; - this.stopAt = - this.element.behavior == "alternate" || - this.element.behavior == "slide" - ? parseInt(height) + corrvalue - : this.originalHeight + parseInt(height); - } else { - this.dirsign = -1; - this.startAt = - this.element.behavior == "alternate" - ? parseInt(height) + corrvalue - : this.originalHeight + parseInt(height); - this.stopAt = - this.element.behavior == "alternate" || - this.element.behavior == "slide" - ? this.originalHeight - corrvalue - : 0; + case "right": + case "left": + default: { + if (innerWidth >= 0) { + start = innerWidth; + end = 0; + } else { + start = 0; + end = innerWidth; + } + if (dir == "right") { + [start, end] = [end, start]; + } + if (cssDirection == "rtl") { + [start, end] = [end, start]; + } + if (this.dirsign == -1) { + [start, end] = [end, start]; + } + break; } - break; } - case "left": - case "right": - default: { - let isRight = this._currentDirection == "right"; - // NOTE: It's important to use getComputedStyle() to not account for the padding. - let innerWidth = parseInt( - this.window.getComputedStyle(this.innerDiv).width - ); - if (innerWidth > this.outerDiv.offsetWidth) { - corrvalue = innerWidth - this.outerDiv.offsetWidth; + break; + case "slide": + switch (dir) { + case "up": { + start = marqueeHeight; + end = 0; + break; } - let rtl = - this.window.getComputedStyle(this.element).direction == "rtl"; - if (isRight != rtl) { - this.dirsign = -1; - this.stopAt = - this.element.behavior == "alternate" || - this.element.behavior == "slide" - ? innerWidth - corrvalue - : 0; - this.startAt = - this.outerDiv.offsetWidth + - (this.element.behavior == "alternate" - ? corrvalue - : innerWidth + this.stopAt); - } else { - this.dirsign = 1; - this.startAt = - this.element.behavior == "alternate" ? innerWidth - corrvalue : 0; - this.stopAt = - this.outerDiv.offsetWidth + - (this.element.behavior == "alternate" || - this.element.behavior == "slide" - ? corrvalue - : innerWidth + this.startAt); + case "down": { + start = -contentHeight; + end = innerHeight; + break; } - if (rtl) { - this.startAt = -this.startAt; - this.stopAt = -this.stopAt; - this.dirsign = -this.dirsign; + case "right": + default: { + let isRight = dir == "right"; + if (cssDirection == "rtl") { + isRight = !isRight; + } + if (isRight) { + start = -contentWidth; + end = innerWidth; + } else { + start = marqueeWidth; + end = 0; + } + break; } - break; } - } - - if (aResetPosition) { - this.newPosition = this.startAt; - this._fireEvent("start", false, false); - } - } // end if - - this.newPosition = - this.newPosition + this.dirsign * this.element.scrollAmount; - - if ( - (this.dirsign == 1 && this.newPosition > this.stopAt) || - (this.dirsign == -1 && this.newPosition < this.stopAt) - ) { - switch (this.element.behavior) { - case "alternate": - // lets start afresh - this.invalidateCache = true; - - // swap direction - const swap = { left: "right", down: "up", up: "down", right: "left" }; - this._currentDirection = swap[this._currentDirection] || "left"; - this.newPosition = this.stopAt; - - if ( - this._currentDirection == "up" || - this._currentDirection == "down" - ) { - this.outerDiv.scrollTop = this.newPosition; - } else { - this.outerDiv.scrollLeft = this.newPosition; - } - - if (this._currentLoop != 1) { - this._fireEvent("bounce", false, true); - } - break; - - case "slide": - if (this._currentLoop > 1) { - this.newPosition = this.startAt; + break; + case "scroll": + default: + switch (dir) { + case "up": + case "down": { + start = marqueeHeight; + end = -contentHeight; + if (dir == "down") { + [start, end] = [end, start]; + } + break; } - break; - - default: - this.newPosition = this.startAt; - - if ( - this._currentDirection == "up" || - this._currentDirection == "down" - ) { - this.outerDiv.scrollTop = this.newPosition; - } else { - this.outerDiv.scrollLeft = this.newPosition; + case "right": + case "left": + default: { + start = marqueeWidth; + end = -contentWidth; + if (dir == "right") { + [start, end] = [end, start]; + } + if (cssDirection == "rtl") { + [start, end] = [end, start]; + } + break; } + } + break; + } + return { start, end, axis }; + } - // dispatch start event, even when this._currentLoop == 1, comp. with IE6 - this._fireEvent("start", false, false); + /** + * Measures the marquee contents, and starts the marquee animation if needed. + * The translate animation is applied to the <slot> element. + * Bouncing and looping is implemented in the finish event handler for the + * given animation (see _animationFinished()). + */ + doStart() { + if (this.animation) { + return; + } + let scrollAmount = this.element.scrollAmount; + if (!scrollAmount) { + return; + } + let metrics = this.getMetrics(); + let { axis, start, end } = this.getTransformParameters(metrics); + let duration = + (Math.abs(end - start) * this.scrollDelayWithTruespeed) / scrollAmount; + let startValue = start + "px"; + let endValue = end + "px"; + if (axis == "y") { + startValue = "0 " + startValue; + endValue = "0 " + endValue; + } + // NOTE(emilio): It seems tempting to use `iterations` here, but doing so + // wouldn't be great because this uses current layout values (via + // getMetrics()), so sizes wouldn't update. This way we update once per + // animation iteration. + // + // fill: forwards is needed so that behavior=slide doesn't jump back to the + // start after the animation finishes. + this.animation = this.slot.animate( + { + translate: [startValue, endValue], + }, + { + duration, + easing: "linear", + fill: "forwards", } + ); + this.animation.addEventListener("finish", this, { once: true }); + } - if (this._currentLoop > 1) { - this._currentLoop--; - } else if (this._currentLoop == 1) { - if ( - this._currentDirection == "up" || - this._currentDirection == "down" - ) { - this.outerDiv.scrollTop = this.stopAt; - } else { - this.outerDiv.scrollLeft = this.stopAt; - } - this.element.stop(); - this._fireEvent("finish", false, true); - return; - } - } else if ( - this._currentDirection == "up" || - this._currentDirection == "down" - ) { - this.outerDiv.scrollTop = this.newPosition; - } else { - this.outerDiv.scrollLeft = this.newPosition; + doStop() { + if (!this.animation) { + return; } - - var myThis = this; - var lambda = function myTimeOutFunction() { - myThis._doMove(false); - }; - this.runId = this.window.setTimeout(lambda, this.scrollDelayWithTruespeed); + if (this._restartScheduled) { + this.window.cancelAnimationFrame(this._restartScheduled); + this._restartScheduled = null; + } + this.animation.removeEventListener("finish", this); + this.animation.cancel(); + this.animation = null; } init() { this.element.stop(); - - if (this._currentDirection == "up" || this._currentDirection == "down") { - // store the original height before we add padding - this.innerDiv.style.padding = 0; - this.originalHeight = this.innerDiv.offsetHeight; - } - - this._doMove(true); + this.doStart(); } _mutationActor(aMutations) { while (aMutations.length) { - var mutation = aMutations.shift(); - var attrName = mutation.attributeName.toLowerCase(); - var oldValue = mutation.oldValue; - var target = mutation.target; - var newValue = target.getAttribute(attrName); - - if (oldValue != newValue) { - this.invalidateCache = true; - switch (attrName) { - case "loop": - this._currentLoop = target.loop; - break; - case "direction": - this._currentDirection = target.direction; - break; - } + let mutation = aMutations.shift(); + let attrName = mutation.attributeName.toLowerCase(); + let oldValue = mutation.oldValue; + let newValue = this.element.getAttribute(attrName); + if (oldValue == newValue) { + continue; + } + if (attrName == "loop") { + this._currentLoop = this.element.loop; + } + if (attrName == "direction" || attrName == "behavior") { + this._scheduleRestartIfNeeded(); } } } -}; - -this.MarqueeHorizontalImplWidget = class extends MarqueeBaseImplWidget { - generateContent() { - // White-space isn't allowed because a marquee could be - // inside 'white-space: pre' - this.shadowRoot.innerHTML = `<div class="outerDiv horizontal" - ><link rel="stylesheet" href="chrome://global/content/elements/marquee.css" - /><div class="innerDiv" id="innerDiv" - ><slot - /></div - ></div>`; - } -}; -this.MarqueeVerticalImplWidget = class extends MarqueeBaseImplWidget { - generateContent() { - // White-space isn't allowed because a marquee could be - // inside 'white-space: pre' - this.shadowRoot.innerHTML = `<div class="outerDiv vertical" - ><link rel="stylesheet" href="chrome://global/content/elements/marquee.css" - /><div class="innerDiv" id="innerDiv" - ><slot - /></div - ></div>`; + // Schedule a restart with the new parameters if we're running. + _scheduleRestartIfNeeded() { + if (!this.animation || this._restartScheduled != null) { + return; + } + this._restartScheduled = this.window.requestAnimationFrame(() => { + if (this.animation) { + this.doStop(); + this.doStart(); + } + }); } }; diff --git a/toolkit/content/widgets/menu.js b/toolkit/content/widgets/menu.js index 1a55d799b6..70b9521a27 100644 --- a/toolkit/content/widgets/menu.js +++ b/toolkit/content/widgets/menu.js @@ -19,7 +19,7 @@ this.setAttribute("value", val); } get value() { - return this.getAttribute("value"); + return this.getAttribute("value") || ""; } // nsIDOMXULSelectControlItemElement diff --git a/toolkit/content/widgets/menulist.js b/toolkit/content/widgets/menulist.js index 3672d4ccf1..c7bff9c9d0 100644 --- a/toolkit/content/widgets/menulist.js +++ b/toolkit/content/widgets/menulist.js @@ -124,8 +124,6 @@ this.shadowRoot.appendChild(document.createElement("slot")); } - this.mSelectedInternal = null; - this.mAttributeObserver = null; this.setInitialSelection(); } @@ -153,7 +151,7 @@ // nsIDOMXULSelectControlElement get value() { - return this.getAttribute("value"); + return this.getAttribute("value") || ""; } // nsIDOMXULMenuListElement @@ -163,12 +161,12 @@ // nsIDOMXULMenuListElement get image() { - return this.getAttribute("image"); + return this.getAttribute("image") || ""; } // nsIDOMXULMenuListElement get label() { - return this.getAttribute("label"); + return this.getAttribute("label") || ""; } set description(val) { @@ -176,7 +174,7 @@ } get description() { - return this.getAttribute("description"); + return this.getAttribute("description") || ""; } // nsIDOMXULMenuListElement @@ -292,6 +290,10 @@ if (this.getAttribute("noinitialselection") === "true") { return; } + + this.mSelectedInternal = null; + this.mAttributeObserver = null; + var popup = this.menupopup; if (popup) { var arr = popup.getElementsByAttribute("selected", "true"); diff --git a/toolkit/content/widgets/moz-button/moz-button.css b/toolkit/content/widgets/moz-button/moz-button.css index 47567df41d..71d57ea93a 100644 --- a/toolkit/content/widgets/moz-button/moz-button.css +++ b/toolkit/content/widgets/moz-button/moz-button.css @@ -4,6 +4,8 @@ :host { display: inline-block; + height: fit-content; + width: fit-content; } button { @@ -133,6 +135,7 @@ button { 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); diff --git a/toolkit/content/widgets/moz-button/moz-button.mjs b/toolkit/content/widgets/moz-button/moz-button.mjs index 3e7c151e61..a951dbf5d8 100644 --- a/toolkit/content/widgets/moz-button/moz-button.mjs +++ b/toolkit/content/widgets/moz-button/moz-button.mjs @@ -68,6 +68,11 @@ export default class MozButton extends MozLitElement { } } + // Delegate clicks on host to the button element. + click() { + this.buttonEl.click(); + } + render() { return html` <link diff --git a/toolkit/content/widgets/moz-card/moz-card.css b/toolkit/content/widgets/moz-card/moz-card.css index 52c0ac0980..da5656e53e 100644 --- a/toolkit/content/widgets/moz-card/moz-card.css +++ b/toolkit/content/widgets/moz-card/moz-card.css @@ -7,7 +7,7 @@ --card-border-radius: var(--border-radius-medium); --card-border-width: var(--border-width); --card-border: var(--card-border-width) solid var(--card-border-color); - --card-background-color: var(--box-background-color); + --card-background-color: var(--background-color-box); --card-focus-outline: var(--focus-outline); --card-box-shadow: var(--box-shadow-10); /* Bug 1791816, 1839523: replace with spacing tokens */ @@ -17,9 +17,9 @@ /* Bug 1791816: replace with button tokens */ @media (prefers-contrast) { - --button-border-color: var(--border-interactive-color); - --button-border-color-hover: var(--border-interactive-color-hover); - --button-border-color-active: var(--border-interactive-color-active); + --button-border-color: var(--border-color-interactive); + --button-border-color-hover: var(--border-color-interactive-hover); + --button-border-color-active: var(--border-color-interactive-active); --card-border-color: color-mix(in srgb, currentColor 41%, transparent); } /* Bug 1791816: replace with button tokens */ @@ -27,9 +27,9 @@ --button-background-color: ButtonFace; --button-background-color-hover: SelectedItemText; --button-background-color-active: SelectedItemText; - --button-border-color: var(--border-interactive-color); - --button-border-color-hover: var(--border-interactive-color-hover); - --button-border-color-active: var(--border-interactive-color-active); + --button-border-color: var(--border-color-interactive); + --button-border-color-hover: var(--border-color-interactive-hover); + --button-border-color-active: var(--border-color-interactive-active); --button-text-color: ButtonText; --button-text-color-hover: SelectedItem; --button-text-color-active: SelectedItem; @@ -81,6 +81,29 @@ summary { gap: var(--card-gap); padding-inline: var(--card-padding); border-radius: var(--card-border-radius); + + .chevron-icon { + background-image: url("chrome://global/skin/icons/arrow-down.svg"); + + details[open] & { + background-image: url("chrome://global/skin/icons/arrow-up.svg"); + } + } + + .chevron-icon, + #heading-icon { + background-position: center; + background-repeat: no-repeat; + -moz-context-properties: fill; + fill: currentColor; + width: 24px; + height: 24px; + min-width: 24px; + min-height: 24px; + padding: 0; + flex-shrink: 0; + align-self: flex-start; + } } #heading { @@ -159,22 +182,3 @@ details { outline: var(--card-focus-outline); } } - -.chevron-icon { - background-image: url("chrome://global/skin/icons/arrow-down.svg"); - background-position: center; - background-repeat: no-repeat; - -moz-context-properties: fill; - fill: currentColor; - width: 24px; - height: 24px; - min-width: 24px; - min-height: 24px; - padding: 0; - flex-shrink: 0; - align-self: flex-start; - - details[open] & { - background-image: url("chrome://global/skin/icons/arrow-up.svg"); - } -} diff --git a/toolkit/content/widgets/moz-card/moz-card.mjs b/toolkit/content/widgets/moz-card/moz-card.mjs index 2bd6e0f987..5687608975 100644 --- a/toolkit/content/widgets/moz-card/moz-card.mjs +++ b/toolkit/content/widgets/moz-card/moz-card.mjs @@ -3,7 +3,11 @@ * 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 "chrome://global/content/vendor/lit.all.mjs"; +import { + html, + ifDefined, + when, +} from "chrome://global/content/vendor/lit.all.mjs"; import { MozLitElement } from "chrome://global/content/lit-utils.mjs"; /** @@ -18,6 +22,7 @@ import { MozLitElement } from "chrome://global/content/lit-utils.mjs"; * * * @property {string} heading - The heading text that will be used for the card. + * @property {string} icon - (optional) A flag to indicate the header should include an icon * @property {string} type - (optional) The type of card. No type specified * will be the default card. The other available type is "accordion" * @slot content - The content to show inside of the card. @@ -31,6 +36,7 @@ export default class MozCard extends MozLitElement { static properties = { heading: { type: String }, + icon: { type: Boolean }, type: { type: String, reflect: true }, expanded: { type: Boolean }, }; @@ -47,9 +53,15 @@ export default class MozCard extends MozLitElement { } return html` <div id="heading-wrapper"> - ${this.type == "accordion" - ? html` <div class="chevron-icon"></div>` - : ""} + ${when( + this.type == "accordion", + () => html`<div class="chevron-icon"></div>` + )} + ${when( + this.icon, + () => + html`<div part="icon" id="heading-icon" role="presentation"></div>` + )} <span id="heading">${this.heading}</span> </div> `; diff --git a/toolkit/content/widgets/moz-card/moz-card.stories.mjs b/toolkit/content/widgets/moz-card/moz-card.stories.mjs index da3279b2a4..0430956a52 100644 --- a/toolkit/content/widgets/moz-card/moz-card.stories.mjs +++ b/toolkit/content/widgets/moz-card/moz-card.stories.mjs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // eslint-disable-next-line import/no-unresolved -import { html, ifDefined } from "lit.all.mjs"; +import { classMap, html, ifDefined } from "lit.all.mjs"; // eslint-disable-next-line import/no-unassigned-import import "./moz-card.mjs"; @@ -15,6 +15,8 @@ export default { fluent: ` moz-card-heading = .heading = This is the label +moz-card-heading-with-icon = + .heading = This is a card with a heading icon `, }, argTypes: { @@ -22,13 +24,27 @@ moz-card-heading = options: ["default", "accordion"], control: { type: "select" }, }, + hasHeadingIcon: { + options: [true, false], + control: { type: "select" }, + }, }, }; -const Template = ({ l10nId, content, type }) => html` - <main style="max-width: 400px"> +const Template = ({ l10nId, content, type, hasHeadingIcon }) => html` + <style> + main { + max-width: 400px; + } + moz-card.headingWithIcon::part(icon) { + background-image: url("chrome://browser/skin/preferences/category-general.svg"); + } + </style> + <main> <moz-card type=${ifDefined(type)} + ?icon=${hasHeadingIcon} + class=${classMap({ headingWithIcon: hasHeadingIcon })} data-l10n-id=${ifDefined(l10nId)} data-l10n-attrs="heading" > @@ -86,3 +102,13 @@ CardTypeAccordion.parameters = { }, }, }; + +export const CardWithHeadingIcon = Template.bind({}); +CardWithHeadingIcon.args = { + l10nId: "moz-card-heading-with-icon", + content: `Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Nunc velit turpis, mollis a ultricies vitae, accumsan ut augue. + In a eros ac dolor hendrerit varius et at mauris.`, + type: "default", + hasHeadingIcon: true, +}; diff --git a/toolkit/content/widgets/moz-message-bar/moz-message-bar.css b/toolkit/content/widgets/moz-message-bar/moz-message-bar.css index 6d35009982..fa7b08612d 100644 --- a/toolkit/content/widgets/moz-message-bar/moz-message-bar.css +++ b/toolkit/content/widgets/moz-message-bar/moz-message-bar.css @@ -6,14 +6,7 @@ /* Icon */ --message-bar-icon-color: var(--icon-color-information); --message-bar-icon-size: var(--size-item-small); - --message-bar-icon-close-color: var(--icon-color); - --message-bar-icon-close-url: url("chrome://global/skin/icons/close-12.svg"); - - /* Button */ - --message-bar-button-size-ghost: var(--button-min-height); - --message-bar-button-border-radius-ghost: var(--button-border-radius); - --message-bar-button-background-color-ghost-hover: var(--button-background-color-hover); - --message-bar-button-background-color-ghost-active: var(--button-background-color-active); + --message-bar-icon-close-url: url("chrome://global/skin/icons/close.svg"); /* Container */ --message-bar-container-min-height: var(--size-item-large); @@ -28,12 +21,13 @@ --message-bar-text-line-height: 1.5em; /* Background */ - --message-bar-background-color: var(--color-background-information); + --message-bar-background-color: var(--background-color-information); background-color: var(--message-bar-background-color); border: var(--message-bar-border-width) solid var(--message-bar-border-color); border-radius: var(--message-bar-border-radius); color: var(--message-bar-text-color); + text-align: start; } @media (prefers-contrast) { @@ -144,31 +138,8 @@ /* Close icon styles */ -.close { +moz-button::part(button) { background-image: var(--message-bar-icon-close-url); - background-repeat: no-repeat; - background-position: center center; - -moz-context-properties: fill; - fill: currentColor; - min-width: auto; - min-height: auto; - width: var(--message-bar-button-size-ghost); - height: var(--message-bar-button-size-ghost); - margin: 0; - padding: 0; - flex-shrink: 0; -} - -.ghost-button { - border-radius: var(--message-bar-button-border-radius-ghost); -} - -.ghost-button:enabled:hover { - background-color: var(--message-bar-button-background-color-ghost-hover); -} - -.ghost-button:enabled:hover:active { - background-color: var(--message-bar-button-background-color-ghost-active); } @media not (prefers-contrast) { @@ -176,7 +147,7 @@ /* Colors from: https://www.figma.com/file/zd3B9UyknB2XNZNdrYLm2W/Outreachy?type=design&node-id=59-1921&mode=design&t=ZYS4e6pAbAlXGvun-4 */ :host([type=warning]) { - --message-bar-background-color: var(--color-background-warning); + --message-bar-background-color: var(--background-color-warning); .icon { --message-bar-icon-color: var(--icon-color-warning); @@ -184,7 +155,7 @@ } :host([type=success]) { - --message-bar-background-color: var(--color-background-success); + --message-bar-background-color: var(--background-color-success); .icon { --message-bar-icon-color: var(--icon-color-success); @@ -193,19 +164,10 @@ :host([type=error]), :host([type=critical]) { - --message-bar-background-color: var(--color-background-critical); + --message-bar-background-color: var(--background-color-critical); .icon { --message-bar-icon-color: var(--icon-color-critical); } } - - .close { - fill: var(--message-bar-icon-close-color); - } - - .ghost-button { - border: none; - background-color: transparent; - } } 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 d83de5d29f..8f0c997149 100644 --- a/toolkit/content/widgets/moz-message-bar/moz-message-bar.mjs +++ b/toolkit/content/widgets/moz-message-bar/moz-message-bar.mjs @@ -4,6 +4,8 @@ import { html, ifDefined } from "../vendor/lit.all.mjs"; import { MozLitElement } from "../lit-utils.mjs"; +// eslint-disable-next-line import/no-unassigned-import +import "chrome://global/content/elements/moz-button.mjs"; const messageTypeToIconData = { info: { @@ -41,7 +43,7 @@ const messageTypeToIconData = { * @property {string} messageL10nArgs - Any args needed for the message l10n ID. * @fires message-bar:close * Custom event indicating that message bar was closed. - * @fires message-bar:user-dismissed + * @fires message-bar:user-dismissed * Custom event indicating that message bar was dismissed by the user. */ @@ -49,7 +51,7 @@ export default class MozMessageBar extends MozLitElement { static queries = { actionsSlotEl: "slot[name=actions]", actionsEl: ".actions", - closeButtonEl: "button.close", + closeButtonEl: "moz-button.close", supportLinkSlotEl: "slot[name=support-link]", }; @@ -113,14 +115,16 @@ export default class MozMessageBar extends MozLitElement { return ""; } - closeButtonTemplate() { + closeButtonTemplate({ size } = {}) { if (this.dismissable) { return html` - <button - class="close ghost-button" + <moz-button + type="icon ghost" + class="close" + size=${ifDefined(size)} data-l10n-id="moz-message-bar-close-button" @click=${this.dismiss} - ></button> + ></moz-button> `; } return ""; diff --git a/toolkit/content/widgets/moz-page-nav/README.stories.md b/toolkit/content/widgets/moz-page-nav/README.stories.md new file mode 100644 index 0000000000..800d446478 --- /dev/null +++ b/toolkit/content/widgets/moz-page-nav/README.stories.md @@ -0,0 +1,98 @@ +# MozPageNav + +`moz-page-nav` is a grouping of navigation buttons that is displayed at the page level, +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-button + view="view-one" + iconSrc="chrome://browser/skin/preferences/category-general.svg" + > + <p style={{ margin: 0 }}>Test 1</p> + </moz-page-nav-button> + <moz-page-nav-button + view="view-two" + iconSrc="chrome://browser/skin/preferences/category-general.svg" + > + <p style={{ margin: 0 }}>Test 2</p> + </moz-page-nav-button> + <moz-page-nav-button + view="view-three" + iconSrc="chrome://browser/skin/preferences/category-general.svg" + > + <p style={{ margin: 0 }}>Test 3</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)) +* This component will be used in about: pages such as about:firefoxview, about:preferences, about:addons, about:debugging, etc. + +## When not to use + +* If you need a navigation menu that does not switch between views within a single page + +## Code + +The source for `moz-page-nav` and `moz-page-nav-button` can be found under +[toolkit/content/widgets/moz-page-nav](https://searchfox.org/mozilla-central/source/toolkit/content/widgets/moz-page-nav). +You can find an examples of `moz-page-nav` in use in the Firefox codebase in +[about:firefoxview](https://searchfox.org/mozilla-central/source/browser/components/firefoxview/firefoxview.html#52-87). + +`moz-page-nav` can be imported into `.html`/`.xhtml` files: + +```html +<script type="module" src="chrome://global/content/elements/moz-page-nav.mjs"></script> +``` + +And used as follows: + +```html +<moz-page-nav> + <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 + 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 + 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> +``` + +### Fluent usage + +Generally the `heading` property of +`moz-page-nav` will be provided via [Fluent attributes](https://mozilla-l10n.github.io/localizer-documentation/tools/fluent/basic_syntax.html#attributes). +To get this working you will need to specify a `data-l10n-id` as well as +`data-l10n-attrs` if you're providing a heading: + +```html +<moz-page-nav data-l10n-id="with-heading" + data-l10n-attrs="heading"></moz-page-nav> +``` + +In which case your Fluent messages will look something like this: + +``` +with-heading = + .heading = Heading text goes here +``` + +You also need to specify a `data-l10n-id` for each `moz-page-nav-button`: + +```html +<moz-page-nav-button data-l10n-id="with-button-text"></moz-page-nav-button> +``` + +``` +with-button-text = button text goes here +``` 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 2975bb1a7c..5d00198d65 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 @@ -13,7 +13,7 @@ button { background-color: var(--page-nav-button-background-color); border: 1px solid var(--page-nav-border-color); -moz-context-properties: fill, fill-opacity; - fill: currentColor; + fill: var(--icon-color); display: grid; grid-template-columns: min-content 1fr; gap: 12px; @@ -34,34 +34,35 @@ button:hover { @media not (prefers-contrast) { button { - border-inline-start: 2px solid transparent; - border-inline-end: none; - border-block: none; + position: relative; } - button:hover, - button[selected]:hover { - background-color: var(--page-nav-button-background-color-hover); + button::before { + content: ""; + display: block; + position: absolute; + inset-block: 0; + inset-inline-start: 0; + width: 2px; + background-color: transparent; } - button[selected]:hover { - border-inline-start-color: inherit; + button[selected]::before { + background-color: var(--color-accent-primary); } - button[selected], - button[selected]:hover { - border-inline-start: 2px solid; + button[selected]:hover::before { + background-color: var(--icon-color); } - button[selected]:not(:focus-visible) { - border-start-start-radius: 0; - border-end-start-radius: 0; + button:hover, + button[selected]:hover { + background-color: var(--page-nav-button-background-color-hover); } button[selected]:not(:hover) { color: var(--color-accent-primary); background-color: color-mix(in srgb, var(--page-nav-button-background-color-selected) 5%, transparent); - border-inline-start-color: var(--color-accent-primary); } } @@ -74,7 +75,7 @@ button:hover { button:focus-visible, button[selected]:focus-visible { outline: var(--focus-outline); - outline-offset: var(--focus-outline-offset); + outline-offset: 0; border-radius: var(--border-radius-small); } diff --git a/toolkit/content/widgets/moz-page-nav/moz-page-nav.css b/toolkit/content/widgets/moz-page-nav/moz-page-nav.css index 49000f622d..8e6724b2f5 100644 --- a/toolkit/content/widgets/moz-page-nav/moz-page-nav.css +++ b/toolkit/content/widgets/moz-page-nav/moz-page-nav.css @@ -20,6 +20,7 @@ position: sticky; top: 0; height: 100vh; + display: block; width: var(--page-nav-width); @media (prefers-reduced-motion) { @@ -38,7 +39,7 @@ nav { grid-template-rows: min-content 1fr auto; gap: var(--page-nav-gap); margin-block: var(--page-nav-margin-top) var(--page-nav-margin-bottom); - height: calc(100vh - var(--page-nav-margin-top) - var(--page-nav-margin-bottom)); + height: calc(100% - var(--page-nav-margin-top) - var(--page-nav-margin-bottom)); @media (max-width: 52rem) { grid-template-rows: 1fr auto; } diff --git a/toolkit/content/widgets/moz-toggle/moz-toggle.css b/toolkit/content/widgets/moz-toggle/moz-toggle.css index 2005544181..ba98e80021 100644 --- a/toolkit/content/widgets/moz-toggle/moz-toggle.css +++ b/toolkit/content/widgets/moz-toggle/moz-toggle.css @@ -37,7 +37,7 @@ --toggle-background-color-pressed: var(--color-accent-primary); --toggle-background-color-pressed-hover: var(--color-accent-primary-hover); --toggle-background-color-pressed-active: var(--color-accent-primary-active); - --toggle-border-color: var(--border-interactive-color); + --toggle-border-color: var(--border-color-interactive); --toggle-border-color-hover: var(--toggle-border-color); --toggle-border-color-active: var(--toggle-border-color); --toggle-border-radius: var(--border-radius-circle); @@ -47,7 +47,7 @@ --toggle-dot-background-color: var(--toggle-border-color); --toggle-dot-background-color-hover: var(--toggle-dot-background-color); --toggle-dot-background-color-active: var(--toggle-dot-background-color); - --toggle-dot-background-color-on-pressed: var(--color-canvas); + --toggle-dot-background-color-on-pressed: var(--background-color-canvas); --toggle-dot-margin: 1px; --toggle-dot-height: calc(var(--toggle-height) - 2 * var(--toggle-dot-margin) - 2 * var(--toggle-border-width)); --toggle-dot-width: var(--toggle-dot-height); @@ -77,7 +77,7 @@ border-color: var(--toggle-border-color); } -.toggle-button:enabled:active { +.toggle-button:enabled:hover:active { background: var(--toggle-background-color-active); border-color: var(--toggle-border-color); } @@ -92,7 +92,7 @@ border-color: transparent; } -.toggle-button[aria-pressed="true"]:enabled:active { +.toggle-button[aria-pressed="true"]:enabled:hover:active { background: var(--toggle-background-color-pressed-active); border-color: transparent; } @@ -114,7 +114,7 @@ } .toggle-button[aria-pressed="true"]:enabled:hover::before, -.toggle-button[aria-pressed="true"]:enabled:active::before { +.toggle-button[aria-pressed="true"]:enabled:hover:active::before { background-color: var(--toggle-dot-background-color-on-pressed); } @@ -149,7 +149,7 @@ border-color: var(--toggle-border-color-hover); } - .toggle-button:enabled:active { + .toggle-button:enabled:hover:active { border-color: var(--toggle-border-color-active); } @@ -163,13 +163,13 @@ border-color: var(--toggle-border-color-hover); } - .toggle-button[aria-pressed="true"]:enabled:active { + .toggle-button[aria-pressed="true"]:enabled:hover:active { background-color: var(--toggle-dot-background-color-active); border-color: var(--toggle-dot-background-color-hover); } .toggle-button:hover::before, - .toggle-button:active::before { + .toggle-button:hover:active::before { background-color: var(--toggle-dot-background-color-hover); } } @@ -181,9 +181,9 @@ --toggle-dot-background-color-active: var(--color-accent-primary-active); --toggle-dot-background-color-on-pressed: var(--button-background-color); --toggle-background-color-disabled: var(--button-background-color-disabled); - --toggle-border-color-hover: var(--border-interactive-color-hover); - --toggle-border-color-active: var(--border-interactive-color-active); - --toggle-border-color-disabled: var(--border-interactive-color-disabled); + --toggle-border-color-hover: var(--border-color-interactive-hover); + --toggle-border-color-active: var(--border-color-interactive-active); + --toggle-border-color-disabled: var(--border-color-interactive-disabled); } .toggle-button[aria-pressed="true"]:enabled::after { @@ -197,7 +197,7 @@ inset: -2px; } - .toggle-button[aria-pressed="true"]:enabled:active::after { + .toggle-button[aria-pressed="true"]:enabled:hover:active::after { border-color: var(--toggle-border-color-active); } } diff --git a/toolkit/content/widgets/notificationbox.js b/toolkit/content/widgets/notificationbox.js index 0161588853..8cfc7b865c 100644 --- a/toolkit/content/widgets/notificationbox.js +++ b/toolkit/content/widgets/notificationbox.js @@ -663,6 +663,10 @@ } } + closeButtonTemplate() { + return super.closeButtonTemplate({ size: "small" }); + } + #setStyles() { let style = document.createElement("link"); style.rel = "stylesheet"; diff --git a/toolkit/content/widgets/radio.js b/toolkit/content/widgets/radio.js index 41e8a945ba..52ace9bf6b 100644 --- a/toolkit/content/widgets/radio.js +++ b/toolkit/content/widgets/radio.js @@ -214,7 +214,7 @@ } get value() { - return this.getAttribute("value"); + return this.getAttribute("value") || ""; } set disabled(val) { @@ -526,7 +526,7 @@ } get value() { - return this.getAttribute("value"); + return this.getAttribute("value") || ""; } get selected() { diff --git a/toolkit/content/widgets/richlistbox.js b/toolkit/content/widgets/richlistbox.js index 01d970e6ed..0d669c4c5e 100644 --- a/toolkit/content/widgets/richlistbox.js +++ b/toolkit/content/widgets/richlistbox.js @@ -109,14 +109,14 @@ for (var i = 0; i < rowCount; i++) { var k = (start + i) % rowCount; var listitem = this.getItemAtIndex(k); - if (!this._canUserSelect(listitem)) { + if (!this.canUserSelect(listitem)) { continue; } // allow richlistitems to specify the string being searched for var searchText = "searchLabel" in listitem ? listitem.searchLabel - : listitem.getAttribute("label"); // (see also bug 250123) + : listitem.getAttribute("label") || ""; // (see also bug 250123) searchText = searchText.substring(0, length).toLowerCase(); if (searchText == incrementalString) { this.ensureIndexIsVisible(k); @@ -227,7 +227,7 @@ this.setAttribute("seltype", val); } get selType() { - return this.getAttribute("seltype"); + return this.getAttribute("seltype") || ""; } // nsIDOMXULSelectControlElement @@ -337,7 +337,7 @@ if ( aStartItem && aStartItem.localName == "richlistitem" && - (!this._userSelecting || this._canUserSelect(aStartItem)) + (!this._userSelecting || this.canUserSelect(aStartItem)) ) { --aDelta; if (aDelta == 0) { @@ -354,7 +354,7 @@ if ( aStartItem && aStartItem.localName == "richlistitem" && - (!this._userSelecting || this._canUserSelect(aStartItem)) + (!this._userSelecting || this.canUserSelect(aStartItem)) ) { --aDelta; if (aDelta == 0) { @@ -771,7 +771,7 @@ var newItem = this.getItemAtIndex(newIndex); // make sure that the item is actually visible/selectable - if (this._userSelecting && newItem && !this._canUserSelect(newItem)) { + if (this._userSelecting && newItem && !this.canUserSelect(newItem)) { newItem = aOffset > 0 ? this.getNextItem(newItem, 1) || this.getPreviousItem(newItem, 1) @@ -811,7 +811,11 @@ } } - _canUserSelect(aItem) { + canUserSelect(aItem) { + if (aItem.disabled) { + return false; + } + var style = document.defaultView.getComputedStyle(aItem); return ( style.display != "none" && @@ -886,7 +890,7 @@ */ this.addEventListener("mousedown", event => { var control = this.control; - if (!control || control.disabled) { + if (!control || this.disabled || control.disabled) { return; } if ( @@ -912,7 +916,7 @@ } var control = this.control; - if (!control || control.disabled) { + if (!control || this.disabled || control.disabled) { return; } control._userSelecting = true; @@ -977,7 +981,7 @@ } get value() { - return this.getAttribute("value"); + return this.getAttribute("value") || ""; } /** diff --git a/toolkit/content/widgets/tabbox.js b/toolkit/content/widgets/tabbox.js index b1b2ddecce..f4003d002c 100644 --- a/toolkit/content/widgets/tabbox.js +++ b/toolkit/content/widgets/tabbox.js @@ -459,7 +459,7 @@ } get value() { - return this.getAttribute("value"); + return this.getAttribute("value") || ""; } get control() { @@ -563,7 +563,7 @@ } get value() { - return this.getAttribute("value"); + return this.getAttribute("value") || ""; } get tabbox() { diff --git a/toolkit/content/widgets/tree.js b/toolkit/content/widgets/tree.js index 4993bef0c2..a871d3396f 100644 --- a/toolkit/content/widgets/tree.js +++ b/toolkit/content/widgets/tree.js @@ -1078,7 +1078,7 @@ } get selType() { - return this.getAttribute("seltype"); + return this.getAttribute("seltype") || ""; } set currentIndex(val) { diff --git a/toolkit/content/widgets/wizard.js b/toolkit/content/widgets/wizard.js index c4285fada5..8a3b9c164d 100644 --- a/toolkit/content/widgets/wizard.js +++ b/toolkit/content/widgets/wizard.js @@ -222,7 +222,7 @@ cp && ((this._accessMethod == "sequential" && cp.pageIndex == this.pageCount - 1) || - (this._accessMethod == "random" && cp.next == "")) + (this._accessMethod == "random" && !cp.next)) ); } @@ -381,7 +381,7 @@ aPage.pageIndex = this.pageCount; this.pageCount += 1; if (!this._accessMethod) { - this._accessMethod = aPage.next == "" ? "sequential" : "random"; + this._accessMethod = aPage.next ? "random" : "sequential"; } if (!this._maybeStartWizard() && this._hasStarted) { // If the wizard has already started, adding a page might require diff --git a/toolkit/content/xul.css b/toolkit/content/xul.css index ead9997295..908132d598 100644 --- a/toolkit/content/xul.css +++ b/toolkit/content/xul.css @@ -389,10 +389,6 @@ tooltip { pointer-events: none; } -tooltip:not([position]) { - margin-top: 21px; -} - /** * It's important that these styles are in a UA sheet, because the default * tooltip is native anonymous content |