diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /browser/extensions/webcompat/about-compat | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'browser/extensions/webcompat/about-compat')
7 files changed, 517 insertions, 0 deletions
diff --git a/browser/extensions/webcompat/about-compat/AboutCompat.jsm b/browser/extensions/webcompat/about-compat/AboutCompat.jsm new file mode 100644 index 0000000000..a90bd8ed80 --- /dev/null +++ b/browser/extensions/webcompat/about-compat/AboutCompat.jsm @@ -0,0 +1,36 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +var EXPORTED_SYMBOLS = ["AboutCompat"]; + +const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); + +const addonID = "webcompat@mozilla.org"; +const addonPageRelativeURL = "/about-compat/aboutCompat.html"; + +function AboutCompat() { + this.chromeURL = WebExtensionPolicy.getByID(addonID).getURL( + addonPageRelativeURL + ); +} +AboutCompat.prototype = { + QueryInterface: ChromeUtils.generateQI(["nsIAboutModule"]), + getURIFlags() { + return Ci.nsIAboutModule.URI_MUST_LOAD_IN_EXTENSION_PROCESS; + }, + + newChannel(aURI, aLoadInfo) { + const uri = Services.io.newURI(this.chromeURL); + const channel = Services.io.newChannelFromURIWithLoadInfo(uri, aLoadInfo); + channel.originalURI = aURI; + + channel.owner = ( + Services.scriptSecurityManager.createContentPrincipal || + Services.scriptSecurityManager.createCodebasePrincipal + )(uri, aLoadInfo.originAttributes); + return channel; + }, +}; diff --git a/browser/extensions/webcompat/about-compat/aboutCompat.css b/browser/extensions/webcompat/about-compat/aboutCompat.css new file mode 100644 index 0000000000..492296dfcf --- /dev/null +++ b/browser/extensions/webcompat/about-compat/aboutCompat.css @@ -0,0 +1,187 @@ +/* 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/. */ + +@media (any-pointer: fine) { + :root { + font-family: sans-serif; + margin: 40px auto; + min-width: 30em; + max-width: 60em; + } + + table { + width: 100%; + padding-bottom: 2em; + } + + .hidden { + display: none; + } + + .table-title-container { + align-items: center; + display: flex; + justify-content: space-between; + } + + .wide-button { + display: block; + min-height: 32px; + padding-inline: 30px; + } + + .submitting { + background-image: url(chrome://global/skin/icons/loading.png); + background-position: center; + background-repeat: no-repeat; + background-size: 16px; + } + + .submitting .submit-crash-button-label { + display: none; + } + + .failed-to-submit { + color: #ca8695; + } + + a.button-as-link { + appearance: none; + min-height: 30px; + color: var(--in-content-text-color) !important; + border: 1px solid var(--in-content-box-border-color) !important; + border-radius: 2px; + background-color: var(--in-content-page-background); + line-height: 30px; + margin: 4px 8px; + /* Ensure font-size isn't overridden by widget styling (e.g. in forms.css) */ + font-size: 1em; + } + + a.button-as-link:hover { + background-color: var(--in-content-box-background-hover) !important; + text-decoration: none; + } + + h2.lighter-font-weight { + font-weight: lighter; + } + + th { + text-align: start; + } +} + +@media (any-pointer: coarse), (any-pointer: none) { + * { + margin: 0; + padding: 0; + } + + html { + font-family: sans-serif; + font-size: 14px; + -moz-text-size-adjust: none; + background-color: #f5f5f5; + } + + table, + tr, + p { + display: block; + background: #fff; + } + + table { + border-top: 2px solid #0a84ff; + margin-top: -2px; + position: absolute; + width: 100%; + z-index: 1; + display: none; + } + + tr { + position: relative; + border-bottom: 1px solid #d7d9db; + padding: 1em; + } + + a { + color: #000; + font-size: 94%; + } + + .tab { + cursor: pointer; + position: relative; + z-index: 2; + display: inline-block; + text-align: left; + padding: 1em; + font-weight: bold; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + border: 1px solid #d7d9db; + border-bottom: 0; + margin-bottom: 2px; + background: #f5f5f5; + color: #363b40; + font-size: 1em; + font-weight: bold; + padding: 1em; + } + + .tab.active { + border-bottom-color: #fff; + background: #fff; + margin-bottom: 0; + padding-bottom: calc(1em + 2px); + } + + .tab.active + table { + display: block; + } + + td { + display: block; + position: relative; + padding-inline-end: 6.5em; + } + + td[colspan="4"] { + padding: 1em; + font-style: italic; + text-align: center; + } + + td:not([colspan]):nth-child(1) { + font-weight: bold; + } + + td:not([colspan]):nth-child(1) { + padding-bottom: 0.25em; + } + + td:nth-child(3) { + display: contents; + } + + button { + background: #e8e8e7; + position: absolute; + top: 0; + bottom: 0; + inset-inline-end: 0; + width: 6em; + border: 0; + border-inline-start: 1px solid #d7d9db; + appearance: none; + color: #000; + } + + button::-moz-focus-inner { + border: 0; + } +} diff --git a/browser/extensions/webcompat/about-compat/aboutCompat.html b/browser/extensions/webcompat/about-compat/aboutCompat.html new file mode 100644 index 0000000000..31180f0b30 --- /dev/null +++ b/browser/extensions/webcompat/about-compat/aboutCompat.html @@ -0,0 +1,37 @@ +<!-- 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/. --> + +<!DOCTYPE HTML> +<html> +<head> + <base/> + + <!-- If you change this script tag you must update the hash in the extension's + `content_security_policy` 'sha256-MmZkN2QaIHhfRWPZ8TVRjijTn5Ci1iEabtTEWrt9CCo=' --> + <script>/* globals browser */ document.head.firstElementChild.href = browser.runtime.getURL("");</script> + + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" href="about-compat/aboutCompat.css" /> + <link rel="stylesheet" media="screen and (pointer:fine), projection" type="text/css" + href="chrome://global/skin/in-content/common.css"/> + <link rel="localization" href="toolkit/about/aboutCompat.ftl"/> + <title data-l10n-id="text-title"></title> + <script src="about-compat/aboutCompat.js"></script> + </head> +<body> + <h2 class="tab active" data-l10n-id="label-overrides"></h2> + <table id="overrides"> + <col/> + <col/> + <col/> + </table> + <h2 class="tab" data-l10n-id="label-interventions"></h2> + <table id="interventions"> + <col/> + <col/> + <col/> + </table> +</body> +</html> diff --git a/browser/extensions/webcompat/about-compat/aboutCompat.js b/browser/extensions/webcompat/about-compat/aboutCompat.js new file mode 100644 index 0000000000..e5c9c4ff17 --- /dev/null +++ b/browser/extensions/webcompat/about-compat/aboutCompat.js @@ -0,0 +1,171 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/* globals browser */ + +let availablePatches; + +const portToAddon = (function() { + let port; + + function connect() { + port = browser.runtime.connect({ name: "AboutCompatTab" }); + port.onMessage.addListener(onMessageFromAddon); + port.onDisconnect.addListener(e => { + port = undefined; + }); + } + + connect(); + + async function send(message) { + if (port) { + return port.postMessage(message); + } + return Promise.reject("background script port disconnected"); + } + + return { send }; +})(); + +const $ = function(sel) { + return document.querySelector(sel); +}; + +const DOMContentLoadedPromise = new Promise(resolve => { + document.addEventListener( + "DOMContentLoaded", + () => { + resolve(); + }, + { once: true } + ); +}); + +Promise.all([ + browser.runtime.sendMessage("getOverridesAndInterventions"), + DOMContentLoadedPromise, +]).then(([info]) => { + document.body.addEventListener("click", async evt => { + const ele = evt.target; + if (ele.nodeName === "BUTTON") { + const row = ele.closest("[data-id]"); + if (row) { + evt.preventDefault(); + ele.disabled = true; + const id = row.getAttribute("data-id"); + try { + await browser.runtime.sendMessage({ command: "toggle", id }); + } catch (_) { + ele.disabled = false; + } + } + } else if (ele.classList.contains("tab")) { + document.querySelectorAll(".tab").forEach(tab => { + tab.classList.remove("active"); + }); + ele.classList.add("active"); + } + }); + + availablePatches = info; + redraw(); +}); + +function onMessageFromAddon(msg) { + if ("interventionsChanged" in msg) { + redrawTable($("#interventions"), msg.interventionsChanged); + } + + if ("overridesChanged" in msg) { + redrawTable($("#overrides"), msg.overridesChanged); + } + + const id = msg.toggling || msg.toggled; + const button = $(`[data-id="${id}"] button`); + if (!button) { + return; + } + const active = msg.active; + document.l10n.setAttributes( + button, + active ? "label-disable" : "label-enable" + ); + button.disabled = !!msg.toggling; +} + +function redraw() { + if (!availablePatches) { + return; + } + const { overrides, interventions } = availablePatches; + const showHidden = location.hash === "#all"; + redrawTable($("#overrides"), overrides, showHidden); + redrawTable($("#interventions"), interventions, showHidden); +} + +function redrawTable(table, data, showHidden = false) { + const df = document.createDocumentFragment(); + table.querySelectorAll("tr").forEach(tr => { + tr.remove(); + }); + + let noEntriesMessage; + if (data === false) { + noEntriesMessage = "text-disabled-in-about-config"; + } else if (data.length === 0) { + noEntriesMessage = + table.id === "overrides" ? "text-no-overrides" : "text-no-interventions"; + } + + if (noEntriesMessage) { + const tr = document.createElement("tr"); + df.appendChild(tr); + + const td = document.createElement("td"); + td.setAttribute("colspan", "3"); + document.l10n.setAttributes(td, noEntriesMessage); + tr.appendChild(td); + + table.appendChild(df); + return; + } + + for (const row of data) { + if (row.hidden && !showHidden) { + continue; + } + + const tr = document.createElement("tr"); + tr.setAttribute("data-id", row.id); + df.appendChild(tr); + + let td = document.createElement("td"); + td.innerText = row.domain; + tr.appendChild(td); + + td = document.createElement("td"); + const a = document.createElement("a"); + const bug = row.bug; + a.href = `https://bugzilla.mozilla.org/show_bug.cgi?id=${bug}`; + document.l10n.setAttributes(a, "label-more-information", { bug }); + a.target = "_blank"; + td.appendChild(a); + tr.appendChild(td); + + td = document.createElement("td"); + tr.appendChild(td); + const button = document.createElement("button"); + document.l10n.setAttributes( + button, + row.active ? "label-disable" : "label-enable" + ); + td.appendChild(button); + } + table.appendChild(df); +} + +window.onhashchange = redraw; diff --git a/browser/extensions/webcompat/about-compat/aboutPage.js b/browser/extensions/webcompat/about-compat/aboutPage.js new file mode 100644 index 0000000000..e719551332 --- /dev/null +++ b/browser/extensions/webcompat/about-compat/aboutPage.js @@ -0,0 +1,48 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/* global ExtensionAPI, Services, XPCOMUtils */ + +ChromeUtils.defineModuleGetter( + this, + "Services", + "resource://gre/modules/Services.jsm" +); + +XPCOMUtils.defineLazyServiceGetter( + this, + "resProto", + "@mozilla.org/network/protocol;1?name=resource", + "nsISubstitutingProtocolHandler" +); + +const ResourceSubstitution = "webcompat"; +const ProcessScriptURL = "resource://webcompat/aboutPageProcessScript.js"; +const ContractID = "@mozilla.org/network/protocol/about;1?what=compat"; + +this.aboutPage = class extends ExtensionAPI { + onStartup() { + const { rootURI } = this.extension; + + resProto.setSubstitution( + ResourceSubstitution, + Services.io.newURI("about-compat/", null, rootURI) + ); + + if (!(ContractID in Cc)) { + Services.ppmm.loadProcessScript(ProcessScriptURL, true); + this.processScriptRegistered = true; + } + } + + onShutdown() { + resProto.setSubstitution(ResourceSubstitution, null); + + if (this.processScriptRegistered) { + Services.ppmm.removeDelayedProcessScript(ProcessScriptURL); + } + } +}; diff --git a/browser/extensions/webcompat/about-compat/aboutPage.json b/browser/extensions/webcompat/about-compat/aboutPage.json new file mode 100644 index 0000000000..42e6114188 --- /dev/null +++ b/browser/extensions/webcompat/about-compat/aboutPage.json @@ -0,0 +1,6 @@ +[ + { + "namespace": "aboutCompat", + "description": "Enables the about:compat page" + } +] diff --git a/browser/extensions/webcompat/about-compat/aboutPageProcessScript.js b/browser/extensions/webcompat/about-compat/aboutPageProcessScript.js new file mode 100644 index 0000000000..e2e9866eb1 --- /dev/null +++ b/browser/extensions/webcompat/about-compat/aboutPageProcessScript.js @@ -0,0 +1,32 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +// Note: This script is used only when a static registration for our +// component is not already present in the libxul binary. + +const Cm = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); + +const classID = Components.ID("{97bf9550-2a7b-11e9-b56e-0800200c9a66}"); + +if (!Cm.isCIDRegistered(classID)) { + const { ComponentUtils } = ChromeUtils.import( + "resource://gre/modules/ComponentUtils.jsm" + ); + + const factory = ComponentUtils.generateSingletonFactory(function() { + const { AboutCompat } = ChromeUtils.import( + "resource://webcompat/AboutCompat.jsm" + ); + return new AboutCompat(); + }); + + Cm.registerFactory( + classID, + "about:compat", + "@mozilla.org/network/protocol/about;1?what=compat", + factory + ); +} |