From d04dc4c767721fb13d91a67cb62ecad9b9219103 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sat, 26 Oct 2024 12:50:40 -0400 Subject: [PATCH] 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 --- src/js/benchmarks.js | 4 ++-- src/js/pagestore.js | 2 +- src/js/static-net-filtering.js | 20 +++++++++++++++++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/js/benchmarks.js b/src/js/benchmarks.js index 8603b8737..59996b0f6 100644 --- a/src/js/benchmarks.js +++ b/src/js/benchmarks.js @@ -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; } } diff --git a/src/js/pagestore.js b/src/js/pagestore.js index e23f0950e..e6ca91f9a 100644 --- a/src/js/pagestore.js +++ b/src/js/pagestore.js @@ -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; } diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js index 23343acec..71b67e30c 100644 --- a/src/js/static-net-filtering.js +++ b/src/js/static-net-filtering.js @@ -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) { }