mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-10 09:07:54 +01:00
Add static network filter option: permissions
Related discussion: https://github.com/uBlockOrigin/uBlock-issues/discussions/2714 Reference: https://adguard.com/kb/general/ad-filtering/create-own-filters/#permissions-modifier Example: ||example.org^$permissions=browsing-topics=() Difference with AdGuard's syntax: use `|` to separate permissions policy directives instead of `\,` -- uBO will replace instances of `|` with `, `: *$permissions=oversized-images=()|unsized-media=() Eventually uBO will support AdGuard's syntax of using escaped commas, but not for this first iteration.
This commit is contained in:
parent
8d09c562ab
commit
5ebdbf3e24
3 changed files with 71 additions and 13 deletions
|
@ -178,6 +178,7 @@ export const NODE_TYPE_NET_OPTION_NAME_MP4 = iota++;
|
||||||
export const NODE_TYPE_NET_OPTION_NAME_NOOP = iota++;
|
export const NODE_TYPE_NET_OPTION_NAME_NOOP = iota++;
|
||||||
export const NODE_TYPE_NET_OPTION_NAME_OBJECT = iota++;
|
export const NODE_TYPE_NET_OPTION_NAME_OBJECT = iota++;
|
||||||
export const NODE_TYPE_NET_OPTION_NAME_OTHER = iota++;
|
export const NODE_TYPE_NET_OPTION_NAME_OTHER = iota++;
|
||||||
|
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_PING = iota++;
|
||||||
export const NODE_TYPE_NET_OPTION_NAME_POPUNDER = 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_POPUP = iota++;
|
||||||
|
@ -252,6 +253,7 @@ export const nodeTypeFromOptionName = new Map([
|
||||||
[ 'object', NODE_TYPE_NET_OPTION_NAME_OBJECT ],
|
[ 'object', NODE_TYPE_NET_OPTION_NAME_OBJECT ],
|
||||||
/* synonym */ [ 'object-subrequest', NODE_TYPE_NET_OPTION_NAME_OBJECT ],
|
/* synonym */ [ 'object-subrequest', NODE_TYPE_NET_OPTION_NAME_OBJECT ],
|
||||||
[ 'other', NODE_TYPE_NET_OPTION_NAME_OTHER ],
|
[ 'other', NODE_TYPE_NET_OPTION_NAME_OTHER ],
|
||||||
|
[ 'permissions', NODE_TYPE_NET_OPTION_NAME_PERMISSIONS ],
|
||||||
[ 'ping', NODE_TYPE_NET_OPTION_NAME_PING ],
|
[ 'ping', NODE_TYPE_NET_OPTION_NAME_PING ],
|
||||||
/* synonym */ [ 'beacon', NODE_TYPE_NET_OPTION_NAME_PING ],
|
/* synonym */ [ 'beacon', NODE_TYPE_NET_OPTION_NAME_PING ],
|
||||||
[ 'popunder', NODE_TYPE_NET_OPTION_NAME_POPUNDER ],
|
[ 'popunder', NODE_TYPE_NET_OPTION_NAME_POPUNDER ],
|
||||||
|
@ -1293,6 +1295,11 @@ export class AstFilterParser {
|
||||||
case NODE_TYPE_NET_OPTION_NAME_MATCHCASE:
|
case NODE_TYPE_NET_OPTION_NAME_MATCHCASE:
|
||||||
realBad = this.isRegexPattern() === false;
|
realBad = this.isRegexPattern() === false;
|
||||||
break;
|
break;
|
||||||
|
case NODE_TYPE_NET_OPTION_NAME_PERMISSIONS:
|
||||||
|
realBad = modifierType !== 0 || (hasValue || isException) === false;
|
||||||
|
if ( realBad ) { break; }
|
||||||
|
modifierType = type;
|
||||||
|
break;
|
||||||
case NODE_TYPE_NET_OPTION_NAME_PING:
|
case NODE_TYPE_NET_OPTION_NAME_PING:
|
||||||
case NODE_TYPE_NET_OPTION_NAME_WEBSOCKET:
|
case NODE_TYPE_NET_OPTION_NAME_WEBSOCKET:
|
||||||
realBad = hasValue;
|
realBad = hasValue;
|
||||||
|
@ -1349,6 +1356,7 @@ export class AstFilterParser {
|
||||||
realBad = abstractTypeCount || behaviorTypeCount || requestTypeCount;
|
realBad = abstractTypeCount || behaviorTypeCount || requestTypeCount;
|
||||||
break;
|
break;
|
||||||
case NODE_TYPE_NET_OPTION_NAME_CSP:
|
case NODE_TYPE_NET_OPTION_NAME_CSP:
|
||||||
|
case NODE_TYPE_NET_OPTION_NAME_PERMISSIONS:
|
||||||
realBad = abstractTypeCount || behaviorTypeCount || requestTypeCount;
|
realBad = abstractTypeCount || behaviorTypeCount || requestTypeCount;
|
||||||
break;
|
break;
|
||||||
case NODE_TYPE_NET_OPTION_NAME_INLINEFONT:
|
case NODE_TYPE_NET_OPTION_NAME_INLINEFONT:
|
||||||
|
|
|
@ -182,12 +182,14 @@ const MODIFIER_TYPE_REDIRECT = 1;
|
||||||
const MODIFIER_TYPE_REDIRECTRULE = 2;
|
const MODIFIER_TYPE_REDIRECTRULE = 2;
|
||||||
const MODIFIER_TYPE_REMOVEPARAM = 3;
|
const MODIFIER_TYPE_REMOVEPARAM = 3;
|
||||||
const MODIFIER_TYPE_CSP = 4;
|
const MODIFIER_TYPE_CSP = 4;
|
||||||
|
const MODIFIER_TYPE_PERMISSIONS = 5;
|
||||||
|
|
||||||
const modifierTypeFromName = new Map([
|
const modifierTypeFromName = new Map([
|
||||||
[ 'redirect', MODIFIER_TYPE_REDIRECT ],
|
[ 'redirect', MODIFIER_TYPE_REDIRECT ],
|
||||||
[ 'redirect-rule', MODIFIER_TYPE_REDIRECTRULE ],
|
[ 'redirect-rule', MODIFIER_TYPE_REDIRECTRULE ],
|
||||||
[ 'removeparam', MODIFIER_TYPE_REMOVEPARAM ],
|
[ 'removeparam', MODIFIER_TYPE_REMOVEPARAM ],
|
||||||
[ 'csp', MODIFIER_TYPE_CSP ],
|
[ 'csp', MODIFIER_TYPE_CSP ],
|
||||||
|
[ 'permissions', MODIFIER_TYPE_PERMISSIONS ],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const modifierNameFromType = new Map([
|
const modifierNameFromType = new Map([
|
||||||
|
@ -195,6 +197,7 @@ const modifierNameFromType = new Map([
|
||||||
[ MODIFIER_TYPE_REDIRECTRULE, 'redirect-rule' ],
|
[ MODIFIER_TYPE_REDIRECTRULE, 'redirect-rule' ],
|
||||||
[ MODIFIER_TYPE_REMOVEPARAM, 'removeparam' ],
|
[ MODIFIER_TYPE_REMOVEPARAM, 'removeparam' ],
|
||||||
[ MODIFIER_TYPE_CSP, 'csp' ],
|
[ MODIFIER_TYPE_CSP, 'csp' ],
|
||||||
|
[ MODIFIER_TYPE_PERMISSIONS, 'permissions' ],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
//const typeValueFromCatBits = catBits => (catBits >>> TypeBitsOffset) & 0b11111;
|
//const typeValueFromCatBits = catBits => (catBits >>> TypeBitsOffset) & 0b11111;
|
||||||
|
@ -3169,6 +3172,7 @@ class FilterCompiler {
|
||||||
]);
|
]);
|
||||||
this.modifierIdToNormalizedId = new Map([
|
this.modifierIdToNormalizedId = new Map([
|
||||||
[ sfp.NODE_TYPE_NET_OPTION_NAME_CSP, MODIFIER_TYPE_CSP ],
|
[ sfp.NODE_TYPE_NET_OPTION_NAME_CSP, MODIFIER_TYPE_CSP ],
|
||||||
|
[ sfp.NODE_TYPE_NET_OPTION_NAME_PERMISSIONS, MODIFIER_TYPE_PERMISSIONS ],
|
||||||
[ sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT, MODIFIER_TYPE_REDIRECT ],
|
[ sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT, MODIFIER_TYPE_REDIRECT ],
|
||||||
[ sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE, MODIFIER_TYPE_REDIRECTRULE ],
|
[ sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE, MODIFIER_TYPE_REDIRECTRULE ],
|
||||||
[ sfp.NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM, MODIFIER_TYPE_REMOVEPARAM ],
|
[ sfp.NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM, MODIFIER_TYPE_REMOVEPARAM ],
|
||||||
|
@ -3438,6 +3442,12 @@ class FilterCompiler {
|
||||||
this.processMethodOption(parser.getNetOptionValue(id));
|
this.processMethodOption(parser.getNetOptionValue(id));
|
||||||
this.optionUnitBits |= this.METHOD_BIT;
|
this.optionUnitBits |= this.METHOD_BIT;
|
||||||
break;
|
break;
|
||||||
|
case sfp.NODE_TYPE_NET_OPTION_NAME_PERMISSIONS:
|
||||||
|
if ( this.processModifierOption(id, parser.getNetOptionValue(id)) === false ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.optionUnitBits |= this.PERMISSIONS_BIT;
|
||||||
|
break;
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT: {
|
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT: {
|
||||||
const actualId = this.action === AllowAction
|
const actualId = this.action === AllowAction
|
||||||
? sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE
|
? sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE
|
||||||
|
@ -3554,6 +3564,7 @@ class FilterCompiler {
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_FROM:
|
case sfp.NODE_TYPE_NET_OPTION_NAME_FROM:
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_HEADER:
|
case sfp.NODE_TYPE_NET_OPTION_NAME_HEADER:
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_METHOD:
|
case sfp.NODE_TYPE_NET_OPTION_NAME_METHOD:
|
||||||
|
case sfp.NODE_TYPE_NET_OPTION_NAME_PERMISSIONS:
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT:
|
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT:
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE:
|
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE:
|
||||||
case sfp.NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM:
|
case sfp.NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM:
|
||||||
|
@ -3622,8 +3633,12 @@ class FilterCompiler {
|
||||||
this.optionUnitBits |= this.NOT_TYPE_BIT;
|
this.optionUnitBits |= this.NOT_TYPE_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CSP directives implicitly apply only to document/subdocument.
|
// CSP/permissions options implicitly apply only to
|
||||||
if ( this.modifyType === MODIFIER_TYPE_CSP ) {
|
// document/subdocument.
|
||||||
|
if (
|
||||||
|
this.modifyType === MODIFIER_TYPE_CSP ||
|
||||||
|
this.modifyType === MODIFIER_TYPE_PERMISSIONS
|
||||||
|
) {
|
||||||
if ( this.typeBits === 0 ) {
|
if ( this.typeBits === 0 ) {
|
||||||
this.processTypeOption(sfp.NODE_TYPE_NET_OPTION_NAME_DOC, false);
|
this.processTypeOption(sfp.NODE_TYPE_NET_OPTION_NAME_DOC, false);
|
||||||
this.processTypeOption(sfp.NODE_TYPE_NET_OPTION_NAME_FRAME, false);
|
this.processTypeOption(sfp.NODE_TYPE_NET_OPTION_NAME_FRAME, false);
|
||||||
|
@ -4013,17 +4028,18 @@ class FilterCompiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FilterCompiler.prototype.FROM_BIT = 0b00000000001;
|
FilterCompiler.prototype.FROM_BIT = 0b000000000001;
|
||||||
FilterCompiler.prototype.TO_BIT = 0b00000000010;
|
FilterCompiler.prototype.TO_BIT = 0b000000000010;
|
||||||
FilterCompiler.prototype.DENYALLOW_BIT = 0b00000000100;
|
FilterCompiler.prototype.DENYALLOW_BIT = 0b000000000100;
|
||||||
FilterCompiler.prototype.HEADER_BIT = 0b00000001000;
|
FilterCompiler.prototype.HEADER_BIT = 0b000000001000;
|
||||||
FilterCompiler.prototype.STRICT_PARTY_BIT = 0b00000010000;
|
FilterCompiler.prototype.STRICT_PARTY_BIT = 0b000000010000;
|
||||||
FilterCompiler.prototype.CSP_BIT = 0b00000100000;
|
FilterCompiler.prototype.CSP_BIT = 0b000000100000;
|
||||||
FilterCompiler.prototype.REMOVEPARAM_BIT = 0b00001000000;
|
FilterCompiler.prototype.REMOVEPARAM_BIT = 0b000001000000;
|
||||||
FilterCompiler.prototype.REDIRECT_BIT = 0b00010000000;
|
FilterCompiler.prototype.REDIRECT_BIT = 0b000010000000;
|
||||||
FilterCompiler.prototype.NOT_TYPE_BIT = 0b00100000000;
|
FilterCompiler.prototype.NOT_TYPE_BIT = 0b000100000000;
|
||||||
FilterCompiler.prototype.IMPORTANT_BIT = 0b01000000000;
|
FilterCompiler.prototype.IMPORTANT_BIT = 0b001000000000;
|
||||||
FilterCompiler.prototype.METHOD_BIT = 0b10000000000;
|
FilterCompiler.prototype.METHOD_BIT = 0b010000000000;
|
||||||
|
FilterCompiler.prototype.PERMISSIONS_BIT = 0b100000000000;
|
||||||
|
|
||||||
FilterCompiler.prototype.FILTER_OK = 0;
|
FilterCompiler.prototype.FILTER_OK = 0;
|
||||||
FilterCompiler.prototype.FILTER_INVALID = 1;
|
FilterCompiler.prototype.FILTER_INVALID = 1;
|
||||||
|
|
|
@ -557,6 +557,10 @@ const onHeadersReceived = function(details) {
|
||||||
modifiedHeaders = true;
|
modifiedHeaders = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( injectPP(fctxt, pageStore, responseHeaders) === true ) {
|
||||||
|
modifiedHeaders = true;
|
||||||
|
}
|
||||||
|
|
||||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1376932
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1376932
|
||||||
// Prevent document from being cached by the browser if we modified it,
|
// Prevent document from being cached by the browser if we modified it,
|
||||||
// either through HTML filtering and/or modified response headers.
|
// either through HTML filtering and/or modified response headers.
|
||||||
|
@ -1004,6 +1008,36 @@ const injectCSP = function(fctxt, pageStore, responseHeaders) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
const injectPP = function(fctxt, pageStore, responseHeaders) {
|
||||||
|
const permissions = [];
|
||||||
|
const directives = staticNetFilteringEngine.matchAndFetchModifiers(fctxt, 'permissions');
|
||||||
|
if ( directives !== undefined ) {
|
||||||
|
for ( const directive of directives ) {
|
||||||
|
if ( directive.result !== 1 ) { continue; }
|
||||||
|
permissions.push(directive.value.replace('|', ', '));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( logger.enabled && directives !== undefined ) {
|
||||||
|
fctxt.setRealm('network')
|
||||||
|
.pushFilters(directives.map(a => a.logData()))
|
||||||
|
.toLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( permissions.length === 0 ) { return; }
|
||||||
|
|
||||||
|
µb.updateToolbarIcon(fctxt.tabId, 0x02);
|
||||||
|
|
||||||
|
responseHeaders.push({
|
||||||
|
name: 'permissions-policy',
|
||||||
|
value: permissions.join(', ')
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/1163
|
// https://github.com/gorhill/uBlock/issues/1163
|
||||||
// "Block elements by size".
|
// "Block elements by size".
|
||||||
// https://github.com/gorhill/uBlock/issues/1390#issuecomment-187310719
|
// https://github.com/gorhill/uBlock/issues/1390#issuecomment-187310719
|
||||||
|
|
Loading…
Reference in a new issue