fune/browser/extensions/report-site-issue/background.js
Luca Greco 14ac3915d9 Bug 1696490 - Fix errors loading report-site-issue builtin extension triggered by pageActionExtras.js due to the pageAction removal. r=mconley,denschub,webcompat-reviewers
This patch does remove the pageActionExtras experimental API, which is what started triggering
those errors after the pageAction manifest property was removed from the manifest in Bug 1690573:

- The pageActionExtras API was internally retrieving the pageAction API class
  (see https://searchfox.org/mozilla-central/rev/eeb8cf278192d68b3977d0adb4d43f1463439269/browser/extensions/report-site-issue/experimentalAPIs/pageActionExtras.js#12-16)
  which is a bit of an hack and it used to work because there was a pageAction property in the
  manifest.json file (and that was what used to guarantee that the ext-pageAction.js API module
  was always loaded before the background page of the extension did have a chance to run)

- In Bug 1690573 we removed the pageAction property from the manifest and as a side-effect the
  ext-pageAction.js module wouldn't be loaded anymore, which did break the assumption in
  the pageActionExtras API (and the extension background page script as a side effect of that)

I assume that if we removed the pageAction from the manifest, then we don't need the pageActionExtras
experimental API neither (it seems that its purpose was to localize the pageAction and to set a custom
telemetry label for it) and so to fix the regression I opted to remove the remaining traces of the
pageActionExtras experimental API.

NOTE: there are some more traces left in head.js, which are used for the test cases.
All the tests are currently disabled and it seems that they are meant to be re-enabled
as part or as a follow up of Bug 1693119 and so I think that for those parts we can
wait to get there.

Differential Revision: https://phabricator.services.mozilla.com/D107326
2021-03-08 16:32:18 +00:00

205 lines
5.1 KiB
JavaScript

/* 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.helpMenu.onHelpMenuCommand.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, "");
}
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});
})()`,
});
}