Offer ability to skip redirects in strict-blocked page

Related discussion:
https://github.com/uBlockOrigin/uBlock-issues/issues/3206#issuecomment-2439639215

If a strict-blocked page matches a `urlskip=` filter, the page
will show the user the destination URL as a result of applying the
`urlskip` filter should they choose to proceed with the
navigation.
This commit is contained in:
Raymond Hill 2024-10-27 14:24:08 -04:00
parent 6aa9391c8d
commit 20b54185fa
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
7 changed files with 63 additions and 22 deletions

View File

@ -1193,6 +1193,10 @@
"message": "Proceed", "message": "Proceed",
"description": "Button text to navigate to the blocked page" "description": "Button text to navigate to the blocked page"
}, },
"docblockedRedirectPrompt": {
"message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}",
"description": "Text warning about an incoming redirect"
},
"cloudPush": { "cloudPush": {
"message": "Export to cloud storage", "message": "Export to cloud storage",
"description": "tooltip" "description": "tooltip"

View File

@ -28,12 +28,18 @@ body {
} }
#rootContainer { #rootContainer {
width: min(100vw, 640px); width: min(100%, 640px);
} }
#rootContainer > * { #rootContainer > * {
margin: 0 0 var(--default-gap-xxlarge) 0; margin: 0 0 var(--default-gap-xxlarge) 0;
} }
:root.mobile #rootContainer > * {
margin-bottom: var(--default-gap-xlarge);
}
p {
margin: 0.5em 0;
}
a { a {
text-decoration: none; text-decoration: none;
} }
@ -45,8 +51,12 @@ a {
color: var(--accent-surface-1); color: var(--accent-surface-1);
fill: var(--accent-surface-1); fill: var(--accent-surface-1);
font-size: 96px; font-size: 96px;
line-height: 1;
width: 100%; width: 100%;
} }
:root.mobile #warningSign {
font-size: 64px;
}
#theURL { #theURL {
color: var(--ink-2); color: var(--ink-2);
padding: 0; padding: 0;
@ -120,6 +130,13 @@ body[dir="rtl"] #toggleParse {
padding-inline-start: var(--default-gap-xsmall); padding-inline-start: var(--default-gap-xsmall);
} }
#urlskip a {
display: block;
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#actionContainer { #actionContainer {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;

View File

@ -33,6 +33,9 @@
</div> </div>
</div> </div>
<div id="urlskip" hidden>
</div>
<div class="li"> <div class="li">
<label><span class="input checkbox"><input type="checkbox" id="disableWarning"><svg viewBox="0 0 24 24"><path d="M1.73,12.91 8.1,19.28 22.79,4.59"/></svg></span><span data-i18n="docblockedDontWarn">_</span></label> <label><span class="input checkbox"><input type="checkbox" id="disableWarning"><svg viewBox="0 0 24 24"><path d="M1.73,12.91 8.1,19.28 22.79,4.59"/></svg></span><span data-i18n="docblockedDontWarn">_</span></label>
</div> </div>
@ -42,13 +45,12 @@
<button id="bye" data-i18n="docblockedClose" type="button">_<span class="hover"></span></button> <button id="bye" data-i18n="docblockedClose" type="button">_<span class="hover"></span></button>
<button id="proceed" class="preferred" data-i18n="docblockedDisable" type="button"><span class="hover"></span></button> <button id="proceed" class="preferred" data-i18n="docblockedDisable" type="button"><span class="hover"></span></button>
</div> </div>
</div>
<div id="templates" style="display: none;"> <div id="templates" style="display: none;">
<li class="filterList"> <li class="filterList">
<a class="filterListSource" href="asset-viewer.html?url=" target="_blank"></a>&nbsp;<!-- <a class="filterListSource" href="asset-viewer.html?url=" target="_blank"></a>&nbsp;<!--
--><a class="fa-icon filterListSupport hidden" href="#" target="_blank" rel="noopener noreferrer">home</a> --><a class="fa-icon filterListSupport hidden" href="#" target="_blank" rel="noopener noreferrer">home</a>
</span> </span>
</div>
</div> </div>
<script src="lib/hsluv/hsluv-0.1.0.min.js"></script> <script src="lib/hsluv/hsluv-0.1.0.min.js"></script>

View File

