summaryrefslogtreecommitdiffstats
path: root/browser/extensions/report-site-issue/background.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/extensions/report-site-issue/background.js')
-rw-r--r--browser/extensions/report-site-issue/background.js215
1 files changed, 215 insertions, 0 deletions
diff --git a/browser/extensions/report-site-issue/background.js b/browser/extensions/report-site-issue/background.js
new file mode 100644
index 0000000000..d5c4edcbd7
--- /dev/null
+++ b/browser/extensions/report-site-issue/background.js
@@ -0,0 +1,215 @@
+/* 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 */
+
+const Config = {
+ newIssueEndpoint: "https://webcompat.com/issues/new",
+ newIssueEndpointPref: "newIssueEndpoint",
+ screenshotFormat: {
+ format: "jpeg",
+ quality: 75,
+ },
+};
+
+const FRAMEWORK_KEYS = ["hasFastClick", "hasMobify", "hasMarfeel"];
+
+browser.pageActionExtras.setLabelForHistogram("webcompat");
+
+browser.pageAction.onClicked.addListener(tab => {
+ return getWebCompatInfoForTab(tab).then(
+ info => {
+ return openWebCompatTab(info);
+ },
+ err => {
+ console.error("WebCompat Reporter: unexpected error", err);
+ }
+ );
+});
+
+browser.aboutConfigPrefs.onEndpointPrefChange.addListener(checkEndpointPref);
+
+checkEndpointPref();
+
+async function checkEndpointPref() {
+ const value = await browser.aboutConfigPrefs.getEndpointPref();
+ if (value === undefined) {
+ browser.aboutConfigPrefs.setEndpointPref(Config.newIssueEndpoint);
+ } else {
+ Config.newIssueEndpoint = value;
+ }
+}
+
+function hasFastClickPageScript() {
+ const win = window.wrappedJSObject;
+
+ if (win.FastClick) {
+ return true;
+ }
+
+ for (const property in win) {
+ try {
+ const proto = win[property].prototype;
+ if (proto && proto.needsClick) {
+ return true;
+ }
+ } catch (_) {}
+ }
+
+ return false;
+}
+
+function hasMobifyPageScript() {
+ const win = window.wrappedJSObject;
+ return !!(win.Mobify && win.Mobify.Tag);
+}
+
+function hasMarfeelPageScript() {
+ const win = window.wrappedJSObject;
+ return !!win.marfeel;
+}
+
+function checkForFrameworks(tabId) {
+ return browser.tabs
+ .executeScript(tabId, {
+ code: `
+ (function() {
+ ${hasFastClickPageScript};
+ ${hasMobifyPageScript};
+ ${hasMarfeelPageScript};
+
+ const result = {
+ hasFastClick: hasFastClickPageScript(),
+ hasMobify: hasMobifyPageScript(),
+ hasMarfeel: hasMarfeelPageScript(),
+ }
+
+ return result;
+ })();
+ `,
+ })
+ .then(([results]) => results)
+ .catch(() => false);
+}
+
+function getWebCompatInfoForTab(tab) {
+ const { id, url } = tab;
+ return Promise.all([
+ browser.browserInfo.getBlockList(),
+ browser.browserInfo.getBuildID(),
+ browser.browserInfo.getGraphicsPrefs(),
+ browser.browserInfo.getUpdateChannel(),
+ browser.browserInfo.hasTouchScreen(),
+ browser.tabExtras.getWebcompatInfo(id),
+ checkForFrameworks(id),
+ browser.tabs.captureTab(id, Config.screenshotFormat).catch(e => {
+ console.error("WebCompat Reporter: getting a screenshot failed", e);
+ return Promise.resolve(undefined);
+ }),
+ ]).then(
+ ([
+ blockList,
+ buildID,
+ graphicsPrefs,
+ channel,
+ hasTouchScreen,
+ frameInfo,
+ frameworks,
+ screenshot,
+ ]) => {
+ if (channel !== "linux") {
+ delete graphicsPrefs["layers.acceleration.force-enabled"];
+ }
+
+ const consoleLog = frameInfo.log;
+ delete frameInfo.log;
+
+ return Object.assign(frameInfo, {
+ tabId: id,
+ blockList,
+ details: Object.assign(graphicsPrefs, {
+ buildID,
+ channel,
+ consoleLog,
+ frameworks,
+ hasTouchScreen,
+ "mixed active content blocked":
+ frameInfo.hasMixedActiveContentBlocked,
+ "mixed passive content blocked":
+ frameInfo.hasMixedDisplayContentBlocked,
+ "tracking content blocked": frameInfo.hasTrackingContentBlocked
+ ? `true (${blockList})`
+ : "false",
+ }),
+ screenshot,
+ url,
+ });
+ }
+ );
+}
+
+function stripNonASCIIChars(str) {
+ // eslint-disable-next-line no-control-regex
+ return str.replace(/[^\x00-\x7F]/g, "");
+}
+
+browser.l10n
+ .getMessage("wc-reporter.label2")
+ .then(browser.pageActionExtras.setDefaultTitle, () => {});
+
+browser.l10n
+ .getMessage("wc-reporter.tooltip")
+ .then(browser.pageActionExtras.setTooltipText, () => {});
+
+async function openWebCompatTab(compatInfo) {
+ const url = new URL(Config.newIssueEndpoint);
+ const { details } = compatInfo;
+ const params = {
+ url: `${compatInfo.url}`,
+ utm_source: "desktop-reporter",
+ utm_campaign: "report-site-issue-button",
+ src: "desktop-reporter",
+ details,
+ extra_labels: [],
+ };
+
+ for (let framework of FRAMEWORK_KEYS) {
+ if (details.frameworks[framework]) {
+ params.details[framework] = true;
+ params.extra_labels.push(
+ framework.replace(/^has/, "type-").toLowerCase()
+ );
+ }
+ }
+ delete details.frameworks;
+
+ if (details["gfx.webrender.all"] || details["gfx.webrender.enabled"]) {
+ params.extra_labels.push("type-webrender-enabled");
+ }
+ if (compatInfo.hasTrackingContentBlocked) {
+ params.extra_labels.push(
+ `type-tracking-protection-${compatInfo.blockList}`
+ );
+ }
+
+ const json = stripNonASCIIChars(JSON.stringify(params));
+ const tab = await browser.tabs.create({ url: url.href });
+ await browser.tabs.executeScript(tab.id, {
+ runAt: "document_end",
+ code: `(function() {
+ async function postMessageData(dataURI, metadata) {
+ const res = await fetch(dataURI);
+ const blob = await res.blob();
+ const data = {
+ screenshot: blob,
+ message: metadata
+ };
+ postMessage(data, "${url.origin}");
+ }
+ postMessageData("${compatInfo.screenshot}", ${json});
+ })()`,
+ });
+}