mirror of
https://github.com/gorhill/uBlock.git
synced 2026-03-11 09:04:36 +00:00
Complete support for reporing strict-block messages
Related issue: https://github.com/uBlockOrigin/uBlock-issues/issues/1195
This commit is contained in:
parent
1b00490a4d
commit
253ef7ade3
7 changed files with 135 additions and 90 deletions
|
|
@ -23,6 +23,9 @@ body {
|
|||
padding: var(--default-gap-xxlarge) var(--default-gap-small);
|
||||
justify-content: center;
|
||||
}
|
||||
body.loading {
|
||||
opacity: 0;
|
||||
}
|
||||
:root.mobile body {
|
||||
padding: var(--default-gap-small);
|
||||
}
|
||||
|
|
@ -128,15 +131,18 @@ body[dir="rtl"] #toggleParse {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
#whyex a {
|
||||
.why-extra a {
|
||||
white-space: nowrap;
|
||||
}
|
||||
#whyex ul {
|
||||
.why-extra ul {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0;
|
||||
padding-inline-start: var(--default-gap-xsmall);
|
||||
}
|
||||
details > *:not(summary) {
|
||||
margin-inline-start: 1em;
|
||||
}
|
||||
|
||||
#urlskip a {
|
||||
display: block;
|
||||
|
|
@ -161,11 +167,14 @@ body[dir="rtl"] #toggleParse {
|
|||
}
|
||||
|
||||
.filterList {
|
||||
display: flex;
|
||||
}
|
||||
.filterList .filterListSupport[href=""] {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.filterList .filterListSupport[href="#"] {
|
||||
display: none;
|
||||
}
|
||||
.filterList .filterListSupport:not([href="#"]) {
|
||||
margin-inline-start: 0.25em;
|
||||
}
|
||||
|
||||
/* Small-screen devices */
|
||||
:root.mobile button {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<link rel="stylesheet" href="css/document-blocked.css">
|
||||
<link rel="icon" type="image/png" href="img/icon_64.png">
|
||||
</head>
|
||||
<body>
|
||||
<body class="loading">
|
||||
<div id="rootContainer">
|
||||
<div id="warningSign">
|
||||
<a class="fa-icon" href="https://github.com/gorhill/uBlock/wiki/Strict-blocking" target="_blank" rel="noopener noreferrer">exclamation-triangle</a>
|
||||
|
|
@ -25,14 +25,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p data-i18n="docblockedPrompt2">_</p>
|
||||
<p id="why" class="code"> </p>
|
||||
<div id="whyex" style="visibility: hidden;">
|
||||
<span data-i18n="docblockedFoundIn">_</span>
|
||||
<ul><li class="filterList"> </ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="why"></div>
|
||||
|
||||
<div id="urlskip" hidden>
|
||||
</div>
|
||||
|
|
@ -47,14 +40,28 @@
|
|||
<button id="proceed" class="preferred" data-i18n="docblockedDisable" type="button"><span class="hover"></span></button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="templates" style="display: none;">
|
||||
<ul>
|
||||
<li class="filterList">
|
||||
<a class="filterListSource" href="asset-viewer.html?url=" target="_blank"></a> <!--
|
||||
|
||||
<template class="why">
|
||||
<p data-i18n="docblockedPrompt2">_</p>
|
||||
<p class="why code"> </p>
|
||||
</template>
|
||||
<template class="why-reason">
|
||||
<details><summary><span data-i18n="docBlockedReasonLabel"></span> <span></span></summary>
|
||||
<p data-i18n="docblockedPrompt2">_</p>
|
||||
<p class="why code"> </p>
|
||||
</details>
|
||||
</template>
|
||||
<template class="why-extra">
|
||||
<div class="why-extra">
|
||||
<span data-i18n="docblockedFoundIn">_</span>
|
||||
</div>
|
||||
</template>
|
||||
<template class="filterList">
|
||||
<span class="filterList">
|
||||
<a class="filterListSource" href="asset-viewer.html?url=" target="_blank"></a><!--
|
||||
--><a class="fa-icon filterListSupport hidden" href="#" target="_blank" rel="noopener noreferrer">home</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script src="lib/hsluv/hsluv-0.1.0.min.js"></script>
|
||||
|
||||
|
|
|
|||
|
|
@ -21,60 +21,22 @@
|
|||
|
||||
import { dom, qs$ } from './dom.js';
|
||||
import { i18n, i18n$ } from './i18n.js';
|
||||
import { faIconsInit } from './fa-icons.js';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const messaging = vAPI.messaging;
|
||||
let details = {};
|
||||
const details = {};
|
||||
|
||||
{
|
||||
const matches = /details=([^&]+)/.exec(window.location.search);
|
||||
if ( matches !== null ) {
|
||||
details = JSON.parse(decodeURIComponent(matches[1]));
|
||||
Object.assign(details, JSON.parse(decodeURIComponent(matches[1])));
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
(async ( ) => {
|
||||
const response = await messaging.send('documentBlocked', {
|
||||
what: 'listsFromNetFilter',
|
||||
rawFilter: details.fs,
|
||||
});
|
||||
if ( response instanceof Object === false ) { return; }
|
||||
|
||||
let lists;
|
||||
for ( const rawFilter in response ) {
|
||||
if ( Object.hasOwn(response, rawFilter) ) {
|
||||
lists = response[rawFilter];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( Array.isArray(lists) === false || lists.length === 0 ) {
|
||||
qs$('#whyex').style.setProperty('visibility', 'collapse');
|
||||
return;
|
||||
}
|
||||
|
||||
const parent = qs$('#whyex > ul');
|
||||
parent.firstElementChild.remove(); // remove placeholder element
|
||||
for ( const list of lists ) {
|
||||
const listElem = dom.clone('#templates .filterList');
|
||||
const sourceElem = qs$(listElem, '.filterListSource');
|
||||
sourceElem.href += encodeURIComponent(list.assetKey);
|
||||
sourceElem.append(i18n.patchUnicodeFlags(list.title));
|
||||
if ( typeof list.supportURL === 'string' && list.supportURL !== '' ) {
|
||||
const supportElem = qs$(listElem, '.filterListSupport');
|
||||
dom.attr(supportElem, 'href', list.supportURL);
|
||||
dom.cl.remove(supportElem, 'hidden');
|
||||
}
|
||||
parent.appendChild(listElem);
|
||||
}
|
||||
qs$('#whyex').style.removeProperty('visibility');
|
||||
})();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const urlToFragment = raw => {
|
||||
try {
|
||||
const fragment = new DocumentFragment();
|
||||
|
|
@ -94,7 +56,26 @@ const urlToFragment = raw => {
|
|||
|
||||
dom.clear('#theURL > p > span:first-of-type');
|
||||
qs$('#theURL > p > span:first-of-type').append(urlToFragment(details.url));
|
||||
dom.text('#why', details.fs);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const lookupFilterLists = async ( ) => {
|
||||
const response = await messaging.send('documentBlocked', {
|
||||
what: 'listsFromNetFilter',
|
||||
rawFilter: details.fs,
|
||||
});
|
||||
if ( response instanceof Object === false ) { return; }
|
||||
let lists;
|
||||
for ( const rawFilter in response ) {
|
||||
if ( Object.hasOwn(response, rawFilter) ) {
|
||||
lists = response[rawFilter];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return lists;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if ( typeof details.to === 'string' && details.to.length !== 0 ) {
|
||||
const fragment = new DocumentFragment();
|
||||
|
|
@ -221,10 +202,6 @@ if ( window.history.length > 1 ) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
const getTargetHostname = function() {
|
||||
return details.hn;
|
||||
};
|
||||
|
||||
const proceedToURL = function() {
|
||||
window.location.replace(details.url);
|
||||
};
|
||||
|
|
@ -232,7 +209,7 @@ const proceedToURL = function() {
|
|||
const proceedTemporary = async function() {
|
||||
await messaging.send('documentBlocked', {
|
||||
what: 'temporarilyWhitelistDocument',
|
||||
hostname: getTargetHostname(),
|
||||
hostname: details.hn,
|
||||
});
|
||||
proceedToURL();
|
||||
};
|
||||
|
|
@ -241,7 +218,7 @@ const proceedPermanent = async function() {
|
|||
await messaging.send('documentBlocked', {
|
||||
what: 'toggleHostnameSwitch',
|
||||
name: 'no-strict-blocking',
|
||||
hostname: getTargetHostname(),
|
||||
hostname: details.hn,
|
||||
deep: true,
|
||||
state: true,
|
||||
persist: true,
|
||||
|
|
@ -263,4 +240,49 @@ dom.on('#proceed', 'click', ( ) => {
|
|||
}
|
||||
});
|
||||
|
||||
lookupFilterLists().then((lists = []) => {
|
||||
let reason = details.reason;
|
||||
if ( Boolean(reason) === false ) {
|
||||
reason = lists.reduce((a, b) => a || b.reason, undefined);
|
||||
}
|
||||
if ( reason ) {
|
||||
const msg = i18n$(`docblockedReason${reason.charAt(0).toUpperCase()}${reason.slice(1)}`);
|
||||
if ( msg ) { reason = msg };
|
||||
}
|
||||
const why = qs$(reason ? 'template.why-reason' : 'template.why')
|
||||
.content
|
||||
.cloneNode(true);
|
||||
i18n.render(why);
|
||||
dom.text(qs$(why, '.why'), details.fs);
|
||||
if ( reason ) {
|
||||
dom.text(qs$(why, 'summary'), `Reason: ${reason}`);
|
||||
}
|
||||
qs$('#why').append(why);
|
||||
dom.cl.remove(dom.body, 'loading');
|
||||
|
||||
if ( lists.length === 0 ) { return; }
|
||||
|
||||
const whyExtra = qs$('template.why-extra').content.cloneNode(true);
|
||||
i18n.render(whyExtra);
|
||||
|
||||
const listTemplate = qs$('template.filterList');
|
||||
const parent = qs$(whyExtra, '.why-extra');
|
||||
let separator = '';
|
||||
for ( const list of lists ) {
|
||||
const listElem = listTemplate.content.cloneNode(true);
|
||||
const sourceElem = qs$(listElem, '.filterListSource');
|
||||
sourceElem.href += encodeURIComponent(list.assetKey);
|
||||
sourceElem.append(i18n.patchUnicodeFlags(list.title));
|
||||
if ( typeof list.supportURL === 'string' && list.supportURL !== '' ) {
|
||||
const supportElem = qs$(listElem, '.filterListSupport');
|
||||
dom.attr(supportElem, 'href', list.supportURL);
|
||||
dom.cl.remove(supportElem, 'hidden');
|
||||
}
|
||||
parent.append(separator, listElem);
|
||||
separator = '\u00A0\u2022\u00A0';
|
||||
}
|
||||
faIconsInit(whyExtra);
|
||||
qs$('#why .why').after(whyExtra);
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
|||
|
|
@ -73,9 +73,10 @@ const fromNetFilter = function(details) {
|
|||
continue;
|
||||
}
|
||||
lists.push({
|
||||
assetKey: assetKey,
|
||||
assetKey,
|
||||
title: entry.title,
|
||||
supportURL: entry.supportURL
|
||||
supportURL: entry.supportURL,
|
||||
reason: entry.reason,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -174,7 +174,6 @@ export const NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT = iota++;
|
|||
export const NODE_TYPE_NET_OPTION_NAME_IPADDRESS = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_MATCHCASE = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_MEDIA = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_MESSAGE = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_METHOD = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_MP4 = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_NOOP = iota++;
|
||||
|
|
@ -184,6 +183,7 @@ export const NODE_TYPE_NET_OPTION_NAME_PERMISSIONS = iota++;
|
|||
export const NODE_TYPE_NET_OPTION_NAME_PING = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_POPUNDER = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_POPUP = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_REASON = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_REDIRECT = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE = iota++;
|
||||
export const NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM = iota++;
|
||||
|
|
@ -256,7 +256,6 @@ export const nodeTypeFromOptionName = new Map([
|
|||
[ 'ipaddress', NODE_TYPE_NET_OPTION_NAME_IPADDRESS ],
|
||||
[ 'match-case', NODE_TYPE_NET_OPTION_NAME_MATCHCASE ],
|
||||
[ 'media', NODE_TYPE_NET_OPTION_NAME_MEDIA ],
|
||||
[ 'message', NODE_TYPE_NET_OPTION_NAME_MESSAGE ],
|
||||
[ 'method', NODE_TYPE_NET_OPTION_NAME_METHOD ],
|
||||
[ 'mp4', NODE_TYPE_NET_OPTION_NAME_MP4 ],
|
||||
[ '_', NODE_TYPE_NET_OPTION_NAME_NOOP ],
|
||||
|
|
@ -268,6 +267,7 @@ export const nodeTypeFromOptionName = new Map([
|
|||
/* synonym */ [ 'beacon', NODE_TYPE_NET_OPTION_NAME_PING ],
|
||||
[ 'popunder', NODE_TYPE_NET_OPTION_NAME_POPUNDER ],
|
||||
[ 'popup', NODE_TYPE_NET_OPTION_NAME_POPUP ],
|
||||
[ 'reason', NODE_TYPE_NET_OPTION_NAME_REASON ],
|
||||
[ 'redirect', NODE_TYPE_NET_OPTION_NAME_REDIRECT ],
|
||||
/* synonym */ [ 'rewrite', NODE_TYPE_NET_OPTION_NAME_REDIRECT ],
|
||||
[ 'redirect-rule', NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE ],
|
||||
|
|
@ -1352,9 +1352,6 @@ export class AstFilterParser {
|
|||
case NODE_TYPE_NET_OPTION_NAME_MATCHCASE:
|
||||
realBad = this.isRegexPattern() === false;
|
||||
break;
|
||||
case NODE_TYPE_NET_OPTION_NAME_MESSAGE:
|
||||
realBad = hasValue === false;
|
||||
break;
|
||||
case NODE_TYPE_NET_OPTION_NAME_PERMISSIONS:
|
||||
realBad = modifierType !== 0 ||
|
||||
(hasValue || isException) === false ||
|
||||
|
|
@ -1378,6 +1375,9 @@ export class AstFilterParser {
|
|||
abstractTypeCount += 1;
|
||||
unredirectableTypeCount += 1;
|
||||
break;
|
||||
case NODE_TYPE_NET_OPTION_NAME_REASON:
|
||||
realBad = hasValue === false;
|
||||
break;
|
||||
case NODE_TYPE_NET_OPTION_NAME_REDIRECT:
|
||||
case NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE:
|
||||
case NODE_TYPE_NET_OPTION_NAME_REPLACE:
|
||||
|
|
@ -3154,7 +3154,6 @@ export const netOptionTokenDescriptors = new Map([
|
|||
[ 'ipaddress', { mustAssign: true } ],
|
||||
[ 'match-case', { } ],
|
||||
[ 'media', { canNegate: true } ],
|
||||
[ 'message', { mustAssign: true } ],
|
||||
[ 'method', { mustAssign: true } ],
|
||||
[ 'mp4', { blockOnly: true } ],
|
||||
[ '_', { } ],
|
||||
|
|
@ -3166,6 +3165,7 @@ export const netOptionTokenDescriptors = new Map([
|
|||
/* synonym */ [ 'beacon', { canNegate: true } ],
|
||||
[ 'popunder', { } ],
|
||||
[ 'popup', { canNegate: true } ],
|
||||
[ 'reason', { mustAssign: true } ],
|
||||
[ 'redirect', { mustAssign: true } ],
|
||||
/* synonym */ [ 'rewrite', { mustAssign: true } ],
|
||||
[ 'redirect-rule', { mustAssign: true } ],
|
||||
|
|
|
|||
|
|
@ -411,6 +411,9 @@ class LogData {
|
|||
}
|
||||
this.raw = raw;
|
||||
this.regex = logData.regex.join('');
|
||||
if ( logData.reason ) {
|
||||
this.reason = logData.reason;
|
||||
}
|
||||
}
|
||||
isUntokenized() {
|
||||
return this.tokenHash === NO_TOKEN_HASH;
|
||||
|
|
@ -3113,7 +3116,7 @@ class FilterMessage {
|
|||
static compile(details) {
|
||||
return [
|
||||
FilterMessage.fid,
|
||||
encodeURIComponent(details.optionValues.get('message')),
|
||||
encodeURIComponent(details.optionValues.get('reason')),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -3127,11 +3130,11 @@ class FilterMessage {
|
|||
}
|
||||
|
||||
static logData(idata, details) {
|
||||
const msg = bidiTrie.extractString(
|
||||
filterData[idata+1],
|
||||
filterData[idata+2]
|
||||
const reason = decodeURIComponent(
|
||||
bidiTrie.extractString(filterData[idata+1], filterData[idata+2])
|
||||
);
|
||||
details.options.push(`message=${decodeURIComponent(msg)}`);
|
||||
details.reason = reason;
|
||||
details.options.push(`reason=${reason}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3612,10 +3615,6 @@ class FilterCompiler {
|
|||
this.optionValues.set('ipaddress', parser.getNetOptionValue(id) || '');
|
||||
this.optionUnitBits |= IPADDRESS_BIT;
|
||||
break;
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_MESSAGE:
|
||||
this.optionValues.set('message', parser.getNetOptionValue(id));
|
||||
this.optionUnitBits |= MESSAGE_BIT;
|
||||
break;
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_METHOD:
|
||||
this.processMethodOption(parser.getNetOptionValue(id));
|
||||
this.optionUnitBits |= METHOD_BIT;
|
||||
|
|
@ -3631,6 +3630,10 @@ class FilterCompiler {
|
|||
}
|
||||
this.optionUnitBits |= MODIFY_BIT;
|
||||
break;
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_REASON:
|
||||
this.optionValues.set('reason', parser.getNetOptionValue(id));
|
||||
this.optionUnitBits |= MESSAGE_BIT;
|
||||
break;
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT: {
|
||||
const actualId = this.action === ALLOW_REALM
|
||||
? sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE
|
||||
|
|
@ -3737,9 +3740,9 @@ class FilterCompiler {
|
|||
case sfp.NODE_TYPE_NET_OPTION_NAME_FROM:
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_HEADER:
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_IPADDRESS:
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_MESSAGE:
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_METHOD:
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_PERMISSIONS:
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_REASON:
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT:
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE:
|
||||
case sfp.NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM:
|
||||
|
|
|
|||
|
|
@ -224,17 +224,20 @@ const onBeforeRootFrameRequest = function(fctxt) {
|
|||
// Find out the URL navigated to should the document not be strict-blocked
|
||||
pageStore.skipMainDocument(fctxt, false);
|
||||
|
||||
const query = encodeURIComponent(JSON.stringify({
|
||||
const query = {
|
||||
url: requestURL,
|
||||
dn: fctxt.getDomain() || requestHostname,
|
||||
fs: logData.raw,
|
||||
hn: requestHostname,
|
||||
to: fctxt.redirectURL || '',
|
||||
}));
|
||||
};
|
||||
if ( logData.reason ) {
|
||||
query.reason = logData.reason;
|
||||
}
|
||||
|
||||
vAPI.tabs.replace(
|
||||
fctxt.tabId,
|
||||
vAPI.getURL('document-blocked.html?details=') + query
|
||||
`${vAPI.getURL('document-blocked.html?details=')}${encodeURIComponent(JSON.stringify(query))}`
|
||||
);
|
||||
|
||||
return { cancel: true };
|
||||
|
|
|
|||
Loading…
Reference in a new issue