├── src ├── shims │ ├── empty-shim.txt │ ├── tracking-pixel.png │ ├── empty-script.js │ ├── mochitest-shim-3.js │ ├── botd.mjs │ ├── google-analytics-ecommerce-plugin.js │ ├── facebook.svg │ ├── vast2.xml │ ├── vast3.xml │ ├── vmad.xml │ ├── addthis-angular.js │ ├── chartbeat.js │ ├── adsafeprotected-ima.js │ ├── bmauth.js │ ├── play.svg │ ├── google-page-ad.js │ ├── adform.js │ ├── doubleverify.js │ ├── iam.js │ ├── iaspet.js │ ├── webtrends.js │ ├── microsoftLogin.js │ ├── moat.js │ ├── microsoftVirtualAssistant.js │ ├── salesforce.js │ ├── instagram.js │ ├── criteo.js │ ├── history.js │ ├── maxmind-geoip.js │ ├── tsn-ca.js │ ├── crave-ca.js │ ├── stackoverflow-login.js │ ├── adnexus-prebid.js │ ├── apstag.js │ ├── kinja.js │ ├── google-ads.js │ ├── fastclick.js │ ├── branch.js │ ├── blogger.js │ ├── bloggerAccount.js │ ├── live-test-shim.js │ ├── firebase.js │ ├── mochitest-shim-2.js │ ├── figshare.js │ ├── mochitest-shim-1.js │ ├── nielsen.js │ ├── messengerLogin.js │ └── eluminate.js ├── about-compat │ ├── aboutPage.json │ ├── aboutPageProcessScript.js │ ├── AboutCompat.sys.mjs │ ├── aboutPage.js │ └── aboutCompat.html ├── injections │ ├── js │ │ ├── .bug1930440-online.singaporepools.com-prevent-unsupported-alert.js.swp │ │ ├── bug0000000-testbed-js-injection.js │ │ ├── bug1818818-fastclick-legacy-shim.js │ │ ├── bug1819678-free4talk.com-window-chrome-shim.js │ │ ├── bug1928941-oasis.decart.ai-window-chrome-shim.js │ │ ├── bug1841730-www.korg.com-fix-broken-page-loads.js │ │ ├── bug1855014-eksiseyler.com.js │ │ ├── bug1889505-bankmandiri.co.id-window.chrome.js │ │ ├── bug1859617-installtrigger-removal-shim.js │ │ ├── bug1902406-sp.hi.co.kr-window-chrome-shim.js │ │ ├── bug1927984-modules.sms-timing.com-chrome-shim.js │ │ ├── bug1774005-installtrigger-shim.js │ │ ├── bug1819476-axisbank.com-webkitSpeechRecognition-shim.js │ │ ├── bug1846742-microsoft.com-search-key-fix.js │ │ ├── bug1724868-news.yahoo.co.jp-ua-override.js │ │ ├── bug1831007-nintendo-window-OnetrustActiveGroups.js │ │ ├── bug1923286-bing.com-image-click-fix.js │ │ ├── bug1819450-cmbchina.com-ua-change.js │ │ ├── bug1849058-nicochannel.jp-picture-in-picture-shim.js │ │ ├── bug1950282-formula1.com-platform-linux-fix.js │ │ ├── bug1448747-fastclick-shim.js │ │ ├── bug1815733-outlook365-clipboard-read-noop.js │ │ ├── bug1945019-order.mealkeyway.com-prevent-unsupported-message.js │ │ ├── bug1905069-one.geekie.com.br-chrome-shims.js │ │ ├── bug1579159-m.tailieu.vn-pdfjs-worker-disable.js │ │ ├── bug1836157-thai-masszazs-niceScroll-disable.js │ │ ├── bug1452707-window.controllers-shim-ib.absa.co.za.js │ │ ├── bug1899937-plus.nhk.jp-request-picture-in-picture.js │ │ ├── bug1898946-transcrib.io-chrome-shim.js │ │ ├── bug1799968-www.samsung.com-appVersion-linux-fix.js │ │ ├── bug1950301-shamir.com-ua-overrides.js │ │ ├── bug1457335-histography.io-ua-change.js │ │ ├── bug1889326-office365-email-handling-prompt-autohide.js │ │ ├── bug1901780-disable-legacy-mutation-events.js │ │ ├── bug1943898-www.capital.gr-suppress-constant-reloading.js │ │ ├── bug1739489-draftjs-beforeinput.js │ │ ├── bug1842437-www.youtube.com-performance-now-precision.js │ │ ├── bug1769762-tiktok.com-plugins-shim.js │ │ ├── bug1944725-homedepot.com-innerWidth-fix.js │ │ ├── bug1799980-healow.com-infinite-loop-fix.js │ │ ├── bug1930440-online.singaporepools.com-prevent-unsupported-alert.js │ │ ├── bug1939248-rosasthai.com-load-event-helper.js │ │ ├── bug1928216-voice.google.com-permissions.query.js │ │ ├── bug1472075-bankofamerica.com-ua-change.js │ │ ├── bug1898952-digits.t-mobile.com.js │ │ ├── bug1924500-www.tiktok.com-fix-captcha-slider.js │ │ └── bug1897120-turnjs-zoom-fix.js │ └── css │ │ ├── bug0000000-testbed-css-injection.css │ │ ├── bug1707795-office365-sheets-overscroll-disable.css │ │ ├── bug1830796-copyleaks.com-hide-unsupported.css │ │ ├── bug1899937-plus.nhk.jp-hide-unsupported.css │ │ ├── bug1741234-patient.alphalabs.ca-height-fix.css │ │ ├── bug1836103-autostar-novoross.ru-make-map-taller.css │ │ ├── bug1896349-vivaldi.com-selected-text-fix.css │ │ ├── bug1819678-nppes.cms.hhs.gov-unsupported-banner.css │ │ ├── bug1934567-www.port8.fi-scrolling-fix.css │ │ ├── bug1779908-play.google.com-scrollbar-fix.css │ │ ├── bug1892898-investopedia.com-fix-card-height.css │ │ ├── bug1911253-qq.com-unhide-checkboxes.css │ │ ├── bug1942292-beterbed.nl-scrollbar-fix.css │ │ ├── bug1943920-add.org-fix-overlapping-menu.css │ │ ├── bug1694470-myvidster.com-content-not-shown.css │ │ ├── bug1784199-entrata-platform-unsupported.css │ │ ├── bug1945830-aliexpress.com-country-flags-fix.css │ │ ├── bug1770962-coldwellbankerhomes.com-image-height.css │ │ ├── bug1856915-login.yahoo.com-unhide-password-button-fix.css │ │ ├── bug1886616-www.six-group.com-select-fix.css │ │ ├── bug1886566-quezoncity.gov.ph-iframe-height.css │ │ ├── bug1895051-www.zhihu.com-broken-button-fix.css │ │ ├── bug1886591-la-vache-noire.com-cookie-banner-fix.css │ │ ├── bug1948047-lovers.cacaushow.com.br-nudge-login-popup-onscreen.css │ │ ├── bug1931538-buzzfeed.com-card-game-fix.css │ │ ├── bug1845299-docs.google.com-hide-extra-scrollbar-on-speaker-notes.css │ │ ├── bug1926506-aliexpress.com-hide-extra-scrollbars.css │ │ ├── bug1896571-gracobaby.ca-unlock-scrolling.css │ │ ├── bug1947105-pexels.com-nudge-thanks-popup-onscreen.css │ │ ├── bug1941530-climate.rutgers.edu-fix-broken-images.css │ │ ├── bug1925937-gazetasp.com.br-hide-extra-scrollbars.css │ │ ├── bug1947979-shazam.com-hide-extra-scrollbars.css │ │ ├── bug1575000-apply.lloydsbank.co.uk-radio-buttons-fix.css │ │ ├── bug1836105-cnn.com-fix-blank-pages-when-printing.css │ │ ├── bug1848849-theaa.com-printing-mode-fix.css │ │ ├── bug1868345-tvmovie.de-scroll-fix.css │ │ ├── bug1901000-eyebuydirect.ca-fix-paypal-button.css │ │ ├── bug1950053-omegleapp.me-fix-scrollbars.css │ │ ├── bug1944727-www.linkedin.com-fix-dark-overlay.css │ │ ├── bug1644830-missingmail.usps.com-checkboxes-not-visible.css │ │ ├── bug1610344-directv.com.co-hide-unsupported-message.css │ │ ├── bug1836872-docs.google.com-font-submenus-inaccessible.css │ │ ├── bug1873166-nsandi.com-hide-unsupported-message.css │ │ ├── bug1848713-cleanrider.com-slider.css │ │ ├── bug1925508-developer-apple.com-transform-scale.css │ │ ├── bug1830752-afisha.ru-slider-pointer-events.css │ │ └── bug1886293-futurePLC-sites-trending_scrollbars.css ├── tests │ └── browser │ │ ├── shims_test_3.js │ │ ├── smartblock_embed_test.html │ │ ├── shims_test.js │ │ ├── shims_test_2.js │ │ ├── browser.toml │ │ ├── iframe_test.html │ │ ├── shims_test.html │ │ ├── shims_test_2.html │ │ ├── shims_test_3.html │ │ ├── browser_aboutcompat.js │ │ ├── embed_test.js │ │ └── browser_shims.js ├── experiment-apis │ ├── appConstants.json │ ├── systemManufacturer.json │ ├── systemManufacturer.js │ ├── matchPatterns.json │ ├── matchPatterns.js │ ├── aboutConfigPrefsChild.js │ ├── testUtils.js │ ├── testUtils.json │ ├── appConstants.js │ ├── aboutConfigPrefs.js │ └── aboutConfigPrefs.json ├── components.conf ├── run.js └── lib │ ├── requestStorageAccess_helper.js │ ├── messaging_helper.js │ └── shim_messaging_helper.js ├── .prettierignore ├── .swp ├── .gitignore ├── .github └── renovate.json ├── spec ├── support │ └── jasmine.json ├── helpers │ ├── mock_about_compat_broker.js │ ├── webext_manifest_schema.js │ ├── mock_webextension_apis.js │ └── content_scripts_test_helpers.js └── available_shims.spec.js ├── .cron.yml ├── .prettierrc.js ├── CODE_OF_CONDUCT.md ├── .githooks └── pre-push ├── package.json └── testing └── webcompat └── interventions └── tests └── test_1947105_pexels_com.py /src/shims/empty-shim.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | src/run.js 2 | -------------------------------------------------------------------------------- /.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-extensions/webcompat-addon/HEAD/.swp -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | dist 3 | node_modules 4 | npm-debug.log 5 | web-ext-artifacts 6 | *.pyc 7 | -------------------------------------------------------------------------------- /src/shims/tracking-pixel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-extensions/webcompat-addon/HEAD/src/shims/tracking-pixel.png -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base"], 3 | "ignoreDeps": ["prettier"], 4 | "reviewers": ["denschub"] 5 | } 6 | -------------------------------------------------------------------------------- /src/about-compat/aboutPage.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "aboutCompat", 4 | "description": "Enables the about:compat page" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /spec/support/jasmine.json: -------------------------------------------------------------------------------- 1 | { 2 | "spec_dir": "spec", 3 | "spec_files": ["**/*[sS]pec.js"], 4 | "helpers": ["helpers/**/*.js"], 5 | "stopSpecOnExpectationFailure": false, 6 | "random": true 7 | } 8 | -------------------------------------------------------------------------------- /.cron.yml: -------------------------------------------------------------------------------- 1 | # Definitions for jobs that run periodically. For details on the format, see 2 | # `taskcluster/taskgraph/cron/schema.py`. For documentation, see 3 | # `taskcluster/docs/cron.rst`. 4 | 5 | --- 6 | 7 | jobs: [] 8 | -------------------------------------------------------------------------------- /src/injections/js/.bug1930440-online.singaporepools.com-prevent-unsupported-alert.js.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-extensions/webcompat-addon/HEAD/src/injections/js/.bug1930440-online.singaporepools.com-prevent-unsupported-alert.js.swp -------------------------------------------------------------------------------- /src/shims/empty-script.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /* This script is intentionally empty */ 6 | -------------------------------------------------------------------------------- /src/shims/mochitest-shim-3.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | window.shimPromiseResolve("shimmed"); 8 | -------------------------------------------------------------------------------- /src/tests/browser/shims_test_3.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | window.shimPromiseResolve("did not shim"); 8 | -------------------------------------------------------------------------------- /src/injections/css/bug0000000-testbed-css-injection.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | #css-injection.red { 6 | background-color: #0f0; 7 | } 8 | -------------------------------------------------------------------------------- /src/tests/browser/smartblock_embed_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |

This is content that should get replaced

