📝 Added entire config directory for backup purposes
This commit is contained in:
parent
4b38e59bb6
commit
9b946e2d14
11091 changed files with 1440953 additions and 0 deletions
|
|
@ -0,0 +1,386 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2015-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
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
(( ) => {
|
||||
// >>>>>>>> start of private namespace
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if (
|
||||
typeof vAPI !== 'object' ||
|
||||
vAPI.domWatcher instanceof Object === false
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const reHasCSSCombinators = /[ >+~]/;
|
||||
const simpleDeclarativeSet = new Set();
|
||||
let simpleDeclarativeStr;
|
||||
const complexDeclarativeSet = new Set();
|
||||
let complexDeclarativeStr;
|
||||
const declarativeStyleDict = new Map();
|
||||
let declarativeStyleStr;
|
||||
const proceduralDict = new Map();
|
||||
const exceptionDict = new Map();
|
||||
let exceptionStr;
|
||||
const proceduralExceptionDict = new Map();
|
||||
const nodesToProcess = new Set();
|
||||
const loggedSelectors = new Set();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const rePseudoElements = /:(?::?after|:?before|:[a-z-]+)$/;
|
||||
|
||||
const safeMatchSelector = function(selector, context) {
|
||||
const safeSelector = rePseudoElements.test(selector)
|
||||
? selector.replace(rePseudoElements, '')
|
||||
: selector;
|
||||
return context.matches(safeSelector);
|
||||
};
|
||||
|
||||
const safeQuerySelector = function(selector, context = document) {
|
||||
const safeSelector = rePseudoElements.test(selector)
|
||||
? selector.replace(rePseudoElements, '')
|
||||
: selector;
|
||||
return context.querySelector(safeSelector);
|
||||
};
|
||||
|
||||
const safeGroupSelectors = function(selectors) {
|
||||
const arr = Array.isArray(selectors)
|
||||
? selectors
|
||||
: Array.from(selectors);
|
||||
return arr.map(s => {
|
||||
return rePseudoElements.test(s)
|
||||
? s.replace(rePseudoElements, '')
|
||||
: s;
|
||||
}).join(',\n');
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const processDeclarativeSimple = function(node, out) {
|
||||
if ( simpleDeclarativeSet.size === 0 ) { return; }
|
||||
if ( simpleDeclarativeStr === undefined ) {
|
||||
simpleDeclarativeStr = safeGroupSelectors(simpleDeclarativeSet);
|
||||
}
|
||||
if (
|
||||
(node === document || node.matches(simpleDeclarativeStr) === false) &&
|
||||
(node.querySelector(simpleDeclarativeStr) === null)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
for ( const selector of simpleDeclarativeSet ) {
|
||||
if (
|
||||
(node === document || safeMatchSelector(selector, node) === false) &&
|
||||
(safeQuerySelector(selector, node) === null)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
out.push(`##${selector}`);
|
||||
simpleDeclarativeSet.delete(selector);
|
||||
simpleDeclarativeStr = undefined;
|
||||
loggedSelectors.add(selector);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const processDeclarativeComplex = function(out) {
|
||||
if ( complexDeclarativeSet.size === 0 ) { return; }
|
||||
if ( complexDeclarativeStr === undefined ) {
|
||||
complexDeclarativeStr = safeGroupSelectors(complexDeclarativeSet);
|
||||
}
|
||||
if ( document.querySelector(complexDeclarativeStr) === null ) { return; }
|
||||
for ( const selector of complexDeclarativeSet ) {
|
||||
if ( safeQuerySelector(selector) === null ) { continue; }
|
||||
out.push(`##${selector}`);
|
||||
complexDeclarativeSet.delete(selector);
|
||||
complexDeclarativeStr = undefined;
|
||||
loggedSelectors.add(selector);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const processDeclarativeStyle = function(out) {
|
||||
if ( declarativeStyleDict.size === 0 ) { return; }
|
||||
if ( declarativeStyleStr === undefined ) {
|
||||
declarativeStyleStr = safeGroupSelectors(declarativeStyleDict.keys());
|
||||
}
|
||||
if ( document.querySelector(declarativeStyleStr) === null ) { return; }
|
||||
for ( const selector of declarativeStyleDict.keys() ) {
|
||||
if ( safeQuerySelector(selector) === null ) { continue; }
|
||||
for ( const style of declarativeStyleDict.get(selector) ) {
|
||||
const raw = `##${selector}:style(${style})`;
|
||||
out.push(raw);
|
||||
loggedSelectors.add(raw);
|
||||
}
|
||||
declarativeStyleDict.delete(selector);
|
||||
declarativeStyleStr = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const processProcedural = function(out) {
|
||||
if ( proceduralDict.size === 0 ) { return; }
|
||||
for ( const [ raw, pselector ] of proceduralDict ) {
|
||||
if ( pselector.hit === false ) { continue; }
|
||||
out.push(`##${raw}`);
|
||||
proceduralDict.delete(raw);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const processExceptions = function(out) {
|
||||
if ( exceptionDict.size === 0 ) { return; }
|
||||
if ( exceptionStr === undefined ) {
|
||||
exceptionStr = safeGroupSelectors(exceptionDict.keys());
|
||||
}
|
||||
if ( document.querySelector(exceptionStr) === null ) { return; }
|
||||
for ( const [ selector, raw ] of exceptionDict ) {
|
||||
if ( safeQuerySelector(selector) === null ) { continue; }
|
||||
out.push(`#@#${raw}`);
|
||||
exceptionDict.delete(selector);
|
||||
exceptionStr = undefined;
|
||||
loggedSelectors.add(raw);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const processProceduralExceptions = function(out) {
|
||||
if ( proceduralExceptionDict.size === 0 ) { return; }
|
||||
for ( const exception of proceduralExceptionDict.values() ) {
|
||||
if ( exception.test() === false ) { continue; }
|
||||
out.push(`#@#${exception.raw}`);
|
||||
proceduralExceptionDict.delete(exception.raw);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const processTimer = new vAPI.SafeAnimationFrame(( ) => {
|
||||
//console.time('dom logger/scanning for matches');
|
||||
processTimer.clear();
|
||||
if ( nodesToProcess.size === 0 ) { return; }
|
||||
|
||||
if ( nodesToProcess.size !== 1 && nodesToProcess.has(document) ) {
|
||||
nodesToProcess.clear();
|
||||
nodesToProcess.add(document);
|
||||
}
|
||||
|
||||
const toLog = [];
|
||||
if ( simpleDeclarativeSet.size !== 0 ) {
|
||||
for ( const node of nodesToProcess ) {
|
||||
processDeclarativeSimple(node, toLog);
|
||||
}
|
||||
}
|
||||
|
||||
processDeclarativeComplex(toLog);
|
||||
processDeclarativeStyle(toLog);
|
||||
processProcedural(toLog);
|
||||
processExceptions(toLog);
|
||||
processProceduralExceptions(toLog);
|
||||
|
||||
nodesToProcess.clear();
|
||||
|
||||
if ( toLog.length === 0 ) { return; }
|
||||
|
||||
const location = vAPI.effectiveSelf.location;
|
||||
|
||||
vAPI.messaging.send('scriptlets', {
|
||||
what: 'logCosmeticFilteringData',
|
||||
frameURL: location.href,
|
||||
frameHostname: location.hostname,
|
||||
matchedSelectors: toLog,
|
||||
});
|
||||
//console.timeEnd('dom logger/scanning for matches');
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const attributeObserver = new MutationObserver(mutations => {
|
||||
if ( nodesToProcess.has(document) ) { return; }
|
||||
for ( const mutation of mutations ) {
|
||||
const node = mutation.target;
|
||||
if ( node.nodeType !== 1 ) { continue; }
|
||||
nodesToProcess.add(node);
|
||||
}
|
||||
if ( nodesToProcess.size !== 0 ) {
|
||||
processTimer.start(100);
|
||||
}
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const handlers = {
|
||||
onFiltersetChanged: function(changes) {
|
||||
//console.time('dom logger/filterset changed');
|
||||
for ( const entry of (changes.declarative || []) ) {
|
||||
for ( let selector of entry[0].split(',\n') ) {
|
||||
if ( entry[1] !== 'display:none!important;' ) {
|
||||
declarativeStyleStr = undefined;
|
||||
const styles = declarativeStyleDict.get(selector);
|
||||
if ( styles === undefined ) {
|
||||
declarativeStyleDict.set(selector, [ entry[1] ]);
|
||||
continue;
|
||||
}
|
||||
styles.push(entry[1]);
|
||||
continue;
|
||||
}
|
||||
if ( loggedSelectors.has(selector) ) { continue; }
|
||||
if ( reHasCSSCombinators.test(selector) ) {
|
||||
complexDeclarativeSet.add(selector);
|
||||
complexDeclarativeStr = undefined;
|
||||
} else {
|
||||
simpleDeclarativeSet.add(selector);
|
||||
simpleDeclarativeStr = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
Array.isArray(changes.procedural) &&
|
||||
changes.procedural.length !== 0
|
||||
) {
|
||||
for ( const selector of changes.procedural ) {
|
||||
proceduralDict.set(selector.raw, selector);
|
||||
}
|
||||
}
|
||||
if ( Array.isArray(changes.exceptions) ) {
|
||||
for ( const selector of changes.exceptions ) {
|
||||
if ( loggedSelectors.has(selector) ) { continue; }
|
||||
if ( selector.charCodeAt(0) !== 0x7B /* '{' */ ) {
|
||||
exceptionDict.set(selector, selector);
|
||||
continue;
|
||||
}
|
||||
const details = JSON.parse(selector);
|
||||
if (
|
||||
details.action !== undefined &&
|
||||
details.tasks === undefined &&
|
||||
details.action[0] === ':style'
|
||||
) {
|
||||
exceptionDict.set(details.selector, details.raw);
|
||||
continue;
|
||||
}
|
||||
proceduralExceptionDict.set(
|
||||
details.raw,
|
||||
vAPI.domFilterer.createProceduralFilter(details)
|
||||
);
|
||||
}
|
||||
exceptionStr = undefined;
|
||||
}
|
||||
nodesToProcess.clear();
|
||||
nodesToProcess.add(document);
|
||||
processTimer.start(1);
|
||||
//console.timeEnd('dom logger/filterset changed');
|
||||
},
|
||||
|
||||
onDOMCreated: function() {
|
||||
if ( vAPI.domFilterer instanceof Object === false ) {
|
||||
return shutdown();
|
||||
}
|
||||
handlers.onFiltersetChanged(vAPI.domFilterer.getAllSelectors());
|
||||
vAPI.domFilterer.addListener(handlers);
|
||||
attributeObserver.observe(document.body, {
|
||||
attributes: true,
|
||||
subtree: true
|
||||
});
|
||||
},
|
||||
|
||||
onDOMChanged: function(addedNodes) {
|
||||
if ( nodesToProcess.has(document) ) { return; }
|
||||
for ( const node of addedNodes ) {
|
||||
if ( node.parentNode === null ) { continue; }
|
||||
nodesToProcess.add(node);
|
||||
}
|
||||
if ( nodesToProcess.size !== 0 ) {
|
||||
processTimer.start(100);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const shutdown = function() {
|
||||
processTimer.clear();
|
||||
attributeObserver.disconnect();
|
||||
if ( typeof vAPI !== 'object' ) { return; }
|
||||
if ( vAPI.domFilterer instanceof Object ) {
|
||||
vAPI.domFilterer.removeListener(handlers);
|
||||
}
|
||||
if ( vAPI.domWatcher instanceof Object ) {
|
||||
vAPI.domWatcher.removeListener(handlers);
|
||||
}
|
||||
if ( vAPI.broadcastListener instanceof Object ) {
|
||||
vAPI.broadcastListener.remove(broadcastListener);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const broadcastListener = msg => {
|
||||
if ( msg.what === 'loggerDisabled' ) {
|
||||
shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.messaging.extend().then(extended => {
|
||||
if ( extended !== true ) {
|
||||
return shutdown();
|
||||
}
|
||||
vAPI.broadcastListener.add(broadcastListener);
|
||||
});
|
||||
|
||||
vAPI.domWatcher.addListener(handlers);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// <<<<<<<< end of private namespace
|
||||
})();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
DO NOT:
|
||||
- Remove the following code
|
||||
- Add code beyond the following code
|
||||
Reason:
|
||||
- https://github.com/gorhill/uBlock/pull/3721
|
||||
- uBO never uses the return value from injected content scripts
|
||||
|
||||
**/
|
||||
|
||||
void 0;
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2015-2018 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
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if ( typeof vAPI === 'object' && vAPI.domFilterer ) {
|
||||
vAPI.domFilterer.toggle(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
DO NOT:
|
||||
- Remove the following code
|
||||
- Add code beyond the following code
|
||||
Reason:
|
||||
- https://github.com/gorhill/uBlock/pull/3721
|
||||
- uBO never uses the return value from injected content scripts
|
||||
|
||||
**/
|
||||
|
||||
void 0;
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2015-2018 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
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if ( typeof vAPI === 'object' && vAPI.domFilterer ) {
|
||||
vAPI.domFilterer.toggle(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
DO NOT:
|
||||
- Remove the following code
|
||||
- Add code beyond the following code
|
||||
Reason:
|
||||
- https://github.com/gorhill/uBlock/pull/3721
|
||||
- uBO never uses the return value from injected content scripts
|
||||
|
||||
**/
|
||||
|
||||
void 0;
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,72 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2015-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
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/756
|
||||
// Keep in mind CPU usage with large DOM and/or filterset.
|
||||
|
||||
(( ) => {
|
||||
if ( typeof vAPI !== 'object' ) { return; }
|
||||
|
||||
const t0 = Date.now();
|
||||
|
||||
if ( vAPI.domSurveyElements instanceof Object === false ) {
|
||||
vAPI.domSurveyElements = {
|
||||
busy: false,
|
||||
hiddenElementCount: Number.NaN,
|
||||
surveyTime: t0,
|
||||
};
|
||||
}
|
||||
const surveyResults = vAPI.domSurveyElements;
|
||||
|
||||
if ( surveyResults.busy ) { return; }
|
||||
surveyResults.busy = true;
|
||||
|
||||
if ( surveyResults.surveyTime < vAPI.domMutationTime ) {
|
||||
surveyResults.hiddenElementCount = Number.NaN;
|
||||
}
|
||||
surveyResults.surveyTime = t0;
|
||||
|
||||
if ( isNaN(surveyResults.hiddenElementCount) ) {
|
||||
surveyResults.hiddenElementCount = (( ) => {
|
||||
if ( vAPI.domFilterer instanceof Object === false ) { return 0; }
|
||||
const details = vAPI.domFilterer.getAllSelectors(0b11);
|
||||
if (
|
||||
Array.isArray(details.declarative) === false ||
|
||||
details.declarative.length === 0
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
return document.querySelectorAll(
|
||||
details.declarative.map(entry => entry[0]).join(',')
|
||||
).length;
|
||||
})();
|
||||
}
|
||||
|
||||
surveyResults.busy = false;
|
||||
|
||||
// IMPORTANT: This is returned to the injector, so this MUST be
|
||||
// the last statement.
|
||||
return surveyResults.hiddenElementCount;
|
||||
})();
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2015-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
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Scriptlets to count the number of script tags in a document.
|
||||
|
||||
(( ) => {
|
||||
if ( typeof vAPI !== 'object' ) { return; }
|
||||
|
||||
const t0 = Date.now();
|
||||
|
||||
if ( vAPI.domSurveyScripts instanceof Object === false ) {
|
||||
vAPI.domSurveyScripts = {
|
||||
busy: false,
|
||||
scriptCount: -1,
|
||||
surveyTime: t0,
|
||||
};
|
||||
}
|
||||
const surveyResults = vAPI.domSurveyScripts;
|
||||
|
||||
if ( surveyResults.busy ) { return; }
|
||||
surveyResults.busy = true;
|
||||
|
||||
if ( surveyResults.surveyTime < vAPI.domMutationTime ) {
|
||||
surveyResults.scriptCount = -1;
|
||||
}
|
||||
surveyResults.surveyTime = t0;
|
||||
|
||||
if ( surveyResults.scriptCount === -1 ) {
|
||||
const reInlineScript = /^(data:|blob:|$)/;
|
||||
let inlineScriptCount = 0;
|
||||
let scriptCount = 0;
|
||||
for ( const script of document.scripts ) {
|
||||
if ( reInlineScript.test(script.src) ) {
|
||||
inlineScriptCount = 1;
|
||||
continue;
|
||||
}
|
||||
scriptCount += 1;
|
||||
if ( scriptCount === 99 ) { break; }
|
||||
}
|
||||
scriptCount += inlineScriptCount;
|
||||
if ( scriptCount !== 0 ) {
|
||||
surveyResults.scriptCount = scriptCount;
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/756
|
||||
// Keep trying to find inline script-like instances but only if we
|
||||
// have the time-budget to do so.
|
||||
if ( surveyResults.scriptCount === -1 ) {
|
||||
if ( document.querySelector('a[href^="javascript:"]') !== null ) {
|
||||
surveyResults.scriptCount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( surveyResults.scriptCount === -1 ) {
|
||||
surveyResults.scriptCount = 0;
|
||||
const onHandlers = new Set([
|
||||
'onabort', 'onblur', 'oncancel', 'oncanplay',
|
||||
'oncanplaythrough', 'onchange', 'onclick', 'onclose',
|
||||
'oncontextmenu', 'oncuechange', 'ondblclick', 'ondrag',
|
||||
'ondragend', 'ondragenter', 'ondragexit', 'ondragleave',
|
||||
'ondragover', 'ondragstart', 'ondrop', 'ondurationchange',
|
||||
'onemptied', 'onended', 'onerror', 'onfocus',
|
||||
'oninput', 'oninvalid', 'onkeydown', 'onkeypress',
|
||||
'onkeyup', 'onload', 'onloadeddata', 'onloadedmetadata',
|
||||
'onloadstart', 'onmousedown', 'onmouseenter', 'onmouseleave',
|
||||
'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup',
|
||||
'onwheel', 'onpause', 'onplay', 'onplaying',
|
||||
'onprogress', 'onratechange', 'onreset', 'onresize',
|
||||
'onscroll', 'onseeked', 'onseeking', 'onselect',
|
||||
'onshow', 'onstalled', 'onsubmit', 'onsuspend',
|
||||
'ontimeupdate', 'ontoggle', 'onvolumechange', 'onwaiting',
|
||||
'onafterprint', 'onbeforeprint', 'onbeforeunload', 'onhashchange',
|
||||
'onlanguagechange', 'onmessage', 'onoffline', 'ononline',
|
||||
'onpagehide', 'onpageshow', 'onrejectionhandled', 'onpopstate',
|
||||
'onstorage', 'onunhandledrejection', 'onunload',
|
||||
'oncopy', 'oncut', 'onpaste'
|
||||
]);
|
||||
const nodeIter = document.createNodeIterator(
|
||||
document.body,
|
||||
NodeFilter.SHOW_ELEMENT
|
||||
);
|
||||
for (;;) {
|
||||
const node = nodeIter.nextNode();
|
||||
if ( node === null ) { break; }
|
||||
if ( node.hasAttributes() === false ) { continue; }
|
||||
for ( const attr of node.getAttributeNames() ) {
|
||||
if ( onHandlers.has(attr) === false ) { continue; }
|
||||
surveyResults.scriptCount = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
surveyResults.busy = false;
|
||||
|
||||
// IMPORTANT: This is returned to the injector, so this MUST be
|
||||
// the last statement.
|
||||
if ( surveyResults.scriptCount !== -1 ) {
|
||||
return surveyResults.scriptCount;
|
||||
}
|
||||
})();
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,67 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2020-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
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
(( ) => {
|
||||
if ( typeof vAPI !== 'object' ) { return; }
|
||||
|
||||
if ( vAPI.dynamicReloadToken === undefined ) {
|
||||
vAPI.dynamicReloadToken = vAPI.randomToken();
|
||||
}
|
||||
|
||||
for ( const sheet of Array.from(document.styleSheets) ) {
|
||||
let loaded = false;
|
||||
try {
|
||||
loaded = sheet.rules.length !== 0;
|
||||
} catch(ex) {
|
||||
}
|
||||
if ( loaded ) { continue; }
|
||||
const link = sheet.ownerNode || null;
|
||||
if ( link === null || link.localName !== 'link' ) { continue; }
|
||||
if ( link.hasAttribute(vAPI.dynamicReloadToken) ) { continue; }
|
||||
const clone = link.cloneNode(true);
|
||||
clone.setAttribute(vAPI.dynamicReloadToken, '');
|
||||
link.replaceWith(clone);
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
DO NOT:
|
||||
- Remove the following code
|
||||
- Add code beyond the following code
|
||||
Reason:
|
||||
- https://github.com/gorhill/uBlock/pull/3721
|
||||
- uBO never uses the return value from injected content scripts
|
||||
|
||||
**/
|
||||
|
||||
void 0;
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2015-2018 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
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
(( ) => {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if (
|
||||
typeof vAPI !== 'object' ||
|
||||
vAPI.loadAllLargeMedia instanceof Function === false
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
vAPI.loadAllLargeMedia();
|
||||
vAPI.loadAllLargeMedia = undefined;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
DO NOT:
|
||||
- Remove the following code
|
||||
- Add code beyond the following code
|
||||
Reason:
|
||||
- https://github.com/gorhill/uBlock/pull/3721
|
||||
- uBO never uses the return value from injected content scripts
|
||||
|
||||
**/
|
||||
|
||||
void 0;
|
||||
|
|
@ -0,0 +1,299 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2015-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
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
(( ) => {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// This can happen
|
||||
if ( typeof vAPI !== 'object' || vAPI.loadAllLargeMedia instanceof Function ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const largeMediaElementAttribute = 'data-' + vAPI.sessionId;
|
||||
const largeMediaElementSelector =
|
||||
':root audio[' + largeMediaElementAttribute + '],\n' +
|
||||
':root img[' + largeMediaElementAttribute + '],\n' +
|
||||
':root picture[' + largeMediaElementAttribute + '],\n' +
|
||||
':root video[' + largeMediaElementAttribute + ']';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const isMediaElement = function(elem) {
|
||||
return /^(?:audio|img|picture|video)$/.test(elem.localName);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const mediaNotLoaded = function(elem) {
|
||||
switch ( elem.localName ) {
|
||||
case 'audio':
|
||||
case 'video': {
|
||||
const src = elem.src || '';
|
||||
if ( src.startsWith('blob:') ) {
|
||||
elem.autoplay = false;
|
||||
elem.pause();
|
||||
}
|
||||
return elem.readyState === 0 || elem.error !== null;
|
||||
}
|
||||
case 'img': {
|
||||
if ( elem.naturalWidth !== 0 || elem.naturalHeight !== 0 ) {
|
||||
break;
|
||||
}
|
||||
const style = window.getComputedStyle(elem);
|
||||
// For some reason, style can be null with Pale Moon.
|
||||
return style !== null ?
|
||||
style.getPropertyValue('display') !== 'none' :
|
||||
elem.offsetHeight !== 0 && elem.offsetWidth !== 0;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// For all media resources which have failed to load, trigger a reload.
|
||||
|
||||
// <audio> and <video> elements.
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
|
||||
|
||||
const surveyMissingMediaElements = function() {
|
||||
let largeMediaElementCount = 0;
|
||||
for ( const elem of document.querySelectorAll('audio,img,video') ) {
|
||||
if ( mediaNotLoaded(elem) === false ) { continue; }
|
||||
elem.setAttribute(largeMediaElementAttribute, '');
|
||||
largeMediaElementCount += 1;
|
||||
switch ( elem.localName ) {
|
||||
case 'img': {
|
||||
const picture = elem.closest('picture');
|
||||
if ( picture !== null ) {
|
||||
picture.setAttribute(largeMediaElementAttribute, '');
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return largeMediaElementCount;
|
||||
};
|
||||
|
||||
if ( surveyMissingMediaElements() === 0 ) { return; }
|
||||
|
||||
// Insert CSS to highlight blocked media elements.
|
||||
if ( vAPI.largeMediaElementStyleSheet === undefined ) {
|
||||
vAPI.largeMediaElementStyleSheet = [
|
||||
largeMediaElementSelector + ' {',
|
||||
'border: 2px dotted red !important;',
|
||||
'box-sizing: border-box !important;',
|
||||
'cursor: zoom-in !important;',
|
||||
'display: inline-block;',
|
||||
'filter: none !important;',
|
||||
'font-size: 1rem !important;',
|
||||
'min-height: 1em !important;',
|
||||
'min-width: 1em !important;',
|
||||
'opacity: 1 !important;',
|
||||
'outline: none !important;',
|
||||
'transform: none !important;',
|
||||
'visibility: visible !important;',
|
||||
'z-index: 2147483647',
|
||||
'}',
|
||||
].join('\n');
|
||||
vAPI.userStylesheet.add(vAPI.largeMediaElementStyleSheet);
|
||||
vAPI.userStylesheet.apply();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const loadMedia = async function(elem) {
|
||||
const src = elem.getAttribute('src') || '';
|
||||
elem.removeAttribute('src');
|
||||
|
||||
await vAPI.messaging.send('scriptlets', {
|
||||
what: 'temporarilyAllowLargeMediaElement',
|
||||
});
|
||||
|
||||
if ( src !== '' ) {
|
||||
elem.setAttribute('src', src);
|
||||
}
|
||||
elem.load();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const loadImage = async function(elem) {
|
||||
const src = elem.getAttribute('src') || '';
|
||||
elem.removeAttribute('src');
|
||||
|
||||
await vAPI.messaging.send('scriptlets', {
|
||||
what: 'temporarilyAllowLargeMediaElement',
|
||||
});
|
||||
|
||||
if ( src !== '' ) {
|
||||
elem.setAttribute('src', src);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const loadMany = function(elems) {
|
||||
for ( const elem of elems ) {
|
||||
switch ( elem.localName ) {
|
||||
case 'audio':
|
||||
case 'video':
|
||||
loadMedia(elem);
|
||||
break;
|
||||
case 'img':
|
||||
loadImage(elem);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const onMouseClick = function(ev) {
|
||||
if ( ev.button !== 0 || ev.isTrusted === false ) { return; }
|
||||
|
||||
const toLoad = [];
|
||||
const elems = document.elementsFromPoint instanceof Function
|
||||
? document.elementsFromPoint(ev.clientX, ev.clientY)
|
||||
: [ ev.target ];
|
||||
for ( const elem of elems ) {
|
||||
if ( elem.matches(largeMediaElementSelector) === false ) { continue; }
|
||||
elem.removeAttribute(largeMediaElementAttribute);
|
||||
if ( mediaNotLoaded(elem) ) {
|
||||
toLoad.push(elem);
|
||||
}
|
||||
}
|
||||
|
||||
if ( toLoad.length === 0 ) { return; }
|
||||
|
||||
loadMany(toLoad);
|
||||
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
};
|
||||
|
||||
document.addEventListener('click', onMouseClick, true);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const onLoadedData = function(ev) {
|
||||
const media = ev.target;
|
||||
if ( media.localName !== 'audio' && media.localName !== 'video' ) {
|
||||
return;
|
||||
}
|
||||
const src = media.src;
|
||||
if ( typeof src === 'string' && src.startsWith('blob:') === false ) {
|
||||
return;
|
||||
}
|
||||
media.autoplay = false;
|
||||
media.pause();
|
||||
};
|
||||
|
||||
// https://www.reddit.com/r/uBlockOrigin/comments/mxgpmc/
|
||||
// Support cases where the media source is not yet set.
|
||||
for ( const media of document.querySelectorAll('audio,video') ) {
|
||||
const src = media.src;
|
||||
if (
|
||||
(typeof src === 'string') &&
|
||||
(src === '' || src.startsWith('blob:'))
|
||||
) {
|
||||
media.autoplay = false;
|
||||
media.pause();
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('loadeddata', onLoadedData);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const onLoad = function(ev) {
|
||||
const elem = ev.target;
|
||||
if ( isMediaElement(elem) === false ) { return; }
|
||||
elem.removeAttribute(largeMediaElementAttribute);
|
||||
};
|
||||
|
||||
document.addEventListener('load', onLoad, true);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const onLoadError = function(ev) {
|
||||
const elem = ev.target;
|
||||
if ( isMediaElement(elem) === false ) { return; }
|
||||
if ( mediaNotLoaded(elem) ) {
|
||||
elem.setAttribute(largeMediaElementAttribute, '');
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('error', onLoadError, true);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.loadAllLargeMedia = function() {
|
||||
document.removeEventListener('click', onMouseClick, true);
|
||||
document.removeEventListener('loadeddata', onLoadedData, true);
|
||||
document.removeEventListener('load', onLoad, true);
|
||||
document.removeEventListener('error', onLoadError, true);
|
||||
|
||||
const toLoad = [];
|
||||
for ( const elem of document.querySelectorAll(largeMediaElementSelector) ) {
|
||||
elem.removeAttribute(largeMediaElementAttribute);
|
||||
if ( mediaNotLoaded(elem) ) {
|
||||
toLoad.push(elem);
|
||||
}
|
||||
}
|
||||
loadMany(toLoad);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
DO NOT:
|
||||
- Remove the following code
|
||||
- Add code beyond the following code
|
||||
Reason:
|
||||
- https://github.com/gorhill/uBlock/pull/3721
|
||||
- uBO never uses the return value from injected content scripts
|
||||
|
||||
**/
|
||||
|
||||
void 0;
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2014-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
|
||||
*/
|
||||
|
||||
// Code below has been imported from uMatrix and modified to fit uBO:
|
||||
// https://github.com/gorhill/uMatrix/blob/3f8794dd899a05e066c24066c6c0a2515d5c60d2/src/js/contentscript.js#L464-L531
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// https://github.com/gorhill/uMatrix/issues/232
|
||||
// Force `display` property, Firefox is still affected by the issue.
|
||||
|
||||
(function() {
|
||||
let noscripts = document.querySelectorAll('noscript');
|
||||
if ( noscripts.length === 0 ) { return; }
|
||||
|
||||
let redirectTimer,
|
||||
reMetaContent = /^\s*(\d+)\s*;\s*url=(['"]?)([^'"]+)\2/i,
|
||||
reSafeURL = /^https?:\/\//;
|
||||
|
||||
let autoRefresh = function(root) {
|
||||
let meta = root.querySelector('meta[http-equiv="refresh"][content]');
|
||||
if ( meta === null ) { return; }
|
||||
let match = reMetaContent.exec(meta.getAttribute('content'));
|
||||
if ( match === null || match[3].trim() === '' ) { return; }
|
||||
|
||||
let url;
|
||||
try {
|
||||
url = new URL(match[3], document.baseURI);
|
||||
} catch(ex) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( reSafeURL.test(url.href) === false ) { return; }
|
||||
redirectTimer = setTimeout(( ) => {
|
||||
location.assign(url.href);
|
||||
},
|
||||
parseInt(match[1], 10) * 1000 + 1
|
||||
);
|
||||
meta.parentNode.removeChild(meta);
|
||||
};
|
||||
|
||||
let morphNoscript = function(from) {
|
||||
if ( /^application\/(?:xhtml\+)?xml/.test(document.contentType) ) {
|
||||
let to = document.createElement('span');
|
||||
while ( from.firstChild !== null ) {
|
||||
to.appendChild(from.firstChild);
|
||||
}
|
||||
return to;
|
||||
}
|
||||
let parser = new DOMParser();
|
||||
let doc = parser.parseFromString(
|
||||
'<span>' + from.textContent + '</span>',
|
||||
'text/html'
|
||||
);
|
||||
return document.adoptNode(doc.querySelector('span'));
|
||||
};
|
||||
|
||||
for ( let noscript of noscripts ) {
|
||||
let parent = noscript.parentNode;
|
||||
if ( parent === null ) { continue; }
|
||||
let span = morphNoscript(noscript);
|
||||
span.style.setProperty('display', 'inline', 'important');
|
||||
if ( redirectTimer === undefined ) {
|
||||
autoRefresh(span);
|
||||
}
|
||||
parent.replaceChild(span, noscript);
|
||||
}
|
||||
})();
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2018-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
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// If content scripts are already injected, we need to respond with `false`,
|
||||
// to "should inject content scripts?"
|
||||
//
|
||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/403
|
||||
// If the content script was not boostrapped, give it another try.
|
||||
|
||||
(( ) => {
|
||||
try {
|
||||
let status = vAPI.uBO !== true;
|
||||
if ( status === false && vAPI.bootstrap ) {
|
||||
self.requestIdleCallback(( ) => vAPI && vAPI.bootstrap());
|
||||
}
|
||||
return status;
|
||||
} catch(ex) {
|
||||
}
|
||||
return true;
|
||||
})();
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2015-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
|
||||
*/
|
||||
|
||||
/* global HTMLDocument */
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Injected into specific web pages, those which have been pre-selected
|
||||
// because they are known to contains `abp:subscribe` links.
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
(( ) => {
|
||||
// >>>>> start of local scope
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/464
|
||||
if ( document instanceof HTMLDocument === false ) { return; }
|
||||
|
||||
// Maybe uBO has gone away meanwhile.
|
||||
if ( typeof vAPI !== 'object' || vAPI === null ) { return; }
|
||||
|
||||
// https://github.com/easylist/EasyListHebrew/issues/89
|
||||
// Ensure trusted events only.
|
||||
|
||||
const onMaybeSubscriptionLinkClicked = function(ev) {
|
||||
if ( ev.button !== 0 || ev.isTrusted === false ) { return; }
|
||||
|
||||
const target = ev.target.closest('a');
|
||||
if ( target instanceof HTMLAnchorElement === false ) { return; }
|
||||
|
||||
if ( vAPI instanceof Object === false ) {
|
||||
document.removeEventListener('click', onMaybeSubscriptionLinkClicked);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/763#issuecomment-691696716
|
||||
// Remove replacement patch if/when filterlists.com fixes encoded '&'.
|
||||
const subscribeURL = new URL(
|
||||
target.href.replace('&title=', '&title=')
|
||||
);
|
||||
if (
|
||||
/^(abp|ubo):$/.test(subscribeURL.protocol) === false &&
|
||||
subscribeURL.hostname !== 'subscribe.adblockplus.org'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const location = subscribeURL.searchParams.get('location') || '';
|
||||
const title = subscribeURL.searchParams.get('title') || '';
|
||||
if ( location === '' || title === '' ) { return; }
|
||||
vAPI.messaging.send('scriptlets', {
|
||||
what: 'subscribeTo',
|
||||
location,
|
||||
title,
|
||||
});
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
} catch (_) {
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', onMaybeSubscriptionLinkClicked);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// <<<<< end of local scope
|
||||
})();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
DO NOT:
|
||||
- Remove the following code
|
||||
- Add code beyond the following code
|
||||
Reason:
|
||||
- https://github.com/gorhill/uBlock/pull/3721
|
||||
- uBO never uses the return value from injected content scripts
|
||||
|
||||
**/
|
||||
|
||||
void 0;
|
||||
Loading…
Add table
Add a link
Reference in a new issue