1
0
Fork 0
firefox/browser/extensions/webcompat/lib/intervention_helpers.js
Daniel Baumann 5e9a113729
Adding upstream version 140.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-25 09:37:52 +02:00

439 lines
8.2 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, UAHelpers */
const GOOGLE_TLDS = [
"com",
"ac",
"ad",
"ae",
"com.af",
"com.ag",
"com.ai",
"al",
"am",
"co.ao",
"com.ar",
"as",
"at",
"com.au",
"az",
"ba",
"com.bd",
"be",
"bf",
"bg",
"com.bh",
"bi",
"bj",
"com.bn",
"com.bo",
"com.br",
"bs",
"bt",
"co.bw",
"by",
"com.bz",
"ca",
"com.kh",
"cc",
"cd",
"cf",
"cat",
"cg",
"ch",
"ci",
"co.ck",
"cl",
"cm",
"cn",
"com.co",
"co.cr",
"com.cu",
"cv",
"com.cy",
"cz",
"de",
"dj",
"dk",
"dm",
"com.do",
"dz",
"com.ec",
"ee",
"com.eg",
"es",
"com.et",
"fi",
"com.fj",
"fm",
"fr",
"ga",
"ge",
"gf",
"gg",
"com.gh",
"com.gi",
"gl",
"gm",
"gp",
"gr",
"com.gt",
"gy",
"com.hk",
"hn",
"hr",
"ht",
"hu",
"co.id",
"iq",
"ie",
"co.il",
"im",
"co.in",
"io",
"is",
"it",
"je",
"com.jm",
"jo",
"co.jp",
"co.ke",
"ki",
"kg",
"co.kr",
"com.kw",
"kz",
"la",
"com.lb",
"com.lc",
"li",
"lk",
"co.ls",
"lt",
"lu",
"lv",
"com.ly",
"co.ma",
"md",
"me",
"mg",
"mk",
"ml",
"com.mm",
"mn",
"ms",
"com.mt",
"mu",
"mv",
"mw",
"com.mx",
"com.my",
"co.mz",
"com.na",
"ne",
"com.nf",
"com.ng",
"com.ni",
"nl",
"no",
"com.np",
"nr",
"nu",
"co.nz",
"com.om",
"com.pk",
"com.pa",
"com.pe",
"com.ph",
"pl",
"com.pg",
"pn",
"com.pr",
"ps",
"pt",
"com.py",
"com.qa",
"ro",
"rs",
"ru",
"rw",
"com.sa",
"com.sb",
"sc",
"se",
"com.sg",
"sh",
"si",
"sk",
"com.sl",
"sn",
"sm",
"so",
"st",
"sr",
"com.sv",
"td",
"tg",
"co.th",
"com.tj",
"tk",
"tl",
"tm",
"to",
"tn",
"com.tr",
"tt",
"com.tw",
"co.tz",
"com.ua",
"co.ug",
"co.uk",
"com",
"com.uy",
"co.uz",
"com.vc",
"co.ve",
"vg",
"co.vi",
"com.vn",
"vu",
"ws",
"co.za",
"co.zm",
"co.zw",
];
var InterventionHelpers = {
skip_if_functions: {
InstallTrigger_defined: () => {
return "InstallTrigger" in window;
},
InstallTrigger_undefined: () => {
return !("InstallTrigger" in window);
},
text_event_supported: () => {
return !!window.TextEvent;
},
},
ua_change_functions: {
add_Chrome: (ua, config) => {
return UAHelpers.addChrome(ua, config.version);
},
add_Firefox_as_Gecko: (ua, config) => {
return UAHelpers.addGecko(ua, config.version);
},
add_Samsung_for_Samsung_devices: ua => {
return UAHelpers.addSamsungForSamsungDevices(ua);
},
add_Version_segment: ua => {
return `${ua} Version/0`;
},
cap_Version_to_99: ua => {
return UAHelpers.capVersionTo99(ua);
},
change_Firefox_to_FireFox: ua => {
return UAHelpers.changeFirefoxToFireFox(ua);
},
change_Gecko_to_like_Gecko: ua => {
return ua.replace("Gecko", "like Gecko");
},
change_OS_to_MacOSX: (ua, config) => {
return UAHelpers.getMacOSXUA(ua, config.arch, config.version);
},
change_OS_to_Windows: ua => {
return UAHelpers.windows(ua);
},
Chrome: (ua, config) => {
config.ua = ua;
config.noFxQuantum = true;
return UAHelpers.getDeviceAppropriateChromeUA(config);
},
Chrome_with_FxQuantum: (ua, config) => {
config.ua = ua;
return UAHelpers.getDeviceAppropriateChromeUA(config);
},
desktop_not_mobile: () => {
return UAHelpers.desktopUA();
},
mimic_Android_Hotspot2_device: ua => {
return UAHelpers.androidHotspot2Device(ua);
},
reduce_firefox_version_by_one: ua => {
const [head, fx, tail] = ua.split(/(firefox\/)/i);
if (!fx || !tail) {
return ua;
}
const major = parseInt(tail);
if (!major) {
return ua;
}
return `${head}${fx}${major - 1}${tail.slice(major.toString().length)}`;
},
Safari: (ua, config) => {
return UAHelpers.safari(config);
},
},
valid_platforms: [
"all",
"android",
"desktop",
"fenix",
"linux",
"mac",
"windows",
],
valid_channels: ["beta", "esr", "nightly", "stable"],
shouldSkip(intervention, firefoxVersion, firefoxChannel) {
const {
bug,
max_version,
min_version,
not_channels,
only_channels,
skip_if,
} = intervention;
if (firefoxChannel) {
if (only_channels && !only_channels.includes(firefoxChannel)) {
return true;
}
if (not_channels?.includes(firefoxChannel)) {
return true;
}
}
if (min_version && firefoxVersion < min_version) {
return true;
}
if (max_version) {
// Make sure to handle the case where only the major version matters,
// for instance if we want 138 and the version number is 138.1.
if (String(max_version).includes(".")) {
if (firefoxVersion > max_version) {
return true;
}
} else if (Math.floor(firefoxVersion) > max_version) {
return true;
}
}
if (skip_if) {
try {
if (this.skip_if_functions[skip_if]?.()) {
return true;
}
} catch (e) {
console.trace(
`Error while checking skip-if condition ${skip_if} for bug ${bug}:`,
e
);
}
}
return false;
},
async getPlatformMatches() {
if (!InterventionHelpers._platformMatches) {
const platformInfo = await browser.runtime.getPlatformInfo();
InterventionHelpers._platformMatches = [
"all",
platformInfo.os,
platformInfo.os == "android" ? "android" : "desktop",
];
if (platformInfo.os == "android") {
const packageName = await browser.appConstants.getAndroidPackageName();
if (packageName.includes("fenix") || packageName.includes("firefox")) {
InterventionHelpers._platformMatches.push("fenix");
}
}
}
return InterventionHelpers._platformMatches;
},
async checkPlatformMatches(intervention) {
let desired = intervention.platforms;
let undesired = intervention.not_platforms;
if (!desired && !undesired) {
return true;
}
const actual = await InterventionHelpers.getPlatformMatches();
if (undesired) {
if (!Array.isArray(undesired)) {
undesired = [undesired];
}
if (
undesired.includes("all") ||
actual.filter(x => undesired.includes(x)).length
) {
return false;
}
}
if (!desired) {
return true;
}
if (!Array.isArray(desired)) {
desired = [desired];
}
return (
desired.includes("all") ||
!!actual.filter(x => desired.includes(x)).length
);
},
applyUAChanges(ua, changes) {
if (!Array.isArray(changes)) {
changes = [changes];
}
for (let config of changes) {
if (typeof config === "string") {
config = { change: config, enabled: true };
}
if (!config.enabled) {
continue;
}
let finalChanges = config.change;
if (!Array.isArray(finalChanges)) {
finalChanges = [finalChanges];
}
for (const change of finalChanges) {
try {
ua = InterventionHelpers.ua_change_functions[change](ua, config);
} catch (e) {
console.trace(
`Error while calling UA change function ${change} for bug ${config.bug}:`,
e
);
return ua;
}
}
}
return ua;
},
/**
* Useful helper to generate a list of domains with a fixed base domain and
* multiple country-TLDs or other cases with various TLDs.
*
* Example:
* matchPatternsForTLDs("*://mozilla.", "/*", ["com", "org"])
* => ["*://mozilla.com/*", "*://mozilla.org/*"]
*/
matchPatternsForTLDs(base, suffix, tlds) {
return tlds.map(tld => base + tld + suffix);
},
/**
* A modified version of matchPatternsForTLDs that always returns the match
* list for all known Google country TLDs.
*/
matchPatternsForGoogle(base, suffix = "/*") {
return InterventionHelpers.matchPatternsForTLDs(base, suffix, GOOGLE_TLDS);
},
};