9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/tests/browser/shims_test.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | if (window.doingOptIn) { 8 | window.optInPromiseResolve(true); 9 | } else { 10 | window.shimPromiseResolve("did not shim"); 11 | } 12 | -------------------------------------------------------------------------------- /src/tests/browser/shims_test_2.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | if (window.doingOptIn) { 8 | window.optInPromiseResolve(true); 9 | } else { 10 | window.shimPromiseResolve("did not shim"); 11 | } 12 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /* eslint-env node */ 6 | 7 | module.exports = { 8 | arrowParens: "avoid", 9 | endOfLine: "lf", 10 | printWidth: 80, 11 | tabWidth: 2, 12 | trailingComma: "es5", 13 | }; 14 | -------------------------------------------------------------------------------- /spec/helpers/mock_about_compat_broker.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | module.exports = { 8 | filterOverrides: () => {}, 9 | portsToAboutCompatTabs: { 10 | broadcast: () => {}, 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /src/shims/botd.mjs: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | let bd = {}; 6 | bd.detect = async function () { 7 | return { bot: false }; 8 | }; 9 | let load = async function () { 10 | return bd; 11 | }; 12 | 13 | export { load, load as default }; 14 | -------------------------------------------------------------------------------- /src/shims/google-analytics-ecommerce-plugin.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | if (!window.gaplugins) { 8 | window.gaplugins = {}; 9 | } 10 | 11 | if (!window.gaplugins.EC) { 12 | window.gaplugins.EC = () => {}; 13 | } 14 | -------------------------------------------------------------------------------- /src/shims/facebook.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Community Participation Guidelines 2 | 3 | This repository is governed by Mozilla's code of conduct and etiquette guidelines. For more details, please read the [Mozilla Community Participation Guidelines](https://www.mozilla.org/about/governance/policies/participation/). 4 | 5 | ## How to Report 6 | 7 | For more information on how to report violations of the Community Participation Guidelines, please read our '[How to Report](https://www.mozilla.org/about/governance/policies/participation/reporting/)' page. 8 | -------------------------------------------------------------------------------- /src/injections/css/bug1707795-office365-sheets-overscroll-disable.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * www.office.com - There is an overscroll effect on Excel sheets which is 7 | * not a very pleasant user experience. This invention disables it. 8 | */ 9 | 10 | .ewr-sheetcontainer { 11 | overscroll-behavior: none; 12 | } 13 | -------------------------------------------------------------------------------- /src/shims/vast2.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | -------------------------------------------------------------------------------- /src/shims/vast3.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | -------------------------------------------------------------------------------- /src/shims/vmad.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | -------------------------------------------------------------------------------- /src/injections/js/bug0000000-testbed-js-injection.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* globals exportFunction */ 8 | 9 | Object.defineProperty(window.wrappedJSObject, "isTestFeatureSupported", { 10 | get: exportFunction(function () { 11 | return true; 12 | }, window), 13 | 14 | set: exportFunction(function () {}, window), 15 | }); 16 | -------------------------------------------------------------------------------- /src/injections/css/bug1830796-copyleaks.com-hide-unsupported.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * copyleaks.com - Unsupported message 7 | * Bug #1830796 - https://bugzilla.mozilla.org/show_bug.cgi?id=1830796 8 | * WebCompat issue #121395 - https://github.com/webcompat/web-bugs/issues/121395 9 | */ 10 | 11 | #outdated { 12 | display: none !important; 13 | } 14 | -------------------------------------------------------------------------------- /src/injections/css/bug1899937-plus.nhk.jp-hide-unsupported.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * plus.nhk.jp - site displays unsupported warning 7 | * Bug #1899937 - https://bugzilla.mozilla.org/show_bug.cgi?id=1899937 8 | * WebCompat issue #103463 - https://webcompat.com/issues/103463 9 | */ 10 | 11 | #for_firefox { 12 | display: none !important; 13 | } 14 | -------------------------------------------------------------------------------- /src/injections/css/bug1741234-patient.alphalabs.ca-height-fix.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * patient.alphalabs.ca - "Continue" button is overlapped by displaced page footer 7 | * Bug #1741234 - https://bugzilla.mozilla.org/show_bug.cgi?id=1741234 8 | * WebCompat issue #93156 - https://webcompat.com/issues/93156 9 | */ 10 | 11 | body { 12 | height: 100%; 13 | } 14 | -------------------------------------------------------------------------------- /src/injections/css/bug1836103-autostar-novoross.ru-make-map-taller.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * autostar-novoross.ru - Map is not as tall as expected 7 | * Bug #1836103 - https://bugzilla.mozilla.org/show_bug.cgi?id=1836103 8 | * WebCompat issue #80763 - https://github.com/webcompat/web-bugs/issues/80763 9 | */ 10 | 11 | .t396 .tn-atom { 12 | height: 100%; 13 | } 14 | -------------------------------------------------------------------------------- /src/tests/browser/browser.toml: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | support-files = [ 3 | "head.js", 4 | "shims_test.js", 5 | "shims_test_2.js", 6 | "shims_test_3.js", 7 | "iframe_test.html", 8 | "shims_test.html", 9 | "shims_test_2.html", 10 | "shims_test_3.html", 11 | "smartblock_embed_test.html", 12 | "embed_test.js", 13 | ] 14 | 15 | ["browser_aboutcompat.js"] 16 | 17 | ["browser_interventions.js"] 18 | 19 | ["browser_shims.js"] 20 | https_first_disabled = true 21 | skip-if = ["verify"] 22 | 23 | ["browser_smartblockembeds.js"] 24 | 25 | ["browser_ua_helpers.js"] 26 | -------------------------------------------------------------------------------- /src/injections/css/bug1896349-vivaldi.com-selected-text-fix.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * vivaldi.com - Selected text is invisible 7 | * Bug #1896349 - https://bugzilla.mozilla.org/show_bug.cgi?id=1896349 8 | * WebCompat issue #136863 - https://webcompat.com/issues/136863 9 | */ 10 | ::selection { 11 | color: HighlightText; 12 | background-color: Highlight; 13 | } 14 | -------------------------------------------------------------------------------- /src/tests/browser/iframe_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 14 | 15 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/experiment-apis/appConstants.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "appConstants", 4 | "description": "experimental API to expose some app constants", 5 | "functions": [ 6 | { 7 | "name": "getEffectiveUpdateChannel", 8 | "type": "function", 9 | "description": "", 10 | "async": true, 11 | "parameters": [] 12 | }, 13 | { 14 | "name": "getReleaseBranch", 15 | "type": "function", 16 | "description": "", 17 | "async": true, 18 | "parameters": [] 19 | } 20 | ] 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /src/tests/browser/shims_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 17 | 18 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /src/tests/browser/shims_test_2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 17 | 18 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /src/tests/browser/shims_test_3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 17 | 18 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /src/shims/addthis-angular.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1713694 - Shim AddThis Angular module 9 | * 10 | * Sites using Angular with AddThis can break entirely if the module is 11 | * blocked. This shim mitigates that breakage by loading an empty module. 12 | */ 13 | 14 | if (!window.addthisModule) { 15 | window.addthisModule = window?.angular?.module("addthis", ["ng"]); 16 | } 17 | -------------------------------------------------------------------------------- /src/injections/css/bug1819678-nppes.cms.hhs.gov-unsupported-banner.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * nppes.cms.hhs.gov - Firefox is an unsupported browser 7 | * WebCompat issue #119017 - https://github.com/webcompat/web-bugs/issues/119017 8 | * 9 | * As everything seems to work just fine, this intervention simply hides the 10 | * banner. 11 | */ 12 | 13 | #unsupportedDiv { 14 | display: none !important; 15 | } 16 | -------------------------------------------------------------------------------- /src/injections/css/bug1934567-www.port8.fi-scrolling-fix.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * www.port8.fi - The site sets Firefox-specific CSS which 7 | * breaks scrolling on mobile. This intervention undoes it. 8 | */ 9 | 10 | @media (max-width: 959px) { 11 | html.firefox .row div[class*="col-lg-"].pos-bottom, 12 | html.firefox .row div[class*="col-lg-"].pos-middle { 13 | height: unset !important; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/shims/chartbeat.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1713699 - Shim ChartBeat tracking 9 | * 10 | * Sites may rely on chartbeat's tracking as they might with Google Analytics, 11 | * expecting it to be present for interactive site content to function. This 12 | * shim mitigates related breakage. 13 | */ 14 | 15 | window.pSUPERFLY = { 16 | activity() {}, 17 | virtualPage() {}, 18 | }; 19 | -------------------------------------------------------------------------------- /src/shims/adsafeprotected-ima.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * 9 | * Sites relying on Ad Safe Protected's adapter for Google IMA may 10 | * have broken videos when the script is blocked. This shim stubs 11 | * out the API to help mitigate major breakage. 12 | */ 13 | 14 | if (!window.googleImaVansAdapter) { 15 | window.googleImaVansAdapter = { 16 | init() {}, 17 | dispose() {}, 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /src/injections/css/bug1779908-play.google.com-scrollbar-fix.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * play.google.com - Extra scrollbar not hidden on store pages. 7 | * 8 | * Bug #1779908 - https://bugzilla.mozilla.org/show_bug.cgi?id=1779908 9 | * 10 | * They are hiding the scrollbar with ::webkit-scrollbar, but not the standards- 11 | * compliant method `scrollbar-width:none`. 12 | */ 13 | .aoJE7e { 14 | scrollbar-width: none; 15 | } 16 | -------------------------------------------------------------------------------- /src/injections/css/bug1892898-investopedia.com-fix-card-height.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * investopedia.com - Article cards are too tall. 7 | * Bug #1892898 - https://bugzilla.mozilla.org/show_bug.cgi?id=1892898 8 | * 9 | * The site is running into an interop issue with images with alt-text 10 | * (see bug 1945916). We can work around this by specifying a minimum height. 11 | */ 12 | .card__img { 13 | min-height: 0; 14 | } 15 | -------------------------------------------------------------------------------- /src/injections/css/bug1911253-qq.com-unhide-checkboxes.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * qq.com - Invisible checkboxes 7 | * Bug #1911253 - https://bugzilla.mozilla.org/show_bug.cgi?id=1911253 8 | * 9 | * The site is relying on a spec-non-compliance bug in Chrome for replaced 10 | * elements, which we can work around with appearance: none. 11 | */ 12 | .accredit_info_op li input[type="checkbox"] { 13 | appearance: none; 14 | } 15 | -------------------------------------------------------------------------------- /src/shims/bmauth.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | if (!window.BmAuth) { 8 | window.BmAuth = { 9 | init: () => new Promise(() => {}), 10 | handleSignIn: () => { 11 | // TODO: handle this properly! 12 | }, 13 | isAuthenticated: () => Promise.resolve(false), 14 | addListener: () => {}, 15 | api: { 16 | event: { 17 | addListener: () => {}, 18 | }, 19 | }, 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /src/injections/css/bug1942292-beterbed.nl-scrollbar-fix.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * beterbed.nl - Extra ugly scrollbar in header. 7 | * 8 | * Bug #1942292 - https://bugzilla.mozilla.org/show_bug.cgi?id=1942292 9 | * 10 | * They are hiding the scrollbar with ::webkit-scrollbar, but not the standards- 11 | * compliant method `scrollbar-width:none`. 12 | */ 13 | .slider-element .slider-content { 14 | scrollbar-width: none; 15 | } 16 | -------------------------------------------------------------------------------- /src/shims/play.svg: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/experiment-apis/systemManufacturer.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "systemManufacturer", 4 | "description": "experimental API extension to allow reading the device's manufacturer", 5 | "functions": [ 6 | { 7 | "name": "getManufacturer", 8 | "type": "function", 9 | "description": "Get the device's manufacturer", 10 | "parameters": [], 11 | "returns": { 12 | "type": "string", 13 | "properties": {}, 14 | "additionalProperties": { "type": "any" }, 15 | "description": "The manufacturer's name." 16 | } 17 | } 18 | ] 19 | } 20 | ] 21 | -------------------------------------------------------------------------------- /src/shims/google-page-ad.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1713692 - Shim Google Page Ad conversion tracker 9 | * 10 | * This shim stubs out the simple API for converstion tracking with 11 | * Google Page Ad, mitigating major breakage on pages which presume 12 | * the API will always successfully load. 13 | */ 14 | 15 | if (!window.google_trackConversion) { 16 | window.google_trackConversion = () => {}; 17 | } 18 | -------------------------------------------------------------------------------- /src/injections/css/bug1943920-add.org-fix-overlapping-menu.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * add.org/adhd-facts - mobile menu is permanently open 7 | * Bug #1943920 - https://bugzilla.mozilla.org/show_bug.cgi?id=1943920 8 | * WebCompat issue #147170 - https://webcompat.com/issues/147170 9 | * 10 | * The site is using a faulty -moz-transform rule, which we can unset. 11 | */ 12 | .mobile-menu-wrapper { 13 | transform: translate(100%, 0); 14 | } 15 | -------------------------------------------------------------------------------- /src/injections/css/bug1694470-myvidster.com-content-not-shown.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * m.myvidster.com - Content is not shown 7 | * Bug #1694470 - https://bugzilla.mozilla.org/show_bug.cgi?id=1694470 8 | * WebCompat issue #67308 - https://webcompat.com/issues/67308 9 | * 10 | * The site depends on Sencha Touch and should receive some specific 11 | * -webkit-box-flex be working. 12 | */ 13 | #home_refresh_var { 14 | -webkit-box-flex: 1; 15 | } 16 | -------------------------------------------------------------------------------- /src/injections/css/bug1784199-entrata-platform-unsupported.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * aptsovation.com - Unsupported message is displayed on sites based on Entrata platform 7 | * Bug #1784199 - https://bugzilla.mozilla.org/show_bug.cgi?id=1784199 8 | * WebCompat issue #100131 - https://webcompat.com/issues/100131 9 | */ 10 | 11 | * { 12 | color: unset; 13 | } 14 | 15 | #browser-warning-popup, 16 | #propertyProduct, 17 | .banner_overlay { 18 | display: none; 19 | } 20 | -------------------------------------------------------------------------------- /src/injections/css/bug1945830-aliexpress.com-country-flags-fix.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * aliexpress.com - country flags are too small and overlap with other items. 7 | * Bug #1945830 - https://bugzilla.mozilla.org/show_bug.cgi?id=1945830 8 | * 9 | * Country flags have an extra -moz-transform specified on top of using 10 | * CSS Zooms, which causes the issues. This fix undoes that -moz-transform. 11 | */ 12 | [class*="country-flag-"] { 13 | -moz-transform: none; 14 | } 15 | -------------------------------------------------------------------------------- /src/injections/js/bug1818818-fastclick-legacy-shim.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1818818 - Neutralize FastClick 9 | * 10 | * The patch is applied on sites using older version of FastClick library. 11 | * This allows to disable FastClick and fix various breakage caused 12 | * by the library. 13 | */ 14 | 15 | /* globals exportFunction */ 16 | 17 | CSS2Properties.prototype.wrappedJSObject.msTouchAction = 18 | window.wrappedJSObject.String("none"); 19 | -------------------------------------------------------------------------------- /src/injections/css/bug1770962-coldwellbankerhomes.com-image-height.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * coldwellbankerhomes.com - Property images are displayed squeezed 7 | * Bug #1770962 - https://bugzilla.mozilla.org/show_bug.cgi?id=1770962 8 | * WebCompat issue #102872 - https://webcompat.com/issues/102872 9 | */ 10 | 11 | .property-snapshot-psr-panel 12 | .prop-pix 13 | .photo-carousel.owl 14 | .owl-stage-outer 15 | .owl-item 16 | img { 17 | height: -moz-available; 18 | } 19 | -------------------------------------------------------------------------------- /src/injections/css/bug1856915-login.yahoo.com-unhide-password-button-fix.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * login.yahoo.com - Toggle to reveal password text is missing 7 | * 8 | * Bug #1856915 - https://bugzilla.mozilla.org/show_bug.cgi?id=1856915 9 | * 10 | * Yahoo is using letter-spacing in a way which relies on a Blink quirk to 11 | * not inadvertently hide their show/hide password text toggle. 12 | */ 13 | #password-container > input[type="password"] { 14 | min-width: 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/injections/css/bug1886616-www.six-group.com-select-fix.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * www.six-group.com - Selected input values are hidden 7 | * Bug #1886616 - https://bugzilla.mozilla.org/show_bug.cgi?id=1886616 8 | * WebCompat issue #129271 - https://webcompat.com/issues/129271 9 | * 10 | * The page is hiding CSS content, which is not interoperable. In this 11 | * case, it causes their select dropdown's values to be hidden. 12 | */ 13 | select { 14 | content: normal; 15 | } 16 | -------------------------------------------------------------------------------- /src/injections/css/bug1886566-quezoncity.gov.ph-iframe-height.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * quezoncity.gov.ph - Main iframe has zero height 7 | * Bug #1886566 - https://bugzilla.mozilla.org/show_bug.cgi?id=1886566 8 | * WebCompat issue #130868 - https://webcompat.com/issues/130868 9 | * 10 | * The page's main iframe has zero height because the sites uses the 11 | * non-standard -webkit-fill-available CSS value to give it a height. 12 | */ 13 | iframe#qcid_iframe { 14 | height: 100%; 15 | } 16 | -------------------------------------------------------------------------------- /src/injections/css/bug1895051-www.zhihu.com-broken-button-fix.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * www.zhihu.com - Certain directory buttons are unclickable 7 | * 8 | * Bug #1895051 - https://bugzilla.mozilla.org/show_bug.cgi?id=1895051 9 | * 10 | * On narrow enough screens, some of the site's directory buttons 11 | * overlap with text differently on Firefox and Safari than in Chromium, 12 | * making them unclickable. This fixes the issue. 13 | */ 14 | .css-376mun { 15 | display: block; 16 | } 17 | -------------------------------------------------------------------------------- /src/injections/css/bug1886591-la-vache-noire.com-cookie-banner-fix.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * la-vache-noire.com - Cookie banner is invisible 7 | * Bug #1886591 - https://bugzilla.mozilla.org/show_bug.cgi?id=1886591 8 | * WebCompat issue #131867 - https://webcompat.com/issues/131867 9 | * 10 | * The site nests position:sticky elements, which renders the inner one 11 | * as invisible. We set the inner one to position:fixed as a workaround. 12 | */ 13 | #cookie-bar { 14 | position: fixed; 15 | } 16 | -------------------------------------------------------------------------------- /src/injections/css/bug1948047-lovers.cacaushow.com.br-nudge-login-popup-onscreen.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * cacaushow.org.br - login popup is mostly off-screen 7 | * Bug #1948047 - https://bugzilla.mozilla.org/show_bug.cgi?id=1948047 8 | * 9 | * This site is using the non-standard CSS webkit-fill-available to give 10 | * their popups their height. We can use standard CSS instead to fix it. 11 | */ 12 | app-root .visibility, 13 | app-root .visibility.container { 14 | height: fit-content; 15 | } 16 | -------------------------------------------------------------------------------- /src/injections/css/bug1931538-buzzfeed.com-card-game-fix.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * www.buzzfeed.com - thanksgiving-foods-showdown-quiz card game is broken 7 | * Bug #1931538 - https://bugzilla.mozilla.org/show_bug.cgi?id=1931538 8 | * 9 | * The cards have an interop issue where Chrome ignores pointer-events on the 10 | * back-faces of the cards, but other browsers do not. This CSS fixes it. 11 | */ 12 | [class*="isFlipped"] [class*="cardFace"][class*="cardBack"] { 13 | pointer-events: none; 14 | } 15 | -------------------------------------------------------------------------------- /src/injections/css/bug1845299-docs.google.com-hide-extra-scrollbar-on-speaker-notes.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * docs.google.com/presentation - speaker notes area has an extra vertical scrollbar 7 | * Bug #1845299 - https://bugzilla.mozilla.org/show_bug.cgi?id=1845299 8 | * 9 | * They are using non-standard webkit-scrollbar CSS to hide the scrollbar, but also 10 | * add overflow-y:scroll, so it is always visible. We can use overflow-y:auto instead. 11 | */ 12 | #speakernotes { 13 | overflow-y: auto; 14 | } 15 | -------------------------------------------------------------------------------- /src/experiment-apis/systemManufacturer.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* global ExtensionAPI, Services, XPCOMUtils */ 8 | 9 | this.systemManufacturer = class extends ExtensionAPI { 10 | getAPI() { 11 | return { 12 | systemManufacturer: { 13 | getManufacturer() { 14 | try { 15 | return Services.sysinfo.getProperty("manufacturer"); 16 | } catch (_) { 17 | return undefined; 18 | } 19 | }, 20 | }, 21 | }; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /src/injections/js/bug1819678-free4talk.com-window-chrome-shim.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1827678 - UA spoof for www.free4talk.com 9 | * 10 | * This site is checking for window.chrome, so let's spoof that. 11 | */ 12 | 13 | /* globals exportFunction */ 14 | 15 | console.info( 16 | "window.chrome has been shimmed for compatibility reasons. See https://github.com/webcompat/web-bugs/issues/77727 for details." 17 | ); 18 | 19 | window.wrappedJSObject.chrome = new window.wrappedJSObject.Object(); 20 | -------------------------------------------------------------------------------- /src/injections/js/bug1928941-oasis.decart.ai-window-chrome-shim.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1928941 - UA spoof for oasis.decart.ai 9 | * 10 | * This site is checking for window.chrome, so let's spoof that. 11 | */ 12 | 13 | /* globals exportFunction */ 14 | 15 | console.info( 16 | "window.chrome has been shimmed for compatibility reasons. https://bugzilla.mozilla.org/show_bug.cgi?id=1928941 for details." 17 | ); 18 | 19 | window.wrappedJSObject.chrome = new window.wrappedJSObject.Object(); 20 | -------------------------------------------------------------------------------- /src/injections/css/bug1926506-aliexpress.com-hide-extra-scrollbars.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * www.aliexpress.com - scrollbars which should be hidden are not hidden 7 | * Bug #1926506 - https://bugzilla.mozilla.org/show_bug.cgi?id=1926506 8 | * WebCompat issue #143067 - https://github.com/webcompat/web-bugs/issues/143067 9 | * 10 | * They are using non-standard webkit-scrollbar CSS to hide scrollbars. 11 | * We can use scrollbar-width instead to hide them. 12 | */ 13 | .aec-scrollview { 14 | scrollbar-width: none; 15 | } 16 | -------------------------------------------------------------------------------- /src/injections/css/bug1896571-gracobaby.ca-unlock-scrolling.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * gracobaby.ca - users cannot scroll the page on narrow viewports 7 | * Bug #1896571 - https://bugzilla.mozilla.org/show_bug.cgi?id=1896571 8 | * 9 | * The page uses a meta viewport on narrower screen widths, and also 10 | * hides overflow on the html tag, making it impossible to scroll the 11 | * page. We can unset the overflow to fix this. 12 | */ 13 | 14 | @media (max-width: 767.98px) { 15 | html { 16 | overflow: auto; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/injections/css/bug1947105-pexels.com-nudge-thanks-popup-onscreen.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * add.org/adhd-facts - mobile menu is permanently open 7 | * Bug #1943920 - https://bugzilla.mozilla.org/show_bug.cgi?id=1943920 8 | * WebCompat issue #147170 - https://webcompat.com/issues/147170 9 | * 10 | * The site is using a faulty -moz-transform rule, which we can unset. 11 | */ 12 | [class*="Modal_overlay"][class*="Modal_positionContentCenter"]:has( 13 | [class*="after-open"] 14 | ) { 15 | justify-content: unset; 16 | } 17 | -------------------------------------------------------------------------------- /src/injections/css/bug1941530-climate.rutgers.edu-fix-broken-images.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * climate.rutgers.edu/snowcover - images are sized as too thin to see 7 | * Bug #1941530 - https://bugzilla.mozilla.org/show_bug.cgi?id=1941530 8 | * WebCompat issue #145677 - https://webcompat.com/issues/145677 9 | * 10 | * There are 100%-width SVG images with broken viewboxes which are not 11 | * given a size by non-Chromium browsers. We fix it by unsetting the width. 12 | */ 13 | .u--svg-inside object { 14 | width: revert-layer; 15 | } 16 | -------------------------------------------------------------------------------- /src/injections/css/bug1925937-gazetasp.com.br-hide-extra-scrollbars.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * www.gazetasp.com.br - scrollbars which should be hidden are not hidden 7 | * Bug #1925937 - https://bugzilla.mozilla.org/show_bug.cgi?id=1925937 8 | * WebCompat issue #142986 - https://github.com/webcompat/web-bugs/issues/142986 9 | * 10 | * They are using non-standard webkit-scrollbar CSS to hide scrollbars. We can use 11 | * scrollbar-width instead to hide them. 12 | */ 13 | .busca, 14 | .lista-categorias { 15 | scrollbar-width: none; 16 | } 17 | -------------------------------------------------------------------------------- /src/injections/css/bug1947979-shazam.com-hide-extra-scrollbars.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * www.shazam.com - scrollbars which should be hidden are not hidden 7 | * Bug #1947979 - https://bugzilla.mozilla.org/show_bug.cgi?id=1947979 8 | * WebCompat issue #148320 - https://github.com/webcompat/web-bugs/issues/148320 9 | * 10 | * They are using non-standard webkit-scrollbar CSS to hide the scrollbar. We can use 11 | * scrollbar-width instead to hide it. 12 | */ 13 | [class*="MedialistInner-module_overflowable"] { 14 | scrollbar-width: none; 15 | } 16 | -------------------------------------------------------------------------------- /.githooks/pre-push: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Installing dependencies to run the pre-push check..." 4 | if ! npm install > /dev/null 2> /dev/null; then 5 | echo "!! Installing dependencies failed! Please run 'npm install' to see what's wrong." 6 | exit 1 7 | fi 8 | 9 | echo "Running unit tests..." 10 | if ! npm run --silent test > /dev/null 2> /dev/null; then 11 | echo "!! Running unit tests returned an error! Please run 'npm run test' to see what's wrong." 12 | exit 1 13 | fi 14 | 15 | echo "Running codestyle checks..." 16 | if ! npm run --silent lint > /dev/null 2> /dev/null; then 17 | echo "!! Running codestyle checks returned an error! Please run 'npm run lint' to see what's wrong." 18 | exit 1 19 | fi 20 | 21 | echo "All good, continuing the push!" 22 | -------------------------------------------------------------------------------- /src/injections/css/bug1575000-apply.lloydsbank.co.uk-radio-buttons-fix.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * apply.lloydsbank.co.uk - radio buttons are misplaced 7 | * Bug #1575000 - https://bugzilla.mozilla.org/show_bug.cgi?id=1575000 8 | * WebCompat issue #34969 - https://webcompat.com/issues/34969 9 | * 10 | * Radio buttons are displaced to the left due to positioning issue of ::before 11 | * pseudo element, adding position relative to it's parent fixes the issue. 12 | */ 13 | .radio-content-field .radio.inline label span.text { 14 | position: relative; 15 | } 16 | -------------------------------------------------------------------------------- /src/injections/js/bug1841730-www.korg.com-fix-broken-page-loads.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1841730 - Fix www.korg.com support download page loads on Windows. 9 | * 10 | * They are using a library named PACE, which has a timing bug with Firefox 11 | * which breaks page loads (due to a stuck progress indicator) on Windows. 12 | * This is the fix suggested at https://github.com/CodeByZach/pace/issues/510 13 | */ 14 | 15 | /* globals cloneInto */ 16 | 17 | window.wrappedJSObject.paceOptions = cloneInto({ eventLag: false }, window); 18 | -------------------------------------------------------------------------------- /src/injections/css/bug1836105-cnn.com-fix-blank-pages-when-printing.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * cnn.com - Printing in portrait mode results in blank pages 7 | * Bug #1836105 - https://bugzilla.mozilla.org/show_bug.cgi?id=1836105 8 | * 9 | * Disable some of CNN's giant styles for height, top and margin-bottom, 10 | * since they break print layout in Firefox (as per bug 1830307) 11 | */ 12 | 13 | @media print { 14 | .header__wrapper-outer { 15 | height: initial !important; 16 | top: initial !important; 17 | margin-bottom: initial !important; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/injections/js/bug1855014-eksiseyler.com.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * eksiseyler.com - Set window.loggingEnabled = false 9 | * WebCompat issue #77221 - https://webcompat.com/issues/77221 10 | * 11 | * A scripting error on the site causes images to not load unless 12 | * window.loggingEnabled = false 13 | */ 14 | 15 | /* globals exportFunction */ 16 | 17 | console.info( 18 | "loggingEnabled been set to true for compatibility reasons. See https://webcompat.com/issues/77221 for details." 19 | ); 20 | 21 | window.wrappedJSObject.loggingEnabled = false; 22 | -------------------------------------------------------------------------------- /src/injections/js/bug1889505-bankmandiri.co.id-window.chrome.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * bankmandiri.co.id - Define window.chrome to an empty object 9 | * Bug #1889505 - https://bugzilla.mozilla.org/show_bug.cgi?id=1889505 10 | * WebCompat issue #67924 - https://webcompat.com/issues/67924 11 | */ 12 | 13 | console.info( 14 | "window.chrome has been set to an empty object for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1889505 for details." 15 | ); 16 | 17 | window.wrappedJSObject.chrome = new window.wrappedJSObject.Object(); 18 | -------------------------------------------------------------------------------- /src/injections/js/bug1859617-installtrigger-removal-shim.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1859617 - Generic window.InstallTrigger removal shim 9 | * 10 | * This interventions shims window.InstallTrigger to undefine it. 11 | */ 12 | 13 | /* globals exportFunction */ 14 | 15 | if (typeof window.InstallTrigger !== "undefined") { 16 | console.info( 17 | "window.InstallTrigger has been undefined for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1859617 for details." 18 | ); 19 | 20 | delete window.wrappedJSObject.InstallTrigger; 21 | } 22 | -------------------------------------------------------------------------------- /src/injections/css/bug1848849-theaa.com-printing-mode-fix.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * www.theaa.com - Print preview is blank 7 | * Bug #1848849 - https://bugzilla.mozilla.org/show_bug.cgi?id=1848849 8 | * WebCompat issue #117996 - https://github.com/webcompat/web-bugs/issues/117996 9 | * 10 | * The site is adding a style rule of size: 16px for @page, which is very small and Chrome 11 | * is ignoring the rule, while Firefox honours it. 12 | * Depends on https://bugzilla.mozilla.org/show_bug.cgi?id=1807985 13 | */ 14 | 15 | @media print { 16 | @page { 17 | size: a3 !important; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/components.conf: -------------------------------------------------------------------------------- 1 | # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- 2 | # vim: set filetype=python: 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | 7 | # Note: This file will add static component registration entries for our 8 | # components to the libxul binary, though the actual component JSMs will be 9 | # packaged with the extension. 10 | Classes = [ 11 | { 12 | 'cid': '{97bf9550-2a7b-11e9-b56e-0800200c9a66}', 13 | 'contract_ids': ['@mozilla.org/network/protocol/about;1?what=compat'], 14 | 'esModule': 'resource://webcompat/AboutCompat.sys.mjs', 15 | 'constructor': 'AboutCompat', 16 | }, 17 | ] 18 | -------------------------------------------------------------------------------- /src/injections/css/bug1868345-tvmovie.de-scroll-fix.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * www.tvmovie.de - Can't scroll tv program on tvmovie.de 7 | * Bug #1868345 - https://bugzilla.mozilla.org/show_bug.cgi?id=1868345 8 | * Bug #1840166 - https://bugzilla.mozilla.org/show_bug.cgi?id=1840166 9 | * WebCompat issue #123254 - https://github.com/webcompat/web-bugs/issues/123254 10 | * 11 | * Due to an unfortunate combination of table layout issues and schroll 12 | * anchoring issues, the page keeps scrolling down forever, with no ability 13 | * to scroll back up. 14 | */ 15 | :root { 16 | overflow-anchor: none; 17 | } 18 | -------------------------------------------------------------------------------- /src/injections/css/bug1901000-eyebuydirect.ca-fix-paypal-button.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * eyebuydirect.ca - PayPal button is unclickable 7 | * Bug #1901000 - https://bugzilla.mozilla.org/show_bug.cgi?id=1901000 8 | * WebCompat issue #137777 - https://github.com/webcompat/web-bugs/issues/137777 9 | * 10 | * The site uses Zoid components for the PayPal button, which gives opacity:0 to 11 | * its containing element, which makes it unclickable in Firefox. We should be able 12 | * to simply remove that opacity:0 for now. 13 | */ 14 | 15 | [id^="zoid-paypal-buttons-"] { 16 | opacity: unset !important; 17 | } 18 | -------------------------------------------------------------------------------- /src/injections/css/bug1950053-omegleapp.me-fix-scrollbars.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * omegleapp.me - scrollbars are not hidden, or are too wide. 7 | * Bug #1950053 - https://bugzilla.mozilla.org/show_bug.cgi?id=1950053 8 | * WebCompat issue #148704 - https://github.com/webcompat/web-bugs/issues/148704 9 | * 10 | * They are using non-standard webkit-scrollbar CSS to style scrollbars. 11 | * We can use scrollbar-width instead to fix them. 12 | */ 13 | .chatAndVideo .chatSection .chatBox_messages { 14 | scrollbar-width: thin; 15 | } 16 | .chatAndVideo .chatSection .chatBox { 17 | scrollbar-width: none; 18 | } 19 | -------------------------------------------------------------------------------- /src/tests/browser/browser_aboutcompat.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | add_task(async function test_about_compat_loads_properly() { 4 | const tab = await BrowserTestUtils.openNewForegroundTab({ 5 | gBrowser, 6 | opening: "about:compat", 7 | waitForLoad: true, 8 | }); 9 | 10 | await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { 11 | await ContentTaskUtils.waitForCondition( 12 | () => content.document.querySelector("#interventions tr[data-id]"), 13 | "interventions are listed" 14 | ); 15 | await ContentTaskUtils.waitForCondition( 16 | () => content.document.querySelector("#smartblock tr[data-id]"), 17 | "SmartBlock shims are listed" 18 | ); 19 | ok(true, "Interventions are listed"); 20 | }); 21 | 22 | await BrowserTestUtils.removeTab(tab); 23 | }); 24 | -------------------------------------------------------------------------------- /src/experiment-apis/matchPatterns.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "matchPatterns", 4 | "description": "experimental API extension to expose MatchPattern functionality", 5 | "functions": [ 6 | { 7 | "name": "getMatcher", 8 | "type": "function", 9 | "description": "get a MatchPatternSet", 10 | "parameters": [ 11 | { 12 | "name": "patterns", 13 | "description": "Array of string URL patterns to match", 14 | "type": "array", 15 | "items": { 16 | "type": "string" 17 | } 18 | } 19 | ], 20 | "returns": { 21 | "type": "object", 22 | "properties": { 23 | "matches": { "type": "function" } 24 | } 25 | } 26 | } 27 | ] 28 | } 29 | ] 30 | -------------------------------------------------------------------------------- /src/injections/css/bug1944727-www.linkedin.com-fix-dark-overlay.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * www.linkedin.com - a dark overlay appears which cannot be dismissed. 7 | * Bug #1944727 - https://bugzilla.mozilla.org/show_bug.cgi?id=1944727 8 | * 9 | * Once a day or so, LinkedIn is displaying a promotional banner to 10 | * encourage mobile users to switch to their app. This banner relies 11 | * on the non-standard CSS -webkit-fill-available, and so breaks on 12 | * Firefox (presumably until bug 1872755 is fixed). This CSS fixes it. 13 | */ 14 | .promo.fixed.h-\[-webkit-fill-available\].top-0.w-\[100vw\] { 15 | height: 100%; 16 | } 17 | -------------------------------------------------------------------------------- /src/injections/css/bug1644830-missingmail.usps.com-checkboxes-not-visible.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * missingmail.usps.com - Unable to mark the check-boxes from "Disclaimer and 7 | * Terms and Conditions" section 8 | * Bug #1644830 - https://bugzilla.mozilla.org/show_bug.cgi?id=1644830 9 | * WebCompat issue #53950 - https://webcompat.com/issues/53950 10 | * 11 | * missingmail.usps.com runs into a case of bug 997189, where an absolutely 12 | * positioned inline-block element with floating siblings is shifter to the 13 | * right, and thus invisible. 14 | */ 15 | .mrc-custom-checkbox-container input { 16 | margin-left: -3rem; 17 | } 18 | -------------------------------------------------------------------------------- /src/injections/js/bug1902406-sp.hi.co.kr-window-chrome-shim.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1902406 - UA spoof for sp.hi.co.kr 9 | * 10 | * This site is checking for window.chrome, so let's spoof that. 11 | */ 12 | 13 | /* globals exportFunction */ 14 | 15 | console.info( 16 | "window.chrome has been shimmed for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1902406 for details." 17 | ); 18 | 19 | Object.defineProperty(window.wrappedJSObject, "chrome", { 20 | get: exportFunction(function () { 21 | return true; 22 | }, window), 23 | 24 | set: exportFunction(function () {}, window), 25 | }); 26 | -------------------------------------------------------------------------------- /src/tests/browser/embed_test.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | document.querySelectorAll(".broken-embed-content").forEach(embedContainer => { 6 | // create the "real" embed content 7 | let contentDiv = document.createElement("div"); 8 | contentDiv.classList.add("loaded-embed-content"); 9 | 10 | let contentContent = document.createTextNode("This is the loaded embed"); 11 | contentDiv.appendChild(contentContent); 12 | 13 | // replace the embed code with the "real" embed 14 | embedContainer.replaceWith(contentDiv); 15 | }); 16 | 17 | const finishedEvent = new Event("testEmbedScriptFinished", { 18 | bubbles: true, 19 | }); 20 | window.dispatchEvent(finishedEvent); 21 | -------------------------------------------------------------------------------- /src/injections/css/bug1610344-directv.com.co-hide-unsupported-message.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * directv.com.co - Browser is not supported message 7 | * Bug #1610344 - https://bugzilla.mozilla.org/show_bug.cgi?id=1610344 8 | * WebCompat issue #41822 - https://webcompat.com/issues/41822 9 | * 10 | * directv.com.co is showing a "This browser is not supported" message in 11 | * Firefox. Our tests indicated that everything is working just fine, and our 12 | * previous contact attempts have not been successful. This intervention 13 | * hides the large red unsupported banner. 14 | */ 15 | .browser-compatible.compatible.incompatible { 16 | display: none; 17 | } 18 | -------------------------------------------------------------------------------- /src/injections/css/bug1836872-docs.google.com-font-submenus-inaccessible.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * docs.google.com - font submenus are inaccessible with overlay scrollbars on 7 | * Bug #1836872 - https://bugzilla.mozilla.org/show_bug.cgi?id=1836872 8 | * 9 | * The submenu panels are shifted too far to the right when overlay 10 | * scrollbars are visible, and so they are dismissed while attemting 11 | * to mouse over to them. Shifting them to the left fixes them. 12 | */ 13 | /* font family sub-menus */ 14 | [class="goog-menu goog-menu-vertical"], 15 | /* font style sub-menus */ 16 | .goog-menu.apps-menu-hide-mnemonics { 17 | margin-inline-start: -20px; 18 | } 19 | -------------------------------------------------------------------------------- /src/injections/js/bug1927984-modules.sms-timing.com-chrome-shim.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1927984 - UA spoof for modules.sms-timing.com 9 | * 10 | * This site is checking for window.chrome, so let's spoof that. 11 | */ 12 | 13 | /* globals exportFunction */ 14 | 15 | console.info( 16 | "window.chrome has been shimmed for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1927984 for details." 17 | ); 18 | 19 | Object.defineProperty(window.wrappedJSObject, "chrome", { 20 | get: exportFunction(function () { 21 | return true; 22 | }, window), 23 | 24 | set: exportFunction(function () {}, window), 25 | }); 26 | -------------------------------------------------------------------------------- /src/injections/css/bug1873166-nsandi.com-hide-unsupported-message.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * nsandi.com - Browser is not supported message 7 | * Bug #1873166 - https://bugzilla.mozilla.org/show_bug.cgi?id=1873166 8 | * WebCompat issue #108408 - https://webcompat.com/issues/108408 9 | * WebCompat issue #108319 - https://webcompat.com/issues/108319 10 | * 11 | * nsandi.com shows a "This browser is not compatible" message in 12 | * Firefox. Our contacts indicated that things should be working fine, 13 | * yet the message remains. This intervention hides that message. 14 | */ 15 | .browser-warning-fade, 16 | #unsupported_browser { 17 | display: none !important; 18 | } 19 | -------------------------------------------------------------------------------- /spec/helpers/webext_manifest_schema.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | const WEBEXT_MATCH_PATTERN = new RegExp( 8 | "^(https?|wss?|file|ftp|\\*)://(\\*|\\*\\.[^*/]+|[^*/]+)/.*$", 9 | "i" 10 | ); 11 | 12 | class WebextManifestSchema { 13 | static matchPatternsValid(patterns) { 14 | if (patterns === undefined) { 15 | return true; 16 | } 17 | return patterns.every(pattern => { 18 | if (typeof pattern == "string") { 19 | return pattern.match(WEBEXT_MATCH_PATTERN) !== null; 20 | } else { 21 | return this.matchPatternsValid(pattern.patterns); 22 | } 23 | }); 24 | } 25 | } 26 | 27 | module.exports = WebextManifestSchema; 28 | -------------------------------------------------------------------------------- /src/experiment-apis/matchPatterns.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* global ExtensionAPI */ 8 | 9 | this.matchPatterns = class extends ExtensionAPI { 10 | getAPI(context) { 11 | return { 12 | matchPatterns: { 13 | getMatcher(patterns) { 14 | const set = new MatchPatternSet(patterns); 15 | return Cu.cloneInto( 16 | { 17 | matches: url => { 18 | return set.matches(url); 19 | }, 20 | }, 21 | context.cloneScope, 22 | { 23 | cloneFunctions: true, 24 | } 25 | ); 26 | }, 27 | }, 28 | }; 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /src/injections/css/bug1848713-cleanrider.com-slider.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * www.cleanrider.com - The price slider does not work 7 | * Bug #1848713 - https://bugzilla.mozilla.org/show_bug.cgi?id=1848713 8 | * WebCompat issue #123642 - https://github.com/webcompat/web-bugs/issues/123642 9 | * 10 | * the site disables pointer events on the slider and only allows them 11 | * in -webkit-slider-thumb style which is not supported in Firefox and 12 | * depends on https://bugzilla.mozilla.org/show_bug.cgi?id=1735575 13 | */ 14 | 15 | input[type="range"]::-moz-range-thumb { 16 | -webkit-appearance: none; 17 | height: 24px; 18 | pointer-events: all; 19 | width: 24px; 20 | } 21 | -------------------------------------------------------------------------------- /src/shims/adform.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1713695 - Shim Adform tracking 9 | * 10 | * Sites such as m.tim.it may gate content behind AdForm's trackpoint, 11 | * breaking download links and such if blocked. This shim stubs out the 12 | * script and its related tracking pixel, so the content still works. 13 | */ 14 | 15 | if (!window.Adform) { 16 | window.Adform = { 17 | Opt: { 18 | disableRedirect() {}, 19 | getStatus(clientID, callback) { 20 | callback({ 21 | clientID, 22 | errorMessage: undefined, 23 | optIn() {}, 24 | optOut() {}, 25 | status: "nocookie", 26 | }); 27 | }, 28 | }, 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /src/injections/js/bug1774005-installtrigger-shim.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1774005 - Generic window.InstallTrigger shim 9 | * 10 | * This interventions shims window.InstallTrigger to a string, which evaluates 11 | * as `true` in web developers browser sniffing code. This intervention will 12 | * be applied to multiple domains, see bug 1774005 for more information. 13 | */ 14 | 15 | /* globals exportFunction */ 16 | 17 | console.info( 18 | "The InstallTrigger has been shimmed for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1774005 for details." 19 | ); 20 | 21 | window.wrappedJSObject.InstallTrigger = 22 | "This property has been shimmed for Web Compatibility reasons."; 23 | -------------------------------------------------------------------------------- /src/injections/js/bug1819476-axisbank.com-webkitSpeechRecognition-shim.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * axisbank.com - Shim webkitSpeechRecognition 9 | * WebCompat issue #117770 - https://webcompat.com/issues/117770 10 | * 11 | * The page with bank offerings is not loading options due to the 12 | * site relying on webkitSpeechRecognition, which is undefined in Firefox. 13 | * Shimming it to `class {}` makes the pages work. 14 | */ 15 | 16 | /* globals exportFunction */ 17 | 18 | console.info( 19 | "webkitSpeechRecognition was shimmed for compatibility reasons. See https://webcompat.com/issues/117770 for details." 20 | ); 21 | 22 | Object.getPrototypeOf(window).wrappedJSObject.webkitSpeechRecognition = 23 | class {}; 24 | -------------------------------------------------------------------------------- /src/shims/doubleverify.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1771557 - Shim DoubleVerify analytics 9 | * 10 | * Some sites such as Sports Illustrated expect DoubleVerify's 11 | * analytics script to load, otherwise odd breakage may occur. 12 | * This shim helps mitigate such breakage. 13 | */ 14 | 15 | if (!window?.PQ?.loaded) { 16 | const cmd = []; 17 | cmd.push = function (c) { 18 | try { 19 | c?.(); 20 | } catch (_) {} 21 | }; 22 | 23 | window.apntag = { 24 | anq: [], 25 | }; 26 | 27 | window.PQ = { 28 | cmd, 29 | loaded: true, 30 | getTargeting: (_, cb) => cb?.([]), 31 | init: () => {}, 32 | loadSignals: (_, cb) => cb?.(), 33 | loadSignalsForSlots: (_, cb) => cb?.(), 34 | PTS: {}, 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /src/experiment-apis/aboutConfigPrefsChild.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* global ExtensionAPI, Services, XPCOMUtils */ 8 | 9 | this.aboutConfigPrefs = class extends ExtensionAPI { 10 | getAPI(context) { 11 | const extensionIDBase = context.extension.id.split("@")[0]; 12 | const extensionPrefNameBase = `extensions.${extensionIDBase}.`; 13 | 14 | return { 15 | aboutConfigPrefs: { 16 | getBoolPrefSync(prefName, defaultValue = false) { 17 | try { 18 | return Services.prefs.getBoolPref( 19 | `${extensionPrefNameBase}${prefName}`, 20 | defaultValue 21 | ); 22 | } catch (_) { 23 | return defaultValue; 24 | } 25 | }, 26 | }, 27 | }; 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /src/injections/js/bug1846742-microsoft.com-search-key-fix.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * www.microsoft.com - Pressing enter on search suggestions does nothing 9 | * 10 | * When pressing enter on a search suggestion, nothing happens in Firefox 11 | * due to key-event interop issues. We listen for enter keypresses and 12 | * click the element as a work-around. 13 | */ 14 | 15 | console.info( 16 | "A simulated click is issued on search suggestions when enter is pressed on them for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1846742 for details." 17 | ); 18 | 19 | document.addEventListener("keydown", ({ target, key }) => { 20 | if (key == "Enter" && target.matches(".m-auto-suggest a.f-product")) { 21 | target.click(); 22 | } 23 | }); 24 | -------------------------------------------------------------------------------- /src/injections/js/bug1724868-news.yahoo.co.jp-ua-override.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1724868 - news.yahoo.co.jp - Override UA on Android and Linux 9 | * WebCompat issue #82605 - https://webcompat.com/issues/82605 10 | * 11 | * Yahoo Japan news doesn't allow playing video in Firefox on Android or Linux 12 | * as those are not in their support matrix. They check UA override twice 13 | * and display different UI with the same error. Changing the UA to Chrome via 14 | * content script allows playing the videos. 15 | */ 16 | 17 | /* globals exportFunction, UAHelpers */ 18 | 19 | console.info( 20 | "The user agent has been overridden for compatibility reasons. See https://webcompat.com/issues/82605 for details." 21 | ); 22 | 23 | UAHelpers.overrideWithDeviceAppropriateChromeUA({ OS: "nonLinux" }); 24 | -------------------------------------------------------------------------------- /src/injections/js/bug1831007-nintendo-window-OnetrustActiveGroups.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1831007 - Shim window.OnetrustActiveGroups for Nintendo sites 9 | * 10 | * Nintendo relies on `window.OnetrustActiveGroups` being defined. If it's not, 11 | * users may have intermittent issues signing into their account, as they're 12 | * then trying to call `.split()` on `undefined`. 13 | * 14 | * This intervention sets a default value (an empty string), but still allows 15 | * the value to be overwritten at any time. 16 | */ 17 | 18 | /* globals exportFunction */ 19 | 20 | console.info( 21 | "The window.OnetrustActiveGroups property has been shimmed for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1831007 for details." 22 | ); 23 | 24 | window.wrappedJSObject.OnetrustActiveGroups = ""; 25 | -------------------------------------------------------------------------------- /src/injections/js/bug1923286-bing.com-image-click-fix.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * www.bing.com - Clicking on images from others pages does nothing 9 | * 10 | * When viewing images from other pages in image search results, 11 | * clicking on them does nothing. We can intercept the click 12 | * attempts and force the navigation as a work-around. 13 | */ 14 | 15 | console.info( 16 | "Clicking on image links is being emulated for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1923286 for details." 17 | ); 18 | 19 | document.addEventListener("click", ({ target }) => { 20 | const link = target?.closest(".richImgLnk[target=_blank]"); 21 | if (link) { 22 | const a = document.createElement("a"); 23 | a.target = "_blank"; 24 | a.href = link.href; 25 | a.click(); 26 | } 27 | }); 28 | -------------------------------------------------------------------------------- /src/injections/css/bug1925508-developer-apple.com-transform-scale.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * developer.apple.com - content of the page is shifted to the left 7 | * Bug #1925508 - https://bugzilla.mozilla.org/show_bug.cgi?id=1925508 8 | * WebCompat issue #4070 - https://webcompat.com/issues/4070 9 | * 10 | * The site is relying on zoom property which is not supported by Mozilla, 11 | * see https://bugzilla.mozilla.org/show_bug.cgi?id=390936. Resetting 12 | * -moz-transform on the table of contents fixes the issue. 13 | */ 14 | @media only screen and (min-device-width: 320px) and (max-device-width: 980px), 15 | (min-device-width: 1024px) and (max-device-width: 1024px) and (min-device-height: 1366px) and (max-device-height: 1366px) and (min-width: 320px) and (max-width: 980px) { 16 | #tocContainer { 17 | -moz-transform: initial; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/injections/js/bug1819450-cmbchina.com-ua-change.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1819450 - cmbchina.com - Override UA 9 | * 10 | * The site is using UA detection to redirect to 11 | * m.cmbchina.com (mobile version of the site). Adding `SAMSUNG` allows 12 | * to bypass the detection of mobile browser. 13 | */ 14 | 15 | /* globals exportFunction */ 16 | 17 | console.info( 18 | "The user agent has been overridden for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1081239 for details." 19 | ); 20 | 21 | const MODIFIED_UA = navigator.userAgent + " SAMSUNG"; 22 | 23 | const nav = Object.getPrototypeOf(navigator.wrappedJSObject); 24 | 25 | const ua = Object.getOwnPropertyDescriptor(nav, "userAgent"); 26 | ua.get = exportFunction(() => MODIFIED_UA, window); 27 | Object.defineProperty(nav, "userAgent", ua); 28 | -------------------------------------------------------------------------------- /src/injections/js/bug1849058-nicochannel.jp-picture-in-picture-shim.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1849058 - Shim PictureInPictureWindow for nicochannel.jp 9 | * WebCompat issue #124463 - https://webcompat.com/issues/124463 10 | * 11 | * The page is showing unsupported message based on typeof 12 | * window.PictureInPictureWindow, which is undefined in Firefox. 13 | * Shimming it to `class {}` makes the pages work. 14 | */ 15 | 16 | /* globals exportFunction */ 17 | 18 | console.info( 19 | "PictureInPictureWindow was shimmed for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1849058 for details." 20 | ); 21 | 22 | window.wrappedJSObject.PictureInPictureWindow = exportFunction( 23 | class {}, 24 | window 25 | ); 26 | 27 | Object.getPrototypeOf(document).wrappedJSObject.pictureInPictureElement = null; 28 | -------------------------------------------------------------------------------- /src/shims/iam.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1761774 - Shim INFOnline IAM tracker 9 | * 10 | * Sites using IAM can break if it is blocked. This shim mitigates that 11 | * breakage by loading a stand-in module. 12 | */ 13 | 14 | if (!window.iom?.c) { 15 | window.iom = { 16 | c: () => {}, 17 | consent: () => {}, 18 | count: () => {}, 19 | ct: () => {}, 20 | deloptout: () => {}, 21 | doo: () => {}, 22 | e: () => {}, 23 | event: () => {}, 24 | getInvitation: () => {}, 25 | getPlus: () => {}, 26 | gi: () => {}, 27 | gp: () => {}, 28 | h: () => {}, 29 | hybrid: () => {}, 30 | i: () => {}, 31 | init: () => {}, 32 | oi: () => {}, 33 | optin: () => {}, 34 | setMultiIdentifier: () => {}, 35 | setoptout: () => {}, 36 | smi: () => {}, 37 | soo: () => {}, 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webcompat", 3 | "title": "Web Compat", 4 | "description": "Urgent post-release fixes for web compatibility.", 5 | "license": "MPL-2.0", 6 | "repository": "https://github.com/mozilla/webcompat-addon", 7 | "version": "138.2.0", 8 | "docker-image": "node-lts-latest", 9 | "private": true, 10 | "scripts": { 11 | "autoformat:prettier": "npx prettier --write '**/{*.css,*.html,*.js,*.jsm,*.json,Jakefile}'", 12 | "autoformat:version-number": "npx jake lint:set-package-version", 13 | "autoformat": "./node_modules/.bin/npm-run-all 'autoformat:*'", 14 | "build": "npx jake export-xpi", 15 | "jake": "npx jake", 16 | "lint:package-version-match": "npx jake lint:verify-version-match", 17 | "lint:prettier": "npx prettier --check '**/{*.css,*.js,*.jsm,*.json,Jakefile}'", 18 | "lint": "./node_modules/.bin/npm-run-all 'lint:*'", 19 | "test": "npx jasmine" 20 | }, 21 | "devDependencies": { 22 | "jake": "10.9.2", 23 | "jasmine": "5.5.0", 24 | "npm-run-all2": "7.0.2", 25 | "prettier": "3.4.1" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /testing/webcompat/interventions/tests/test_1947105_pexels_com.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | URL = "https://www.pexels.com/photo/stylish-woman-relaxing-outdoors-in-autumn-fashion-29946756/" 4 | 5 | FREE_DOWNLOAD_BUTTON_CSS = ( 6 | "a[class*=Button][href*='dl=pexels-ekoagalarov-29946756.jpg']" 7 | ) 8 | POPUP_CSS = ".ReactModal__Content[class*=after-open]" 9 | 10 | 11 | async def is_popup_offscreen(client): 12 | await client.navigate(URL) 13 | client.soft_click(client.await_css(FREE_DOWNLOAD_BUTTON_CSS, is_displayed=True)) 14 | popup = client.await_css(POPUP_CSS, is_displayed=True) 15 | return client.execute_script( 16 | """ 17 | return arguments[0].getBoundingClientRect().top < 0; 18 | """, 19 | popup, 20 | ) 21 | 22 | 23 | @pytest.mark.asyncio 24 | @pytest.mark.with_interventions 25 | async def test_enabled(client): 26 | assert not await is_popup_offscreen(client) 27 | 28 | 29 | @pytest.mark.asyncio 30 | @pytest.mark.without_interventions 31 | async def test_disabled(client): 32 | assert await is_popup_offscreen(client) 33 | -------------------------------------------------------------------------------- /src/injections/js/bug1950282-formula1.com-platform-linux-fix.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1950282 - navigator.platform Windowss override for Formula 1 TV on Linux 9 | * 10 | * Formula1 TV is doing some kind of check for Android devices which is 11 | * causing it to treat Firefox on Linux as an Android device, and blocking it. 12 | * Overriding navigator.platform to Win64 on Linux works around this issue. 13 | */ 14 | 15 | /* globals exportFunction */ 16 | 17 | console.info( 18 | "navigator.platform has been overridden for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1950282 for details." 19 | ); 20 | 21 | const nav = Object.getPrototypeOf(navigator.wrappedJSObject); 22 | const platform = Object.getOwnPropertyDescriptor(nav, "platform"); 23 | platform.get = exportFunction(() => "Win64", window); 24 | Object.defineProperty(nav, "platform", platform); 25 | -------------------------------------------------------------------------------- /src/run.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* globals AboutCompatBroker, AVAILABLE_SHIMS, 8 | CUSTOM_FUNCTIONS, Interventions, Shims */ 9 | 10 | let interventions, shims; 11 | 12 | const AVAILABLE_INTERVENTIONS = 13 | #include data/interventions.json 14 | 15 | try { 16 | interventions = new Interventions(AVAILABLE_INTERVENTIONS, CUSTOM_FUNCTIONS); 17 | interventions.bootup(); 18 | } catch (e) { 19 | console.error("Interventions failed to start", e); 20 | interventions = undefined; 21 | } 22 | 23 | try { 24 | shims = new Shims(AVAILABLE_SHIMS); 25 | } catch (e) { 26 | console.error("Shims failed to start", e); 27 | shims = undefined; 28 | } 29 | 30 | try { 31 | const aboutCompatBroker = new AboutCompatBroker({ 32 | interventions, 33 | shims, 34 | }); 35 | aboutCompatBroker.bootup(); 36 | } catch (e) { 37 | console.error("about:compat broker failed to start", e); 38 | } 39 | -------------------------------------------------------------------------------- /src/injections/js/bug1448747-fastclick-shim.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1448747 - Neutralize FastClick 9 | * 10 | * The patch is applied on sites using FastClick library 11 | * to make sure `FastClick.notNeeded` returns `true`. 12 | * This allows to disable FastClick and fix various breakage caused 13 | * by the library (mainly non-functioning drop-down lists). 14 | */ 15 | 16 | /* globals exportFunction */ 17 | 18 | (function () { 19 | const proto = CSS2Properties.prototype.wrappedJSObject; 20 | const descriptor = Object.getOwnPropertyDescriptor(proto, "touchAction"); 21 | const { get } = descriptor; 22 | 23 | descriptor.get = exportFunction(function () { 24 | if (new Error().stack?.includes("notNeeded")) { 25 | return "none"; 26 | } 27 | return get.call(this); 28 | }, window); 29 | 30 | Object.defineProperty(proto, "touchAction", descriptor); 31 | })(); 32 | -------------------------------------------------------------------------------- /src/injections/css/bug1830752-afisha.ru-slider-pointer-events.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * afisha.ru - Slider not working 7 | * Bug #1830752 - https://bugzilla.mozilla.org/show_bug.cgi?id=1830752 8 | * WebCompat issue #120455 - https://github.com/webcompat/web-bugs/issues/120455 9 | * 10 | * The range slider for price filtering is not working because of pointer-events:none applied 11 | * on the slider element. It's working in Chrome because of webkit specific rules 12 | * set with -moz-range-thumb that override the pointer events on the slider thumb to auto. 13 | * Setting the same rule with -moz-range-thumb makes the slider to work. 14 | */ 15 | 16 | .XdRPG, 17 | .gkKBB { 18 | pointer-events: auto; 19 | } 20 | .XdRPG::-moz-range-thumb, 21 | .gkKBB::-moz-range-thumb { 22 | background-color: #ff3118; 23 | border-color: #ff3118; 24 | border-radius: 50%; 25 | cursor: pointer; 26 | pointer-events: auto; 27 | } 28 | -------------------------------------------------------------------------------- /src/injections/js/bug1815733-outlook365-clipboard-read-noop.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1815733 - Annoying "Paste" overlay when trying to paste 9 | * 10 | * As per https://bugzilla.mozilla.org/show_bug.cgi?id=1815733#c13, Outlook 11 | * is calling clipboard.read() again when they shouldn't. This is causing a 12 | * visible "Paste" prompt for the user, which is stealing focus and can be 13 | * annoying. 14 | */ 15 | 16 | /* globals exportFunction */ 17 | 18 | Object.defineProperty(navigator.clipboard.wrappedJSObject, "read", { 19 | configurable: true, 20 | value: exportFunction(function () { 21 | return new Promise((resolve, _) => { 22 | console.log( 23 | "clipboard.read() has been overwriten with a no-op. See https://bugzilla.mozilla.org/show_bug.cgi?id=1815733#c13 for details." 24 | ); 25 | 26 | resolve(); 27 | }); 28 | }, navigator.clipboard), 29 | }); 30 | -------------------------------------------------------------------------------- /src/injections/js/bug1945019-order.mealkeyway.com-prevent-unsupported-message.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /* globals exportFunction */ 6 | 7 | "use strict"; 8 | 9 | /** 10 | * www.menusifu.com - Shows an 'for a better experience, use Chrome' message. 11 | * Bug #1945019 - https://bugzilla.mozilla.org/show_bug.cgi?id=1945019 12 | * 13 | * We can automatically hide the message for users. 14 | */ 15 | 16 | console.info( 17 | "Web compatibility fixes are in effect. See https://bugzilla.mozilla.org/show_bug.cgi?id=1923286 for details." 18 | ); 19 | 20 | const timer = setInterval(() => { 21 | for (const node of document.querySelectorAll( 22 | "[class*=customMiniPrompt_customPromptContent]" 23 | )) { 24 | if (node.innerText.includes("Chrome")) { 25 | node.parentElement 26 | .querySelector("[class*=customMiniPrompt_iconAdd]") 27 | ?.click(); 28 | clearInterval(timer); 29 | } 30 | } 31 | }, 100); 32 | -------------------------------------------------------------------------------- /src/injections/js/bug1905069-one.geekie.com.br-chrome-shims.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1905069 - UA spoof for one.geekie.com.br 9 | * 10 | * This site is checking for window.chrome and navigator.vendor, so let's spoof those. 11 | */ 12 | 13 | /* globals exportFunction */ 14 | 15 | console.info( 16 | "window.chrome and navigator.vendor have been shimmed for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1905069 for details." 17 | ); 18 | 19 | Object.defineProperty(window.wrappedJSObject, "chrome", { 20 | get: exportFunction(function () { 21 | return true; 22 | }, window), 23 | 24 | set: exportFunction(function () {}, window), 25 | }); 26 | 27 | Object.defineProperty(window.navigator.wrappedJSObject, "vendor", { 28 | get: exportFunction(function () { 29 | return "Google Inc."; 30 | }, window), 31 | 32 | set: exportFunction(function () {}, window), 33 | }); 34 | -------------------------------------------------------------------------------- /src/injections/js/bug1579159-m.tailieu.vn-pdfjs-worker-disable.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * m.tailieu.vn - Override PDFJS.disableWorker to be true 9 | * WebCompat issue #39057 - https://webcompat.com/issues/39057 10 | * 11 | * Custom viewer built with PDF.js is not working in Firefox for Android 12 | * Disabling worker to match Chrome behavior fixes the issue 13 | */ 14 | 15 | /* globals exportFunction */ 16 | 17 | console.info( 18 | "window.PDFJS.disableWorker has been set to true for compatibility reasons. See https://webcompat.com/issues/39057 for details." 19 | ); 20 | 21 | let globals = {}; 22 | 23 | Object.defineProperty(window.wrappedJSObject, "PDFJS", { 24 | configurable: true, 25 | 26 | get: exportFunction(function () { 27 | return globals; 28 | }, window), 29 | 30 | set: exportFunction(function (value = {}) { 31 | globals = value; 32 | globals.disableWorker = true; 33 | }, window), 34 | }); 35 | -------------------------------------------------------------------------------- /src/shims/iaspet.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1713701 - Shim Integral Ad Science iaspet.js 9 | * 10 | * Some sites use iaspet to place content, often together with Google Publisher 11 | * Tags. This shim prevents breakage when the script is blocked. 12 | */ 13 | 14 | if (!window.__iasPET?.VERSION) { 15 | let queue = window?.__iasPET?.queue; 16 | if (!Array.isArray(queue)) { 17 | queue = []; 18 | } 19 | 20 | const response = JSON.stringify({ 21 | brandSafety: {}, 22 | slots: {}, 23 | }); 24 | 25 | function run(cmd) { 26 | try { 27 | cmd?.dataHandler?.(response); 28 | } catch (_) {} 29 | } 30 | 31 | queue.push = run; 32 | 33 | window.__iasPET = { 34 | VERSION: "1.16.18", 35 | queue, 36 | sessionId: "", 37 | setTargetingForAppNexus() {}, 38 | setTargetingForGPT() {}, 39 | start() {}, 40 | }; 41 | 42 | while (queue.length) { 43 | run(queue.shift()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/experiment-apis/testUtils.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* global ExtensionAPI, Services */ 8 | 9 | this.testUtils = class extends ExtensionAPI { 10 | getAPI() { 11 | return { 12 | testUtils: { 13 | async interventionsActive() { 14 | Services.ppmm.sharedData.set( 15 | "WebCompatTests:InterventionsStatus", 16 | "active" 17 | ); 18 | }, 19 | async interventionsInactive() { 20 | Services.ppmm.sharedData.set( 21 | "WebCompatTests:InterventionsStatus", 22 | "inactive" 23 | ); 24 | }, 25 | async shimsActive() { 26 | Services.ppmm.sharedData.set("WebCompatTests:ShimsStatus", "active"); 27 | }, 28 | async shimsInactive() { 29 | Services.ppmm.sharedData.set( 30 | "WebCompatTests:ShimsStatus", 31 | "inactive" 32 | ); 33 | }, 34 | }, 35 | }; 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /src/experiment-apis/testUtils.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "testUtils", 4 | "description": "experimental API extension to let tests know the addon's status", 5 | "functions": [ 6 | { 7 | "name": "interventionsActive", 8 | "type": "function", 9 | "description": "Mark for tests that the webcompat interventions are now active.", 10 | "parameters": [], 11 | "async": true 12 | }, 13 | { 14 | "name": "interventionsInactive", 15 | "type": "function", 16 | "description": "Mark for tests that the webcompat interventions are now inactive.", 17 | "parameters": [], 18 | "async": true 19 | }, 20 | { 21 | "name": "shimsActive", 22 | "type": "function", 23 | "description": "Mark for tests that the SmartBlock shims are now active.", 24 | "parameters": [], 25 | "async": true 26 | }, 27 | { 28 | "name": "shimsInactive", 29 | "type": "function", 30 | "description": "Mark for tests that the SmartBlock shims are now inactive.", 31 | "parameters": [], 32 | "async": true 33 | } 34 | ] 35 | } 36 | ] 37 | -------------------------------------------------------------------------------- /src/injections/js/bug1836157-thai-masszazs-niceScroll-disable.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * Bug 1836157 - Shim navigator.platform on www.thai-massaszs.net/en/ 7 | * 8 | * This page adds niceScroll on Android, which breaks scrolling and 9 | * zooming on Firefox. Adding ` Mac` to `navigator.platform` makes 10 | * the page avoid adding niceScroll entirely, unbreaking the page. 11 | */ 12 | 13 | /* globals exportFunction */ 14 | 15 | var plat = navigator.platform; 16 | if (!plat.includes("Mac")) { 17 | console.info( 18 | "The navigator.platform property has been shimmed to include 'Mac' for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1836157 for details." 19 | ); 20 | 21 | const newPlat = plat + " Mac"; 22 | const nav = Object.getPrototypeOf(navigator.wrappedJSObject); 23 | const platform = Object.getOwnPropertyDescriptor(nav, "platform"); 24 | platform.get = exportFunction(() => newPlat, window); 25 | Object.defineProperty(nav, "platform", platform); 26 | } 27 | -------------------------------------------------------------------------------- /src/shims/webtrends.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1766414 - Shim WebTrends Core Tag and Advanced Link Tracking 9 | * 10 | * Sites using WebTrends Core Tag or Link Tracking can break if they are 11 | * are blocked. This shim mitigates that breakage by loading an empty module. 12 | */ 13 | 14 | if (!window.dcsMultiTrack) { 15 | window.dcsMultiTrack = o => { 16 | o?.callback?.({}); 17 | }; 18 | } 19 | 20 | if (!window.WebTrends) { 21 | class dcs { 22 | addSelector() { 23 | return this; 24 | } 25 | addTransform() { 26 | return this; 27 | } 28 | DCSext = {}; 29 | init(_obj) { 30 | return this; 31 | } 32 | track() { 33 | return this; 34 | } 35 | } 36 | 37 | window.Webtrends = window.WebTrends = { 38 | dcs, 39 | multiTrack: window.dcsMultiTrack, 40 | }; 41 | 42 | window.requestAnimationFrame(() => { 43 | window.webtrendsAsyncLoad?.(dcs); 44 | window.webtrendsAsyncInit?.(); 45 | }); 46 | } 47 | -------------------------------------------------------------------------------- /src/about-compat/aboutPageProcessScript.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /* eslint-env mozilla/process-script */ 6 | 7 | "use strict"; 8 | 9 | // Note: This script is used only when a static registration for our 10 | // component is not already present in the libxul binary. 11 | 12 | const Cm = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); 13 | 14 | const classID = Components.ID("{97bf9550-2a7b-11e9-b56e-0800200c9a66}"); 15 | 16 | if (!Cm.isCIDRegistered(classID)) { 17 | const { ComponentUtils } = ChromeUtils.importESModule( 18 | "resource://gre/modules/ComponentUtils.sys.mjs" 19 | ); 20 | 21 | const factory = ComponentUtils.generateSingletonFactory(function () { 22 | const { AboutCompat } = ChromeUtils.importESModule( 23 | "resource://webcompat/AboutCompat.sys.mjs" 24 | ); 25 | return new AboutCompat(); 26 | }); 27 | 28 | Cm.registerFactory( 29 | classID, 30 | "about:compat", 31 | "@mozilla.org/network/protocol/about;1?what=compat", 32 | factory 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /src/shims/microsoftLogin.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | const SANDBOX_ATTR = "allow-storage-access-by-user-activation"; 6 | 7 | console.warn( 8 | "Firefox calls the Storage Access API on behalf of the site. See https://bugzilla.mozilla.org/show_bug.cgi?id=1638383 for details." 9 | ); 10 | 11 | // Watches for MS auth iframes and adds missing sandbox attribute. The attribute 12 | // is required so the third-party iframe can gain access to its first party 13 | // storage via the Storage Access API. 14 | function init() { 15 | const observer = new MutationObserver(() => { 16 | document.body 17 | .querySelectorAll( 18 | `iframe:is([id^='msalRenewFrame'], [src^="https://login.microsoftonline.com"])[sandbox]` 19 | ) 20 | .forEach(frame => { 21 | frame.sandbox.add(SANDBOX_ATTR); 22 | }); 23 | }); 24 | 25 | observer.observe(document.body, { 26 | attributes: true, 27 | subtree: false, 28 | childList: true, 29 | }); 30 | } 31 | window.addEventListener("DOMContentLoaded", init); 32 | -------------------------------------------------------------------------------- /src/injections/css/bug1886293-futurePLC-sites-trending_scrollbars.css: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /** 6 | * Sites maintained by Future PLC 7 | * Bug #1886285 - https://bugzilla.mozilla.org/show_bug.cgi?id=1886285 8 | * - androidcentral.com 9 | * - creativebloq.com 10 | * - cyclingnews.com 11 | * - gamesradar.com 12 | * - imore.com 13 | * - itpro.com 14 | * - laptopmag.com 15 | * - livescience.com 16 | * - loudersound.com 17 | * - musicradar.com 18 | * - pcgamer.com 19 | * - space.com 20 | * - techradar.com 21 | * - tomshardware.com 22 | * - windowscentral.com 23 | * 24 | * They are using ::webkit-scrollbar to style their "trending" lists, 25 | * which results in the wrong colors being applied and sometimes for the 26 | * bottom of the text in the list being covered by the scrollbar. Adding 27 | * the standard CSS equivalents fixes this. 28 | */ 29 | 30 | .trending__list { 31 | scrollbar-width: thin; 32 | scrollbar-color: var(--trending-scrollbar-color) 33 | var(--trending-scrollbar-background-color); 34 | } 35 | -------------------------------------------------------------------------------- /src/injections/js/bug1452707-window.controllers-shim-ib.absa.co.za.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1452707 - Build site patch for ib.absa.co.za 9 | * WebCompat issue #16401 - https://webcompat.com/issues/16401 10 | * 11 | * The online banking at ib.absa.co.za detect if window.controllers is a 12 | * non-falsy value to detect if the current browser is Firefox or something 13 | * else. In bug 1448045, this shim has been disabled for Firefox Nightly 61+, 14 | * which breaks the UA detection on this site and results in a "Browser 15 | * unsuppored" error message. 16 | * 17 | * This site patch simply sets window.controllers to a string, resulting in 18 | * their check to work again. 19 | */ 20 | 21 | /* globals exportFunction */ 22 | 23 | console.info( 24 | "window.controllers has been shimmed for compatibility reasons. See https://webcompat.com/issues/16401 for details." 25 | ); 26 | 27 | Object.getPrototypeOf(window).wrappedJSObject.controllers = exportFunction( 28 | () => true, 29 | window 30 | ); 31 | -------------------------------------------------------------------------------- /src/lib/requestStorageAccess_helper.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /* globals browser */ 6 | 7 | // Helper for calling the internal requestStorageAccessForOrigin method. The 8 | // method is called on the first-party document for the third-party which needs 9 | // first-party storage access. 10 | browser.runtime.onMessage.addListener(request => { 11 | let { requestStorageAccessOrigin, warning } = request; 12 | if (!requestStorageAccessOrigin) { 13 | return false; 14 | } 15 | 16 | // Log a warning to the web console, informing about the shim. 17 | console.warn(warning); 18 | 19 | // Call the internal storage access API. Passing false means we don't require 20 | // user activation, but will always show the storage access prompt. The user 21 | // has to explicitly allow storage access. 22 | return document 23 | .requestStorageAccessForOrigin(requestStorageAccessOrigin, false) 24 | .then(() => { 25 | return { success: true }; 26 | }) 27 | .catch(() => { 28 | return { success: false }; 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /src/injections/js/bug1899937-plus.nhk.jp-request-picture-in-picture.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1899937 - Shim requestPictureInPicture for plus.nhk.jp 9 | * WebCompat issue #103463 - https://webcompat.com/issues/103463 10 | * 11 | * plus.nhk.jp is showing an error when attempting to play videos. 12 | * Shimming requestPictureInPicture to `{}` makes the videos play. 13 | */ 14 | 15 | /* globals exportFunction, cloneInto */ 16 | 17 | console.info( 18 | "PictureInPicture APIs are being shimmed for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1899937 for details." 19 | ); 20 | 21 | const win = window.wrappedJSObject; 22 | 23 | const proto = win.HTMLVideoElement.prototype; 24 | const promise = win.Promise.resolve(); 25 | proto.requestPictureInPicture = exportFunction(() => promise, window); 26 | 27 | win.Document.prototype.pictureInPictureElement = null; 28 | win.PictureInPictureWindow = exportFunction(class {}, window); 29 | win.PictureInPictureEvent = exportFunction(class {}, window); 30 | -------------------------------------------------------------------------------- /spec/available_shims.spec.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | const WebExtManifestSchmea = require("./helpers/webext_manifest_schema"); 8 | 9 | const AVAILABLE_SHIMS = require("../src/data/shims.js"); 10 | 11 | describe("AVAILABLE_SHIMS", () => { 12 | it("contains at least one Shim definition", () => { 13 | expect(AVAILABLE_SHIMS.length).toBeGreaterThanOrEqual(1); 14 | }); 15 | }); 16 | 17 | for (const shim of AVAILABLE_SHIMS) { 18 | describe(`shim #${shim.id}`, () => { 19 | it("provides an ID", () => { 20 | expect(shim.id).toBeTruthy(); 21 | }); 22 | 23 | it("provides a valid platform", () => { 24 | expect( 25 | ["all", "desktop", "android", "never matches"].includes(shim.platform) 26 | ).toBeTruthy(); 27 | }); 28 | 29 | it("provides a bug ID", () => { 30 | expect(shim.bug).toBeTruthy(); 31 | }); 32 | 33 | it("provides valid URLs", () => { 34 | expect( 35 | WebExtManifestSchmea.matchPatternsValid(shim.matches) 36 | ).toBeTruthy(); 37 | }); 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /src/injections/js/bug1898946-transcrib.io-chrome-shim.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1898946 - UA spoof for transcrib.io 9 | * 10 | * This checks navigator.userAgent and navigator.vendor to detect Chrome, 11 | * so let's set appropriate values to also look like Chrome. 12 | */ 13 | 14 | /* globals exportFunction */ 15 | 16 | console.info( 17 | "The user agent and navigator.vendor have been shimmed for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1898946 for details." 18 | ); 19 | 20 | const CHROME_UA = navigator.userAgent + " Chrome for WebCompat"; 21 | 22 | Object.defineProperty(window.navigator.wrappedJSObject, "userAgent", { 23 | get: exportFunction(function () { 24 | return CHROME_UA; 25 | }, window), 26 | 27 | set: exportFunction(function () {}, window), 28 | }); 29 | 30 | Object.defineProperty(window.navigator.wrappedJSObject, "vendor", { 31 | get: exportFunction(function () { 32 | return "Google Inc."; 33 | }, window), 34 | 35 | set: exportFunction(function () {}, window), 36 | }); 37 | -------------------------------------------------------------------------------- /src/injections/js/bug1799968-www.samsung.com-appVersion-linux-fix.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1799968 - Build site patch for www.samsung.com on Linux 9 | * Bug 1860417 - and Android 10 | * WebCompat issue #108993 - https://webcompat.com/issues/108993 11 | * 12 | * Samsung's Watch pages try to detect the OS via navigator.appVersion, 13 | * but fail with Linux and Android because they expect it to contain the 14 | * literal string "linux", and their JS breaks. 15 | * 16 | * As such this site patch sets appVersion to "5.0 (Linux)", and is 17 | * only meant to be applied on Linux or Android. 18 | */ 19 | 20 | /* globals exportFunction */ 21 | 22 | console.info( 23 | "navigator.appVersion has been shimmed for compatibility reasons. See https://webcompat.com/issues/108993 for details." 24 | ); 25 | 26 | const nav = Object.getPrototypeOf(navigator.wrappedJSObject); 27 | const appVersion = Object.getOwnPropertyDescriptor(nav, "appVersion"); 28 | appVersion.get = exportFunction(() => "5.0 (Linux)", window); 29 | Object.defineProperty(nav, "appVersion", appVersion); 30 | -------------------------------------------------------------------------------- /src/injections/js/bug1950301-shamir.com-ua-overrides.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1950301 - UA spoofs for shamir.com 9 | * 10 | * Something about the site's Rocket loader code breaks when the useragent is Firefox and 11 | * there is no navigator.vendor set. We can spoof these values to bypass the breakage. 12 | */ 13 | 14 | /* globals exportFunction */ 15 | 16 | console.info( 17 | "navigator.userAgent and navigator.vendor have been shimmed for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1950301 for details." 18 | ); 19 | 20 | const UA = navigator.userAgent.replace("Firefox", "FireFox"); 21 | 22 | Object.defineProperty(window.navigator.wrappedJSObject, "userAgent", { 23 | get: exportFunction(function () { 24 | return UA; 25 | }, window), 26 | 27 | set: exportFunction(function () {}, window), 28 | }); 29 | 30 | Object.defineProperty(window.navigator.wrappedJSObject, "vendor", { 31 | get: exportFunction(function () { 32 | return "Mozilla"; 33 | }, window), 34 | 35 | set: exportFunction(function () {}, window), 36 | }); 37 | -------------------------------------------------------------------------------- /src/injections/js/bug1457335-histography.io-ua-change.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1457335 - histography.io - Override UA & navigator.vendor 9 | * WebCompat issue #1804 - https://webcompat.com/issues/1804 10 | * 11 | * This site is using a strict matching of navigator.userAgent and 12 | * navigator.vendor to allow access for Safari or Chrome. Here, we set the 13 | * values appropriately so we get recognized as Chrome. 14 | */ 15 | 16 | /* globals exportFunction */ 17 | 18 | console.info( 19 | "The user agent has been overridden for compatibility reasons. See https://webcompat.com/issues/1804 for details." 20 | ); 21 | 22 | const CHROME_UA = navigator.userAgent + " Chrome for WebCompat"; 23 | 24 | const nav = Object.getPrototypeOf(navigator.wrappedJSObject); 25 | 26 | const ua = Object.getOwnPropertyDescriptor(nav, "userAgent"); 27 | ua.get = exportFunction(() => CHROME_UA, window); 28 | Object.defineProperty(nav, "userAgent", ua); 29 | 30 | const vendor = Object.getOwnPropertyDescriptor(nav, "vendor"); 31 | vendor.get = exportFunction(() => "Google Inc.", window); 32 | Object.defineProperty(nav, "vendor", vendor); 33 | -------------------------------------------------------------------------------- /src/injections/js/bug1889326-office365-email-handling-prompt-autohide.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1889326 - Office 365 email handling prompt autohide 9 | * 10 | * This site patch prevents the notification bar on Office 365 11 | * apps from popping up on each page-load, offering to handle 12 | * email with Outlook. 13 | */ 14 | 15 | /* globals exportFunction */ 16 | 17 | const warning = 18 | "Office 365 Outlook email handling prompt has been hidden. See https://bugzilla.mozilla.org/show_bug.cgi?id=1889326 for details."; 19 | 20 | const localStorageKey = "mailProtocolHandlerAlreadyOffered"; 21 | 22 | const proto = Object.getPrototypeOf(navigator).wrappedJSObject; 23 | const { registerProtocolHandler } = proto; 24 | const { localStorage } = window.wrappedJSObject; 25 | 26 | proto.registerProtocolHandler = exportFunction(function (scheme, url, title) { 27 | if (localStorage.getItem(localStorageKey)) { 28 | console.info(warning); 29 | return undefined; 30 | } 31 | registerProtocolHandler.call(this, scheme, url, title); 32 | localStorage.setItem(localStorageKey, true); 33 | return undefined; 34 | }, window); 35 | -------------------------------------------------------------------------------- /src/about-compat/AboutCompat.sys.mjs: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | const addonID = "webcompat@mozilla.org"; 6 | const addonPageRelativeURL = "/about-compat/aboutCompat.html"; 7 | 8 | export function AboutCompat() { 9 | this.chromeURL = 10 | WebExtensionPolicy.getByID(addonID).getURL(addonPageRelativeURL); 11 | } 12 | 13 | AboutCompat.prototype = { 14 | QueryInterface: ChromeUtils.generateQI(["nsIAboutModule"]), 15 | getURIFlags() { 16 | return ( 17 | Ci.nsIAboutModule.URI_MUST_LOAD_IN_EXTENSION_PROCESS | 18 | Ci.nsIAboutModule.IS_SECURE_CHROME_UI 19 | ); 20 | }, 21 | 22 | newChannel(aURI, aLoadInfo) { 23 | const uri = Services.io.newURI(this.chromeURL); 24 | const channel = Services.io.newChannelFromURIWithLoadInfo(uri, aLoadInfo); 25 | channel.originalURI = aURI; 26 | 27 | channel.owner = ( 28 | Services.scriptSecurityManager.createContentPrincipal || 29 | // Handles fallback to earlier versions. 30 | // eslint-disable-next-line mozilla/valid-services-property 31 | Services.scriptSecurityManager.createCodebasePrincipal 32 | )(uri, aLoadInfo.originAttributes); 33 | return channel; 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /src/about-compat/aboutPage.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* global ExtensionAPI, XPCOMUtils, Services */ 8 | 9 | XPCOMUtils.defineLazyServiceGetter( 10 | this, 11 | "resProto", 12 | "@mozilla.org/network/protocol;1?name=resource", 13 | "nsISubstitutingProtocolHandler" 14 | ); 15 | 16 | const ResourceSubstitution = "webcompat"; 17 | const ProcessScriptURL = "resource://webcompat/aboutPageProcessScript.js"; 18 | const ContractID = "@mozilla.org/network/protocol/about;1?what=compat"; 19 | 20 | this.aboutPage = class extends ExtensionAPI { 21 | onStartup() { 22 | const { rootURI } = this.extension; 23 | 24 | resProto.setSubstitution( 25 | ResourceSubstitution, 26 | Services.io.newURI("about-compat/", null, rootURI) 27 | ); 28 | 29 | if (!(ContractID in Cc)) { 30 | Services.ppmm.loadProcessScript(ProcessScriptURL, true); 31 | this.processScriptRegistered = true; 32 | } 33 | } 34 | 35 | onShutdown() { 36 | resProto.setSubstitution(ResourceSubstitution, null); 37 | 38 | if (this.processScriptRegistered) { 39 | Services.ppmm.removeDelayedProcessScript(ProcessScriptURL); 40 | } 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /src/experiment-apis/appConstants.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* global AppConstants, ExtensionAPI, XPCOMUtils */ 8 | 9 | this.appConstants = class extends ExtensionAPI { 10 | getAPI() { 11 | return { 12 | appConstants: { 13 | getEffectiveUpdateChannel: () => { 14 | const ver = AppConstants.MOZ_APP_VERSION_DISPLAY; 15 | if (ver.includes("a")) { 16 | return "nightly"; 17 | } else if (ver.includes("b")) { 18 | return "beta"; 19 | } else if (ver.includes("esr")) { 20 | return "esr"; 21 | } 22 | return "stable"; 23 | }, 24 | getReleaseBranch: () => { 25 | if (AppConstants.NIGHTLY_BUILD) { 26 | return "nightly"; 27 | } else if (AppConstants.MOZ_DEV_EDITION) { 28 | return "dev_edition"; 29 | } else if (AppConstants.EARLY_BETA_OR_EARLIER) { 30 | return "early_beta_or_earlier"; 31 | } else if (AppConstants.RELEASE_OR_BETA) { 32 | return "release_or_beta"; 33 | } 34 | return "unknown"; 35 | }, 36 | }, 37 | }; 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /src/injections/js/bug1901780-disable-legacy-mutation-events.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bugs 1901780 - Disable legacy DOM Mutation Events to prevent performance issues. 9 | */ 10 | 11 | /* globals exportFunction */ 12 | 13 | console.info( 14 | "DOM Mutation Events have been disabled to prevent performance issues. See https://bugzilla.mozilla.org/show_bug.cgi?id=1901780 for details." 15 | ); 16 | 17 | (function disableMutationEvents() { 18 | const whichEvents = [ 19 | "domattrmodified", 20 | "domcharacterdatamodified", 21 | "domnodeinserted", 22 | "domnodeinsertedintodocument", 23 | "domnoderemoved", 24 | "domnoderemovedfromdocument", 25 | "domsubtreemodified", 26 | ]; 27 | 28 | const { prototype } = window.wrappedJSObject.EventTarget; 29 | const { addEventListener } = prototype; 30 | Object.defineProperty(prototype, "addEventListener", { 31 | value: exportFunction(function (_type, b, c, d) { 32 | const type = _type?.toLowerCase(); 33 | if (whichEvents.includes(type)) { 34 | return undefined; 35 | } 36 | return addEventListener.call(this, type, b, c, d); 37 | }, window), 38 | }); 39 | })(); 40 | -------------------------------------------------------------------------------- /src/injections/js/bug1943898-www.capital.gr-suppress-constant-reloading.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * www.capital.gr - Reloading the page results in endless reloading loops. 9 | * Bug #1943898 - https://bugzilla.mozilla.org/show_bug.cgi?id=1943898 10 | * WebCompat issue #74073 - https://webcompat.com/issues/74073 11 | * 12 | * The site does not anticipate Firefox's form-filling behavior on page 13 | * reloads, which causes it to accidentally trigger endless reload loops. 14 | * We fix this by clearing the form element as they check it the first time. 15 | */ 16 | 17 | /* globals exportFunction */ 18 | 19 | console.info( 20 | "setTimeout has been overridden for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1943898 for details." 21 | ); 22 | 23 | window.wrappedJSObject.setTimeout = exportFunction(function (fn, time) { 24 | const text = "" + fn; 25 | if ( 26 | text.includes("var el = document.getElementById('alwaysFetch');") && 27 | text.includes("el.value = el.value ? location.reload() : true;") 28 | ) { 29 | document.getElementById("alwaysFetch").value = ""; 30 | } 31 | return window.setTimeout(fn, time); 32 | }, window); 33 | -------------------------------------------------------------------------------- /src/injections/js/bug1739489-draftjs-beforeinput.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1739489 - Entering an emoji using the MacOS IME "crashes" Draft.js editors. 9 | */ 10 | 11 | /* globals exportFunction */ 12 | 13 | console.info( 14 | "textInput event has been remapped to beforeinput for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1739489 for details." 15 | ); 16 | 17 | window.wrappedJSObject.TextEvent = window.wrappedJSObject.InputEvent; 18 | 19 | const { CustomEvent, Event, EventTarget } = window.wrappedJSObject; 20 | var Remapped = [ 21 | [CustomEvent, "constructor"], 22 | [Event, "constructor"], 23 | [Event, "initEvent"], 24 | [EventTarget, "addEventListener"], 25 | [EventTarget, "removeEventListener"], 26 | ]; 27 | 28 | for (const [obj, name] of Remapped) { 29 | const { prototype } = obj; 30 | const orig = prototype[name]; 31 | Object.defineProperty(prototype, name, { 32 | configurable: true, 33 | value: exportFunction(function (type, b, c, d) { 34 | if (type?.toLowerCase() === "textinput") { 35 | type = "beforeinput"; 36 | } 37 | return orig.call(this, type, b, c, d); 38 | }, window), 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /src/lib/messaging_helper.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* globals browser */ 8 | 9 | // By default, only the first handler for browser.runtime.onMessage which 10 | // returns a value will get to return one. As such, we need to let them all 11 | // receive the message, and all have a chance to return a response (with the 12 | // first non-undefined result being the one that is ultimately returned). 13 | // This way, about:compat and the shims library can both get a chance to 14 | // process a message, and just return undefined if they wish to ignore it. 15 | 16 | const onMessageFromTab = (function () { 17 | const handlers = new Set(); 18 | 19 | browser.runtime.onMessage.addListener((msg, sender) => { 20 | const promises = [...handlers.values()].map(fn => fn(msg, sender)); 21 | return Promise.allSettled(promises).then(results => { 22 | for (const { reason, value } of results) { 23 | if (reason) { 24 | console.error(reason); 25 | } else if (value !== undefined) { 26 | return value; 27 | } 28 | } 29 | return undefined; 30 | }); 31 | }); 32 | 33 | return function (handler) { 34 | handlers.add(handler); 35 | }; 36 | })(); 37 | -------------------------------------------------------------------------------- /src/injections/js/bug1842437-www.youtube.com-performance-now-precision.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1842437 - When attempting to go back on youtube.com, the content remains the same 9 | * 10 | * If consecutive session history entries had history.state.entryTime set to same value, 11 | * back button doesn't work as expected. The entryTime value is coming from performance.now() 12 | * and modifying its return value slightly to make sure two close consecutive calls don't 13 | * get the same result helped with resolving the issue. 14 | */ 15 | 16 | /* globals exportFunction */ 17 | 18 | console.info( 19 | "performance.now precision has been modified for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1756970 for details." 20 | ); 21 | 22 | let counter = 0; 23 | let previousVal = 0; 24 | 25 | const perf = Object.getPrototypeOf(performance.wrappedJSObject); 26 | const now = perf.now; 27 | perf.now = exportFunction(function () { 28 | let originalVal = now.call(this); 29 | if (originalVal === previousVal) { 30 | originalVal += 0.00000003 * ++counter; 31 | } else { 32 | previousVal = originalVal; 33 | counter = 0; 34 | } 35 | return originalVal; 36 | }, window); 37 | -------------------------------------------------------------------------------- /src/injections/js/bug1769762-tiktok.com-plugins-shim.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1769762 - Empty out navigator.plugins 9 | * WebCompat issue #103612 - https://webcompat.com/issues/103612 10 | * 11 | * Certain features of the site are breaking if navigator.plugins array is not empty: 12 | * 13 | * 1. "Likes" on the comments are not saved 14 | * 2. Can't reply to other people's comments 15 | * 3. "Likes" on the videos are not saved 16 | * 4. Can't follow an account (after refreshing "Follow" button is visible again) 17 | * 18 | * (note that the first 2 are still broken if you open devtools even with this intervention) 19 | */ 20 | 21 | /* globals exportFunction */ 22 | 23 | console.info( 24 | "The PluginArray has been overridden for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1753874 for details." 25 | ); 26 | 27 | const pluginsArray = new window.wrappedJSObject.Array(); 28 | Object.setPrototypeOf(pluginsArray, PluginArray.prototype); 29 | const navProto = Object.getPrototypeOf(navigator.wrappedJSObject); 30 | const pluginsDesc = Object.getOwnPropertyDescriptor(navProto, "plugins"); 31 | pluginsDesc.get = exportFunction(() => pluginsArray, window); 32 | Object.defineProperty(navProto, "plugins", pluginsDesc); 33 | -------------------------------------------------------------------------------- /src/injections/js/bug1944725-homedepot.com-innerWidth-fix.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1944725 - window.innerWidth/Height fix 9 | * 10 | * A white bar appears on the left of the screen at small window sizes, due to 11 | * window.innerWidth/Height providing different values than the site expects. 12 | */ 13 | 14 | /* globals exportFunction */ 15 | 16 | console.info( 17 | "window.innerWidth and window.innerHeight have been shimmed for compatibility reasons. https://bugzilla.mozilla.org/show_bug.cgi?id=1944725 for details." 18 | ); 19 | 20 | const div = document.createElement("div"); 21 | div.inert = true; 22 | div.style = 23 | "position:fixed; top:0; left:0; right:0; bottom:0; opacity:0; z-index:-1"; 24 | document.documentElement.appendChild(div); 25 | 26 | const win = window.wrappedJSObject; 27 | 28 | const iw = Object.getOwnPropertyDescriptor(win, "innerWidth"); 29 | iw.get = exportFunction(() => div.getBoundingClientRect().width, window); 30 | Object.defineProperty(win, "innerWidth", iw); 31 | 32 | const ih = Object.getOwnPropertyDescriptor(win, "innerHeight"); 33 | ih.get = exportFunction(() => div.getBoundingClientRect().height, window); 34 | Object.defineProperty(win, "innerHeight", ih); 35 | 36 | window.wrappedJSObject.chrome = new window.wrappedJSObject.Object(); 37 | -------------------------------------------------------------------------------- /src/shims/moat.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1713704 - Shim Moat ad tracker 9 | * 10 | * Sites such as Forbes may gate content behind Moat ads, resulting in 11 | * breakage like black boxes where videos should be placed. This shim 12 | * helps mitigate that breakage by allowing the placement to succeed. 13 | */ 14 | 15 | if (!window.moatPrebidAPI?.__A) { 16 | const targeting = new Map(); 17 | 18 | const slotConfig = { 19 | m_categories: ["moat_safe"], 20 | m_data: "0", 21 | m_safety: "safe", 22 | }; 23 | 24 | window.moatPrebidApi = { 25 | __A() {}, 26 | disableLogging() {}, 27 | enableLogging() {}, 28 | getMoatTargetingForPage: () => slotConfig, 29 | getMoatTargetingForSlot(slot) { 30 | return targeting.get(slot?.getSlotElementId()); 31 | }, 32 | pageDataAvailable: () => true, 33 | safetyDataAvailable: () => true, 34 | setMoatTargetingForAllSlots() { 35 | for (const slot of window.googletag.pubads().getSlots() || []) { 36 | targeting.set(slot.getSlotElementId(), slot.getTargeting()); 37 | } 38 | }, 39 | setMoatTargetingForSlot(slot) { 40 | targeting.set(slot?.getSlotElementId(), slotConfig); 41 | }, 42 | slotDataAvailable() { 43 | return window.googletag?.pubads().getSlots().length > 0; 44 | }, 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /src/injections/js/bug1799980-healow.com-infinite-loop-fix.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1799980 - Healow gets stuck in an infinite loop while pages load 9 | * 10 | * This patch keeps Healow's localization scripts from getting stuck in 11 | * an infinite loop while their pages are loading. 12 | * 13 | * This happens because they use synchronous XMLHttpRequests to fetch a 14 | * JSON file with their localized text on the first call to their i18n 15 | * function, and then force subsequent calls to wait for it by waiting 16 | * in an infinite loop. 17 | * 18 | * But since they're in an infinite loop, the code after the syncXHR will 19 | * never be able to run, so this ultimately triggers a slow script warning. 20 | * 21 | * We can improve this by just preventing the infinite loop from happening, 22 | * though since they disable caching on their JSON files it means that more 23 | * XHRs may happen. But since those files are small, this seems like a 24 | * reasonable compromise until they migrate to a better i18n solution. 25 | * 26 | * See https://bugzilla.mozilla.org/show_bug.cgi?id=1799980 for details. 27 | */ 28 | 29 | /* globals exportFunction */ 30 | 31 | Object.defineProperty(window.wrappedJSObject, "ajaxRequestProcessing", { 32 | get: exportFunction(function () { 33 | return false; 34 | }, window), 35 | 36 | set: exportFunction(function () {}, window), 37 | }); 38 | -------------------------------------------------------------------------------- /src/injections/js/bug1930440-online.singaporepools.com-prevent-unsupported-alert.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /* globals exportFunction */ 6 | 7 | "use strict"; 8 | 9 | /** 10 | * online.singaporepools.com - Shows an 'unsupported browser' alert 11 | * Bug #1930440 - https://bugzilla.mozilla.org/show_bug.cgi?id=1930440 12 | * WebCompat issue #143685 - https://webcompat.com/issues/143685 13 | * 14 | * We can intercept the call to alert and hide it, as well as hide the 15 | * additional in-page support message that they show to all browsers. 16 | */ 17 | 18 | console.info( 19 | "window.alert is being overriden for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1923286 for details." 20 | ); 21 | 22 | new MutationObserver(mutations => { 23 | for (let { addedNodes } of mutations) { 24 | for (const node of addedNodes) { 25 | try { 26 | if ( 27 | node.matches(".alert.views-row") && 28 | node.innerText.includes("Chrome") 29 | ) { 30 | node.remove(); 31 | } 32 | } catch (_) {} 33 | } 34 | } 35 | }).observe(document.documentElement, { 36 | childList: true, 37 | subtree: true, 38 | }); 39 | 40 | const originalAlert = window.wrappedJSObject.alert; 41 | window.wrappedJSObject.alert = exportFunction(function (msg) { 42 | if (!msg?.toLowerCase?.().includes("unsupported browser")) { 43 | originalAlert(msg); 44 | } 45 | }, window); 46 | -------------------------------------------------------------------------------- /src/injections/js/bug1939248-rosasthai.com-load-event-helper.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1939248 - Load event listener issue on rosasthai.com 9 | * WebCompat issue #145642 - https://webcompat.com/issues/145642 10 | * 11 | * The site assumes that its code will run before the window load event, and 12 | * so their buttons will not function properly if that is untrue. We can call 13 | * those event listeners immediately as they try to add them, if the document 14 | * readyState is already "complete", which fixes this bug. 15 | */ 16 | 17 | /* globals exportFunction */ 18 | 19 | console.info( 20 | "running late window load listeners for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1939248 for details." 21 | ); 22 | 23 | (function runLateWindowLoadEventListenersImmediately() { 24 | const { prototype } = window.wrappedJSObject.EventTarget; 25 | const { addEventListener } = prototype; 26 | prototype.addEventListener = exportFunction(function (type, b, c, d) { 27 | if ( 28 | this !== window || 29 | document?.readyState !== "complete" || 30 | type?.toLowerCase() !== "load" 31 | ) { 32 | return addEventListener.call(this, type, b, c, d); 33 | } 34 | console.log("window.addEventListener(load) called too late, so calling", b); 35 | try { 36 | b?.call(); 37 | } catch (e) { 38 | console.error(e); 39 | } 40 | return undefined; 41 | }, window); 42 | })(); 43 | -------------------------------------------------------------------------------- /src/shims/microsoftVirtualAssistant.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1801277 - Shim Microsoft virtual assistant. 9 | * 10 | * The microsoft virtual assistant will break when accessing the indexedDB that 11 | * will throw a security error because the virtual assistant is under a 12 | * third-party tracking domain 'liveperson.net'. The shim replaces the indexedDB 13 | * with a fake interface that won't throw an error. 14 | */ 15 | 16 | /* globals cloneInto */ 17 | 18 | (function () { 19 | const win = window.wrappedJSObject; 20 | 21 | try { 22 | // We only replace the indexedDB when liveperson.net is loaded in a 23 | // third-party context. Note that this is not strictly correct because 24 | // this is a cross-origin check but not a third-party check. 25 | if (win.parent == win || win.location.origin == win.top.location.origin) { 26 | return; 27 | } 28 | } catch (e) { 29 | // If we get a security error when accessing the top-level origin, this 30 | // shows that the window is in a cross-origin context. In this case, we can 31 | // proceed to apply the shim. 32 | if (e.name != "SecurityError") { 33 | throw e; 34 | } 35 | } 36 | 37 | const emptyMsg = cloneInto({ message: "" }, window); 38 | 39 | const idb = { 40 | open: () => win.Promise.reject(emptyMsg), 41 | }; 42 | 43 | Object.defineProperty(win, "indexedDB", { 44 | value: cloneInto(idb, window, { cloneFunctions: true }), 45 | }); 46 | })(); 47 | -------------------------------------------------------------------------------- /src/shims/salesforce.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1855139 - The pop-up for "Où trouver ma référence ?" option is blank at 9 | * garantie30minutes.sncf.com with ETP set to STANDARD 10 | * 11 | * emeraude.my.salesforce.com is marked as a tracker, and it tries to access localstorage, but the 12 | * script returned does not handle the error. The shim replaces localstorage with a fake 13 | * interface to avoid the error. 14 | * 15 | */ 16 | 17 | /* globals cloneInto */ 18 | 19 | (function () { 20 | const win = window.wrappedJSObject; 21 | 22 | try { 23 | // We only replace the indexedDB when emeraude.my.salesforce.com is loaded in a 24 | // third-party context. Note that this is not strictly correct because 25 | // this is a cross-origin check but not a third-party check. 26 | if (win.parent == win || win.location.origin == win.top.location.origin) { 27 | return; 28 | } 29 | } catch (e) { 30 | // If we get a security error when accessing the top-level origin, this 31 | // shows that the window is in a cross-origin context. In this case, we can 32 | // proceed to apply the shim. 33 | if (e.name != "SecurityError") { 34 | throw e; 35 | } 36 | } 37 | 38 | const emptyMsg = cloneInto({ message: "" }, window); 39 | 40 | const idb = { 41 | open: () => win.Promise.reject(emptyMsg), 42 | }; 43 | 44 | Object.defineProperty(win, "indexedDB", { 45 | value: cloneInto(idb, window, { cloneFunctions: true }), 46 | }); 47 | })(); 48 | -------------------------------------------------------------------------------- /src/injections/js/bug1928216-voice.google.com-permissions.query.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1928216 - Google Voice doesn't list microphones in Firefox 132 9 | * 10 | * As per https://bugzilla.mozilla.org/show_bug.cgi?id=1928216#c9, Google Voice 11 | * is not handling permissions.query() working for camera and microphone correctly, 12 | * so emulate an earlier version that rejects for those. 13 | */ 14 | 15 | /* globals exportFunction, cloneInto */ 16 | 17 | (() => { 18 | const nativeQuery = navigator.permissions.wrappedJSObject.query.bind( 19 | navigator.permissions.wrappedJSObject 20 | ); 21 | 22 | Object.getPrototypeOf(navigator.permissions).wrappedJSObject.query = 23 | exportFunction(function query(descriptor) { 24 | if (typeof descriptor == "object") { 25 | switch (descriptor.name) { 26 | case "camera": 27 | case "microphone": { 28 | console.log( 29 | "permissions.query() has been overwriten to not work with camera and microphone. See https://bugzilla.mozilla.org/show_bug.cgi?id=1928216#c9" 30 | ); 31 | const err = new TypeError( 32 | `'${descriptor.name}' (value of 'name' member of PermissionDescriptor) is not a valid value for enumeration PermissionName.` 33 | ); 34 | return window.Promise.reject(cloneInto(err, window)); 35 | } 36 | } 37 | } 38 | return nativeQuery(descriptor); 39 | }, navigator.permissions); 40 | })(); 41 | -------------------------------------------------------------------------------- /src/about-compat/aboutCompat.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 28 | 29 | 30 | 31 | 32 |

33 |

34 | 35 | 36 | 37 | 38 |
39 |

40 | 41 | 42 | 43 | 44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /src/injections/js/bug1472075-bankofamerica.com-ua-change.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1472075 - Build UA override for Bank of America for OSX & Linux 9 | * WebCompat issue #2787 - https://webcompat.com/issues/2787 10 | * 11 | * BoA is showing a red warning to Linux and macOS users, while accepting 12 | * Windows users without warning. From our side, there is no difference here 13 | * and we receive a lot of user complains about the warnings, so we spoof 14 | * as Firefox on Windows in those cases. 15 | */ 16 | 17 | /* globals exportFunction */ 18 | 19 | if (!navigator.platform.includes("Win")) { 20 | console.info( 21 | "The user agent has been overridden for compatibility reasons. See https://webcompat.com/issues/2787 for details." 22 | ); 23 | 24 | const WINDOWS_UA = navigator.userAgent.replace( 25 | /\(.*; rv:/i, 26 | "(Windows NT 10.0; Win64; x64; rv:" 27 | ); 28 | 29 | const nav = Object.getPrototypeOf(navigator.wrappedJSObject); 30 | 31 | const ua = Object.getOwnPropertyDescriptor(nav, "userAgent"); 32 | ua.get = exportFunction(() => WINDOWS_UA, window); 33 | Object.defineProperty(nav, "userAgent", ua); 34 | 35 | const appVersion = Object.getOwnPropertyDescriptor(nav, "appVersion"); 36 | appVersion.get = exportFunction(() => "appVersion", window); 37 | Object.defineProperty(nav, "appVersion", appVersion); 38 | 39 | const platform = Object.getOwnPropertyDescriptor(nav, "platform"); 40 | platform.get = exportFunction(() => "Win64", window); 41 | Object.defineProperty(nav, "platform", platform); 42 | } 43 | -------------------------------------------------------------------------------- /src/shims/instagram.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* 8 | * Bug 1804445 - instagram login broken with dFPI enabled 9 | * 10 | * Instagram login with Facebook account requires Facebook to have the storage 11 | * access under Instagram. This shim adds a request for storage access for 12 | * Facebook when the user tries to log in with a Facebook account. 13 | */ 14 | 15 | console.warn( 16 | `When logging in, Firefox calls the Storage Access API on behalf of the site. See https://bugzilla.mozilla.org/show_bug.cgi?id=1804445 for details.` 17 | ); 18 | 19 | // Third-party origin we need to request storage access for. 20 | const STORAGE_ACCESS_ORIGIN = "https://www.facebook.com"; 21 | 22 | document.documentElement.addEventListener( 23 | "click", 24 | e => { 25 | const { target, isTrusted } = e; 26 | if (!isTrusted) { 27 | return; 28 | } 29 | const button = target.closest("button[type=button]"); 30 | if (!button) { 31 | return; 32 | } 33 | const form = target.closest("#loginForm"); 34 | if (!form) { 35 | return; 36 | } 37 | 38 | console.warn( 39 | "Calling the Storage Access API on behalf of " + STORAGE_ACCESS_ORIGIN 40 | ); 41 | button.disabled = true; 42 | e.stopPropagation(); 43 | e.preventDefault(); 44 | document 45 | .requestStorageAccessForOrigin(STORAGE_ACCESS_ORIGIN) 46 | .then(() => { 47 | button.disabled = false; 48 | target.click(); 49 | }) 50 | .catch(() => { 51 | button.disabled = false; 52 | }); 53 | }, 54 | true 55 | ); 56 | -------------------------------------------------------------------------------- /src/shims/criteo.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1713720 - Shim Criteo 9 | * 10 | * Sites relying on window.Criteo to be loaded can experience 11 | * breakage if it is blocked. Stubbing out the API in a shim can 12 | * mitigate this breakage. 13 | */ 14 | 15 | if (window.Criteo?.CallRTA === undefined) { 16 | window.Criteo = { 17 | CallRTA() {}, 18 | ComputeStandaloneDFPTargeting() {}, 19 | DisplayAcceptableAdIfAdblocked() {}, 20 | DisplayAd() {}, 21 | GetBids() {}, 22 | GetBidsForAdUnit() {}, 23 | Passback: { 24 | RequestBids() {}, 25 | RenderAd() {}, 26 | }, 27 | PubTag: { 28 | Adapters: { 29 | AMP() {}, 30 | Prebid() {}, 31 | }, 32 | Context: { 33 | GetIdfs() {}, 34 | SetIdfs() {}, 35 | }, 36 | DirectBidding: { 37 | DirectBiddingEvent() {}, 38 | DirectBiddingSlot() {}, 39 | DirectBiddingUrlBuilder() {}, 40 | Size() {}, 41 | }, 42 | RTA: { 43 | DefaultCrtgContentName: "crtg_content", 44 | DefaultCrtgRtaCookieName: "crtg_rta", 45 | }, 46 | }, 47 | RenderAd() {}, 48 | RequestBids() {}, 49 | RequestBidsOnGoogleTagSlots() {}, 50 | SetCCPAExplicitOptOut() {}, 51 | SetCeh() {}, 52 | SetDFPKeyValueTargeting() {}, 53 | SetLineItemRanges() {}, 54 | SetPublisherExt() {}, 55 | SetSlotsExt() {}, 56 | SetTargeting() {}, 57 | SetUserExt() {}, 58 | events: { 59 | push() {}, 60 | }, 61 | passbackEvents: [], 62 | usePrebidEvents: true, 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /src/shims/history.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* 8 | * Bug 1624853 - Shim Storage Access API on history.com 9 | * 10 | * history.com uses Adobe as a necessary third party to authenticating 11 | * with a TV provider. In order to accomodate this, we grant storage access 12 | * to the Adobe domain via the Storage Access API when the login or logout 13 | * buttons are clicked, then forward the click to continue as normal. 14 | */ 15 | 16 | console.warn( 17 | `When using oauth, Firefox calls the Storage Access API on behalf of the site. See https://bugzilla.mozilla.org/show_bug.cgi?id=1624853 for details.` 18 | ); 19 | 20 | // Third-party origin we need to request storage access for. 21 | const STORAGE_ACCESS_ORIGIN = "https://sp.auth.adobe.com"; 22 | 23 | document.documentElement.addEventListener( 24 | "click", 25 | e => { 26 | const { target, isTrusted } = e; 27 | if (!isTrusted) { 28 | return; 29 | } 30 | 31 | const button = target.closest("a"); 32 | if (!button) { 33 | return; 34 | } 35 | 36 | const buttonLink = button.href; 37 | if (buttonLink?.startsWith("https://www.history.com/mvpd-auth")) { 38 | button.disabled = true; 39 | button.style.opacity = 0.5; 40 | e.stopPropagation(); 41 | e.preventDefault(); 42 | document 43 | .requestStorageAccessForOrigin(STORAGE_ACCESS_ORIGIN) 44 | .then(() => { 45 | target.click(); 46 | }) 47 | .catch(() => { 48 | button.disabled = false; 49 | button.style.opacity = 1.0; 50 | }); 51 | } 52 | }, 53 | true 54 | ); 55 | -------------------------------------------------------------------------------- /src/shims/maxmind-geoip.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1754389 - Shim Maxmind GeoIP library 9 | * 10 | * Some sites rely on Maxmind's GeoIP library which gets blocked by ETP's 11 | * fingerprinter blocking. With the library window global not being defined 12 | * functionality may break or the site does not render at all. This shim 13 | * has it return the United States as the location for all users. 14 | */ 15 | 16 | if (!window.geoip2) { 17 | const continent = { 18 | code: "NA", 19 | geoname_id: 6255149, 20 | names: { 21 | de: "Nordamerika", 22 | en: "North America", 23 | es: "Norteamérica", 24 | fr: "Amérique du Nord", 25 | ja: "北アメリカ", 26 | "pt-BR": "América do Norte", 27 | ru: "Северная Америка", 28 | "zh-CN": "北美洲", 29 | }, 30 | }; 31 | 32 | const country = { 33 | geoname_id: 6252001, 34 | iso_code: "US", 35 | names: { 36 | de: "USA", 37 | en: "United States", 38 | es: "Estados Unidos", 39 | fr: "États-Unis", 40 | ja: "アメリカ合衆国", 41 | "pt-BR": "Estados Unidos", 42 | ru: "США", 43 | "zh-CN": "美国", 44 | }, 45 | }; 46 | 47 | const city = { 48 | names: { 49 | en: "", 50 | }, 51 | }; 52 | 53 | const callback = onSuccess => { 54 | requestAnimationFrame(() => { 55 | onSuccess({ 56 | city, 57 | continent, 58 | country, 59 | registered_country: country, 60 | }); 61 | }); 62 | }; 63 | 64 | window.geoip2 = { 65 | country: callback, 66 | city: callback, 67 | insights: callback, 68 | }; 69 | } 70 | -------------------------------------------------------------------------------- /src/shims/tsn-ca.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* 8 | * Bug 1802340 - tsn.ca login broken with dFPI enabled 9 | * 10 | * tsn.ca relies upon a login page that is out-of-origin. That login page 11 | * sets a cookie for https://www.tsn.ca, which is then used as an proof of 12 | * authentication on redirect back to the main site. This shim adds a request 13 | * for storage access for https://www.tsn.ca when the user tries to log in. 14 | */ 15 | 16 | console.warn( 17 | `When logging in, Firefox calls the Storage Access API on behalf of the site. See https://bugzilla.mozilla.org/show_bug.cgi?id=1802340 for details.` 18 | ); 19 | 20 | // Third-party origin we need to request storage access for. 21 | const STORAGE_ACCESS_ORIGIN = "https://www.tsn.ca"; 22 | 23 | document.documentElement.addEventListener( 24 | "click", 25 | e => { 26 | const { target, isTrusted } = e; 27 | if (!isTrusted) { 28 | return; 29 | } 30 | 31 | const button = target.closest("button"); 32 | if (!button) { 33 | return; 34 | } 35 | const form = target.closest(".login-form"); 36 | if (!form) { 37 | return; 38 | } 39 | 40 | console.warn( 41 | "Calling the Storage Access API on behalf of " + STORAGE_ACCESS_ORIGIN 42 | ); 43 | button.disabled = true; 44 | e.stopPropagation(); 45 | e.preventDefault(); 46 | document 47 | .requestStorageAccessForOrigin(STORAGE_ACCESS_ORIGIN) 48 | .then(() => { 49 | button.disabled = false; 50 | target.click(); 51 | }) 52 | .catch(() => { 53 | button.disabled = false; 54 | }); 55 | }, 56 | true 57 | ); 58 | -------------------------------------------------------------------------------- /src/shims/crave-ca.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* 8 | * Bug 1746439 - crave.ca login broken with dFPI enabled 9 | * 10 | * Crave.ca relies upon a login page that is out-of-origin. That login page 11 | * sets a cookie for https://www.crave.ca, which is then used as an proof of 12 | * authentication on redirect back to the main site. This shim adds a request 13 | * for storage access for https://www.crave.ca when the user tries to log in. 14 | */ 15 | 16 | console.warn( 17 | `When logging in, Firefox calls the Storage Access API on behalf of the site. See https://bugzilla.mozilla.org/show_bug.cgi?id=1746439 for details.` 18 | ); 19 | 20 | // Third-party origin we need to request storage access for. 21 | const STORAGE_ACCESS_ORIGIN = "https://www.crave.ca"; 22 | 23 | document.documentElement.addEventListener( 24 | "click", 25 | e => { 26 | const { target, isTrusted } = e; 27 | if (!isTrusted) { 28 | return; 29 | } 30 | const button = target.closest("button"); 31 | if (!button) { 32 | return; 33 | } 34 | const form = target.closest(".login-form"); 35 | if (!form) { 36 | return; 37 | } 38 | 39 | console.warn( 40 | "Calling the Storage Access API on behalf of " + STORAGE_ACCESS_ORIGIN 41 | ); 42 | button.disabled = true; 43 | e.stopPropagation(); 44 | e.preventDefault(); 45 | document 46 | .requestStorageAccessForOrigin(STORAGE_ACCESS_ORIGIN) 47 | .then(() => { 48 | button.disabled = false; 49 | target.click(); 50 | }) 51 | .catch(() => { 52 | button.disabled = false; 53 | }); 54 | }, 55 | true 56 | ); 57 | -------------------------------------------------------------------------------- /src/shims/stackoverflow-login.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | console.warn( 8 | `When logging in, Firefox calls the Storage Access API on behalf of the site. See https://bugzilla.mozilla.org/show_bug.cgi?id=1949491 for details.` 9 | ); 10 | 11 | const STORAGE_ACCESS_ORIGIN = "https://stackexchange.com"; 12 | 13 | const STACKOVERFLOW_LOGIN_HERF_PREFIX = "https://stackoverflow.com/users/login"; 14 | const STACKOVERFLOW_SIGNUP_HERF_PREFIX = 15 | "https://stackoverflow.com/users/signup"; 16 | 17 | document.documentElement.addEventListener( 18 | "click", 19 | e => { 20 | const { target, isTrusted } = e; 21 | if (!isTrusted) { 22 | return; 23 | } 24 | 25 | // Find the click event on button elements. 26 | const button = target.closest("a.s-btn"); 27 | if (!button) { 28 | return; 29 | } 30 | 31 | // Only request storage access for login/signup buttons. 32 | if ( 33 | !button.href.startsWith(STACKOVERFLOW_LOGIN_HERF_PREFIX) && 34 | !button.href.startsWith(STACKOVERFLOW_SIGNUP_HERF_PREFIX) 35 | ) { 36 | return; 37 | } 38 | 39 | console.warn( 40 | "Calling the Storage Access API on behalf of " + STORAGE_ACCESS_ORIGIN 41 | ); 42 | 43 | // Disable the button to prevent it from being clicked again. 44 | button.style.pointerEvents = "none"; 45 | e.stopPropagation(); 46 | e.preventDefault(); 47 | document 48 | .requestStorageAccessForOrigin(STORAGE_ACCESS_ORIGIN) 49 | .finally(() => { 50 | // Re-enable the button and proceed with the login/signup flow. 51 | button.style.pointerEvents = ""; 52 | button.click(); 53 | }); 54 | }, 55 | true 56 | ); 57 | -------------------------------------------------------------------------------- /src/shims/adnexus-prebid.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1694401 - Shim Prebid.js 9 | * 10 | * Some sites rely on prebid.js to place content, perhaps in conjunction with 11 | * other services like Google Publisher Tags and Amazon TAM. This shim prevents 12 | * site breakage like image galleries breaking as the user browsers them, by 13 | * allowing the content placement to succeed. 14 | */ 15 | 16 | if (!window.pbjs?.requestBids) { 17 | const que = window.pbjs?.que || []; 18 | const cmd = window.pbjs?.cmd || []; 19 | const adUnits = window.pbjs?.adUnits || []; 20 | 21 | window.pbjs = { 22 | adUnits, 23 | addAdUnits(arr) { 24 | if (!Array.isArray(arr)) { 25 | arr = [arr]; 26 | } 27 | adUnits.push(arr); 28 | }, 29 | cmd, 30 | offEvent() {}, 31 | que, 32 | refreshAds() {}, 33 | removeAdUnit(codes) { 34 | if (!Array.isArray(codes)) { 35 | codes = [codes]; 36 | } 37 | for (const code of codes) { 38 | for (let i = adUnits.length - 1; i >= 0; i--) { 39 | if (adUnits[i].code === code) { 40 | adUnits.splice(i, 1); 41 | } 42 | } 43 | } 44 | }, 45 | renderAd() {}, 46 | requestBids(params) { 47 | params?.bidsBackHandler?.(); 48 | }, 49 | setConfig() {}, 50 | setTargetingForGPTAsync() {}, 51 | }; 52 | 53 | const push = function (fn) { 54 | if (typeof fn === "function") { 55 | try { 56 | fn(); 57 | } catch (e) { 58 | console.trace(e); 59 | } 60 | } 61 | }; 62 | 63 | que.push = push; 64 | cmd.push = push; 65 | 66 | que.forEach(push); 67 | cmd.forEach(push); 68 | } 69 | -------------------------------------------------------------------------------- /src/shims/apstag.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1713698 - Shim Amazon Transparent Ad Marketplace's apstag.js 9 | * 10 | * Some sites such as politico.com rely on Amazon TAM tracker to serve ads, 11 | * breaking functionality like galleries if it is blocked. This shim helps 12 | * mitigate major breakage in that case. 13 | */ 14 | 15 | if (!window.apstag?._getSlotIdToNameMapping) { 16 | const _Q = window.apstag?._Q || []; 17 | 18 | const newBid = config => { 19 | return { 20 | amznbid: "", 21 | amzniid: "", 22 | amznp: "", 23 | amznsz: "0x0", 24 | size: "0x0", 25 | slotID: config.slotID, 26 | }; 27 | }; 28 | 29 | window.apstag = { 30 | _Q, 31 | _getSlotIdToNameMapping() {}, 32 | bids() {}, 33 | debug() {}, 34 | deleteId() {}, 35 | fetchBids(cfg, cb) { 36 | if (!Array.isArray(cfg?.slots)) { 37 | return; 38 | } 39 | setTimeout(() => { 40 | cb(cfg.slots.map(s => newBid(s))); 41 | }, 1); 42 | }, 43 | init() {}, 44 | punt() {}, 45 | renderImp() {}, 46 | renewId() {}, 47 | setDisplayBids() {}, 48 | targetingKeys: () => [], 49 | thirdPartyData: {}, 50 | updateId() {}, 51 | }; 52 | 53 | window.apstagLOADED = true; 54 | 55 | _Q.push = function (prefix, args) { 56 | try { 57 | switch (prefix) { 58 | case "f": 59 | window.apstag.fetchBids(...args); 60 | break; 61 | case "i": 62 | window.apstag.init(...args); 63 | break; 64 | } 65 | } catch (e) { 66 | console.trace(e); 67 | } 68 | }; 69 | 70 | for (const cmd of _Q) { 71 | _Q.push(cmd); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/shims/kinja.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /* globals exportFunction */ 6 | 7 | "use strict"; 8 | 9 | /** 10 | * Kinja powered blogs rely on storage access to https://kinja.com to enable 11 | * oauth with external providers. For dFPI, sites need to use the Storage Access 12 | * API to gain first party storage access. This shim calls requestStorageAccess 13 | * on behalf of the site when a user wants to log in via oauth. 14 | */ 15 | 16 | // Third-party origin we need to request storage access for. 17 | const STORAGE_ACCESS_ORIGIN = "https://kinja.com"; 18 | 19 | // Prefix of the path opened in a new window when users click the oauth login 20 | // buttons. 21 | const OAUTH_PATH_PREFIX = "/oauthlogin?provider="; 22 | 23 | console.warn( 24 | `When using oauth, Firefox calls the Storage Access API on behalf of the site. See https://bugzilla.mozilla.org/show_bug.cgi?id=1656171 for details.` 25 | ); 26 | 27 | // Overwrite the window.open method so we can detect oauth related popups. 28 | const origOpen = window.wrappedJSObject.open; 29 | Object.defineProperty(window.wrappedJSObject, "open", { 30 | value: exportFunction((url, ...args) => { 31 | // Filter oauth popups. 32 | if (!url.startsWith(OAUTH_PATH_PREFIX)) { 33 | return origOpen(url, ...args); 34 | } 35 | // Request storage access for Kinja. 36 | document.requestStorageAccessForOrigin(STORAGE_ACCESS_ORIGIN).then(() => { 37 | origOpen(url, ...args); 38 | }); 39 | // We don't have the window object yet which window.open returns, since the 40 | // sign-in flow is dependent on the async storage access request. This isn't 41 | // a problem as long as the website does not consume it. 42 | return null; 43 | }, window), 44 | }); 45 | -------------------------------------------------------------------------------- /src/lib/shim_messaging_helper.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* globals browser */ 8 | 9 | if (!window.Shims) { 10 | window.Shims = new Map(); 11 | } 12 | 13 | if (!window.ShimsHelperReady) { 14 | window.ShimsHelperReady = true; 15 | 16 | browser.runtime.onMessage.addListener(details => { 17 | const { shimId, warning } = details; 18 | if (!shimId) { 19 | return; 20 | } 21 | window.Shims.set(shimId, details); 22 | if (warning) { 23 | console.warn(warning); 24 | } 25 | }); 26 | 27 | async function handleMessage(port, shimId, messageId, message) { 28 | let response; 29 | const shim = window.Shims.get(shimId); 30 | if (shim) { 31 | const { needsShimHelpers, origin } = shim; 32 | if (origin === location.origin) { 33 | if (needsShimHelpers?.includes(message)) { 34 | const msg = { shimId, message }; 35 | try { 36 | response = await browser.runtime.sendMessage(msg); 37 | } catch (_) {} 38 | } 39 | } 40 | } 41 | port.postMessage({ messageId, response }); 42 | } 43 | 44 | window.addEventListener( 45 | "ShimConnects", 46 | e => { 47 | e.stopPropagation(); 48 | e.preventDefault(); 49 | const { port, pendingMessages, shimId } = e.detail; 50 | const shim = window.Shims.get(shimId); 51 | if (!shim) { 52 | return; 53 | } 54 | port.onmessage = ({ data }) => { 55 | handleMessage(port, shimId, data.messageId, data.message); 56 | }; 57 | for (const [messageId, message] of pendingMessages) { 58 | handleMessage(port, shimId, messageId, message); 59 | } 60 | }, 61 | true 62 | ); 63 | 64 | window.dispatchEvent(new CustomEvent("ShimHelperReady")); 65 | } 66 | -------------------------------------------------------------------------------- /src/shims/google-ads.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1713726 - Shim Ads by Google 9 | * 10 | * Sites relying on window.adsbygoogle may encounter breakage if it is blocked. 11 | * This shim provides a stub for that API to mitigate that breakage. 12 | */ 13 | 14 | if (window.adsbygoogle?.loaded === undefined) { 15 | window.adsbygoogle = { 16 | loaded: true, 17 | push() {}, 18 | }; 19 | } 20 | 21 | if (window.gapi?._pl === undefined) { 22 | const stub = { 23 | go() {}, 24 | render: () => "", 25 | }; 26 | window.gapi = { 27 | _pl: true, 28 | additnow: stub, 29 | autocomplete: stub, 30 | backdrop: stub, 31 | blogger: stub, 32 | commentcount: stub, 33 | comments: stub, 34 | community: stub, 35 | donation: stub, 36 | family_creation: stub, 37 | follow: stub, 38 | hangout: stub, 39 | health: stub, 40 | interactivepost: stub, 41 | load() {}, 42 | logutil: { 43 | enableDebugLogging() {}, 44 | }, 45 | page: stub, 46 | partnersbadge: stub, 47 | person: stub, 48 | platform: { 49 | go() {}, 50 | }, 51 | playemm: stub, 52 | playreview: stub, 53 | plus: stub, 54 | plusone: stub, 55 | post: stub, 56 | profile: stub, 57 | ratingbadge: stub, 58 | recobar: stub, 59 | savetoandroidpay: stub, 60 | savetodrive: stub, 61 | savetowallet: stub, 62 | share: stub, 63 | sharetoclassroom: stub, 64 | shortlists: stub, 65 | signin: stub, 66 | signin2: stub, 67 | surveyoptin: stub, 68 | visibility: stub, 69 | youtube: stub, 70 | ytsubscribe: stub, 71 | zoomableimage: stub, 72 | }; 73 | } 74 | 75 | for (const e of document.querySelectorAll("ins.adsbygoogle")) { 76 | e.style.maxWidth = "0px"; 77 | } 78 | -------------------------------------------------------------------------------- /src/injections/js/bug1898952-digits.t-mobile.com.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1898952 - Spoof navigator.userAgentData for digits.t-mobile.com 9 | * Webcompat issue #119767 - https://webcompat.com/issues/119767 10 | * 11 | * The site blocks Firefox and Safari, reading info from userAgentData. 12 | */ 13 | 14 | /* globals exportFunction, cloneInto */ 15 | 16 | if (!navigator.userAgentData) { 17 | console.info( 18 | "navigator.userAgentData has been overridden for compatibility reasons. See https://webcompat.com/issues/119767 for details." 19 | ); 20 | 21 | const ua = navigator.userAgent; 22 | const mobile = ua.includes("Mobile") || ua.includes("Tablet"); 23 | 24 | // Very roughly matches Chromium's GetPlatformForUAMetadata() 25 | let platform = "Linux"; 26 | if (mobile) { 27 | platform = "Android"; 28 | } else if (navigator.platform.startsWith("Win")) { 29 | platform = "Windows"; 30 | } else if (navigator.platform.startsWith("Mac")) { 31 | platform = "macOS"; 32 | } 33 | 34 | const version = (ua.match(/Firefox\/([0-9.]+)/) || ["", "58.0"])[1]; 35 | 36 | // These match Chrome's output as of version 126. 37 | const brands = [ 38 | { 39 | brand: "Not/A)Brand", 40 | version: "8", 41 | }, 42 | { 43 | brand: "Chromium", 44 | version, 45 | }, 46 | { 47 | brand: "Google Chrome", 48 | version, 49 | }, 50 | ]; 51 | 52 | const userAgentData = cloneInto( 53 | { 54 | brands, 55 | mobile, 56 | platform, 57 | }, 58 | window 59 | ); 60 | 61 | Object.defineProperty(window.navigator.wrappedJSObject, "userAgentData", { 62 | get: exportFunction(function () { 63 | return userAgentData; 64 | }, window), 65 | 66 | set: exportFunction(function () {}, window), 67 | }); 68 | } 69 | -------------------------------------------------------------------------------- /src/experiment-apis/aboutConfigPrefs.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* global ExtensionAPI, ExtensionCommon, Services */ 8 | 9 | this.aboutConfigPrefs = class extends ExtensionAPI { 10 | getAPI(context) { 11 | const EventManager = ExtensionCommon.EventManager; 12 | const extensionIDBase = context.extension.id.split("@")[0]; 13 | const extensionPrefNameBase = `extensions.${extensionIDBase}.`; 14 | 15 | return { 16 | aboutConfigPrefs: { 17 | onPrefChange: new EventManager({ 18 | context, 19 | name: "aboutConfigPrefs.onUAOverridesPrefChange", 20 | register: (fire, name) => { 21 | const prefName = `${extensionPrefNameBase}${name}`; 22 | const callback = () => { 23 | fire.async(name).catch(() => {}); // ignore Message Manager disconnects 24 | }; 25 | Services.prefs.addObserver(prefName, callback); 26 | return () => { 27 | Services.prefs.removeObserver(prefName, callback); 28 | }; 29 | }, 30 | }).api(), 31 | async getBranch(branchName) { 32 | const branch = `${extensionPrefNameBase}${branchName}.`; 33 | return Services.prefs.getChildList(branch).map(pref => { 34 | const name = pref.replace(branch, ""); 35 | return { name, value: Services.prefs.getBoolPref(pref) }; 36 | }); 37 | }, 38 | async getPref(name) { 39 | try { 40 | return Services.prefs.getBoolPref( 41 | `${extensionPrefNameBase}${name}` 42 | ); 43 | } catch (_) { 44 | return undefined; 45 | } 46 | }, 47 | async setPref(name, value) { 48 | Services.prefs.setBoolPref(`${extensionPrefNameBase}${name}`, value); 49 | }, 50 | }, 51 | }; 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /src/shims/fastclick.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1738220 - Shim Conversant FastClick 9 | * 10 | * Sites assuming FastClick will load can break if it is blocked. 11 | * This shim mitigates that breakage. 12 | */ 13 | 14 | // FastClick bundles nodeJS packages/core-js/internals/dom-iterables.js 15 | // which is known to be needed by at least one site. 16 | if (!HTMLCollection.prototype.forEach) { 17 | const DOMIterables = [ 18 | "CSSRuleList", 19 | "CSSStyleDeclaration", 20 | "CSSValueList", 21 | "ClientRectList", 22 | "DOMRectList", 23 | "DOMStringList", 24 | "DOMTokenList", 25 | "DataTransferItemList", 26 | "FileList", 27 | "HTMLAllCollection", 28 | "HTMLCollection", 29 | "HTMLFormElement", 30 | "HTMLSelectElement", 31 | "MediaList", 32 | "MimeTypeArray", 33 | "NamedNodeMap", 34 | "NodeList", 35 | "PaintRequestList", 36 | "Plugin", 37 | "PluginArray", 38 | "SVGLengthList", 39 | "SVGNumberList", 40 | "SVGPathSegList", 41 | "SVGPointList", 42 | "SVGStringList", 43 | "SVGTransformList", 44 | "SourceBufferList", 45 | "StyleSheetList", 46 | "TextTrackCueList", 47 | "TextTrackList", 48 | "TouchList", 49 | ]; 50 | 51 | const forEach = Array.prototype.forEach; 52 | 53 | const handlePrototype = proto => { 54 | if (!proto || proto.forEach === forEach) { 55 | return; 56 | } 57 | try { 58 | Object.defineProperty(proto, "forEach", { 59 | enumerable: false, 60 | get: () => forEach, 61 | }); 62 | } catch (_) { 63 | proto.forEach = forEach; 64 | } 65 | }; 66 | 67 | for (const name of DOMIterables) { 68 | handlePrototype(window[name]?.prototype); 69 | } 70 | } 71 | 72 | if (!window.conversant?.launch) { 73 | const c = (window.conversant = window.conversant || {}); 74 | c.launch = () => {}; 75 | } 76 | -------------------------------------------------------------------------------- /src/shims/branch.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1716220 - Shim Branch Web SDK 9 | * 10 | * Sites such as TataPlay may not load properly if Branch Web SDK is 11 | * blocked. This shim stubs out its script so the page still loads. 12 | */ 13 | 14 | if (!window?.branch?.b) { 15 | const queue = window?.branch?._q || []; 16 | window.branch = new (class { 17 | V = {}; 18 | g = 0; 19 | X = "web2.62.0"; 20 | b = { 21 | A: {}, 22 | clear() {}, 23 | get() {}, 24 | getAll() {}, 25 | isEnabled: () => true, 26 | remove() {}, 27 | set() {}, 28 | ca() {}, 29 | g: [], 30 | l: 0, 31 | o: 0, 32 | s: null, 33 | }; 34 | addListener() {} 35 | applyCode() {} 36 | autoAppIndex() {} 37 | banner() {} 38 | c() {} 39 | closeBanner() {} 40 | closeJourney() {} 41 | constructor() {} 42 | creditHistory() {} 43 | credits() {} 44 | crossPlatformIds() {} 45 | data() {} 46 | deepview() {} 47 | deepviewCta() {} 48 | disableTracking() {} 49 | first() {} 50 | getBrowserFingerprintId() {} 51 | getCode() {} 52 | init(key, ...args) { 53 | const cb = args.pop(); 54 | if (typeof cb === "function") { 55 | cb(undefined, {}); 56 | } 57 | } 58 | lastAttributedTouchData() {} 59 | link() {} 60 | logEvent() {} 61 | logout() {} 62 | qrCode() {} 63 | redeem() {} 64 | referrals() {} 65 | removeListener() {} 66 | renderFinalize() {} 67 | renderQueue() {} 68 | sendSMS() {} 69 | setAPIResponseCallback() {} 70 | setBranchViewData() {} 71 | setIdentity() {} 72 | track() {} 73 | trackCommerceEvent() {} 74 | validateCode() {} 75 | })(); 76 | const push = ([fn, ...args]) => { 77 | try { 78 | window.branch[fn].apply(window.branch, args); 79 | } catch (e) { 80 | console.error(e); 81 | } 82 | }; 83 | queue.forEach(push); 84 | } 85 | -------------------------------------------------------------------------------- /src/shims/blogger.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /* globals exportFunction */ 6 | 7 | "use strict"; 8 | 9 | /** 10 | * Blogger powered blogs rely on storage access to https://blogger.com to enable 11 | * oauth with Google. For dFPI, sites need to use the Storage Access API to gain 12 | * first party storage access. This shim calls requestStorageAccess on behalf of 13 | * the site when a user wants to log in via oauth. 14 | */ 15 | 16 | console.warn( 17 | `When using oauth, Firefox calls the Storage Access API on behalf of the site. See https://bugzilla.mozilla.org/show_bug.cgi?id=1776869 for details.` 18 | ); 19 | 20 | const GOOGLE_OAUTH_PATH_PREFIX = "https://accounts.google.com/ServiceLogin"; 21 | 22 | // After permission was granted request (use) storage access and reload 23 | async function requestGrantedAccess() { 24 | const storageAccessPermission = await navigator.permissions.query({ 25 | name: "storage-access", 26 | }); 27 | const hasStorageAccess = await document.hasStorageAccess(); 28 | if (storageAccessPermission.state === "granted" && !hasStorageAccess) { 29 | await document.requestStorageAccess(); 30 | location.reload(); 31 | } 32 | } 33 | 34 | requestGrantedAccess(); 35 | 36 | // Overwrite the window.open method so we can detect oauth related popups. 37 | const origOpen = window.wrappedJSObject.open; 38 | Object.defineProperty(window.wrappedJSObject, "open", { 39 | value: exportFunction((url, ...args) => { 40 | // Filter oauth popups. 41 | if (!url.startsWith(GOOGLE_OAUTH_PATH_PREFIX)) { 42 | return origOpen(url, ...args); 43 | } 44 | // Request storage access for the Blogger iframe. 45 | document.requestStorageAccess().then(() => { 46 | origOpen(url, ...args); 47 | }); 48 | // We don't have the window object yet which window.open returns, since the 49 | // sign-in flow is dependent on the async storage access request. This isn't 50 | // a problem as long as the website does not consume it. 51 | return null; 52 | }, window), 53 | }); 54 | -------------------------------------------------------------------------------- /spec/helpers/mock_webextension_apis.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * This mocks WebExtension APIs with noop functions so tests don't fail. 9 | * Generally, we only want to verify that those APIs are called with the right 10 | * paramaters, and not test the APIs themselves - those have in-tree tests, 11 | * and their API is considered stable, so we'd just be duplicating efforts here. 12 | */ 13 | jasmine.getGlobal().browser = { 14 | aboutConfigPrefs: { 15 | getPref: async () => { 16 | return true; 17 | }, 18 | getBoolPrefSync: () => true, 19 | onPrefChange: { 20 | addListener: () => {}, 21 | }, 22 | }, 23 | appConstants: { 24 | getReleaseBranch: async () => "release_or_beta", 25 | }, 26 | contentScripts: { 27 | register: async () => {}, 28 | }, 29 | runtime: { 30 | getPlatformInfo: async () => { 31 | return { 32 | os: "test runner", 33 | }; 34 | }, 35 | }, 36 | scripting: { 37 | registerContentScripts: async () => {}, 38 | unregisterContentScripts: async () => {}, 39 | getRegisteredContentScripts: async () => { 40 | return []; 41 | }, 42 | }, 43 | systemManufacturer: { 44 | getManufacturer: () => {}, 45 | }, 46 | testUtils: { 47 | interventionsAactive: () => {}, 48 | interventionsInactive: () => {}, 49 | shimsAactive: () => {}, 50 | shimsInactive: () => {}, 51 | }, 52 | trackingProtection: { 53 | allow: async () => {}, 54 | isDFPIActive: async () => false, 55 | onPrivateSessionEnd: { 56 | addListener: () => {}, 57 | }, 58 | onSmartBlockEmbedReblock: { 59 | addListener: () => {}, 60 | }, 61 | onSmartBlockEmbedUnblock: { 62 | addListener: () => {}, 63 | }, 64 | revoke: async () => {}, 65 | shim: async () => {}, 66 | wasRequestUnblocked: async () => false, 67 | }, 68 | webRequest: { 69 | onBeforeRequest: { 70 | addListener: () => {}, 71 | }, 72 | onBeforeSendHeaders: { 73 | addListener: () => {}, 74 | }, 75 | onHeadersReceived: { 76 | addListener: () => {}, 77 | }, 78 | }, 79 | }; 80 | -------------------------------------------------------------------------------- /src/injections/js/bug1924500-www.tiktok.com-fix-captcha-slider.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1924500 - Fix www.tiktok.com captcha slider 9 | * WebCompat issue #142709 - https://webcompat.com/issues/142709 10 | * 11 | * They are relying on drag events having clientX coordinates, which are 12 | * always zero on Firefox. A work-around is to listen for mousemove and 13 | * dragover events to capture the clientX value from them, and then 14 | * pass the value along when they reads a DragEvent.clientX. 15 | */ 16 | 17 | /* globals exportFunction */ 18 | 19 | (function () { 20 | let lastClientX = 0; 21 | 22 | const win = window.wrappedJSObject; 23 | Object.defineProperty(win.DragEvent.prototype, "clientX", { 24 | get: exportFunction(function () { 25 | return lastClientX; 26 | }, window), 27 | set: exportFunction(function () {}, window), 28 | configurable: true, 29 | }); 30 | 31 | function setLastClientX(evt) { 32 | lastClientX = evt.clientX; 33 | } 34 | 35 | const captchaOverlayQuery = ".TUXModal-overlay"; 36 | 37 | function activate() { 38 | document.documentElement.addEventListener("mousemove", setLastClientX); 39 | document.documentElement.addEventListener("dragover", setLastClientX); 40 | } 41 | 42 | function deactivate() { 43 | lastClientX = 0; 44 | document.documentElement.removeEventListener("mousemove", setLastClientX); 45 | document.documentElement.removeEventListener("dragover", setLastClientX); 46 | } 47 | 48 | const captchaObserver = new MutationObserver(mutations => { 49 | for (let { addedNodes, removedNodes } of mutations) { 50 | for (const node of addedNodes) { 51 | try { 52 | if (node.matches(captchaOverlayQuery)) { 53 | activate(); 54 | } 55 | } catch (_) {} 56 | } 57 | for (const node of removedNodes) { 58 | try { 59 | if (node.matches(captchaOverlayQuery)) { 60 | deactivate(); 61 | } 62 | } catch (_) {} 63 | } 64 | } 65 | }); 66 | 67 | captchaObserver.observe(document.documentElement, { 68 | childList: true, 69 | subtree: true, 70 | }); 71 | })(); 72 | -------------------------------------------------------------------------------- /src/shims/bloggerAccount.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | /* globals exportFunction */ 6 | 7 | "use strict"; 8 | 9 | /** 10 | * Blogger uses Google as the auth provider. The account panel uses a 11 | * third-party iframe of https://ogs.google.com, which requires first-party 12 | * storage access to authenticate. This shim calls requestStorageAccess on 13 | * behalf of the site when the user opens the account panel. 14 | */ 15 | 16 | console.warn( 17 | `When logging in with Google, Firefox calls the Storage Access API on behalf of the site. See https://bugzilla.mozilla.org/show_bug.cgi?id=1777690 for details.` 18 | ); 19 | 20 | const STORAGE_ACCESS_ORIGIN = "https://ogs.google.com"; 21 | 22 | document.documentElement.addEventListener( 23 | "click", 24 | e => { 25 | const { target, isTrusted } = e; 26 | if (!isTrusted) { 27 | return; 28 | } 29 | 30 | const anchorEl = target.closest("a"); 31 | if (!anchorEl) { 32 | return; 33 | } 34 | 35 | if ( 36 | !anchorEl.href.startsWith("https://accounts.google.com/SignOutOptions") 37 | ) { 38 | return; 39 | } 40 | 41 | // The storage access request below runs async so the panel won't open 42 | // immediately. Mitigate this UX issue by updating the clicked element's 43 | // style so the user gets some immediate feedback. 44 | anchorEl.style.opacity = 0.5; 45 | e.stopPropagation(); 46 | e.preventDefault(); 47 | 48 | document 49 | .requestStorageAccessForOrigin(STORAGE_ACCESS_ORIGIN) 50 | .then(() => { 51 | // Reload all iframes of ogs.google.com so the first-party cookies are 52 | // sent to the server. 53 | // The reload mechanism here is a bit of a hack, since we don't have 54 | // access to the content window of a cross-origin iframe. 55 | document 56 | .querySelectorAll("iframe[src^='https://ogs.google.com/']") 57 | .forEach(frame => (frame.src += "")); 58 | }) 59 | // Show the panel in both success and error state. When the user denies 60 | // the storage access prompt they will see an error message in the account 61 | // panel. 62 | .finally(() => { 63 | anchorEl.style.opacity = 1.0; 64 | target.click(); 65 | }); 66 | }, 67 | true 68 | ); 69 | -------------------------------------------------------------------------------- /src/tests/browser/browser_shims.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | registerCleanupFunction(() => { 4 | UrlClassifierTestUtils.cleanupTestTrackers(); 5 | Services.prefs.clearUserPref(TRACKING_PREF); 6 | }); 7 | 8 | add_setup(async function () { 9 | await UrlClassifierTestUtils.addTestTrackers(); 10 | }); 11 | 12 | add_task(async function test_shim_disabled_by_own_pref() { 13 | // Test that a shim will not apply if disabled in about:config 14 | 15 | Services.prefs.setBoolPref(DISABLE_SHIM1_PREF, true); 16 | Services.prefs.setBoolPref(TRACKING_PREF, true); 17 | 18 | await testShimDoesNotRun(); 19 | 20 | Services.prefs.clearUserPref(DISABLE_SHIM1_PREF); 21 | Services.prefs.clearUserPref(TRACKING_PREF); 22 | }); 23 | 24 | add_task(async function test_shim_disabled_by_global_pref() { 25 | // Test that a shim will not apply if disabled in about:config 26 | 27 | Services.prefs.setBoolPref(GLOBAL_PREF, false); 28 | Services.prefs.setBoolPref(DISABLE_SHIM1_PREF, false); 29 | Services.prefs.setBoolPref(TRACKING_PREF, true); 30 | 31 | await testShimDoesNotRun(); 32 | 33 | Services.prefs.clearUserPref(GLOBAL_PREF); 34 | Services.prefs.clearUserPref(DISABLE_SHIM1_PREF); 35 | Services.prefs.clearUserPref(TRACKING_PREF); 36 | }); 37 | 38 | add_task(async function test_shim_disabled_hosts_notHosts() { 39 | Services.prefs.setBoolPref(TRACKING_PREF, true); 40 | 41 | await testShimDoesNotRun(false, SHIMMABLE_TEST_PAGE_3); 42 | 43 | Services.prefs.clearUserPref(TRACKING_PREF); 44 | }); 45 | 46 | add_task(async function test_shim_disabled_overridden_by_pref() { 47 | Services.prefs.setBoolPref(TRACKING_PREF, true); 48 | 49 | await testShimDoesNotRun(false, SHIMMABLE_TEST_PAGE_2); 50 | 51 | Services.prefs.setBoolPref(DISABLE_SHIM2_PREF, false); 52 | 53 | await testShimRuns(SHIMMABLE_TEST_PAGE_2); 54 | 55 | Services.prefs.clearUserPref(TRACKING_PREF); 56 | Services.prefs.clearUserPref(DISABLE_SHIM2_PREF); 57 | }); 58 | 59 | add_task(async function test_shim() { 60 | // Test that a shim which only runs in strict mode works, and that it 61 | // is permitted to opt into showing normally-blocked tracking content. 62 | 63 | Services.prefs.setBoolPref(TRACKING_PREF, true); 64 | 65 | await testShimRuns(SHIMMABLE_TEST_PAGE); 66 | 67 | // test that if the user opts in on one domain, they will still have to opt 68 | // in on another domain which embeds an iframe to the first one. 69 | 70 | await testShimRuns(EMBEDDING_TEST_PAGE, 0, false, false); 71 | 72 | Services.prefs.clearUserPref(TRACKING_PREF); 73 | }); 74 | -------------------------------------------------------------------------------- /src/shims/live-test-shim.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* globals browser */ 8 | 9 | if (!window.LiveTestShimPromise) { 10 | const originalUrl = 11 | "https://webcompat-addon-testbed.herokuapp.com/shims_test.js"; 12 | 13 | const shimId = "LiveTestShim"; 14 | 15 | const sendMessageToAddon = (function () { 16 | const pendingMessages = new Map(); 17 | const channel = new MessageChannel(); 18 | channel.port1.onerror = console.error; 19 | channel.port1.onmessage = event => { 20 | const { messageId, response } = event.data; 21 | const resolve = pendingMessages.get(messageId); 22 | if (resolve) { 23 | pendingMessages.delete(messageId); 24 | resolve(response); 25 | } 26 | }; 27 | function reconnect() { 28 | const detail = { 29 | pendingMessages: [...pendingMessages.values()], 30 | port: channel.port2, 31 | shimId, 32 | }; 33 | window.dispatchEvent(new CustomEvent("ShimConnects", { detail })); 34 | } 35 | window.addEventListener("ShimHelperReady", reconnect); 36 | reconnect(); 37 | return function (message) { 38 | const messageId = 39 | Math.random().toString(36).substring(2) + Date.now().toString(36); 40 | return new Promise(resolve => { 41 | const payload = { 42 | message, 43 | messageId, 44 | shimId, 45 | }; 46 | pendingMessages.set(messageId, resolve); 47 | channel.port1.postMessage(payload); 48 | }); 49 | }; 50 | })(); 51 | 52 | async function go(options) { 53 | try { 54 | const o = document.getElementById("shims"); 55 | const cl = o.classList; 56 | cl.remove("red"); 57 | cl.add("green"); 58 | o.innerText = JSON.stringify(options || ""); 59 | } catch (_) {} 60 | 61 | if (window !== top) { 62 | return; 63 | } 64 | 65 | await sendMessageToAddon("optIn"); 66 | 67 | const s = document.createElement("script"); 68 | s.src = originalUrl; 69 | document.head.appendChild(s); 70 | } 71 | 72 | window[`${shimId}Promise`] = sendMessageToAddon("getOptions").then( 73 | options => { 74 | if (document.readyState !== "loading") { 75 | go(options); 76 | } else { 77 | window.addEventListener("DOMContentLoaded", () => { 78 | go(options); 79 | }); 80 | } 81 | } 82 | ); 83 | } 84 | -------------------------------------------------------------------------------- /src/injections/js/bug1897120-turnjs-zoom-fix.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* 8 | * Bug 1897120 - Override "MozTransform" in element.style and return false 9 | * Webcompat issue #137038 - https://github.com/webcompat/web-bugs/issues/137038 10 | * 11 | * The site is using turn js and detecting "MozTransform" in document.body.style, 12 | * which returns true at the moment and uses the -moz-transform, which doesn't work, 13 | * so zooming functionality breaks. Overriding "MozTransform" in element.style to 14 | * return false fixes the problem. 15 | */ 16 | 17 | /* globals exportFunction, cloneInto */ 18 | 19 | console.info( 20 | "Overriding MozTransform in element.style for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1897120 for details." 21 | ); 22 | 23 | (function () { 24 | const ele = HTMLElement.wrappedJSObject.prototype; 25 | const obj = window.wrappedJSObject.Object; 26 | const style = obj.getOwnPropertyDescriptor(ele, "style"); 27 | const { get } = style; 28 | style.get = exportFunction(function () { 29 | const styles = get.call(this); 30 | return new window.wrappedJSObject.Proxy( 31 | styles, 32 | cloneInto( 33 | { 34 | deleteProperty(target, prop) { 35 | return Reflect.deleteProperty(target, prop); 36 | }, 37 | get(target, key) { 38 | const val = Reflect.get(target, key); 39 | if (typeof val == "function") { 40 | // We can't just return the function, as it's a method which 41 | // needs `this` to be the styles object. So we return a wrapper. 42 | return exportFunction(function () { 43 | return val.apply(styles, arguments); 44 | }, window); 45 | } 46 | return val; 47 | }, 48 | has(target, key) { 49 | if (key == "MozTransform" || key == "WebkitTransform") { 50 | return false; 51 | } 52 | return Reflect.has(target, key); 53 | }, 54 | ownKeys(target) { 55 | return Reflect.ownKeys(target); 56 | }, 57 | set(target, key, value) { 58 | return Reflect.set(target, key, value); 59 | }, 60 | }, 61 | window, 62 | { cloneFunctions: true } 63 | ) 64 | ); 65 | }, window); 66 | obj.defineProperty(ele, "style", style); 67 | })(); 68 | -------------------------------------------------------------------------------- /src/shims/firebase.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1767407 - Shim Firebase 9 | * 10 | * Sites relying on firebase-messaging.js will break in Private 11 | * browsing mode because it assumes that they require service 12 | * workers and indexedDB, when they generally do not. 13 | */ 14 | 15 | /* globals cloneInto */ 16 | 17 | (function () { 18 | const win = window.wrappedJSObject; 19 | const emptyObj = new win.Object(); 20 | const emptyArr = new win.Array(); 21 | const emptyMsg = cloneInto({ message: "" }, window); 22 | const noOpFn = cloneInto(function () {}, window, { cloneFunctions: true }); 23 | 24 | if (!win.indexedDB) { 25 | const idb = { 26 | open: () => win.Promise.reject(emptyMsg), 27 | }; 28 | 29 | Object.defineProperty(win, "indexedDB", { 30 | value: cloneInto(idb, window, { cloneFunctions: true }), 31 | }); 32 | } 33 | 34 | // bug 1778993 35 | for (const name of [ 36 | "IDBCursor", 37 | "IDBDatabase", 38 | "IDBIndex", 39 | "IDBOpenDBRequest", 40 | "IDBRequest", 41 | "IDBTransaction", 42 | ]) { 43 | if (!win[name]) { 44 | Object.defineProperty(win, name, { value: emptyObj }); 45 | } 46 | } 47 | 48 | if (!win.serviceWorker) { 49 | const sw = { 50 | addEventListener() {}, 51 | getRegistrations: () => win.Promise.resolve(emptyArr), 52 | register: () => win.Promise.reject(emptyMsg), 53 | }; 54 | 55 | Object.defineProperty(navigator.wrappedJSObject, "serviceWorker", { 56 | value: cloneInto(sw, window, { cloneFunctions: true }), 57 | }); 58 | 59 | // bug 1779536 60 | Object.defineProperty(navigator.wrappedJSObject.serviceWorker, "ready", { 61 | value: new win.Promise(noOpFn), 62 | }); 63 | } 64 | 65 | // bug 1750699 66 | if (!win.PushManager) { 67 | Object.defineProperty(win, "PushManager", { value: emptyObj }); 68 | } 69 | 70 | // bug 1750699 71 | if (!win.PushSubscription) { 72 | const ps = { 73 | prototype: { 74 | getKey() {}, 75 | }, 76 | }; 77 | 78 | Object.defineProperty(win, "PushSubscription", { 79 | value: cloneInto(ps, window, { cloneFunctions: true }), 80 | }); 81 | } 82 | 83 | // bug 1750699 84 | if (!win.ServiceWorkerRegistration) { 85 | const swr = { 86 | prototype: { 87 | showNotification() {}, 88 | }, 89 | }; 90 | 91 | Object.defineProperty(win, "ServiceWorkerRegistration", { 92 | value: cloneInto(swr, window, { cloneFunctions: true }), 93 | }); 94 | } 95 | })(); 96 | -------------------------------------------------------------------------------- /src/shims/mochitest-shim-2.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* globals browser */ 8 | 9 | if (!window.testPromise) { 10 | const originalUrl = 11 | "http://example.com/browser/browser/extensions/webcompat/tests/browser/shims_test_2.js"; 12 | 13 | const shimId = "MochitestShim2"; 14 | 15 | const sendMessageToAddon = (function () { 16 | const pendingMessages = new Map(); 17 | const channel = new MessageChannel(); 18 | channel.port1.onerror = console.error; 19 | channel.port1.onmessage = event => { 20 | const { messageId, response } = event.data; 21 | const resolve = pendingMessages.get(messageId); 22 | if (resolve) { 23 | pendingMessages.delete(messageId); 24 | resolve(response); 25 | } 26 | }; 27 | function reconnect() { 28 | const detail = { 29 | pendingMessages: [...pendingMessages.values()], 30 | port: channel.port2, 31 | shimId, 32 | }; 33 | window.dispatchEvent(new CustomEvent("ShimConnects", { detail })); 34 | } 35 | window.addEventListener("ShimHelperReady", reconnect); 36 | reconnect(); 37 | return function (message) { 38 | const messageId = 39 | Math.random().toString(36).substring(2) + Date.now().toString(36); 40 | return new Promise(resolve => { 41 | const payload = { 42 | message, 43 | messageId, 44 | shimId, 45 | }; 46 | pendingMessages.set(messageId, resolve); 47 | channel.port1.postMessage(payload); 48 | }); 49 | }; 50 | })(); 51 | 52 | async function go(options) { 53 | try { 54 | const o = document.getElementById("shims"); 55 | const cl = o.classList; 56 | cl.remove("red"); 57 | cl.add("green"); 58 | o.innerText = JSON.stringify(options || ""); 59 | } catch (_) {} 60 | 61 | window.shimPromiseResolve("shimmed"); 62 | 63 | if (window !== top) { 64 | window.optInPromiseResolve(false); 65 | return; 66 | } 67 | 68 | await sendMessageToAddon("optIn"); 69 | 70 | window.doingOptIn = true; 71 | const s = document.createElement("script"); 72 | s.src = originalUrl; 73 | s.onerror = () => window.optInPromiseResolve("error"); 74 | document.head.appendChild(s); 75 | } 76 | 77 | sendMessageToAddon("getOptions").then(options => { 78 | if (document.readyState !== "loading") { 79 | go(options); 80 | } else { 81 | window.addEventListener("DOMContentLoaded", () => { 82 | go(options); 83 | }); 84 | } 85 | }); 86 | } 87 | -------------------------------------------------------------------------------- /src/experiment-apis/aboutConfigPrefs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "aboutConfigPrefs", 4 | "description": "experimental API extension to allow access to about:config preferences", 5 | "events": [ 6 | { 7 | "name": "onPrefChange", 8 | "type": "function", 9 | "parameters": [ 10 | { 11 | "name": "name", 12 | "type": "string", 13 | "description": "The preference which changed" 14 | } 15 | ], 16 | "extraParameters": [ 17 | { 18 | "name": "name", 19 | "type": "string", 20 | "description": "The preference to monitor" 21 | } 22 | ] 23 | } 24 | ], 25 | "functions": [ 26 | { 27 | "name": "getBranch", 28 | "type": "function", 29 | "description": "Get all child prefs for a branch", 30 | "parameters": [ 31 | { 32 | "name": "branchName", 33 | "type": "string", 34 | "description": "The branch name" 35 | } 36 | ], 37 | "async": true 38 | }, 39 | { 40 | "name": "getPref", 41 | "type": "function", 42 | "description": "Get a preference's value", 43 | "parameters": [ 44 | { 45 | "name": "name", 46 | "type": "string", 47 | "description": "The preference name" 48 | } 49 | ], 50 | "async": true 51 | }, 52 | { 53 | "name": "getBoolPrefSync", 54 | "type": "function", 55 | "description": "Get a webcompat preference's boolean value synchronously", 56 | "parameters": [ 57 | { 58 | "name": "name", 59 | "type": "string", 60 | "description": "The preference name" 61 | }, 62 | { 63 | "name": "defaultValue", 64 | "type": "boolean", 65 | "optional": true, 66 | "description": "Default value to return if the pref is not set (defaults to false if omitted)" 67 | } 68 | ], 69 | "returns": { 70 | "type": "boolean", 71 | "description": "returns the value of a boolean pref." 72 | } 73 | }, 74 | { 75 | "name": "setPref", 76 | "type": "function", 77 | "description": "Set a preference's value", 78 | "parameters": [ 79 | { 80 | "name": "name", 81 | "type": "string", 82 | "description": "The preference name" 83 | }, 84 | { 85 | "name": "value", 86 | "type": "boolean", 87 | "description": "The new value" 88 | } 89 | ], 90 | "async": true 91 | } 92 | ] 93 | } 94 | ] 95 | -------------------------------------------------------------------------------- /src/shims/figshare.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1895990 - figshare login broken with dFPI enabled 9 | * 10 | * The websites that use figshare for login require unpartitioned third-party 11 | * cookie access for https://figshare.com. The figshare login process sets a 12 | * third-party cookie for https://figshare.com, which is used as an proof of 13 | * authentication on redirect back to the main site. This shim adds a request 14 | * for storage access for https://figshare.com when the user tries to log in. 15 | */ 16 | 17 | // Third-party origin we need to request storage access for. 18 | const STORAGE_ACCESS_ORIGIN = "https://figshare.com"; 19 | 20 | console.warn( 21 | `When logging in, Firefox calls the Storage Access API on behalf of the site. See https://bugzilla.mozilla.org/show_bug.cgi?id=1895990 for details.` 22 | ); 23 | 24 | document.documentElement.addEventListener( 25 | "click", 26 | e => { 27 | const { target, isTrusted } = e; 28 | if (!isTrusted) { 29 | return; 30 | } 31 | 32 | // If the user clicks the login link, we need to request storage access 33 | // for https://figshare.com. 34 | const link = target.closest(`a[href^="https://login.figshare.com"]`); 35 | if (!link) { 36 | return; 37 | } 38 | 39 | console.warn( 40 | "Calling the Storage Access API on behalf of " + STORAGE_ACCESS_ORIGIN 41 | ); 42 | 43 | e.stopPropagation(); 44 | e.preventDefault(); 45 | document.requestStorageAccessForOrigin(STORAGE_ACCESS_ORIGIN).then(() => { 46 | link.click(); 47 | }); 48 | }, 49 | true 50 | ); 51 | 52 | function watchFirefoxNotificationDialogAndHide() { 53 | const observer = new MutationObserver((mutations, obs) => { 54 | const element = document.querySelector( 55 | "div[data-alerts-channel='firefox-notifications']" 56 | ); 57 | if (element) { 58 | element.style.display = "none"; 59 | obs.disconnect(); // Stop observing once we've found and hidden the element 60 | } 61 | }); 62 | 63 | // Start observing the document. 64 | observer.observe(document.body, { 65 | childList: true, 66 | subtree: true, 67 | }); 68 | } 69 | 70 | // Hide the Firefox error notification 71 | const notificationElement = document.querySelector( 72 | "div[data-alerts-channel='firefox-notifications']" 73 | ); 74 | if (notificationElement) { 75 | notificationElement.style.display = "none"; 76 | } else { 77 | // Add a listener to watch for the Firefox notification element to load. 78 | window.addEventListener( 79 | "DOMContentLoaded", 80 | watchFirefoxNotificationDialogAndHide 81 | ); 82 | } 83 | -------------------------------------------------------------------------------- /src/shims/mochitest-shim-1.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* globals browser */ 8 | 9 | if (!window.MochitestShimPromise) { 10 | const originalUrl = 11 | "http://example.com/browser/browser/extensions/webcompat/tests/browser/shims_test.js"; 12 | 13 | const shimId = "MochitestShim"; 14 | 15 | const sendMessageToAddon = (function () { 16 | const pendingMessages = new Map(); 17 | const channel = new MessageChannel(); 18 | channel.port1.onerror = console.error; 19 | channel.port1.onmessage = event => { 20 | const { messageId, response } = event.data; 21 | const resolve = pendingMessages.get(messageId); 22 | if (resolve) { 23 | pendingMessages.delete(messageId); 24 | resolve(response); 25 | } 26 | }; 27 | function reconnect() { 28 | const detail = { 29 | pendingMessages: [...pendingMessages.values()], 30 | port: channel.port2, 31 | shimId, 32 | }; 33 | window.dispatchEvent(new CustomEvent("ShimConnects", { detail })); 34 | } 35 | window.addEventListener("ShimHelperReady", reconnect); 36 | reconnect(); 37 | return function (message) { 38 | const messageId = 39 | Math.random().toString(36).substring(2) + Date.now().toString(36); 40 | return new Promise(resolve => { 41 | const payload = { 42 | message, 43 | messageId, 44 | shimId, 45 | }; 46 | pendingMessages.set(messageId, resolve); 47 | channel.port1.postMessage(payload); 48 | }); 49 | }; 50 | })(); 51 | 52 | async function go(options) { 53 | try { 54 | const o = document.getElementById("shims"); 55 | const cl = o.classList; 56 | cl.remove("red"); 57 | cl.add("green"); 58 | o.innerText = JSON.stringify(options || ""); 59 | } catch (_) {} 60 | 61 | window.shimPromiseResolve("shimmed"); 62 | 63 | if (window !== top) { 64 | window.optInPromiseResolve(false); 65 | return; 66 | } 67 | 68 | await sendMessageToAddon("optIn"); 69 | 70 | window.doingOptIn = true; 71 | const s = document.createElement("script"); 72 | s.src = originalUrl; 73 | s.onerror = () => window.optInPromiseResolve("error"); 74 | document.head.appendChild(s); 75 | } 76 | 77 | window[`${shimId}Promise`] = new Promise(resolve => { 78 | sendMessageToAddon("getOptions").then(options => { 79 | if (document.readyState !== "loading") { 80 | resolve(go(options)); 81 | } else { 82 | window.addEventListener("DOMContentLoaded", () => { 83 | resolve(go(options)); 84 | }); 85 | } 86 | }); 87 | }); 88 | } 89 | -------------------------------------------------------------------------------- /src/shims/nielsen.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1760754 - Shim Nielsen tracker 9 | * 10 | * Sites expecting the Nielsen tracker to load properly can break if it 11 | * is blocked. This shim mitigates that breakage by loading a stand-in. 12 | */ 13 | 14 | if (!window.nol_t) { 15 | const cid = ""; 16 | 17 | let domain = ""; 18 | let schemeHost = ""; 19 | let scriptName = ""; 20 | try { 21 | const url = document?.currentScript?.src; 22 | const { pathname, protocol, host } = new URL(url); 23 | domain = host.split(".").slice(0, -2).join("."); 24 | schemeHost = `${protocol}//${host}/`; 25 | scriptName = pathname.split("/").pop(); 26 | } catch (_) {} 27 | 28 | const NolTracker = class { 29 | CONST = { 30 | max_tags: 20, 31 | }; 32 | feat = {}; 33 | globals = { 34 | cid, 35 | content: "0", 36 | defaultApidFile: "config250", 37 | defaultErrorParams: { 38 | nol_vcid: "c00", 39 | nol_clientid: "", 40 | }, 41 | domain, 42 | fpidSfCodeList: [""], 43 | init() {}, 44 | tagCurrRetry: -1, 45 | tagMaxRetry: 3, 46 | wlCurrRetry: -1, 47 | wlMaxRetry: 3, 48 | }; 49 | pmap = []; 50 | pvar = { 51 | cid, 52 | content: "0", 53 | cookies_enabled: "n", 54 | server: domain, 55 | }; 56 | scriptName = [scriptName]; 57 | version = "6.0.107"; 58 | 59 | addScript() {} 60 | catchLinkOverlay() {} 61 | clickEvent() {} 62 | clickTrack() {} 63 | do_sample() {} 64 | downloadEvent() {} 65 | eventTrack() {} 66 | filter() {} 67 | fireToUrl() {} 68 | getSchemeHost() { 69 | return schemeHost; 70 | } 71 | getVersion() {} 72 | iframe() {} 73 | in_sample() { 74 | return true; 75 | } 76 | injectBsdk() {} 77 | invite() {} 78 | linkTrack() {} 79 | mergeFeatures() {} 80 | pageEvent() {} 81 | pause() {} 82 | populateWhitelist() {} 83 | post() {} 84 | postClickTrack() {} 85 | postData() {} 86 | postEvent() {} 87 | postEventTrack() {} 88 | postLinkTrack() {} 89 | prefix() { 90 | return ""; 91 | } 92 | processDdrsSvc() {} 93 | random() {} 94 | record() { 95 | return this; 96 | } 97 | regLinkOverlay() {} 98 | regListen() {} 99 | retrieveCiFileViaCors() {} 100 | sectionEvent() {} 101 | sendALink() {} 102 | sendForm() {} 103 | sendIt() {} 104 | slideEvent() {} 105 | whitelistAssigned() {} 106 | }; 107 | 108 | window.nol_t = () => { 109 | return new NolTracker(); 110 | }; 111 | } 112 | -------------------------------------------------------------------------------- /src/shims/messengerLogin.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /* globals browser */ 8 | 9 | /** 10 | * Bug 1934814 - Messenger login broken with Total Cookie Protection 11 | * 12 | * The messenger login flow redirects to the Facebook page and then back to the 13 | * messenger page to finish the login. However, the redirect could get stuck in 14 | * the Facebook page for unknown reasons. 15 | * 16 | * This shim requests storage access for Facebook under the messenger page to 17 | * allow Facebook SSO login to work on the messenger page. So, there will be 18 | * no redirection and fix the login issue. 19 | */ 20 | 21 | console.warn( 22 | `When logging in, Firefox calls the Storage Access API on behalf of the site. See https://bugzilla.mozilla.org/show_bug.cgi?id=1934814 for details.` 23 | ); 24 | 25 | const STORAGE_ACCESS_ORIGIN = "https://www.facebook.com"; 26 | 27 | document.documentElement.addEventListener( 28 | "click", 29 | e => { 30 | const { target, isTrusted } = e; 31 | if (!isTrusted) { 32 | return; 33 | } 34 | const button = target.closest("button[id=loginbutton]"); 35 | if (!button) { 36 | return; 37 | } 38 | 39 | // We don't need to do anything if the button is not visible. When the login 40 | // button is hidden, the Facebook SSO login button is shown instead. In this 41 | // case, we don't need to do anything. 42 | if ( 43 | !button.checkVisibility({ 44 | contentVisibilityAuto: true, 45 | opacityProperty: true, 46 | visibilityProperty: true, 47 | }) 48 | ) { 49 | return; 50 | } 51 | 52 | console.warn( 53 | "Calling the Storage Access API on behalf of " + STORAGE_ACCESS_ORIGIN 54 | ); 55 | button.disabled = true; 56 | e.stopPropagation(); 57 | e.preventDefault(); 58 | document 59 | .requestStorageAccessForOrigin(STORAGE_ACCESS_ORIGIN) 60 | .then(_ => { 61 | return browser.runtime.sendMessage({ 62 | message: "checkFacebookLoginStatus", 63 | shimId: "MessengerLogin", 64 | }); 65 | }) 66 | .then(isLoggedIn => { 67 | button.disabled = false; 68 | 69 | if (!isLoggedIn) { 70 | // We need to click the login button to continue the login flow if 71 | // the user is not logged in to Facebook. 72 | button.click(); 73 | } else { 74 | // Reload the page so that the messenger page will show Facebook SSO 75 | // button instead of the login button. 76 | location.reload(); 77 | } 78 | }) 79 | .catch(() => { 80 | button.disabled = false; 81 | // Continue the login flow if the storage access is denied by clicking 82 | // the button again. 83 | button.click(); 84 | }); 85 | }, 86 | true 87 | ); 88 | -------------------------------------------------------------------------------- /src/shims/eluminate.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | /** 8 | * Bug 1606448 - Shim CoreMetrics Eluminate analytics 9 | * 10 | * Sites may rely on eluminate.js tracking in ways which cause breakage, 11 | * which has been seen on shopping sites such as Vans.com, where the 12 | * search filtering UX is broken. This shim mitigates such breakage. 13 | */ 14 | 15 | if (!window.CM_DDX) { 16 | window.CM_DDX = { 17 | domReadyFired: false, 18 | headScripts: true, 19 | dispatcherLoadRequested: false, 20 | firstPassFunctionBinding: false, 21 | BAD_PAGE_ID_ELAPSED_TIMEOUT: 5000, 22 | version: -1, 23 | standalone: false, 24 | test: { 25 | syndicate: true, 26 | testCounter: "", 27 | doTest: false, 28 | newWin: false, 29 | process: () => {}, 30 | }, 31 | partner: {}, 32 | invokeFunctionWhenAvailable: a => { 33 | a(); 34 | }, 35 | gup: _d => "", 36 | privacy: { 37 | isDoNotTrackEnabled: () => false, 38 | setDoNotTrack: () => {}, 39 | getDoNotTrack: () => false, 40 | }, 41 | setSubCookie: () => {}, 42 | }; 43 | const noopfn = () => {}; 44 | const w = window; 45 | w.cmAddShared = noopfn; 46 | w.cmCalcSKUString = noopfn; 47 | w.cmCreateManualImpressionTag = noopfn; 48 | w.cmCreateManualLinkClickTag = noopfn; 49 | w.cmCreateManualPageviewTag = noopfn; 50 | w.cmCreateOrderTag = noopfn; 51 | w.cmCreatePageviewTag = noopfn; 52 | w.cmExecuteTagQueue = noopfn; 53 | w.cmRetrieveUserID = noopfn; 54 | w.cmSetClientID = noopfn; 55 | w.cmSetCurrencyCode = noopfn; 56 | w.cmSetFirstPartyIDs = noopfn; 57 | w.cmSetSubCookie = noopfn; 58 | w.cmSetupCookieMigration = noopfn; 59 | w.cmSetupNormalization = noopfn; 60 | w.cmSetupOther = noopfn; 61 | w.cmStartTagSet = noopfn; 62 | w.cmCreateConversionEventTag = noopfn; 63 | w.cmCreateDefaultPageviewTag = noopfn; 64 | w.cmCreateElementTag = noopfn; 65 | w.cmCreateManualImpressionTag = noopfn; 66 | w.cmCreateManualLinkClickTag = noopfn; 67 | w.cmCreateManualPageviewTag = noopfn; 68 | w.cmCreatePageElementTag = noopfn; 69 | w.cmCreatePageviewTag = noopfn; 70 | w.cmCreateProductElementTag = noopfn; 71 | w.cmCreateProductviewTag = noopfn; 72 | w.cmCreateTechPropsTag = noopfn; 73 | w.cmLoadIOConfig = noopfn; 74 | w.cmSetClientID = noopfn; 75 | w.cmSetCurrencyCode = noopfn; 76 | w.cmSetFirstPartyIDs = noopfn; 77 | w.cmSetupCookieMigration = noopfn; 78 | w.cmSetupNormalization = noopfn; 79 | 80 | w.cmSetupOther = b => { 81 | for (const a in b) { 82 | window[a] = b[a]; 83 | } 84 | }; 85 | 86 | const techProps = {}; 87 | 88 | w.coremetrics = { 89 | cmLastReferencedPageID: "", 90 | cmLoad: noopfn, 91 | cmUpdateConfig: noopfn, 92 | getTechProps: () => techProps, 93 | isDef: c => typeof c !== "undefined" && c, 94 | }; 95 | } 96 | -------------------------------------------------------------------------------- /spec/helpers/content_scripts_test_helpers.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | "use strict"; 6 | 7 | // Asserts the expected parameters are passed to 8 | // scripting.registerContentScripts calls. 9 | function assertScriptingAPISpyCalls(spy) { 10 | expect(spy).toHaveBeenCalled(); 11 | for (const spyCall of spy.calls.all()) { 12 | expect(spyCall.args).toHaveSize(1); 13 | const arg = spyCall.args[0]; 14 | expect(arg).toBeInstanceOf(Array); 15 | expect(arg).toHaveSize(1); 16 | expect(arg[0]).toBeInstanceOf(Object); 17 | expect(arg[0].id).toBeInstanceOf(String); 18 | expect(arg[0].id).not.toHaveSize(0); 19 | expect(arg[0].persistAcrossSessions).toBe(false); 20 | expect(arg[0].matches).toBeInstanceOf(Array); 21 | expect(arg[0].matches).not.toHaveSize(0); 22 | arg[0].matches.forEach(match => { 23 | expect(match).toBeInstanceOf(String); 24 | }); 25 | // At least one of js or css is expected to be 26 | // a non empty array. 27 | expect(arg[0].js || arg[0].css).toBeInstanceOf(Array); 28 | expect(arg[0].js?.length || arg[0].css?.length).not.toBe(0); 29 | // Verify css and js array elements are all non empty strings. 30 | if (Array.isArray(arg[0].js)) { 31 | arg[0].js.forEach(js => { 32 | expect(js).toBeInstanceOf(String); 33 | expect(js).not.toHaveSize(0); 34 | }); 35 | } 36 | if (Array.isArray(arg[0].css)) { 37 | arg[0].css.forEach(css => { 38 | expect(css).toBeInstanceOf(String); 39 | expect(css).not.toHaveSize(0); 40 | }); 41 | } 42 | } 43 | } 44 | 45 | // Asserts the expected parameters are passed to 46 | // contentScripts.register calls. 47 | function assertContentScriptsAPISpyCalls(spy) { 48 | expect(spy).toHaveBeenCalled(); 49 | for (const spyCall of spy.calls.all()) { 50 | expect(spyCall.args).toHaveSize(1); 51 | const arg = spyCall.args[0]; 52 | expect(arg).toBeInstanceOf(Object); 53 | expect(arg.id).not.toBeDefined(); 54 | expect(arg.matches).not.toHaveSize(0); 55 | arg.matches.forEach(match => { 56 | expect(match).toBeInstanceOf(String); 57 | }); 58 | // At least one of js or css is expected to be 59 | // a non empty array. 60 | expect(arg.js || arg.css).toBeInstanceOf(Array); 61 | expect(arg.js?.length || arg.css?.length).not.toBe(0); 62 | // Verify css and js array elements are all object with a 63 | // file property set to a non-empty string. 64 | if (Array.isArray(arg.js)) { 65 | arg.js.forEach(js => { 66 | expect(js).toBeInstanceOf(Object); 67 | expect(js.file).toBeInstanceOf(String); 68 | expect(js.file).not.toHaveSize(0); 69 | }); 70 | } 71 | if (Array.isArray(arg.css)) { 72 | arg.css.forEach(css => { 73 | expect(css).toBeInstanceOf(Object); 74 | expect(css.file).toBeInstanceOf(String); 75 | expect(css.file).not.toHaveSize(0); 76 | }); 77 | } 78 | } 79 | } 80 | 81 | module.exports = { 82 | assertScriptingAPISpyCalls, 83 | assertContentScriptsAPISpyCalls, 84 | }; 85 | --------------------------------------------------------------------------------