Skip to content

Commit 253ef7a

Browse files
committed
Complete support for reporing strict-block messages
Related issue: uBlockOrigin/uBlock-issues#1195
1 parent 1b00490 commit 253ef7a

File tree

7 files changed

+135
-90
lines changed

7 files changed

+135
-90
lines changed

src/css/document-blocked.css

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ body {
2323
padding: var(--default-gap-xxlarge) var(--default-gap-small);
2424
justify-content: center;
2525
}
26+
body.loading {
27+
opacity: 0;
28+
}
2629
:root.mobile body {
2730
padding: var(--default-gap-small);
2831
}
@@ -128,15 +131,18 @@ body[dir="rtl"] #toggleParse {
128131
font-weight: bold;
129132
}
130133

131-
#whyex a {
134+
.why-extra a {
132135
white-space: nowrap;
133136
}
134-
#whyex ul {
137+
.why-extra ul {
135138
display: flex;
136139
flex-direction: column;
137140
margin: 0;
138141
padding-inline-start: var(--default-gap-xsmall);
139142
}
143+
details > *:not(summary) {
144+
margin-inline-start: 1em;
145+
}
140146

141147
#urlskip a {
142148
display: block;
@@ -161,11 +167,14 @@ body[dir="rtl"] #toggleParse {
161167
}
162168

163169
.filterList {
164-
display: flex;
165-
}
166-
.filterList .filterListSupport[href=""] {
170+
white-space: nowrap;
171+
}
172+
.filterList .filterListSupport[href="#"] {
167173
display: none;
168174
}
175+
.filterList .filterListSupport:not([href="#"]) {
176+
margin-inline-start: 0.25em;
177+
}
169178

