diff options
Diffstat (limited to 'browser/extensions/webcompat/shims')
16 files changed, 1122 insertions, 0 deletions
diff --git a/browser/extensions/webcompat/shims/adsafeprotected-ima.js b/browser/extensions/webcompat/shims/adsafeprotected-ima.js new file mode 100644 index 0000000000..de273de7d8 --- /dev/null +++ b/browser/extensions/webcompat/shims/adsafeprotected-ima.js @@ -0,0 +1,69 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/** + * Bug 1508639 - Shim Ad Safe Protected's Google IMA adapter + */ + +if (!window.googleImaVansAdapter) { + const shimId = "AdSafeProtectedGoogleIMAAdapter"; + + const sendMessageToAddon = (function() { + const pendingMessages = new Map(); + const channel = new MessageChannel(); + channel.port1.onerror = console.error; + channel.port1.onmessage = event => { + const { messageId, response } = event.data; + const resolve = pendingMessages.get(messageId); + if (resolve) { + pendingMessages.delete(messageId); + resolve(response); + } + }; + function reconnect() { + const detail = { + pendingMessages: [...pendingMessages.values()], + port: channel.port2, + shimId, + }; + window.dispatchEvent(new CustomEvent("ShimConnects", { detail })); + } + window.addEventListener("ShimHelperReady", reconnect); + reconnect(); + return function(message) { + const messageId = + Math.random() + .toString(36) + .substring(2) + Date.now().toString(36); + return new Promise(resolve => { + const payload = { + message, + messageId, + shimId, + }; + pendingMessages.set(messageId, resolve); + channel.port1.postMessage(payload); + }); + }; + })(); + + window.googleImaVansAdapter = { + init: () => {}, + dispose: () => {}, + }; + + // Treat it as an opt-in when the user clicks on a video + // TODO: Improve this! It races to tell the bg script to unblock the ad from + // https://pubads.g.doubleclick.net/gampad/ads before the page loads them. + async function click(e) { + if (e.isTrusted && e.target.closest("#video-player")) { + document.documentElement.removeEventListener("click", click, true); + await sendMessageToAddon("optIn"); + // TODO: reload ima3.js? + } + } + document.documentElement.addEventListener("click", click, true); +} diff --git a/browser/extensions/webcompat/shims/bmauth.js b/browser/extensions/webcompat/shims/bmauth.js new file mode 100644 index 0000000000..944f2100d6 --- /dev/null +++ b/browser/extensions/webcompat/shims/bmauth.js @@ -0,0 +1,21 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +if (!window.BmAuth) { + window.BmAuth = { + init: () => new Promise(() => {}), + handleSignIn: () => { + // TODO: handle this properly! + }, + isAuthenticated: () => Promise.resolve(false), + addListener: () => {}, + api: { + event: { + addListener: () => {}, + }, + }, + }; +} diff --git a/browser/extensions/webcompat/shims/eluminate.js b/browser/extensions/webcompat/shims/eluminate.js new file mode 100644 index 0000000000..863d4ef2da --- /dev/null +++ b/browser/extensions/webcompat/shims/eluminate.js @@ -0,0 +1,68 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +if (!window.CM_DDX) { + window.CM_DDX = { + domReadyFired: false, + headScripts: true, + dispatcherLoadRequested: false, + firstPassFunctionBinding: false, + BAD_PAGE_ID_ELAPSED_TIMEOUT: 5000, + version: -1, + standalone: false, + test: { + syndicate: true, + testCounter: "", + doTest: false, + newWin: false, + process: () => {}, + }, + partner: {}, + invokeFunctionWhenAvailable: a => { + a(); + }, + gup: d => "", + privacy: { + isDoNotTrackEnabled: () => false, + setDoNotTrack: () => {}, + getDoNotTrack: () => false, + }, + setSubCookie: () => {}, + }; + + const noopfn = () => {}; + const w = window; + w.cmAddShared = noopfn; + w.cmCalcSKUString = noopfn; + w.cmCreateManualImpressionTag = noopfn; + w.cmCreateManualLinkClickTag = noopfn; + w.cmCreateManualPageviewTag = noopfn; + w.cmCreateOrderTag = noopfn; + w.cmCreatePageviewTag = noopfn; + w.cmRetrieveUserID = noopfn; + w.cmSetClientID = noopfn; + w.cmSetCurrencyCode = noopfn; + w.cmSetFirstPartyIDs = noopfn; + w.cmSetSubCookie = noopfn; + w.cmSetupCookieMigration = noopfn; + w.cmSetupNormalization = noopfn; + w.cmSetupOther = noopfn; + w.cmStartTagSet = noopfn; + + function cmExecuteTagQueue() { + var b = window.cmTagQueue; + if (b) { + if (!Array.isArray(b)) { + return undefined; + } + for (var a = 0; a < b.length; ++a) { + window[b[a][0]].apply(window, b[a].slice(1)); + } + } + return true; + } + cmExecuteTagQueue(); +} diff --git a/browser/extensions/webcompat/shims/empty-script.js b/browser/extensions/webcompat/shims/empty-script.js new file mode 100644 index 0000000000..d01f2ab537 --- /dev/null +++ b/browser/extensions/webcompat/shims/empty-script.js @@ -0,0 +1,5 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* This script is intentionally empty */ diff --git a/browser/extensions/webcompat/shims/facebook-sdk.js b/browser/extensions/webcompat/shims/facebook-sdk.js new file mode 100644 index 0000000000..95928be857 --- /dev/null +++ b/browser/extensions/webcompat/shims/facebook-sdk.js @@ -0,0 +1,198 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/** + * Bug 1226498 - Shim Facebook SDK + * + * The Facebook SDK is commonly used by sites to allow users to authenticate + * for logins, but it is blocked by strict tracking protection. It is possible + * to shim the SDK and allow users to still opt into logging in via Facebook. + * It is also possible to replace any Facebook widgets or comments with + * placeholders that the user may click to opt into loading the content. + */ + +if (!window.FB) { + const originalUrl = document.currentScript.src; + const pendingParses = []; + + function getGUID() { + return ( + Math.random() + .toString(36) + .substring(2) + Date.now().toString(36) + ); + } + + const shimId = "FacebookSDK"; + + const sendMessageToAddon = (function() { + const pendingMessages = new Map(); + const channel = new MessageChannel(); + channel.port1.onerror = console.error; + channel.port1.onmessage = event => { + const { messageId, response } = event.data; + const resolve = pendingMessages.get(messageId); + if (resolve) { + pendingMessages.delete(messageId); + resolve(response); + } + }; + function reconnect() { + const detail = { + pendingMessages: [...pendingMessages.values()], + port: channel.port2, + shimId, + }; + window.dispatchEvent(new CustomEvent("ShimConnects", { detail })); + } + window.addEventListener("ShimHelperReady", reconnect); + reconnect(); + return function(message) { + const messageId = getGUID(); + return new Promise(resolve => { + const payload = { + message, + messageId, + shimId, + }; + pendingMessages.set(messageId, resolve); + channel.port1.postMessage(payload); + }); + }; + })(); + + let ready = false; + let initInfo; + const needPopup = + !/app_runner/.test(window.name) && !/iframe_canvas/.test(window.name); + const popupName = getGUID(); + + if (needPopup) { + const oldWindowOpen = window.open; + window.open = function(href, name, params) { + try { + const url = new URL(href); + if ( + url.protocol === "https:" && + (url.hostname === "m.facebook.com" || + url.hostname === "www.facebook.com") && + url.pathname.endsWith("/oauth") + ) { + name = popupName; + } + } catch (_) {} + return oldWindowOpen.call(window, href, name, params); + }; + } + + async function allowFacebookSDK(callback) { + await sendMessageToAddon("optIn"); + + window.FB = undefined; + const oldInit = window.fbAsyncInit; + window.fbAsyncInit = () => { + ready = true; + if (typeof initInfo !== "undefined") { + window.FB.init(initInfo); + } else if (oldInit) { + oldInit(); + } + if (callback) { + callback(); + } + }; + + const s = document.createElement("script"); + s.src = originalUrl; + await new Promise((resolve, reject) => { + s.onerror = reject; + s.onload = function() { + for (const args of pendingParses) { + window.FB.XFBML.parse.apply(window.FB.XFBML, args); + } + resolve(); + }; + document.head.appendChild(s); + }); + } + + function buildPopupParams() { + const { outerWidth, outerHeight, screenX, screenY } = window; + const { width, height } = window.screen; + const w = Math.min(width, 400); + const h = Math.min(height, 400); + const ua = navigator.userAgent; + const isMobile = ua.includes("Mobile") || ua.includes("Tablet"); + const left = screenX + (screenX < 0 ? width : 0) + (outerWidth - w) / 2; + const top = screenY + (screenY < 0 ? height : 0) + (outerHeight - h) / 2.5; + let params = `left=${left},top=${top},width=${w},height=${h},scrollbars=1,toolbar=0,location=1`; + if (!isMobile) { + params = `${params},width=${w},height=${h}`; + } + return params; + } + + async function doLogin(a, b) { + window.FB.login(a, b); + } + + function proxy(name, fn) { + return function() { + if (ready) { + return window.FB[name].apply(this, arguments); + } + return fn.apply(this, arguments); + }; + } + + window.FB = { + api: proxy("api", () => {}), + AppEvents: { + EventNames: {}, + logPageView: () => {}, + }, + Event: { + subscribe: () => {}, + }, + getAccessToken: proxy("getAccessToken", () => null), + getAuthResponse: proxy("getAuthResponse", () => { + return { status: "" }; + }), + getLoginStatus: proxy("getLoginStatus", cb => { + cb({ status: "" }); + }), + getUserID: proxy("getUserID", () => {}), + init: _initInfo => { + if (ready) { + doLogin(_initInfo); + } else { + initInfo = _initInfo; // in case the site is not using fbAsyncInit + } + }, + login: (a, b) => { + // We have to load Facebook's script, and then wait for it to call + // window.open. By that time, the popup blocker will likely trigger. + // So we open a popup now with about:blank, and then make sure FB + // will re-use that same popup later. + if (needPopup) { + window.open("about:blank", popupName, buildPopupParams()); + } + allowFacebookSDK(() => { + doLogin(a, b); + }); + }, + logout: proxy("logout", cb => cb()), + XFBML: { + parse: e => { + pendingParses.push([e]); + }, + }, + }; + + if (window.fbAsyncInit) { + window.fbAsyncInit(); + } +} diff --git a/browser/extensions/webcompat/shims/google-analytics-ecommerce-plugin.js b/browser/extensions/webcompat/shims/google-analytics-ecommerce-plugin.js new file mode 100644 index 0000000000..60b49df120 --- /dev/null +++ b/browser/extensions/webcompat/shims/google-analytics-ecommerce-plugin.js @@ -0,0 +1,13 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +if (!window.gaplugins) { + window.gaplugins = {}; +} + +if (!window.gaplugins.EC) { + window.gaplugins.EC = () => {}; +} diff --git a/browser/extensions/webcompat/shims/google-analytics-legacy.js b/browser/extensions/webcompat/shims/google-analytics-legacy.js new file mode 100644 index 0000000000..056186f75c --- /dev/null +++ b/browser/extensions/webcompat/shims/google-analytics-legacy.js @@ -0,0 +1,133 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// based on https://github.com/gorhill/uBlock/blob/caa8e7d35ba61214a9d13e7d324b2bd2aa73237f/src/web_accessible_resources/google-analytics_ga.js + +"use strict"; + +if (!window._gaq) { + function noopfn() {} + + const gaq = { + Na: noopfn, + O: noopfn, + Sa: noopfn, + Ta: noopfn, + Va: noopfn, + _createAsyncTracker: noopfn, + _getAsyncTracker: noopfn, + _getPlugin: noopfn, + push: a => { + if (typeof a === "function") { + a(); + return; + } + if (!Array.isArray(a)) { + return; + } + if (a[0] === "_link" && typeof a[1] === "string") { + window.location.assign(a[1]); + } + if ( + a[0] === "_set" && + a[1] === "hitCallback" && + typeof a[2] === "function" + ) { + a[2](); + } + }, + }; + + const tracker = { + _addIgnoredOrganic: noopfn, + _addIgnoredRef: noopfn, + _addItem: noopfn, + _addOrganic: noopfn, + _addTrans: noopfn, + _clearIgnoredOrganic: noopfn, + _clearIgnoredRef: noopfn, + _clearOrganic: noopfn, + _cookiePathCopy: noopfn, + _deleteCustomVar: noopfn, + _getName: noopfn, + _setAccount: noopfn, + _getAccount: noopfn, + _getClientInfo: noopfn, + _getDetectFlash: noopfn, + _getDetectTitle: noopfn, + _getLinkerUrl: a => a, + _getLocalGifPath: noopfn, + _getServiceMode: noopfn, + _getVersion: noopfn, + _getVisitorCustomVar: noopfn, + _initData: noopfn, + _link: noopfn, + _linkByPost: noopfn, + _setAllowAnchor: noopfn, + _setAllowHash: noopfn, + _setAllowLinker: noopfn, + _setCampContentKey: noopfn, + _setCampMediumKey: noopfn, + _setCampNameKey: noopfn, + _setCampNOKey: noopfn, + _setCampSourceKey: noopfn, + _setCampTermKey: noopfn, + _setCampaignCookieTimeout: noopfn, + _setCampaignTrack: noopfn, + _setClientInfo: noopfn, + _setCookiePath: noopfn, + _setCookiePersistence: noopfn, + _setCookieTimeout: noopfn, + _setCustomVar: noopfn, + _setDetectFlash: noopfn, + _setDetectTitle: noopfn, + _setDomainName: noopfn, + _setLocalGifPath: noopfn, + _setLocalRemoteServerMode: noopfn, + _setLocalServerMode: noopfn, + _setReferrerOverride: noopfn, + _setRemoteServerMode: noopfn, + _setSampleRate: noopfn, + _setSessionTimeout: noopfn, + _setSiteSpeedSampleRate: noopfn, + _setSessionCookieTimeout: noopfn, + _setVar: noopfn, + _setVisitorCookieTimeout: noopfn, + _trackEvent: noopfn, + _trackPageLoadTime: noopfn, + _trackPageview: noopfn, + _trackSocial: noopfn, + _trackTiming: noopfn, + _trackTrans: noopfn, + _visitCode: noopfn, + }; + + const gat = { + _anonymizeIP: noopfn, + _createTracker: noopfn, + _forceSSL: noopfn, + _getPlugin: noopfn, + _getTracker: () => tracker, + _getTrackerByName: () => tracker, + _getTrackers: noopfn, + aa: noopfn, + ab: noopfn, + hb: noopfn, + la: noopfn, + oa: noopfn, + pa: noopfn, + u: noopfn, + }; + + window._gat = gat; + + const aa = window._gaq || []; + if (Array.isArray(aa)) { + while (aa[0]) { + gaq.push(aa.shift()); + } + } + + window._gaq = gaq.qf = gaq; +} diff --git a/browser/extensions/webcompat/shims/google-analytics-tag-manager.js b/browser/extensions/webcompat/shims/google-analytics-tag-manager.js new file mode 100644 index 0000000000..b8398f91b6 --- /dev/null +++ b/browser/extensions/webcompat/shims/google-analytics-tag-manager.js @@ -0,0 +1,24 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// based on https://github.com/gorhill/uBlock/blob/caa8e7d35ba61214a9d13e7d324b2bd2aa73237f/src/web_accessible_resources/googletagmanager_gtm.js + +"use strict"; + +if (!window.ga) { + window.ga = () => {}; + + try { + window.dataLayer.hide.end(); + } catch (_) {} + + const dl = window.dataLayer; + if (typeof dl.push === "function") { + dl.push = o => { + if (o instanceof Object && typeof o.eventCallback === "function") { + setTimeout(o.eventCallback, 1); + } + }; + } +} diff --git a/browser/extensions/webcompat/shims/google-analytics.js b/browser/extensions/webcompat/shims/google-analytics.js new file mode 100644 index 0000000000..f0162b1f63 --- /dev/null +++ b/browser/extensions/webcompat/shims/google-analytics.js @@ -0,0 +1,45 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// based on https://github.com/gorhill/uBlock/blob/8a1a8b103f56e4fcef1264e02dfd718a29bda006/src/web_accessible_resources/google-analytics_analytics.js + +"use strict"; + +if (!window[window.GoogleAnalyticsObject || "ga"]) { + function ga() { + const len = arguments.length; + if (!len) { + return; + } + const args = Array.from(arguments); + let fn; + let a = args[len - 1]; + if (a instanceof Object && a.hitCallback instanceof Function) { + fn = a.hitCallback; + } else { + const pos = args.indexOf("hitCallback"); + if (pos !== -1 && args[pos + 1] instanceof Function) { + fn = args[pos + 1]; + } + } + if (!(fn instanceof Function)) { + return; + } + try { + fn(); + } catch (_) {} + } + ga.create = () => {}; + ga.getByName = () => null; + ga.getAll = () => []; + ga.remove = () => {}; + ga.loaded = true; + + const gaName = window.GoogleAnalyticsObject || "ga"; + window[gaName] = ga; +} + +try { + window.dataLayer.hide.end(); +} catch (_) {} diff --git a/browser/extensions/webcompat/shims/google-publisher-tags.js b/browser/extensions/webcompat/shims/google-publisher-tags.js new file mode 100644 index 0000000000..756e29bac5 --- /dev/null +++ b/browser/extensions/webcompat/shims/google-publisher-tags.js @@ -0,0 +1,163 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/** + * Bug 1600538 - Shim Google Publisher Tags + */ + +"use strict"; + +if (!window.googletag?.apiReady) { + const noopfn = function() {}; + const noopthisfn = function() { + return this; + }; + const noopnullfn = function() { + return null; + }; + const nooparrayfn = function() { + return []; + }; + const noopstrfn = function() { + return ""; + }; + + function newPassbackSlot() { + return { + display: noopfn, + get: noopnullfn, + set: noopthisfn, + setClickUrl: noopthisfn, + setTagForChildDirectedTreatment: noopthisfn, + setTargeting: noopthisfn, + updateTargetingFromMap: noopthisfn, + }; + } + + function display(id) { + const parent = document.getElementById(id); + if (parent) { + parent.appendChild(document.createElement("div")); + } + } + + const companionAdsService = { + addEventListener: noopthisfn, + enableSyncLoading: noopfn, + setRefreshUnfilledSlots: noopfn, + }; + + const contentService = { + addEventListener: noopthisfn, + setContent: noopfn, + }; + + const pubadsService = { + addEventListener: noopthisfn, + clear: noopfn, + clearCategoryExclusions: noopthisfn, + clearTagForChildDirectedTreatment: noopthisfn, + clearTargeting: noopthisfn, + collapseEmptyDivs: noopfn, + defineOutOfPagePassback: () => newPassbackSlot(), + definePassback: () => newPassbackSlot(), + disableInitialLoad: noopfn, + display, + enableAsyncRendering: noopfn, + enableSingleRequest: noopfn, + enableSyncRendering: noopfn, + enableVideoAds: noopfn, + get: noopnullfn, + getAttributeKeys: nooparrayfn, + getTargeting: noopfn, + getTargetingKeys: nooparrayfn, + getSlots: nooparrayfn, + refresh: noopfn, + set: noopthisfn, + setCategoryExclusion: noopthisfn, + setCentering: noopfn, + setCookieOptions: noopthisfn, + setForceSafeFrame: noopthisfn, + setLocation: noopthisfn, + setPublisherProvidedId: noopthisfn, + setRequestNonPersonalizedAds: noopthisfn, + setSafeFrameConfig: noopthisfn, + setTagForChildDirectedTreatment: noopthisfn, + setTargeting: noopthisfn, + setVideoContent: noopthisfn, + updateCorrelator: noopfn, + }; + + function newSizeMappingBuilder() { + return { + addSize: noopthisfn, + build: noopnullfn, + }; + } + + function newSlot() { + return { + addService: noopthisfn, + clearCategoryExclusions: noopthisfn, + clearTargeting: noopthisfn, + defineSizeMapping: noopthisfn, + get: noopnullfn, + getAdUnitPath: nooparrayfn, + getAttributeKeys: nooparrayfn, + getCategoryExclusions: nooparrayfn, + getDomId: noopstrfn, + getSlotElementId: noopstrfn, + getSlotId: noopthisfn, + getTargeting: nooparrayfn, + getTargetingKeys: nooparrayfn, + set: noopthisfn, + setCategoryExclusion: noopthisfn, + setClickUrl: noopthisfn, + setCollapseEmptyDiv: noopthisfn, + setTargeting: noopthisfn, + }; + } + + let gt = window.googletag; + if (!gt) { + gt = window.googletag = {}; + } + + for (const [key, value] of Object.entries({ + apiReady: true, + companionAds: () => companionAdsService, + content: () => contentService, + defineOutOfPageSlot: () => newSlot(), + defineSlot: () => newSlot(), + destroySlots: noopfn, + disablePublisherConsole: noopfn, + display, + enableServices: noopfn, + getVersion: noopstrfn, + pubads: () => pubadsService, + pubabsReady: true, + setAdIframeTitle: noopfn, + sizeMapping: () => newSizeMappingBuilder(), + })) { + gt[key] = value; + } + + function runCmd(fn) { + try { + fn(); + } catch (_) {} + return 1; + } + + const cmds = gt.cmd; + const newCmd = []; + newCmd.push = runCmd; + gt.cmd = newCmd; + + for (const cmd of cmds) { + runCmd(cmd); + } +} diff --git a/browser/extensions/webcompat/shims/live-test-shim.js b/browser/extensions/webcompat/shims/live-test-shim.js new file mode 100644 index 0000000000..552020820f --- /dev/null +++ b/browser/extensions/webcompat/shims/live-test-shim.js @@ -0,0 +1,84 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/* globals browser */ + +if (!window.LiveTestShimPromise) { + const originalUrl = document.currentScript.src; + + const shimId = "LiveTestShim"; + + const sendMessageToAddon = (function() { + const pendingMessages = new Map(); + const channel = new MessageChannel(); + channel.port1.onerror = console.error; + channel.port1.onmessage = event => { + const { messageId, response } = event.data; + const resolve = pendingMessages.get(messageId); + if (resolve) { + pendingMessages.delete(messageId); + resolve(response); + } + }; + function reconnect() { + const detail = { + pendingMessages: [...pendingMessages.values()], + port: channel.port2, + shimId, + }; + window.dispatchEvent(new CustomEvent("ShimConnects", { detail })); + } + window.addEventListener("ShimHelperReady", reconnect); + reconnect(); + return function(message) { + const messageId = + Math.random() + .toString(36) + .substring(2) + Date.now().toString(36); + return new Promise(resolve => { + const payload = { + message, + messageId, + shimId, + }; + pendingMessages.set(messageId, resolve); + channel.port1.postMessage(payload); + }); + }; + })(); + + async function go(options) { + try { + const o = document.getElementById("shims"); + const cl = o.classList; + cl.remove("red"); + cl.add("green"); + o.innerText = JSON.stringify(options || ""); + } catch (_) {} + + if (window !== top) { + return; + } + + await sendMessageToAddon("optIn"); + + const s = document.createElement("script"); + s.src = originalUrl; + document.head.appendChild(s); + } + + window[`${shimId}Promise`] = sendMessageToAddon("getOptions").then( + options => { + if (document.readyState !== "loading") { + go(options); + } else { + window.addEventListener("DOMContentLoaded", () => { + go(options); + }); + } + } + ); +} diff --git a/browser/extensions/webcompat/shims/mochitest-shim-1.js b/browser/extensions/webcompat/shims/mochitest-shim-1.js new file mode 100644 index 0000000000..d18e965f3c --- /dev/null +++ b/browser/extensions/webcompat/shims/mochitest-shim-1.js @@ -0,0 +1,89 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/* globals browser */ + +if (!window.MochitestShimPromise) { + const originalUrl = document.currentScript.src; + + const shimId = "MochitestShim"; + + const sendMessageToAddon = (function() { + const pendingMessages = new Map(); + const channel = new MessageChannel(); + channel.port1.onerror = console.error; + channel.port1.onmessage = event => { + const { messageId, response } = event.data; + const resolve = pendingMessages.get(messageId); + if (resolve) { + pendingMessages.delete(messageId); + resolve(response); + } + }; + function reconnect() { + const detail = { + pendingMessages: [...pendingMessages.values()], + port: channel.port2, + shimId, + }; + window.dispatchEvent(new CustomEvent("ShimConnects", { detail })); + } + window.addEventListener("ShimHelperReady", reconnect); + reconnect(); + return function(message) { + const messageId = + Math.random() + .toString(36) + .substring(2) + Date.now().toString(36); + return new Promise(resolve => { + const payload = { + message, + messageId, + shimId, + }; + pendingMessages.set(messageId, resolve); + channel.port1.postMessage(payload); + }); + }; + })(); + + async function go(options) { + try { + const o = document.getElementById("shims"); + const cl = o.classList; + cl.remove("red"); + cl.add("green"); + o.innerText = JSON.stringify(options || ""); + } catch (_) {} + + window.shimPromiseResolve("shimmed"); + + if (window !== top) { + window.optInPromiseResolve(false); + return; + } + + await sendMessageToAddon("optIn"); + + window.doingOptIn = true; + const s = document.createElement("script"); + s.src = originalUrl; + s.onerror = () => window.optInPromiseResolve("error"); + document.head.appendChild(s); + } + + window[`${shimId}Promise`] = new Promise(resolve => { + sendMessageToAddon("getOptions").then(options => { + if (document.readyState !== "loading") { + resolve(go(options)); + } else { + window.addEventListener("DOMContentLoaded", () => { + resolve(go(options)); + }); + } + }); + }); +} diff --git a/browser/extensions/webcompat/shims/mochitest-shim-2.js b/browser/extensions/webcompat/shims/mochitest-shim-2.js new file mode 100644 index 0000000000..3b60038599 --- /dev/null +++ b/browser/extensions/webcompat/shims/mochitest-shim-2.js @@ -0,0 +1,87 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/* globals browser */ + +if (!window.testPromise) { + const originalUrl = document.currentScript.src; + + const shimId = "MochitestShim2"; + + const sendMessageToAddon = (function() { + const pendingMessages = new Map(); + const channel = new MessageChannel(); + channel.port1.onerror = console.error; + channel.port1.onmessage = event => { + const { messageId, response } = event.data; + const resolve = pendingMessages.get(messageId); + if (resolve) { + pendingMessages.delete(messageId); + resolve(response); + } + }; + function reconnect() { + const detail = { + pendingMessages: [...pendingMessages.values()], + port: channel.port2, + shimId, + }; + window.dispatchEvent(new CustomEvent("ShimConnects", { detail })); + } + window.addEventListener("ShimHelperReady", reconnect); + reconnect(); + return function(message) { + const messageId = + Math.random() + .toString(36) + .substring(2) + Date.now().toString(36); + return new Promise(resolve => { + const payload = { + message, + messageId, + shimId, + }; + pendingMessages.set(messageId, resolve); + channel.port1.postMessage(payload); + }); + }; + })(); + + async function go(options) { + try { + const o = document.getElementById("shims"); + const cl = o.classList; + cl.remove("red"); + cl.add("green"); + o.innerText = JSON.stringify(options || ""); + } catch (_) {} + + window.shimPromiseResolve("shimmed"); + + if (window !== top) { + window.optInPromiseResolve(false); + return; + } + + await sendMessageToAddon("optIn"); + + window.doingOptIn = true; + const s = document.createElement("script"); + s.src = originalUrl; + s.onerror = () => window.optInPromiseResolve("error"); + document.head.appendChild(s); + } + + sendMessageToAddon("getOptions").then(options => { + if (document.readyState !== "loading") { + go(options); + } else { + window.addEventListener("DOMContentLoaded", () => { + go(options); + }); + } + }); +} diff --git a/browser/extensions/webcompat/shims/mochitest-shim-3.js b/browser/extensions/webcompat/shims/mochitest-shim-3.js new file mode 100644 index 0000000000..dc0a8005f5 --- /dev/null +++ b/browser/extensions/webcompat/shims/mochitest-shim-3.js @@ -0,0 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +window.shimPromiseResolve("shimmed"); diff --git a/browser/extensions/webcompat/shims/rambler-authenticator.js b/browser/extensions/webcompat/shims/rambler-authenticator.js new file mode 100644 index 0000000000..0554eabc2c --- /dev/null +++ b/browser/extensions/webcompat/shims/rambler-authenticator.js @@ -0,0 +1,86 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +if (!window.ramblerIdHelper) { + const originalScript = document.currentScript.src; + + const sendMessageToAddon = (function() { + const shimId = "Rambler"; + const pendingMessages = new Map(); + const channel = new MessageChannel(); + channel.port1.onerror = console.error; + channel.port1.onmessage = event => { + const { messageId, response } = event.data; + const resolve = pendingMessages.get(messageId); + if (resolve) { + pendingMessages.delete(messageId); + resolve(response); + } + }; + function reconnect() { + const detail = { + pendingMessages: [...pendingMessages.values()], + port: channel.port2, + shimId, + }; + window.dispatchEvent(new CustomEvent("ShimConnects", { detail })); + } + window.addEventListener("ShimHelperReady", reconnect); + reconnect(); + return function(message) { + const messageId = + Math.random() + .toString(36) + .substring(2) + Date.now().toString(36); + return new Promise(resolve => { + const payload = { + message, + messageId, + shimId, + }; + pendingMessages.set(messageId, resolve); + channel.port1.postMessage(payload); + }); + }; + })(); + + const ramblerIdHelper = { + getProfileInfo: (successCallback, errorCallback) => { + successCallback({}); + }, + openAuth: () => { + sendMessageToAddon("optIn").then(function() { + const openAuthArgs = arguments; + window.ramblerIdHelper = undefined; + const s = document.createElement("script"); + s.src = originalScript; + document.head.appendChild(s); + s.addEventListener("load", () => { + const helper = window.ramblerIdHelper; + for (const { fn, args } of callLog) { + helper[fn].apply(helper, args); + } + helper.openAuth.apply(helper, openAuthArgs); + }); + }); + }, + }; + + const callLog = []; + function addLoggedCall(fn) { + ramblerIdHelper[fn] = () => { + callLog.push({ fn, args: arguments }); + }; + } + + addLoggedCall("registerOnFrameCloseCallback"); + addLoggedCall("registerOnFrameRedirect"); + addLoggedCall("registerOnPossibleLoginCallback"); + addLoggedCall("registerOnPossibleLogoutCallback"); + addLoggedCall("registerOnPossibleOauthLoginCallback"); + + window.ramblerIdHelper = ramblerIdHelper; +} diff --git a/browser/extensions/webcompat/shims/rich-relevance.js b/browser/extensions/webcompat/shims/rich-relevance.js new file mode 100644 index 0000000000..d7f2802ac9 --- /dev/null +++ b/browser/extensions/webcompat/shims/rich-relevance.js @@ -0,0 +1,30 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/** + * Bug 1449347 - Rich Relevance + */ + +"use strict"; + +if (!window.r3_common) { + const noopfn = () => {}; + + window.rr_flush_onload = noopfn; + window.r3 = noopfn; + window.r3_home = noopfn; + window.RR = noopfn; + window.r3_common = function() {}; + window.r3_common.prototype = { + addContext: noopfn, + addPlacementType: noopfn, + setUserId: noopfn, + setSessionId: noopfn, + setClickthruServer: noopfn, + setBaseUrl: noopfn, + setApiKey: noopfn, + }; +} |