@ -19,10 +19,8 @@
Home: https://github.com/gorhill/uBlock Home: https://github.com/gorhill/uBlock
*/ */
'use strict';
import { i18n, i18n$ } from './i18n.js';
import { dom, qs$ } from './dom.js'; import { dom, qs$ } from './dom.js';
import { i18n, i18n$ } from './i18n.js';
/******************************************************************************/ /******************************************************************************/
@ -47,7 +45,7 @@ let details = {};
let lists; let lists;
for ( const rawFilter in response ) { for ( const rawFilter in response ) {
if ( response.hasOwnProperty(rawFilter) ) { if ( Object.prototype.hasOwnProperty.call(response, rawFilter) ) {
lists = response[rawFilter]; lists = response[rawFilter];
break; break;
} }
@ -80,6 +78,24 @@ let details = {};
dom.text('#theURL > p > span:first-of-type', details.url); dom.text('#theURL > p > span:first-of-type', details.url);
dom.text('#why', details.fs); dom.text('#why', details.fs);
if ( typeof details.to === 'string' && details.to.length !== 0 ) {
const fragment = new DocumentFragment();
const text = i18n$('docblockedRedirectPrompt');
const linkPlaceholder = '{{url}}';
let pos = text.indexOf(linkPlaceholder);
if ( pos !== -1 ) {
const link = document.createElement('a');
link.href = link.textContent = details.to;
fragment.append(
text.slice(0, pos),
link,
text.slice(pos + linkPlaceholder.length)
);
qs$('#urlskip').append(fragment);
dom.attr('#urlskip', 'hidden', null);
}
}
/******************************************************************************/ /******************************************************************************/
// https://github.com/gorhill/uBlock/issues/691 // https://github.com/gorhill/uBlock/issues/691

View File

@ -19,8 +19,6 @@
Home: https://github.com/gorhill/uBlock Home: https://github.com/gorhill/uBlock
*/ */
'use strict';
/******************************************************************************/ /******************************************************************************/
const i18n = const i18n =
@ -168,14 +166,14 @@ if ( isBackgroundProcess !== true ) {
const re = /\{\{\w+\}\}/g; const re = /\{\{\w+\}\}/g;
let textout = ''; let textout = '';
for (;;) { for (;;) {
let match = re.exec(textin); const match = re.exec(textin);
if ( match === null ) { if ( match === null ) {
textout += textin; textout += textin;
break; break;
} }
textout += textin.slice(0, match.index); textout += textin.slice(0, match.index);
let prop = match[0].slice(2, -2); let prop = match[0].slice(2, -2);
if ( dict.hasOwnProperty(prop) ) { if ( Object.prototype.hasOwnProperty.call(dict, prop) ) {
textout += dict[prop].replace(/</g, '&lt;') textout += dict[prop].replace(/</g, '&lt;')
.replace(/>/g, '&gt;'); .replace(/>/g, '&gt;');
} else { } else {

View File

@ -955,8 +955,8 @@ const PageStore = class {
}); });
} }
skipMainDocument(fctxt) { skipMainDocument(fctxt, blocked) {
const directives = staticNetFilteringEngine.urlSkip(fctxt); const directives = staticNetFilteringEngine.urlSkip(fctxt, blocked);
if ( directives === undefined ) { return; } if ( directives === undefined ) { return; }
if ( logger.enabled !== true ) { return; } if ( logger.enabled !== true ) { return; }
fctxt.pushFilters(directives.map(a => a.logData())); fctxt.pushFilters(directives.map(a => a.logData()));

View File

@ -197,7 +197,7 @@ const onBeforeRootFrameRequest = function(fctxt) {
if ( result !== 1 ) { if ( result !== 1 ) {
pageStore.redirectNonBlockedRequest(fctxt); pageStore.redirectNonBlockedRequest(fctxt);
} else { } else {
pageStore.skipMainDocument(fctxt); pageStore.skipMainDocument(fctxt, true);
} }
} }
@ -216,16 +216,20 @@ const onBeforeRootFrameRequest = function(fctxt) {
if ( result !== 1 ) { return; } if ( result !== 1 ) { return; }
// No log data means no strict blocking (because we need to report why // No log data means no strict blocking (because we need to report why
// the blocking occurs. // the blocking occurs
if ( logData === undefined ) { return; } if ( logData === undefined ) { return; }
// Blocked // Blocked
// Find out the URL navigated to should the document not be strict-blocked
pageStore.skipMainDocument(fctxt, false);
const query = encodeURIComponent(JSON.stringify({ const query = encodeURIComponent(JSON.stringify({
url: requestURL, url: requestURL,
hn: requestHostname,
dn: fctxt.getDomain() || requestHostname, dn: fctxt.getDomain() || requestHostname,
fs: logData.raw fs: logData.raw,
hn: requestHostname,
to: fctxt.redirectURL || '',
})); }));
vAPI.tabs.replace( vAPI.tabs.replace(