170179
/* Small-screen devices */
171180
:root.mobile button {

src/document-blocked.html

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<link rel="stylesheet" href="css/document-blocked.css">
1212
<link rel="icon" type="image/png" href="img/icon_64.png">
1313
</head>
14-
<body>
14+
<body class="loading">
1515
<div id="rootContainer">
1616
<div id="warningSign">
1717
<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 @@
2525
</div>
2626
</div>
2727

28-
<div>
29-
<p data-i18n="docblockedPrompt2">_</p>
30-
<p id="why" class="code">&nbsp;</p>
31-
<div id="whyex" style="visibility: hidden;">
32-
<span data-i18n="docblockedFoundIn">_</span>
33-
<ul><li class="filterList">&nbsp;</ul>
34-
</div>
35-
</div>
28+
<div id="why"></div>
3629

3730
<div id="urlskip" hidden>
3831
</div>
@@ -47,14 +40,28 @@
4740
<button id="proceed" class="preferred" data-i18n="docblockedDisable" type="button"><span class="hover"></span></button>
4841
</div>
4942
</div>
50-
<div id="templates" style="display: none;">
51-
<ul>
52-
<li class="filterList">
53-
<a class="filterListSource" href="asset-viewer.html?url=" target="_blank"></a>&nbsp;<!--
43+
44+
<template class="why">
45+
<p data-i18n="docblockedPrompt2">_</p>
46+
<p class="why code">&nbsp;</p>
47+
</template>
48+
<template class="why-reason">
49+
<details><summary><span data-i18n="docBlockedReasonLabel"></span> <span></span></summary>
50+
<p data-i18n="docblockedPrompt2">_</p>
51+
<p class="why code">&nbsp;</p>
52+
</details>
53+
</template>
54+
<template class="why-extra">
55+
<div class="why-extra">
56+
<span data-i18n="docblockedFoundIn">_</span>&nbsp;
57+
</div>
58+
</template>
59+
<template class="filterList">
60+
<span class="filterList">
61+
<a class="filterListSource" href="asset-viewer.html?url=" target="_blank"></a><!--
5462
--><a class="fa-icon filterListSupport hidden" href="#" target="_blank" rel="noopener noreferrer">home</a>
55-
</li>
56-
</ul>
57-
</div>
63+
</span>
64+
</template>
5865

5966
<script src="lib/hsluv/hsluv-0.1.0.min.js"></script>
6067

src/js/document-blocked.js

Lines changed: 70 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -21,60 +21,22 @@
2121

2222
import { dom, qs$ } from './dom.js';
2323
import { i18n, i18n$ } from './i18n.js';
24+
import { faIconsInit } from './fa-icons.js';
2425

2526
/******************************************************************************/
2627

2728
const messaging = vAPI.messaging;
28-
let details = {};
29+
const details = {};
2930

3031
{
3132
const matches = /details=([^&]+)/.exec(window.location.search);
3233
if ( matches !== null ) {
33-
details = JSON.parse(decodeURIComponent(matches[1]));
34+
Object.assign(details, JSON.parse(decodeURIComponent(matches[1])));
3435
}
3536
}
3637

3738
/******************************************************************************/
3839

39-
(async ( ) => {
40-
const response = await messaging.send('documentBlocked', {
41-
what: 'listsFromNetFilter',
42-
rawFilter: details.fs,
43-
});
44-
if ( response instanceof Object === false ) { return; }
45-
46-
let lists;
47-
for ( const rawFilter in response ) {
48-
if ( Object.hasOwn(response, rawFilter) ) {
49-
lists = response[rawFilter];
50-
break;
51-
}
52-
}
53-
54-
if ( Array.isArray(lists) === false || lists.length === 0 ) {
55-
qs$('#whyex').style.setProperty('visibility', 'collapse');
56-
return;
57-
}
58-
59-
const parent = qs$('#whyex > ul');
60-
parent.firstElementChild.remove(); // remove placeholder element
61-
for ( const list of lists ) {
62-
const listElem = dom.clone('#templates .filterList');
63-
const sourceElem = qs$(listElem, '.filterListSource');
64-
sourceElem.href += encodeURIComponent(list.assetKey);
65-
sourceElem.append(i18n.patchUnicodeFlags(list.title));
66-
if ( typeof list.supportURL === 'string' && list.supportURL !== '' ) {
67-
const supportElem = qs$(listElem, '.filterListSupport');
68-
dom.attr(supportElem, 'href', list.supportURL);
69-
dom.cl.remove(supportElem, 'hidden');
70-
}
71-
parent.appendChild(listElem);
72-
}
73-
qs$('#whyex').style.removeProperty('visibility');
74-
})();
75-
76-
/******************************************************************************/
77-
7840
const urlToFragment = raw => {
7941
try {
8042
const fragment = new DocumentFragment();
@@ -94,7 +56,26 @@ const urlToFragment = raw => {
9456

9557
dom.clear('#theURL > p > span:first-of-type');
9658
qs$('#theURL > p > span:first-of-type').append(urlToFragment(details.url));
97-
dom.text('#why', details.fs);
59+
60+
/******************************************************************************/
61+
62+
const lookupFilterLists = async ( ) => {
63+
const response = await messaging.send('documentBlocked', {
64+
what: 'listsFromNetFilter',
65+
rawFilter: details.fs,
66+
});
67+
if ( response instanceof Object === false ) { return; }
68+
let lists;
69+
for ( const rawFilter in response ) {
70+
if ( Object.hasOwn(response, rawFilter) ) {
71+
lists = response[rawFilter];
72+
break;
73+
}
74+
}
75+
return lists;
76+
};
77+
78+
/******************************************************************************/
9879

9980
if ( typeof details.to === 'string' && details.to.length !== 0 ) {
10081
const fragment = new DocumentFragment();
@@ -221,18 +202,14 @@ if ( window.history.length > 1 ) {
221202

222203
/******************************************************************************/
223204

224-
const getTargetHostname = function() {
225-
return details.hn;
226-
};
227-
228205
const proceedToURL = function() {
229206
window.location.replace(details.url);
230207
};
231208

232209
const proceedTemporary = async function() {
233210
await messaging.send('documentBlocked', {
234211
what: 'temporarilyWhitelistDocument',
235-
hostname: getTargetHostname(),
212+
hostname: details.hn,
236213
});
237214
proceedToURL();
238215
};
@@ -241,7 +218,7 @@ const proceedPermanent = async function() {
241218
await messaging.send('documentBlocked', {
242219
what: 'toggleHostnameSwitch',
243220
name: 'no-strict-blocking',
244-
hostname: getTargetHostname(),
221+
hostname: details.hn,
245222
deep: true,
246223
state: true,
247224
persist: true,
@@ -263,4 +240,49 @@ dom.on('#proceed', 'click', ( ) => {
263240
}
264241
});
265242

243+
lookupFilterLists().then((lists = []) => {
244+
let reason = details.reason;
245+
if ( Boolean(reason) === false ) {
246+
reason = lists.reduce((a, b) => a || b.reason, undefined);
247+
}
248+
if ( reason ) {
249+
const msg = i18n$(`docblockedReason${reason.charAt(0).toUpperCase()}${reason.slice(1)}`);
250+
if ( msg ) { reason = msg };
251+
}
252+
const why = qs$(reason ? 'template.why-reason' : 'template.why')
253+
.content
254+
.cloneNode(true);
255+
i18n.render(why);
256+
dom.text(qs$(why, '.why'), details.fs);
257+
if ( reason ) {
258+
dom.text(qs$(why, 'summary'), `Reason: ${reason}`);
259+
}
260+
qs$('#why').append(why);
261+
dom.cl.remove(dom.body, 'loading');
262+
263+
if ( lists.length === 0 ) { return; }
264+
265+
const whyExtra = qs$('template.why-extra').content.cloneNode(true);
266+
i18n.render(whyExtra);
267+
268+
const listTemplate = qs$('template.filterList');
269+
const parent = qs$(whyExtra, '.why-extra');
270+
let separator = '';
271+
for ( const list of lists ) {
272+
const listElem = listTemplate.content.cloneNode(true);
273+
const sourceElem = qs$(listElem, '.filterListSource');
274+
sourceElem.href += encodeURIComponent(list.assetKey);
275+
sourceElem.append(i18n.patchUnicodeFlags(list.title));
276+
if ( typeof list.supportURL === 'string' && list.supportURL !== '' ) {
277+
const supportElem = qs$(listElem, '.filterListSupport');
278+
dom.attr(supportElem, 'href', list.supportURL);
279+
dom.cl.remove(supportElem, 'hidden');
280+
}
281+
parent.append(separator, listElem);
282+
separator = '\u00A0\u2022\u00A0';
283+
}
284+
faIconsInit(whyExtra);
285+
qs$('#why .why').after(whyExtra);
286+
});
287+
266288
/******************************************************************************/

src/js/reverselookup-worker.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,10 @@ const fromNetFilter = function(details) {
7373
continue;
7474
}
7575
lists.push({
76-
assetKey: assetKey,
76+
assetKey,
7777
title: entry.title,
78-
supportURL: entry.supportURL
78+
supportURL: entry.supportURL,
79+
reason: entry.reason,
7980
});
8081
break;
8182
}

src/js/static-filtering-parser.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ export const NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT = iota++;
174174
export const NODE_TYPE_NET_OPTION_NAME_IPADDRESS = iota++;
175175
export const NODE_TYPE_NET_OPTION_NAME_MATCHCASE = iota++;
176176
export const NODE_TYPE_NET_OPTION_NAME_MEDIA = iota++;
177-
export const NODE_TYPE_NET_OPTION_NAME_MESSAGE = iota++;
178177
export const NODE_TYPE_NET_OPTION_NAME_METHOD = iota++;
179178
export const NODE_TYPE_NET_OPTION_NAME_MP4 = iota++;
180179
export const NODE_TYPE_NET_OPTION_NAME_NOOP = iota++;
@@ -184,6 +183,7 @@ export const NODE_TYPE_NET_OPTION_NAME_PERMISSIONS = iota++;
184183
export const NODE_TYPE_NET_OPTION_NAME_PING = iota++;
185184
export const NODE_TYPE_NET_OPTION_NAME_POPUNDER = iota++;
186185
export const NODE_TYPE_NET_OPTION_NAME_POPUP = iota++;
186+
export const NODE_TYPE_NET_OPTION_NAME_REASON = iota++;
187187
export const NODE_TYPE_NET_OPTION_NAME_REDIRECT = iota++;
188188
export const NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE = iota++;
189189
export const NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM = iota++;
@@ -256,7 +256,6 @@ export const nodeTypeFromOptionName = new Map([
256256
[ 'ipaddress', NODE_TYPE_NET_OPTION_NAME_IPADDRESS ],
257257
[ 'match-case', NODE_TYPE_NET_OPTION_NAME_MATCHCASE ],
258258
[ 'media', NODE_TYPE_NET_OPTION_NAME_MEDIA ],
259-
[ 'message', NODE_TYPE_NET_OPTION_NAME_MESSAGE ],
260259
[ 'method', NODE_TYPE_NET_OPTION_NAME_METHOD ],
261260
[ 'mp4', NODE_TYPE_NET_OPTION_NAME_MP4 ],
262261
[ '_', NODE_TYPE_NET_OPTION_NAME_NOOP ],
@@ -268,6 +267,7 @@ export const nodeTypeFromOptionName = new Map([
268267
/* synonym */ [ 'beacon', NODE_TYPE_NET_OPTION_NAME_PING ],
269268
[ 'popunder', NODE_TYPE_NET_OPTION_NAME_POPUNDER ],
270269
[ 'popup', NODE_TYPE_NET_OPTION_NAME_POPUP ],
270+
[ 'reason', NODE_TYPE_NET_OPTION_NAME_REASON ],
271271
[ 'redirect', NODE_TYPE_NET_OPTION_NAME_REDIRECT ],
272272
/* synonym */ [ 'rewrite', NODE_TYPE_NET_OPTION_NAME_REDIRECT ],
273273
[ 'redirect-rule', NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE ],
@@ -1352,9 +1352,6 @@ export class AstFilterParser {
13521352
case NODE_TYPE_NET_OPTION_NAME_MATCHCASE:
13531353
realBad = this.isRegexPattern() === false;
13541354
break;
1355-
case NODE_TYPE_NET_OPTION_NAME_MESSAGE:
1356-
realBad = hasValue === false;
1357-
break;
13581355
case NODE_TYPE_NET_OPTION_NAME_PERMISSIONS:
13591356
realBad = modifierType !== 0 ||
13601357
(hasValue || isException) === false ||
@@ -1378,6 +1375,9 @@ export class AstFilterParser {
13781375
abstractTypeCount += 1;
13791376
unredirectableTypeCount += 1;
13801377
break;
1378+
case NODE_TYPE_NET_OPTION_NAME_REASON:
1379+
realBad = hasValue === false;
1380+
break;
13811381
case NODE_TYPE_NET_OPTION_NAME_REDIRECT:
13821382
case NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE:
13831383
case NODE_TYPE_NET_OPTION_NAME_REPLACE:
@@ -3154,7 +3154,6 @@ export const netOptionTokenDescriptors = new Map([
31543154
[ 'ipaddress', { mustAssign: true } ],
31553155
[ 'match-case', { } ],
31563156
[ 'media', { canNegate: true } ],
3157-
[ 'message', { mustAssign: true } ],
31583157
[ 'method', { mustAssign: true } ],
31593158
[ 'mp4', { blockOnly: true } ],
31603159
[ '_', { } ],
@@ -3166,6 +3165,7 @@ export const netOptionTokenDescriptors = new Map([
31663165
/* synonym */ [ 'beacon', { canNegate: true } ],
31673166
[ 'popunder', { } ],
31683167
[ 'popup', { canNegate: true } ],
3168+
[ 'reason', { mustAssign: true } ],
31693169
[ 'redirect', { mustAssign: true } ],
31703170
/* synonym */ [ 'rewrite', { mustAssign: true } ],
31713171
[ 'redirect-rule', { mustAssign: true } ],

0 commit comments

Comments
 (0)