diff --git a/src/js/background.js b/src/js/background.js index 516774261..109bdde05 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -48,6 +48,7 @@ const µBlock = (function() { // jshint ignore:line cacheControlForFirefox1376932: 'no-cache, no-store, must-revalidate', consoleLogLevel: 'unset', debugScriptlets: false, + debugScriptletInjector: false, disableWebAssembly: false, ignoreRedirectFilters: false, ignoreScriptInjectFilters: false, diff --git a/src/js/redirect-engine.js b/src/js/redirect-engine.js index e9819e63a..5a512f288 100644 --- a/src/js/redirect-engine.js +++ b/src/js/redirect-engine.js @@ -65,6 +65,9 @@ const immutableResources = new Map([ alias: 'ampproject.org/v0.js', inject: false } ], + [ 'bab-defuser.js', { + alias: 'nobab.js', + } ], [ 'chartbeat.js', { alias: 'static.chartbeat.com/chartbeat.js', inject: false @@ -127,6 +130,14 @@ const immutableResources = new Map([ alias: 'd3pkae9owd2lcf.cloudfront.net/mb105.js', inject: false } ], + [ 'nano-setInterval-booster.js', { + alias: 'nano-sib.js', + redirect: false + } ], + [ 'nano-setTimeout-booster.js', { + alias: 'nano-stb.js', + redirect: false + } ], [ 'noeval-silent.js', { alias: 'silent-noeval.js', } ], @@ -165,8 +176,20 @@ const immutableResources = new Map([ [ 'set-constant.js', { redirect: false } ], + [ 'setInterval-defuser.js', { + alias: 'sid.js', + redirect: false + } ], + [ 'setInterval-logger.js', { + alias: 'sil.js', + redirect: false + } ], [ 'setTimeout-defuser.js', { - alias: 'stod.js', + alias: 'std.js', + redirect: false + } ], + [ 'setTimeout-logger.js', { + alias: 'stl.js', redirect: false } ], [ 'webrtc-if.js', { @@ -680,7 +703,7 @@ RedirectEngine.prototype.loadBuiltinResources = function() { const match = /^\/web_accessible_resources\/([^?]+)/.exec(result.url); if ( match === null ) { continue; } const name = match[1]; - const content = result.content.replace(/^\/\*[\S\s]+?\*\/\s*/, ''); + const content = result.content.replace(/^\/\*[\S\s]+?\n\*\/\s*/, ''); const details = immutableResources.get(name); const entry = RedirectEntry.fromSelfie({ mime: mimeFromName(name), diff --git a/src/js/scriptlet-filtering.js b/src/js/scriptlet-filtering.js index 4f9ddee41..a597883be 100644 --- a/src/js/scriptlet-filtering.js +++ b/src/js/scriptlet-filtering.js @@ -210,7 +210,7 @@ let pos = args.indexOf(','); if ( pos === -1 ) { pos = args.length; } const arg = args.slice(0, pos).trim().replace(reEscapeScriptArg, '\\$&'); - content = content.replace('{{' + i + '}}', arg); + content = content.replace(`{{${i}}}`, arg); args = args.slice(pos + 1).trim(); i++; } @@ -227,7 +227,7 @@ .setDocOriginFromURL(details.url) .setFilter({ source: 'cosmetic', - raw: (isException ? '#@#' : '##') + '+js(' + token + ')' + raw: (isException ? '#@#' : '##') + `+js(${token})` }) .toLogger(); }; @@ -356,6 +356,10 @@ if ( out.length === 0 ) { return; } + if ( µb.hiddenSettings.debugScriptlets ) { + out.unshift('debugger'); + } + return out.join('\n'); }; @@ -375,7 +379,7 @@ const scriptlets = µb.scriptletFilteringEngine.retrieve(request); if ( scriptlets === undefined ) { return; } let code = contentscriptCode.assemble(request.hostname, scriptlets); - if ( µb.hiddenSettings.debugScriptlets ) { + if ( µb.hiddenSettings.debugScriptletInjector ) { code = 'debugger;\n' + code; } vAPI.tabs.injectScript( diff --git a/src/web_accessible_resources/bab-defuser.js b/src/web_accessible_resources/bab-defuser.js new file mode 100644 index 000000000..32a298335 --- /dev/null +++ b/src/web_accessible_resources/bab-defuser.js @@ -0,0 +1,87 @@ +/******************************************************************************* + + uBlock Origin - a browser extension to block requests. + Copyright (C) 2019-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +(function() { + 'use strict'; + const signatures = [ + [ 'blockadblock' ], + [ 'babasbm' ], + [ /getItem\('babn'\)/ ], + [ + 'getElementById', + 'String.fromCharCode', + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', + 'charAt', + 'DOMContentLoaded', + 'AdBlock', + 'addEventListener', + 'doScroll', + 'fromCharCode', + '<<2|r>>4', + 'sessionStorage', + 'clientWidth', + 'localStorage', + 'Math', + 'random' + ], + ]; + const check = function(s) { + for ( let i = 0; i < signatures.length; i++ ) { + const tokens = signatures[i]; + let match = 0; + for ( let j = 0; j < tokens.length; j++ ) { + const token = tokens[j]; + const pos = token instanceof RegExp + ? s.search(token) + : s.indexOf(token); + if ( pos !== -1 ) { match += 1; } + } + if ( (match / tokens.length) >= 0.8 ) { return true; } + } + return false; + }; + window.eval = new Proxy(window.eval, { // jshint ignore: line + apply: function(target, thisArg, args) { + const a = args[0]; + if ( typeof a !== 'string' || !check(a) ) { + return target.apply(thisArg, args); + } + if ( document.body ) { + document.body.style.removeProperty('visibility'); + } + let el = document.getElementById('babasbmsgx'); + if ( el ) { + el.parentNode.removeChild(el); + } + } + }); + window.setTimeout = new Proxy(window.setTimeout, { + apply: function(target, thisArg, args) { + const a = args[0]; + if ( + typeof a !== 'string' || + /\.bab_elementid.$/.test(a) === false + ) { + return target.apply(thisArg, args); + } + } + }); +})(); diff --git a/src/web_accessible_resources/nano-setInterval-booster.js b/src/web_accessible_resources/nano-setInterval-booster.js new file mode 100644 index 000000000..f08c6401f --- /dev/null +++ b/src/web_accessible_resources/nano-setInterval-booster.js @@ -0,0 +1,51 @@ +/******************************************************************************* + + Imported from: + https://github.com/NanoAdblocker/NanoFilters/blob/1f3be7211bb0809c5106996f52564bf10c4525f7/NanoFiltersSource/NanoResources.txt#L126 + + Speed up or down setInterval, 3 optional arguments. + funcMatcher - The payload matcher, a string literal or a JavaScript RegExp, + defaults to match all. + delayMatcher - The delay matcher, an integer, defaults to 1000. + boostRatio - The delay multiplier when there is a match, 0.5 speeds up by + 2 times and 2 slows down by 2 times, defaults to 0.05 or speed up 20 times. + Speed up and down both cap at 50 times. + +*/ + +(function() { + 'use strict'; + let needle = '{{1}}'; + let delay = parseInt('{{2}}', 10); + let boost = parseFloat('{{3}}'); + if ( needle === '' || needle === '{{1}}' ) { + needle = '.?'; + } else if ( needle.charAt(0) === '/' && needle.slice(-1) === '/' ) { + needle = needle.slice(1, -1); + } else { + needle = needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + } + needle = new RegExp(needle); + if ( isNaN(delay) || !isFinite(delay) ) { + delay = 1000; + } + if ( isNaN(boost) || !isFinite(boost) ) { + boost = 0.05; + } + if ( boost < 0.02 ) { + boost = 0.02; + } + if ( boost > 50 ) { + boost = 50; + } + window.setInterval = new Proxy(window.setInterval, { + apply: function(target, thisArg, args) { + const a = args[0]; + const b = args[1]; + if ( b === delay && needle.test(a.toString()) ) { + args[1] = b * boost; + } + return target.apply(thisArg, args); + } + }); +})(); diff --git a/src/web_accessible_resources/nano-setTimeout-booster.js b/src/web_accessible_resources/nano-setTimeout-booster.js new file mode 100644 index 000000000..afce15579 --- /dev/null +++ b/src/web_accessible_resources/nano-setTimeout-booster.js @@ -0,0 +1,51 @@ +/******************************************************************************* + + Originally imported from: + https://github.com/NanoAdblocker/NanoFilters/blob/1f3be7211bb0809c5106996f52564bf10c4525f7/NanoFiltersSource/NanoResources.txt#L82 + + Speed up or down setTimeout, 3 optional arguments. + funcMatcher - The payload matcher, a string literal or a JavaScript RegExp, + defaults to match all. + delayMatcher - The delay matcher, an integer, defaults to 1000. + boostRatio - The delay multiplier when there is a match, 0.5 speeds up by + 2 times and 2 slows down by 2 times, defaults to 0.05 or speed up 20 times. + Speed up and down both cap at 50 times. + +*/ + +(function() { + 'use strict'; + let needle = '{{1}}'; + let delay = parseInt('{{2}}', 10); + let boost = parseFloat('{{3}}'); + if ( needle === '' || needle === '{{1}}' ) { + needle = '.?'; + } else if ( needle.startsWith('/') && needle.endsWith('/') ) { + needle = needle.slice(1, -1); + } else { + needle = needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + } + needle = new RegExp(needle); + if ( isNaN(delay) || !isFinite(delay) ) { + delay = 1000; + } + if ( isNaN(boost) || !isFinite(boost) ) { + boost = 0.05; + } + if ( boost < 0.02 ) { + boost = 0.02; + } + if ( boost > 50 ) { + boost = 50; + } + window.setTimeout = new Proxy(window.setTimeout, { + apply: function(target, thisArg, args) { + const a = args[0]; + const b = args[1]; + if ( b === delay && needle.test(a.toString()) ) { + args[1] = b * boost; + } + return target.apply(thisArg, args); + } + }); +})(); diff --git a/src/web_accessible_resources/setInterval-defuser.js b/src/web_accessible_resources/setInterval-defuser.js new file mode 100644 index 000000000..c443ffcdf --- /dev/null +++ b/src/web_accessible_resources/setInterval-defuser.js @@ -0,0 +1,44 @@ +/******************************************************************************* + + uBlock Origin - a browser extension to block requests. + Copyright (C) 2019-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +(function() { + 'use strict'; + let needle = '{{1}}'; + const delay = parseInt('{{2}}', 10); + if ( needle === '' || needle === '{{1}}' ) { + needle = '.?'; + } else if ( needle.startsWith('/') && needle.endsWith('/') ) { + needle = needle.slice(1,-1); + } else { + needle = needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + } + needle = new RegExp(needle); + window.setInterval = new Proxy(window.setInterval, { + apply: function(target, thisArg, args) { + const a = args[0]; + const b = args[1]; + if ( (isNaN(delay) || b === delay) && needle.test(a.toString()) ) { + args[0] = function(){}; + } + return target.apply(thisArg, args); + } + }); +})(); diff --git a/src/web_accessible_resources/setInterval-logger.js b/src/web_accessible_resources/setInterval-logger.js new file mode 100644 index 000000000..49e05bc73 --- /dev/null +++ b/src/web_accessible_resources/setInterval-logger.js @@ -0,0 +1,33 @@ +/******************************************************************************* + + uBlock Origin - a browser extension to block requests. + Copyright (C) 2019-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +(function() { + 'use strict'; + const log = console.log.bind(console); + window.setInterval = new Proxy(window.setInterval, { + apply: function(target, thisArg, args) { + const a = args[0]; + const b = args[1]; + log('uBO: setInterval("%s", %s)', a.toString(), b); + return target.apply(thisArg, args); + } + }); +})(); diff --git a/src/web_accessible_resources/setTimeout-logger.js b/src/web_accessible_resources/setTimeout-logger.js new file mode 100644 index 000000000..604eef004 --- /dev/null +++ b/src/web_accessible_resources/setTimeout-logger.js @@ -0,0 +1,33 @@ +/******************************************************************************* + + uBlock Origin - a browser extension to block requests. + Copyright (C) 2019-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +(function() { + 'use strict'; + const log = console.log.bind(console); + window.setTimeout = new Proxy(window.setTimeout, { + apply: function(target, thisArg, args) { + const a = args[0]; + const b = args[1]; + log('uBO: setTimeout("%s", %s)', a.toString(), b); + return target.apply(thisArg, args); + } + }); +})();