Skip to content

Commit

Permalink
Add optional support for generic procedural cosmetic filters
Browse files Browse the repository at this point in the history
Related issue:
- uBlockOrigin/uBlock-issues#131

The new advanced setting and its default value is:

    allowGenericProceduralFilters false

Whenever this setting is toggled, the user is responsible
of forcing a reload of all filter lists so as to allow uBO
to process differently any existing generic procedural
cosmetic filters.
  • Loading branch information
gorhill committed May 18, 2019
1 parent e66e449 commit 1caff74
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 43 deletions.
5 changes: 3 additions & 2 deletions src/js/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ if ( vAPI.webextFlavor === undefined ) {
const µBlock = (function() { // jshint ignore:line

const hiddenSettingsDefault = {
allowGenericProceduralFilters: false,
assetFetchTimeout: 30,
autoCommentFilterTemplate: '{{date}} {{origin}}',
autoUpdateAssetFetchPeriod: 120,
Expand All @@ -54,7 +55,7 @@ const µBlock = (function() { // jshint ignore:line
selfieAfter: 3,
strictBlockingBypassDuration: 120,
suspendTabsUntilReady: 'unset',
userResourcesLocation: 'unset'
userResourcesLocation: 'unset',
};

return {
Expand Down Expand Up @@ -135,7 +136,7 @@ const µBlock = (function() { // jshint ignore:line

// Read-only
systemSettings: {
compiledMagic: 15, // Increase when compiled format changes
compiledMagic: 16, // Increase when compiled format changes
selfieMagic: 16 // Increase when selfie format changes
},

Expand Down
62 changes: 21 additions & 41 deletions src/js/cosmetic-filtering.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ const SelectorCacheEntry = class {
}

addCosmetic(details) {
let selectors = details.selectors,
i = selectors.length || 0;
const selectors = details.selectors;
let i = selectors.length || 0;
// https://github.com/gorhill/uBlock/issues/2011
// Avoiding seemingly pointless surveys only if they appear costly.
if ( details.first && i === 0 ) {
Expand All @@ -90,8 +90,8 @@ const SelectorCacheEntry = class {
if ( this.net.size < SelectorCacheEntry.netHighWaterMark ) {
return;
}
let dict = this.net;
let keys = Array.from(dict.keys()).sort(function(a, b) {
const dict = this.net;
const keys = Array.from(dict.keys()).sort(function(a, b) {
return dict.get(b) - dict.get(a);
}).slice(SelectorCacheEntry.netLowWaterMark);
let i = keys.length;
Expand Down Expand Up @@ -146,7 +146,7 @@ const SelectorCacheEntry = class {

retrieve(type, out) {
this.lastAccessTime = Date.now();
let iterator = type === 'cosmetic' ? this.cosmetic : this.net.keys();
const iterator = type === 'cosmetic' ? this.cosmetic : this.net.keys();
if ( Array.isArray(out) ) {
this.retrieveToArray(iterator, out);
} else {
Expand Down Expand Up @@ -201,9 +201,6 @@ const FilterContainer = function() {
this.netSelectorCacheCountMax = SelectorCacheEntry.netHighWaterMark;
this.selectorCacheTimer = null;

// generic exception filters
this.genericDonthideSet = new Set();

// specific filters
this.specificFilters = new µb.staticExtFilteringEngine.HostnameBasedDB(2);

Expand Down Expand Up @@ -269,9 +266,6 @@ FilterContainer.prototype.reset = function() {
// generic filters
this.hasGenericHide = false;

// generic exception filters
this.genericDonthideSet.clear();

// hostname, entity-based filters
this.specificFilters.clear();

Expand Down Expand Up @@ -312,7 +306,6 @@ FilterContainer.prototype.freeze = function() {
this.frozen = true;
};


/******************************************************************************/

// https://github.com/gorhill/uBlock/issues/1668
Expand Down Expand Up @@ -429,11 +422,17 @@ FilterContainer.prototype.compileGenericHideSelector = function(
// https://github.com/uBlockOrigin/uBlock-issues/issues/464
// Pseudoclass-based selectors can be compiled, but are also valid
// plain selectors.
// https://github.com/uBlockOrigin/uBlock-issues/issues/131
// Support generic procedural filters as per advanced settings.
// TODO: prevent double compilation.
if (
compiled === undefined ||
compiled !== selector &&
µb.staticExtFilteringEngine.compileSelector.pseudoclass !== true
) {
if ( µb.hiddenSettings.allowGenericProceduralFilters === true ) {
return this.compileSpecificSelector('', parsed, writer);
}
const who = writer.properties.get('assetKey') || '?';
µb.logger.writeOne({
realm: 'message',
Expand All @@ -450,8 +449,8 @@ FilterContainer.prototype.compileGenericHideSelector = function(
writer.push([
type === 0x23 /* '#' */ ? 1 : 3,
key.slice(1),
selector ]
);
selector
]);
return;
}

Expand Down Expand Up @@ -493,7 +492,7 @@ FilterContainer.prototype.compileGenericUnhideSelector = function(
writer
) {
// Procedural cosmetic filters are acceptable as generic exception filters.
let compiled = µb.staticExtFilteringEngine.compileSelector(parsed.suffix);
const compiled = µb.staticExtFilteringEngine.compileSelector(parsed.suffix);
if ( compiled === undefined ) {
const who = writer.properties.get('assetKey') || '?';
µb.logger.writeOne({
Expand All @@ -505,9 +504,12 @@ FilterContainer.prototype.compileGenericUnhideSelector = function(
}

// https://github.com/chrisaljoudi/uBlock/issues/497
// All generic exception filters are put in the same bucket: they are
// expected to be very rare.
writer.push([ 7 /* g1 */, compiled ]);
// All generic exception filters are stored as hostname-based filter
// whereas the hostname is the empty string (which matches all
// hostnames). No distinction is made between declarative and
// procedural selectors, since they really exist only to cancel
// out other cosmetic filters.
writer.push([ 8, '', 0b01, compiled ]);
};

/******************************************************************************/
Expand Down Expand Up @@ -622,13 +624,6 @@ FilterContainer.prototype.fromCompiledContent = function(reader, options) {
this.highlyGeneric.complex.dict.add(args[1]);
break;

// https://github.com/chrisaljoudi/uBlock/issues/497
// Generic exception filters: expected to be a rare occurrence.
// #@#.tweet
case 7:
this.genericDonthideSet.add(args[1]);
break;

// hash, example.com, .promoted-tweet
// hash, example.*, .promoted-tweet
case 8:
Expand Down Expand Up @@ -660,13 +655,6 @@ FilterContainer.prototype.skipGenericCompiledContent = function(reader) {

switch ( args[0] ) {

// https://github.com/chrisaljoudi/uBlock/issues/497
// Generic exception filters: expected to be a rare occurrence.
case 7:
this.duplicateBuster.add(fingerprint);
this.genericDonthideSet.add(args[1]);
break;

// hash, example.com, .promoted-tweet
// hash, example.*, .promoted-tweet
case 8:
Expand Down Expand Up @@ -707,7 +695,6 @@ FilterContainer.prototype.toSelfie = function() {
lowlyGenericCCL: Array.from(this.lowlyGeneric.cl.complex),
highSimpleGenericHideArray: Array.from(this.highlyGeneric.simple.dict),
highComplexGenericHideArray: Array.from(this.highlyGeneric.complex.dict),
genericDonthideArray: Array.from(this.genericDonthideSet)
};
};

Expand All @@ -726,7 +713,6 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
this.highlyGeneric.simple.str = selfie.highSimpleGenericHideArray.join(',\n');
this.highlyGeneric.complex.dict = new Set(selfie.highComplexGenericHideArray);
this.highlyGeneric.complex.str = selfie.highComplexGenericHideArray.join(',\n');
this.genericDonthideSet = new Set(selfie.genericDonthideArray);
this.frozen = true;
};

Expand Down Expand Up @@ -989,13 +975,6 @@ FilterContainer.prototype.retrieveSpecificSelectors = function(
};

if ( options.noCosmeticFiltering !== true ) {
// Exception cosmetic filters: prime with generic exception filters.
const exceptionSet = this.setRegister0;
// Genetic exceptions (should be extremely rare).
for ( let exception of this.genericDonthideSet ) {
exceptionSet.add(exception);
}

const specificSet = this.setRegister1;
// Cached cosmetic filters: these are always declarative.
if ( cacheEntry !== undefined ) {
Expand All @@ -1006,6 +985,7 @@ FilterContainer.prototype.retrieveSpecificSelectors = function(
}
}

const exceptionSet = this.setRegister0;
const proceduralSet = this.setRegister2;

this.specificFilters.retrieve(
Expand Down

0 comments on commit 1caff74

Please sign in to comment.