diff --git a/src/js/background.js b/src/js/background.js index 86e7a6351..ea3a28896 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -154,7 +154,7 @@ const µBlock = { // jshint ignore:line // Read-only systemSettings: { - compiledMagic: 37, // Increase when compiled format changes + compiledMagic: 38, // Increase when compiled format changes selfieMagic: 38, // Increase when selfie format changes }, diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js index aba753f8b..a408ead76 100644 --- a/src/js/static-net-filtering.js +++ b/src/js/static-net-filtering.js @@ -297,9 +297,6 @@ class LogData { isRegex: false, }; filterUnits[iunit].logData(logData); - if ( (categoryBits & Important) !== 0 ) { - logData.options.unshift('important'); - } if ( (categoryBits & ThirdParty) !== 0 ) { logData.options.unshift('3p'); } else if ( (categoryBits & FirstParty) !== 0 ) { @@ -599,6 +596,42 @@ registerFilterClass(FilterTrue); /******************************************************************************/ +// The only purpose of this class is so that the `important` filter +// option is added to the logged raw filter. + +const FilterImportant = class { + match() { + return true; + } + + logData(details) { + details.options.unshift('important'); + } + + toSelfie() { + return FilterImportant.compile(); + } + + static compile() { + return [ FilterImportant.fid ]; + } + + static fromCompiled() { + return new FilterImportant(); + } + + static fromSelfie() { + return new FilterImportant(); + } + + static keyFromArgs() { + } +}; + +registerFilterClass(FilterImportant); + +/******************************************************************************/ + const FilterPatternPlain = class { constructor(i, n) { this.i = i | 0; @@ -3398,6 +3431,11 @@ class FilterCompiler { units.push(FilterAnchorRight.compile()); } + // Important + if ( (this.action & Important) !== 0 ) { + units.push(FilterImportant.compile()); + } + // Strict partiness if ( this.strictParty !== 0 ) { units.push(FilterStrictParty.compile(this)); @@ -3434,7 +3472,19 @@ class FilterCompiler { const fdata = units.length === 1 ? units[0] : FilterCompositeAll.compile(units); + this.compileToAtomicFilter(fdata, writer); + + // Add block-important filters to the block realm, so as to avoid + // to unconditionally match against the block-important realm for + // every network request. Block-important filters are quite rare so + // the block-important realm should be checked when and only when + // there is a matched exception filter, which important filters are + // meant to override. + if ( (this.action & BlockImportant) !== 0 ) { + this.action &= ~Important; + this.compileToAtomicFilter(fdata, writer); + } } compileToAtomicFilter(fdata, writer) { @@ -4202,15 +4252,14 @@ FilterContainer.prototype.matchRequest = function(fctxt, modifiers = 0) { $docEntity.reset(); $requestHostname = fctxt.getHostname(); - // Important block realm. - if ( this.realmMatchString(BlockImportant, typeValue, partyBits) ) { - return 1; - } - - // Evaluate block realm before allow realm. + // Evaluate block realm before allow realm, and allow realm before + // block-important realm, i.e. by order of likelihood of a match. const r = this.realmMatchString(BlockAction, typeValue, partyBits); if ( r || (modifiers & 0b0010) !== 0 ) { if ( this.realmMatchString(AllowAction, typeValue, partyBits) ) { + if ( this.realmMatchString(BlockImportant, typeValue, partyBits) ) { + return 1; + } return 2; } if ( r ) { return 1; }