Fine tune new resources-related code

Make sure the parser is safely compatible with old
resources format -- for those users still using
custom resources (via `userResourcesLocation`).

Prepare code for future fix to
<https://github.com/uBlockOrigin/uBlock-issues/issues/156>:

This commit introduces a new private Map() object,
`uBOSafe`, accessible by all injected scriptlets. This
private safe can be used to store data which can be shared
with different scriptlets. The idea is for scriptlets to
use that safe to graciously deal with the need to install
multiple listeners for the same property.
This commit is contained in:
Raymond Hill 2019-07-08 08:56:36 -04:00
parent da4c4ded8d
commit e55cae6232
No known key found for this signature in database
GPG key ID: 25E1490B761470C2
3 changed files with 74 additions and 60 deletions

View file

@ -22,11 +22,21 @@
web page context.
*/
// The lines below are skipped by the resource parser. Purpose is clean
// jshinting.
(function() {
// >>>> start of private namespace
'use strict';
// This a private safe available for use by all injected scriptlets.
const uBOSafe = new Map(); // jshint ignore: line
/// abort-current-inline-script.js
/// alias acis.js
(function() {
'use strict';
const target = '{{1}}';
if ( target === '' || target === '{{1}}' ) { return; }
const needle = '{{2}}';
@ -88,7 +98,6 @@
/// abort-on-property-read.js
/// alias aopr.js
(function() {
'use strict';
const magic = String.fromCharCode(Date.now() % 26 + 97) +
Math.floor(Math.random() * 982451653 + 982451653).toString(36);
const abort = function() {
@ -143,7 +152,6 @@
/// abort-on-property-write.js
/// alias aopw.js
(function() {
'use strict';
const magic = String.fromCharCode(Date.now() % 26 + 97) +
Math.floor(Math.random() * 982451653 + 982451653).toString(36);
let prop = '{{1}}';
@ -176,7 +184,6 @@
/// addEventListener-defuser.js
/// alias aeld.js
(function() {
'use strict';
let needle1 = '{{1}}';
if ( needle1 === '' || needle1 === '{{1}}' ) {
needle1 = '.?';
@ -216,7 +223,6 @@
/// addEventListener-logger.js
/// alias aell.js
(function() {
'use strict';
const log = console.log.bind(console);
self.EventTarget.prototype.addEventListener = new Proxy(
self.EventTarget.prototype.addEventListener,
@ -235,7 +241,6 @@
/// nano-setInterval-booster.js
/// alias nano-sib.js
(function() {
'use strict';
let needle = '{{1}}';
let delay = parseInt('{{2}}', 10);
let boost = parseFloat('{{3}}');
@ -275,7 +280,6 @@
/// nano-setTimeout-booster.js
/// alias nano-stb.js
(function() {
'use strict';
let needle = '{{1}}';
let delay = parseInt('{{2}}', 10);
let boost = parseFloat('{{3}}');
@ -314,7 +318,6 @@
/// noeval-if.js
(function() {
'use strict';
let needle = '{{1}}';
if ( needle === '' || needle === '{{1}}' ) {
needle = '.?';
@ -338,7 +341,6 @@
/// remove-attr.js
/// alias ra.js
(function() {
'use strict';
const token = '{{1}}';
if ( token === '' || token === '{{1}}' ) { return; }
const tokens = token.split(/\s*\|\s*/);
@ -370,7 +372,6 @@
/// set-constant.js
(function() {
'use strict';
const thisScript = document.currentScript;
let cValue = '{{2}}';
if ( cValue === 'undefined' ) {
@ -452,7 +453,6 @@
/// setInterval-defuser.js
/// alias sid.js
(function() {
'use strict';
let needle = '{{1}}';
const delay = parseInt('{{2}}', 10);
if ( needle === '' || needle === '{{1}}' ) {
@ -479,7 +479,6 @@
/// setInterval-logger.js
/// alias sil.js
(function() {
'use strict';
const log = console.log.bind(console);
window.setInterval = new Proxy(window.setInterval, {
apply: function(target, thisArg, args) {
@ -495,7 +494,6 @@
/// setTimeout-defuser.js
/// alias std.js
(function() {
'use strict';
let needle = '{{1}}';
const delay = parseInt('{{2}}', 10);
if ( needle === '' || needle === '{{1}}' ) {
@ -522,7 +520,6 @@
/// setTimeout-logger.js
/// alias stl.js
(function() {
'use strict';
const log = console.log.bind(console);
window.setTimeout = new Proxy(window.setTimeout, {
apply: function(target, thisArg, args) {
@ -537,7 +534,6 @@
/// webrtc-if.js
(function() {
'use strict';
let good = '{{1}}';
if ( good.startsWith('/') && good.endsWith('/') ) {
good = good.slice(1, -1);
@ -607,7 +603,6 @@
// https://github.com/gorhill/uBlock/issues/1228
/// window.name-defuser
(function() {
'use strict';
if ( window === window.top ) {
window.name = '';
}
@ -619,7 +614,6 @@
// as a stock tool in uBO's popup panel.
/// overlay-buster.js
(function() {
'use strict';
if ( window !== window.top ) {
return;
}
@ -676,7 +670,6 @@
// https://github.com/uBlockOrigin/uAssets/issues/8
/// alert-buster.js
(function() {
'use strict';
window.alert = function(a) {
console.info(a);
};
@ -686,7 +679,6 @@
// https://github.com/uBlockOrigin/uAssets/issues/58
/// gpt-defuser.js
(function() {
'use strict';
const noopfn = function() {
};
let props = '_resetGPT resetGPT resetAndLoadGPTRecovery _resetAndLoadGPTRecovery setupGPT setupGPTuo';
@ -708,7 +700,6 @@
// Prevent web pages from using RTCPeerConnection(), and report attempts in console.
/// nowebrtc.js
(function() {
'use strict';
var rtcName = window.RTCPeerConnection ? 'RTCPeerConnection' : (
window.webkitRTCPeerConnection ? 'webkitRTCPeerConnection' : ''
);
@ -744,7 +735,6 @@
// https://github.com/uBlockOrigin/uAssets/issues/88
/// golem.de.js
(function() {
'use strict';
const rael = window.addEventListener;
window.addEventListener = function(a, b) {
rael(...arguments);
@ -767,7 +757,6 @@
// https://www.reddit.com/r/chrome/comments/58eix6/ublock_origin_not_working_on_certain_sites/
/// upmanager-defuser.js
(function() {
'use strict';
var onerror = window.onerror;
window.onerror = function(msg, source, lineno, colno, error) {
if ( typeof msg === 'string' && msg.indexOf('upManager') !== -1 ) {
@ -784,7 +773,6 @@
// https://github.com/uBlockOrigin/uAssets/issues/110
/// smartadserver.com.js
(function() {
'use strict';
Object.defineProperties(window, {
SmartAdObject: { value: function(){} },
SmartAdServerAjax: { value: function(){} },
@ -797,7 +785,6 @@
// https://github.com/uBlockOrigin/uAssets/issues/883
/// adfly-defuser.js
(function() {
'use strict';
// Based on AdsBypasser
// License:
// https://github.com/adsbypasser/adsbypasser/blob/master/LICENSE
@ -861,7 +848,6 @@
// https://github.com/uBlockOrigin/uAssets/issues/913
/// disable-newtab-links.js
(function() {
'use strict';
document.addEventListener('click', function(ev) {
var target = ev.target;
while ( target !== null ) {
@ -878,7 +864,6 @@
/// damoh-defuser.js
(function() {
'use strict';
var handled = new WeakSet();
var asyncTimer;
var cleanVideo = function() {
@ -907,7 +892,6 @@
// https://github.com/uBlockOrigin/uAssets/pull/3517
/// twitch-videoad.js
(function() {
'use strict';
if ( /(^|\.)twitch\.tv$/.test(document.location.hostname) === false ) { return; }
var realFetch = window.fetch;
window.fetch = function(input) {
@ -924,7 +908,6 @@
// https://github.com/uBlockOrigin/uAssets/issues/2912
/// fingerprint2.js
(function() {
'use strict';
let fp2 = function(){};
fp2.prototype = {
get: function(cb) {
@ -938,7 +921,6 @@
// https://github.com/NanoAdblocker/NanoFilters/issues/149
/// cookie-remover.js
(function() {
'use strict';
let needle = '{{1}}',
reName = /./;
if ( /^\/.+\/$/.test(needle) ) {
@ -973,3 +955,11 @@
removeCookie();
window.addEventListener('beforeunload', removeCookie);
})();
// These lines below are skipped by the resource parser.
// <<<< end of private namespace
})();

View file

@ -149,7 +149,6 @@ const redirectableResources = new Map([
alias: 'popads.net.js',
} ],
[ 'popads-dummy.js', {
alias: 'popads-dummy.js',
} ],
[ 'scorecardresearch_beacon.js', {
alias: 'scorecardresearch.com/beacon.js',
@ -159,20 +158,22 @@ const redirectableResources = new Map([
} ],
]);
const mimeMap = {
gif: 'image/gif',
html: 'text/html',
js: 'application/javascript',
mp3: 'audio/mp3',
mp4: 'video/mp4',
png: 'image/png',
txt: 'text/plain',
};
const extToMimeMap = new Map([
[ 'gif', 'image/gif' ],
[ 'html', 'text/html' ],
[ 'js', 'application/javascript' ],
[ 'mp3', 'audio/mp3' ],
[ 'mp4', 'video/mp4' ],
[ 'png', 'image/png' ],
[ 'txt', 'text/plain' ],
]);
const validMimes = new Set(extToMimeMap.values());
const mimeFromName = function(name) {
const match = /\.([^.]+)$/.exec(name);
if ( match !== null ) {
return mimeMap[match[1]];
return extToMimeMap.get(match[1]);
}
};
@ -590,16 +591,24 @@ RedirectEngine.prototype.resourcesFromString = function(text) {
if ( line.startsWith('// ') ) { continue; }
if ( fields === undefined ) {
if ( line === '' ) { continue; }
// Modern parser
if ( line.startsWith('/// ') ) {
const name = line.slice(4).trim();
fields = [ name, mimeFromName(name) ];
} else {
const head = line.trim().split(/\s+/);
if ( head.length !== 2 ) { continue; }
if ( head[0] === 'none' ) { continue; }
encoded = head[1].indexOf(';') !== -1;
fields = head;
continue;
}
// Legacy parser
const head = line.trim().split(/\s+/);
if ( head.length !== 2 ) { continue; }
if ( head[0] === 'none' ) { continue; }
let pos = head[1].indexOf(';');
if ( pos === -1 ) { pos = head[1].length; }
if ( validMimes.has(head[1].slice(0, pos)) === false ) {
continue;
}
encoded = head[1].indexOf(';') !== -1;
fields = head;
continue;
}
@ -619,7 +628,7 @@ RedirectEngine.prototype.resourcesFromString = function(text) {
continue;
}
const name = fields[0];
const name = this.aliases.get(fields[0]) || fields[0];
const mime = fields[1];
const content = µBlock.orphanizeString(
fields.slice(2).join(encoded ? '' : '\n')

View file

@ -66,7 +66,7 @@
// Consequently, the programmatic-injection code path is taken only with
// Chromium-based browsers.
const contentscriptCode = (function() {
const contentscriptCode = (( ) => {
const parts = [
'(',
function(hostname, scriptlets) {
@ -76,7 +76,7 @@
) {
return;
}
let injectScriptlets = function(d) {
const injectScriptlets = function(d) {
let script;
try {
script = d.createElement('script');
@ -94,17 +94,17 @@
}
};
injectScriptlets(document);
let processIFrame = function(iframe) {
let src = iframe.src;
const processIFrame = function(iframe) {
const src = iframe.src;
if ( /^https?:\/\//.test(src) === false ) {
injectScriptlets(iframe.contentDocument);
}
};
let observerTimer,
observerLists = [];
let observerAsync = function() {
for ( let nodelist of observerLists ) {
for ( let node of nodelist ) {
const observerAsync = function() {
for ( const nodelist of observerLists ) {
for ( const node of nodelist ) {
if ( node.nodeType !== 1 ) { continue; }
if ( node.parentElement === null ) { continue; }
if ( node.localName === 'iframe' ) {
@ -112,7 +112,7 @@
}
if ( node.childElementCount === 0 ) { continue; }
let iframes = node.querySelectorAll('iframe');
for ( let iframe of iframes ) {
for ( const iframe of iframes ) {
processIFrame(iframe);
}
}
@ -120,17 +120,17 @@
observerLists = [];
observerTimer = undefined;
};
let ready = function(ev) {
const ready = function(ev) {
if ( ev !== undefined ) {
window.removeEventListener(ev.type, ready);
}
let iframes = document.getElementsByTagName('iframe');
const iframes = document.getElementsByTagName('iframe');
if ( iframes.length !== 0 ) {
observerLists.push(iframes);
observerTimer = setTimeout(observerAsync, 1);
}
let observer = new MutationObserver(function(mutations) {
for ( let mutation of mutations ) {
const observer = new MutationObserver(function(mutations) {
for ( const mutation of mutations ) {
if ( mutation.addedNodes.length !== 0 ) {
observerLists.push(mutation.addedNodes);
}
@ -380,9 +380,24 @@
if ( out.length === 0 ) { return; }
if ( µb.hiddenSettings.debugScriptlets ) {
out.unshift('debugger');
out.unshift('debugger;');
}
// https://github.com/uBlockOrigin/uBlock-issues/issues/156
// Provide a private Map() object available for use by all
// scriptlets.
out.unshift(
'(function() {',
'// >>>> start of private namespace',
'const uBOSafe = new Map();',
'',
);
out.push(
'',
'// <<<< end of private namespace',
'})();',
);
return out.join('\n');
};