mirror of
https://github.com/gorhill/uBlock.git
synced 2024-10-06 09:37:12 +02:00
Add support for AdGuard's empty
option
Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/701 The filter option `empty` is converted to `redirect=empty` by uBO internally; however unlike when the `redirect=` option is used expressly, the `empty` option does not require a resource type. When `empty` is used, only network requests which are meant to return a text response will be redirected to an empty response body by uBO -- so `empty` will not work for resources such as images, media, or other binary resources.
This commit is contained in:
parent
2c39a1af02
commit
3e5c9e00ab
@ -56,15 +56,15 @@ const redirectableResources = new Map([
|
|||||||
[ 'addthis_widget.js', {
|
[ 'addthis_widget.js', {
|
||||||
alias: 'addthis.com/addthis_widget.js',
|
alias: 'addthis.com/addthis_widget.js',
|
||||||
} ],
|
} ],
|
||||||
|
[ 'amazon_ads.js', {
|
||||||
|
alias: 'amazon-adsystem.com/aax2/amzn_ads.js',
|
||||||
|
} ],
|
||||||
[ 'ampproject_v0.js', {
|
[ 'ampproject_v0.js', {
|
||||||
alias: 'ampproject.org/v0.js',
|
alias: 'ampproject.org/v0.js',
|
||||||
} ],
|
} ],
|
||||||
[ 'chartbeat.js', {
|
[ 'chartbeat.js', {
|
||||||
alias: 'static.chartbeat.com/chartbeat.js',
|
alias: 'static.chartbeat.com/chartbeat.js',
|
||||||
} ],
|
} ],
|
||||||
[ 'amazon_ads.js', {
|
|
||||||
alias: 'amazon-adsystem.com/aax2/amzn_ads.js',
|
|
||||||
} ],
|
|
||||||
[ 'disqus_embed.js', {
|
[ 'disqus_embed.js', {
|
||||||
alias: 'disqus.com/embed.js',
|
alias: 'disqus.com/embed.js',
|
||||||
} ],
|
} ],
|
||||||
@ -74,6 +74,9 @@ const redirectableResources = new Map([
|
|||||||
[ 'doubleclick_instream_ad_status.js', {
|
[ 'doubleclick_instream_ad_status.js', {
|
||||||
alias: 'doubleclick.net/instream/ad_status.js',
|
alias: 'doubleclick.net/instream/ad_status.js',
|
||||||
} ],
|
} ],
|
||||||
|
[ 'empty', {
|
||||||
|
data: 'text', // Important!
|
||||||
|
} ],
|
||||||
[ 'google-analytics_analytics.js', {
|
[ 'google-analytics_analytics.js', {
|
||||||
alias: 'google-analytics.com/analytics.js',
|
alias: 'google-analytics.com/analytics.js',
|
||||||
} ],
|
} ],
|
||||||
@ -165,6 +168,15 @@ const extToMimeMap = new Map([
|
|||||||
[ 'txt', 'text/plain' ],
|
[ 'txt', 'text/plain' ],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const typeToMimeMap = new Map([
|
||||||
|
[ 'main_frame', 'text/html' ],
|
||||||
|
[ 'other', 'text/plain' ],
|
||||||
|
[ 'script', 'application/javascript' ],
|
||||||
|
[ 'stylesheet', 'text/css' ],
|
||||||
|
[ 'sub_frame', 'text/html' ],
|
||||||
|
[ 'xmlhttprequest', 'text/plain' ],
|
||||||
|
]);
|
||||||
|
|
||||||
const validMimes = new Set(extToMimeMap.values());
|
const validMimes = new Set(extToMimeMap.values());
|
||||||
|
|
||||||
const mimeFromName = function(name) {
|
const mimeFromName = function(name) {
|
||||||
@ -177,13 +189,12 @@ const mimeFromName = function(name) {
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
const RedirectEntry = function() {
|
const RedirectEntry = class {
|
||||||
|
constructor() {
|
||||||
this.mime = '';
|
this.mime = '';
|
||||||
this.data = '';
|
this.data = '';
|
||||||
this.warURL = undefined;
|
this.warURL = undefined;
|
||||||
};
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// Prevent redirection to web accessible resources when the request is
|
// Prevent redirection to web accessible resources when the request is
|
||||||
// of type 'xmlhttprequest', because XMLHttpRequest.responseURL would
|
// of type 'xmlhttprequest', because XMLHttpRequest.responseURL would
|
||||||
@ -191,7 +202,7 @@ const RedirectEntry = function() {
|
|||||||
// - https://stackoverflow.com/a/8056313
|
// - https://stackoverflow.com/a/8056313
|
||||||
// - https://bugzilla.mozilla.org/show_bug.cgi?id=998076
|
// - https://bugzilla.mozilla.org/show_bug.cgi?id=998076
|
||||||
|
|
||||||
RedirectEntry.prototype.toURL = function(fctxt, asDataURI = false) {
|
toURL(fctxt, asDataURI = false) {
|
||||||
if (
|
if (
|
||||||
this.warURL !== undefined &&
|
this.warURL !== undefined &&
|
||||||
asDataURI !== true &&
|
asDataURI !== true &&
|
||||||
@ -201,15 +212,19 @@ RedirectEntry.prototype.toURL = function(fctxt, asDataURI = false) {
|
|||||||
return `${this.warURL}${vAPI.warSecret()}`;
|
return `${this.warURL}${vAPI.warSecret()}`;
|
||||||
}
|
}
|
||||||
if ( this.data === undefined ) { return; }
|
if ( this.data === undefined ) { return; }
|
||||||
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/701
|
||||||
|
if ( this.data === '' ) {
|
||||||
|
const mime = typeToMimeMap.get(fctxt.type);
|
||||||
|
if ( mime === undefined ) { return; }
|
||||||
|
return `data:${mime},`;
|
||||||
|
}
|
||||||
if ( this.data.startsWith('data:') === false ) {
|
if ( this.data.startsWith('data:') === false ) {
|
||||||
this.data = `data:${this.mime};base64,${btoa(this.data)}`;
|
this.data = `data:${this.mime};base64,${btoa(this.data)}`;
|
||||||
}
|
}
|
||||||
return this.data;
|
return this.data;
|
||||||
};
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
toContent() {
|
||||||
|
|
||||||
RedirectEntry.prototype.toContent = function() {
|
|
||||||
if ( this.data.startsWith('data:') ) {
|
if ( this.data.startsWith('data:') ) {
|
||||||
const pos = this.data.indexOf(',');
|
const pos = this.data.indexOf(',');
|
||||||
const base64 = this.data.endsWith(';base64', pos);
|
const base64 = this.data.endsWith(';base64', pos);
|
||||||
@ -219,25 +234,22 @@ RedirectEntry.prototype.toContent = function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.data;
|
return this.data;
|
||||||
};
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
static fromContent(mime, content) {
|
||||||
|
|
||||||
RedirectEntry.fromContent = function(mime, content) {
|
|
||||||
const r = new RedirectEntry();
|
const r = new RedirectEntry();
|
||||||
r.mime = mime;
|
r.mime = mime;
|
||||||
r.data = content;
|
r.data = content;
|
||||||
return r;
|
return r;
|
||||||
};
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
static fromSelfie(selfie) {
|
||||||
|
|
||||||
RedirectEntry.fromSelfie = function(selfie) {
|
|
||||||
const r = new RedirectEntry();
|
const r = new RedirectEntry();
|
||||||
r.mime = selfie.mime;
|
r.mime = selfie.mime;
|
||||||
r.data = selfie.data;
|
r.data = selfie.data;
|
||||||
r.warURL = selfie.warURL;
|
r.warURL = selfie.warURL;
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -248,7 +260,13 @@ const RedirectEngine = function() {
|
|||||||
this.resources = new Map();
|
this.resources = new Map();
|
||||||
this.reset();
|
this.reset();
|
||||||
this.resourceNameRegister = '';
|
this.resourceNameRegister = '';
|
||||||
this._desAll = []; // re-use better than re-allocate
|
|
||||||
|
// Internal use
|
||||||
|
this._missedQueryHash = '';
|
||||||
|
this._src = '';
|
||||||
|
this._srcAll = [ '*' ];
|
||||||
|
this._des = '';
|
||||||
|
this._desAll = [ '*' ];
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -278,35 +296,60 @@ RedirectEngine.prototype.toBroaderHostname = function(hostname) {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
RedirectEngine.prototype.decomposeHostname = function(hn, dict, out) {
|
||||||
|
let i = 0;
|
||||||
|
for (;;) {
|
||||||
|
if ( dict.has(hn) ) {
|
||||||
|
out[i] = hn; i += 1;
|
||||||
|
}
|
||||||
|
hn = this.toBroaderHostname(hn);
|
||||||
|
if ( hn === '' ) { break; }
|
||||||
|
}
|
||||||
|
out.length = i;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
RedirectEngine.prototype.lookup = function(fctxt) {
|
RedirectEngine.prototype.lookup = function(fctxt) {
|
||||||
|
const src = fctxt.getDocHostname();
|
||||||
|
const des = fctxt.getHostname();
|
||||||
const type = fctxt.type;
|
const type = fctxt.type;
|
||||||
if ( this.ruleTypes.has(type) === false ) { return; }
|
const queryHash = `${src} ${des} ${type}`;
|
||||||
const desAll = this._desAll;
|
if ( queryHash === this._missedQueryHash ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( src !== this._src ) {
|
||||||
|
this._src = src;
|
||||||
|
this.decomposeHostname(src, this.ruleSources, this._srcAll);
|
||||||
|
}
|
||||||
|
if ( this._srcAll.length === 0 ) {
|
||||||
|
this._missedQueryHash = queryHash;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( des !== this._des ) {
|
||||||
|
this._des = des;
|
||||||
|
this.decomposeHostname(des, this.ruleDestinations, this._desAll);
|
||||||
|
}
|
||||||
|
if ( this._desAll.length === 0 ) {
|
||||||
|
this._missedQueryHash = queryHash;
|
||||||
|
return;
|
||||||
|
}
|
||||||
const reqURL = fctxt.url;
|
const reqURL = fctxt.url;
|
||||||
let src = fctxt.getDocHostname();
|
for ( const src of this._srcAll ) {
|
||||||
let des = fctxt.getHostname();
|
for ( const des of this._desAll ) {
|
||||||
let n = 0;
|
let entries = this.rules.get(`${src} ${des} ${type}`);
|
||||||
for (;;) {
|
if ( entries !== undefined ) {
|
||||||
if ( this.ruleDestinations.has(des) ) {
|
|
||||||
desAll[n] = des; n += 1;
|
|
||||||
}
|
|
||||||
des = this.toBroaderHostname(des);
|
|
||||||
if ( des === '' ) { break; }
|
|
||||||
}
|
|
||||||
if ( n === 0 ) { return; }
|
|
||||||
for (;;) {
|
|
||||||
if ( this.ruleSources.has(src) ) {
|
|
||||||
for ( let i = 0; i < n; i++ ) {
|
|
||||||
const entries = this.rules.get(`${src} ${desAll[i]} ${type}`);
|
|
||||||
if ( entries === undefined ) { continue; }
|
|
||||||
const rule = this.lookupRule(entries, reqURL);
|
const rule = this.lookupRule(entries, reqURL);
|
||||||
if ( rule === undefined ) { continue; }
|
if ( rule !== undefined ) { return rule; }
|
||||||
return rule;
|
}
|
||||||
|
entries = this.rules.get(`${src} ${des} *`);
|
||||||
|
if ( entries !== undefined ) {
|
||||||
|
const rule = this.lookupRule(entries, reqURL);
|
||||||
|
if ( rule !== undefined ) { return rule; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
src = this.toBroaderHostname(src);
|
|
||||||
if ( src === '' ) { break; }
|
|
||||||
}
|
}
|
||||||
|
this._missedQueryHash = queryHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
RedirectEngine.prototype.lookupRule = function(entries, reqURL) {
|
RedirectEngine.prototype.lookupRule = function(entries, reqURL) {
|
||||||
@ -428,6 +471,10 @@ RedirectEngine.prototype.compileRuleFromStaticFilter = function(line) {
|
|||||||
redirect = option.slice(14);
|
redirect = option.slice(14);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if ( option === 'empty' ) {
|
||||||
|
redirect = 'empty';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if ( option.startsWith('domain=') ) {
|
if ( option.startsWith('domain=') ) {
|
||||||
srchns = option.slice(7).split('|');
|
srchns = option.slice(7).split('|');
|
||||||
continue;
|
continue;
|
||||||
@ -448,7 +495,10 @@ RedirectEngine.prototype.compileRuleFromStaticFilter = function(line) {
|
|||||||
if ( redirect === '' ) { return; }
|
if ( redirect === '' ) { return; }
|
||||||
|
|
||||||
// Need one single type -- not negated.
|
// Need one single type -- not negated.
|
||||||
if ( type === undefined ) { return; }
|
if ( type === undefined ) {
|
||||||
|
if ( redirect !== 'empty' ) { return; }
|
||||||
|
type = '*';
|
||||||
|
}
|
||||||
|
|
||||||
if ( deshn === '' ) {
|
if ( deshn === '' ) {
|
||||||
deshn = '*';
|
deshn = '*';
|
||||||
@ -649,12 +699,12 @@ const removeTopCommentBlock = function(text) {
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
RedirectEngine.prototype.loadBuiltinResources = function() {
|
RedirectEngine.prototype.loadBuiltinResources = function() {
|
||||||
this.resources = new Map();
|
|
||||||
this.aliases = new Map();
|
|
||||||
|
|
||||||
// TODO: remove once usage of uBO 1.20.4 is widespread.
|
// TODO: remove once usage of uBO 1.20.4 is widespread.
|
||||||
µBlock.assets.remove('ublock-resources');
|
µBlock.assets.remove('ublock-resources');
|
||||||
|
|
||||||
|
this.resources = new Map();
|
||||||
|
this.aliases = new Map();
|
||||||
|
|
||||||
const fetches = [
|
const fetches = [
|
||||||
µBlock.assets.fetchText(
|
µBlock.assets.fetchText(
|
||||||
'/assets/resources/scriptlets.js'
|
'/assets/resources/scriptlets.js'
|
||||||
|
@ -2012,6 +2012,11 @@ FilterParser.prototype.parseOptions = function(s) {
|
|||||||
}
|
}
|
||||||
// Used by Adguard, purpose is unclear -- just ignore for now.
|
// Used by Adguard, purpose is unclear -- just ignore for now.
|
||||||
if ( opt === 'empty' ) {
|
if ( opt === 'empty' ) {
|
||||||
|
if ( this.redirect !== 0 ) {
|
||||||
|
this.unsupported = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.redirect = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// https://github.com/uBlockOrigin/uAssets/issues/192
|
// https://github.com/uBlockOrigin/uAssets/issues/192
|
||||||
|
0
src/web_accessible_resources/empty
Normal file
0
src/web_accessible_resources/empty
Normal file
Loading…
Reference in New Issue
Block a user