Add `-blocked` directive to `urlskip=` option

Potentially breaking change:

`urlskip=` option will no longer apply by default to blocked network
requests, only network requests which are not blocked can be skipped
through a `urlskip=` filter.

The new `urlskip=` directive `-blocked` can be used to explicitly
allow a `urlskip=` filter to also apply to blocked network requests.

Example: given the filter `||example.com^`, the filter:

  ||example.com/path/to/tracker$urlskip=?url

Will not prevent strict-blocking when navigating to:

  https://example.com/path/to/tracker?url=https://example.org/

However, the filter:

  ||example.com/path/to/tracker$urlskip=-blocked ?url

Will cause the strict-blocking to be ignored and allow navigation
to proceed to the URL extracted as a result of applying the `urlskip=`
filter:

  https://example.org/

Related discussion:
https://github.com/uBlockOrigin/uBlock-issues/issues/3206#issuecomment-2439627386
This commit is contained in:
Raymond Hill 2024-10-26 12:50:40 -04:00
parent 50785ea38b
commit d04dc4c767
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
3 changed files with 20 additions and 6 deletions

View File

@ -191,7 +191,7 @@ export async function benchmarkStaticNetFiltering(options = {}) {
removeparamCount += 1;
}
}
if ( sfne.urlSkip(fctxt) ) {
if ( sfne.urlSkip(fctxt, false) ) {
urlskipCount += 1;
}
if ( fctxt.isDocument() ) {
@ -210,7 +210,7 @@ export async function benchmarkStaticNetFiltering(options = {}) {
if ( sfne.redirectRequest(redirectEngine, fctxt) ) {
redirectCount += 1;
}
if ( fctxt.isRootDocument() && sfne.urlSkip(fctxt) ) {
if ( fctxt.isRootDocument() && sfne.urlSkip(fctxt, true) ) {
urlskipCount += 1;
}
}

View File

@ -943,7 +943,7 @@ const PageStore = class {
staticNetFilteringEngine.filterQuery(fctxt, directives);
}
if ( this.urlSkippableResources.has(fctxt.itype) ) {
staticNetFilteringEngine.urlSkip(fctxt, directives);
staticNetFilteringEngine.urlSkip(fctxt, false, directives);
}
if ( directives.length === 0 ) { return; }
if ( logger.enabled !== true ) { return; }

View File

@ -5405,6 +5405,9 @@ StaticNetFilteringEngine.prototype.transformRequest = function(fctxt, out = [])
*
* `-uricomponent`: decode the current string as a URI encoded string.
*
* `-blocked`: allow the redirection of blocked requests. By default, blocked
* requests can't by urlskip'ed.
*
* At any given step, the currently extracted string may not necessarily be
* a valid URL, and more transformation steps may be needed to obtain a valid
* URL once all the steps are applied.
@ -5423,7 +5426,11 @@ StaticNetFilteringEngine.prototype.transformRequest = function(fctxt, out = [])
*
* */
StaticNetFilteringEngine.prototype.urlSkip = function(fctxt, out = []) {
StaticNetFilteringEngine.prototype.urlSkip = function(
fctxt,
blocked,
out = []
) {
if ( fctxt.redirectURL !== undefined ) { return; }
const directives = this.matchAndFetchModifiers(fctxt, 'urlskip');
if ( directives === undefined ) { return; }
@ -5435,7 +5442,7 @@ StaticNetFilteringEngine.prototype.urlSkip = function(fctxt, out = []) {
const urlin = fctxt.url;
const value = directive.value;
const steps = value.includes(' ') && value.split(/ +/) || [ value ];
const urlout = urlSkip(directive, urlin, steps);
const urlout = urlSkip(directive, urlin, blocked, steps);
if ( urlout === undefined ) { continue; }
if ( urlout === urlin ) { continue; }
fctxt.redirectURL = urlout;
@ -5446,8 +5453,9 @@ StaticNetFilteringEngine.prototype.urlSkip = function(fctxt, out = []) {
return out;
};
function urlSkip(directive, url, steps) {
function urlSkip(directive, url, blocked, steps) {
try {
let redirectBlocked = false;
let urlout = url;
for ( const step of steps ) {
const urlin = urlout;
@ -5481,6 +5489,11 @@ function urlSkip(directive, url, steps) {
urlout = self.decodeURIComponent(urlin);
continue;
}
// Enable skip of blocked requests
if ( step === '-blocked' ) {
redirectBlocked = true;
continue;
}
}
// Regex extraction from first capture group
if ( c0 === 0x2F ) { // /
@ -5507,6 +5520,7 @@ function urlSkip(directive, url, steps) {
}
const urlfinal = new URL(urlout);
if ( urlfinal.protocol !== 'https:' ) { return; }
if ( blocked && redirectBlocked !== true ) { return; }
return urlout;
} catch(x) {
}