mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-17 16:02:33 +01:00
c3bc2c741d
This concerns the static network filtering engine. Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/943 * * * New static network filter type: `cname` By default, network requests which are result of resolving a canonical name are subject to filtering. This filtering can be bypassed by creating exception filters using the `cname` option. For example: @@*$cname The filter above tells the network filtering engine to except network requests which fulfill all the following conditions: - network request is blocked - network request is that of an unaliased hostname Filter list authors are discouraged from using exception filters of `cname` type, unless there no other practical solution such that maintenance burden become the greater issue. Of course, such exception filters should be as narrow as possible, i.e. apply to specific domain, etc. * * * New static network filter option: `denyallow` The purpose of `denyallow` is bring default-deny/allow-exceptionally ability into static network filtering arsenal. Example of usage: *$3p,script, \ denyallow=x.com|y.com \ domain=a.com|b.com The above filter tells the network filtering engine that when the context is `a.com` or `b.com`, block all 3rd-party scripts except those from `x.com` and `y.com`. Essentially, the new `denyallow` option makes it easier to implement default-deny/allow-exceptionally in static filter lists, whereas before this had to be done with unwieldy regular expressions[1], or through the mix of broadly blocking filters along with exception filters[2]. [1] https://hg.adblockplus.org/ruadlist/rev/f362910bc9a0 [2] Typically filters which pattern are of the form `|http*://`
217 lines
6.1 KiB
JavaScript
217 lines
6.1 KiB
JavaScript
/*******************************************************************************
|
|
|
|
uBlock Origin - a browser extension to block requests.
|
|
Copyright (C) 2015-present Raymond Hill
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
|
|
|
Home: https://github.com/gorhill/uBlock
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
/******************************************************************************/
|
|
|
|
µBlock.staticFilteringReverseLookup = (( ) => {
|
|
|
|
/******************************************************************************/
|
|
|
|
const workerTTL = 5 * 60 * 1000;
|
|
const pendingResponses = new Map();
|
|
|
|
let worker = null;
|
|
let workerTTLTimer;
|
|
let needLists = true;
|
|
let messageId = 1;
|
|
|
|
/******************************************************************************/
|
|
|
|
const onWorkerMessage = function(e) {
|
|
const msg = e.data;
|
|
const resolver = pendingResponses.get(msg.id);
|
|
pendingResponses.delete(msg.id);
|
|
resolver(msg.response);
|
|
};
|
|
|
|
/******************************************************************************/
|
|
|
|
const stopWorker = function() {
|
|
if ( workerTTLTimer !== undefined ) {
|
|
clearTimeout(workerTTLTimer);
|
|
workerTTLTimer = undefined;
|
|
}
|
|
if ( worker === null ) { return; }
|
|
worker.terminate();
|
|
worker = null;
|
|
needLists = true;
|
|
for ( const resolver of pendingResponses.values() ) {
|
|
resolver();
|
|
}
|
|
pendingResponses.clear();
|
|
};
|
|
|
|
/******************************************************************************/
|
|
|
|
const initWorker = function() {
|
|
if ( worker === null ) {
|
|
worker = new Worker('js/reverselookup-worker.js');
|
|
worker.onmessage = onWorkerMessage;
|
|
}
|
|
|
|
// The worker will be shutdown after n minutes without being used.
|
|
if ( workerTTLTimer !== undefined ) {
|
|
clearTimeout(workerTTLTimer);
|
|
}
|
|
workerTTLTimer = vAPI.setTimeout(stopWorker, workerTTL);
|
|
|
|
if ( needLists === false ) {
|
|
return Promise.resolve();
|
|
}
|
|
needLists = false;
|
|
|
|
const entries = new Map();
|
|
|
|
const onListLoaded = function(details) {
|
|
const entry = entries.get(details.assetKey);
|
|
|
|
// https://github.com/gorhill/uBlock/issues/536
|
|
// Use assetKey when there is no filter list title.
|
|
|
|
worker.postMessage({
|
|
what: 'setList',
|
|
details: {
|
|
assetKey: details.assetKey,
|
|
title: entry.title || details.assetKey,
|
|
supportURL: entry.supportURL,
|
|
content: details.content
|
|
}
|
|
});
|
|
};
|
|
|
|
const µb = µBlock;
|
|
for ( const listKey in µb.availableFilterLists ) {
|
|
if ( µb.availableFilterLists.hasOwnProperty(listKey) === false ) {
|
|
continue;
|
|
}
|
|
const entry = µb.availableFilterLists[listKey];
|
|
if ( entry.off === true ) { continue; }
|
|
entries.set(listKey, {
|
|
title: listKey !== µb.userFiltersPath ?
|
|
entry.title :
|
|
vAPI.i18n('1pPageName'),
|
|
supportURL: entry.supportURL || ''
|
|
});
|
|
}
|
|
if ( entries.size === 0 ) {
|
|
return Promise.resolve();
|
|
}
|
|
|
|
const promises = [];
|
|
for ( const listKey of entries.keys() ) {
|
|
promises.push(
|
|
µb.getCompiledFilterList(listKey).then(details => {
|
|
onListLoaded(details);
|
|
})
|
|
);
|
|
}
|
|
return Promise.all(promises);
|
|
};
|
|
|
|
/******************************************************************************/
|
|
|
|
const fromNetFilter = async function(rawFilter) {
|
|
if ( typeof rawFilter !== 'string' || rawFilter === '' ) { return; }
|
|
|
|
const µb = µBlock;
|
|
const writer = new µb.CompiledLineIO.Writer();
|
|
if ( µb.staticNetFilteringEngine.compile(rawFilter, writer) === false ) {
|
|
return;
|
|
}
|
|
|
|
await initWorker();
|
|
|
|
const id = messageId++;
|
|
worker.postMessage({
|
|
what: 'fromNetFilter',
|
|
id: id,
|
|
compiledFilter: writer.last(),
|
|
rawFilter: rawFilter
|
|
});
|
|
|
|
return new Promise(resolve => {
|
|
pendingResponses.set(id, resolve);
|
|
});
|
|
};
|
|
|
|
/******************************************************************************/
|
|
|
|
const fromCosmeticFilter = async function(details) {
|
|
if ( typeof details.rawFilter !== 'string' || details.rawFilter === '' ) {
|
|
return;
|
|
}
|
|
|
|
await initWorker();
|
|
|
|
const id = messageId++;
|
|
const hostname = µBlock.URI.hostnameFromURI(details.url);
|
|
|
|
worker.postMessage({
|
|
what: 'fromCosmeticFilter',
|
|
id: id,
|
|
domain: µBlock.URI.domainFromHostname(hostname),
|
|
hostname: hostname,
|
|
ignoreGeneric:
|
|
µBlock.staticNetFilteringEngine.matchStringReverse(
|
|
'generichide',
|
|
details.url
|
|
) === 2,
|
|
ignoreSpecific:
|
|
µBlock.staticNetFilteringEngine.matchStringReverse(
|
|
'specifichide',
|
|
details.url
|
|
) === 2,
|
|
rawFilter: details.rawFilter
|
|
});
|
|
|
|
return new Promise(resolve => {
|
|
pendingResponses.set(id, resolve);
|
|
});
|
|
|
|
};
|
|
|
|
/******************************************************************************/
|
|
|
|
// This tells the worker that filter lists may have changed.
|
|
|
|
const resetLists = function() {
|
|
needLists = true;
|
|
if ( worker === null ) { return; }
|
|
worker.postMessage({ what: 'resetLists' });
|
|
};
|
|
|
|
/******************************************************************************/
|
|
|
|
return {
|
|
fromNetFilter,
|
|
fromCosmeticFilter,
|
|
resetLists,
|
|
shutdown: stopWorker
|
|
};
|
|
|
|
/******************************************************************************/
|
|
|
|
})();
|
|
|
|
/******************************************************************************/
|