2017-12-28 19:49:02 +01:00
|
|
|
/*******************************************************************************
|
|
|
|
|
|
|
|
uBlock Origin - a browser extension to block requests.
|
2018-09-07 15:11:07 +02:00
|
|
|
Copyright (C) 2017-present Raymond Hill
|
2017-12-28 19:49:02 +01:00
|
|
|
|
|
|
|
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.scriptletFilteringEngine = (function() {
|
2018-12-13 18:30:54 +01:00
|
|
|
const µb = µBlock,
|
2017-12-28 19:49:02 +01:00
|
|
|
duplicates = new Set(),
|
|
|
|
scriptletCache = new µb.MRUCache(32),
|
|
|
|
scriptletsRegister = new Map(),
|
2018-12-13 18:30:54 +01:00
|
|
|
exceptionsRegister = new Set(),
|
2017-12-28 19:49:02 +01:00
|
|
|
reEscapeScriptArg = /[\\'"]/g;
|
|
|
|
|
2018-12-13 18:30:54 +01:00
|
|
|
let acceptedCount = 0,
|
|
|
|
discardedCount = 0,
|
2019-05-14 14:52:34 +02:00
|
|
|
scriptletDB = new µb.staticExtFilteringEngine.HostnameBasedDB(1);
|
2018-12-13 18:30:54 +01:00
|
|
|
|
|
|
|
const api = {
|
|
|
|
get acceptedCount() {
|
|
|
|
return acceptedCount;
|
|
|
|
},
|
|
|
|
get discardedCount() {
|
|
|
|
return discardedCount;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-05-20 12:49:12 +02:00
|
|
|
// Purpose of `contentscriptCode` below is too programmatically inject
|
|
|
|
// content script code which only purpose is to inject scriptlets. This
|
|
|
|
// essentially does the same as what uBO's declarative content script does,
|
|
|
|
// except that this allows to inject the scriptlets earlier than it is
|
|
|
|
// possible through the declarative content script.
|
|
|
|
//
|
|
|
|
// Declaratively:
|
|
|
|
// 1. Browser injects generic content script =>
|
|
|
|
// 2. Content script queries scriptlets =>
|
|
|
|
// 3. Main process sends scriptlets =>
|
|
|
|
// 4. Content script injects scriptlets
|
|
|
|
//
|
|
|
|
// Programmatically:
|
|
|
|
// 1. uBO injects specific scriptlets-aware content script =>
|
|
|
|
// 2. Content script injects scriptlets
|
|
|
|
//
|
|
|
|
// However currently this programmatic injection works well only on
|
|
|
|
// Chromium-based browsers, it does not work properly with Firefox. More
|
|
|
|
// investigations is needed to find out why this fails with Firefox.
|
|
|
|
// Consequently, the programmatic-injection code path is taken only with
|
|
|
|
// Chromium-based browsers.
|
|
|
|
|
2019-07-08 14:56:36 +02:00
|
|
|
const contentscriptCode = (( ) => {
|
2018-12-13 18:30:54 +01:00
|
|
|
const parts = [
|
2018-05-17 22:24:08 +02:00
|
|
|
'(',
|
|
|
|
function(hostname, scriptlets) {
|
2018-05-20 12:49:12 +02:00
|
|
|
if (
|
|
|
|
document.location === null ||
|
|
|
|
hostname !== document.location.hostname
|
|
|
|
) {
|
|
|
|
return;
|
2018-05-17 13:33:21 +02:00
|
|
|
}
|
2019-07-08 14:56:36 +02:00
|
|
|
const injectScriptlets = function(d) {
|
2018-05-22 15:26:49 +02:00
|
|
|
let script;
|
2018-05-20 12:49:12 +02:00
|
|
|
try {
|
2018-05-22 15:26:49 +02:00
|
|
|
script = d.createElement('script');
|
2018-05-20 12:49:12 +02:00
|
|
|
script.appendChild(d.createTextNode(
|
|
|
|
decodeURIComponent(scriptlets))
|
|
|
|
);
|
|
|
|
(d.head || d.documentElement).appendChild(script);
|
|
|
|
} catch (ex) {
|
|
|
|
}
|
2018-06-02 00:41:27 +02:00
|
|
|
if ( script ) {
|
|
|
|
if ( script.parentNode ) {
|
|
|
|
script.parentNode.removeChild(script);
|
|
|
|
}
|
|
|
|
script.textContent = '';
|
2018-05-20 12:49:12 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
injectScriptlets(document);
|
2019-07-08 14:56:36 +02:00
|
|
|
const processIFrame = function(iframe) {
|
|
|
|
const src = iframe.src;
|
2018-05-20 12:49:12 +02:00
|
|
|
if ( /^https?:\/\//.test(src) === false ) {
|
|
|
|
injectScriptlets(iframe.contentDocument);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
let observerTimer,
|
|
|
|
observerLists = [];
|
2019-07-08 14:56:36 +02:00
|
|
|
const observerAsync = function() {
|
|
|
|
for ( const nodelist of observerLists ) {
|
|
|
|
for ( const node of nodelist ) {
|
2018-05-20 12:49:12 +02:00
|
|
|
if ( node.nodeType !== 1 ) { continue; }
|
|
|
|
if ( node.parentElement === null ) { continue; }
|
|
|
|
if ( node.localName === 'iframe' ) {
|
|
|
|
processIFrame(node);
|
|
|
|
}
|
|
|
|
if ( node.childElementCount === 0 ) { continue; }
|
|
|
|
let iframes = node.querySelectorAll('iframe');
|
2019-07-08 14:56:36 +02:00
|
|
|
for ( const iframe of iframes ) {
|
2018-05-20 12:49:12 +02:00
|
|
|
processIFrame(iframe);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
observerLists = [];
|
|
|
|
observerTimer = undefined;
|
|
|
|
};
|
2019-07-08 14:56:36 +02:00
|
|
|
const ready = function(ev) {
|
2018-05-20 12:49:12 +02:00
|
|
|
if ( ev !== undefined ) {
|
|
|
|
window.removeEventListener(ev.type, ready);
|
|
|
|
}
|
2019-07-08 14:56:36 +02:00
|
|
|
const iframes = document.getElementsByTagName('iframe');
|
2018-05-20 12:49:12 +02:00
|
|
|
if ( iframes.length !== 0 ) {
|
|
|
|
observerLists.push(iframes);
|
|
|
|
observerTimer = setTimeout(observerAsync, 1);
|
|
|
|
}
|
2019-07-08 14:56:36 +02:00
|
|
|
const observer = new MutationObserver(function(mutations) {
|
|
|
|
for ( const mutation of mutations ) {
|
2018-05-20 12:49:12 +02:00
|
|
|
if ( mutation.addedNodes.length !== 0 ) {
|
|
|
|
observerLists.push(mutation.addedNodes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
observerLists.length !== 0 &&
|
|
|
|
observerTimer === undefined
|
|
|
|
) {
|
|
|
|
observerTimer = setTimeout(observerAsync, 1);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
observer.observe(
|
|
|
|
document.documentElement,
|
|
|
|
{ childList: true, subtree: true }
|
|
|
|
);
|
|
|
|
};
|
|
|
|
if ( document.readyState === 'loading' ) {
|
|
|
|
window.addEventListener('DOMContentLoaded', ready);
|
|
|
|
} else {
|
|
|
|
ready();
|
2018-05-17 13:33:21 +02:00
|
|
|
}
|
|
|
|
}.toString(),
|
2018-05-17 22:24:08 +02:00
|
|
|
')(',
|
|
|
|
'"', 'hostname-slot', '", ',
|
|
|
|
'"', 'scriptlets-slot', '"',
|
|
|
|
'); void 0;',
|
|
|
|
];
|
|
|
|
return {
|
|
|
|
parts: parts,
|
|
|
|
hostnameSlot: parts.indexOf('hostname-slot'),
|
|
|
|
scriptletsSlot: parts.indexOf('scriptlets-slot'),
|
|
|
|
assemble: function(hostname, scriptlets) {
|
|
|
|
this.parts[this.hostnameSlot] = hostname;
|
|
|
|
this.parts[this.scriptletsSlot] =
|
|
|
|
encodeURIComponent(scriptlets);
|
|
|
|
return this.parts.join('');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
})();
|
2019-07-05 16:10:59 +02:00
|
|
|
|
2019-07-05 18:33:14 +02:00
|
|
|
const normalizeRawFilter = function(rawFilter) {
|
|
|
|
let rawToken = rawFilter.slice(4, -1);
|
|
|
|
let rawEnd = rawToken.length;
|
|
|
|
let end = rawToken.indexOf(',');
|
2019-07-05 16:10:59 +02:00
|
|
|
if ( end === -1 ) {
|
|
|
|
end = rawEnd;
|
|
|
|
}
|
2019-07-05 18:33:14 +02:00
|
|
|
let token = rawToken.slice(0, end).trim();
|
2019-07-05 16:10:59 +02:00
|
|
|
let normalized = token.endsWith('.js') ? token.slice(0, -3) : token;
|
|
|
|
let beg = end + 1;
|
|
|
|
while ( beg < rawEnd ) {
|
2019-07-05 18:33:14 +02:00
|
|
|
end = rawToken.indexOf(',', beg);
|
2019-07-05 16:10:59 +02:00
|
|
|
if ( end === -1 ) { end = rawEnd; }
|
2019-07-05 18:33:14 +02:00
|
|
|
normalized += ', ' + rawToken.slice(beg, end).trim();
|
2019-07-05 16:10:59 +02:00
|
|
|
beg = end + 1;
|
|
|
|
}
|
2019-07-05 18:33:14 +02:00
|
|
|
return `+js(${normalized})`;
|
2019-07-05 16:10:59 +02:00
|
|
|
};
|
|
|
|
|
2019-07-05 17:44:40 +02:00
|
|
|
const lookupScriptlet = function(rawToken, reng, toInject) {
|
|
|
|
if ( toInject.has(rawToken) ) { return; }
|
2017-12-28 19:49:02 +01:00
|
|
|
if ( scriptletCache.resetTime < reng.modifyTime ) {
|
|
|
|
scriptletCache.reset();
|
|
|
|
}
|
2019-07-05 17:44:40 +02:00
|
|
|
let content = scriptletCache.lookup(rawToken);
|
2017-12-28 19:49:02 +01:00
|
|
|
if ( content === undefined ) {
|
2019-07-05 17:44:40 +02:00
|
|
|
const pos = rawToken.indexOf(',');
|
2018-12-13 18:30:54 +01:00
|
|
|
let token, args;
|
2017-12-28 19:49:02 +01:00
|
|
|
if ( pos === -1 ) {
|
2019-07-05 17:44:40 +02:00
|
|
|
token = rawToken;
|
2017-12-28 19:49:02 +01:00
|
|
|
} else {
|
2019-07-05 17:44:40 +02:00
|
|
|
token = rawToken.slice(0, pos).trim();
|
|
|
|
args = rawToken.slice(pos + 1).trim();
|
2017-12-28 19:49:02 +01:00
|
|
|
}
|
2019-07-05 16:10:59 +02:00
|
|
|
content = reng.resourceContentFromName(
|
|
|
|
`${token}.js`,
|
|
|
|
'application/javascript'
|
|
|
|
);
|
2017-12-28 19:49:02 +01:00
|
|
|
if ( !content ) { return; }
|
|
|
|
if ( args ) {
|
|
|
|
content = patchScriptlet(content, args);
|
|
|
|
if ( !content ) { return; }
|
|
|
|
}
|
2018-04-09 23:49:35 +02:00
|
|
|
content =
|
|
|
|
'try {\n' +
|
|
|
|
content + '\n' +
|
|
|
|
'} catch ( e ) { }';
|
2019-07-05 17:44:40 +02:00
|
|
|
scriptletCache.add(rawToken, content);
|
2017-12-28 19:49:02 +01:00
|
|
|
}
|
2019-07-05 17:44:40 +02:00
|
|
|
toInject.set(rawToken, content);
|
2017-12-28 19:49:02 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
// Fill template placeholders. Return falsy if:
|
|
|
|
// - At least one argument contains anything else than /\w/ and `.`
|
|
|
|
|
2018-12-13 18:30:54 +01:00
|
|
|
const patchScriptlet = function(content, args) {
|
|
|
|
let i = 1;
|
2017-12-28 19:49:02 +01:00
|
|
|
while ( args !== '' ) {
|
2018-12-13 18:30:54 +01:00
|
|
|
let pos = args.indexOf(',');
|
2017-12-28 19:49:02 +01:00
|
|
|
if ( pos === -1 ) { pos = args.length; }
|
2018-12-13 18:30:54 +01:00
|
|
|
const arg = args.slice(0, pos).trim().replace(reEscapeScriptArg, '\\$&');
|
2019-07-03 20:33:06 +02:00
|
|
|
content = content.replace(`{{${i}}}`, arg);
|
2017-12-28 19:49:02 +01:00
|
|
|
args = args.slice(pos + 1).trim();
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
return content;
|
|
|
|
};
|
|
|
|
|
2018-12-13 18:30:54 +01:00
|
|
|
const logOne = function(isException, token, details) {
|
|
|
|
µBlock.filteringContext
|
|
|
|
.duplicate()
|
|
|
|
.fromTabId(details.tabId)
|
|
|
|
.setRealm('cosmetic')
|
|
|
|
.setType('dom')
|
|
|
|
.setURL(details.url)
|
|
|
|
.setDocOriginFromURL(details.url)
|
|
|
|
.setFilter({
|
2017-12-28 19:49:02 +01:00
|
|
|
source: 'cosmetic',
|
2019-07-03 20:33:06 +02:00
|
|
|
raw: (isException ? '#@#' : '##') + `+js(${token})`
|
2018-12-13 18:30:54 +01:00
|
|
|
})
|
|
|
|
.toLogger();
|
2017-12-28 19:49:02 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
api.reset = function() {
|
|
|
|
scriptletDB.clear();
|
|
|
|
duplicates.clear();
|
2017-12-29 19:31:37 +01:00
|
|
|
acceptedCount = 0;
|
|
|
|
discardedCount = 0;
|
2017-12-28 19:49:02 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
api.freeze = function() {
|
|
|
|
duplicates.clear();
|
2019-05-14 14:52:34 +02:00
|
|
|
scriptletDB.collectGarbage();
|
2017-12-28 19:49:02 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
api.compile = function(parsed, writer) {
|
|
|
|
// 1001 = scriptlet injection
|
|
|
|
writer.select(1001);
|
|
|
|
|
|
|
|
// Only exception filters are allowed to be global.
|
2019-07-05 18:33:14 +02:00
|
|
|
const normalized = normalizeRawFilter(parsed.suffix);
|
2017-12-28 19:49:02 +01:00
|
|
|
|
|
|
|
if ( parsed.hostnames.length === 0 ) {
|
|
|
|
if ( parsed.exception ) {
|
2019-07-05 17:44:40 +02:00
|
|
|
writer.push([ 32, '', 1, normalized ]);
|
2017-12-28 19:49:02 +01:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// https://github.com/gorhill/uBlock/issues/3375
|
|
|
|
// Ignore instances of exception filter with negated hostnames,
|
|
|
|
// because there is no way to create an exception to an exception.
|
|
|
|
|
2018-09-09 14:10:09 +02:00
|
|
|
for ( let hn of parsed.hostnames ) {
|
2018-12-13 18:30:54 +01:00
|
|
|
const negated = hn.charCodeAt(0) === 0x7E /* '~' */;
|
2017-12-28 19:49:02 +01:00
|
|
|
if ( negated ) {
|
2018-09-09 14:10:09 +02:00
|
|
|
hn = hn.slice(1);
|
2017-12-28 19:49:02 +01:00
|
|
|
}
|
2019-05-14 14:52:34 +02:00
|
|
|
let kind = 0;
|
2017-12-28 19:49:02 +01:00
|
|
|
if ( parsed.exception ) {
|
|
|
|
if ( negated ) { continue; }
|
2019-05-14 14:52:34 +02:00
|
|
|
kind |= 1;
|
2017-12-28 19:49:02 +01:00
|
|
|
} else if ( negated ) {
|
2019-05-14 14:52:34 +02:00
|
|
|
kind |= 1;
|
2017-12-28 19:49:02 +01:00
|
|
|
}
|
2019-07-05 17:44:40 +02:00
|
|
|
writer.push([ 32, hn, kind, normalized ]);
|
2017-12-28 19:49:02 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// 01234567890123456789
|
2018-09-07 15:11:07 +02:00
|
|
|
// +js(token[, arg[, ...]])
|
|
|
|
// ^ ^
|
|
|
|
// 4 -1
|
2017-12-28 19:49:02 +01:00
|
|
|
|
|
|
|
api.fromCompiledContent = function(reader) {
|
|
|
|
// 1001 = scriptlet injection
|
|
|
|
reader.select(1001);
|
|
|
|
|
|
|
|
while ( reader.next() ) {
|
2017-12-29 19:31:37 +01:00
|
|
|
acceptedCount += 1;
|
2018-12-13 18:30:54 +01:00
|
|
|
const fingerprint = reader.fingerprint();
|
2017-12-29 19:31:37 +01:00
|
|
|
if ( duplicates.has(fingerprint) ) {
|
|
|
|
discardedCount += 1;
|
|
|
|
continue;
|
|
|
|
}
|
2017-12-28 19:49:02 +01:00
|
|
|
duplicates.add(fingerprint);
|
2018-12-13 18:30:54 +01:00
|
|
|
const args = reader.args();
|
2017-12-28 19:49:02 +01:00
|
|
|
if ( args.length < 4 ) { continue; }
|
2019-05-14 14:52:34 +02:00
|
|
|
scriptletDB.store(args[1], args[2], args[3].slice(4, -1));
|
2017-12-28 19:49:02 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
api.retrieve = function(request) {
|
|
|
|
if ( scriptletDB.size === 0 ) { return; }
|
|
|
|
if ( µb.hiddenSettings.ignoreScriptInjectFilters ) { return; }
|
|
|
|
|
2018-12-13 18:30:54 +01:00
|
|
|
const reng = µb.redirectEngine;
|
2017-12-28 19:49:02 +01:00
|
|
|
if ( !reng ) { return; }
|
|
|
|
|
2018-12-13 18:30:54 +01:00
|
|
|
const hostname = request.hostname;
|
2017-12-28 19:49:02 +01:00
|
|
|
|
|
|
|
// https://github.com/gorhill/uBlock/issues/2835
|
|
|
|
// Do not inject scriptlets if the site is under an `allow` rule.
|
|
|
|
if (
|
|
|
|
µb.userSettings.advancedUserEnabled &&
|
|
|
|
µb.sessionFirewall.evaluateCellZY(hostname, hostname, '*') === 2
|
|
|
|
) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-05-14 14:52:34 +02:00
|
|
|
const scriptlets = new Set();
|
|
|
|
const exceptions = exceptionsRegister;
|
2017-12-28 19:49:02 +01:00
|
|
|
|
2019-05-14 14:52:34 +02:00
|
|
|
scriptletDB.retrieve(
|
|
|
|
hostname,
|
|
|
|
[ scriptlets, exceptions ]
|
|
|
|
);
|
|
|
|
if ( request.entity !== '' ) {
|
|
|
|
scriptletDB.retrieve(
|
|
|
|
`${hostname.slice(0, -request.domain)}${request.entity}`,
|
|
|
|
[ scriptlets, exceptions ]
|
|
|
|
);
|
2017-12-28 19:49:02 +01:00
|
|
|
}
|
2019-05-14 14:52:34 +02:00
|
|
|
|
2019-07-05 16:10:59 +02:00
|
|
|
for ( const rawToken of scriptlets ) {
|
|
|
|
lookupScriptlet(rawToken, reng, scriptletsRegister);
|
2017-12-28 19:49:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( scriptletsRegister.size === 0 ) { return; }
|
|
|
|
|
2019-07-05 16:10:59 +02:00
|
|
|
// Return an array of scriptlets, and log results if needed.
|
2018-12-13 18:30:54 +01:00
|
|
|
const out = [];
|
|
|
|
const loggerEnabled = µb.logger.enabled;
|
2019-07-05 17:44:40 +02:00
|
|
|
for ( const [ rawToken, code ] of scriptletsRegister ) {
|
|
|
|
const isException = exceptions.has(rawToken);
|
2018-12-13 18:30:54 +01:00
|
|
|
if ( isException === false ) {
|
2019-05-14 14:52:34 +02:00
|
|
|
out.push(code);
|
2017-12-28 19:49:02 +01:00
|
|
|
}
|
2018-12-13 18:30:54 +01:00
|
|
|
if ( loggerEnabled ) {
|
2019-07-05 17:44:40 +02:00
|
|
|
logOne(isException, rawToken, request);
|
2017-12-28 19:49:02 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
scriptletsRegister.clear();
|
|
|
|
exceptionsRegister.clear();
|
|
|
|
|
|
|
|
if ( out.length === 0 ) { return; }
|
|
|
|
|
2019-07-03 20:33:06 +02:00
|
|
|
if ( µb.hiddenSettings.debugScriptlets ) {
|
2019-07-08 14:56:36 +02:00
|
|
|
out.unshift('debugger;');
|
2019-07-03 20:33:06 +02:00
|
|
|
}
|
|
|
|
|
2019-07-08 14:56:36 +02:00
|
|
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/156
|
|
|
|
// Provide a private Map() object available for use by all
|
|
|
|
// scriptlets.
|
|
|
|
out.unshift(
|
|
|
|
'(function() {',
|
|
|
|
'// >>>> start of private namespace',
|
|
|
|
'const uBOSafe = new Map();',
|
|
|
|
'',
|
|
|
|
);
|
|
|
|
out.push(
|
|
|
|
'',
|
|
|
|
'// <<<< end of private namespace',
|
|
|
|
'})();',
|
|
|
|
);
|
|
|
|
|
2017-12-28 19:49:02 +01:00
|
|
|
return out.join('\n');
|
|
|
|
};
|
|
|
|
|
2018-05-17 13:33:21 +02:00
|
|
|
api.injectNow = function(details) {
|
|
|
|
if ( typeof details.frameId !== 'number' ) { return; }
|
|
|
|
if ( µb.URI.isNetworkURI(details.url) === false ) { return; }
|
2018-12-13 18:30:54 +01:00
|
|
|
const request = {
|
2018-05-17 13:33:21 +02:00
|
|
|
tabId: details.tabId,
|
|
|
|
frameId: details.frameId,
|
|
|
|
url: details.url,
|
|
|
|
hostname: µb.URI.hostnameFromURI(details.url),
|
|
|
|
domain: undefined,
|
|
|
|
entity: undefined
|
|
|
|
};
|
2018-11-24 18:21:25 +01:00
|
|
|
request.domain = µb.URI.domainFromHostname(request.hostname);
|
2018-05-17 13:33:21 +02:00
|
|
|
request.entity = µb.URI.entityFromDomain(request.domain);
|
2018-12-13 18:30:54 +01:00
|
|
|
const scriptlets = µb.scriptletFilteringEngine.retrieve(request);
|
2018-05-17 13:33:21 +02:00
|
|
|
if ( scriptlets === undefined ) { return; }
|
2018-05-17 22:24:08 +02:00
|
|
|
let code = contentscriptCode.assemble(request.hostname, scriptlets);
|
2019-07-03 20:33:06 +02:00
|
|
|
if ( µb.hiddenSettings.debugScriptletInjector ) {
|
2018-05-20 12:49:12 +02:00
|
|
|
code = 'debugger;\n' + code;
|
|
|
|
}
|
2018-07-08 14:25:08 +02:00
|
|
|
vAPI.tabs.injectScript(
|
2018-05-17 13:33:21 +02:00
|
|
|
details.tabId,
|
|
|
|
{
|
2018-05-17 22:24:08 +02:00
|
|
|
code: code,
|
2018-05-17 13:33:21 +02:00
|
|
|
frameId: details.frameId,
|
2018-05-20 12:49:12 +02:00
|
|
|
matchAboutBlank: false,
|
2018-05-17 13:33:21 +02:00
|
|
|
runAt: 'document_start'
|
|
|
|
}
|
|
|
|
);
|
2017-12-28 19:49:02 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
api.toSelfie = function() {
|
|
|
|
return scriptletDB.toSelfie();
|
|
|
|
};
|
|
|
|
|
|
|
|
api.fromSelfie = function(selfie) {
|
2019-05-14 14:52:34 +02:00
|
|
|
scriptletDB = new µb.staticExtFilteringEngine.HostnameBasedDB(1, selfie);
|
2017-12-28 19:49:02 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
return api;
|
|
|
|
})();
|
|
|
|
|
|
|
|
/******************************************************************************/
|