mirror of https://github.com/gorhill/uBlock.git
Add trusted-source support for privileged scriptlets
At the moment, the only filter lists deemed from a "trusted source" are uBO-specific filter lists (i.e. "uBlock filters -- ..."), and the user's own filters from "My filters". A new scriptlet which can only be used by filter lists from trusted sources has been introduced: `sed.js`. The new `sed.js` scriptlet provides the ability to perform text-level substitutions. Usage: example.org##+js(sed, nodeName, pattern, replacement, ...) `nodeName` The name of the node for which the text content must be substituted. Valid node names can be found at: https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeName `pattern` A string or regex to find in the text content of the node as the target of substitution. `replacement` The replacement text. Can be omitted if the goal is to delete the text which matches the pattern. Cannot be omitted if extra pairs of parameters have to be used (see below). Optionally, extra pairs of parameters to modify the behavior of the scriptlet: `condition, pattern` A string or regex which must be found in the text content of the node in order for the substitution to occur. `sedCount, n` This will cause the scriptlet to stop after n instances of substitution. Since a mutation oberver is used by the scriptlet, it's advised to stop it whenever it becomes pointless. Default to zero, which means the scriptlet never stops. `tryCount, n` This will cause the scriptlet to stop after n instances of mutation observer run (regardless of whether a substitution occurred). Default to zero, which means the scriptlet never stops. `log, 1` This will cause the scriptlet to output information at the console, useful as a debugging tool for filter authors. The logging ability is supported only in the dev build of uBO. Examples of usage: example.com##+js(sed, script, /devtoolsDetector\.launch\(\)\;/, , sedCount, 1) example.com##+js(sed, #text, /^Advertisement$/)
This commit is contained in:
parent
2c7d91ba57
commit
41876336db
|
@ -68,14 +68,13 @@ builtinScriptlets.push({
|
||||||
name: 'pattern-to-regex.fn',
|
name: 'pattern-to-regex.fn',
|
||||||
fn: patternToRegex,
|
fn: patternToRegex,
|
||||||
});
|
});
|
||||||
function patternToRegex(pattern) {
|
function patternToRegex(pattern, flags = undefined) {
|
||||||
if ( pattern === '' ) {
|
if ( pattern === '' ) { return /^/; }
|
||||||
return /^/;
|
const match = /^\/(.+)\/([gimsu]*)$/.exec(pattern);
|
||||||
|
if ( match !== null ) {
|
||||||
|
return new RegExp(match[1], match[2] || flags);
|
||||||
}
|
}
|
||||||
if ( pattern.startsWith('/') && pattern.endsWith('/') ) {
|
return new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), flags);
|
||||||
return new RegExp(pattern.slice(1, -1));
|
|
||||||
}
|
|
||||||
return new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -394,7 +393,7 @@ function abortOnStackTrace(
|
||||||
for ( let line of err.stack.split(/[\n\r]+/) ) {
|
for ( let line of err.stack.split(/[\n\r]+/) ) {
|
||||||
if ( line.includes(exceptionToken) ) { continue; }
|
if ( line.includes(exceptionToken) ) { continue; }
|
||||||
line = line.trim();
|
line = line.trim();
|
||||||
let match = safe.RegExp_exec.call(reLine, line);
|
const match = safe.RegExp_exec.call(reLine, line);
|
||||||
if ( match === null ) { continue; }
|
if ( match === null ) { continue; }
|
||||||
let url = match[2];
|
let url = match[2];
|
||||||
if ( url.startsWith('(') ) { url = url.slice(1); }
|
if ( url.startsWith('(') ) { url = url.slice(1); }
|
||||||
|
@ -2122,6 +2121,9 @@ function callNothrow(
|
||||||
builtinScriptlets.push({
|
builtinScriptlets.push({
|
||||||
name: 'spoof-css.js',
|
name: 'spoof-css.js',
|
||||||
fn: spoofCSS,
|
fn: spoofCSS,
|
||||||
|
dependencies: [
|
||||||
|
'safe-self.fn',
|
||||||
|
],
|
||||||
});
|
});
|
||||||
function spoofCSS(
|
function spoofCSS(
|
||||||
selector,
|
selector,
|
||||||
|
@ -2137,19 +2139,30 @@ function spoofCSS(
|
||||||
if ( typeof args[i+1] !== 'string' ) { break; }
|
if ( typeof args[i+1] !== 'string' ) { break; }
|
||||||
propToValueMap.set(toCamelCase(args[i+0]), args[i+1]);
|
propToValueMap.set(toCamelCase(args[i+0]), args[i+1]);
|
||||||
}
|
}
|
||||||
|
const safe = safeSelf();
|
||||||
|
const canDebug = scriptletGlobals.has('canDebug');
|
||||||
|
const shouldDebug = canDebug && propToValueMap.get('debug') || 0;
|
||||||
|
const shouldLog = canDebug && propToValueMap.has('log') || 0;
|
||||||
|
const proxiedStyles = new WeakSet();
|
||||||
|
const spoofStyle = (prop, real) => {
|
||||||
|
const normalProp = toCamelCase(prop);
|
||||||
|
const shouldSpoof = propToValueMap.has(normalProp);
|
||||||
|
const value = shouldSpoof ? propToValueMap.get(normalProp) : real;
|
||||||
|
if ( shouldLog === 2 || shouldSpoof && shouldLog === 1 ) {
|
||||||
|
safe.uboLog(prop, value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
self.getComputedStyle = new Proxy(self.getComputedStyle, {
|
self.getComputedStyle = new Proxy(self.getComputedStyle, {
|
||||||
apply: function(target, thisArg, args) {
|
apply: function(target, thisArg, args) {
|
||||||
if ( propToValueMap.has('debug') ) { debugger; } // jshint ignore: line
|
if ( shouldDebug !== 0 ) { debugger; } // jshint ignore: line
|
||||||
const style = Reflect.apply(target, thisArg, args);
|
const style = Reflect.apply(target, thisArg, args);
|
||||||
const targetElements = new WeakSet(document.querySelectorAll(selector));
|
const targetElements = new WeakSet(document.querySelectorAll(selector));
|
||||||
if ( targetElements.has(args[0]) === false ) { return style; }
|
if ( targetElements.has(args[0]) === false ) { return style; }
|
||||||
|
proxiedStyles.add(target);
|
||||||
const proxiedStyle = new Proxy(style, {
|
const proxiedStyle = new Proxy(style, {
|
||||||
get(target, prop, receiver) {
|
get(target, prop, receiver) {
|
||||||
const normalProp = toCamelCase(prop);
|
return spoofStyle(prop, Reflect.get(target, prop, receiver));
|
||||||
const value = propToValueMap.has(normalProp)
|
|
||||||
? propToValueMap.get(normalProp)
|
|
||||||
: Reflect.get(target, prop, receiver);
|
|
||||||
return value;
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return proxiedStyle;
|
return proxiedStyle;
|
||||||
|
@ -2161,9 +2174,23 @@ function spoofCSS(
|
||||||
return Reflect.get(target, prop, receiver);
|
return Reflect.get(target, prop, receiver);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
CSSStyleDeclaration.prototype.getPropertyValue = new Proxy(CSSStyleDeclaration.prototype.getPropertyValue, {
|
||||||
|
apply: function(target, thisArg, args) {
|
||||||
|
if ( shouldDebug !== 0 ) { debugger; } // jshint ignore: line
|
||||||
|
const value = Reflect.apply(target, thisArg, args);
|
||||||
|
if ( proxiedStyles.has(thisArg) === false ) { return value; }
|
||||||
|
return spoofStyle(args[0], value);
|
||||||
|
},
|
||||||
|
get(target, prop, receiver) {
|
||||||
|
if ( prop === 'toString' ) {
|
||||||
|
return target.toString.bind(target);
|
||||||
|
}
|
||||||
|
return Reflect.get(target, prop, receiver);
|
||||||
|
},
|
||||||
|
});
|
||||||
Element.prototype.getBoundingClientRect = new Proxy(Element.prototype.getBoundingClientRect, {
|
Element.prototype.getBoundingClientRect = new Proxy(Element.prototype.getBoundingClientRect, {
|
||||||
apply: function(target, thisArg, args) {
|
apply: function(target, thisArg, args) {
|
||||||
if ( propToValueMap.has('debug') ) { debugger; } // jshint ignore: line
|
if ( shouldDebug !== 0 ) { debugger; } // jshint ignore: line
|
||||||
const rect = Reflect.apply(target, thisArg, args);
|
const rect = Reflect.apply(target, thisArg, args);
|
||||||
const targetElements = new WeakSet(document.querySelectorAll(selector));
|
const targetElements = new WeakSet(document.querySelectorAll(selector));
|
||||||
if ( targetElements.has(thisArg) === false ) { return rect; }
|
if ( targetElements.has(thisArg) === false ) { return rect; }
|
||||||
|
@ -2186,3 +2213,62 @@ function spoofCSS(
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
builtinScriptlets.push({
|
||||||
|
name: 'sed.js',
|
||||||
|
requiresTrust: true,
|
||||||
|
fn: sed,
|
||||||
|
dependencies: [
|
||||||
|
'pattern-to-regex.fn',
|
||||||
|
'safe-self.fn',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
function sed(
|
||||||
|
nodeName = '',
|
||||||
|
pattern = '',
|
||||||
|
replacement = ''
|
||||||
|
) {
|
||||||
|
const reNodeName = patternToRegex(nodeName, 'i');
|
||||||
|
const rePattern = patternToRegex(pattern, 'gms');
|
||||||
|
const extraArgs = new Map(
|
||||||
|
Array.from(arguments).slice(3).reduce((out, v, i, a) => {
|
||||||
|
if ( (i & 1) === 0 ) { out.push([ a[i], a[i+1] || undefined ]); }
|
||||||
|
return out;
|
||||||
|
}, [])
|
||||||
|
);
|
||||||
|
const shouldLog = scriptletGlobals.has('canDebug') && extraArgs.get('log') || 0;
|
||||||
|
const reCondition = patternToRegex(extraArgs.get('condition') || '', 'gms');
|
||||||
|
let sedCount = extraArgs.has('sedCount') ? parseInt(extraArgs.get('sedCount')) : 0;
|
||||||
|
let tryCount = extraArgs.has('tryCount') ? parseInt(extraArgs.get('tryCount')) : 0;
|
||||||
|
const safe = safeSelf();
|
||||||
|
const handler = mutations => {
|
||||||
|
for ( const mutation of mutations ) {
|
||||||
|
for ( const node of mutation.addedNodes ) {
|
||||||
|
if ( reNodeName.test(node.nodeName) === false ) { continue; }
|
||||||
|
const before = node.textContent;
|
||||||
|
if ( safe.RegExp_test.call(rePattern, before) === false ) { continue; }
|
||||||
|
if ( safe.RegExp_test.call(reCondition, before) === false ) { continue; }
|
||||||
|
if ( shouldLog !== 0 ) { safe.uboLog('sed.js before:\n', before); }
|
||||||
|
const after = before.replace(rePattern, replacement);
|
||||||
|
if ( shouldLog !== 0 ) { safe.uboLog('sed.js after:\n', after); }
|
||||||
|
node.textContent = after;
|
||||||
|
if ( sedCount !== 0 && (sedCount -= 1) === 0 ) {
|
||||||
|
observer.disconnect();
|
||||||
|
if ( shouldLog !== 0 ) { safe.uboLog('sed.js: quitting'); }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( tryCount !== 0 && (tryCount -= 1) === 0 ) {
|
||||||
|
observer.disconnect();
|
||||||
|
if ( shouldLog !== 0 ) { safe.uboLog('sed.js: quitting'); }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const observer = new MutationObserver(handler);
|
||||||
|
observer.observe(document.documentElement, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
|
@ -86,6 +86,7 @@ class RedirectEntry {
|
||||||
this.data = '';
|
this.data = '';
|
||||||
this.warURL = undefined;
|
this.warURL = undefined;
|
||||||
this.params = undefined;
|
this.params = undefined;
|
||||||
|
this.requiresTrust = false;
|
||||||
this.dependencies = [];
|
this.dependencies = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,21 +150,16 @@ class RedirectEntry {
|
||||||
return this.data;
|
return this.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromContent(mime, content, dependencies = []) {
|
static fromDetails(details) {
|
||||||
const r = new RedirectEntry();
|
const r = new RedirectEntry();
|
||||||
r.mime = mime;
|
r.mime = details.mime;
|
||||||
r.data = content;
|
r.data = details.data;
|
||||||
r.dependencies.push(...dependencies);
|
r.requiresTrust = details.requiresTrust === true;
|
||||||
return r;
|
r.warURL = details.warURL !== undefined && details.warURL || undefined;
|
||||||
}
|
r.params = details.params !== undefined && details.params || undefined;
|
||||||
|
if ( Array.isArray(details.dependencies) ) {
|
||||||
static fromSelfie(selfie) {
|
r.dependencies.push(...details.dependencies);
|
||||||
const r = new RedirectEntry();
|
}
|
||||||
r.mime = selfie.mime;
|
|
||||||
r.data = selfie.data;
|
|
||||||
r.warURL = selfie.warURL;
|
|
||||||
r.params = selfie.params;
|
|
||||||
r.dependencies = selfie.dependencies || [];
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,6 +209,11 @@ class RedirectEngine {
|
||||||
return this.resources.get(this.aliases.get(token) || token) !== undefined;
|
return this.resources.get(this.aliases.get(token) || token) !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tokenRequiresTrust(token) {
|
||||||
|
const entry = this.resources.get(this.aliases.get(token) || token);
|
||||||
|
return entry && entry.requiresTrust === true || false;
|
||||||
|
}
|
||||||
|
|
||||||
async toSelfie() {
|
async toSelfie() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,10 +289,10 @@ class RedirectEngine {
|
||||||
// No more data, add the resource.
|
// No more data, add the resource.
|
||||||
const name = this.aliases.get(fields[0]) || fields[0];
|
const name = this.aliases.get(fields[0]) || fields[0];
|
||||||
const mime = fields[1];
|
const mime = fields[1];
|
||||||
const content = orphanizeString(
|
const data = orphanizeString(
|
||||||
fields.slice(2).join(encoded ? '' : '\n')
|
fields.slice(2).join(encoded ? '' : '\n')
|
||||||
);
|
);
|
||||||
this.resources.set(name, RedirectEntry.fromContent(mime, content));
|
this.resources.set(name, RedirectEntry.fromDetails({ mime, data }));
|
||||||
if ( Array.isArray(details) ) {
|
if ( Array.isArray(details) ) {
|
||||||
for ( const { prop, value } of details ) {
|
for ( const { prop, value } of details ) {
|
||||||
if ( prop !== 'alias' ) { continue; }
|
if ( prop !== 'alias' ) { continue; }
|
||||||
|
@ -314,11 +315,12 @@ class RedirectEngine {
|
||||||
import('/assets/resources/scriptlets.js').then(module => {
|
import('/assets/resources/scriptlets.js').then(module => {
|
||||||
for ( const scriptlet of module.builtinScriptlets ) {
|
for ( const scriptlet of module.builtinScriptlets ) {
|
||||||
const { name, aliases, fn } = scriptlet;
|
const { name, aliases, fn } = scriptlet;
|
||||||
const entry = RedirectEntry.fromContent(
|
const entry = RedirectEntry.fromDetails({
|
||||||
mimeFromName(name),
|
mime: mimeFromName(name),
|
||||||
fn.toString(),
|
data: fn.toString(),
|
||||||
scriptlet.dependencies,
|
dependencies: scriptlet.dependencies,
|
||||||
);
|
requiresTrust: scriptlet.requiresTrust === true,
|
||||||
|
});
|
||||||
this.resources.set(name, entry);
|
this.resources.set(name, entry);
|
||||||
if ( Array.isArray(aliases) === false ) { continue; }
|
if ( Array.isArray(aliases) === false ) { continue; }
|
||||||
for ( const alias of aliases ) {
|
for ( const alias of aliases ) {
|
||||||
|
@ -331,7 +333,7 @@ class RedirectEngine {
|
||||||
|
|
||||||
const store = (name, data = undefined) => {
|
const store = (name, data = undefined) => {
|
||||||
const details = redirectableResources.get(name);
|
const details = redirectableResources.get(name);
|
||||||
const entry = RedirectEntry.fromSelfie({
|
const entry = RedirectEntry.fromDetails({
|
||||||
mime: mimeFromName(name),
|
mime: mimeFromName(name),
|
||||||
data,
|
data,
|
||||||
warURL: `/web_accessible_resources/${name}`,
|
warURL: `/web_accessible_resources/${name}`,
|
||||||
|
@ -444,7 +446,7 @@ class RedirectEngine {
|
||||||
this.aliases = new Map(selfie.aliases);
|
this.aliases = new Map(selfie.aliases);
|
||||||
this.resources = new Map();
|
this.resources = new Map();
|
||||||
for ( const [ token, entry ] of selfie.resources ) {
|
for ( const [ token, entry ] of selfie.resources ) {
|
||||||
this.resources.set(token, RedirectEntry.fromSelfie(entry));
|
this.resources.set(token, RedirectEntry.fromDetails(entry));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
import µb from './background.js';
|
import µb from './background.js';
|
||||||
import { redirectEngine } from './redirect-engine.js';
|
import { redirectEngine as reng } from './redirect-engine.js';
|
||||||
import { sessionFirewall } from './filtering-engines.js';
|
import { sessionFirewall } from './filtering-engines.js';
|
||||||
import { StaticExtFilteringHostnameDB } from './static-ext-filtering-db.js';
|
import { StaticExtFilteringHostnameDB } from './static-ext-filtering-db.js';
|
||||||
import * as sfp from './static-filtering-parser.js';
|
import * as sfp from './static-filtering-parser.js';
|
||||||
|
@ -119,7 +119,7 @@ const contentscriptCode = (( ) => {
|
||||||
// TODO: Probably should move this into StaticFilteringParser
|
// TODO: Probably should move this into StaticFilteringParser
|
||||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/1031
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/1031
|
||||||
// Normalize scriptlet name to its canonical, unaliased name.
|
// Normalize scriptlet name to its canonical, unaliased name.
|
||||||
const normalizeRawFilter = function(parser) {
|
const normalizeRawFilter = function(parser, sourceIsTrusted = false) {
|
||||||
const root = parser.getBranchFromType(sfp.NODE_TYPE_EXT_PATTERN_SCRIPTLET);
|
const root = parser.getBranchFromType(sfp.NODE_TYPE_EXT_PATTERN_SCRIPTLET);
|
||||||
const walker = parser.getWalker(root);
|
const walker = parser.getWalker(root);
|
||||||
const args = [];
|
const args = [];
|
||||||
|
@ -135,10 +135,14 @@ const normalizeRawFilter = function(parser) {
|
||||||
}
|
}
|
||||||
walker.dispose();
|
walker.dispose();
|
||||||
if ( args.length !== 0 ) {
|
if ( args.length !== 0 ) {
|
||||||
const full = `${args[0]}.js`;
|
let token = `${args[0]}.js`;
|
||||||
if ( redirectEngine.aliases.has(full) ) {
|
if ( reng.aliases.has(token) ) {
|
||||||
args[0] = redirectEngine.aliases.get(full).slice(0, -3);
|
token = reng.aliases.get(token);
|
||||||
}
|
}
|
||||||
|
if ( sourceIsTrusted !== true && reng.tokenRequiresTrust(token) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
args[0] = token.slice(0, -3);
|
||||||
}
|
}
|
||||||
return `+js(${args.join(', ')})`;
|
return `+js(${args.join(', ')})`;
|
||||||
};
|
};
|
||||||
|
@ -155,19 +159,19 @@ const lookupScriptlet = function(rawToken, scriptletMap, dependencyMap) {
|
||||||
}
|
}
|
||||||
// TODO: The alias lookup can be removed once scriptlet resources
|
// TODO: The alias lookup can be removed once scriptlet resources
|
||||||
// with obsolete name are converted to their new name.
|
// with obsolete name are converted to their new name.
|
||||||
if ( redirectEngine.aliases.has(token) ) {
|
if ( reng.aliases.has(token) ) {
|
||||||
token = redirectEngine.aliases.get(token);
|
token = reng.aliases.get(token);
|
||||||
} else {
|
} else {
|
||||||
token = `${token}.js`;
|
token = `${token}.js`;
|
||||||
}
|
}
|
||||||
const details = redirectEngine.contentFromName(token, 'text/javascript');
|
const details = reng.contentFromName(token, 'text/javascript');
|
||||||
if ( details === undefined ) { return; }
|
if ( details === undefined ) { return; }
|
||||||
const content = patchScriptlet(details.js, args);
|
const content = patchScriptlet(details.js, args);
|
||||||
const dependencies = details.dependencies || [];
|
const dependencies = details.dependencies || [];
|
||||||
while ( dependencies.length !== 0 ) {
|
while ( dependencies.length !== 0 ) {
|
||||||
const token = dependencies.shift();
|
const token = dependencies.shift();
|
||||||
if ( dependencyMap.has(token) ) { continue; }
|
if ( dependencyMap.has(token) ) { continue; }
|
||||||
const details = redirectEngine.contentFromName(token, 'fn/javascript');
|
const details = reng.contentFromName(token, 'fn/javascript');
|
||||||
if ( details === undefined ) { continue; }
|
if ( details === undefined ) { continue; }
|
||||||
dependencyMap.set(token, details.js);
|
dependencyMap.set(token, details.js);
|
||||||
if ( Array.isArray(details.dependencies) === false ) { continue; }
|
if ( Array.isArray(details.dependencies) === false ) { continue; }
|
||||||
|
@ -254,7 +258,10 @@ scriptletFilteringEngine.compile = function(parser, writer) {
|
||||||
|
|
||||||
// Only exception filters are allowed to be global.
|
// Only exception filters are allowed to be global.
|
||||||
const isException = parser.isException();
|
const isException = parser.isException();
|
||||||
const normalized = normalizeRawFilter(parser);
|
const normalized = normalizeRawFilter(parser, writer.properties.get('isTrusted'));
|
||||||
|
|
||||||
|
// Can fail if there is a mismatch with trust requirement
|
||||||
|
if ( normalized === undefined ) { return; }
|
||||||
|
|
||||||
// Tokenless is meaningful only for exception filters.
|
// Tokenless is meaningful only for exception filters.
|
||||||
if ( normalized === '+js()' && isException === false ) { return; }
|
if ( normalized === '+js()' && isException === false ) { return; }
|
||||||
|
@ -343,7 +350,7 @@ scriptletFilteringEngine.retrieve = function(request) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( scriptletCache.resetTime < redirectEngine.modifyTime ) {
|
if ( scriptletCache.resetTime < reng.modifyTime ) {
|
||||||
scriptletCache.reset();
|
scriptletCache.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -368,6 +368,14 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µb.isTrustedList = function(assetKey) {
|
||||||
|
if ( assetKey.startsWith('ublock-') ) { return true; }
|
||||||
|
if ( assetKey === this.userFiltersPath ) { return true; }
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
µb.loadSelectedFilterLists = async function() {
|
µb.loadSelectedFilterLists = async function() {
|
||||||
const bin = await vAPI.storage.get('selectedFilterLists');
|
const bin = await vAPI.storage.get('selectedFilterLists');
|
||||||
if ( bin instanceof Object && Array.isArray(bin.selectedFilterLists) ) {
|
if ( bin instanceof Object && Array.isArray(bin.selectedFilterLists) ) {
|
||||||
|
@ -560,7 +568,8 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
|
||||||
await this.saveUserFilters(details.content.trim() + '\n' + filters);
|
await this.saveUserFilters(details.content.trim() + '\n' + filters);
|
||||||
|
|
||||||
const compiledFilters = this.compileFilters(filters, {
|
const compiledFilters = this.compileFilters(filters, {
|
||||||
assetKey: this.userFiltersPath
|
assetKey: this.userFiltersPath,
|
||||||
|
isTrusted: true,
|
||||||
});
|
});
|
||||||
const snfe = staticNetFilteringEngine;
|
const snfe = staticNetFilteringEngine;
|
||||||
const cfe = cosmeticFilteringEngine;
|
const cfe = cosmeticFilteringEngine;
|
||||||
|
@ -885,10 +894,10 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
|
||||||
if ( µb.inMemoryFilters.length !== 0 ) {
|
if ( µb.inMemoryFilters.length !== 0 ) {
|
||||||
if ( µb.inMemoryFiltersCompiled === '' ) {
|
if ( µb.inMemoryFiltersCompiled === '' ) {
|
||||||
µb.inMemoryFiltersCompiled =
|
µb.inMemoryFiltersCompiled =
|
||||||
µb.compileFilters(
|
µb.compileFilters(µb.inMemoryFilters.join('\n'), {
|
||||||
µb.inMemoryFilters.join('\n'),
|
assetKey: 'in-memory',
|
||||||
{ assetKey: 'in-memory'}
|
isTrusted: true,
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
if ( µb.inMemoryFiltersCompiled !== '' ) {
|
if ( µb.inMemoryFiltersCompiled !== '' ) {
|
||||||
toLoad.push(
|
toLoad.push(
|
||||||
|
@ -953,8 +962,10 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
|
||||||
return { assetKey, content: '' };
|
return { assetKey, content: '' };
|
||||||
}
|
}
|
||||||
|
|
||||||
const compiledContent =
|
const compiledContent = this.compileFilters(rawDetails.content, {
|
||||||
this.compileFilters(rawDetails.content, { assetKey });
|
assetKey,
|
||||||
|
isTrusted: this.isTrustedList(assetKey),
|
||||||
|
});
|
||||||
io.put(compiledPath, compiledContent);
|
io.put(compiledPath, compiledContent);
|
||||||
|
|
||||||
return { assetKey, content: compiledContent };
|
return { assetKey, content: compiledContent };
|
||||||
|
@ -1020,6 +1031,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
|
||||||
// client compilers.
|
// client compilers.
|
||||||
if ( details.assetKey ) {
|
if ( details.assetKey ) {
|
||||||
writer.properties.set('name', details.assetKey);
|
writer.properties.set('name', details.assetKey);
|
||||||
|
writer.properties.set('isTrusted', details.isTrusted === true);
|
||||||
}
|
}
|
||||||
const assetName = details.assetKey ? details.assetKey : '?';
|
const assetName = details.assetKey ? details.assetKey : '?';
|
||||||
const expertMode =
|
const expertMode =
|
||||||
|
@ -1539,7 +1551,8 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
|
||||||
io.put(
|
io.put(
|
||||||
'compiled/' + details.assetKey,
|
'compiled/' + details.assetKey,
|
||||||
this.compileFilters(details.content, {
|
this.compileFilters(details.content, {
|
||||||
assetKey: details.assetKey
|
assetKey: details.assetKey,
|
||||||
|
isTrusted: this.isTrustedList(details.assetKey),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue