mirror of https://github.com/gorhill/uBlock.git
Remove `assets` dependency from redirect engine
Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/1664 This change allows to add the redirect engine into the nodejs package. The purpose of the redirect engine is to resolve a redirect token into a path to a local resource, to be used by the caller as wished.
This commit is contained in:
parent
3879835324
commit
f8daea085b
|
@ -23,8 +23,6 @@
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
import io from './assets.js';
|
||||
|
||||
import {
|
||||
LineIterator,
|
||||
orphanizeString,
|
||||
|
@ -204,6 +202,14 @@ const mimeFromName = function(name) {
|
|||
}
|
||||
};
|
||||
|
||||
// vAPI.warSecret() is optional, it could be absent in some environments,
|
||||
// i.e. nodejs for example. Probably the best approach is to have the
|
||||
// "web_accessible_resources secret" added outside by the client of this
|
||||
// module, but for now I just want to remove an obstacle to modularization.
|
||||
const warSecret = typeof vAPI === 'object' && vAPI !== null
|
||||
? vAPI.warSecret
|
||||
: ( ) => '';
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
|
@ -230,14 +236,20 @@ const RedirectEntry = class {
|
|||
fctxt instanceof Object &&
|
||||
fctxt.type !== 'xmlhttprequest'
|
||||
) {
|
||||
let url = `${this.warURL}?secret=${vAPI.warSecret()}`;
|
||||
const params = [];
|
||||
const secret = warSecret();
|
||||
if ( secret !== '' ) { params.push(`secret=${secret}`); }
|
||||
if ( this.params !== undefined ) {
|
||||
for ( const name of this.params ) {
|
||||
const value = fctxt[name];
|
||||
if ( value === undefined ) { continue; }
|
||||
url += `&${name}=${encodeURIComponent(value)}`;
|
||||
params.push(`${name}=${encodeURIComponent(value)}`);
|
||||
}
|
||||
}
|
||||
let url = `${this.warURL}`;
|
||||
if ( params.length !== 0 ) {
|
||||
url += `?${params.join('&')}`;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
if ( this.data === undefined ) { return; }
|
||||
|
@ -439,18 +451,18 @@ const removeTopCommentBlock = function(text) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
RedirectEngine.prototype.loadBuiltinResources = function() {
|
||||
RedirectEngine.prototype.loadBuiltinResources = function(fetcher) {
|
||||
this.resources = new Map();
|
||||
this.aliases = new Map();
|
||||
|
||||
const fetches = [
|
||||
io.fetchText(
|
||||
fetcher(
|
||||
'/assets/resources/scriptlets.js'
|
||||
).then(result => {
|
||||
const content = result.content;
|
||||
if ( typeof content === 'string' && content.length !== 0 ) {
|
||||
if ( typeof content !== 'string' ) { return; }
|
||||
if ( content.length === 0 ) { return; }
|
||||
this.resourcesFromString(content);
|
||||
}
|
||||
}),
|
||||
];
|
||||
|
||||
|
@ -459,7 +471,7 @@ RedirectEngine.prototype.loadBuiltinResources = function() {
|
|||
const entry = RedirectEntry.fromSelfie({
|
||||
mime: mimeFromName(name),
|
||||
data,
|
||||
warURL: vAPI.getURL(`/web_accessible_resources/${name}`),
|
||||
warURL: `/web_accessible_resources/${name}`,
|
||||
params: details.params,
|
||||
});
|
||||
this.resources.set(name, entry);
|
||||
|
@ -506,10 +518,9 @@ RedirectEngine.prototype.loadBuiltinResources = function() {
|
|||
continue;
|
||||
}
|
||||
fetches.push(
|
||||
io.fetch(
|
||||
`/web_accessible_resources/${name}?secret=${vAPI.warSecret()}`,
|
||||
{ responseType: details.data }
|
||||
).then(
|
||||
fetcher(`/web_accessible_resources/${name}`, {
|
||||
responseType: details.data
|
||||
}).then(
|
||||
result => process(result)
|
||||
)
|
||||
);
|
||||
|
@ -545,21 +556,22 @@ RedirectEngine.prototype.getResourceDetails = function() {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
const resourcesSelfieVersion = 5;
|
||||
const RESOURCES_SELFIE_VERSION = 6;
|
||||
const RESOURCES_SELFIE_NAME = 'compiled/redirectEngine/resources';
|
||||
|
||||
RedirectEngine.prototype.selfieFromResources = function() {
|
||||
io.put(
|
||||
'compiled/redirectEngine/resources',
|
||||
RedirectEngine.prototype.selfieFromResources = function(storage) {
|
||||
storage.put(
|
||||
RESOURCES_SELFIE_NAME,
|
||||
JSON.stringify({
|
||||
version: resourcesSelfieVersion,
|
||||
version: RESOURCES_SELFIE_VERSION,
|
||||
aliases: Array.from(this.aliases),
|
||||
resources: Array.from(this.resources),
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
RedirectEngine.prototype.resourcesFromSelfie = async function() {
|
||||
const result = await io.get('compiled/redirectEngine/resources');
|
||||
RedirectEngine.prototype.resourcesFromSelfie = async function(storage) {
|
||||
const result = await storage.get(RESOURCES_SELFIE_NAME);
|
||||
let selfie;
|
||||
try {
|
||||
selfie = JSON.parse(result.content);
|
||||
|
@ -567,7 +579,7 @@ RedirectEngine.prototype.resourcesFromSelfie = async function() {
|
|||
}
|
||||
if (
|
||||
selfie instanceof Object === false ||
|
||||
selfie.version !== resourcesSelfieVersion ||
|
||||
selfie.version !== RESOURCES_SELFIE_VERSION ||
|
||||
Array.isArray(selfie.resources) === false
|
||||
) {
|
||||
return false;
|
||||
|
@ -580,8 +592,8 @@ RedirectEngine.prototype.resourcesFromSelfie = async function() {
|
|||
return true;
|
||||
};
|
||||
|
||||
RedirectEngine.prototype.invalidateResourcesSelfie = function() {
|
||||
io.remove('compiled/redirectEngine/resources');
|
||||
RedirectEngine.prototype.invalidateResourcesSelfie = function(storage) {
|
||||
storage.remove(RESOURCES_SELFIE_NAME);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -140,7 +140,7 @@ const onVersionReady = function(lastVersion) {
|
|||
|
||||
// Since built-in resources may have changed since last version, we
|
||||
// force a reload of all resources.
|
||||
redirectEngine.invalidateResourcesSelfie();
|
||||
redirectEngine.invalidateResourcesSelfie(io);
|
||||
|
||||
// https://github.com/LiCybora/NanoDefenderFirefox/issues/196
|
||||
// Toggle on the blocking of CSP reports by default for Firefox.
|
||||
|
|
|
@ -35,7 +35,6 @@ import {
|
|||
hostnameFromNetworkURL,
|
||||
} from './uri-utils.js';
|
||||
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#browser_compatibility
|
||||
//
|
||||
// This import would be best done dynamically, but since dynamic imports are
|
||||
|
@ -4287,22 +4286,20 @@ FilterContainer.prototype.redirectRequest = function(redirectEngine, fctxt) {
|
|||
const highest = directives.length - 1;
|
||||
// More than a single directive means more work.
|
||||
if ( highest !== 0 ) {
|
||||
directives.sort(
|
||||
FilterContainer.compareRedirectRequests.bind(this, redirectEngine)
|
||||
);
|
||||
directives.sort((a, b) => compareRedirectRequests(redirectEngine, a, b));
|
||||
}
|
||||
// Redirect to highest-ranked directive
|
||||
const directive = directives[highest];
|
||||
if ( (directive.bits & AllowAction) === 0 ) {
|
||||
const { token } =
|
||||
FilterContainer.parseRedirectRequestValue(directive.modifier);
|
||||
parseRedirectRequestValue(directive.modifier);
|
||||
fctxt.redirectURL = redirectEngine.tokenToURL(fctxt, token);
|
||||
if ( fctxt.redirectURL === undefined ) { return; }
|
||||
}
|
||||
return directives;
|
||||
};
|
||||
|
||||
FilterContainer.parseRedirectRequestValue = function(modifier) {
|
||||
const parseRedirectRequestValue = function(modifier) {
|
||||
if ( modifier.cache === undefined ) {
|
||||
modifier.cache =
|
||||
StaticFilteringParser.parseRedirectValue(modifier.value);
|
||||
|
@ -4310,12 +4307,12 @@ FilterContainer.parseRedirectRequestValue = function(modifier) {
|
|||
return modifier.cache;
|
||||
};
|
||||
|
||||
FilterContainer.compareRedirectRequests = function(redirectEngine, a, b) {
|
||||
const compareRedirectRequests = function(redirectEngine, a, b) {
|
||||
const { token: atok, priority: aint, bits: abits } =
|
||||
FilterContainer.parseRedirectRequestValue(a.modifier);
|
||||
parseRedirectRequestValue(a.modifier);
|
||||
if ( redirectEngine.hasToken(atok) === false ) { return -1; }
|
||||
const { token: btok, priority: bint, bits: bbits } =
|
||||
FilterContainer.parseRedirectRequestValue(b.modifier);
|
||||
parseRedirectRequestValue(b.modifier);
|
||||
if ( redirectEngine.hasToken(btok) === false ) { return 1; }
|
||||
if ( abits !== bbits ) {
|
||||
if ( (abits & Important) !== 0 ) { return 1; }
|
||||
|
|
|
@ -1151,11 +1151,19 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
|
|||
|
||||
µb.loadRedirectResources = async function() {
|
||||
try {
|
||||
const success = await redirectEngine.resourcesFromSelfie();
|
||||
const success = await redirectEngine.resourcesFromSelfie(io);
|
||||
if ( success === true ) { return true; }
|
||||
|
||||
const fetcher = (path, options = undefined) => {
|
||||
if ( path.startsWith('/web_accessible_resources/') ) {
|
||||
path += `?secret=${vAPI.warSecret()}`;
|
||||
return io.fetch(path, options);
|
||||
}
|
||||
return io.fetchText(path);
|
||||
};
|
||||
|
||||
const fetchPromises = [
|
||||
redirectEngine.loadBuiltinResources()
|
||||
redirectEngine.loadBuiltinResources(fetcher)
|
||||
];
|
||||
|
||||
const userResourcesLocation = this.hiddenSettings.userResourcesLocation;
|
||||
|
@ -1182,7 +1190,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
|
|||
}
|
||||
|
||||
redirectEngine.resourcesFromString(content);
|
||||
redirectEngine.selfieFromResources();
|
||||
redirectEngine.selfieFromResources(io);
|
||||
} catch(ex) {
|
||||
ubolog(ex);
|
||||
return false;
|
||||
|
@ -1617,7 +1625,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
|
|||
this.hiddenSettings.userResourcesLocation !== 'unset' ||
|
||||
vAPI.webextFlavor.soup.has('devbuild')
|
||||
) {
|
||||
redirectEngine.invalidateResourcesSelfie();
|
||||
redirectEngine.invalidateResourcesSelfie(io);
|
||||
}
|
||||
this.loadFilterLists();
|
||||
}
|
||||
|
|
|
@ -61,6 +61,12 @@ const supportsFloc = document.interestCohort instanceof Function;
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
const patchLocalRedirectURL = url => url.charCodeAt(0) === 0x2F /* '/' */
|
||||
? vAPI.getURL(url)
|
||||
: url;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Intercept and filter web requests.
|
||||
|
||||
const onBeforeRequest = function(details) {
|
||||
|
@ -102,7 +108,7 @@ const onBeforeRequest = function(details) {
|
|||
// Redirected
|
||||
|
||||
if ( fctxt.redirectURL !== undefined ) {
|
||||
return { redirectUrl: fctxt.redirectURL };
|
||||
return { redirectUrl: patchLocalRedirectURL(fctxt.redirectURL) };
|
||||
}
|
||||
|
||||
// Not redirected
|
||||
|
@ -208,7 +214,7 @@ const onBeforeRootFrameRequest = function(fctxt) {
|
|||
// Redirected
|
||||
|
||||
if ( fctxt.redirectURL !== undefined ) {
|
||||
return { redirectUrl: fctxt.redirectURL };
|
||||
return { redirectUrl: patchLocalRedirectURL(fctxt.redirectURL) };
|
||||
}
|
||||
|
||||
// Not blocked
|
||||
|
@ -414,7 +420,7 @@ const onBeforeBehindTheSceneRequest = function(fctxt) {
|
|||
// Redirected
|
||||
|
||||
if ( fctxt.redirectURL !== undefined ) {
|
||||
return { redirectUrl: fctxt.redirectURL };
|
||||
return { redirectUrl: patchLocalRedirectURL(fctxt.redirectURL) };
|
||||
}
|
||||
|
||||
// Blocked?
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
import contextMenu from './contextmenu.js';
|
||||
import cosmeticFilteringEngine from './cosmetic-filtering.js';
|
||||
import io from './assets.js';
|
||||
import µb from './background.js';
|
||||
import { hostnameFromURI } from './uri-utils.js';
|
||||
import { redirectEngine } from './redirect-engine.js';
|
||||
|
@ -423,7 +424,7 @@ const matchBucket = function(url, hostname, bucket, start) {
|
|||
this.hiddenSettings = hs;
|
||||
this.saveHiddenSettings();
|
||||
if ( mustReloadResources ) {
|
||||
redirectEngine.invalidateResourcesSelfie();
|
||||
redirectEngine.invalidateResourcesSelfie(io);
|
||||
this.loadRedirectResources();
|
||||
}
|
||||
this.fireDOMEvent('hiddenSettingsChanged');
|
||||
|
|
Loading…
Reference in New Issue