Skip to content

Commit

Permalink
Add support for all filter option
Browse files Browse the repository at this point in the history
Related discussion:
- https://www.reddit.com/r/uBlockOrigin/comments/bqnsoa/

The `all` option is equivalent to specifying all
network-based types + `popup`, `document`,
`inline-font`, `inline-script`.

Example from discussion:

    ||bet365.com^$all

Above will block all network requests, block all popups,
prevent inline fonts/scripts from `bet365.com`. EasyList-
compatible syntax does not allow to accomplish that
semantic when using only `||bet365.com^`.

If using specific negated type options along with `all`,
the order in which the options appear is important. In
such case `all` should always be first, followed by
the negated type option(s).
  • Loading branch information
gorhill committed May 20, 2019
1 parent 134c59e commit 1888033
Showing 1 changed file with 41 additions and 18 deletions.
59 changes: 41 additions & 18 deletions src/js/static-net-filtering.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,26 @@ const typeNameToTypeValue = {
'webrtc': 19 << 4,
'unsupported': 20 << 4
};

const otherTypeBitValue = typeNameToTypeValue.other;

// All network request types to bitmap
// bring origin to 0 (from 4 -- see typeNameToTypeValue)
// left-shift 1 by the above-calculated value
// subtract 1 to set all type bits
const allNetworkTypesBits =
(1 << (otherTypeBitValue >>> 4)) - 1;

const allTypesBits =
allNetworkTypesBits |
1 << (typeNameToTypeValue['popup'] >>> 4) - 1 |
1 << (typeNameToTypeValue['main_frame'] >>> 4) - 1 |
1 << (typeNameToTypeValue['inline-font'] >>> 4) - 1 |
1 << (typeNameToTypeValue['inline-script'] >>> 4) - 1;

const unsupportedTypeBit =
1 << (typeNameToTypeValue['unsupported'] >>> 4) - 1;

const typeValueToTypeName = {
1: 'stylesheet',
2: 'image',
Expand Down Expand Up @@ -1792,12 +1810,6 @@ const FilterParser = function() {
this.reBadCSP = /(?:^|;)\s*report-(?:to|uri)\b/;
this.domainOpt = '';
this.noTokenHash = µb.urlTokenizer.noTokenHash;
this.unsupportedTypeBit = this.bitFromType('unsupported');
// All network request types to bitmap
// bring origin to 0 (from 4 -- see typeNameToTypeValue)
// left-shift 1 by the above-calculated value
// subtract 1 to set all type bits
this.allNetRequestTypeBits = (1 << (otherTypeBitValue >>> 4)) - 1;
this.reset();
};

Expand All @@ -1807,6 +1819,7 @@ const FilterParser = function() {
// Transpose `ping` into `other` for now.

FilterParser.prototype.toNormalizedType = {
'all': 'all',
'beacon': 'other',
'css': 'stylesheet',
'data': 'data',
Expand All @@ -1833,7 +1846,7 @@ FilterParser.prototype.toNormalizedType = {
'xhr': 'xmlhttprequest',
'xmlhttprequest': 'xmlhttprequest',
'webrtc': 'unsupported',
'websocket': 'websocket'
'websocket': 'websocket',
};

/******************************************************************************/
Expand Down Expand Up @@ -1877,24 +1890,28 @@ FilterParser.prototype.bitFromType = function(type) {
// Be ready to handle multiple negated types

FilterParser.prototype.parseTypeOption = function(raw, not) {
var typeBit = this.bitFromType(this.toNormalizedType[raw]);
const typeBit = raw !== 'all'
? this.bitFromType(this.toNormalizedType[raw])
: allTypesBits;

if ( !not ) {
this.types |= typeBit;
return;
}

// Non-discrete network types can't be negated.
if ( (typeBit & this.allNetRequestTypeBits) === 0 ) {
// Non-network types can only toggle themselves.
if ( (typeBit & allNetworkTypesBits) === 0 ) {
this.types &= ~typeBit;
return;
}

// Negated type: set all valid network request type bits to 1
// Negated network type: the first negation imply all network types are
// toggled on.
if (
(typeBit & this.allNetRequestTypeBits) !== 0 &&
(this.types & this.allNetRequestTypeBits) === 0
(typeBit & allNetworkTypesBits) !== 0 &&
(this.types & allNetworkTypesBits) === 0
) {
this.types |= this.allNetRequestTypeBits;
this.types |= allNetworkTypesBits;
}
this.types &= ~typeBit;
};
Expand Down Expand Up @@ -2080,8 +2097,8 @@ FilterParser.prototype.parse = function(raw) {
// https://github.com/gorhill/uBlock/issues/2283
// Abort if type is only for unsupported types, otherwise
// toggle off `unsupported` bit.
if ( this.types & this.unsupportedTypeBit ) {
this.types &= ~this.unsupportedTypeBit;
if ( this.types & unsupportedTypeBit ) {
this.types &= ~unsupportedTypeBit;
if ( this.types === 0 ) {
this.unsupported = true;
return this;
Expand Down Expand Up @@ -2735,6 +2752,12 @@ FilterContainer.prototype.compileToAtomicFilter = function(
return;
}

// If all network types are set, just use `no_type`.
if ( (type & allNetworkTypesBits) === allNetworkTypesBits ) {
writer.push([ descBits, parsed.tokenHash, fdata ]);
type &= ~allNetworkTypesBits;
}

// Specific type(s)
let bitOffset = 1;
do {
Expand All @@ -2748,9 +2771,9 @@ FilterContainer.prototype.compileToAtomicFilter = function(
// Only static filter with an explicit type can be redirected. If we reach
// this point, it's because there is one or more explicit type.
if ( parsed.redirect ) {
let redirects = µb.redirectEngine.compileRuleFromStaticFilter(parsed.raw);
const redirects = µb.redirectEngine.compileRuleFromStaticFilter(parsed.raw);
if ( Array.isArray(redirects) ) {
for ( let redirect of redirects ) {
for ( const redirect of redirects ) {
writer.push([ typeNameToTypeValue.redirect, redirect ]);
}
}
Expand Down

1 comment on commit 1888033

@gorhill
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meant to add this important note in the commit message but forgot: all must be seen as an alias of

[network request-based types],other,doc,popup,inline-font,inline-script

The logger will never report a filter with all type option, only filters with one of the above type, if any.

Please sign in to comment.