UNPKG

@eyeo/snippets

Version:

eye/o snippets for Ads blocker

1,684 lines (1,405 loc) 97.7 kB
(environment, ...filters) => { /*! * This file is part of eyeo's Anti-Circumvention Snippets module (@eyeo/snippets), * Copyright (C) 2006-present eyeo GmbH * * @eyeo/snippets is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * @eyeo/snippets is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with @eyeo/snippets. If not, see <http://www.gnu.org/licenses/>. */ const $$1 = Proxy; const {apply: a, bind: b, call: c} = Function; const apply$2 = c.bind(a); const bind = c.bind(b); const call = c.bind(c); const callerHandler = { get(target, name) { return bind(c, target[name]); } }; const caller = target => new $$1(target, callerHandler); const proxy = (source, target) => new $$1(source, { apply: (_, self, args) => apply$2(target, self, args) }); const handler$2 = { get(target, name) { return bind(target[name], target); } }; const bound = target => new $$1(target, handler$2); const { assign: assign$1, defineProperties: defineProperties$1, freeze: freeze$1, getOwnPropertyDescriptor: getOwnPropertyDescriptor$3, getOwnPropertyDescriptors: getOwnPropertyDescriptors$1, getPrototypeOf } = bound(Object); const {hasOwnProperty} = caller({}); const {species} = Symbol; const handler$1 = { get(target, name) { const Native = target[name]; class Secure extends Native {} const proto = getOwnPropertyDescriptors$1(Native.prototype); delete proto.constructor; freeze$1(defineProperties$1(Secure.prototype, proto)); const statics = getOwnPropertyDescriptors$1(Native); delete statics.length; delete statics.prototype; statics[species] = {value: Secure}; return freeze$1(defineProperties$1(Secure, statics)); } }; const secure = target => new $$1(target, handler$1); const libEnvironment = typeof environment !== "undefined" ? environment : {}; if (typeof globalThis === "undefined") window.globalThis = window; const {apply: apply$1, ownKeys} = bound(Reflect); const worldEnvDefined = "world" in libEnvironment; const isIsolatedWorld = worldEnvDefined && libEnvironment.world === "ISOLATED"; const isMainWorld = worldEnvDefined && libEnvironment.world === "MAIN"; const chromeObjAvailable = typeof chrome === "object" && !!chrome.runtime; const browserObjAvailable = typeof browser === "object" && !!browser.runtime; const isExtensionContext$2 = !isMainWorld && (isIsolatedWorld || chromeObjAvailable || browserObjAvailable); const copyIfExtension = value => isExtensionContext$2 ? value : create(value, getOwnPropertyDescriptors(value)); const { create, defineProperties, defineProperty, freeze, getOwnPropertyDescriptor: getOwnPropertyDescriptor$2, getOwnPropertyDescriptors } = bound(Object); const invokes = bound(globalThis); const classes = isExtensionContext$2 ? globalThis : secure(globalThis); const {Map: Map$c, RegExp: RegExp$3, Set: Set$3, WeakMap: WeakMap$6, WeakSet: WeakSet$4} = classes; const augment = (source, target, method = null) => { const known = ownKeys(target); for (const key of ownKeys(source)) { if (known.includes(key)) continue; const descriptor = getOwnPropertyDescriptor$2(source, key); if (method && "value" in descriptor) { const {value} = descriptor; if (typeof value === "function") descriptor.value = method(value); } defineProperty(target, key, descriptor); } }; const primitive = name => { const Super = classes[name]; class Class extends Super {} const {toString, valueOf} = Super.prototype; defineProperties(Class.prototype, { toString: {value: toString}, valueOf: {value: valueOf} }); const type = name.toLowerCase(); const method = callback => function() { const result = apply$1(callback, this, arguments); return typeof result === type ? new Class(result) : result; }; augment(Super, Class, method); augment(Super.prototype, Class.prototype, method); return Class; }; const variables$3 = freeze({ frozen: new WeakMap$6(), hidden: new WeakSet$4(), iframePropertiesToAbort: { read: new Set$3(), write: new Set$3() }, abortedIframes: new WeakMap$6() }); const startsCapitalized = new RegExp$3("^[A-Z]"); const extensionApi = ( isExtensionContext$2 && ( (chromeObjAvailable && chrome) || (browserObjAvailable && browser) ) ) || void 0; var env = new Proxy(new Map$c([ ["chrome", extensionApi], ["browser", extensionApi], ["isExtensionContext", isExtensionContext$2], ["variables", variables$3], ["console", copyIfExtension(console)], ["document", globalThis.document], ["JSON", copyIfExtension(JSON)], ["Map", Map$c], ["Math", copyIfExtension(Math)], ["Number", isExtensionContext$2 ? Number : primitive("Number")], ["RegExp", RegExp$3], ["Set", Set$3], ["String", isExtensionContext$2 ? String : primitive("String")], ["WeakMap", WeakMap$6], ["WeakSet", WeakSet$4], ["MouseEvent", MouseEvent] ]), { get(map, key) { if (map.has(key)) return map.get(key); let value = globalThis[key]; if (typeof value === "function") value = (startsCapitalized.test(key) ? classes : invokes)[key]; map.set(key, value); return value; }, has(map, key) { return map.has(key); } }); class WeakValue { has() { return false; } set() {} } const helpers = {WeakSet, WeakMap, WeakValue}; const {apply} = Reflect; function transformOnce (callback) { const {WeakSet, WeakMap, WeakValue} = (this || helpers); const ws = new WeakSet; const wm = new WeakMap; const wv = new WeakValue; return function (any) { if (ws.has(any)) return any; if (wm.has(any)) return wm.get(any); if (wv.has(any)) return wv.get(any); const value = apply(callback, this, arguments); ws.add(value); if (value !== any) (typeof any === 'object' && any ? wm : wv).set(any, value); return value; }; } const {Map: Map$b, WeakMap: WeakMap$5, WeakSet: WeakSet$3, setTimeout} = env; let cleanup = true; let cleanUpCallback = map => { map.clear(); cleanup = !cleanup; }; var transformer = transformOnce.bind({ WeakMap: WeakMap$5, WeakSet: WeakSet$3, WeakValue: class extends Map$b { set(key, value) { if (cleanup) { cleanup = !cleanup; setTimeout(cleanUpCallback, 0, this); } return super.set(key, value); } } }); const {concat, includes, join, reduce, unshift} = caller([]); const globals = secure(globalThis); const { Map: Map$a, WeakMap: WeakMap$4 } = globals; const map = new Map$a; const descriptors = target => { const chain = []; let current = target; while (current) { if (map.has(current)) unshift(chain, map.get(current)); else { const descriptors = getOwnPropertyDescriptors$1(current); map.set(current, descriptors); unshift(chain, descriptors); } current = getPrototypeOf(current); } unshift(chain, {}); return apply$2(assign$1, null, chain); }; const chain = source => { const target = typeof source === 'function' ? source.prototype : source; const chained = descriptors(target); const handler = { get(target, key) { if (key in chained) { const {value, get} = chained[key]; if (get) return call(get, target); if (typeof value === 'function') return bind(value, target); } return target[key]; }, set(target, key, value) { if (key in chained) { const {set} = chained[key]; if (set) { call(set, target, value); return true; } } target[key] = value; return true; } }; return target => new $$1(target, handler); }; const { isExtensionContext: isExtensionContext$1, Array: Array$7, Number: Number$1, String: String$1, Object: Object$e } = env; const {isArray} = Array$7; const {getOwnPropertyDescriptor: getOwnPropertyDescriptor$1, setPrototypeOf: setPrototypeOf$1} = Object$e; const {toString: toString$1} = Object$e.prototype; const {slice} = String$1.prototype; const getBrand = value => call(slice, call(toString$1, value), 8, -1); const {get: nodeType} = getOwnPropertyDescriptor$1(Node.prototype, "nodeType"); const chained = isExtensionContext$1 ? {} : { Attr: chain(Attr), CanvasRenderingContext2D: chain(CanvasRenderingContext2D), CSSStyleDeclaration: chain(CSSStyleDeclaration), Document: chain(Document), Element: chain(Element), HTMLCanvasElement: chain(HTMLCanvasElement), HTMLElement: chain(HTMLElement), HTMLImageElement: chain(HTMLImageElement), HTMLScriptElement: chain(HTMLScriptElement), MutationRecord: chain(MutationRecord), Node: chain(Node), ShadowRoot: chain(ShadowRoot), get CSS2Properties() { return chained.CSSStyleDeclaration; } }; const upgrade = (value, hint) => { if (hint !== "Element" && hint in chained) return chained[hint](value); if (isArray(value)) return setPrototypeOf$1(value, Array$7.prototype); const brand = getBrand(value); if (brand in chained) return chained[brand](value); if (brand in env) return setPrototypeOf$1(value, env[brand].prototype); if ("nodeType" in value) { switch (call(nodeType, value)) { case 1: if (!(hint in chained)) throw new Error("unknown hint " + hint); return chained[hint](value); case 2: return chained.Attr(value); case 3: return chained.Node(value); case 9: return chained.Document(value); } } throw new Error("unknown brand " + brand); }; var $ = isExtensionContext$1 ? value => (value === window || value === globalThis ? env : value) : transformer((value, hint = "Element") => { if (value === window || value === globalThis) return env; switch (typeof value) { case "object": return value && upgrade(value, hint); case "string": return new String$1(value); case "number": return new Number$1(value); default: throw new Error("unsupported value"); } }); const handler = { get(target, name) { const context = target; while (!hasOwnProperty(target, name)) target = getPrototypeOf(target); const {get, set} = getOwnPropertyDescriptor$3(target, name); return function () { return arguments.length ? apply$2(set, context, arguments) : call(get, context); }; } }; const accessor = target => new $$1(target, handler); let {Math: Math$2, setInterval: setInterval$1, performance} = $(window); const noopProfile = { mark() {}, end() {}, toString() { return "{mark(){},end(){}}"; } }; let inactive = true; function setProfile() { inactive = false; } function profile(id, rate = 10) { if (inactive) return noopProfile; function processSamples() { let samples = $([]); for (let {name, duration} of performance.getEntriesByType("measure")) samples.push({name, duration}); if (samples.length) performance.clearMeasures(); } if (!profile[id]) { profile[id] = setInterval$1(processSamples, Math$2.round(60000 / Math$2.min(60, rate))); } return { mark() { performance.mark(id); }, end(clear = false) { performance.measure(id, id); const measures = performance.getEntriesByName(id, "measure"); const measureObj = measures.length > 0 ? measures[measures.length - 1] : null; console.log("PROFILER:", measureObj); performance.clearMarks(id); if (clear) { clearInterval(profile[id]); delete profile[id]; processSamples(); } } }; } let debugging = false; function debug() { return debugging; } function setDebug() { debugging = true; } const {console: console$4} = $(window); const noop = () => {}; function log(...args) { let {mark, end} = profile("log"); if (debug()) { const logArgs = ["%c DEBUG", "font-weight: bold;"]; const isErrorIndex = args.indexOf("error"); const isWarnIndex = args.indexOf("warn"); const isSuccessIndex = args.indexOf("success"); const isInfoIndex = args.indexOf("info"); if (isErrorIndex !== -1) { logArgs[0] += " - ERROR"; logArgs[1] += "color: red; border:2px solid red"; $(args).splice(isErrorIndex, 1); } else if (isWarnIndex !== -1) { logArgs[0] += " - WARNING"; logArgs[1] += "color: orange; border:2px solid orange "; $(args).splice(isWarnIndex, 1); } else if (isSuccessIndex !== -1) { logArgs[0] += " - SUCCESS"; logArgs[1] += "color: green; border:2px solid green"; $(args).splice(isSuccessIndex, 1); } else if (isInfoIndex !== -1) { logArgs[1] += "color: black;"; $(args).splice(isInfoIndex, 1); } $(args).unshift(...logArgs); } mark(); console$4.log(...args); end(); } function getDebugger(name) { return bind(debug() ? log : noop, null, name); } let {Array: Array$6, Math: Math$1, RegExp: RegExp$2} = $(window); function regexEscape(string) { return $(string).replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"); } function toRegExp(pattern) { let {length} = pattern; if (length > 1 && pattern[0] === "/") { let isCaseSensitive = pattern[length - 1] === "/"; if (isCaseSensitive || (length > 2 && $(pattern).endsWith("/i"))) { let args = [$(pattern).slice(1, isCaseSensitive ? -1 : -2)]; if (!isCaseSensitive) args.push("i"); return new RegExp$2(...args); } } return new RegExp$2(regexEscape(pattern)); } function randomId() { return $(Math$1.floor(Math$1.random() * 2116316160 + 60466176)).toString(36); } function formatArguments(args) { return $(Array$6.from(args)).map(arg => `'${arg}'`).join(" "); } let { parseFloat, variables: variables$2, Array: Array$5, Error: Error$9, Map: Map$9, Object: Object$d, ReferenceError: ReferenceError$2, Set: Set$2, WeakMap: WeakMap$3 } = $(window); let {onerror} = accessor(window); let NodeProto$1 = Node.prototype; let ElementProto$2 = Element.prototype; let propertyAccessors = null; function wrapPropertyAccess(object, property, descriptor, setConfigurable = true) { let $property = $(property); let dotIndex = $property.indexOf("."); if (dotIndex == -1) { let currentDescriptor = Object$d.getOwnPropertyDescriptor(object, property); if (currentDescriptor && !currentDescriptor.configurable) return; let newDescriptor = Object$d.assign({}, descriptor, { configurable: setConfigurable }); if (!currentDescriptor && !newDescriptor.get && newDescriptor.set) { let propertyValue = object[property]; newDescriptor.get = () => propertyValue; } Object$d.defineProperty(object, property, newDescriptor); return; } let name = $property.slice(0, dotIndex).toString(); property = $property.slice(dotIndex + 1).toString(); let value = object[name]; if (value && (typeof value == "object" || typeof value == "function")) wrapPropertyAccess(value, property, descriptor); let currentDescriptor = Object$d.getOwnPropertyDescriptor(object, name); if (currentDescriptor && !currentDescriptor.configurable) return; if (!propertyAccessors) propertyAccessors = new WeakMap$3(); if (!propertyAccessors.has(object)) propertyAccessors.set(object, new Map$9()); let properties = propertyAccessors.get(object); if (properties.has(name)) { properties.get(name).set(property, descriptor); return; } let toBeWrapped = new Map$9([[property, descriptor]]); properties.set(name, toBeWrapped); Object$d.defineProperty(object, name, { get: () => value, set(newValue) { value = newValue; if (value && (typeof value == "object" || typeof value == "function")) { for (let [prop, desc] of toBeWrapped) wrapPropertyAccess(value, prop, desc); } }, configurable: setConfigurable }); } function overrideOnError(magic) { let prev = onerror(); onerror((...args) => { let message = args.length && args[0]; if (typeof message == "string" && $(message).includes(magic)) return true; if (typeof prev == "function") return apply$2(prev, this, args); }); } function abortOnRead(loggingPrefix, context, property, formattedProperties = "", setConfigurable = true) { let debugLog = getDebugger(loggingPrefix); if (!property) { debugLog("error", "no property to abort on read"); return; } let rid = randomId(); function abort() { debugLog("success", `${property} access aborted`, `\nFILTER: ${loggingPrefix} ${formattedProperties}`); throw new ReferenceError$2(rid); } debugLog("info", `aborting on ${property} access`); wrapPropertyAccess(context, property, {get: abort, set() {}}, setConfigurable); overrideOnError(rid); } function abortOnWrite(loggingPrefix, context, property, formattedProperties = "", setConfigurable = true) { let debugLog = getDebugger(loggingPrefix); if (!property) { debugLog("error", "no property to abort on write"); return; } let rid = randomId(); function abort() { debugLog("success", `setting ${property} aborted`, `\nFILTER: ${loggingPrefix} ${formattedProperties}`); throw new ReferenceError$2(rid); } debugLog("info", `aborting when setting ${property}`); wrapPropertyAccess(context, property, {set: abort}, setConfigurable); overrideOnError(rid); } function abortOnIframe( properties, abortRead = false, abortWrite = false ) { let abortedIframes = variables$2.abortedIframes; let iframePropertiesToAbort = variables$2.iframePropertiesToAbort; const formattedPropertiesToLog = formatArguments(properties); for (let frame of Array$5.from(window.frames)) { if (abortedIframes.has(frame)) { for (let property of properties) { if (abortRead) abortedIframes.get(frame).read.add({property, formattedProperties: formattedPropertiesToLog}); if (abortWrite) abortedIframes.get(frame).write.add({property, formattedProperties: formattedPropertiesToLog}); } } } for (let property of properties) { if (abortRead) iframePropertiesToAbort.read.add({property, formattedProperties: formattedPropertiesToLog}); if (abortWrite) iframePropertiesToAbort.write.add({property, formattedProperties: formattedPropertiesToLog}); } queryAndProxyIframe(); if (!abortedIframes.has(document)) { abortedIframes.set(document, true); addHooksOnDomAdditions(queryAndProxyIframe); } function queryAndProxyIframe() { for (let frame of Array$5.from(window.frames)) { if (!abortedIframes.has(frame)) { abortedIframes.set(frame, { read: new Set$2(iframePropertiesToAbort.read), write: new Set$2(iframePropertiesToAbort.write) }); } let readProps = abortedIframes.get(frame).read; if (readProps.size > 0) { let props = Array$5.from(readProps); readProps.clear(); for (let {property, formattedProperties} of props) { abortOnRead("abort-on-iframe-property-read", frame, property, formattedProperties); } } let writeProps = abortedIframes.get(frame).write; if (writeProps.size > 0) { let props = Array$5.from(writeProps); writeProps.clear(); for (let {property, formattedProperties} of props) { abortOnWrite("abort-on-iframe-property-write", frame, property, formattedProperties); } } } } } function addHooksOnDomAdditions(endCallback) { let descriptor; wrapAccess(NodeProto$1, ["appendChild", "insertBefore", "replaceChild"]); wrapAccess(ElementProto$2, ["append", "prepend", "replaceWith", "after", "before", "insertAdjacentElement", "insertAdjacentHTML"]); descriptor = getInnerHTMLDescriptor(ElementProto$2, "innerHTML"); wrapPropertyAccess(ElementProto$2, "innerHTML", descriptor); descriptor = getInnerHTMLDescriptor(ElementProto$2, "outerHTML"); wrapPropertyAccess(ElementProto$2, "outerHTML", descriptor); function wrapAccess(prototype, names) { for (let name of names) { let desc = getAppendChildDescriptor(prototype, name); wrapPropertyAccess(prototype, name, desc); } } function getAppendChildDescriptor(target, property) { let currentValue = target[property]; return { get() { return function(...args) { let result; result = apply$2(currentValue, this, args); endCallback && endCallback(); return result; }; } }; } function getInnerHTMLDescriptor(target, property) { let desc = Object$d.getOwnPropertyDescriptor(target, property); let {set: prevSetter} = desc || {}; return { set(val) { let result; result = call(prevSetter, this, val); endCallback && endCallback(); return result; } }; } } let {Object: NativeObject} = window; function findOwner(root, path) { if (!(root instanceof NativeObject)) return; let object = root; let chain = $(path).split("."); if (chain.length === 0) return; for (let i = 0; i < chain.length - 1; i++) { let prop = chain[i]; if (!hasOwnProperty(object, prop)) return; object = object[prop]; if (!(object instanceof NativeObject)) return; } let prop = chain[chain.length - 1]; if (hasOwnProperty(object, prop)) return [object, prop]; } const decimals = $(/^\d+$/); function overrideValue(value) { switch (value) { case "false": return false; case "true": return true; case "null": return null; case "noopFunc": return () => {}; case "trueFunc": return () => true; case "falseFunc": return () => false; case "emptyArray": return []; case "emptyObj": return {}; case "undefined": return void 0; case "": return value; default: if (decimals.test(value)) return parseFloat(value); throw new Error$9("[override-property-read snippet]: " + `Value "${value}" is not valid.`); } } let {HTMLScriptElement: HTMLScriptElement$1, Object: Object$c, ReferenceError: ReferenceError$1} = $(window); let Script = Object$c.getPrototypeOf(HTMLScriptElement$1); function abortCurrentInlineScript(api, search = null) { const formattedArguments = formatArguments(arguments); const debugLog = getDebugger("abort-current-inline-script"); const {mark, end} = profile("abort-current-inline-script"); const re = search ? toRegExp(search) : null; const rid = randomId(); const us = $(document).currentScript; let object = window; const path = $(api).split("."); const name = $(path).pop(); for (let node of $(path)) { object = object[node]; if ( !object || !(typeof object == "object" || typeof object == "function")) { debugLog("warn", path, " is not found"); return; } } const {get: prevGetter, set: prevSetter} = Object$c.getOwnPropertyDescriptor(object, name) || {}; let currentValue = object[name]; if (typeof currentValue === "undefined") debugLog("warn", "The property", name, "doesn't exist yet. Check typos."); const abort = () => { const element = $(document).currentScript; if (element instanceof Script && $(element, "HTMLScriptElement").src == "" && element != us && (!re || re.test($(element).textContent))) { debugLog("success", path, " is aborted \n", element, "\nFILTER: abort-current-inline-script", formattedArguments); throw new ReferenceError$1(rid); } }; const descriptor = { get() { abort(); if (prevGetter) return call(prevGetter, this); return currentValue; }, set(value) { abort(); if (prevSetter) call(prevSetter, this, value); else currentValue = value; } }; mark(); wrapPropertyAccess(object, name, descriptor); end(); overrideOnError(rid); } function abortOnIframePropertyRead(...properties) { const {mark, end} = profile("abort-on-iframe-property-read"); mark(); abortOnIframe(properties, true, false); end(); } function abortOnIframePropertyWrite(...properties) { const {mark, end} = profile("abort-on-iframe-property-write"); mark(); abortOnIframe(properties, false, true); end(); } function abortOnPropertyRead(property, setConfigurable) { const configurableFlag = !(setConfigurable === "false"); const formattedArguments = formatArguments(arguments); const {mark, end} = profile("abort-on-property-read"); mark(); abortOnRead("abort-on-property-read", window, property, formattedArguments, configurableFlag); end(); } function abortOnPropertyWrite(property, setConfigurable) { const formattedArguments = formatArguments(arguments); const {mark, end} = profile("abort-on-property-write"); const configurableFlag = !(setConfigurable === "false"); mark(); abortOnWrite("abort-on-property-write", window, property, formattedArguments, configurableFlag); end(); } const {Error: Error$8, Object: Object$b, Array: Array$4, Map: Map$8} = $(window); let arrayValues = null; function hasMatchingProperty(val, needle, pathSegments) { let current = val; for (const segment of pathSegments) { if (!current || !hasOwnProperty(current, segment)) return false; current = current[segment]; } if (typeof current === "string" || typeof current === "number"){ const currStr = current.toString(); return needle.test(currStr); } return false; } function arrayOverride(method, needle, returnValue = "false", path) { if (!method) throw new Error$8("[array-override snippet]: Missing method to override."); if (!needle) throw new Error$8("[array-override snippet]: Missing needle."); if (!arrayValues) arrayValues = new Map$8(); let debugLog = getDebugger("array-override"); const {mark, end} = profile("array-override"); const formattedArgsToLog = formatArguments(arguments); if (method === "push" && !arrayValues.has("push")) { mark(); const {push} = Array$4.prototype; arrayValues.set("push", $([])); Object$b.defineProperty(window.Array.prototype, "push", { value: proxy(push, function(val) { const overrideVals = arrayValues.get("push"); for (const {needleRegex, pathSegments} of overrideVals) { if (!pathSegments.length && (typeof val === "string" || typeof val === "number")) { const valStr = val.toString(); if (valStr.match && valStr.match(needleRegex)) { debugLog("success", `Array.push is ignored for needle: ${needleRegex}\nFILTER: array-override ${formattedArgsToLog}`); return; } } else if (pathSegments.length && typeof val === "object" && val !== null) { if (hasMatchingProperty(val, needleRegex, pathSegments)) { debugLog("success", `Array.push is ignored for object containing needle: ${needleRegex}\nFILTER: array-override ${formattedArgsToLog}`); return; } } } return apply$2(push, this, arguments); }) }); debugLog("info", "Wrapped Array.prototype.push"); end(); } else if (method === "includes" && !arrayValues.has("includes")) { mark(); const {includes} = Array$4.prototype; arrayValues.set("includes", $([])); Object$b.defineProperty(window.Array.prototype, "includes", { value: proxy(includes, function(val) { const overrideVals = arrayValues.get("includes"); for (const {needleRegex, retVal, pathSegments} of overrideVals) { if (!pathSegments.length && (typeof val === "string" || typeof val === "number")) { if (val.toString().match && val.toString().match(needleRegex)) { debugLog("success", `Array.includes returned ${retVal} for ${needleRegex}\nFILTER: array-override ${formattedArgsToLog}`); return retVal; } } else if (pathSegments.length && typeof val === "object" && val !== null) { if (hasMatchingProperty(val, needleRegex, pathSegments)) { debugLog("success", `Array.includes returned ${retVal} for object containing ${needleRegex}\nFILTER: array-override ${formattedArgsToLog}`); return retVal; } } } return apply$2(includes, this, arguments); }) }); debugLog("info", "Wrapped Array.prototype.includes"); end(); } else if (method === "forEach" && !arrayValues.has("forEach")) { mark(); const {forEach} = Array$4.prototype; arrayValues.set("forEach", $([])); Object$b.defineProperty(window.Array.prototype, "forEach", { value: proxy(forEach, function(callback, thisArg) { const overrideVals = arrayValues.get("forEach"); const filteredCallback = function(item, index, array) { for (const {needleRegex, pathSegments} of overrideVals) { if (!pathSegments.length && (typeof item === "string" || typeof item === "number")) { const itemStr = item.toString(); if (itemStr.match && itemStr.match(needleRegex)) { debugLog("success", `Array.forEach skipped callback for item matching needle: ${needleRegex}\nFILTER: array-override ${formattedArgsToLog}`); return; } } else if (pathSegments.length && typeof item === "object" && item !== null) { if (hasMatchingProperty(item, needleRegex, pathSegments)) { debugLog("success", `Array.forEach skipped callback for object containing needle: ${needleRegex}\nFILTER: array-override ${formattedArgsToLog}`); return; } } } return apply$2(callback, thisArg || this, [item, index, array]); }; return apply$2(forEach, this, [filteredCallback, thisArg]); }) }); debugLog("info", "Wrapped Array.prototype.forEach"); end(); } const needleRegex = toRegExp(needle); let pathSegments = []; if (path) pathSegments = path.split("."); const overrideVals = arrayValues.get(method); const retVal = returnValue === "true"; overrideVals.push({needleRegex, retVal, pathSegments}); arrayValues.set(method, overrideVals); } const {Array: Array$3, Blob, Error: Error$7, Object: Object$a, Reflect: Reflect$2} = $(window); const blobRules = []; function blobOverride(search, replacement = "", needle = null) { if (!search) { throw new Error$7( "[blob-override snippet]: Missing parameter search." ); } const debugLog = getDebugger("blob-override"); const formattedArgsToLog = formatArguments(arguments); const {mark, end} = profile("blob-override"); mark(); blobRules.push({ match: toRegExp(search), replaceWith: replacement, needle: needle ? toRegExp(needle) : null, formattedArgs: formattedArgsToLog }); if (blobRules.length > 1) return; const OriginalBlob = Blob; function PatchedBlob(data, options = {}) { if (Array$3.isArray(data)) { data = $(data).map(chunk => { if (typeof chunk !== "string") return chunk; let modified = $(chunk); for (const rule of $(blobRules)) { if ( (!rule.needle || rule.needle.test(modified)) && rule.match.test(modified) ) { modified = modified.replace(rule.match, rule.replaceWith); debugLog("success", `Replaced: ${rule.match} → ${rule.replaceWith},\nFILTER: blob-override ${rule.formattedArgs}`); } } return modified; }); } const blob = Reflect$2.construct(OriginalBlob, [data, options]); Object$a.setPrototypeOf(blob, PatchedBlob.prototype); return blob; } PatchedBlob.prototype = OriginalBlob.prototype; Object$a.setPrototypeOf(PatchedBlob, OriginalBlob); window.Blob = PatchedBlob; debugLog("info", "Wrapped Blob constructor in context "); end(); } let {Error: Error$6, URL: URL$2} = $(window); let {cookie: documentCookies} = accessor(document); function cookieRemover(cookie, autoRemoveCookie = false) { if (!cookie) throw new Error$6("[cookie-remover snippet]: No cookie to remove."); const formattedArguments = formatArguments(arguments); let debugLog = getDebugger("cookie-remover"); const {mark, end} = profile("cookie-remover"); let re = toRegExp(cookie); if (!$(/^http|^about/).test(location.protocol)) { debugLog("warn", "Snippet only works for http or https and about."); return; } function getCookieMatches() { const arr = $(documentCookies()).split(";"); return arr.filter(str => re.test($(str).split("=")[0])); } const mainLogic = () => { debugLog("info", "Parsing cookies for matches"); mark(); for (const pair of $(getCookieMatches())) { let $hostname = $(location.hostname); if (!$hostname && $(location.ancestorOrigins) && $(location.ancestorOrigins[0])) $hostname = new URL$2($(location.ancestorOrigins[0])).hostname; const name = $(pair).split("=")[0]; const expires = "expires=Thu, 01 Jan 1970 00:00:00 GMT"; const path = "path=/"; const domainParts = $hostname.split("."); for (let numDomainParts = domainParts.length; numDomainParts > 0; numDomainParts--) { const domain = domainParts.slice(domainParts.length - numDomainParts).join("."); documentCookies(`${$(name).trim()}=;${expires};${path};domain=${domain}`); documentCookies(`${$(name).trim()}=;${expires};${path};domain=.${domain}`); debugLog("success", `Set expiration date on ${name}`, "\nFILTER: cookie-remover", formattedArguments); } } end(); }; mainLogic(); if (autoRemoveCookie) { let lastCookie = getCookieMatches(); setInterval(() => { let newCookie = getCookieMatches(); if (newCookie !== lastCookie) { try { mainLogic(); } finally { lastCookie = newCookie; } } }, 1000); } } const {Map: Map$7, Object: Object$9, Reflect: Reflect$1, WeakMap: WeakMap$2} = $(window); const originalAddEventListener = window.EventTarget.prototype.addEventListener; const originalRemoveEventListener = window.EventTarget. prototype.removeEventListener; const listenerMap = new WeakMap$2(); let eventOverrides = []; function eventOverride(eventType, mode, needle = null) { const formattedArgs = formatArguments(arguments); const overrideConfig = { eventType, mode, needle: needle ? toRegExp(needle) : null, formattedArgs }; if (!eventOverrides.includes(overrideConfig)) eventOverrides.push(overrideConfig); if (eventOverrides.length > 1) return; let debugLog = getDebugger("[event-override]"); const {mark, end} = profile("event-override"); const addEventListenerDescriptor = Object$9.getOwnPropertyDescriptor( window.EventTarget.prototype, "addEventListener" ); if (addEventListenerDescriptor.configurable) { Object$9.defineProperty(window.EventTarget.prototype, "addEventListener", { ...addEventListenerDescriptor, value: proxy( originalAddEventListener, function(type, listener, options) { mark(); const filteredEvents = eventOverrides.filter( ev => ev.eventType === type ); if (!filteredEvents.length || type !== filteredEvents[0].eventType) { end(); return apply$2(originalAddEventListener, this, arguments); } const disabledEvent = filteredEvents.find( ev => (ev.mode === "disable") && (ev.needle ? ev.needle.test(listener.toString()) : true) ); if (disabledEvent) { debugLog("success", `Disabling ${disabledEvent.eventType} event, \nFILTER: event-override ${disabledEvent.formattedArgs}`); end(); return; } const changedEvents = filteredEvents.filter( ev => (ev.mode === "trusted") && (ev.needle ? ev.needle.test(listener.toString()) : true) ); if (typeof listener !== "function" && !(listener && typeof listener.handleEvent === "function") || !changedEvents.length || type !== changedEvents[0].eventType) { end(); return apply$2(originalAddEventListener, this, arguments); } const wrappedListener = function(originalEvent) { const customEvent = new Proxy(originalEvent, { get(target, prop) { if (prop === "isTrusted") { debugLog("success", `Providing trusted value for ${originalEvent.type} event`); return true; } const val = Reflect$1.get(target, prop); if (typeof val === "function") { return function(...args) { return apply$2(val, target, args); }; } return val; } }); if (typeof listener === "function") return call(listener, this, customEvent); return call(listener.handleEvent, listener, customEvent); }; wrappedListener.originalListener = listener; if (!listenerMap.has(listener)) listenerMap.set(listener, new Map$7()); listenerMap.get(listener).set(type, wrappedListener); debugLog("info", `\nWrapping event listener for ${type}`); end(); return apply$2( originalAddEventListener, this, [type, wrappedListener, options] ); }) }); } const removeEventListenerDescriptor = Object$9.getOwnPropertyDescriptor( window.EventTarget.prototype, "removeEventListener" ); if (removeEventListenerDescriptor.configurable) { Object$9.defineProperty(window.EventTarget.prototype, "removeEventListener", { ...removeEventListenerDescriptor, value: proxy( originalRemoveEventListener, function(type, listener, options) { if (listener && listenerMap.has(listener) && listenerMap.get(listener).has(type)) { const wrappedListener = listenerMap.get(listener).get(type); listenerMap.get(listener).delete(type); return apply$2( originalRemoveEventListener, this, [type, wrappedListener, options] ); } return apply$2(originalRemoveEventListener, this, arguments); }) }); } debugLog("info", "Initialized event-override snippet"); } let { console: console$3, document: document$2, getComputedStyle, isExtensionContext, variables: variables$1, Array: Array$2, MutationObserver: MutationObserver$3, Object: Object$8, XPathEvaluator, XPathExpression, XPathResult } = $(window); const {querySelectorAll} = document$2; const document$$ = querySelectorAll && bind(querySelectorAll, document$2); function $openOrClosedShadowRoot(element, failSilently = false) { try { const shadowRoot = (navigator.userAgent.includes("Firefox")) ? element.openOrClosedShadowRoot : browser.dom.openOrClosedShadowRoot(element); if (shadowRoot === null && ((debug() && !failSilently))) console$3.log("Shadow root not found or not added in element yet", element); return shadowRoot; } catch (error) { if (debug() && !failSilently) console$3.log("Error while accessing shadow root", element, error); return null; } } function $$(selector, returnRoots = false) { return $$recursion( selector, document$$.bind(document$2), document$2, returnRoots ); } function isArrayEmptyStrings(arr) { return !arr || arr.length === 0 || arr.every(item => item.trim() === ""); } function executeSvgCommand( nestedCommands, rootParent, resultNodes, rootParents ) { const xlinkHref = rootParent.getAttribute("xlink:href") || rootParent.getAttribute("href"); if (xlinkHref) { const matchingElement = document$$(xlinkHref)[0]; if (!matchingElement && debug()) { console$3.log("No elements found matching", xlinkHref); return false; } if (isArrayEmptyStrings(nestedCommands)) { const oldRootParents = rootParents.length > 0 ? rootParents : []; resultNodes.push({ element: matchingElement, rootParents: [...oldRootParents, rootParent] }); return false; } const next$$ = matchingElement.querySelectorAll.bind(matchingElement); return { nextBoundElement: matchingElement, nestedSelectorsString: nestedCommands.join("^^"), next$$ }; } } function executeShadowRootCommand(nestedCommands, rootParent) { const shadowRoot = $openOrClosedShadowRoot(rootParent); if (shadowRoot) { const {querySelectorAll: shadowRootQuerySelectorAll} = shadowRoot; const next$$ = shadowRootQuerySelectorAll && bind(shadowRootQuerySelectorAll, shadowRoot).bind(shadowRoot); return { nextBoundElement: rootParent, nestedSelectorsString: ":host " + nestedCommands.join("^^"), next$$ }; } return false; } function $$recursion( selector, bound$$, boundElement, returnRoots, rootParents = [] ) { if (selector.includes("^^")) { const [currentSelector, currentCommand, ...nestedCommands] = selector.split("^^"); let newRootParents; let commandFn; switch (currentCommand) { case "svg": { commandFn = executeSvgCommand; break; } case "sh": { commandFn = executeShadowRootCommand; break; } default: { if (debug()) { console$3.log( currentCommand, " is not supported. Supported commands are: \n^^sh^^\n^^svg^^" ); } return []; } } if (currentSelector.trim() === "") newRootParents = [boundElement]; else newRootParents = bound$$(currentSelector); const resultNodes = []; for (const rootParent of newRootParents) { const res = commandFn(nestedCommands, rootParent, resultNodes, rootParents); if (!res) continue; const {next$$, nestedSelectorsString, nextBoundElement} = res; const nestedElements = $$recursion( nestedSelectorsString, next$$, nextBoundElement, returnRoots, [...rootParents, rootParent] ); if (nestedElements) resultNodes.push(...nestedElements); } return resultNodes; } const foundElements = bound$$(selector); if (returnRoots) { return [...foundElements].map(element => ( {element, rootParents: rootParents.length > 0 ? rootParents : []}) ); } return foundElements; } const {assign, setPrototypeOf} = Object$8; class $XPathExpression extends XPathExpression { evaluate(...args) { return setPrototypeOf( apply$2(super.evaluate, this, args), XPathResult.prototype ); } } class $XPathEvaluator extends XPathEvaluator { createExpression(...args) { return setPrototypeOf( apply$2(super.createExpression, this, args), $XPathExpression.prototype ); } } function hideElement(element) { if (variables$1.hidden.has(element)) return false; notifyElementHidden(element); variables$1.hidden.add(element); let {style} = $(element); let $style = $(style, "CSSStyleDeclaration"); let properties = $([]); let {debugCSSProperties} = libEnvironment; for (let [key, value] of (debugCSSProperties || [["display", "none"]])) { $style.setProperty(key, value, "important"); properties.push([key, $style.getPropertyValue(key)]); } new MutationObserver$3(() => { for (let [key, value] of properties) { let propertyValue = $style.getPropertyValue(key); let propertyPriority = $style.getPropertyPriority(key); if (propertyValue != value || propertyPriority != "important") $style.setProperty(key, value, "important"); } }).observe(element, {attributes: true, attributeFilter: ["style"]}); return true; } function notifyElementHidden(element) { if (isExtensionContext && typeof checkElement === "function") checkElement(element); } function initQueryAndApply(selector) { let $selector = selector; if ($selector.startsWith("xpath(") && $selector.endsWith(")")) { let xpathQuery = $selector.slice(6, -1); let evaluator = new $XPathEvaluator(); let expression = evaluator.createExpression(xpathQuery, null); let flag = XPathResult.ORDERED_NODE_SNAPSHOT_TYPE; return cb => { if (!cb) return; let result = expression.evaluate(document$2, flag, null); let {snapshotLength} = result; for (let i = 0; i < snapshotLength; i++) cb(result.snapshotItem(i)); }; } return cb => $$(selector).forEach(cb); } function initQueryAll(selector) { let $selector = selector; if ($selector.startsWith("xpath(") && $selector.endsWith(")")) { let queryAndApply = initQueryAndApply(selector); return () => { let elements = $([]); queryAndApply(e => elements.push(e)); return elements; }; } return () => Array$2.from($$(selector)); } let {ELEMENT_NODE, TEXT_NODE, prototype: NodeProto} = Node; let {prototype: ElementProto$1} = Element; let {prototype: HTMLElementProto} = HTMLElement; let { console: console$2,