mirror of
https://github.com/gorhill/uBlock.git
synced 2026-03-11 09:04:36 +00:00
[mv3] Add support for explicit generichide filter option
`generichide` option is implicitly enforced on all sites unless an exception overrides `generichide`. Though rare, sometimes a `generichide` exception needs to be overridden so that generic cosmetic filtering is made possible on a specific site. This commit is to add support for restoring generic cosmetic filtering on sites which were excluded through a `generichide` exception. Concretely, this is needed to ensure the test suite can properly verify that generic cosmetic filtering is working when the filtering mode is set to "complete": ||ublockorigin.github.io^$generichide,important
This commit is contained in:
parent
839e240ec1
commit
98b011f64c
4 changed files with 151 additions and 59 deletions
|
|
@ -66,6 +66,15 @@ const arrayEq = (a = [], b = [], sort = true) => {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
const normalizeMatches = matches => {
|
||||
if ( matches.length <= 1 ) { return; }
|
||||
if ( matches.includes('<all_urls>') === false ) { return; }
|
||||
matches.length = 0;
|
||||
matches.push('<all_urls>');
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// The extensions API does not always return exactly what we fed it, so we
|
||||
// need to normalize some entries to be sure we properly detect changes when
|
||||
// comparing registered entries vs. entries to register.
|
||||
|
|
@ -93,11 +102,17 @@ function registerHighGeneric(context, genericDetails) {
|
|||
const { before, filteringModeDetails, rulesetsDetails } = context;
|
||||
|
||||
const excludeHostnames = [];
|
||||
const includeHostnames = [];
|
||||
const css = [];
|
||||
for ( const details of rulesetsDetails ) {
|
||||
const hostnames = genericDetails.get(details.id);
|
||||
if ( hostnames !== undefined ) {
|
||||
excludeHostnames.push(...hostnames);
|
||||
if ( hostnames ) {
|
||||
if ( hostnames.unhide ) {
|
||||
excludeHostnames.push(...hostnames.unhide);
|
||||
}
|
||||
if ( hostnames.hide ) {
|
||||
includeHostnames.push(...hostnames.hide);
|
||||
}
|
||||
}
|
||||
const count = details.css?.generichigh || 0;
|
||||
if ( count === 0 ) { continue; }
|
||||
|
|
@ -165,12 +180,18 @@ function registerHighGeneric(context, genericDetails) {
|
|||
function registerGeneric(context, genericDetails) {
|
||||
const { before, filteringModeDetails, rulesetsDetails } = context;
|
||||
|
||||
const excludeHostnames = [];
|
||||
const excludedByFilter = [];
|
||||
const includedByFilter = [];
|
||||
const js = [];
|
||||
for ( const details of rulesetsDetails ) {
|
||||
const hostnames = genericDetails.get(details.id);
|
||||
if ( hostnames !== undefined ) {
|
||||
excludeHostnames.push(...hostnames);
|
||||
if ( hostnames ) {
|
||||
if ( hostnames.unhide ) {
|
||||
excludedByFilter.push(...hostnames.unhide);
|
||||
}
|
||||
if ( hostnames.hide ) {
|
||||
includedByFilter.push(...hostnames.hide);
|
||||
}
|
||||
}
|
||||
const count = details.css?.generic || 0;
|
||||
if ( count === 0 ) { continue; }
|
||||
|
|
@ -183,53 +204,86 @@ function registerGeneric(context, genericDetails) {
|
|||
js.push('/js/scripting/css-generic.js');
|
||||
|
||||
const { none, basic, optimal, complete } = filteringModeDetails;
|
||||
const matches = [];
|
||||
const excludeMatches = [];
|
||||
if ( complete.has('all-urls') ) {
|
||||
excludeMatches.push(...ut.matchesFromHostnames(none));
|
||||
excludeMatches.push(...ut.matchesFromHostnames(basic));
|
||||
excludeMatches.push(...ut.matchesFromHostnames(optimal));
|
||||
excludeMatches.push(...ut.matchesFromHostnames(excludeHostnames));
|
||||
matches.push('<all_urls>');
|
||||
} else {
|
||||
matches.push(
|
||||
const includedByMode = [ ...complete ];
|
||||
const excludedByMode = [ ...none, ...basic, ...optimal ];
|
||||
|
||||
if ( complete.has('all-urls') === false ) {
|
||||
const matches = [
|
||||
...ut.matchesFromHostnames(
|
||||
ut.subtractHostnameIters(
|
||||
Array.from(complete),
|
||||
excludeHostnames
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( matches.length === 0 ) { return; }
|
||||
|
||||
const registered = before.get('css-generic');
|
||||
before.delete('css-generic'); // Important!
|
||||
|
||||
const directive = {
|
||||
id: 'css-generic',
|
||||
js,
|
||||
allFrames: true,
|
||||
matches,
|
||||
excludeMatches,
|
||||
runAt: 'document_idle',
|
||||
};
|
||||
|
||||
// register
|
||||
if ( registered === undefined ) {
|
||||
context.toAdd.push(directive);
|
||||
ut.subtractHostnameIters(includedByMode, excludedByFilter)
|
||||
),
|
||||
...ut.matchesFromHostnames(
|
||||
ut.intersectHostnameIters(includedByMode, includedByFilter)
|
||||
),
|
||||
];
|
||||
if ( matches.length === 0 ) { return; }
|
||||
const registered = before.get('css-generic-some');
|
||||
before.delete('css-generic-some'); // Important!
|
||||
const directive = {
|
||||
id: 'css-generic-some',
|
||||
js,
|
||||
allFrames: true,
|
||||
matches,
|
||||
runAt: 'document_idle',
|
||||
};
|
||||
if ( registered === undefined ) { // register
|
||||
context.toAdd.push(directive);
|
||||
} else if ( // update
|
||||
arrayEq(registered.js, js, false) === false ||
|
||||
arrayEq(registered.matches, directive.matches) === false
|
||||
) {
|
||||
context.toRemove.push('css-generic-some');
|
||||
context.toAdd.push(directive);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// update
|
||||
if (
|
||||
arrayEq(registered.js, js, false) === false ||
|
||||
arrayEq(registered.matches, matches) === false ||
|
||||
arrayEq(registered.excludeMatches, excludeMatches) === false
|
||||
const excludeMatches = [
|
||||
...ut.matchesFromHostnames(excludedByMode),
|
||||
...ut.matchesFromHostnames(excludedByFilter),
|
||||
];
|
||||
const registeredAll = before.get('css-generic-all');
|
||||
before.delete('css-generic-all'); // Important!
|
||||
const directiveAll = {
|
||||
id: 'css-generic-all',
|
||||
js,
|
||||
allFrames: true,
|
||||
matches: [ '<all_urls>' ],
|
||||
excludeMatches,
|
||||
runAt: 'document_idle',
|
||||
};
|
||||
if ( registeredAll === undefined ) { // register
|
||||
context.toAdd.push(directiveAll);
|
||||
} else if ( // update
|
||||
arrayEq(registeredAll.js, js, false) === false ||
|
||||
arrayEq(registeredAll.excludeMatches, directiveAll.excludeMatches) === false
|
||||
) {
|
||||
context.toRemove.push('css-generic');
|
||||
context.toAdd.push(directive);
|
||||
context.toRemove.push('css-generic-all');
|
||||
context.toAdd.push(directiveAll);
|
||||
}
|
||||
const matches = [
|
||||
...ut.matchesFromHostnames(
|
||||
ut.subtractHostnameIters(includedByFilter, excludedByMode)
|
||||
),
|
||||
];
|
||||
if ( matches.length === 0 ) { return; }
|
||||
const registeredSome = before.get('css-generic-some');
|
||||
before.delete('css-generic-some'); // Important!
|
||||
const directiveSome = {
|
||||
id: 'css-generic-some',
|
||||
js,
|
||||
allFrames: true,
|
||||
matches,
|
||||
runAt: 'document_idle',
|
||||
};
|
||||
if ( registeredSome === undefined ) { // register
|
||||
context.toAdd.push(directiveSome);
|
||||
} else if ( // update
|
||||
arrayEq(registeredSome.js, js, false) === false ||
|
||||
arrayEq(registeredSome.matches, directiveSome.matches) === false
|
||||
) {
|
||||
context.toRemove.push('css-generic-some');
|
||||
context.toAdd.push(directiveSome);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -253,6 +307,8 @@ function registerProcedural(context) {
|
|||
];
|
||||
if ( matches.length === 0 ) { return; }
|
||||
|
||||
normalizeMatches(matches);
|
||||
|
||||
js.unshift('/js/scripting/isolated-api.js');
|
||||
js.push('/js/scripting/css-procedural.js');
|
||||
|
||||
|
|
@ -313,6 +369,8 @@ function registerDeclarative(context) {
|
|||
];
|
||||
if ( matches.length === 0 ) { return; }
|
||||
|
||||
normalizeMatches(matches);
|
||||
|
||||
js.unshift('/js/scripting/isolated-api.js');
|
||||
js.push('/js/scripting/css-declarative.js');
|
||||
|
||||
|
|
@ -373,6 +431,8 @@ function registerSpecific(context) {
|
|||
];
|
||||
if ( matches.length === 0 ) { return; }
|
||||
|
||||
normalizeMatches(matches);
|
||||
|
||||
js.unshift('/js/scripting/isolated-api.js');
|
||||
js.push('/js/scripting/css-specific.js');
|
||||
|
||||
|
|
|
|||
|
|
@ -100,15 +100,13 @@ const subtractHostnameIters = (itera, iterb) => {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
const matchFromHostname = hn =>
|
||||
hn === '*' || hn === 'all-urls' ? '<all_urls>' : `*://*.${hn}/*`;
|
||||
|
||||
const matchesFromHostnames = hostnames => {
|
||||
const out = [];
|
||||
for ( const hn of hostnames ) {
|
||||
if ( hn === '*' || hn === 'all-urls' ) {
|
||||
out.length = 0;
|
||||
out.push('<all_urls>');
|
||||
break;
|
||||
}
|
||||
out.push(`*://*.${hn}/*`);
|
||||
out.push(matchFromHostname(hn));
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
|
@ -144,6 +142,7 @@ export {
|
|||
isDescendantHostnameOfIter,
|
||||
intersectHostnameIters,
|
||||
subtractHostnameIters,
|
||||
matchFromHostname,
|
||||
matchesFromHostnames,
|
||||
hostnamesFromMatches,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1245,14 +1245,25 @@ async function rulesetFromURLs(assetDetails) {
|
|||
log(rejectedCosmetic.map(line => `\t${line}`).join('\n'), true);
|
||||
}
|
||||
|
||||
const genericDetailsForRuleset = {};
|
||||
if (
|
||||
Array.isArray(results.network.generichideExclusions) &&
|
||||
results.network.generichideExclusions.length !== 0
|
||||
) {
|
||||
genericDetails.set(
|
||||
assetDetails.id,
|
||||
results.network.generichideExclusions.filter(hn => hn.endsWith('.*') === false).sort()
|
||||
);
|
||||
genericDetailsForRuleset.unhide = results.network.generichideExclusions
|
||||
.filter(hn => hn.endsWith('.*') === false)
|
||||
.sort();
|
||||
}
|
||||
if (
|
||||
Array.isArray(results.network.generichideInclusions) &&
|
||||
results.network.generichideInclusions.length !== 0
|
||||
) {
|
||||
genericDetailsForRuleset.hide = results.network.generichideInclusions
|
||||
.filter(hn => hn.endsWith('.*') === false)
|
||||
.sort();
|
||||
}
|
||||
if ( genericDetailsForRuleset.unhide || genericDetailsForRuleset.hide ) {
|
||||
genericDetails.set(assetDetails.id, genericDetailsForRuleset);
|
||||
}
|
||||
|
||||
const genericCosmeticStats = await processGenericCosmeticFilters(
|
||||
|
|
@ -1367,8 +1378,8 @@ async function main() {
|
|||
],
|
||||
dnrURL: 'https://ublockorigin.github.io/uAssets/dnr/default.json',
|
||||
homeURL: 'https://github.com/uBlockOrigin/uAssets',
|
||||
filters: [
|
||||
],
|
||||
filters: [`
|
||||
`],
|
||||
});
|
||||
|
||||
await rulesetFromURLs({
|
||||
|
|
|
|||
|
|
@ -4511,6 +4511,7 @@ StaticNetFilteringEngine.prototype.dnrFromCompiled = function(op, context, ...ar
|
|||
|
||||
// Collect generichide filters
|
||||
const generichideExclusions = [];
|
||||
const generichideInclusions = [];
|
||||
{
|
||||
const bucket = buckets.get(ALLOW_REALM | typeNameToTypeValue['generichide']);
|
||||
if ( bucket ) {
|
||||
|
|
@ -4522,6 +4523,26 @@ StaticNetFilteringEngine.prototype.dnrFromCompiled = function(op, context, ...ar
|
|||
} else if ( rule.condition.requestDomains ) {
|
||||
generichideExclusions.push(...rule.condition.requestDomains);
|
||||
}
|
||||
if ( rule.condition.excludedInitiatorDomains ) {
|
||||
generichideInclusions.push(...rule.condition.excludedInitiatorDomains);
|
||||
} else if ( rule.condition.excludedRequestDomains ) {
|
||||
generichideInclusions.push(...rule.condition.excludedRequestDomains);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
const bucket = buckets.get(BLOCKIMPORTANT_REALM | typeNameToTypeValue['generichide']);
|
||||
if ( bucket ) {
|
||||
for ( const rules of bucket.values() ) {
|
||||
for ( const rule of rules ) {
|
||||
if ( rule.condition === undefined ) { continue; }
|
||||
if ( rule.condition.initiatorDomains ) {
|
||||
generichideInclusions.push(...rule.condition.initiatorDomains);
|
||||
} else if ( rule.condition.requestDomains ) {
|
||||
generichideInclusions.push(...rule.condition.requestDomains);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4714,6 +4735,7 @@ StaticNetFilteringEngine.prototype.dnrFromCompiled = function(op, context, ...ar
|
|||
acceptedFilterCount: context.acceptedFilterCount,
|
||||
rejectedFilterCount: context.rejectedFilterCount,
|
||||
generichideExclusions: Array.from(new Set(generichideExclusions)),
|
||||
generichideInclusions: Array.from(new Set(generichideInclusions)),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue