Skip to content

Commit b7ed3b4

Browse files
committed
Add ability to directly evaluate static network filtering engine
Related issue: uBlockOrigin/uBlock-issues#3362 There used to be a way to test URL against the network filtering engine, but this was removed in a distant past during refactoring. The ability has been brought back through uBO's own developer tools, accessible through the _More_ button in the _Support_ pane in the dashboard. To query the static network filtering engine, enter the following in the text editor: snfe?url-to-test [type] [url-of-context] `snfe?` is a prompt indicating the intent to query the static network filtering engine. At a minimum there must be a URL to test. Optionally the type of the resource to match, default to `xhr` if none specified. Also optionally, the context from within which the request is made. Example: Enter: snfe?https://www.google-analytics.com/analytics.js Result: url: https://www.google-analytics.com/analytics.js blocked: ||google-analytics.com^ Enter: snfe?https://www.google-analytics.com/analytics.js script Result: url: https://www.google-analytics.com/analytics.js type: script blocked: ||google-analytics.com^ modified: ||google-analytics.com/analytics.js$script,redirect-rule=google-analytics_analytics.js:5 Enter: snfe?https://example.com/ Result: url: https://example.com/ not blocked Enter: snfe?https://example.com/ ping Result: url: https://example.com/ type: ping blocked: *$ping,3p
1 parent eef99e9 commit b7ed3b4

File tree

5 files changed

+171
-78
lines changed

5 files changed

+171
-78
lines changed

.eslintrc.yml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ rules:
1212
- error
1313
- 4
1414
- ignoredNodes:
15+
- Program > BlockStatement
1516
- Program > IfStatement > BlockStatement
1617
- Program > ExpressionStatement > CallExpression > ArrowFunctionExpression > BlockStatement
1718
- Program > ExpressionStatement > CallExpression > FunctionExpression > BlockStatement

src/js/benchmarks.js

+23-27
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,22 @@
1919
Home: https://github.com/gorhill/uBlock
2020
*/
2121

22-
'use strict';
23-
24-
/******************************************************************************/
25-
26-
import cosmeticFilteringEngine from './cosmetic-filtering.js';
27-
import io from './assets.js';
28-
import scriptletFilteringEngine from './scriptlet-filtering.js';
29-
import staticNetFilteringEngine from './static-net-filtering.js';
30-
import µb from './background.js';
31-
import webRequest from './traffic.js';
32-
import { FilteringContext } from './filtering-context.js';
33-
import { LineIterator } from './text-utils.js';
34-
import { sessionFirewall } from './filtering-engines.js';
35-
3622
import {
3723
domainFromHostname,
3824
entityFromDomain,
3925
hostnameFromURI,
4026
} from './uri-utils.js';
4127

28+
import { FilteringContext } from './filtering-context.js';
29+
import { LineIterator } from './text-utils.js';
30+
import cosmeticFilteringEngine from './cosmetic-filtering.js';
31+
import io from './assets.js';
32+
import scriptletFilteringEngine from './scriptlet-filtering.js';
33+
import { sessionFirewall } from './filtering-engines.js';
34+
import { default as sfne } from './static-net-filtering.js';
35+
import webRequest from './traffic.js';
36+
import µb from './background.js';
37+
4238
/******************************************************************************/
4339

4440
// The requests.json.gz file can be downloaded from:
@@ -155,13 +151,13 @@ export async function benchmarkStaticNetFiltering(options = {}) {
155151
fctxt.setURL(request.url);
156152
fctxt.setDocOriginFromURL(request.frameUrl);
157153
fctxt.setType(request.cpt);
158-
const r = staticNetFilteringEngine.matchRequest(fctxt);
154+
const r = sfne.matchRequest(fctxt);
159155
console.info(`Result=${r}:`);
160156
console.info(`\ttype=${fctxt.type}`);
161157
console.info(`\turl=${fctxt.url}`);
162158
console.info(`\tdocOrigin=${fctxt.getDocOrigin()}`);
163159
if ( r !== 0 ) {
164-
console.info(staticNetFilteringEngine.toLogData());
160+
console.info(sfne.toLogData());
165161
}
166162
return;
167163
}
@@ -180,34 +176,34 @@ export async function benchmarkStaticNetFiltering(options = {}) {
180176
fctxt.setURL(request.url);
181177
fctxt.setDocOriginFromURL(request.frameUrl);
182178
fctxt.setType(request.cpt);
183-
staticNetFilteringEngine.redirectURL = undefined;
184-
const r = staticNetFilteringEngine.matchRequest(fctxt);
179+
sfne.redirectURL = undefined;
180+
const r = sfne.matchRequest(fctxt);
185181
matchCount += 1;
186182
if ( r === 1 ) { blockCount += 1; }
187183
else if ( r === 2 ) { allowCount += 1; }
188184
if ( r !== 1 ) {
189-
if ( staticNetFilteringEngine.transformRequest(fctxt) ) {
185+
if ( sfne.transformRequest(fctxt) ) {
190186
redirectCount += 1;
191187
}
192-
if ( fctxt.redirectURL !== undefined && staticNetFilteringEngine.hasQuery(fctxt) ) {
193-
if ( staticNetFilteringEngine.filterQuery(fctxt, 'removeparam') ) {
188+
if ( fctxt.redirectURL !== undefined && sfne.hasQuery(fctxt) ) {
189+
if ( sfne.filterQuery(fctxt, 'removeparam') ) {
194190
removeparamCount += 1;
195191
}
196192
}
197193
if ( fctxt.type === 'main_frame' || fctxt.type === 'sub_frame' ) {
198-
if ( staticNetFilteringEngine.matchAndFetchModifiers(fctxt, 'csp') ) {
194+
if ( sfne.matchAndFetchModifiers(fctxt, 'csp') ) {
199195
cspCount += 1;
200196
}
201-
if ( staticNetFilteringEngine.matchAndFetchModifiers(fctxt, 'permissions') ) {
197+
if ( sfne.matchAndFetchModifiers(fctxt, 'permissions') ) {
202198
permissionsCount += 1;
203199
}
204200
}
205-
staticNetFilteringEngine.matchHeaders(fctxt, []);
206-
if ( staticNetFilteringEngine.matchAndFetchModifiers(fctxt, 'replace') ) {
201+
sfne.matchHeaders(fctxt, []);
202+
if ( sfne.matchAndFetchModifiers(fctxt, 'replace') ) {
207203
replaceCount += 1;
208204
}
209205
} else if ( redirectEngine !== undefined ) {
210-
if ( staticNetFilteringEngine.redirectRequest(redirectEngine, fctxt) ) {
206+
if ( sfne.redirectRequest(redirectEngine, fctxt) ) {
211207
redirectCount += 1;
212208
}
213209
}
@@ -254,7 +250,7 @@ export async function tokenHistogramsfunction() {
254250
fctxt.setURL(request.url);
255251
fctxt.setDocOriginFromURL(request.frameUrl);
256252
fctxt.setType(request.cpt);
257-
const r = staticNetFilteringEngine.matchRequest(fctxt);
253+
const r = sfne.matchRequest(fctxt);
258254
for ( let [ keyword ] of request.url.toLowerCase().matchAll(reTokens) ) {
259255
const token = keyword.slice(0, 7);
260256
if ( r === 0 ) {

src/js/devtools.js

+41-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121

2222
/* global CodeMirror, uBlockDashboard */
2323

24-
'use strict';
25-
2624
import { dom, qs$ } from './dom.js';
2725

2826
/******************************************************************************/
@@ -212,3 +210,44 @@ vAPI.messaging.send('dashboard', {
212210
});
213211

214212
/******************************************************************************/
213+
214+
async function snfeQuery(lineNo, query) {
215+
const doc = cmEditor.getDoc();
216+
const lineHandle = doc.getLineHandle(lineNo)
217+
const result = await vAPI.messaging.send('devTools', {
218+
what: 'snfeQuery',
219+
query
220+
});
221+
if ( typeof result !== 'string' ) { return; }
222+
cmEditor.startOperation();
223+
const nextLineNo = doc.getLineNumber(lineHandle) + 1;
224+
doc.replaceRange(`${result}\n`, { line: nextLineNo, ch: 0 });
225+
cmEditor.endOperation();
226+
}
227+
228+
cmEditor.on('beforeChange', (cm, details) => {
229+
if ( details.origin !== '+input' ) { return; }
230+
if ( details.text.length !== 2 ) { return; }
231+
if ( details.text[1] !== '' ) { return; }
232+
const lineNo = details.from.line;
233+
const line = cm.getLine(lineNo);
234+
if ( details.from.ch !== line.length ) { return; }
235+
if ( line.startsWith('snfe?') === false ) { return; }
236+
const fields = line.slice(5).split(/\s+/);
237+
const query = {};
238+
for ( const field of fields ) {
239+
if ( /[/.]/.test(field) ) {
240+
if ( query.url === undefined ) {
241+
query.url = field;
242+
} else if ( query.from === undefined ) {
243+
query.from = field;
244+
}
245+
} else if ( query.type === undefined ) {
246+
query.type = field;
247+
}
248+
}
249+
if ( query.url === undefined ) { return; }
250+
snfeQuery(lineNo, query);
251+
});
252+
253+
/******************************************************************************/

src/js/messaging.js

+47-43
Original file line numberDiff line numberDiff line change
@@ -19,53 +19,50 @@
1919
Home: https://github.com/gorhill/uBlock
2020
*/
2121

22-
/* globals browser */
23-
24-
'use strict';
22+
import * as s14e from './s14e-serializer.js';
23+
import * as sfp from './static-filtering-parser.js';
2524

26-
/******************************************************************************/
25+
import {
26+
domainFromHostname,
27+
domainFromURI,
28+
entityFromDomain,
29+
hostnameFromURI,
30+
isNetworkURI,
31+
} from './uri-utils.js';
2732

28-
import publicSuffixList from '../lib/publicsuffixlist/publicsuffixlist.js';
29-
import punycode from '../lib/punycode.js';
33+
import {
34+
permanentFirewall,
35+
permanentSwitches,
36+
permanentURLFiltering,
37+
sessionFirewall,
38+
sessionSwitches,
39+
sessionURLFiltering,
40+
} from './filtering-engines.js';
3041

31-
import { filteringBehaviorChanged } from './broadcast.js';
3242
import cacheStorage from './cachestorage.js';
3343
import cosmeticFilteringEngine from './cosmetic-filtering.js';
44+
import { denseBase64 } from './base64-custom.js';
45+
import { dnrRulesetFromRawLists } from './static-dnr-filtering.js';
46+
import { filteringBehaviorChanged } from './broadcast.js';
3447
import htmlFilteringEngine from './html-filtering.js';
48+
import { i18n$ } from './i18n.js';
49+
import io from './assets.js';
3550
import logger from './logger.js';
3651
import lz4Codec from './lz4.js';
37-
import io from './assets.js';
52+
import publicSuffixList from '../lib/publicsuffixlist/publicsuffixlist.js';
53+
import punycode from '../lib/punycode.js';
54+
import { redirectEngine } from './redirect-engine.js';
3855
import scriptletFilteringEngine from './scriptlet-filtering.js';
3956
import staticFilteringReverseLookup from './reverselookup.js';
4057
import staticNetFilteringEngine from './static-net-filtering.js';
41-
import µb from './background.js';
4258
import webRequest from './traffic.js';
43-
import { denseBase64 } from './base64-custom.js';
44-
import { dnrRulesetFromRawLists } from './static-dnr-filtering.js';
45-
import { i18n$ } from './i18n.js';
46-
import { redirectEngine } from './redirect-engine.js';
47-
import * as sfp from './static-filtering-parser.js';
48-
import * as s14e from './s14e-serializer.js';
49-
50-
import {
51-
permanentFirewall,
52-
sessionFirewall,
53-
permanentSwitches,
54-
sessionSwitches,
55-
permanentURLFiltering,
56-
sessionURLFiltering,
57-
} from './filtering-engines.js';
58-
59-
import {
60-
domainFromHostname,
61-
domainFromURI,
62-
entityFromDomain,
63-
hostnameFromURI,
64-
isNetworkURI,
65-
} from './uri-utils.js';
59+
import µb from './background.js';
6660

6761
/******************************************************************************/
6862

63+
const hasOwnProperty = (o, p) =>
64+
Object.prototype.hasOwnProperty.call(o, p);
65+
6966
// https://github.com/uBlockOrigin/uBlock-issues/issues/710
7067
// Listeners have a name and a "privileged" status.
7168
// The nameless default handler is always deemed "privileged".
@@ -807,7 +804,7 @@ const onMessage = function(request, sender, callback) {
807804
});
808805
break;
809806

810-
case 'shouldRenderNoscriptTags':
807+
case 'shouldRenderNoscriptTags': {
811808
if ( pageStore === null ) { break; }
812809
const fctxt = µb.filteringContext.fromTabId(sender.tabId);
813810
if ( pageStore.filterScripting(fctxt, undefined) ) {
@@ -818,7 +815,7 @@ const onMessage = function(request, sender, callback) {
818815
});
819816
}
820817
break;
821-
818+
}
822819
case 'retrieveGenericCosmeticSelectors':
823820
request.tabId = sender.tabId;
824821
request.frameId = sender.frameId;
@@ -1098,7 +1095,7 @@ const restoreUserData = async function(request) {
10981095
// Discard unknown setting or setting with default value.
10991096
for ( const key in hiddenSettings ) {
11001097
if (
1101-
µb.hiddenSettingsDefault.hasOwnProperty(key) === false ||
1098+
hasOwnProperty(µb.hiddenSettingsDefault, key) === false ||
11021099
hiddenSettings[key] === µb.hiddenSettingsDefault[key]
11031100
) {
11041101
delete hiddenSettings[key];
@@ -1128,7 +1125,7 @@ const restoreUserData = async function(request) {
11281125
});
11291126
µb.saveUserFilters(userData.userFilters);
11301127
if ( Array.isArray(userData.selectedFilterLists) ) {
1131-
await µb.saveSelectedFilterLists(userData.selectedFilterLists);
1128+
await µb.saveSelectedFilterLists(userData.selectedFilterLists);
11321129
}
11331130

11341131
vAPI.app.restart();
@@ -1150,7 +1147,7 @@ const resetUserData = async function() {
11501147
// Filter lists
11511148
const prepListEntries = function(entries) {
11521149
for ( const k in entries ) {
1153-
if ( entries.hasOwnProperty(k) === false ) { continue; }
1150+
if ( hasOwnProperty(entries, k) === false ) { continue; }
11541151
const entry = entries[k];
11551152
if ( typeof entry.supportURL === 'string' && entry.supportURL !== '' ) {
11561153
entry.supportName = hostnameFromURI(entry.supportURL);
@@ -1338,7 +1335,7 @@ const getSupportData = async function() {
13381335
let addedListset = {};
13391336
let removedListset = {};
13401337
for ( const listKey in lists ) {
1341-
if ( lists.hasOwnProperty(listKey) === false ) { continue; }
1338+
if ( hasOwnProperty(lists, listKey) === false ) { continue; }
13421339
const list = lists[listKey];
13431340
if ( list.content !== 'filters' ) { continue; }
13441341
const used = µb.selectedFilterLists.includes(listKey);
@@ -1755,7 +1752,7 @@ const onMessage = (request, sender, callback) => {
17551752
// Sync
17561753
let response;
17571754
switch ( request.what ) {
1758-
case 'getInspectorArgs':
1755+
case 'getInspectorArgs': {
17591756
const bc = new globalThis.BroadcastChannel('contentInspectorChannel');
17601757
bc.postMessage({
17611758
what: 'contentInspectorChannel',
@@ -1768,6 +1765,7 @@ const onMessage = (request, sender, callback) => {
17681765
),
17691766
};
17701767
break;
1768+
}
17711769
default:
17721770
return vAPI.messaging.UNHANDLED;
17731771
}
@@ -2004,6 +2002,12 @@ const onMessage = function(request, sender, callback) {
20042002
response = staticNetFilteringEngine.dump();
20052003
break;
20062004

2005+
case 'snfeQuery':
2006+
response = staticNetFilteringEngine.test(
2007+
Object.assign({ redirectEngine }, request.query)
2008+
);
2009+
break;
2010+
20072011
case 'cfeDump':
20082012
response = cosmeticFilteringEngine.dump();
20092013
break;
@@ -2181,7 +2185,7 @@ const onMessage = function(request, sender, callback) {
21812185
}
21822186
break;
21832187

2184-
case 'subscribeTo':
2188+
case 'subscribeTo': {
21852189
// https://github.com/uBlockOrigin/uBlock-issues/issues/1797
21862190
if ( /^(file|https?):\/\//.test(request.location) === false ) { break; }
21872191
const url = encodeURIComponent(request.location);
@@ -2194,8 +2198,8 @@ const onMessage = function(request, sender, callback) {
21942198
select: true,
21952199
});
21962200
break;
2197-
2198-
case 'updateLists':
2201+
}
2202+
case 'updateLists': {
21992203
const listkeys = request.listkeys.split(',').filter(s => s !== '');
22002204
if ( listkeys.length === 0 ) { return; }
22012205
if ( listkeys.includes('all') ) {
@@ -2211,7 +2215,7 @@ const onMessage = function(request, sender, callback) {
22112215
});
22122216
µb.scheduleAssetUpdater({ now: true, fetchDelay: 100, auto: request.auto });
22132217
break;
2214-
2218+
}
22152219
default:
22162220
return vAPI.messaging.UNHANDLED;
22172221
}

0 commit comments

Comments
 (0)