diff --git a/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.css b/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.css index e0032240a4d2..de29761cc647 100644 --- a/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.css +++ b/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.css @@ -1,3 +1,15 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +.card { + margin-bottom: 16px; +} + +.window-card-title { + display: inline; +} + +.window-card-title:not(.current-window) { + font-weight: normal; +} diff --git a/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.html b/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.html index 114bb572e590..b492f645e4a8 100644 --- a/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.html +++ b/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.html @@ -9,16 +9,27 @@ + + - +

- - +

+
+
+ + diff --git a/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.js b/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.js index 84d1a95aef2f..4aef3d0dd73c 100644 --- a/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.js +++ b/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.js @@ -10,30 +10,50 @@ function refreshMessages() { let windowMessages = {}; let windowTitles = {}; AboutWindowsMessages.getMessages(window, windowMessages, windowTitles); - let messagesUl = document.getElementById("messages-ul"); - messagesUl.innerHTML = ""; + let windowsDiv = document.getElementById("windows-div"); + windowsDiv.innerHTML = ""; + const templateCard = document.querySelector("template[name=window-card]"); for (let i = 0; i < windowTitles.value.length; ++i) { - let titleLi = document.createElement("li"); - let titleTextNode = document.createTextNode(windowTitles.value[i]); - if (i === 0) { - // bold the first window since it's the current one - let b = document.createElement("b"); - b.appendChild(titleTextNode); - titleLi.appendChild(b); - } else { - titleLi.appendChild(titleTextNode); - } + let windowCard = templateCard.content + .cloneNode(true) + .querySelector("details"); + // open the current window by default + windowCard.open = i === 0; + let summary = windowCard.querySelector("summary"); + let titleSpan = summary.querySelector("h3.window-card-title"); + titleSpan.appendChild(document.createTextNode(windowTitles.value[i])); + titleSpan.classList.toggle("current-window", windowCard.open); + let copyButton = summary.querySelector("button"); + copyButton.addEventListener("click", async e => { + e.target.disabled = true; + await copyMessagesToClipboard(e); + e.target.disabled = false; + }); let innerUl = document.createElement("ul"); for (let j = 0; j < windowMessages.value[i].length; ++j) { let innerLi = document.createElement("li"); + innerLi.className = "message"; innerLi.innerText = windowMessages.value[i][j]; innerUl.appendChild(innerLi); } - titleLi.appendChild(innerUl); - messagesUl.append(titleLi); + windowCard.appendChild(innerUl); + windowsDiv.append(windowCard); } } +async function copyMessagesToClipboard(event) { + const details = event.target.parentElement.parentElement; + // Avoid copying the window name as it is Category 3 data, + // and only useful for the user to identify which window + // is which. + const messagesText = + Array.from(details.querySelector("ul").children) + .map(li => li.innerText) + .join("\n") + "\n"; + + await navigator.clipboard.writeText(messagesText); +} + function onLoad() { refreshMessages(); } diff --git a/toolkit/components/aboutwindowsmessages/moz.build b/toolkit/components/aboutwindowsmessages/moz.build index 8693ab62488d..9687e513f734 100644 --- a/toolkit/components/aboutwindowsmessages/moz.build +++ b/toolkit/components/aboutwindowsmessages/moz.build @@ -9,6 +9,7 @@ with Files("**"): FINAL_LIBRARY = "xul" +BROWSER_CHROME_MANIFESTS += ["tests/browser/browser.ini"] JAR_MANIFESTS += ["jar.mn"] XPCOM_MANIFESTS += ["components.conf"] XPIDL_MODULE = "AboutWindowsMessages" diff --git a/toolkit/components/aboutwindowsmessages/tests/browser/browser.ini b/toolkit/components/aboutwindowsmessages/tests/browser/browser.ini new file mode 100644 index 000000000000..debdaaa0262f --- /dev/null +++ b/toolkit/components/aboutwindowsmessages/tests/browser/browser.ini @@ -0,0 +1 @@ +[browser_aboutwindowsmessages.js] diff --git a/toolkit/components/aboutwindowsmessages/tests/browser/browser_aboutwindowsmessages.js b/toolkit/components/aboutwindowsmessages/tests/browser/browser_aboutwindowsmessages.js new file mode 100644 index 000000000000..38f4f1c78c38 --- /dev/null +++ b/toolkit/components/aboutwindowsmessages/tests/browser/browser_aboutwindowsmessages.js @@ -0,0 +1,86 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +async function resizeWindow(windowToResize, width, height) { + let resizePromise = BrowserTestUtils.waitForEvent( + windowToResize, + "resize", + false + ); + windowToResize.resizeTo(width, height); + await resizePromise; +} + +add_task(async () => { + const TEST_LINK = "https://example.com/"; + let originalBrowserWindow = Services.wm.getMostRecentWindow( + "navigator:browser" + ); + let originalBrowser = originalBrowserWindow.gBrowser; + // Resize this window so we can check for WM_NCCALCSIZE events below + await resizeWindow(originalBrowserWindow, 500, 400); + await resizeWindow(originalBrowserWindow, 600, 500); + await resizeWindow(originalBrowserWindow, 700, 600); + let newWindow = await BrowserTestUtils.openNewBrowserWindow({ + url: TEST_LINK, + }); + registerCleanupFunction(async function() { + await BrowserTestUtils.closeWindow(newWindow); + }); + await BrowserTestUtils.withNewTab( + { gBrowser: originalBrowser, url: "about:windows-messages" }, + async browser => { + let messagesList = content.document.getElementById("windows-div"); + // This is tricky because the test framework has its own windows + Assert.greaterOrEqual( + messagesList.childNodes.length, + 2, + "should have enough window entries" + ); + + let firstList = true; + for (let sublist of messagesList.childNodes) { + const messages = Array.from(sublist.querySelectorAll("li.message")); + const numberOfMessages = messages.length; + // Every window gets a few window messages when it opens, so there + // should be at least a few here. + Assert.greaterOrEqual( + numberOfMessages, + 3, + "should have enough messages for the current window" + ); + if (firstList) { + // It would be nice if we could check for a less obscure event. + // However, since we're resizing the window programatically we don't + // get WM_SIZE or WM_SIZING events. + Assert.greaterOrEqual( + messages.filter(messageLi => + messageLi.innerHTML.includes("WM_NCCALCSIZE") + ).length, + 5, + "active window should have enough WM_NCCALCSIZE events" + ); + firstList = false; + } + let buttons = sublist.querySelectorAll("button"); + Assert.equal(buttons.length, 1, "should have only one button"); + let clipboardButton = buttons[0]; + clipboardButton.click(); + // Wait until copying is done and the button becomes clickable. + await BrowserTestUtils.waitForMutationCondition( + clipboardButton, + { attributes: true }, + () => !clipboardButton.disabled + ); + const clipboardText = await navigator.clipboard.readText(); + const numberOfLines = Array.from(clipboardText.matchAll("\n")).length; + Assert.equal( + numberOfLines, + numberOfMessages, + "should copy the right number of lines to the clipboard" + ); + } + } + ); +}); diff --git a/toolkit/locales/en-US/toolkit/about/aboutWindowsMessages.ftl b/toolkit/locales/en-US/toolkit/about/aboutWindowsMessages.ftl index e958f2c1d90f..b0ba33aa913e 100644 --- a/toolkit/locales/en-US/toolkit/about/aboutWindowsMessages.ftl +++ b/toolkit/locales/en-US/toolkit/about/aboutWindowsMessages.ftl @@ -3,9 +3,17 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. ### Localization for the about:windows-messages page, which is only available -### on the Windows OS. -### This page records and shows messages sent from the OS to individual browser -### windows. These messages can be useful in debugging hard-to-reproduce issues -### with window sizing and position. +### on the Windows operating system. +### This page records and shows messages sent from the operating system to +### individual browser windows. These messages can be useful in debugging +### hard-to-reproduce issues with window sizing and position. +# Windows refers to the operating system windows-messages-page-title = Windows Messages Information +windows-messages-intro = + This page shows the most recent messages sent by Windows + to the { -brand-short-name } browser windows. The + bolded entry represents this window. Note that this page shows + the most recent messages at the time the page was loaded; + to see current ones you will need to refresh the page. +windows-messages-copy-to-clipboard = Copy to clipboard