summaryrefslogtreecommitdiffstats
path: root/toolkit/components/reportbrokensite
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/reportbrokensite')
-rw-r--r--toolkit/components/reportbrokensite/ReportBrokenSiteChild.sys.mjs525
-rw-r--r--toolkit/components/reportbrokensite/ReportBrokenSiteParent.sys.mjs292
-rw-r--r--toolkit/components/reportbrokensite/metrics.yaml686
-rw-r--r--toolkit/components/reportbrokensite/moz.build13
-rw-r--r--toolkit/components/reportbrokensite/pings.yaml18
5 files changed, 1534 insertions, 0 deletions
diff --git a/toolkit/components/reportbrokensite/ReportBrokenSiteChild.sys.mjs b/toolkit/components/reportbrokensite/ReportBrokenSiteChild.sys.mjs
new file mode 100644
index 0000000000..8220f5b4b6
--- /dev/null
+++ b/toolkit/components/reportbrokensite/ReportBrokenSiteChild.sys.mjs
@@ -0,0 +1,525 @@
+/* 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/. */
+
+import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
+
+const SCREENSHOT_FORMAT = { format: "jpeg", quality: 75 };
+
+function RunScriptInFrame(win, script) {
+ const contentPrincipal = win.document.nodePrincipal;
+ const sandbox = Cu.Sandbox([contentPrincipal], {
+ sandboxName: "Report Broken Site webcompat.com helper",
+ sandboxPrototype: win,
+ sameZoneAs: win,
+ originAttributes: contentPrincipal.originAttributes,
+ });
+ return Cu.evalInSandbox(script, sandbox, null, "sandbox eval code", 1);
+}
+
+class ConsoleLogHelper {
+ static PREVIEW_MAX_ITEMS = 10;
+ static LOG_LEVELS = ["debug", "info", "warn", "error"];
+
+ #windowId = undefined;
+
+ constructor(windowId) {
+ this.#windowId = windowId;
+ }
+
+ getLoggedMessages(alsoIncludePrivate = true) {
+ return this.getConsoleAPIMessages().concat(
+ this.getScriptErrors(alsoIncludePrivate)
+ );
+ }
+
+ getConsoleAPIMessages() {
+ const ConsoleAPIStorage = Cc[
+ "@mozilla.org/consoleAPI-storage;1"
+ ].getService(Ci.nsIConsoleAPIStorage);
+ let messages = ConsoleAPIStorage.getEvents(this.#windowId);
+ return messages.map(evt => {
+ const { columnNumber, filename, level, lineNumber, timeStamp } = evt;
+
+ const args = [];
+ for (const arg of evt.arguments) {
+ args.push(this.#getArgs(arg));
+ }
+
+ const message = {
+ level,
+ log: args,
+ uri: filename,
+ pos: `${lineNumber}:${columnNumber}`,
+ };
+
+ return { timeStamp, message };
+ });
+ }
+
+ getScriptErrors(alsoIncludePrivate) {
+ const messages = Services.console.getMessageArray();
+ return messages
+ .filter(message => {
+ if (message instanceof Ci.nsIScriptError) {
+ if (!alsoIncludePrivate && message.isFromPrivateWindow) {
+ return false;
+ }
+ if (this.#windowId && this.#windowId !== message.innerWindowID) {
+ return false;
+ }
+ return true;
+ }
+
+ // If this is not an nsIScriptError and we need to do window-based
+ // filtering we skip this message.
+ return false;
+ })
+ .map(error => {
+ const {
+ timeStamp,
+ errorMessage,
+ sourceName,
+ lineNumber,
+ columnNumber,
+ logLevel,
+ } = error;
+ const message = {
+ level: ConsoleLogHelper.LOG_LEVELS[logLevel],
+ log: [errorMessage],
+ uri: sourceName,
+ pos: `${lineNumber}:${columnNumber}`,
+ };
+ return { timeStamp, message };
+ });
+ }
+
+ #getPreview(value) {
+ switch (typeof value) {
+ case "symbol":
+ return value.toString();
+
+ case "function":
+ return "function ()";
+
+ case "object":
+ if (value === null) {
+ return null;
+ }
+ if (Array.isArray(value)) {
+ return `(${value.length})[...]`;
+ }
+ return "{...}";
+
+ case "undefined":
+ return "undefined";
+
+ default:
+ try {
+ structuredClone(value);
+ } catch (_) {
+ return `${value}` || "?";
+ }
+ return value;
+ }
+ }
+
+ #getArrayPreview(arr) {
+ const preview = [];
+ let count = 0;
+ for (const value of arr) {
+ if (++count > ConsoleLogHelper.PREVIEW_MAX_ITEMS) {
+ break;
+ }
+ preview.push(this.#getPreview(value));
+ }
+
+ return preview;
+ }
+
+ #getObjectPreview(obj) {
+ const preview = {};
+ let count = 0;
+ for (const key of Object.keys(obj)) {
+ if (++count > ConsoleLogHelper.PREVIEW_MAX_ITEMS) {
+ break;
+ }
+ preview[key] = this.#getPreview(obj[key]);
+ }
+
+ return preview;
+ }
+
+ #getArgs(value) {
+ if (typeof value === "object" && value !== null) {
+ if (Array.isArray(value)) {
+ return this.#getArrayPreview(value);
+ }
+ return this.#getObjectPreview(value);
+ }
+
+ return this.#getPreview(value);
+ }
+}
+
+const FrameworkDetector = {
+ hasFastClickPageScript(window) {
+ if (window.FastClick) {
+ return true;
+ }
+
+ for (const property in window) {
+ try {
+ const proto = window[property].prototype;
+ if (proto && proto.needsClick) {
+ return true;
+ }
+ } catch (_) {}
+ }
+
+ return false;
+ },
+
+ hasMobifyPageScript(window) {
+ return !!window.Mobify?.Tag;
+ },
+
+ hasMarfeelPageScript(window) {
+ return !!window.marfeel;
+ },
+
+ checkWindow(window) {
+ const script = `
+ (function() {
+ function ${FrameworkDetector.hasFastClickPageScript};
+ function ${FrameworkDetector.hasMobifyPageScript};
+ function ${FrameworkDetector.hasMarfeelPageScript};
+ const win = window.wrappedJSObject || window;
+ return {
+ fastclick: hasFastClickPageScript(win),
+ mobify: hasMobifyPageScript(win),
+ marfeel: hasMarfeelPageScript(win),
+ }
+ })();
+ `;
+ return RunScriptInFrame(window, script);
+ },
+};
+
+function getSysinfoProperty(propertyName, defaultValue) {
+ try {
+ return Services.sysinfo.getProperty(propertyName);
+ } catch (e) {}
+ return defaultValue;
+}
+
+const BrowserInfo = {
+ getAppInfo() {
+ const { userAgent } = Cc[
+ "@mozilla.org/network/protocol;1?name=http"
+ ].getService(Ci.nsIHttpProtocolHandler);
+ return {
+ applicationName: Services.appinfo.name,
+ buildId: Services.appinfo.appBuildID,
+ defaultUserAgent: userAgent,
+ updateChannel: AppConstants.MOZ_UPDATE_CHANNEL,
+ version: AppConstants.MOZ_APP_VERSION_DISPLAY,
+ };
+ },
+
+ getPrefs() {
+ const prefs = {};
+ for (const [name, dflt] of Object.entries({
+ "layers.acceleration.force-enabled": undefined,
+ "gfx.webrender.software": undefined,
+ "browser.opaqueResponseBlocking": undefined,
+ "extensions.InstallTrigger.enabled": undefined,
+ "privacy.resistFingerprinting": undefined,
+ "privacy.globalprivacycontrol.enabled": undefined,
+ })) {
+ prefs[name] = Services.prefs.getBoolPref(name, dflt);
+ }
+ const cookieBehavior = "network.cookie.cookieBehavior";
+ prefs[cookieBehavior] = Services.prefs.getIntPref(cookieBehavior);
+ return prefs;
+ },
+
+ getPlatformInfo() {
+ let memoryMB = getSysinfoProperty("memsize", null);
+ if (memoryMB) {
+ memoryMB = Math.round(memoryMB / 1024 / 1024);
+ }
+
+ const info = {
+ fissionEnabled: Services.appinfo.fissionAutostart,
+ memoryMB,
+ osArchitecture: getSysinfoProperty("arch", null),
+ osName: getSysinfoProperty("name", null),
+ osVersion: getSysinfoProperty("version", null),
+ os: AppConstants.platform,
+ };
+ if (AppConstants.platform === "android") {
+ info.device = getSysinfoProperty("device", null);
+ info.isTablet = getSysinfoProperty("tablet", false);
+ }
+ return info;
+ },
+
+ getAllData() {
+ return {
+ app: BrowserInfo.getAppInfo(),
+ prefs: BrowserInfo.getPrefs(),
+ platform: BrowserInfo.getPlatformInfo(),
+ };
+ },
+};
+
+export class ReportBrokenSiteChild extends JSWindowActorChild {
+ #getWebCompatInfo(docShell) {
+ return Promise.all([
+ this.#getConsoleLogs(docShell),
+ this.sendQuery(
+ "GetWebcompatInfoOnlyAvailableInParentProcess",
+ SCREENSHOT_FORMAT
+ ),
+ ]).then(([consoleLog, infoFromParent]) => {
+ const { antitracking, graphics, locales, screenshot, security } =
+ infoFromParent;
+
+ const browser = BrowserInfo.getAllData();
+ browser.graphics = graphics;
+ browser.locales = locales;
+ browser.security = security;
+
+ const win = docShell.domWindow;
+ const frameworks = FrameworkDetector.checkWindow(win);
+
+ if (browser.platform.os !== "linux") {
+ delete browser.prefs["layers.acceleration.force-enabled"];
+ }
+
+ return {
+ antitracking,
+ browser,
+ consoleLog,
+ devicePixelRatio: win.devicePixelRatio,
+ frameworks,
+ languages: win.navigator.languages,
+ screenshot,
+ url: win.location.href,
+ userAgent: win.navigator.userAgent,
+ };
+ });
+ }
+
+ async #getConsoleLogs(docShell) {
+ return this.#getLoggedMessages()
+ .flat()
+ .sort((a, b) => a.timeStamp - b.timeStamp)
+ .map(m => m.message);
+ }
+
+ #getLoggedMessages(alsoIncludePrivate = false) {
+ const windowId = this.contentWindow.windowGlobalChild.innerWindowId;
+ const helper = new ConsoleLogHelper(windowId, alsoIncludePrivate);
+ return helper.getLoggedMessages();
+ }
+
+ #formatReportDataForWebcompatCom({
+ reason,
+ description,
+ reportUrl,
+ reporterConfig,
+ webcompatInfo,
+ }) {
+ const extra_labels = [];
+
+ const message = Object.assign({}, reporterConfig, {
+ url: reportUrl,
+ category: reason,
+ description,
+ details: {},
+ extra_labels,
+ });
+
+ const payload = {
+ message,
+ };
+
+ if (webcompatInfo) {
+ const {
+ antitracking,
+ browser,
+ devicePixelRatio,
+ consoleLog,
+ frameworks,
+ languages,
+ screenshot,
+ url,
+ userAgent,
+ } = webcompatInfo;
+
+ const {
+ blockList,
+ isPrivateBrowsing,
+ hasMixedActiveContentBlocked,
+ hasMixedDisplayContentBlocked,
+ hasTrackingContentBlocked,
+ } = antitracking;
+
+ message.blockList = blockList;
+
+ const { app, graphics, prefs, platform, security } = browser;
+
+ const { applicationName, version, updateChannel, defaultUserAgent } = app;
+
+ const {
+ fissionEnabled,
+ memoryMb,
+ osArchitecture,
+ osName,
+ osVersion,
+ device,
+ isTablet,
+ } = platform;
+
+ const additionalData = {
+ applicationName,
+ blockList,
+ devicePixelRatio,
+ finalUserAgent: userAgent,
+ fissionEnabled,
+ gfxData: graphics,
+ hasMixedActiveContentBlocked,
+ hasMixedDisplayContentBlocked,
+ hasTrackingContentBlocked,
+ isPB: isPrivateBrowsing,
+ languages,
+ memoryMb,
+ osArchitecture,
+ osName,
+ osVersion,
+ prefs,
+ updateChannel,
+ userAgent: defaultUserAgent,
+ version,
+ };
+ if (security !== undefined) {
+ additionalData.sec = security;
+ }
+ if (device !== undefined) {
+ additionalData.device = device;
+ }
+ if (isTablet !== undefined) {
+ additionalData.isTablet = isTablet;
+ }
+
+ const specialPrefs = {};
+ for (const pref of [
+ "layers.acceleration.force-enabled",
+ "gfx.webrender.software",
+ ]) {
+ specialPrefs[pref] = prefs[pref];
+ }
+
+ const details = Object.assign(message.details, specialPrefs, {
+ additionalData,
+ buildId: browser.buildId,
+ blockList,
+ channel: browser.updateChannel,
+ hasTouchScreen: browser.graphics.hasTouchScreen,
+ });
+
+ // If the user enters a URL unrelated to the current tab,
+ // don't bother sending a screnshot or logs/etc
+ let sendRecordedPageSpecificDetails = false;
+ try {
+ const givenUri = new URL(reportUrl);
+ const recordedUri = new URL(url);
+ sendRecordedPageSpecificDetails =
+ givenUri.origin == recordedUri.origin &&
+ givenUri.pathname == recordedUri.pathname;
+ } catch (_) {}
+
+ if (sendRecordedPageSpecificDetails) {
+ payload.screenshot = screenshot;
+
+ details.consoleLog = consoleLog;
+ details.frameworks = frameworks;
+ details["mixed active content blocked"] =
+ antitracking.hasMixedActiveContentBlocked;
+ details["mixed passive content blocked"] =
+ antitracking.hasMixedDisplayContentBlocked;
+ details["tracking content blocked"] =
+ antitracking.hasTrackingContentBlocked
+ ? `true (${antitracking.blockList})`
+ : "false";
+
+ if (antitracking.hasTrackingContentBlocked) {
+ extra_labels.push(
+ `type-tracking-protection-${antitracking.blockList}`
+ );
+ }
+
+ for (const [framework, active] of Object.entries(frameworks)) {
+ if (!active) {
+ continue;
+ }
+ details[framework] = true;
+ extra_labels.push(`type-${framework}`);
+ }
+ }
+ }
+
+ return payload;
+ }
+
+ #stripNonASCIIChars(str) {
+ // eslint-disable-next-line no-control-regex
+ return str.replace(/[^\x00-\x7F]/g, "");
+ }
+
+ async receiveMessage(msg) {
+ const { docShell } = this;
+ switch (msg.name) {
+ case "SendDataToWebcompatCom": {
+ const win = docShell.domWindow;
+ const expectedEndpoint = msg.data.endpointUrl;
+ if (win.location.href == expectedEndpoint) {
+ // Ensure that the tab has fully loaded and is waiting for messages
+ const onLoad = () => {
+ const payload = this.#formatReportDataForWebcompatCom(msg.data);
+ const json = this.#stripNonASCIIChars(JSON.stringify(payload));
+ const expectedOrigin = JSON.stringify(
+ new URL(expectedEndpoint).origin
+ );
+ // webcompat.com checks that the message comes from its own origin
+ const script = `
+ const wrtReady = window.wrappedJSObject?.wrtReady;
+ if (wrtReady) {
+ console.info("Report Broken Site is waiting");
+ }
+ Promise.resolve(wrtReady).then(() => {
+ console.debug(${json});
+ postMessage(${json}, ${expectedOrigin})
+ });`;
+ RunScriptInFrame(win, script);
+ };
+ if (win.document.readyState == "complete") {
+ onLoad();
+ } else {
+ win.addEventListener("load", onLoad, { once: true });
+ }
+ }
+ return null;
+ }
+ case "GetWebCompatInfo": {
+ return this.#getWebCompatInfo(docShell);
+ }
+ case "GetConsoleLog": {
+ return this.#getLoggedMessages();
+ }
+ }
+ return null;
+ }
+}
diff --git a/toolkit/components/reportbrokensite/ReportBrokenSiteParent.sys.mjs b/toolkit/components/reportbrokensite/ReportBrokenSiteParent.sys.mjs
new file mode 100644
index 0000000000..d6363a4ee1
--- /dev/null
+++ b/toolkit/components/reportbrokensite/ReportBrokenSiteParent.sys.mjs
@@ -0,0 +1,292 @@
+/* vim: set ts=2 sw=2 et tw=80: */
+/* 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/. */
+
+import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
+
+function getSysinfoProperty(propertyName, defaultValue) {
+ try {
+ return Services.sysinfo.getProperty(propertyName);
+ } catch (e) {}
+ return defaultValue;
+}
+
+function getSecurityInfo() {
+ const keys = [
+ ["registeredAntiVirus", "antivirus"],
+ ["registeredAntiSpyware", "antispyware"],
+ ["registeredFirewall", "firewall"],
+ ];
+
+ let result = {};
+
+ for (let [inKey, outKey] of keys) {
+ const str = getSysinfoProperty(inKey, null);
+ result[outKey] = !str ? null : str.split(";");
+ }
+
+ // Right now, security data is only available for Windows builds, and
+ // we might as well not return anything at all if no data is available.
+ if (!Object.values(result).filter(e => e).length) {
+ return undefined;
+ }
+
+ return result;
+}
+
+class DriverInfo {
+ constructor(gl, ext) {
+ try {
+ this.extensions = ext.getParameter(ext.EXTENSIONS);
+ } catch (e) {}
+
+ try {
+ this.renderer = ext.getParameter(gl.RENDERER);
+ } catch (e) {}
+
+ try {
+ this.vendor = ext.getParameter(gl.VENDOR);
+ } catch (e) {}
+
+ try {
+ this.version = ext.getParameter(gl.VERSION);
+ } catch (e) {}
+
+ try {
+ this.wsiInfo = ext.getParameter(ext.WSI_INFO);
+ } catch (e) {}
+ }
+
+ equals(info2) {
+ return this.renderer == info2.renderer && this.version == info2.version;
+ }
+
+ static getByType(driver) {
+ const doc = new DOMParser().parseFromString("<html/>", "text/html");
+ const canvas = doc.createElement("canvas");
+ canvas.width = 1;
+ canvas.height = 1;
+ let error;
+ canvas.addEventListener("webglcontextcreationerror", function (e) {
+ error = true;
+ });
+ let gl = null;
+ try {
+ gl = canvas.getContext(driver);
+ } catch (e) {
+ error = true;
+ }
+ if (error || !gl?.getExtension) {
+ return undefined;
+ }
+
+ let ext = null;
+ try {
+ ext = gl.getExtension("MOZ_debug");
+ } catch (e) {}
+ if (!ext) {
+ return undefined;
+ }
+
+ const data = new DriverInfo(gl, ext);
+
+ try {
+ gl.getExtension("WEBGL_lose_context").loseContext();
+ } catch (e) {}
+
+ return data;
+ }
+
+ static getAll() {
+ const drivers = [];
+
+ function tryDriver(type) {
+ const driver = DriverInfo.getByType(type);
+ if (driver) {
+ drivers.push(driver);
+ }
+ }
+
+ tryDriver("webgl");
+ tryDriver("webgl2");
+ tryDriver("webgpu");
+
+ return drivers;
+ }
+}
+
+export class ReportBrokenSiteParent extends JSWindowActorParent {
+ #getAntitrackingBlockList() {
+ // If content-track-digest256 is in the tracking table,
+ // the user has enabled the strict list.
+ const trackingTable = Services.prefs.getCharPref(
+ "urlclassifier.trackingTable"
+ );
+ return trackingTable.includes("content") ? "strict" : "basic";
+ }
+
+ #getAntitrackingInfo(browsingContext) {
+ return {
+ blockList: this.#getAntitrackingBlockList(),
+ isPrivateBrowsing: browsingContext.usePrivateBrowsing,
+ hasTrackingContentBlocked: !!(
+ browsingContext.currentWindowGlobal.contentBlockingEvents &
+ Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT
+ ),
+ hasMixedActiveContentBlocked: !!(
+ browsingContext.secureBrowserUI.state &
+ Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT
+ ),
+ hasMixedDisplayContentBlocked: !!(
+ browsingContext.secureBrowserUI.state &
+ Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT
+ ),
+ };
+ }
+
+ #getBasicGraphicsInfo(gfxInfo) {
+ const get = name => {
+ try {
+ return gfxInfo[name];
+ } catch (e) {}
+ return undefined;
+ };
+
+ const clean = rawObj => {
+ const obj = JSON.parse(JSON.stringify(rawObj));
+ if (!Object.keys(obj).length) {
+ return undefined;
+ }
+ return obj;
+ };
+
+ const cleanDevice = (vendorID, deviceID, subsysID) => {
+ return clean({ vendorID, deviceID, subsysID });
+ };
+
+ const d1 = cleanDevice(
+ get("adapterVendorID"),
+ get("adapterDeviceID"),
+ get("adapterSubsysID")
+ );
+ const d2 = cleanDevice(
+ get("adapterVendorID2"),
+ get("adapterDeviceID2"),
+ get("adapterSubsysID2")
+ );
+ const devices = (get("isGPU2Active") ? [d2, d1] : [d1, d2]).filter(
+ v => v !== undefined
+ );
+
+ return clean({
+ direct2DEnabled: get("direct2DEnabled"),
+ directWriteEnabled: get("directWriteEnabled"),
+ directWriteVersion: get("directWriteVersion"),
+ hasTouchScreen: gfxInfo.getInfo().ApzTouchInput == 1,
+ cleartypeParameters: get("clearTypeParameters"),
+ targetFrameRate: get("targetFrameRate"),
+ devices,
+ });
+ }
+
+ #getGraphicsInfo() {
+ const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo);
+
+ const data = this.#getBasicGraphicsInfo(gfxInfo);
+
+ data.drivers = DriverInfo.getAll().map(({ renderer, vendor, version }) => {
+ return { renderer: `${vendor} -- ${renderer}`, version };
+ });
+
+ try {
+ const info = gfxInfo.CodecSupportInfo;
+ if (info) {
+ const codecs = {};
+ for (const item of gfxInfo.CodecSupportInfo.split("\n")) {
+ const [codec, ...types] = item.split(" ");
+ if (!codecs[codec]) {
+ codecs[codec] = { software: false, hardware: false };
+ }
+ if (types.includes("SW")) {
+ codecs[codec].software = true;
+ }
+ if (types.includes("HW")) {
+ codecs[codec].hardware = true;
+ }
+ }
+ data.codecSupport = codecs;
+ }
+ } catch (e) {}
+
+ try {
+ const { features } = gfxInfo.getFeatureLog();
+ data.features = {};
+ for (let { name, log, status } of features) {
+ for (const item of log.reverse()) {
+ if (!item.failureId || item.status != status) {
+ continue;
+ }
+ status = `${status} (${item.message || item.failureId})`;
+ }
+ data.features[name] = status;
+ }
+ } catch (e) {}
+
+ try {
+ if (AppConstants.platform !== "android") {
+ data.monitors = gfxInfo.getMonitors();
+ }
+ } catch (e) {}
+
+ return data;
+ }
+
+ async #getScreenshot(browsingContext, format, quality) {
+ const zoom = browsingContext.fullZoom;
+ const scale = browsingContext.topChromeWindow?.devicePixelRatio || 1;
+ const wgp = browsingContext.currentWindowGlobal;
+
+ const image = await wgp.drawSnapshot(
+ undefined, // rect
+ scale * zoom,
+ "white",
+ undefined // resetScrollPosition
+ );
+
+ const doc = Services.appShell.hiddenDOMWindow.document;
+ const canvas = doc.createElement("canvas");
+ canvas.width = image.width;
+ canvas.height = image.height;
+
+ const ctx = canvas.getContext("2d", { alpha: false });
+ ctx.drawImage(image, 0, 0);
+ image.close();
+
+ return canvas.toDataURL(`image/${format}`, quality / 100);
+ }
+
+ async receiveMessage(msg) {
+ switch (msg.name) {
+ case "GetWebcompatInfoOnlyAvailableInParentProcess": {
+ const { format, quality } = msg.data;
+ const screenshot = await this.#getScreenshot(
+ msg.target.browsingContext,
+ format,
+ quality
+ ).catch(e => {
+ console.error("Report Broken Site: getting a screenshot failed", e);
+ return Promise.resolve(undefined);
+ });
+ return {
+ antitracking: this.#getAntitrackingInfo(msg.target.browsingContext),
+ graphics: this.#getGraphicsInfo(),
+ locales: Services.locale.availableLocales,
+ screenshot,
+ security: getSecurityInfo(),
+ };
+ }
+ }
+ return null;
+ }
+}
diff --git a/toolkit/components/reportbrokensite/metrics.yaml b/toolkit/components/reportbrokensite/metrics.yaml
new file mode 100644
index 0000000000..cde4d28ef4
--- /dev/null
+++ b/toolkit/components/reportbrokensite/metrics.yaml
@@ -0,0 +1,686 @@
+# 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/.
+
+# Adding a new metric? We have docs for that!
+# https://firefox-source-docs.mozilla.org/toolkit/components/glean/user/new_definitions_file.html
+
+---
+$schema: moz://mozilla.org/schemas/glean/metrics/2-0-0
+$tags:
+ - "Web Compatibility :: Tooling & Investigations"
+
+broken_site_report:
+ breakage_category:
+ type: string
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ An optional select-box choice (options may eventually change)
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ description:
+ type: text
+ expires: never
+ data_sensitivity:
+ - highly_sensitive
+ description: >
+ An optional description of the site issue the user is experiencing. May contain PII.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ url:
+ type: url
+ expires: never
+ data_sensitivity:
+ - highly_sensitive
+ description: >
+ The URL of the site being reported. May contain PII.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+
+broken_site_report.tab_info:
+ languages:
+ type: string_list
+ expires: never
+ data_sensitivity:
+ - technical
+ description: >
+ The languages the site actually sees (may be overridden)
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ useragent_string:
+ type: text
+ expires: never
+ data_sensitivity:
+ - stored_content
+ description: >
+ The userAgent the site actually sees (may be overridden)
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+broken_site_report.tab_info.antitracking:
+ block_list:
+ type: string
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Currently either `basic` or `strict`, may change in the future.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ has_mixed_active_content_blocked:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Whether the reported tab has any blocked mixed active content
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ has_mixed_display_content_blocked:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Whether the reported tab has any blocked mixed display content
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ has_tracking_content_blocked:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Whether the reported tab has any blocked tracking content
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ is_private_browsing:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Whether the tab the user was on when reporting is in private browsing mode
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+broken_site_report.tab_info.frameworks:
+ fastclick:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Whether the FastClick web library was detected on the original tab.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ marfeel:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Whether the Marfeel web framework was detected on the original tab.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ mobify:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Whether the Mobify web framework was detected on the original tab.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+
+broken_site_report.browser_info.app:
+ default_locales:
+ type: string_list
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Locale strings, ie `["en-US", "en"]`
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ default_useragent_string:
+ type: text
+ expires: never
+ data_sensitivity:
+ - stored_content
+ description: >
+ The default user-agent string of the browser
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ fission_enabled:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - technical
+ description: >
+ Whether Fission is enabled
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+broken_site_report.browser_info.graphics:
+ device_pixel_ratio:
+ type: string
+ expires: never
+ data_sensitivity:
+ - technical
+ description: >
+ A decimal number
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ has_touch_screen:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - technical
+ description: >
+ Whether a touch screen was detected
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ devices_json:
+ type: text
+ expires: never
+ data_sensitivity:
+ - stored_content
+ description: >
+ JSON array of objects with `vendorID` and `deviceID`.
+ For instance, `[{"vendorID":"0x000", "deviceID":"0x001"}]`
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ drivers_json:
+ type: text
+ expires: never
+ data_sensitivity:
+ - stored_content
+ description: >
+ JSON array of objects with `renderer` and `version`.
+ For instance, `[{"renderer":"demo", "version":"0.2"}]`
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ features_json:
+ type: text
+ expires: never
+ data_sensitivity:
+ - stored_content
+ description: >
+ JSON object.
+ For instance, `{"WEBRENDER":"available","WEBRENDER_PARTIAL":"disabled (User disabled via pref)"}`
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ monitors_json:
+ type: text
+ expires: never
+ data_sensitivity:
+ - stored_content
+ description: >
+ JSON array of objects with `screenWidth`, 'screenHeight`, and `scale`.
+ For instance, `[{"screenWidth":3584,"screenHeight":2240,"scale":2}]`
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+broken_site_report.browser_info.system:
+ is_tablet:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - technical
+ description: >
+ Whether the device is a tablet
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ memory:
+ type: quantity
+ unit: mb
+ expires: never
+ data_sensitivity:
+ - technical
+ description: >
+ How many mb of RAM is reported for the system
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+
+broken_site_report.browser_info.prefs:
+ opaque_response_blocking:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Value of `browser.opaqueResponseBlocking`
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ installtrigger_enabled:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Value of `extensions.InstallTrigger.enabled`
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ software_webrender:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Value of `gfx.webrender.software`
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ forced_accelerated_layers:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Value of `layers.acceleration_force.enabled`
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ cookie_behavior:
+ type: quantity
+ unit: integer
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Value of `network.cookie.cookieBehavior`
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ global_privacy_control_enabled:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Value of `privacy.globalprivacycontrol.enabled`
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ resist_fingerprinting_enabled:
+ type: boolean
+ expires: never
+ data_sensitivity:
+ - interaction
+ description: >
+ Value of `privacy.resistFingerprinting`
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+
+broken_site_report.browser_info.security:
+ antivirus:
+ type: string_list
+ expires: never
+ data_sensitivity:
+ - technical
+ description: >
+ Which antivirus software was reported on this system.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ antispyware:
+ type: string_list
+ expires: never
+ data_sensitivity:
+ - technical
+ description: >
+ Which antispyware software was reported on this system.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+ firewall:
+ type: string_list
+ expires: never
+ data_sensitivity:
+ - technical
+ description: >
+ Which firewall software was reported on this system.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ send_in_pings:
+ - broken-site-report
+
+
+webcompatreporting:
+ opened:
+ type: event
+ description: >
+ Records the method for opening the webcompat reporting window.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ expires: never
+ extra_keys:
+ source:
+ description: >
+ From which entry-point the user accessed the reporting window.
+ One of
+ * `helpMenu`
+ * `hamburgerMenu`
+ * `ETPShieldIconMenu`
+ type: string
+ reason_dropdown:
+ type: event
+ description: >
+ Record whether the user has a dropdown enabled + whether the dropdown menu is optional or mandatory.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ expires: never
+ extra_keys:
+ setting:
+ description: >
+ One of
+ * `disabled`
+ * `optional`
+ * `required`
+ type: string
+ send:
+ type: event
+ description: >
+ Recorded when a user selects the Send button to submit webcompat report data.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ expires: never
+ send_more_info:
+ type: event
+ description: >
+ Recorded when a user clicks on the Send More Info link in the reporting UI
+ The user will be redirected to webcompat.com to submit a more comprehensive report.
+ (This is only enabled on beta/nightly/pre-release channels).
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - twisniewski@mozilla.com
+ - webcompat-reporting-tool-telemetry@mozilla.com
+ expires: never
diff --git a/toolkit/components/reportbrokensite/moz.build b/toolkit/components/reportbrokensite/moz.build
new file mode 100644
index 0000000000..e0956c46e3
--- /dev/null
+++ b/toolkit/components/reportbrokensite/moz.build
@@ -0,0 +1,13 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+FINAL_TARGET_FILES.actors = [
+ "ReportBrokenSiteChild.sys.mjs",
+ "ReportBrokenSiteParent.sys.mjs",
+]
+
+with Files("**"):
+ BUG_COMPONENT = ("Web Compatibility", "Tooling & Investigations")
diff --git a/toolkit/components/reportbrokensite/pings.yaml b/toolkit/components/reportbrokensite/pings.yaml
new file mode 100644
index 0000000000..7b8ee70c3c
--- /dev/null
+++ b/toolkit/components/reportbrokensite/pings.yaml
@@ -0,0 +1,18 @@
+# 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/.
+
+---
+$schema: moz://mozilla.org/schemas/glean/pings/2-0-0
+
+broken-site-report:
+ description: |
+ A ping containing the data for a user-initiated report for a broken site.
+ Does not contain a `client_id`. All report data is self-contained.
+ include_client_id: false
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852340#c16
+ notification_emails:
+ - twisniewski@mozilla.com