mirror of https://github.com/gorhill/uBlock.git
Improve `prevent-fetch` scriptlet
Related discussion: https://github.com/uBlockOrigin/uBlock-discussions/discussions/848#discussioncomment-10027757 Added support for AdGuard's `responseType` parameter. Extended the meaning of that 3rd parameter to also be a JSON string with properties to set on the returned response instance. Currently supported properties: - `ok`, supported values: `false`, `true` - `type, supported values: `"basic"`, `"cors"`, `"opaque"` Reference: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#-%EF%B8%8F-prevent-fetch
This commit is contained in:
parent
a54d416143
commit
e785b99338
|
@ -57,6 +57,7 @@ function safeSelf() {
|
||||||
'Math_random': Math.random,
|
'Math_random': Math.random,
|
||||||
'Object': Object,
|
'Object': Object,
|
||||||
'Object_defineProperty': Object.defineProperty.bind(Object),
|
'Object_defineProperty': Object.defineProperty.bind(Object),
|
||||||
|
'Object_defineProperties': Object.defineProperties.bind(Object),
|
||||||
'Object_fromEntries': Object.fromEntries.bind(Object),
|
'Object_fromEntries': Object.fromEntries.bind(Object),
|
||||||
'Object_getOwnPropertyDescriptor': Object.getOwnPropertyDescriptor.bind(Object),
|
'Object_getOwnPropertyDescriptor': Object.getOwnPropertyDescriptor.bind(Object),
|
||||||
'RegExp': self.RegExp,
|
'RegExp': self.RegExp,
|
||||||
|
@ -2067,11 +2068,11 @@ builtinScriptlets.push({
|
||||||
});
|
});
|
||||||
function noFetchIf(
|
function noFetchIf(
|
||||||
propsToMatch = '',
|
propsToMatch = '',
|
||||||
responseBody = ''
|
responseBody = '',
|
||||||
|
responseType = ''
|
||||||
) {
|
) {
|
||||||
if ( typeof propsToMatch !== 'string' ) { return; }
|
|
||||||
const safe = safeSelf();
|
const safe = safeSelf();
|
||||||
const logPrefix = safe.makeLogPrefix('prevent-fetch', propsToMatch, responseBody);
|
const logPrefix = safe.makeLogPrefix('prevent-fetch', propsToMatch, responseBody, responseType);
|
||||||
const needles = [];
|
const needles = [];
|
||||||
for ( const condition of propsToMatch.split(/\s+/) ) {
|
for ( const condition of propsToMatch.split(/\s+/) ) {
|
||||||
if ( condition === '' ) { continue; }
|
if ( condition === '' ) { continue; }
|
||||||
|
@ -2086,6 +2087,26 @@ function noFetchIf(
|
||||||
}
|
}
|
||||||
needles.push({ key, re: safe.patternToRegex(value) });
|
needles.push({ key, re: safe.patternToRegex(value) });
|
||||||
}
|
}
|
||||||
|
const validResponseProps = {
|
||||||
|
ok: [ false, true ],
|
||||||
|
type: [ 'basic', 'cors', 'opaque' ],
|
||||||
|
};
|
||||||
|
let responseProps;
|
||||||
|
if ( /^\{.*\}$/.test(responseType) ) {
|
||||||
|
responseProps = {};
|
||||||
|
try {
|
||||||
|
Object.entries(JSON.parse(responseType)).forEach(([ p, v ]) => {
|
||||||
|
if ( validResponseProps[p] === undefined ) { return; }
|
||||||
|
if ( validResponseProps[p].includes(v) === false ) { return; }
|
||||||
|
responseProps[p] = { value: v };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch(ex) {}
|
||||||
|
} else if ( responseType !== '' ) {
|
||||||
|
if ( validResponseProps.type.includes(responseType) ) {
|
||||||
|
responseProps = { type: { value: responseType } };
|
||||||
|
}
|
||||||
|
}
|
||||||
self.fetch = new Proxy(self.fetch, {
|
self.fetch = new Proxy(self.fetch, {
|
||||||
apply: function(target, thisArg, args) {
|
apply: function(target, thisArg, args) {
|
||||||
const details = args[0] instanceof self.Request
|
const details = args[0] instanceof self.Request
|
||||||
|
@ -2123,17 +2144,6 @@ function noFetchIf(
|
||||||
if ( proceed ) {
|
if ( proceed ) {
|
||||||
return Reflect.apply(target, thisArg, args);
|
return Reflect.apply(target, thisArg, args);
|
||||||
}
|
}
|
||||||
let responseType = '';
|
|
||||||
if ( details.mode === undefined || details.mode === 'cors' ) {
|
|
||||||
try {
|
|
||||||
const desURL = new URL(details.url);
|
|
||||||
responseType = desURL.origin !== document.location.origin
|
|
||||||
? 'cors'
|
|
||||||
: 'basic';
|
|
||||||
} catch(ex) {
|
|
||||||
safe.uboErr(logPrefix, `Error: ${ex}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return generateContentFn(responseBody).then(text => {
|
return generateContentFn(responseBody).then(text => {
|
||||||
safe.uboLog(logPrefix, `Prevented with response "${text}"`);
|
safe.uboLog(logPrefix, `Prevented with response "${text}"`);
|
||||||
const response = new Response(text, {
|
const response = new Response(text, {
|
||||||
|
@ -2142,14 +2152,11 @@ function noFetchIf(
|
||||||
'Content-Length': text.length,
|
'Content-Length': text.length,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
safe.Object_defineProperty(response, 'url', {
|
const props = Object.assign(
|
||||||
value: details.url
|
{ url: { value: details.url } },
|
||||||
});
|
responseProps
|
||||||
if ( responseType !== '' ) {
|
);
|
||||||
safe.Object_defineProperty(response, 'type', {
|
safe.Object_defineProperties(response, props);
|
||||||
value: responseType
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return response;
|
return response;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue