summaryrefslogtreecommitdiffstats
path: root/browser/extensions/webcompat/about-compat
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /browser/extensions/webcompat/about-compat
parentInitial commit. (diff)
downloadfirefox-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')
-rw-r--r--browser/extensions/webcompat/about-compat/AboutCompat.jsm36
-rw-r--r--browser/extensions/webcompat/about-compat/aboutCompat.css187
-rw-r--r--browser/extensions/webcompat/about-compat/aboutCompat.html37
-rw-r--r--browser/extensions/webcompat/about-compat/aboutCompat.js171
-rw-r--r--browser/extensions/webcompat/about-compat/aboutPage.js48
-rw-r--r--browser/extensions/webcompat/about-compat/aboutPage.json6
-rw-r--r--browser/extensions/webcompat/about-compat/aboutPageProcessScript.js32
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
+ );
+}