Bug 1966129 - Teach about:logging to copy the current settings to the clipboard as a preset URL. r=julienw,desktop-theme-reviewers,emilio

Differential Revision: https://phabricator.services.mozilla.com/D249082
This commit is contained in:
Paul Adenot
2025-05-20 15:06:02 +00:00
committed by padenot@mozilla.com
parent ab0bcf2219
commit c0d83d2613
7 changed files with 162 additions and 3 deletions

0
out.js Normal file
View File

View File

@@ -10,6 +10,32 @@
display: none !important; display: none !important;
} }
.about-logging-title-bar {
display: flex;
align-items: center;
gap: 1em;
}
#copy-as-url::part(button) {
background-image: url("chrome://global/skin/icons/edit-copy.svg");
}
#toast-copied {
visibility: hidden;
background-color: var(--background-color-success);
color: var(--text-color);
text-align: center;
border-radius: var(--border-radius-small);
padding: var(--space-medium);
opacity: 0;
transition: opacity 0.5s, visibility 0.5s;
margin-left: auto;
&.show {
visibility: visible;
opacity: 1;
}
}
/** Content area **/ /** Content area **/
.main-content { .main-content {
width: min(90%, 1024px); width: min(90%, 1024px);

View File

@@ -27,7 +27,25 @@
<body id="body"> <body id="body">
<main class="main-content"> <main class="main-content">
<div class="about-logging-title-bar">
<h1 id="title" data-l10n-id="about-logging-page-title"></h1> <h1 id="title" data-l10n-id="about-logging-page-title"></h1>
<div id="toast-copied" data-l10n-id="about-logging-url-copied"></div>
<moz-button
iconsrc="chrome://global/skin/icons/more.svg"
aria-expanded="false"
aria-haspopup="menu"
type="default"
size="default"
id="open-menu-button"
></moz-button>
<panel-list>
<panel-item
id="copy-as-url"
data-l10n-id="about-logging-copy-as-url"
action="copy"
></panel-item>
</panel-list>
</div>
<section> <section>
<div hidden id="error" class="page-subsection info-box"> <div hidden id="error" class="page-subsection info-box">
<div class="info-box-label" data-l10n-id="about-logging-error"></div> <div class="info-box-label" data-l10n-id="about-logging-error"></div>

View File

@@ -295,6 +295,44 @@ class ParseError extends Error {
value; value;
} }
// Returns a URL from the current state of the page
function serializeState() {
const params = new URLSearchParams();
const logModules = $("#log-modules")?.value;
const dropdown = $("#logging-preset-dropdown")?.value;
const outputType = $("[name=logging-output]:checked")?.value;
const threads = $("#threads")?.value;
const profilerPreset = $("#profiler-preset-dropdown")?.value;
const profilerStacks = $("#with-profiler-stacks-checkbox")?.checked;
if (logModules && logModules.trim()) {
params.set("modules", logModules.trim());
}
if (dropdown && dropdown !== "custom") {
params.set("preset", dropdown);
}
if (outputType === "profiler" || outputType === "file") {
params.set("output", outputType);
}
if (threads && threads.trim()) {
params.set("threads", threads.trim());
}
if (profilerPreset && profilerPreset !== "none") {
params.set("profiler-preset", profilerPreset);
}
if (profilerStacks) {
params.set("profilerstacks", "");
}
return `about:logging?${params.toString()}`;
}
function parseURL() { function parseURL() {
let options = new URL(document.location.href).searchParams; let options = new URL(document.location.href).searchParams;
@@ -413,6 +451,16 @@ function parseURL() {
$("#some-elements-unavailable").hidden = !someElementsDisabled; $("#some-elements-unavailable").hidden = !someElementsDisabled;
} }
async function copyAsURL() {
let url = serializeState();
await navigator.clipboard.writeText(url);
const toast = $("#toast-copied");
toast.classList.add("show");
setTimeout(() => {
toast.classList.remove("show");
}, 2000);
}
let gInited = false; let gInited = false;
function init() { function init() {
if (gInited) { if (gInited) {
@@ -437,6 +485,22 @@ function init() {
let toggleLoggingButton = $("#toggle-logging-button"); let toggleLoggingButton = $("#toggle-logging-button");
toggleLoggingButton.addEventListener("click", startStopLogging); toggleLoggingButton.addEventListener("click", startStopLogging);
$("#copy-as-url").onclick = copyAsURL;
function openMenu(event) {
if (
event.type == "mousedown" ||
event.inputSource == MouseEvent.MOZ_SOURCE_KEYBOARD ||
!event.detail
) {
document.querySelector("panel-list").toggle(event);
}
}
let menuButton = $("#open-menu-button");
menuButton.addEventListener("mousedown", openMenu);
menuButton.addEventListener("click", openMenu);
$$("input[type=radio]").forEach(radio => { $$("input[type=radio]").forEach(radio => {
radio.onchange = e => { radio.onchange = e => {
updateLoggingOutputType(e.target.value); updateLoggingOutputType(e.target.value);

View File

@@ -610,3 +610,51 @@ add_task(async function testAndroidUI() {
); );
}); });
}); });
add_task(async function testCopyToClipboard() {
await BrowserTestUtils.withNewTab(
PAGE,
async browser => {
const document = browser.contentDocument;
const window = browser.contentWindow;
// Open the menu, click on the item to copy to the clipboard
var menuButton = document.querySelector("#open-menu-button");
EventUtils.synthesizeMouseAtCenter(menuButton, {}, window);
var copyAction = await getElementFromDocumentByText(
document,
"Copy current settings as URL"
);
EventUtils.synthesizeMouseAtCenter(copyAction, {}, window);
// In theory, we could wait for the toast, and check that the clipboard
// has been filled with reasonnable data. In practice the CI machines
// are too slow and miss the toast, so we're repeatedly checking the
// content of the clipboard instead.
var copiedString = await TestUtils.waitForCondition(() => {
const xferable = Cc[
"@mozilla.org/widget/transferable;1"
].createInstance(Ci.nsITransferable);
xferable.init(null);
xferable.addDataFlavor("text/plain");
Services.clipboard.getData(xferable, Ci.nsIClipboard.kGlobalClipboard);
let data = {};
let type = {};
try {
xferable.getAnyTransferData(type, data);
data = data.value.QueryInterface(Ci.nsISupportsString).data;
} catch {
data = "";
}
if (data.startsWith("about:logging")) {
return data;
}
return false;
});
Assert.stringMatches(
copiedString,
/^about:logging\?/,
`about:logging URL copied successfully ${copiedString}`
);
},
"Waiting to have clipboard data"
);
});

View File

@@ -17,6 +17,8 @@ about-logging-set-log-file = Set Log File
about-logging-set-log-modules = Set Log Modules about-logging-set-log-modules = Set Log Modules
about-logging-start-logging = Start Logging about-logging-start-logging = Start Logging
about-logging-stop-logging = Stop Logging about-logging-stop-logging = Stop Logging
about-logging-copy-as-url = Copy current settings as URL
about-logging-url-copied = Logging settings copied to the clipboard as a preset URL
about-logging-buttons-disabled = Logging configured via environment variables, dynamic configuration unavailable. about-logging-buttons-disabled = Logging configured via environment variables, dynamic configuration unavailable.
about-logging-some-elements-disabled = Logging configured via URL, some configuration options are unavailable about-logging-some-elements-disabled = Logging configured via URL, some configuration options are unavailable
about-logging-info = Info: about-logging-info = Info:

View File

@@ -50,3 +50,4 @@ toolkit.jar:
# used in about:logging on Android # used in about:logging on Android
skin/classic/global/icons/open-in-new.svg (../../shared/icons/open-in-new.svg) skin/classic/global/icons/open-in-new.svg (../../shared/icons/open-in-new.svg)
skin/classic/global/icons/edit-copy.svg (../../shared/icons/edit-copy.svg)