diff --git a/platform/nodejs/main.js b/platform/nodejs/main.js
index 41a6f809d..6874bdf94 100644
--- a/platform/nodejs/main.js
+++ b/platform/nodejs/main.js
@@ -29,10 +29,10 @@ import './lib/punycode.js';
import './lib/publicsuffixlist/publicsuffixlist.js';
import globals from './js/globals.js';
+import snfe from './js/static-net-filtering.js';
import { FilteringContext } from './js/filtering-context.js';
import { LineIterator } from './js/text-iterators.js';
import { StaticFilteringParser } from './js/static-filtering-parser.js';
-import { staticNetFilteringEngine } from './js/static-net-filtering.js';
import {
CompiledListReader,
@@ -41,33 +41,31 @@ import {
/******************************************************************************/
-function compileList(rawText, writer) {
+function compileList(rawText, writer, options = {}) {
const lineIter = new LineIterator(rawText);
const parser = new StaticFilteringParser(true);
+ const events = Array.isArray(options.events) ? options.events : undefined;
- parser.setMaxTokenLength(staticNetFilteringEngine.MAX_TOKEN_LENGTH);
+ parser.setMaxTokenLength(snfe.MAX_TOKEN_LENGTH);
while ( lineIter.eot() === false ) {
let line = lineIter.next();
-
while ( line.endsWith(' \\') ) {
if ( lineIter.peek(4) !== ' ' ) { break; }
line = line.slice(0, -2).trim() + lineIter.next().trim();
}
parser.analyze(line);
-
if ( parser.shouldIgnore() ) { continue; }
if ( parser.category !== parser.CATStaticNetFilter ) { continue; }
if ( parser.patternHasUnicode() && parser.toASCII() === false ) {
continue;
}
- if ( staticNetFilteringEngine.compile(parser, writer) ) { continue; }
- if ( staticNetFilteringEngine.error !== undefined ) {
- console.info(JSON.stringify({
- realm: 'message',
+ if ( snfe.compile(parser, writer) ) { continue; }
+ if ( snfe.error !== undefined && events !== undefined ) {
+ options.events.push({
type: 'error',
- text: staticNetFilteringEngine.error
- }));
+ text: snfe.error
+ });
}
}
@@ -79,13 +77,13 @@ function applyList(name, raw) {
writer.properties.set('name', name);
const compiled = compileList(raw, writer);
const reader = new CompiledListReader(compiled);
- staticNetFilteringEngine.fromCompiled(reader);
+ snfe.fromCompiled(reader);
}
function enableWASM(path) {
return Promise.all([
globals.publicSuffixList.enableWASM(`${path}/lib/publicsuffixlist`),
- staticNetFilteringEngine.enableWASM(`${path}/js`),
+ snfe.enableWASM(`${path}/js`),
]);
}
@@ -94,35 +92,32 @@ function pslInit(raw) {
const require = createRequire(import.meta.url); // jshint ignore:line
raw = require('./data/effective_tld_names.json');
if ( typeof raw !== 'string' || raw.trim() === '' ) {
- console.info('Unable to populate public suffix list');
+ console.error('Unable to populate public suffix list');
return;
}
}
globals.publicSuffixList.parse(raw, globals.punycode.toASCII);
- console.info('Public suffix list populated');
}
-function restart(lists) {
+function restart(lists, options = {}) {
// Remove all filters
reset();
if ( Array.isArray(lists) && lists.length !== 0 ) {
// Populate filtering engine with filter lists
for ( const { name, raw } of lists ) {
- applyList(name, raw);
+ applyList(name, raw, options);
}
// Commit changes
- staticNetFilteringEngine.freeze();
- staticNetFilteringEngine.optimize();
+ snfe.freeze();
+ snfe.optimize();
}
- console.info('Static network filtering engine populated');
-
- return staticNetFilteringEngine;
+ return snfe;
}
function reset() {
- staticNetFilteringEngine.reset();
+ snfe.reset();
}
export {
diff --git a/platform/nodejs/test.js b/platform/nodejs/test.js
index b0f7966e8..c4735e1bc 100644
--- a/platform/nodejs/test.js
+++ b/platform/nodejs/test.js
@@ -51,7 +51,7 @@ function fetch(listName) {
}
*/
- pslInit();
+ await pslInit();
const snfe = await Promise.all([
fetch('easylist'),
diff --git a/src/background.html b/src/background.html
index 21429406f..9f085da94 100644
--- a/src/background.html
+++ b/src/background.html
@@ -5,37 +5,17 @@
uBlock Origin
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/js/assets.js b/src/js/assets.js
index d7e144e55..3394e8a82 100644
--- a/src/js/assets.js
+++ b/src/js/assets.js
@@ -23,7 +23,9 @@
/******************************************************************************/
-import µBlock from './background.js';
+import cacheStorage from './cachestorage.js';
+import logger from './logger.js';
+import µb from './background.js';
/******************************************************************************/
@@ -31,7 +33,7 @@ const reIsExternalPath = /^(?:[a-z-]+):\/\//;
const reIsUserAsset = /^user-/;
const errorCantConnectTo = vAPI.i18n('errorCantConnectTo');
-const api = {};
+const assets = {};
// A hint for various pieces of code to take measures if possible to save
// bandwidth of remote servers.
@@ -41,13 +43,13 @@ let remoteServerFriendly = false;
const observers = [];
-api.addObserver = function(observer) {
+assets.addObserver = function(observer) {
if ( observers.indexOf(observer) === -1 ) {
observers.push(observer);
}
};
-api.removeObserver = function(observer) {
+assets.removeObserver = function(observer) {
let pos;
while ( (pos = observers.indexOf(observer)) !== -1 ) {
observers.splice(pos, 1);
@@ -65,11 +67,11 @@ const fireNotification = function(topic, details) {
/******************************************************************************/
-api.fetch = function(url, options = {}) {
+assets.fetch = function(url, options = {}) {
return new Promise((resolve, reject) => {
// Start of executor
- const timeoutAfter = µBlock.hiddenSettings.assetFetchTimeout * 1000 || 30000;
+ const timeoutAfter = µb.hiddenSettings.assetFetchTimeout * 1000 || 30000;
const xhr = new XMLHttpRequest();
let contentLoaded = 0;
let timeoutTimer;
@@ -86,7 +88,7 @@ api.fetch = function(url, options = {}) {
};
const fail = function(details, msg) {
- µBlock.logger.writeOne({
+ logger.writeOne({
realm: 'message',
type: 'error',
text: msg,
@@ -154,7 +156,7 @@ api.fetch = function(url, options = {}) {
/******************************************************************************/
-api.fetchText = async function(url) {
+assets.fetchText = async function(url) {
const isExternal = reIsExternalPath.test(url);
let actualUrl = isExternal ? url : vAPI.getURL(url);
@@ -171,7 +173,7 @@ api.fetchText = async function(url) {
// servers.
if ( isExternal && remoteServerFriendly !== true ) {
const cacheBypassToken =
- µBlock.hiddenSettings.updateAssetBypassBrowserCache
+ µb.hiddenSettings.updateAssetBypassBrowserCache
? Math.floor(Date.now() / 1000) % 86413
: Math.floor(Date.now() / 3600000) % 13;
const queryValue = `_=${cacheBypassToken}`;
@@ -185,7 +187,7 @@ api.fetchText = async function(url) {
let details = { content: '' };
try {
- details = await api.fetch(actualUrl);
+ details = await assets.fetch(actualUrl);
// Consider an empty result to be an error
if ( stringIsNotEmpty(details.content) === false ) {
@@ -223,7 +225,7 @@ api.fetchText = async function(url) {
// https://github.com/gorhill/uBlock/issues/3331
// Support the seamless loading of sublists.
-api.fetchFilterList = async function(mainlistURL) {
+assets.fetchFilterList = async function(mainlistURL) {
const toParsedURL = url => {
try {
return new URL(url.trim());
@@ -265,7 +267,7 @@ api.fetchFilterList = async function(mainlistURL) {
}
if ( result instanceof Object === false ) { continue; }
const content = result.content;
- const slices = µBlock.preparseDirectives.split(content);
+ const slices = µb.preparseDirectives.split(content);
for ( let i = 0, n = slices.length - 1; i < n; i++ ) {
const slice = content.slice(slices[i+0], slices[i+1]);
if ( (i & 1) !== 0 ) {
@@ -288,7 +290,7 @@ api.fetchFilterList = async function(mainlistURL) {
out.push(
slice.slice(lastIndex, match.index + match[0].length),
`! >>>>>>>> ${subURL}\n`,
- api.fetchText(subURL),
+ assets.fetchText(subURL),
`! <<<<<<<< ${subURL}\n`
);
lastIndex = reInclude.lastIndex;
@@ -346,7 +348,7 @@ let assetSourceRegistryPromise,
const getAssetSourceRegistry = function() {
if ( assetSourceRegistryPromise === undefined ) {
- assetSourceRegistryPromise = µBlock.cacheStorage.get(
+ assetSourceRegistryPromise = cacheStorage.get(
'assetSourceRegistry'
).then(bin => {
if (
@@ -356,12 +358,12 @@ const getAssetSourceRegistry = function() {
assetSourceRegistry = bin.assetSourceRegistry;
return assetSourceRegistry;
}
- return api.fetchText(
- µBlock.assetsBootstrapLocation || 'assets/assets.json'
+ return assets.fetchText(
+ µb.assetsBootstrapLocation || 'assets/assets.json'
).then(details => {
return details.content !== ''
? details
- : api.fetchText('assets/assets.json');
+ : assets.fetchText('assets/assets.json');
}).then(details => {
updateAssetSourceRegistry(details.content, true);
return assetSourceRegistry;
@@ -418,7 +420,7 @@ const saveAssetSourceRegistry = (( ) => {
let timer;
const save = function() {
timer = undefined;
- µBlock.cacheStorage.set({ assetSourceRegistry });
+ cacheStorage.set({ assetSourceRegistry });
};
return function(lazily) {
if ( timer !== undefined ) {
@@ -464,13 +466,13 @@ const updateAssetSourceRegistry = function(json, silent) {
saveAssetSourceRegistry();
};
-api.registerAssetSource = async function(assetKey, details) {
+assets.registerAssetSource = async function(assetKey, details) {
await getAssetSourceRegistry();
registerAssetSource(assetKey, details);
saveAssetSourceRegistry(true);
};
-api.unregisterAssetSource = async function(assetKey) {
+assets.unregisterAssetSource = async function(assetKey) {
await getAssetSourceRegistry();
unregisterAssetSource(assetKey);
saveAssetSourceRegistry(true);
@@ -489,7 +491,7 @@ let assetCacheRegistry = {};
const getAssetCacheRegistry = function() {
if ( assetCacheRegistryPromise === undefined ) {
- assetCacheRegistryPromise = µBlock.cacheStorage.get(
+ assetCacheRegistryPromise = cacheStorage.get(
'assetCacheRegistry'
).then(bin => {
if (
@@ -523,7 +525,7 @@ const saveAssetCacheRegistry = (( ) => {
let timer;
const save = function() {
timer = undefined;
- µBlock.cacheStorage.set({ assetCacheRegistry });
+ cacheStorage.set({ assetCacheRegistry });
};
return function(lazily) {
if ( timer !== undefined ) { clearTimeout(timer); }
@@ -547,7 +549,7 @@ const assetCacheRead = async function(assetKey, updateReadTime = false) {
const [ , bin ] = await Promise.all([
getAssetCacheRegistry(),
- µBlock.cacheStorage.get(internalKey),
+ cacheStorage.get(internalKey),
]);
if (
bin instanceof Object === false ||
@@ -593,7 +595,7 @@ const assetCacheWrite = async function(assetKey, details) {
if ( typeof options.url === 'string' ) {
entry.remoteURL = options.url;
}
- µBlock.cacheStorage.set({
+ cacheStorage.set({
assetCacheRegistry,
[`cache/${assetKey}`]: content
});
@@ -623,8 +625,8 @@ const assetCacheRemove = async function(pattern) {
}
if ( removedContent.length !== 0 ) {
await Promise.all([
- µBlock.cacheStorage.remove(removedContent),
- µBlock.cacheStorage.set({ assetCacheRegistry }),
+ cacheStorage.remove(removedContent),
+ cacheStorage.set({ assetCacheRegistry }),
]);
}
for ( let i = 0; i < removedEntries.length; i++ ) {
@@ -658,7 +660,7 @@ const assetCacheMarkAsDirty = async function(pattern, exclude) {
mustSave = true;
}
if ( mustSave ) {
- µBlock.cacheStorage.set({ assetCacheRegistry });
+ cacheStorage.set({ assetCacheRegistry });
}
};
@@ -708,8 +710,8 @@ const saveUserAsset = function(assetKey, content) {
/******************************************************************************/
-api.get = async function(assetKey, options = {}) {
- if ( assetKey === µBlock.userFiltersPath ) {
+assets.get = async function(assetKey, options = {}) {
+ if ( assetKey === µb.userFiltersPath ) {
return readUserAsset(assetKey);
}
@@ -770,8 +772,8 @@ api.get = async function(assetKey, options = {}) {
continue;
}
const details = assetDetails.content === 'filters'
- ? await api.fetchFilterList(contentURL)
- : await api.fetchText(contentURL);
+ ? await assets.fetchFilterList(contentURL)
+ : await assets.fetchText(contentURL);
if ( details.content === '' ) { continue; }
if ( reIsExternalPath.test(contentURL) && options.dontCache !== true ) {
assetCacheWrite(assetKey, {
@@ -832,8 +834,8 @@ const getRemote = async function(assetKey) {
if ( reIsExternalPath.test(contentURL) === false ) { continue; }
const result = assetDetails.content === 'filters'
- ? await api.fetchFilterList(contentURL)
- : await api.fetchText(contentURL);
+ ? await assets.fetchFilterList(contentURL)
+ : await assets.fetchText(contentURL);
// Failure
if ( stringIsNotEmpty(result.content) === false ) {
@@ -861,7 +863,7 @@ const getRemote = async function(assetKey) {
/******************************************************************************/
-api.put = async function(assetKey, content) {
+assets.put = async function(assetKey, content) {
return reIsUserAsset.test(assetKey)
? await saveUserAsset(assetKey, content)
: await assetCacheWrite(assetKey, content);
@@ -869,7 +871,7 @@ api.put = async function(assetKey, content) {
/******************************************************************************/
-api.metadata = async function() {
+assets.metadata = async function() {
await Promise.all([
getAssetSourceRegistry(),
getAssetCacheRegistry(),
@@ -888,7 +890,7 @@ api.metadata = async function() {
assetEntry.isDefault =
assetEntry.off === undefined ||
assetEntry.off === true &&
- µBlock.listMatchesEnvironment(assetEntry);
+ µb.listMatchesEnvironment(assetEntry);
}
if ( cacheEntry ) {
assetEntry.cached = true;
@@ -911,13 +913,13 @@ api.metadata = async function() {
/******************************************************************************/
-api.purge = assetCacheMarkAsDirty;
+assets.purge = assetCacheMarkAsDirty;
-api.remove = function(pattern) {
+assets.remove = function(pattern) {
return assetCacheRemove(pattern);
};
-api.rmrf = function() {
+assets.rmrf = function() {
return assetCacheRemove(/./);
};
@@ -1014,7 +1016,7 @@ const updateDone = function() {
fireNotification('after-assets-updated', { assetKeys: assetKeys });
};
-api.updateStart = function(details) {
+assets.updateStart = function(details) {
const oldUpdateDelay = updaterAssetDelay;
const newUpdateDelay = typeof details.delay === 'number'
? details.delay
@@ -1031,7 +1033,7 @@ api.updateStart = function(details) {
updateFirst();
};
-api.updateStop = function() {
+assets.updateStop = function() {
if ( updaterTimer ) {
clearTimeout(updaterTimer);
updaterTimer = undefined;
@@ -1041,15 +1043,13 @@ api.updateStop = function() {
}
};
-api.isUpdating = function() {
+assets.isUpdating = function() {
return updaterStatus === 'updating' &&
- updaterAssetDelay <= µBlock.hiddenSettings.manualUpdateAssetFetchPeriod;
+ updaterAssetDelay <= µb.hiddenSettings.manualUpdateAssetFetchPeriod;
};
/******************************************************************************/
-// Export
-
-µBlock.assets = api;
+export default assets;
/******************************************************************************/
diff --git a/src/js/background.js b/src/js/background.js
index b6794f5ac..347324b4d 100644
--- a/src/js/background.js
+++ b/src/js/background.js
@@ -24,6 +24,8 @@
/******************************************************************************/
import globals from './globals.js';
+import logger from './logger.js';
+import { FilteringContext } from './filtering-context.js';
import {
domainFromHostname,
@@ -31,11 +33,6 @@ import {
originFromURI,
} from './uri-utils.js';
-import { FilteringContext } from './filtering-context.js';
-import { CompiledListWriter } from './static-filtering-io.js';
-import { StaticFilteringParser } from './static-filtering-parser.js';
-import { staticNetFilteringEngine } from './static-net-filtering.js';
-
/******************************************************************************/
// Not all platforms may have properly declared vAPI.webextFlavor.
@@ -333,7 +330,6 @@ const µBlock = { // jshint ignore:line
if ( this.tabDomain === undefined ) {
void this.getTabDomain();
}
- const logger = µBlock.logger;
const filters = this.filter;
// Many filters may have been applied to the current context
if ( Array.isArray(filters) === false ) {
@@ -347,9 +343,6 @@ const µBlock = { // jshint ignore:line
};
µBlock.filteringContext = new µBlock.FilteringContext();
-µBlock.CompiledListWriter = CompiledListWriter;
-µBlock.StaticFilteringParser = StaticFilteringParser;
-µBlock.staticNetFilteringEngine = staticNetFilteringEngine;
globals.µBlock = µBlock;
diff --git a/src/js/cachestorage.js b/src/js/cachestorage.js
index 85cd9c0ac..2c2e60957 100644
--- a/src/js/cachestorage.js
+++ b/src/js/cachestorage.js
@@ -25,7 +25,8 @@
/******************************************************************************/
-import µBlock from './background.js';
+import lz4Codec from './lz4.js';
+import µb from './background.js';
/******************************************************************************/
@@ -54,431 +55,434 @@ import µBlock from './background.js';
// https://github.com/uBlockOrigin/uBlock-issues/issues/409
// Allow forcing the use of webext storage on Firefox.
-µBlock.cacheStorage = (function() {
+const STORAGE_NAME = 'uBlock0CacheStorage';
- const STORAGE_NAME = 'uBlock0CacheStorage';
+// Default to webext storage.
+const storageLocal = webext.storage.local;
- // Default to webext storage.
- const localStorage = webext.storage.local;
- const api = {
- name: 'browser.storage.local',
- get: localStorage.get,
- set: localStorage.set,
- remove: localStorage.remove,
- clear: localStorage.clear,
- getBytesInUse: localStorage.getBytesInUse,
- select: function(selectedBackend) {
- let actualBackend = selectedBackend;
- if ( actualBackend === undefined || actualBackend === 'unset' ) {
- actualBackend = vAPI.webextFlavor.soup.has('firefox')
- ? 'indexedDB'
- : 'browser.storage.local';
- }
- if ( actualBackend === 'indexedDB' ) {
- return selectIDB().then(success => {
- if ( success || selectedBackend === 'indexedDB' ) {
- clearWebext();
- return 'indexedDB';
- }
- clearIDB();
- return 'browser.storage.local';
- });
- }
- if ( actualBackend === 'browser.storage.local' ) {
+const cacheStorage = {
+ name: 'browser.storage.local',
+ get: storageLocal.get.bind(storageLocal),
+ set: storageLocal.set.bind(storageLocal),
+ remove: storageLocal.remove.bind(storageLocal),
+ clear: storageLocal.clear.bind(storageLocal),
+ // Not all platforms support getBytesInUse
+ getBytesInUse: storageLocal.getBytesInUse
+ ? storageLocal.getBytesInUse.bind(storageLocal)
+ : undefined,
+ select: function(selectedBackend) {
+ let actualBackend = selectedBackend;
+ if ( actualBackend === undefined || actualBackend === 'unset' ) {
+ actualBackend = vAPI.webextFlavor.soup.has('firefox')
+ ? 'indexedDB'
+ : 'browser.storage.local';
+ }
+ if ( actualBackend === 'indexedDB' ) {
+ return selectIDB().then(success => {
+ if ( success || selectedBackend === 'indexedDB' ) {
+ clearWebext();
+ return 'indexedDB';
+ }
clearIDB();
- }
- return Promise.resolve('browser.storage.local');
-
- },
- error: undefined
+ return 'browser.storage.local';
+ });
+ }
+ if ( actualBackend === 'browser.storage.local' ) {
+ clearIDB();
+ }
+ return Promise.resolve('browser.storage.local');
+
+ },
+ error: undefined
+};
+
+// Reassign API entries to that of indexedDB-based ones
+const selectIDB = async function() {
+ let db;
+ let dbPromise;
+ let dbTimer;
+
+ const noopfn = function () {
};
- // Reassign API entries to that of indexedDB-based ones
- const selectIDB = async function() {
- let db;
- let dbPromise;
- let dbTimer;
+ const disconnect = function() {
+ if ( dbTimer !== undefined ) {
+ clearTimeout(dbTimer);
+ dbTimer = undefined;
+ }
+ if ( db instanceof IDBDatabase ) {
+ db.close();
+ db = undefined;
+ }
+ };
- const noopfn = function () {
- };
-
- const disconnect = function() {
- if ( dbTimer !== undefined ) {
- clearTimeout(dbTimer);
+ const keepAlive = function() {
+ if ( dbTimer !== undefined ) {
+ clearTimeout(dbTimer);
+ }
+ dbTimer = vAPI.setTimeout(
+ ( ) => {
dbTimer = undefined;
- }
- if ( db instanceof IDBDatabase ) {
- db.close();
- db = undefined;
- }
- };
+ disconnect();
+ },
+ Math.max(
+ µb.hiddenSettings.autoUpdateAssetFetchPeriod * 2 * 1000,
+ 180000
+ )
+ );
+ };
- const keepAlive = function() {
- if ( dbTimer !== undefined ) {
- clearTimeout(dbTimer);
- }
- dbTimer = vAPI.setTimeout(
- ( ) => {
- dbTimer = undefined;
- disconnect();
- },
- Math.max(
- µBlock.hiddenSettings.autoUpdateAssetFetchPeriod * 2 * 1000,
- 180000
- )
- );
- };
+ // https://github.com/gorhill/uBlock/issues/3156
+ // I have observed that no event was fired in Tor Browser 7.0.7 +
+ // medium security level after the request to open the database was
+ // created. When this occurs, I have also observed that the `error`
+ // property was already set, so this means uBO can detect here whether
+ // the database can be opened successfully. A try-catch block is
+ // necessary when reading the `error` property because we are not
+ // allowed to read this propery outside of event handlers in newer
+ // implementation of IDBRequest (my understanding).
- // https://github.com/gorhill/uBlock/issues/3156
- // I have observed that no event was fired in Tor Browser 7.0.7 +
- // medium security level after the request to open the database was
- // created. When this occurs, I have also observed that the `error`
- // property was already set, so this means uBO can detect here whether
- // the database can be opened successfully. A try-catch block is
- // necessary when reading the `error` property because we are not
- // allowed to read this propery outside of event handlers in newer
- // implementation of IDBRequest (my understanding).
-
- const getDb = function() {
- keepAlive();
- if ( db !== undefined ) {
- return Promise.resolve(db);
- }
- if ( dbPromise !== undefined ) {
- return dbPromise;
- }
- dbPromise = new Promise(resolve => {
- let req;
- try {
- req = indexedDB.open(STORAGE_NAME, 1);
- if ( req.error ) {
- console.log(req.error);
- req = undefined;
- }
- } catch(ex) {
- }
- if ( req === undefined ) {
- db = null;
- dbPromise = undefined;
- return resolve(null);
- }
- req.onupgradeneeded = function(ev) {
- if ( ev.oldVersion === 1 ) { return; }
- try {
- const db = ev.target.result;
- db.createObjectStore(STORAGE_NAME, { keyPath: 'key' });
- } catch(ex) {
- req.onerror();
- }
- };
- req.onsuccess = function(ev) {
- if ( resolve === undefined ) { return; }
- req = undefined;
- db = ev.target.result;
- dbPromise = undefined;
- resolve(db);
- resolve = undefined;
- };
- req.onerror = req.onblocked = function() {
- if ( resolve === undefined ) { return; }
- req = undefined;
- console.log(this.error);
- db = null;
- dbPromise = undefined;
- resolve(null);
- resolve = undefined;
- };
- setTimeout(( ) => {
- if ( resolve === undefined ) { return; }
- db = null;
- dbPromise = undefined;
- resolve(null);
- resolve = undefined;
- }, 5000);
- });
+ const getDb = function() {
+ keepAlive();
+ if ( db !== undefined ) {
+ return Promise.resolve(db);
+ }
+ if ( dbPromise !== undefined ) {
return dbPromise;
- };
-
- const fromBlob = function(data) {
- if ( data instanceof Blob === false ) {
- return Promise.resolve(data);
- }
- return new Promise(resolve => {
- const blobReader = new FileReader();
- blobReader.onloadend = ev => {
- resolve(new Uint8Array(ev.target.result));
- };
- blobReader.readAsArrayBuffer(data);
- });
- };
-
- const toBlob = function(data) {
- const value = data instanceof Uint8Array
- ? new Blob([ data ])
- : data;
- return Promise.resolve(value);
- };
-
- const compress = function(store, key, data) {
- return µBlock.lz4Codec.encode(data, toBlob).then(value => {
- store.push({ key, value });
- });
- };
-
- const decompress = function(store, key, data) {
- return µBlock.lz4Codec.decode(data, fromBlob).then(data => {
- store[key] = data;
- });
- };
-
- const getFromDb = async function(keys, keyvalStore, callback) {
- if ( typeof callback !== 'function' ) { return; }
- if ( keys.length === 0 ) { return callback(keyvalStore); }
- const promises = [];
- const gotOne = function() {
- if ( typeof this.result !== 'object' ) { return; }
- const { key, value } = this.result;
- keyvalStore[key] = value;
- if ( value instanceof Blob === false ) { return; }
- promises.push(decompress(keyvalStore, key, value));
- };
+ }
+ dbPromise = new Promise(resolve => {
+ let req;
try {
- const db = await getDb();
- if ( !db ) { return callback(); }
- const transaction = db.transaction(STORAGE_NAME, 'readonly');
- transaction.oncomplete =
- transaction.onerror =
- transaction.onabort = ( ) => {
- Promise.all(promises).then(( ) => {
- callback(keyvalStore);
- });
- };
- const table = transaction.objectStore(STORAGE_NAME);
- for ( const key of keys ) {
- const req = table.get(key);
- req.onsuccess = gotOne;
- req.onerror = noopfn;
+ req = indexedDB.open(STORAGE_NAME, 1);
+ if ( req.error ) {
+ console.log(req.error);
+ req = undefined;
}
+ } catch(ex) {
}
- catch(reason) {
- console.info(`cacheStorage.getFromDb() failed: ${reason}`);
- callback();
+ if ( req === undefined ) {
+ db = null;
+ dbPromise = undefined;
+ return resolve(null);
}
- };
+ req.onupgradeneeded = function(ev) {
+ if ( ev.oldVersion === 1 ) { return; }
+ try {
+ const db = ev.target.result;
+ db.createObjectStore(STORAGE_NAME, { keyPath: 'key' });
+ } catch(ex) {
+ req.onerror();
+ }
+ };
+ req.onsuccess = function(ev) {
+ if ( resolve === undefined ) { return; }
+ req = undefined;
+ db = ev.target.result;
+ dbPromise = undefined;
+ resolve(db);
+ resolve = undefined;
+ };
+ req.onerror = req.onblocked = function() {
+ if ( resolve === undefined ) { return; }
+ req = undefined;
+ console.log(this.error);
+ db = null;
+ dbPromise = undefined;
+ resolve(null);
+ resolve = undefined;
+ };
+ setTimeout(( ) => {
+ if ( resolve === undefined ) { return; }
+ db = null;
+ dbPromise = undefined;
+ resolve(null);
+ resolve = undefined;
+ }, 5000);
+ });
+ return dbPromise;
+ };
- const visitAllFromDb = async function(visitFn) {
+ const fromBlob = function(data) {
+ if ( data instanceof Blob === false ) {
+ return Promise.resolve(data);
+ }
+ return new Promise(resolve => {
+ const blobReader = new FileReader();
+ blobReader.onloadend = ev => {
+ resolve(new Uint8Array(ev.target.result));
+ };
+ blobReader.readAsArrayBuffer(data);
+ });
+ };
+
+ const toBlob = function(data) {
+ const value = data instanceof Uint8Array
+ ? new Blob([ data ])
+ : data;
+ return Promise.resolve(value);
+ };
+
+ const compress = function(store, key, data) {
+ return lz4Codec.encode(data, toBlob).then(value => {
+ store.push({ key, value });
+ });
+ };
+
+ const decompress = function(store, key, data) {
+ return lz4Codec.decode(data, fromBlob).then(data => {
+ store[key] = data;
+ });
+ };
+
+ const getFromDb = async function(keys, keyvalStore, callback) {
+ if ( typeof callback !== 'function' ) { return; }
+ if ( keys.length === 0 ) { return callback(keyvalStore); }
+ const promises = [];
+ const gotOne = function() {
+ if ( typeof this.result !== 'object' ) { return; }
+ const { key, value } = this.result;
+ keyvalStore[key] = value;
+ if ( value instanceof Blob === false ) { return; }
+ promises.push(decompress(keyvalStore, key, value));
+ };
+ try {
const db = await getDb();
- if ( !db ) { return visitFn(); }
+ if ( !db ) { return callback(); }
const transaction = db.transaction(STORAGE_NAME, 'readonly');
transaction.oncomplete =
transaction.onerror =
- transaction.onabort = ( ) => visitFn();
+ transaction.onabort = ( ) => {
+ Promise.all(promises).then(( ) => {
+ callback(keyvalStore);
+ });
+ };
const table = transaction.objectStore(STORAGE_NAME);
- const req = table.openCursor();
- req.onsuccess = function(ev) {
- let cursor = ev.target && ev.target.result;
- if ( !cursor ) { return; }
- let entry = cursor.value;
- visitFn(entry);
- cursor.continue();
- };
- };
-
- const getAllFromDb = function(callback) {
- if ( typeof callback !== 'function' ) { return; }
- const promises = [];
- const keyvalStore = {};
- visitAllFromDb(entry => {
- if ( entry === undefined ) {
- Promise.all(promises).then(( ) => {
- callback(keyvalStore);
- });
- return;
- }
- const { key, value } = entry;
- keyvalStore[key] = value;
- if ( entry.value instanceof Blob === false ) { return; }
- promises.push(decompress(keyvalStore, key, value));
- }).catch(reason => {
- console.info(`cacheStorage.getAllFromDb() failed: ${reason}`);
- callback();
- });
- };
-
- // https://github.com/uBlockOrigin/uBlock-issues/issues/141
- // Mind that IDBDatabase.transaction() and IDBObjectStore.put()
- // can throw:
- // https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/transaction
- // https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/put
-
- const putToDb = async function(keyvalStore, callback) {
- if ( typeof callback !== 'function' ) {
- callback = noopfn;
- }
- const keys = Object.keys(keyvalStore);
- if ( keys.length === 0 ) { return callback(); }
- const promises = [ getDb() ];
- const entries = [];
- const dontCompress =
- µBlock.hiddenSettings.cacheStorageCompression !== true;
for ( const key of keys ) {
- const value = keyvalStore[key];
- const isString = typeof value === 'string';
- if ( isString === false || dontCompress ) {
- entries.push({ key, value });
- continue;
- }
- promises.push(compress(entries, key, value));
- }
- const finish = ( ) => {
- if ( callback === undefined ) { return; }
- let cb = callback;
- callback = undefined;
- cb();
- };
- try {
- const results = await Promise.all(promises);
- const db = results[0];
- if ( !db ) { return callback(); }
- const transaction = db.transaction(
- STORAGE_NAME,
- 'readwrite'
- );
- transaction.oncomplete =
- transaction.onerror =
- transaction.onabort = finish;
- const table = transaction.objectStore(STORAGE_NAME);
- for ( const entry of entries ) {
- table.put(entry);
- }
- } catch (ex) {
- finish();
- }
- };
-
- const deleteFromDb = async function(input, callback) {
- if ( typeof callback !== 'function' ) {
- callback = noopfn;
- }
- const keys = Array.isArray(input) ? input.slice() : [ input ];
- if ( keys.length === 0 ) { return callback(); }
- const finish = ( ) => {
- if ( callback === undefined ) { return; }
- let cb = callback;
- callback = undefined;
- cb();
- };
- try {
- const db = await getDb();
- if ( !db ) { return callback(); }
- const transaction = db.transaction(STORAGE_NAME, 'readwrite');
- transaction.oncomplete =
- transaction.onerror =
- transaction.onabort = finish;
- const table = transaction.objectStore(STORAGE_NAME);
- for ( const key of keys ) {
- table.delete(key);
- }
- } catch (ex) {
- finish();
- }
- };
-
- const clearDb = async function(callback) {
- if ( typeof callback !== 'function' ) {
- callback = noopfn;
- }
- try {
- const db = await getDb();
- if ( !db ) { return callback(); }
- const transaction = db.transaction(STORAGE_NAME, 'readwrite');
- transaction.oncomplete =
- transaction.onerror =
- transaction.onabort = ( ) => {
- callback();
- };
- transaction.objectStore(STORAGE_NAME).clear();
- }
- catch(reason) {
- console.info(`cacheStorage.clearDb() failed: ${reason}`);
- callback();
- }
- };
-
- await getDb();
- if ( !db ) { return false; }
-
- api.name = 'indexedDB';
- api.get = function get(keys) {
- return new Promise(resolve => {
- if ( keys === null ) {
- return getAllFromDb(bin => resolve(bin));
- }
- let toRead, output = {};
- if ( typeof keys === 'string' ) {
- toRead = [ keys ];
- } else if ( Array.isArray(keys) ) {
- toRead = keys;
- } else /* if ( typeof keys === 'object' ) */ {
- toRead = Object.keys(keys);
- output = keys;
- }
- getFromDb(toRead, output, bin => resolve(bin));
- });
- };
- api.set = function set(keys) {
- return new Promise(resolve => {
- putToDb(keys, details => resolve(details));
- });
- };
- api.remove = function remove(keys) {
- return new Promise(resolve => {
- deleteFromDb(keys, ( ) => resolve());
- });
- };
- api.clear = function clear() {
- return new Promise(resolve => {
- clearDb(( ) => resolve());
- });
- };
- api.getBytesInUse = function getBytesInUse() {
- return Promise.resolve(0);
- };
- return true;
- };
-
- // https://github.com/uBlockOrigin/uBlock-issues/issues/328
- // Delete cache-related entries from webext storage.
- const clearWebext = async function() {
- const bin = await webext.storage.local.get('assetCacheRegistry');
- if (
- bin instanceof Object === false ||
- bin.assetCacheRegistry instanceof Object === false
- ) {
- return;
- }
- const toRemove = [
- 'assetCacheRegistry',
- 'assetSourceRegistry',
- 'resourcesSelfie',
- 'selfie'
- ];
- for ( const key in bin.assetCacheRegistry ) {
- if ( bin.assetCacheRegistry.hasOwnProperty(key) ) {
- toRemove.push('cache/' + key);
+ const req = table.get(key);
+ req.onsuccess = gotOne;
+ req.onerror = noopfn;
}
}
- webext.storage.local.remove(toRemove);
+ catch(reason) {
+ console.info(`cacheStorage.getFromDb() failed: ${reason}`);
+ callback();
+ }
};
- const clearIDB = function() {
+ const visitAllFromDb = async function(visitFn) {
+ const db = await getDb();
+ if ( !db ) { return visitFn(); }
+ const transaction = db.transaction(STORAGE_NAME, 'readonly');
+ transaction.oncomplete =
+ transaction.onerror =
+ transaction.onabort = ( ) => visitFn();
+ const table = transaction.objectStore(STORAGE_NAME);
+ const req = table.openCursor();
+ req.onsuccess = function(ev) {
+ let cursor = ev.target && ev.target.result;
+ if ( !cursor ) { return; }
+ let entry = cursor.value;
+ visitFn(entry);
+ cursor.continue();
+ };
+ };
+
+ const getAllFromDb = function(callback) {
+ if ( typeof callback !== 'function' ) { return; }
+ const promises = [];
+ const keyvalStore = {};
+ visitAllFromDb(entry => {
+ if ( entry === undefined ) {
+ Promise.all(promises).then(( ) => {
+ callback(keyvalStore);
+ });
+ return;
+ }
+ const { key, value } = entry;
+ keyvalStore[key] = value;
+ if ( entry.value instanceof Blob === false ) { return; }
+ promises.push(decompress(keyvalStore, key, value));
+ }).catch(reason => {
+ console.info(`cacheStorage.getAllFromDb() failed: ${reason}`);
+ callback();
+ });
+ };
+
+ // https://github.com/uBlockOrigin/uBlock-issues/issues/141
+ // Mind that IDBDatabase.transaction() and IDBObjectStore.put()
+ // can throw:
+ // https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/transaction
+ // https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/put
+
+ const putToDb = async function(keyvalStore, callback) {
+ if ( typeof callback !== 'function' ) {
+ callback = noopfn;
+ }
+ const keys = Object.keys(keyvalStore);
+ if ( keys.length === 0 ) { return callback(); }
+ const promises = [ getDb() ];
+ const entries = [];
+ const dontCompress =
+ µb.hiddenSettings.cacheStorageCompression !== true;
+ for ( const key of keys ) {
+ const value = keyvalStore[key];
+ const isString = typeof value === 'string';
+ if ( isString === false || dontCompress ) {
+ entries.push({ key, value });
+ continue;
+ }
+ promises.push(compress(entries, key, value));
+ }
+ const finish = ( ) => {
+ if ( callback === undefined ) { return; }
+ let cb = callback;
+ callback = undefined;
+ cb();
+ };
try {
- indexedDB.deleteDatabase(STORAGE_NAME);
- } catch(ex) {
+ const results = await Promise.all(promises);
+ const db = results[0];
+ if ( !db ) { return callback(); }
+ const transaction = db.transaction(
+ STORAGE_NAME,
+ 'readwrite'
+ );
+ transaction.oncomplete =
+ transaction.onerror =
+ transaction.onabort = finish;
+ const table = transaction.objectStore(STORAGE_NAME);
+ for ( const entry of entries ) {
+ table.put(entry);
+ }
+ } catch (ex) {
+ finish();
}
};
- return api;
-}());
+ const deleteFromDb = async function(input, callback) {
+ if ( typeof callback !== 'function' ) {
+ callback = noopfn;
+ }
+ const keys = Array.isArray(input) ? input.slice() : [ input ];
+ if ( keys.length === 0 ) { return callback(); }
+ const finish = ( ) => {
+ if ( callback === undefined ) { return; }
+ let cb = callback;
+ callback = undefined;
+ cb();
+ };
+ try {
+ const db = await getDb();
+ if ( !db ) { return callback(); }
+ const transaction = db.transaction(STORAGE_NAME, 'readwrite');
+ transaction.oncomplete =
+ transaction.onerror =
+ transaction.onabort = finish;
+ const table = transaction.objectStore(STORAGE_NAME);
+ for ( const key of keys ) {
+ table.delete(key);
+ }
+ } catch (ex) {
+ finish();
+ }
+ };
+
+ const clearDb = async function(callback) {
+ if ( typeof callback !== 'function' ) {
+ callback = noopfn;
+ }
+ try {
+ const db = await getDb();
+ if ( !db ) { return callback(); }
+ const transaction = db.transaction(STORAGE_NAME, 'readwrite');
+ transaction.oncomplete =
+ transaction.onerror =
+ transaction.onabort = ( ) => {
+ callback();
+ };
+ transaction.objectStore(STORAGE_NAME).clear();
+ }
+ catch(reason) {
+ console.info(`cacheStorage.clearDb() failed: ${reason}`);
+ callback();
+ }
+ };
+
+ await getDb();
+ if ( !db ) { return false; }
+
+ cacheStorage.name = 'indexedDB';
+ cacheStorage.get = function get(keys) {
+ return new Promise(resolve => {
+ if ( keys === null ) {
+ return getAllFromDb(bin => resolve(bin));
+ }
+ let toRead, output = {};
+ if ( typeof keys === 'string' ) {
+ toRead = [ keys ];
+ } else if ( Array.isArray(keys) ) {
+ toRead = keys;
+ } else /* if ( typeof keys === 'object' ) */ {
+ toRead = Object.keys(keys);
+ output = keys;
+ }
+ getFromDb(toRead, output, bin => resolve(bin));
+ });
+ };
+ cacheStorage.set = function set(keys) {
+ return new Promise(resolve => {
+ putToDb(keys, details => resolve(details));
+ });
+ };
+ cacheStorage.remove = function remove(keys) {
+ return new Promise(resolve => {
+ deleteFromDb(keys, ( ) => resolve());
+ });
+ };
+ cacheStorage.clear = function clear() {
+ return new Promise(resolve => {
+ clearDb(( ) => resolve());
+ });
+ };
+ cacheStorage.getBytesInUse = function getBytesInUse() {
+ return Promise.resolve(0);
+ };
+ return true;
+};
+
+// https://github.com/uBlockOrigin/uBlock-issues/issues/328
+// Delete cache-related entries from webext storage.
+const clearWebext = async function() {
+ const bin = await webext.storage.local.get('assetCacheRegistry');
+ if (
+ bin instanceof Object === false ||
+ bin.assetCacheRegistry instanceof Object === false
+ ) {
+ return;
+ }
+ const toRemove = [
+ 'assetCacheRegistry',
+ 'assetSourceRegistry',
+ 'resourcesSelfie',
+ 'selfie'
+ ];
+ for ( const key in bin.assetCacheRegistry ) {
+ if ( bin.assetCacheRegistry.hasOwnProperty(key) ) {
+ toRemove.push('cache/' + key);
+ }
+ }
+ webext.storage.local.remove(toRemove);
+};
+
+const clearIDB = function() {
+ try {
+ indexedDB.deleteDatabase(STORAGE_NAME);
+ } catch(ex) {
+ }
+};
+
+/******************************************************************************/
+
+export default cacheStorage;
/******************************************************************************/
diff --git a/src/js/commands.js b/src/js/commands.js
index 463e63c08..19583799a 100644
--- a/src/js/commands.js
+++ b/src/js/commands.js
@@ -24,24 +24,23 @@
/******************************************************************************/
import { hostnameFromURI } from './uri-utils.js';
-import µBlock from './background.js';
+import µb from './background.js';
/******************************************************************************/
-µBlock.canUseShortcuts = vAPI.commands instanceof Object;
+µb.canUseShortcuts = vAPI.commands instanceof Object;
// https://github.com/uBlockOrigin/uBlock-issues/issues/386
// Firefox 74 and above has complete shotcut assignment user interface.
-µBlock.canUpdateShortcuts =
- µBlock.canUseShortcuts &&
+µb.canUpdateShortcuts =
+ µb.canUseShortcuts &&
vAPI.webextFlavor.soup.has('firefox') &&
typeof vAPI.commands.update === 'function';
-if ( µBlock.canUpdateShortcuts ) {
+if ( µb.canUpdateShortcuts ) {
self.addEventListener(
'webextFlavor',
( ) => {
- const µb = µBlock;
µb.canUpdateShortcuts = vAPI.webextFlavor.major < 74;
if ( µb.canUpdateShortcuts === false ) { return; }
vAPI.storage.get('commandShortcuts').then(bin => {
@@ -65,7 +64,7 @@ if ( µBlock.canUpdateShortcuts ) {
// *****************************************************************************
// start of local namespace
-if ( µBlock.canUseShortcuts === false ) { return; }
+if ( µb.canUseShortcuts === false ) { return; }
const relaxBlockingMode = (( ) => {
const reloadTimers = new Map();
@@ -73,7 +72,6 @@ const relaxBlockingMode = (( ) => {
return function(tab) {
if ( tab instanceof Object === false || tab.id <= 0 ) { return; }
- const µb = µBlock;
const normalURL = µb.normalizeTabURL(tab.id, tab.url);
if ( µb.getNetFilteringSwitch(normalURL) === false ) { return; }
@@ -161,8 +159,6 @@ const relaxBlockingMode = (( ) => {
})();
vAPI.commands.onCommand.addListener(async command => {
- const µb = µBlock;
-
switch ( command ) {
case 'launch-element-picker':
case 'launch-element-zapper': {
diff --git a/src/js/console.js b/src/js/console.js
index f29d9f087..15e0129b7 100644
--- a/src/js/console.js
+++ b/src/js/console.js
@@ -21,15 +21,39 @@
'use strict';
-self.log = (function() {
- const noopFunc = function() {};
- const info = function(s) { console.log(`[uBO] ${s}`); };
- return {
- get verbosity( ) { return; },
- set verbosity(level) {
- this.info = console.info = level === 'info' ? info : noopFunc;
- },
- info: noopFunc,
- print: info,
+/******************************************************************************/
+
+function ubologSet(state = false) {
+ if ( state ) {
+ if ( ubolog.process instanceof Function ) {
+ ubolog.process();
+ }
+ ubolog = ubologDo;
+ } else {
+ ubolog = ubologIgnore;
+ }
+}
+
+function ubologDo(...args) {
+ console.info('[uBO]', ...args);
+}
+
+function ubologIgnore() {
+}
+
+let ubolog = (( ) => {
+ const pending = [];
+ const store = function(...args) {
+ pending.push(args);
};
+ store.process = function() {
+ for ( const args of pending ) {
+ ubologDo(...args);
+ }
+ };
+ return store;
})();
+
+/******************************************************************************/
+
+export { ubolog, ubologSet };
diff --git a/src/js/contextmenu.js b/src/js/contextmenu.js
index e664c3364..1c8acf520 100644
--- a/src/js/contextmenu.js
+++ b/src/js/contextmenu.js
@@ -23,11 +23,11 @@
/******************************************************************************/
-import µBlock from './background.js';
+import µb from './background.js';
/******************************************************************************/
-µBlock.contextMenu = (( ) => {
+const contextMenu = (( ) => {
/******************************************************************************/
@@ -61,8 +61,8 @@ const onBlockElement = function(details, tab) {
}
}
- µBlock.epickerArgs.mouse = true;
- µBlock.elementPickerExec(tab.id, 0, `${tagName}\t${src}`);
+ µb.epickerArgs.mouse = true;
+ µb.elementPickerExec(tab.id, 0, `${tagName}\t${src}`);
};
/******************************************************************************/
@@ -70,8 +70,8 @@ const onBlockElement = function(details, tab) {
const onBlockElementInFrame = function(details, tab) {
if ( tab === undefined ) { return; }
if ( /^https?:\/\//.test(details.frameUrl) === false ) { return; }
- µBlock.epickerArgs.mouse = false;
- µBlock.elementPickerExec(tab.id, details.frameId);
+ µb.epickerArgs.mouse = false;
+ µb.elementPickerExec(tab.id, details.frameId);
};
/******************************************************************************/
@@ -87,7 +87,7 @@ const onSubscribeToList = function(details) {
const url = parsedURL.searchParams.get('location');
if ( url === null ) { return; }
const title = parsedURL.searchParams.get('title') || '?';
- const hash = µBlock.selectedFilterLists.indexOf(parsedURL) !== -1
+ const hash = µb.selectedFilterLists.indexOf(parsedURL) !== -1
? '#subscribed'
: '';
vAPI.tabs.open({
@@ -104,7 +104,7 @@ const onSubscribeToList = function(details) {
const onTemporarilyAllowLargeMediaElements = function(details, tab) {
if ( tab === undefined ) { return; }
- let pageStore = µBlock.pageStoreFromTabId(tab.id);
+ const pageStore = µb.pageStoreFromTabId(tab.id);
if ( pageStore === null ) { return; }
pageStore.temporarilyAllowLargeMediaElements(true);
};
@@ -166,8 +166,8 @@ let currentBits = 0;
const update = function(tabId = undefined) {
let newBits = 0;
- if ( µBlock.userSettings.contextMenuEnabled && tabId !== undefined ) {
- const pageStore = µBlock.pageStoreFromTabId(tabId);
+ if ( µb.userSettings.contextMenuEnabled && tabId !== undefined ) {
+ const pageStore = µb.pageStoreFromTabId(tabId);
if ( pageStore && pageStore.getNetFilteringSwitch() ) {
if ( pageStore.shouldApplySpecificCosmeticFilters(0) ) {
newBits |= 0b0001;
@@ -206,7 +206,7 @@ const update = function(tabId = undefined) {
// looked up after closing a window.
vAPI.contextMenu.onMustUpdate = async function(tabId = undefined) {
- if ( µBlock.userSettings.contextMenuEnabled === false ) {
+ if ( µb.userSettings.contextMenuEnabled === false ) {
return update();
}
if ( tabId !== undefined ) {
@@ -222,3 +222,9 @@ return { update: vAPI.contextMenu.onMustUpdate };
/******************************************************************************/
})();
+
+/******************************************************************************/
+
+export default contextMenu;
+
+/******************************************************************************/
diff --git a/src/js/cosmetic-filtering.js b/src/js/cosmetic-filtering.js
index 3601a7229..02b01bb64 100644
--- a/src/js/cosmetic-filtering.js
+++ b/src/js/cosmetic-filtering.js
@@ -23,17 +23,22 @@
/******************************************************************************/
+import logger from './logger.js';
+import µb from './background.js';
+
+import {
+ StaticExtFilteringHostnameDB,
+ StaticExtFilteringSessionDB,
+} from './static-ext-filtering-db.js';
+
import {
domainFromHostname,
entityFromDomain,
hostnameFromURI,
} from './uri-utils.js';
-import µBlock from './background.js';
-
/******************************************************************************/
-const µb = µBlock;
const cosmeticSurveyingMissCountMax =
parseInt(vAPI.localStorage.getItem('cosmeticSurveyingMissCountMax'), 10) ||
15;
@@ -205,10 +210,10 @@ const FilterContainer = function() {
this.selectorCacheTimer = null;
// specific filters
- this.specificFilters = new µb.staticExtFilteringEngine.HostnameBasedDB(2);
+ this.specificFilters = new StaticExtFilteringHostnameDB(2);
// temporary filters
- this.sessionFilterDB = new µb.staticExtFilteringEngine.SessionDB();
+ this.sessionFilterDB = new StaticExtFilteringSessionDB();
// low generic cosmetic filters, organized by id/class then simple/complex.
this.lowlyGeneric = Object.create(null);
@@ -390,7 +395,7 @@ FilterContainer.prototype.compileGenericHideSelector = function(
const { raw, compiled, pseudoclass } = parser.result;
if ( compiled === undefined ) {
const who = writer.properties.get('name') || '?';
- µb.logger.writeOne({
+ logger.writeOne({
realm: 'message',
type: 'error',
text: `Invalid generic cosmetic filter in ${who}: ${raw}`
@@ -437,7 +442,7 @@ FilterContainer.prototype.compileGenericHideSelector = function(
return this.compileSpecificSelector(parser, '', false, writer);
}
const who = writer.properties.get('name') || '?';
- µb.logger.writeOne({
+ logger.writeOne({
realm: 'message',
type: 'error',
text: `Invalid generic cosmetic filter in ${who}: ##${raw}`
@@ -493,7 +498,7 @@ FilterContainer.prototype.compileGenericUnhideSelector = function(
const { raw, compiled } = parser.result;
if ( compiled === undefined ) {
const who = writer.properties.get('name') || '?';
- µb.logger.writeOne({
+ logger.writeOne({
realm: 'message',
type: 'error',
text: `Invalid cosmetic filter in ${who}: #@#${raw}`
@@ -523,7 +528,7 @@ FilterContainer.prototype.compileSpecificSelector = function(
const { raw, compiled, exception } = parser.result;
if ( compiled === undefined ) {
const who = writer.properties.get('name') || '?';
- µb.logger.writeOne({
+ logger.writeOne({
realm: 'message',
type: 'error',
text: `Invalid cosmetic filter in ${who}: ##${raw}`
@@ -1169,8 +1174,8 @@ FilterContainer.prototype.benchmark = async function() {
/******************************************************************************/
-// Export
+const cosmeticFilteringEngine = new FilterContainer();
-µBlock.cosmeticFilteringEngine = new FilterContainer();
+export default cosmeticFilteringEngine;
/******************************************************************************/
diff --git a/src/js/dynamic-net-filtering.js b/src/js/dynamic-net-filtering.js
index 6f2833027..47e8d3935 100644
--- a/src/js/dynamic-net-filtering.js
+++ b/src/js/dynamic-net-filtering.js
@@ -28,9 +28,9 @@
import '../lib/punycode.js';
import globals from './globals.js';
+import µb from './background.js';
import { domainFromHostname } from './uri-utils.js';
import { LineIterator } from './text-iterators.js';
-import µBlock from './background.js';
/******************************************************************************/
@@ -266,7 +266,7 @@ const Matrix = class {
evaluateCellZ(srcHostname, desHostname, type) {
- µBlock.decomposeHostname(srcHostname, this.decomposedSource);
+ µb.decomposeHostname(srcHostname, this.decomposedSource);
this.type = type;
const bitOffset = typeBitOffsets[type];
for ( const shn of this.decomposedSource ) {
@@ -296,7 +296,7 @@ const Matrix = class {
// Precedence: from most specific to least specific
// Specific-destination, any party, any type
- µBlock.decomposeHostname(desHostname, this.decomposedDestination);
+ µb.decomposeHostname(desHostname, this.decomposedDestination);
for ( const dhn of this.decomposedDestination ) {
if ( dhn === '*' ) { break; }
this.y = dhn;
@@ -509,13 +509,13 @@ const Matrix = class {
async benchmark() {
- const requests = await µBlock.loadBenchmarkDataset();
+ const requests = await µb.loadBenchmarkDataset();
if ( Array.isArray(requests) === false || requests.length === 0 ) {
- log.print('No requests found to benchmark');
+ console.info('No requests found to benchmark');
return;
}
- log.print(`Benchmarking sessionFirewall.evaluateCellZY()...`);
- const fctxt = µBlock.filteringContext.duplicate();
+ console.info(`Benchmarking sessionFirewall.evaluateCellZY()...`);
+ const fctxt = µb.filteringContext.duplicate();
const t0 = self.performance.now();
for ( const request of requests ) {
fctxt.setURL(request.url);
@@ -529,8 +529,8 @@ const Matrix = class {
}
const t1 = self.performance.now();
const dur = t1 - t0;
- log.print(`Evaluated ${requests.length} requests in ${dur.toFixed(0)} ms`);
- log.print(`\tAverage: ${(dur / requests.length).toFixed(3)} ms per request`);
+ console.info(`Evaluated ${requests.length} requests in ${dur.toFixed(0)} ms`);
+ console.info(`\tAverage: ${(dur / requests.length).toFixed(3)} ms per request`);
}
};
@@ -544,11 +544,9 @@ Matrix.prototype.magicId = 1;
/******************************************************************************/
-// Export
+const sessionFirewall = new Matrix();
+const permanentFirewall = new Matrix();
-µBlock.Firewall = Matrix;
-
-µBlock.sessionFirewall = new µBlock.Firewall();
-µBlock.permanentFirewall = new µBlock.Firewall();
+export { permanentFirewall, sessionFirewall };
/******************************************************************************/
diff --git a/src/js/hnswitches.js b/src/js/hnswitches.js
index 9df8a7494..fdc08f243 100644
--- a/src/js/hnswitches.js
+++ b/src/js/hnswitches.js
@@ -28,8 +28,8 @@
import '../lib/punycode.js';
import globals from './globals.js';
+import µb from './background.js';
import { LineIterator } from './text-iterators.js';
-import µBlock from './background.js';
/******************************************************************************/
@@ -228,7 +228,7 @@ HnSwitches.prototype.evaluateZ = function(switchName, hostname) {
return false;
}
this.n = switchName;
- µBlock.decomposeHostname(hostname, this.decomposedSource);
+ µb.decomposeHostname(hostname, this.decomposedSource);
for ( const shn of this.decomposedSource ) {
let bits = this.switches.get(shn);
if ( bits !== undefined ) {
@@ -323,11 +323,9 @@ HnSwitches.prototype.removeFromRuleParts = function(parts) {
/******************************************************************************/
-// Export
+const sessionSwitches = new HnSwitches();
+const permanentSwitches = new HnSwitches();
-µBlock.HnSwitches = HnSwitches;
-
-µBlock.sessionSwitches = new HnSwitches();
-µBlock.permanentSwitches = new HnSwitches();
+export { permanentSwitches, sessionSwitches };
/******************************************************************************/
diff --git a/src/js/hntrie.js b/src/js/hntrie.js
index f18c13a90..abebf2d65 100644
--- a/src/js/hntrie.js
+++ b/src/js/hntrie.js
@@ -796,7 +796,7 @@ const getWasmModule = (( ) => {
).then(
WebAssembly.compileStreaming
).catch(reason => {
- log.info(reason);
+ console.info(reason);
});
return wasmModulePromise;
diff --git a/src/js/html-filtering.js b/src/js/html-filtering.js
index 52e9bb962..a563826fb 100644
--- a/src/js/html-filtering.js
+++ b/src/js/html-filtering.js
@@ -23,22 +23,28 @@
/******************************************************************************/
-import µBlock from './background.js';
+import logger from './logger.js';
+import µb from './background.js';
+import { sessionFirewall } from './dynamic-net-filtering.js';
+
+import {
+ StaticExtFilteringHostnameDB,
+ StaticExtFilteringSessionDB,
+} from './static-ext-filtering-db.js';
/******************************************************************************/
-const µb = µBlock;
const pselectors = new Map();
const duplicates = new Set();
-const filterDB = new µb.staticExtFilteringEngine.HostnameBasedDB(2);
-const sessionFilterDB = new µb.staticExtFilteringEngine.SessionDB();
+const filterDB = new StaticExtFilteringHostnameDB(2);
+const sessionFilterDB = new StaticExtFilteringSessionDB();
let acceptedCount = 0;
let discardedCount = 0;
let docRegister;
-const api = {
+const htmlFilteringEngine = {
get acceptedCount() {
return acceptedCount;
},
@@ -237,7 +243,7 @@ PSelector.prototype.operatorToTaskMap = new Map([
PSelector.prototype.invalid = false;
const logOne = function(details, exception, selector) {
- µBlock.filteringContext
+ µb.filteringContext
.duplicate()
.fromTabId(details.tabId)
.setRealm('extended')
@@ -263,7 +269,7 @@ const applyProceduralSelector = function(details, selector) {
node.remove();
modified = true;
}
- if ( modified && µb.logger.enabled ) {
+ if ( modified && logger.enabled ) {
logOne(details, 0, pselector.raw);
}
return modified;
@@ -276,13 +282,13 @@ const applyCSSSelector = function(details, selector) {
node.remove();
modified = true;
}
- if ( modified && µb.logger.enabled ) {
+ if ( modified && logger.enabled ) {
logOne(details, 0, selector);
}
return modified;
};
-api.reset = function() {
+htmlFilteringEngine.reset = function() {
filterDB.clear();
pselectors.clear();
duplicates.clear();
@@ -290,16 +296,16 @@ api.reset = function() {
discardedCount = 0;
};
-api.freeze = function() {
+htmlFilteringEngine.freeze = function() {
duplicates.clear();
filterDB.collectGarbage();
};
-api.compile = function(parser, writer) {
+htmlFilteringEngine.compile = function(parser, writer) {
const { raw, compiled, exception } = parser.result;
if ( compiled === undefined ) {
const who = writer.properties.get('name') || '?';
- µb.logger.writeOne({
+ logger.writeOne({
realm: 'message',
type: 'error',
text: `Invalid HTML filter in ${who}: ##${raw}`
@@ -325,14 +331,14 @@ api.compile = function(parser, writer) {
}
};
-api.compileTemporary = function(parser) {
+htmlFilteringEngine.compileTemporary = function(parser) {
return {
session: sessionFilterDB,
selector: parser.result.compiled,
};
};
-api.fromCompiledContent = function(reader) {
+htmlFilteringEngine.fromCompiledContent = function(reader) {
// Don't bother loading filters if stream filtering is not supported.
if ( µb.canFilterResponseData === false ) { return; }
@@ -351,11 +357,11 @@ api.fromCompiledContent = function(reader) {
}
};
-api.getSession = function() {
+htmlFilteringEngine.getSession = function() {
return sessionFilterDB;
};
-api.retrieve = function(details) {
+htmlFilteringEngine.retrieve = function(details) {
const hostname = details.hostname;
const plains = new Set();
@@ -384,7 +390,7 @@ api.retrieve = function(details) {
// Do not filter if the site is under an `allow` rule.
if (
µb.userSettings.advancedUserEnabled &&
- µb.sessionFirewall.evaluateCellZY(hostname, hostname, '*') === 2
+ sessionFirewall.evaluateCellZY(hostname, hostname, '*') === 2
) {
return;
}
@@ -413,7 +419,7 @@ api.retrieve = function(details) {
}
};
-api.apply = function(doc, details) {
+htmlFilteringEngine.apply = function(doc, details) {
docRegister = doc;
let modified = false;
for ( const selector of details.selectors.plains ) {
@@ -430,19 +436,17 @@ api.apply = function(doc, details) {
return modified;
};
-api.toSelfie = function() {
+htmlFilteringEngine.toSelfie = function() {
return filterDB.toSelfie();
};
-api.fromSelfie = function(selfie) {
+htmlFilteringEngine.fromSelfie = function(selfie) {
filterDB.fromSelfie(selfie);
pselectors.clear();
};
/******************************************************************************/
-// Export
-
-µBlock.htmlFilteringEngine = api;
+export default htmlFilteringEngine;
/******************************************************************************/
diff --git a/src/js/httpheader-filtering.js b/src/js/httpheader-filtering.js
index 19c6b40e7..3212bb660 100644
--- a/src/js/httpheader-filtering.js
+++ b/src/js/httpheader-filtering.js
@@ -23,15 +23,21 @@
/******************************************************************************/
+import logger from './logger.js';
+import µb from './background.js';
import { entityFromDomain } from './uri-utils.js';
-import µBlock from './background.js';
+import { sessionFirewall } from './dynamic-net-filtering.js';
+
+import {
+ StaticExtFilteringHostnameDB,
+ StaticExtFilteringSessionDB,
+} from './static-ext-filtering-db.js';
/******************************************************************************/
-const µb = µBlock;
const duplicates = new Set();
-const filterDB = new µb.staticExtFilteringEngine.HostnameBasedDB(1);
-const sessionFilterDB = new µb.staticExtFilteringEngine.SessionDB();
+const filterDB = new StaticExtFilteringHostnameDB(1);
+const sessionFilterDB = new StaticExtFilteringSessionDB();
const $headers = new Set();
const $exceptions = new Set();
@@ -62,7 +68,7 @@ const logOne = function(isException, token, fctxt) {
.toLogger();
};
-const api = {
+const httpheaderFilteringEngine = {
get acceptedCount() {
return acceptedCount;
},
@@ -71,19 +77,19 @@ const api = {
}
};
-api.reset = function() {
+httpheaderFilteringEngine.reset = function() {
filterDB.clear();
duplicates.clear();
acceptedCount = 0;
discardedCount = 0;
};
-api.freeze = function() {
+httpheaderFilteringEngine.freeze = function() {
duplicates.clear();
filterDB.collectGarbage();
};
-api.compile = function(parser, writer) {
+httpheaderFilteringEngine.compile = function(parser, writer) {
writer.select(µb.compiledHTTPHeaderSection);
const { compiled, exception } = parser.result;
@@ -117,7 +123,7 @@ api.compile = function(parser, writer) {
}
};
-api.compileTemporary = function(parser) {
+httpheaderFilteringEngine.compileTemporary = function(parser) {
return {
session: sessionFilterDB,
selector: parser.result.compiled.slice(15, -1),
@@ -129,7 +135,7 @@ api.compileTemporary = function(parser) {
// ^ ^
// 15 -1
-api.fromCompiledContent = function(reader) {
+httpheaderFilteringEngine.fromCompiledContent = function(reader) {
reader.select(µb.compiledHTTPHeaderSection);
while ( reader.next() ) {
@@ -146,11 +152,11 @@ api.fromCompiledContent = function(reader) {
}
};
-api.getSession = function() {
+httpheaderFilteringEngine.getSession = function() {
return sessionFilterDB;
};
-api.apply = function(fctxt, headers) {
+httpheaderFilteringEngine.apply = function(fctxt, headers) {
if ( filterDB.size === 0 ) { return; }
const hostname = fctxt.getHostname();
@@ -178,13 +184,12 @@ api.apply = function(fctxt, headers) {
// Do not filter response headers if the site is under an `allow` rule.
if (
µb.userSettings.advancedUserEnabled &&
- µb.sessionFirewall.evaluateCellZY(hostname, hostname, '*') === 2
+ sessionFirewall.evaluateCellZY(hostname, hostname, '*') === 2
) {
return;
}
const hasGlobalException = $exceptions.has('');
- const loggerEnabled = µb.logger.enabled;
let modified = false;
@@ -194,13 +199,13 @@ api.apply = function(fctxt, headers) {
if ( i === -1 ) { break; }
const isExcepted = hasGlobalException || $exceptions.has(name);
if ( isExcepted ) {
- if ( loggerEnabled ) {
+ if ( logger.enabled ) {
logOne(true, hasGlobalException ? '' : name, fctxt);
}
break;
}
headers.splice(i, 1);
- if ( loggerEnabled ) {
+ if ( logger.enabled ) {
logOne(false, name, fctxt);
}
modified = true;
@@ -210,18 +215,16 @@ api.apply = function(fctxt, headers) {
return modified;
};
-api.toSelfie = function() {
+httpheaderFilteringEngine.toSelfie = function() {
return filterDB.toSelfie();
};
-api.fromSelfie = function(selfie) {
+httpheaderFilteringEngine.fromSelfie = function(selfie) {
filterDB.fromSelfie(selfie);
};
/******************************************************************************/
-// Export
-
-µb.httpheaderFilteringEngine = api;
+export default httpheaderFilteringEngine;
/******************************************************************************/
diff --git a/src/js/logger.js b/src/js/logger.js
index eb417d306..53cdc3d1f 100644
--- a/src/js/logger.js
+++ b/src/js/logger.js
@@ -23,10 +23,6 @@
/******************************************************************************/
-import µBlock from './background.js';
-
-/******************************************************************************/
-
let buffer = null;
let lastReadTime = 0;
let writePtr = 0;
@@ -40,10 +36,10 @@ const janitor = ( ) => {
buffer !== null &&
lastReadTime < (Date.now() - logBufferObsoleteAfter)
) {
- api.enabled = false;
+ logger.enabled = false;
buffer = null;
writePtr = 0;
- api.ownerId = undefined;
+ logger.ownerId = undefined;
vAPI.messaging.broadcast({ what: 'loggerDisabled' });
}
if ( buffer !== null ) {
@@ -58,7 +54,7 @@ const boxEntry = function(details) {
return JSON.stringify(details);
};
-const api = {
+const logger = {
enabled: false,
ownerId: undefined,
writeOne: function(details) {
@@ -87,8 +83,6 @@ const api = {
/******************************************************************************/
-// Export
-
-µBlock.logger = api;
+export default logger;
/******************************************************************************/
diff --git a/src/js/lz4.js b/src/js/lz4.js
index 539fc8a94..0c91b2f76 100644
--- a/src/js/lz4.js
+++ b/src/js/lz4.js
@@ -25,7 +25,7 @@
/******************************************************************************/
-import µBlock from './background.js';
+import µb from './background.js';
/*******************************************************************************
@@ -46,7 +46,7 @@ let ttlTimer;
let ttlDelay = 60000;
const init = function() {
- ttlDelay = µBlock.hiddenSettings.autoUpdateAssetFetchPeriod * 1000 + 15000;
+ ttlDelay = µb.hiddenSettings.autoUpdateAssetFetchPeriod * 1000 + 15000;
if ( lz4CodecInstance === null ) {
return Promise.resolve(null);
}
@@ -55,7 +55,7 @@ const init = function() {
}
if ( pendingInitialization === undefined ) {
let flavor;
- if ( µBlock.hiddenSettings.disableWebAssembly === true ) {
+ if ( µb.hiddenSettings.disableWebAssembly === true ) {
flavor = 'js';
}
pendingInitialization = lz4BlockCodec.createInstance(flavor)
@@ -155,7 +155,7 @@ const decodeValue = function(inputArray) {
return s;
};
-µBlock.lz4Codec = {
+const lz4Codec = {
// Arguments:
// dataIn: must be a string
// Returns:
@@ -199,3 +199,7 @@ const decodeValue = function(inputArray) {
};
/******************************************************************************/
+
+export default lz4Codec;
+
+/******************************************************************************/
diff --git a/src/js/messaging.js b/src/js/messaging.js
index ab161940f..c14d746db 100644
--- a/src/js/messaging.js
+++ b/src/js/messaging.js
@@ -26,7 +26,30 @@
import '../lib/publicsuffixlist/publicsuffixlist.js';
import '../lib/punycode.js';
+import cacheStorage from './cachestorage.js';
+import cosmeticFilteringEngine from './cosmetic-filtering.js';
import globals from './globals.js';
+import logger from './logger.js';
+import lz4Codec from './lz4.js';
+import io from './assets.js';
+import scriptletFilteringEngine from './scriptlet-filtering.js';
+import staticExtFilteringEngine from './static-ext-filtering.js';
+import staticFilteringReverseLookup from './reverselookup.js';
+import staticNetFilteringEngine from './static-net-filtering.js';
+import µb from './background.js';
+import { redirectEngine } from './redirect-engine.js';
+import { StaticFilteringParser } from './static-filtering-parser.js';
+import { webRequest } from './traffic.js';
+
+import {
+ permanentFirewall,
+ sessionFirewall,
+} from './dynamic-net-filtering.js';
+
+import {
+ permanentSwitches,
+ sessionSwitches,
+} from './hnswitches.js';
import {
domainFromHostname,
@@ -36,8 +59,10 @@ import {
isNetworkURI,
} from './uri-utils.js';
-import { StaticFilteringParser } from './static-filtering-parser.js';
-import µBlock from './background.js';
+import {
+ permanentURLFiltering,
+ sessionURLFiltering,
+} from './url-net-filtering.js';
/******************************************************************************/
@@ -56,8 +81,6 @@ import µBlock from './background.js';
{
// >>>>> start of local scope
-const µb = µBlock;
-
const clickToLoad = function(request, sender) {
const { tabId, frameId } = sender;
if ( tabId === undefined || frameId === undefined ) { return false; }
@@ -81,7 +104,7 @@ const onMessage = function(request, sender, callback) {
switch ( request.what ) {
case 'getAssetContent':
// https://github.com/chrisaljoudi/uBlock/issues/417
- µb.assets.get(request.url, {
+ io.get(request.url, {
dontCache: true,
needSourceURL: true,
}).then(result => {
@@ -90,7 +113,7 @@ const onMessage = function(request, sender, callback) {
return;
case 'listsFromNetFilter':
- µb.staticFilteringReverseLookup.fromNetFilter(
+ staticFilteringReverseLookup.fromNetFilter(
request.rawFilter
).then(response => {
callback(response);
@@ -98,7 +121,7 @@ const onMessage = function(request, sender, callback) {
return;
case 'listsFromCosmeticFilter':
- µb.staticFilteringReverseLookup.fromCosmeticFilter(
+ staticFilteringReverseLookup.fromCosmeticFilter(
request
).then(response => {
callback(response);
@@ -115,9 +138,9 @@ const onMessage = function(request, sender, callback) {
case 'sfneBenchmark':
µb.loadBenchmarkDataset().then(requests => {
- µb.staticNetFilteringEngine.benchmark(
+ staticNetFilteringEngine.benchmark(
requests,
- { redirectEngine: µb.redirectEngine }
+ { redirectEngine }
).then(result => {
callback(result);
});
@@ -146,7 +169,7 @@ const onMessage = function(request, sender, callback) {
case 'forceUpdateAssets':
µb.scheduleAssetUpdater(0);
- µb.assets.updateStart({
+ io.updateStart({
delay: µb.hiddenSettings.manualUpdateAssetFetchPeriod
});
break;
@@ -241,8 +264,6 @@ vAPI.messaging.setup(onMessage);
{
// >>>>> start of local scope
-const µb = µBlock;
-
const createCounts = ( ) => {
return {
blocked: { any: 0, frame: 0, script: 0 },
@@ -291,7 +312,7 @@ const firewallRuleTypes = [
const getFirewallRules = function(src, out) {
const ruleset = out.firewallRules = {};
- const df = µb.sessionFirewall;
+ const df = sessionFirewall;
for ( const type of firewallRuleTypes ) {
const r = df.lookupRuleData('*', '*', type);
@@ -358,26 +379,26 @@ const popupDataFromTabId = function(tabId, tabTitle) {
r.contentLastModified = pageStore.contentLastModified;
getFirewallRules(rootHostname, r);
r.canElementPicker = isNetworkURI(r.rawURL);
- r.noPopups = µb.sessionSwitches.evaluateZ(
+ r.noPopups = sessionSwitches.evaluateZ(
'no-popups',
rootHostname
);
r.popupBlockedCount = pageStore.popupBlockedCount;
- r.noCosmeticFiltering = µb.sessionSwitches.evaluateZ(
+ r.noCosmeticFiltering = sessionSwitches.evaluateZ(
'no-cosmetic-filtering',
rootHostname
);
- r.noLargeMedia = µb.sessionSwitches.evaluateZ(
+ r.noLargeMedia = sessionSwitches.evaluateZ(
'no-large-media',
rootHostname
);
r.largeMediaCount = pageStore.largeMediaCount;
- r.noRemoteFonts = µb.sessionSwitches.evaluateZ(
+ r.noRemoteFonts = sessionSwitches.evaluateZ(
'no-remote-fonts',
rootHostname
);
r.remoteFontCount = pageStore.remoteFontCount;
- r.noScripting = µb.sessionSwitches.evaluateZ(
+ r.noScripting = sessionSwitches.evaluateZ(
'no-scripting',
rootHostname
);
@@ -386,14 +407,14 @@ const popupDataFromTabId = function(tabId, tabTitle) {
getFirewallRules(undefined, r);
}
- r.matrixIsDirty = µb.sessionFirewall.hasSameRules(
- µb.permanentFirewall,
+ r.matrixIsDirty = sessionFirewall.hasSameRules(
+ permanentFirewall,
rootHostname,
r.hostnameDict
) === false;
if ( r.matrixIsDirty === false ) {
- r.matrixIsDirty = µb.sessionSwitches.hasSameRules(
- µb.permanentSwitches,
+ r.matrixIsDirty = sessionSwitches.hasSameRules(
+ permanentSwitches,
rootHostname
) === false;
}
@@ -470,17 +491,17 @@ const onMessage = function(request, sender, callback) {
break;
case 'revertFirewallRules':
- µb.sessionFirewall.copyRules(
- µb.permanentFirewall,
+ sessionFirewall.copyRules(
+ permanentFirewall,
request.srcHostname,
request.desHostnames
);
- µb.sessionSwitches.copyRules(
- µb.permanentSwitches,
+ sessionSwitches.copyRules(
+ permanentSwitches,
request.srcHostname
);
// https://github.com/gorhill/uBlock/issues/188
- µb.cosmeticFilteringEngine.removeFromSelectorCache(
+ cosmeticFilteringEngine.removeFromSelectorCache(
request.srcHostname,
'net'
);
@@ -490,8 +511,8 @@ const onMessage = function(request, sender, callback) {
case 'saveFirewallRules':
if (
- µb.permanentFirewall.copyRules(
- µb.sessionFirewall,
+ permanentFirewall.copyRules(
+ sessionFirewall,
request.srcHostname,
request.desHostnames
)
@@ -499,8 +520,8 @@ const onMessage = function(request, sender, callback) {
µb.savePermanentFirewallRules();
}
if (
- µb.permanentSwitches.copyRules(
- µb.sessionSwitches,
+ permanentSwitches.copyRules(
+ sessionSwitches,
request.srcHostname
)
) {
@@ -556,8 +577,6 @@ vAPI.messaging.listen({
{
// >>>>> start of local scope
-const µb = µBlock;
-
const retrieveContentScriptParameters = async function(sender, request) {
if ( µb.readyToFilter !== true ) { return; }
const { tabId, frameId } = sender;
@@ -575,7 +594,6 @@ const retrieveContentScriptParameters = async function(sender, request) {
request.url = pageStore.getEffectiveFrameURL(sender);
}
- const loggerEnabled = µb.logger.enabled;
const noSpecificCosmeticFiltering =
pageStore.shouldApplySpecificCosmeticFilters(frameId) === false;
const noGenericCosmeticFiltering =
@@ -594,13 +612,13 @@ const retrieveContentScriptParameters = async function(sender, request) {
request.entity = entityFromDomain(request.domain);
response.specificCosmeticFilters =
- µb.cosmeticFilteringEngine.retrieveSpecificSelectors(request, response);
+ cosmeticFilteringEngine.retrieveSpecificSelectors(request, response);
// The procedural filterer's code is loaded only when needed and must be
// present before returning response to caller.
if (
Array.isArray(response.specificCosmeticFilters.proceduralFilters) || (
- loggerEnabled &&
+ logger.enabled &&
response.specificCosmeticFilters.exceptedFilters.length !== 0
)
) {
@@ -620,14 +638,14 @@ const retrieveContentScriptParameters = async function(sender, request) {
µb.canInjectScriptletsNow === false ||
isNetworkURI(sender.frameURL) === false
) {
- response.scriptlets = µb.scriptletFilteringEngine.retrieve(request);
+ response.scriptlets = scriptletFilteringEngine.retrieve(request);
}
// https://github.com/NanoMeow/QuickReports/issues/6#issuecomment-414516623
// Inject as early as possible to make the cosmetic logger code less
// sensitive to the removal of DOM nodes which may match injected
// cosmetic filters.
- if ( loggerEnabled ) {
+ if ( logger.enabled ) {
if (
noSpecificCosmeticFiltering === false ||
noGenericCosmeticFiltering === false
@@ -666,7 +684,7 @@ const onMessage = function(request, sender, callback) {
switch ( request.what ) {
case 'cosmeticFiltersInjected':
- µb.cosmeticFilteringEngine.addToSelectorCache(request);
+ cosmeticFilteringEngine.addToSelectorCache(request);
break;
case 'getCollapsibleBlockedRequests':
@@ -674,7 +692,7 @@ const onMessage = function(request, sender, callback) {
id: request.id,
hash: request.hash,
netSelectorCacheCountMax:
- µb.cosmeticFilteringEngine.netSelectorCacheCountMax,
+ cosmeticFilteringEngine.netSelectorCacheCountMax,
};
if (
µb.userSettings.collapseBlocked &&
@@ -705,7 +723,7 @@ const onMessage = function(request, sender, callback) {
request.tabId = sender.tabId;
request.frameId = sender.frameId;
response = {
- result: µb.cosmeticFilteringEngine.retrieveGenericSelectors(request),
+ result: cosmeticFilteringEngine.retrieveGenericSelectors(request),
};
break;
@@ -735,8 +753,6 @@ vAPI.messaging.listen({
// >>>>> start of local scope
const onMessage = function(request, sender, callback) {
- const µb = µBlock;
-
// Async
switch ( request.what ) {
// The procedural filterer must be present in case the user wants to
@@ -801,7 +817,7 @@ const fromBase64 = function(encoded) {
}
let u8array;
try {
- u8array = µBlock.denseBase64.decode(encoded);
+ u8array = µb.denseBase64.decode(encoded);
} catch(ex) {
}
return Promise.resolve(u8array !== undefined ? u8array : encoded);
@@ -809,22 +825,22 @@ const fromBase64 = function(encoded) {
const toBase64 = function(data) {
const value = data instanceof Uint8Array
- ? µBlock.denseBase64.encode(data)
+ ? µb.denseBase64.encode(data)
: data;
return Promise.resolve(value);
};
const compress = function(json) {
- return µBlock.lz4Codec.encode(json, toBase64);
+ return lz4Codec.encode(json, toBase64);
};
const decompress = function(encoded) {
- return µBlock.lz4Codec.decode(encoded, fromBase64);
+ return lz4Codec.decode(encoded, fromBase64);
};
const onMessage = function(request, sender, callback) {
// Cloud storage support is optional.
- if ( µBlock.cloudStorageSupported !== true ) {
+ if ( µb.cloudStorageSupported !== true ) {
callback();
return;
}
@@ -833,7 +849,7 @@ const onMessage = function(request, sender, callback) {
switch ( request.what ) {
case 'cloudGetOptions':
vAPI.cloud.getOptions(function(options) {
- options.enabled = µBlock.userSettings.cloudStorageEnabled === true;
+ options.enabled = µb.userSettings.cloudStorageEnabled === true;
callback(options);
});
return;
@@ -849,7 +865,7 @@ const onMessage = function(request, sender, callback) {
});
case 'cloudPush':
- if ( µBlock.hiddenSettings.cloudStorageCompression ) {
+ if ( µb.hiddenSettings.cloudStorageCompression ) {
request.encode = compress;
}
return vAPI.cloud.push(request).then(result => {
@@ -901,8 +917,6 @@ vAPI.messaging.listen({
{
// >>>>> start of local scope
-const µb = µBlock;
-
// Settings
const getLocalData = async function() {
const data = Object.assign({}, µb.restoreBackupSettings);
@@ -924,9 +938,9 @@ const backupUserData = async function() {
hiddenSettings:
µb.getModifiedSettings(µb.hiddenSettings, µb.hiddenSettingsDefault),
whitelist: µb.arrayFromWhitelist(µb.netWhitelist),
- dynamicFilteringString: µb.permanentFirewall.toString(),
- urlFilteringString: µb.permanentURLFiltering.toString(),
- hostnameSwitchesString: µb.permanentSwitches.toString(),
+ dynamicFilteringString: permanentFirewall.toString(),
+ urlFilteringString: permanentURLFiltering.toString(),
+ hostnameSwitchesString: permanentSwitches.toString(),
userFilters: userFilters.content,
};
@@ -962,17 +976,17 @@ const restoreUserData = async function(request) {
// https://github.com/chrisaljoudi/uBlock/issues/1102
// Ensure all currently cached assets are flushed from storage AND memory.
- µb.assets.rmrf();
+ io.rmrf();
// If we are going to restore all, might as well wipe out clean local
// storages
await Promise.all([
- µb.cacheStorage.clear(),
+ cacheStorage.clear(),
vAPI.storage.clear(),
]);
// Restore block stats
- µBlock.saveLocalSettings();
+ µb.saveLocalSettings();
// Restore user data
vAPI.storage.set(userData.userSettings);
@@ -980,7 +994,7 @@ const restoreUserData = async function(request) {
// Restore advanced settings.
let hiddenSettings = userData.hiddenSettings;
if ( hiddenSettings instanceof Object === false ) {
- hiddenSettings = µBlock.hiddenSettingsFromString(
+ hiddenSettings = µb.hiddenSettingsFromString(
userData.hiddenSettingsString || ''
);
}
@@ -1027,7 +1041,7 @@ const restoreUserData = async function(request) {
// quite attached to numbers
const resetUserData = async function() {
await Promise.all([
- µb.cacheStorage.clear(),
+ cacheStorage.clear(),
vAPI.storage.clear(),
]);
@@ -1056,17 +1070,17 @@ const getLists = async function(callback) {
autoUpdate: µb.userSettings.autoUpdate,
available: null,
cache: null,
- cosmeticFilterCount: µb.cosmeticFilteringEngine.getFilterCount(),
+ cosmeticFilterCount: cosmeticFilteringEngine.getFilterCount(),
current: µb.availableFilterLists,
ignoreGenericCosmeticFilters: µb.userSettings.ignoreGenericCosmeticFilters,
- isUpdating: µb.assets.isUpdating(),
- netFilterCount: µb.staticNetFilteringEngine.getFilterCount(),
+ isUpdating: io.isUpdating(),
+ netFilterCount: staticNetFilteringEngine.getFilterCount(),
parseCosmeticFilters: µb.userSettings.parseAllABPHideFilters,
userFiltersPath: µb.userFiltersPath
};
const [ lists, metadata ] = await Promise.all([
µb.getAvailableLists(),
- µb.assets.metadata(),
+ io.metadata(),
]);
r.available = lists;
prepListEntries(r.available);
@@ -1099,14 +1113,14 @@ const getOriginHints = function() {
const getRules = function() {
return {
permanentRules:
- µb.permanentFirewall.toArray().concat(
- µb.permanentSwitches.toArray(),
- µb.permanentURLFiltering.toArray()
+ permanentFirewall.toArray().concat(
+ permanentSwitches.toArray(),
+ permanentURLFiltering.toArray()
),
sessionRules:
- µb.sessionFirewall.toArray().concat(
- µb.sessionSwitches.toArray(),
- µb.sessionURLFiltering.toArray()
+ sessionFirewall.toArray().concat(
+ sessionSwitches.toArray(),
+ sessionURLFiltering.toArray()
),
pslSelfie: globals.publicSuffixList.toSelfie(),
};
@@ -1115,13 +1129,13 @@ const getRules = function() {
const modifyRuleset = function(details) {
let swRuleset, hnRuleset, urlRuleset;
if ( details.permanent ) {
- swRuleset = µb.permanentSwitches;
- hnRuleset = µb.permanentFirewall;
- urlRuleset = µb.permanentURLFiltering;
+ swRuleset = permanentSwitches;
+ hnRuleset = permanentFirewall;
+ urlRuleset = permanentURLFiltering;
} else {
- swRuleset = µb.sessionSwitches;
- hnRuleset = µb.sessionFirewall;
- urlRuleset = µb.sessionURLFiltering;
+ swRuleset = sessionSwitches;
+ hnRuleset = sessionFirewall;
+ urlRuleset = sessionURLFiltering;
}
let toRemove = new Set(details.toRemove.trim().split(/\s*[\n\r]+\s*/));
for ( let rule of toRemove ) {
@@ -1240,7 +1254,7 @@ const onMessage = function(request, sender, callback) {
case 'getAutoCompleteDetails':
response = {};
if ( (request.hintUpdateToken || 0) === 0 ) {
- response.redirectResources = µb.redirectEngine.getResourceDetails();
+ response.redirectResources = redirectEngine.getResourceDetails();
response.preparseDirectiveTokens = µb.preparseDirectives.getTokens();
response.preparseDirectiveHints = µb.preparseDirectives.getHints();
response.expertMode = µb.hiddenSettings.filterAuthorMode;
@@ -1257,22 +1271,22 @@ const onMessage = function(request, sender, callback) {
case 'modifyRuleset':
// https://github.com/chrisaljoudi/uBlock/issues/772
- µb.cosmeticFilteringEngine.removeFromSelectorCache('*');
+ cosmeticFilteringEngine.removeFromSelectorCache('*');
modifyRuleset(request);
response = getRules();
break;
case 'purgeAllCaches':
if ( request.hard ) {
- µb.assets.remove(/./);
+ io.remove(/./);
} else {
- µb.assets.purge(/./, 'public_suffix_list.dat');
+ io.purge(/./, 'public_suffix_list.dat');
}
break;
case 'purgeCache':
- µb.assets.purge(request.assetKey);
- µb.assets.remove('compiled/' + request.assetKey);
+ io.purge(request.assetKey);
+ io.remove('compiled/' + request.assetKey);
break;
case 'readHiddenSettings':
@@ -1325,7 +1339,6 @@ vAPI.messaging.listen({
{
// >>>>> start of local scope
-const µb = µBlock;
const extensionOriginURL = vAPI.getURL('');
const documentBlockedURL = vAPI.getURL('document-blocked.html');
@@ -1333,7 +1346,7 @@ const getLoggerData = async function(details, activeTabId, callback) {
const response = {
activeTabId,
colorBlind: µb.userSettings.colorBlindFriendly,
- entries: µb.logger.readAll(details.ownerId),
+ entries: logger.readAll(details.ownerId),
filterAuthorMode: µb.hiddenSettings.filterAuthorMode,
tabIdsToken: µb.pageStoresToken,
tooltips: µb.userSettings.tooltipsDisabled === false
@@ -1386,8 +1399,8 @@ const getURLFilteringData = function(details) {
dirty: false,
colors: colors
};
- const suf = µb.sessionURLFiltering;
- const puf = µb.permanentURLFiltering;
+ const suf = sessionURLFiltering;
+ const puf = permanentURLFiltering;
const urls = details.urls;
const context = details.context;
const type = details.type;
@@ -1416,7 +1429,7 @@ const compileTemporaryException = function(filter) {
const parser = new StaticFilteringParser();
parser.analyze(filter);
if ( parser.shouldDiscard() ) { return; }
- return µb.staticExtFilteringEngine.compileTemporary(parser);
+ return staticExtFilteringEngine.compileTemporary(parser);
};
const toggleTemporaryException = function(details) {
@@ -1443,8 +1456,8 @@ const onMessage = function(request, sender, callback) {
switch ( request.what ) {
case 'readAll':
if (
- µb.logger.ownerId !== undefined &&
- µb.logger.ownerId !== request.ownerId
+ logger.ownerId !== undefined &&
+ logger.ownerId !== request.ownerId
) {
return callback({ unavailable: true });
}
@@ -1466,14 +1479,14 @@ const onMessage = function(request, sender, callback) {
break;
case 'releaseView':
- if ( request.ownerId === µb.logger.ownerId ) {
- µb.logger.ownerId = undefined;
+ if ( request.ownerId === logger.ownerId ) {
+ logger.ownerId = undefined;
}
break;
case 'saveURLFilteringRules':
- response = µb.permanentURLFiltering.copyRules(
- µb.sessionURLFiltering,
+ response = permanentURLFiltering.copyRules(
+ sessionURLFiltering,
request.context,
request.urls,
request.type
@@ -1539,7 +1552,7 @@ const onMessage = function(request, sender, callback) {
break;
case 'temporarilyWhitelistDocument':
- µBlock.webRequest.strictBlockBypass(request.hostname);
+ webRequest.strictBlockBypass(request.hostname);
break;
default:
@@ -1568,10 +1581,8 @@ vAPI.messaging.listen({
{
// >>>>> start of local scope
-const µb = µBlock;
-
const logCosmeticFilters = function(tabId, details) {
- if ( µb.logger.enabled === false ) { return; }
+ if ( logger.enabled === false ) { return; }
const filter = { source: 'cosmetic', raw: '' };
const fctxt = µb.filteringContext.duplicate();
@@ -1588,7 +1599,7 @@ const logCosmeticFilters = function(tabId, details) {
};
const logCSPViolations = function(pageStore, request) {
- if ( µb.logger.enabled === false || pageStore === null ) {
+ if ( logger.enabled === false || pageStore === null ) {
return false;
}
if ( request.violations.length === 0 ) {
@@ -1606,7 +1617,7 @@ const logCSPViolations = function(pageStore, request) {
cspData = new Map();
const staticDirectives =
- µb.staticNetFilteringEngine.matchAndFetchModifiers(fctxt, 'csp');
+ staticNetFilteringEngine.matchAndFetchModifiers(fctxt, 'csp');
if ( staticDirectives !== undefined ) {
for ( const directive of staticDirectives ) {
if ( directive.result !== 1 ) { continue; }
@@ -1691,7 +1702,7 @@ const onMessage = function(request, sender, callback) {
switch ( request.what ) {
case 'inlinescriptFound':
- if ( µb.logger.enabled && pageStore !== null ) {
+ if ( logger.enabled && pageStore !== null ) {
const fctxt = µb.filteringContext.duplicate();
fctxt.fromTabId(tabId)
.setType('inline-script')
diff --git a/src/js/pagestore.js b/src/js/pagestore.js
index 64d14c2b4..5d9871cf0 100644
--- a/src/js/pagestore.js
+++ b/src/js/pagestore.js
@@ -23,14 +23,21 @@
/******************************************************************************/
+import contextMenu from './contextmenu.js';
+import logger from './logger.js';
+import staticNetFilteringEngine from './static-net-filtering.js';
+import µb from './background.js';
+import { redirectEngine } from './redirect-engine.js';
+import { sessionFirewall } from './dynamic-net-filtering.js';
+import { sessionSwitches } from './hnswitches.js';
+import { sessionURLFiltering } from './url-net-filtering.js';
+
import {
domainFromHostname,
hostnameFromURI,
isNetworkURI,
} from './uri-utils.js';
-import µBlock from './background.js';
-
/*******************************************************************************
A PageRequestStore object is used to store net requests in two ways:
@@ -42,10 +49,6 @@ To create a log of net requests
/******************************************************************************/
-const µb = µBlock;
-
-/******************************************************************************/
-
const NetFilteringResultCache = class {
constructor() {
this.init();
@@ -217,18 +220,18 @@ const FrameStore = class {
}
this._cosmeticFilteringBits = 0b11;
{
- const result = µb.staticNetFilteringEngine.matchRequestReverse(
+ const result = staticNetFilteringEngine.matchRequestReverse(
'specifichide',
this.rawURL
);
- if ( result !== 0 && µb.logger.enabled ) {
- µBlock.filteringContext
+ if ( result !== 0 && logger.enabled ) {
+ µb.filteringContext
.duplicate()
.fromTabId(tabId)
.setURL(this.rawURL)
.setRealm('network')
.setType('specifichide')
- .setFilter(µb.staticNetFilteringEngine.toLogData())
+ .setFilter(staticNetFilteringEngine.toLogData())
.toLogger();
}
if ( result === 2 ) {
@@ -236,18 +239,18 @@ const FrameStore = class {
}
}
{
- const result = µb.staticNetFilteringEngine.matchRequestReverse(
+ const result = staticNetFilteringEngine.matchRequestReverse(
'generichide',
this.rawURL
);
- if ( result !== 0 && µb.logger.enabled ) {
- µBlock.filteringContext
+ if ( result !== 0 && logger.enabled ) {
+ µb.filteringContext
.duplicate()
.fromTabId(tabId)
.setURL(this.rawURL)
.setRealm('network')
.setType('generichide')
- .setFilter(µb.staticNetFilteringEngine.toLogData())
+ .setFilter(staticNetFilteringEngine.toLogData())
.toLogger();
}
if ( result === 2 ) {
@@ -559,18 +562,18 @@ const PageStore = class {
if ( this._noCosmeticFiltering === undefined ) {
this._noCosmeticFiltering = this.getNetFilteringSwitch() === false;
if ( this._noCosmeticFiltering === false ) {
- this._noCosmeticFiltering = µb.sessionSwitches.evaluateZ(
+ this._noCosmeticFiltering = sessionSwitches.evaluateZ(
'no-cosmetic-filtering',
this.tabHostname
) === true;
- if ( this._noCosmeticFiltering && µb.logger.enabled ) {
+ if ( this._noCosmeticFiltering && logger.enabled ) {
µb.filteringContext
.duplicate()
.fromTabId(this.tabId)
.setURL(this.rawURL)
.setRealm('cosmetic')
.setType('dom')
- .setFilter(µb.sessionSwitches.toLogData())
+ .setFilter(sessionSwitches.toLogData())
.toLogger();
}
}
@@ -620,12 +623,12 @@ const PageStore = class {
allFrames: true,
runAt: 'document_idle',
});
- µb.contextMenu.update(this.tabId);
+ contextMenu.update(this.tabId);
}
temporarilyAllowLargeMediaElements(state) {
this.largeMediaCount = 0;
- µb.contextMenu.update(this.tabId);
+ contextMenu.update(this.tabId);
if ( state ) {
this.allowLargeMediaElementsUntil = 0;
this.allowLargeMediaElementsRegex = undefined;
@@ -784,32 +787,32 @@ const PageStore = class {
}
const requestType = fctxt.type;
- const loggerEnabled = µb.logger.enabled;
+ const loggerEnabled = logger.enabled;
// Dynamic URL filtering.
- let result = µb.sessionURLFiltering.evaluateZ(
+ let result = sessionURLFiltering.evaluateZ(
fctxt.getTabHostname(),
fctxt.url,
requestType
);
if ( result !== 0 && loggerEnabled ) {
- fctxt.filter = µb.sessionURLFiltering.toLogData();
+ fctxt.filter = sessionURLFiltering.toLogData();
}
// Dynamic hostname/type filtering.
if ( result === 0 && µb.userSettings.advancedUserEnabled ) {
- result = µb.sessionFirewall.evaluateCellZY(
+ result = sessionFirewall.evaluateCellZY(
fctxt.getTabHostname(),
fctxt.getHostname(),
requestType
);
if ( result !== 0 && result !== 3 && loggerEnabled ) {
- fctxt.filter = µb.sessionFirewall.toLogData();
+ fctxt.filter = sessionFirewall.toLogData();
}
}
// Static filtering has lowest precedence.
- const snfe = µb.staticNetFilteringEngine;
+ const snfe = staticNetFilteringEngine;
if ( result === 0 || result === 3 ) {
result = snfe.matchRequest(fctxt);
if ( result !== 0 ) {
@@ -873,19 +876,19 @@ const PageStore = class {
if ( this.getNetFilteringSwitch(fctxt) === false ) { return 0; }
- let result = µb.staticNetFilteringEngine.matchHeaders(fctxt, headers);
+ let result = staticNetFilteringEngine.matchHeaders(fctxt, headers);
if ( result === 0 ) { return 0; }
- const loggerEnabled = µb.logger.enabled;
+ const loggerEnabled = logger.enabled;
if ( loggerEnabled ) {
- fctxt.filter = µb.staticNetFilteringEngine.toLogData();
+ fctxt.filter = staticNetFilteringEngine.toLogData();
}
// Dynamic filtering allow rules
// URL filtering
if (
result === 1 &&
- µb.sessionURLFiltering.evaluateZ(
+ sessionURLFiltering.evaluateZ(
fctxt.getTabHostname(),
fctxt.url,
fctxt.type
@@ -893,14 +896,14 @@ const PageStore = class {
) {
result = 2;
if ( loggerEnabled ) {
- fctxt.filter = µb.sessionURLFiltering.toLogData();
+ fctxt.filter = sessionURLFiltering.toLogData();
}
}
// Hostname filtering
if (
result === 1 &&
µb.userSettings.advancedUserEnabled &&
- µb.sessionFirewall.evaluateCellZY(
+ sessionFirewall.evaluateCellZY(
fctxt.getTabHostname(),
fctxt.getHostname(),
fctxt.type
@@ -908,7 +911,7 @@ const PageStore = class {
) {
result = 2;
if ( loggerEnabled ) {
- fctxt.filter = µb.sessionFirewall.toLogData();
+ fctxt.filter = sessionFirewall.toLogData();
}
}
@@ -916,24 +919,24 @@ const PageStore = class {
}
redirectBlockedRequest(fctxt) {
- const directives = µb.staticNetFilteringEngine.redirectRequest(
- µb.redirectEngine,
+ const directives = staticNetFilteringEngine.redirectRequest(
+ redirectEngine,
fctxt
);
if ( directives === undefined ) { return; }
- if ( µb.logger.enabled !== true ) { return; }
+ if ( logger.enabled !== true ) { return; }
fctxt.pushFilters(directives.map(a => a.logData()));
if ( fctxt.redirectURL === undefined ) { return; }
fctxt.pushFilter({
source: 'redirect',
- raw: µb.redirectEngine.resourceNameRegister
+ raw: redirectEngine.resourceNameRegister
});
}
redirectNonBlockedRequest(fctxt) {
- const directives = µb.staticNetFilteringEngine.filterQuery(fctxt);
+ const directives = staticNetFilteringEngine.filterQuery(fctxt);
if ( directives === undefined ) { return; }
- if ( µb.logger.enabled !== true ) { return; }
+ if ( logger.enabled !== true ) { return; }
fctxt.pushFilters(directives.map(a => a.logData()));
if ( fctxt.redirectURL === undefined ) { return; }
fctxt.pushFilter({
@@ -944,13 +947,13 @@ const PageStore = class {
filterCSPReport(fctxt) {
if (
- µb.sessionSwitches.evaluateZ(
+ sessionSwitches.evaluateZ(
'no-csp-reports',
fctxt.getHostname()
)
) {
- if ( µb.logger.enabled ) {
- fctxt.filter = µb.sessionSwitches.toLogData();
+ if ( logger.enabled ) {
+ fctxt.filter = sessionSwitches.toLogData();
}
return 1;
}
@@ -962,13 +965,13 @@ const PageStore = class {
this.remoteFontCount += 1;
}
if (
- µb.sessionSwitches.evaluateZ(
+ sessionSwitches.evaluateZ(
'no-remote-fonts',
fctxt.getTabHostname()
) !== false
) {
- if ( µb.logger.enabled ) {
- fctxt.filter = µb.sessionSwitches.toLogData();
+ if ( logger.enabled ) {
+ fctxt.filter = sessionSwitches.toLogData();
}
return 1;
}
@@ -982,15 +985,15 @@ const PageStore = class {
}
if (
netFiltering === false ||
- µb.sessionSwitches.evaluateZ(
+ sessionSwitches.evaluateZ(
'no-scripting',
fctxt.getTabHostname()
) === false
) {
return 0;
}
- if ( µb.logger.enabled ) {
- fctxt.filter = µb.sessionSwitches.toLogData();
+ if ( logger.enabled ) {
+ fctxt.filter = sessionSwitches.toLogData();
}
return 1;
}
@@ -1019,7 +1022,7 @@ const PageStore = class {
return 0;
}
if (
- µb.sessionSwitches.evaluateZ(
+ sessionSwitches.evaluateZ(
'no-large-media',
fctxt.getTabHostname()
) !== true
@@ -1039,8 +1042,8 @@ const PageStore = class {
}, 500);
}
- if ( µb.logger.enabled ) {
- fctxt.filter = µb.sessionSwitches.toLogData();
+ if ( logger.enabled ) {
+ fctxt.filter = sessionSwitches.toLogData();
}
return 1;
@@ -1069,14 +1072,14 @@ const PageStore = class {
}
}
if ( exceptCname === undefined ) {
- const result = µb.staticNetFilteringEngine.matchRequestReverse(
+ const result = staticNetFilteringEngine.matchRequestReverse(
'cname',
frameStore instanceof Object
? frameStore.rawURL
: fctxt.getDocOrigin()
);
exceptCname = result === 2
- ? µb.staticNetFilteringEngine.toLogData()
+ ? staticNetFilteringEngine.toLogData()
: false;
if ( frameStore instanceof Object ) {
frameStore.exceptCname = exceptCname;
@@ -1128,6 +1131,6 @@ PageStore.prototype.collapsibleResources = new Set([
PageStore.junkyard = [];
PageStore.junkyardMax = 10;
-µb.PageStore = PageStore;
-
/******************************************************************************/
+
+export { PageStore };
diff --git a/src/js/redirect-engine.js b/src/js/redirect-engine.js
index a07fddbe6..58a6ec467 100644
--- a/src/js/redirect-engine.js
+++ b/src/js/redirect-engine.js
@@ -23,8 +23,9 @@
/******************************************************************************/
+import io from './assets.js';
+import µb from './background.js';
import { LineIterator } from './text-iterators.js';
-import µBlock from './background.js';
/******************************************************************************/
@@ -408,7 +409,7 @@ RedirectEngine.prototype.resourcesFromString = function(text) {
// No more data, add the resource.
const name = this.aliases.get(fields[0]) || fields[0];
const mime = fields[1];
- const content = µBlock.orphanizeString(
+ const content = µb.orphanizeString(
fields.slice(2).join(encoded ? '' : '\n')
);
this.resources.set(
@@ -436,14 +437,11 @@ const removeTopCommentBlock = function(text) {
/******************************************************************************/
RedirectEngine.prototype.loadBuiltinResources = function() {
- // TODO: remove once usage of uBO 1.20.4 is widespread.
- µBlock.assets.remove('ublock-resources');
-
this.resources = new Map();
this.aliases = new Map();
const fetches = [
- µBlock.assets.fetchText(
+ io.fetchText(
'/assets/resources/scriptlets.js'
).then(result => {
const content = result.content;
@@ -505,7 +503,7 @@ RedirectEngine.prototype.loadBuiltinResources = function() {
continue;
}
fetches.push(
- µBlock.assets.fetch(
+ io.fetch(
`/web_accessible_resources/${name}?secret=${vAPI.warSecret()}`,
{ responseType: details.data }
).then(
@@ -547,7 +545,7 @@ RedirectEngine.prototype.getResourceDetails = function() {
const resourcesSelfieVersion = 5;
RedirectEngine.prototype.selfieFromResources = function() {
- µBlock.assets.put(
+ io.put(
'compiled/redirectEngine/resources',
JSON.stringify({
version: resourcesSelfieVersion,
@@ -558,7 +556,7 @@ RedirectEngine.prototype.selfieFromResources = function() {
};
RedirectEngine.prototype.resourcesFromSelfie = async function() {
- const result = await µBlock.assets.get('compiled/redirectEngine/resources');
+ const result = await io.get('compiled/redirectEngine/resources');
let selfie;
try {
selfie = JSON.parse(result.content);
@@ -580,13 +578,13 @@ RedirectEngine.prototype.resourcesFromSelfie = async function() {
};
RedirectEngine.prototype.invalidateResourcesSelfie = function() {
- µBlock.assets.remove('compiled/redirectEngine/resources');
+ io.remove('compiled/redirectEngine/resources');
};
/******************************************************************************/
-// Export
+const redirectEngine = new RedirectEngine();
-µBlock.redirectEngine = new RedirectEngine();
+export { redirectEngine };
/******************************************************************************/
diff --git a/src/js/reverselookup-worker.js b/src/js/reverselookup-worker.js
new file mode 100644
index 000000000..0e4cf624f
--- /dev/null
+++ b/src/js/reverselookup-worker.js
@@ -0,0 +1,293 @@
+/*******************************************************************************
+
+ uBlock Origin - a browser extension to block requests.
+ Copyright (C) 2015-present Raymond Hill
+
+ 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';
+
+/******************************************************************************/
+
+{
+// >>>>> start of local scope
+
+/******************************************************************************/
+
+const reBlockStart = /^#block-start-(\d+)\n/gm;
+let listEntries = Object.create(null);
+
+const extractBlocks = function(content, begId, endId) {
+ reBlockStart.lastIndex = 0;
+ const out = [];
+ let match = reBlockStart.exec(content);
+ while ( match !== null ) {
+ const beg = match.index + match[0].length;
+ const blockId = parseInt(match[1], 10);
+ if ( blockId >= begId && blockId < endId ) {
+ const end = content.indexOf('#block-end-' + match[1], beg);
+ out.push(content.slice(beg, end));
+ reBlockStart.lastIndex = end;
+ }
+ match = reBlockStart.exec(content);
+ }
+ return out.join('\n');
+};
+
+// https://github.com/MajkiIT/polish-ads-filter/issues/14768#issuecomment-536006312
+// Avoid reporting badfilter-ed filters.
+
+const fromNetFilter = function(details) {
+ const lists = [];
+ const compiledFilter = details.compiledFilter;
+
+ for ( const assetKey in listEntries ) {
+ const entry = listEntries[assetKey];
+ if ( entry === undefined ) { continue; }
+ const content = extractBlocks(entry.content, 100, 101);
+ let pos = 0;
+ for (;;) {
+ pos = content.indexOf(compiledFilter, pos);
+ if ( pos === -1 ) { break; }
+ // We need an exact match.
+ // https://github.com/gorhill/uBlock/issues/1392
+ // https://github.com/gorhill/uBlock/issues/835
+ const notFound = pos !== 0 &&
+ content.charCodeAt(pos - 1) !== 0x0A;
+ pos += compiledFilter.length;
+ if (
+ notFound ||
+ pos !== content.length && content.charCodeAt(pos) !== 0x0A
+ ) {
+ continue;
+ }
+ lists.push({
+ assetKey: assetKey,
+ title: entry.title,
+ supportURL: entry.supportURL
+ });
+ break;
+ }
+ }
+
+ const response = {};
+ response[details.rawFilter] = lists;
+
+ self.postMessage({ id: details.id, response });
+};
+
+// Looking up filter lists from a cosmetic filter is a bit more complicated
+// than with network filters:
+//
+// The filter is its raw representation, not its compiled version. This is
+// because the cosmetic filtering engine can't translate a live cosmetic
+// filter into its compiled version. Reason is I do not want to burden
+// cosmetic filtering with the resource overhead of being able to recompile
+// live cosmetic filters. I want the cosmetic filtering code to be left
+// completely unaffected by reverse lookup requirements.
+//
+// Mainly, given a CSS selector and a hostname as context, we will derive
+// various versions of compiled filters and see if there are matches. This
+// way the whole CPU cost is incurred by the reverse lookup code -- in a
+// worker thread, and the cosmetic filtering engine incurs no cost at all.
+//
+// For this though, the reverse lookup code here needs some knowledge of
+// the inners of the cosmetic filtering engine.
+// FilterContainer.fromCompiledContent() is our reference code to create
+// the various compiled versions.
+
+const fromCosmeticFilter = function(details) {
+ const match = /^#@?#\^?/.exec(details.rawFilter);
+ const prefix = match[0];
+ const exception = prefix.charAt(1) === '@';
+ const selector = details.rawFilter.slice(prefix.length);
+ const isHtmlFilter = prefix.endsWith('^');
+ const hostname = details.hostname;
+
+ // The longer the needle, the lower the number of false positives.
+ // https://github.com/uBlockOrigin/uBlock-issues/issues/1139
+ // Mind that there is no guarantee a selector has `\w` characters.
+ const needle = selector.match(/\w+|\*/g).reduce(function(a, b) {
+ return a.length > b.length ? a : b;
+ });
+
+ const regexFromLabels = (prefix, hn, suffix) =>
+ new RegExp(
+ prefix +
+ hn.split('.').reduce((acc, item) => `(${acc}\\.)?${item}`) +
+ suffix
+ );
+
+ // https://github.com/uBlockOrigin/uBlock-issues/issues/803
+ // Support looking up selectors of the form `*##...`
+ const reHostname = regexFromLabels('^', hostname, '$');
+ let reEntity;
+ {
+ const domain = details.domain;
+ const pos = domain.indexOf('.');
+ if ( pos !== -1 ) {
+ reEntity = regexFromLabels(
+ '^(',
+ hostname.slice(0, pos + hostname.length - domain.length),
+ '\\.)?\\*$'
+ );
+ }
+ }
+
+ const hostnameMatches = hn => {
+ return hn === '' ||
+ reHostname.test(hn) ||
+ reEntity !== undefined && reEntity.test(hn);
+ };
+
+ const response = Object.create(null);
+
+ for ( const assetKey in listEntries ) {
+ const entry = listEntries[assetKey];
+ if ( entry === undefined ) { continue; }
+ let content = extractBlocks(entry.content, 200, 1000),
+ isProcedural,
+ found;
+ let pos = 0;
+ while ( (pos = content.indexOf(needle, pos)) !== -1 ) {
+ let beg = content.lastIndexOf('\n', pos);
+ if ( beg === -1 ) { beg = 0; }
+ let end = content.indexOf('\n', pos);
+ if ( end === -1 ) { end = content.length; }
+ pos = end;
+ const fargs = JSON.parse(content.slice(beg, end));
+ const filterType = fargs[0];
+
+ // https://github.com/gorhill/uBlock/issues/2763
+ if (
+ filterType >= 0 &&
+ filterType <= 5 &&
+ details.ignoreGeneric
+ ) {
+ continue;
+ }
+
+ // Do not confuse cosmetic filters with HTML ones.
+ if ( (filterType === 64) !== isHtmlFilter ) { continue; }
+
+ switch ( filterType ) {
+ // Lowly generic cosmetic filters
+ case 0: // simple id-based
+ if ( exception ) { break; }
+ if ( fargs[1] !== selector.slice(1) ) { break; }
+ if ( selector.charAt(0) !== '#' ) { break; }
+ found = prefix + selector;
+ break;
+ case 2: // simple class-based
+ if ( exception ) { break; }
+ if ( fargs[1] !== selector.slice(1) ) { break; }
+ if ( selector.charAt(0) !== '.' ) { break; }
+ found = prefix + selector;
+ break;
+ case 1: // complex id-based
+ case 3: // complex class-based
+ if ( exception ) { break; }
+ if ( fargs[2] !== selector ) { break; }
+ found = prefix + selector;
+ break;
+ // Highly generic cosmetic filters
+ case 4: // simple highly generic
+ case 5: // complex highly generic
+ if ( exception ) { break; }
+ if ( fargs[1] !== selector ) { break; }
+ found = prefix + selector;
+ break;
+ // Specific cosmetic filtering
+ // Generic exception
+ case 8:
+ // HTML filtering
+ // Response header filtering
+ case 64:
+ if ( exception !== ((fargs[2] & 0b001) !== 0) ) { break; }
+ isProcedural = (fargs[2] & 0b010) !== 0;
+ if (
+ isProcedural === false && fargs[3] !== selector ||
+ isProcedural && JSON.parse(fargs[3]).raw !== selector
+ ) {
+ break;
+ }
+ if ( hostnameMatches(fargs[1]) === false ) { break; }
+ // https://www.reddit.com/r/uBlockOrigin/comments/d6vxzj/
+ // Ignore match if specific cosmetic filters are disabled
+ if (
+ filterType === 8 &&
+ exception === false &&
+ details.ignoreSpecific
+ ) {
+ break;
+ }
+ found = fargs[1] + prefix + selector;
+ break;
+ // Scriptlet injection
+ case 32:
+ if ( exception !== ((fargs[2] & 0b001) !== 0) ) { break; }
+ if ( fargs[3] !== selector ) { break; }
+ if ( hostnameMatches(fargs[1]) ) {
+ found = fargs[1] + prefix + selector;
+ }
+ break;
+ }
+ if ( found !== undefined ) {
+ if ( response[found] === undefined ) {
+ response[found] = [];
+ }
+ response[found].push({
+ assetKey: assetKey,
+ title: entry.title,
+ supportURL: entry.supportURL
+ });
+ break;
+ }
+ }
+ }
+
+ self.postMessage({ id: details.id, response });
+};
+
+self.onmessage = function(e) { // jshint ignore:line
+ const msg = e.data;
+
+ switch ( msg.what ) {
+ case 'resetLists':
+ listEntries = Object.create(null);
+ break;
+
+ case 'setList':
+ listEntries[msg.details.assetKey] = msg.details;
+ break;
+
+ case 'fromNetFilter':
+ fromNetFilter(msg);
+ break;
+
+ case 'fromCosmeticFilter':
+ fromCosmeticFilter(msg);
+ break;
+ }
+};
+
+/******************************************************************************/
+
+// <<<<< end of local scope
+}
+
+/******************************************************************************/
diff --git a/src/js/reverselookup.js b/src/js/reverselookup.js
index 8549287a5..aa3bf01ae 100644
--- a/src/js/reverselookup.js
+++ b/src/js/reverselookup.js
@@ -23,462 +23,192 @@
/******************************************************************************/
-(( ) => {
-// >>>>> start of local scope
+import staticNetFilteringEngine from './static-net-filtering.js';
+import µb from './background.js';
+import { CompiledListWriter } from './static-filtering-io.js';
+import { StaticFilteringParser } from './static-filtering-parser.js';
+
+import {
+ domainFromHostname,
+ hostnameFromURI,
+} from './uri-utils.js';
/******************************************************************************/
-// Worker context
+const workerTTL = 5 * 60 * 1000;
+const pendingResponses = new Map();
-if (
- self.WorkerGlobalScope instanceof Object &&
- self instanceof self.WorkerGlobalScope
-) {
- const reBlockStart = /^#block-start-(\d+)\n/gm;
- let listEntries = Object.create(null);
+let worker = null;
+let workerTTLTimer;
+let needLists = true;
+let messageId = 1;
- const extractBlocks = function(content, begId, endId) {
- reBlockStart.lastIndex = 0;
- const out = [];
- let match = reBlockStart.exec(content);
- while ( match !== null ) {
- const beg = match.index + match[0].length;
- const blockId = parseInt(match[1], 10);
- if ( blockId >= begId && blockId < endId ) {
- const end = content.indexOf('#block-end-' + match[1], beg);
- out.push(content.slice(beg, end));
- reBlockStart.lastIndex = end;
- }
- match = reBlockStart.exec(content);
- }
- return out.join('\n');
- };
+const onWorkerMessage = function(e) {
+ const msg = e.data;
+ const resolver = pendingResponses.get(msg.id);
+ pendingResponses.delete(msg.id);
+ resolver(msg.response);
+};
- // https://github.com/MajkiIT/polish-ads-filter/issues/14768#issuecomment-536006312
- // Avoid reporting badfilter-ed filters.
+const stopWorker = function() {
+ if ( workerTTLTimer !== undefined ) {
+ clearTimeout(workerTTLTimer);
+ workerTTLTimer = undefined;
+ }
+ if ( worker === null ) { return; }
+ worker.terminate();
+ worker = null;
+ needLists = true;
+ for ( const resolver of pendingResponses.values() ) {
+ resolver();
+ }
+ pendingResponses.clear();
+};
- const fromNetFilter = function(details) {
- const lists = [];
- const compiledFilter = details.compiledFilter;
+const initWorker = function() {
+ if ( worker === null ) {
+ worker = new Worker('js/reverselookup-worker.js');
+ worker.onmessage = onWorkerMessage;
+ }
- for ( const assetKey in listEntries ) {
- const entry = listEntries[assetKey];
- if ( entry === undefined ) { continue; }
- const content = extractBlocks(entry.content, 100, 101);
- let pos = 0;
- for (;;) {
- pos = content.indexOf(compiledFilter, pos);
- if ( pos === -1 ) { break; }
- // We need an exact match.
- // https://github.com/gorhill/uBlock/issues/1392
- // https://github.com/gorhill/uBlock/issues/835
- const notFound = pos !== 0 &&
- content.charCodeAt(pos - 1) !== 0x0A;
- pos += compiledFilter.length;
- if (
- notFound ||
- pos !== content.length && content.charCodeAt(pos) !== 0x0A
- ) {
- continue;
- }
- lists.push({
- assetKey: assetKey,
- title: entry.title,
- supportURL: entry.supportURL
- });
- break;
- }
- }
+ // The worker will be shutdown after n minutes without being used.
+ if ( workerTTLTimer !== undefined ) {
+ clearTimeout(workerTTLTimer);
+ }
+ workerTTLTimer = vAPI.setTimeout(stopWorker, workerTTL);
- const response = {};
- response[details.rawFilter] = lists;
+ if ( needLists === false ) {
+ return Promise.resolve();
+ }
+ needLists = false;
- self.postMessage({ id: details.id, response });
- };
+ const entries = new Map();
- // Looking up filter lists from a cosmetic filter is a bit more complicated
- // than with network filters:
- //
- // The filter is its raw representation, not its compiled version. This is
- // because the cosmetic filtering engine can't translate a live cosmetic
- // filter into its compiled version. Reason is I do not want to burden
- // cosmetic filtering with the resource overhead of being able to recompile
- // live cosmetic filters. I want the cosmetic filtering code to be left
- // completely unaffected by reverse lookup requirements.
- //
- // Mainly, given a CSS selector and a hostname as context, we will derive
- // various versions of compiled filters and see if there are matches. This
- // way the whole CPU cost is incurred by the reverse lookup code -- in a
- // worker thread, and the cosmetic filtering engine incurs no cost at all.
- //
- // For this though, the reverse lookup code here needs some knowledge of
- // the inners of the cosmetic filtering engine.
- // FilterContainer.fromCompiledContent() is our reference code to create
- // the various compiled versions.
+ const onListLoaded = function(details) {
+ const entry = entries.get(details.assetKey);
- const fromCosmeticFilter = function(details) {
- const match = /^#@?#\^?/.exec(details.rawFilter);
- const prefix = match[0];
- const exception = prefix.charAt(1) === '@';
- const selector = details.rawFilter.slice(prefix.length);
- const isHtmlFilter = prefix.endsWith('^');
- const hostname = details.hostname;
-
- // The longer the needle, the lower the number of false positives.
- // https://github.com/uBlockOrigin/uBlock-issues/issues/1139
- // Mind that there is no guarantee a selector has `\w` characters.
- const needle = selector.match(/\w+|\*/g).reduce(function(a, b) {
- return a.length > b.length ? a : b;
- });
-
- const regexFromLabels = (prefix, hn, suffix) =>
- new RegExp(
- prefix +
- hn.split('.').reduce((acc, item) => `(${acc}\\.)?${item}`) +
- suffix
- );
-
- // https://github.com/uBlockOrigin/uBlock-issues/issues/803
- // Support looking up selectors of the form `*##...`
- const reHostname = regexFromLabels('^', hostname, '$');
- let reEntity;
- {
- const domain = details.domain;
- const pos = domain.indexOf('.');
- if ( pos !== -1 ) {
- reEntity = regexFromLabels(
- '^(',
- hostname.slice(0, pos + hostname.length - domain.length),
- '\\.)?\\*$'
- );
- }
- }
-
- const hostnameMatches = hn => {
- return hn === '' ||
- reHostname.test(hn) ||
- reEntity !== undefined && reEntity.test(hn);
- };
-
- const response = Object.create(null);
-
- for ( const assetKey in listEntries ) {
- const entry = listEntries[assetKey];
- if ( entry === undefined ) { continue; }
- let content = extractBlocks(entry.content, 200, 1000),
- isProcedural,
- found;
- let pos = 0;
- while ( (pos = content.indexOf(needle, pos)) !== -1 ) {
- let beg = content.lastIndexOf('\n', pos);
- if ( beg === -1 ) { beg = 0; }
- let end = content.indexOf('\n', pos);
- if ( end === -1 ) { end = content.length; }
- pos = end;
- const fargs = JSON.parse(content.slice(beg, end));
- const filterType = fargs[0];
-
- // https://github.com/gorhill/uBlock/issues/2763
- if (
- filterType >= 0 &&
- filterType <= 5 &&
- details.ignoreGeneric
- ) {
- continue;
- }
-
- // Do not confuse cosmetic filters with HTML ones.
- if ( (filterType === 64) !== isHtmlFilter ) { continue; }
-
- switch ( filterType ) {
- // Lowly generic cosmetic filters
- case 0: // simple id-based
- if ( exception ) { break; }
- if ( fargs[1] !== selector.slice(1) ) { break; }
- if ( selector.charAt(0) !== '#' ) { break; }
- found = prefix + selector;
- break;
- case 2: // simple class-based
- if ( exception ) { break; }
- if ( fargs[1] !== selector.slice(1) ) { break; }
- if ( selector.charAt(0) !== '.' ) { break; }
- found = prefix + selector;
- break;
- case 1: // complex id-based
- case 3: // complex class-based
- if ( exception ) { break; }
- if ( fargs[2] !== selector ) { break; }
- found = prefix + selector;
- break;
- // Highly generic cosmetic filters
- case 4: // simple highly generic
- case 5: // complex highly generic
- if ( exception ) { break; }
- if ( fargs[1] !== selector ) { break; }
- found = prefix + selector;
- break;
- // Specific cosmetic filtering
- // Generic exception
- case 8:
- // HTML filtering
- // Response header filtering
- case 64:
- if ( exception !== ((fargs[2] & 0b001) !== 0) ) { break; }
- isProcedural = (fargs[2] & 0b010) !== 0;
- if (
- isProcedural === false && fargs[3] !== selector ||
- isProcedural && JSON.parse(fargs[3]).raw !== selector
- ) {
- break;
- }
- if ( hostnameMatches(fargs[1]) === false ) { break; }
- // https://www.reddit.com/r/uBlockOrigin/comments/d6vxzj/
- // Ignore match if specific cosmetic filters are disabled
- if (
- filterType === 8 &&
- exception === false &&
- details.ignoreSpecific
- ) {
- break;
- }
- found = fargs[1] + prefix + selector;
- break;
- // Scriptlet injection
- case 32:
- if ( exception !== ((fargs[2] & 0b001) !== 0) ) { break; }
- if ( fargs[3] !== selector ) { break; }
- if ( hostnameMatches(fargs[1]) ) {
- found = fargs[1] + prefix + selector;
- }
- break;
- }
- if ( found !== undefined ) {
- if ( response[found] === undefined ) {
- response[found] = [];
- }
- response[found].push({
- assetKey: assetKey,
- title: entry.title,
- supportURL: entry.supportURL
- });
- break;
- }
- }
- }
-
- self.postMessage({ id: details.id, response });
- };
-
- self.onmessage = function(e) { // jshint ignore:line
- const msg = e.data;
-
- switch ( msg.what ) {
- case 'resetLists':
- listEntries = Object.create(null);
- break;
-
- case 'setList':
- listEntries[msg.details.assetKey] = msg.details;
- break;
-
- case 'fromNetFilter':
- fromNetFilter(msg);
- break;
-
- case 'fromCosmeticFilter':
- fromCosmeticFilter(msg);
- break;
- }
- };
-
- return;
-}
-
-/******************************************************************************/
-
-// Main context
-
-{
- if ( typeof µBlock !== 'object' ) { return; }
-
- const workerTTL = 5 * 60 * 1000;
- const pendingResponses = new Map();
-
- let worker = null;
- let workerTTLTimer;
- let needLists = true;
- let messageId = 1;
-
- const onWorkerMessage = function(e) {
- const msg = e.data;
- const resolver = pendingResponses.get(msg.id);
- pendingResponses.delete(msg.id);
- resolver(msg.response);
- };
-
- const stopWorker = function() {
- if ( workerTTLTimer !== undefined ) {
- clearTimeout(workerTTLTimer);
- workerTTLTimer = undefined;
- }
- if ( worker === null ) { return; }
- worker.terminate();
- worker = null;
- needLists = true;
- for ( const resolver of pendingResponses.values() ) {
- resolver();
- }
- pendingResponses.clear();
- };
-
- const initWorker = function() {
- if ( worker === null ) {
- worker = new Worker('js/reverselookup.js');
- worker.onmessage = onWorkerMessage;
- }
-
- // The worker will be shutdown after n minutes without being used.
- if ( workerTTLTimer !== undefined ) {
- clearTimeout(workerTTLTimer);
- }
- workerTTLTimer = vAPI.setTimeout(stopWorker, workerTTL);
-
- if ( needLists === false ) {
- return Promise.resolve();
- }
- needLists = false;
-
- const entries = new Map();
-
- const onListLoaded = function(details) {
- const entry = entries.get(details.assetKey);
-
- // https://github.com/gorhill/uBlock/issues/536
- // Use assetKey when there is no filter list title.
-
- worker.postMessage({
- what: 'setList',
- details: {
- assetKey: details.assetKey,
- title: entry.title || details.assetKey,
- supportURL: entry.supportURL,
- content: details.content
- }
- });
- };
-
- const µb = µBlock;
- for ( const listKey in µb.availableFilterLists ) {
- if ( µb.availableFilterLists.hasOwnProperty(listKey) === false ) {
- continue;
- }
- const entry = µb.availableFilterLists[listKey];
- if ( entry.off === true ) { continue; }
- entries.set(listKey, {
- title: listKey !== µb.userFiltersPath ?
- entry.title :
- vAPI.i18n('1pPageName'),
- supportURL: entry.supportURL || ''
- });
- }
- if ( entries.size === 0 ) {
- return Promise.resolve();
- }
-
- const promises = [];
- for ( const listKey of entries.keys() ) {
- promises.push(
- µb.getCompiledFilterList(listKey).then(details => {
- onListLoaded(details);
- })
- );
- }
- return Promise.all(promises);
- };
-
- const fromNetFilter = async function(rawFilter) {
- if ( typeof rawFilter !== 'string' || rawFilter === '' ) { return; }
-
- const µb = µBlock;
- const writer = new µb.CompiledListWriter();
- const parser = new µb.StaticFilteringParser();
- parser.setMaxTokenLength(µb.staticNetFilteringEngine.MAX_TOKEN_LENGTH);
- parser.analyze(rawFilter);
-
- if ( µb.staticNetFilteringEngine.compile(parser, writer) === false ) {
- return;
- }
-
- await initWorker();
-
- const id = messageId++;
- worker.postMessage({
- what: 'fromNetFilter',
- id: id,
- compiledFilter: writer.last(),
- rawFilter: rawFilter
- });
-
- return new Promise(resolve => {
- pendingResponses.set(id, resolve);
- });
- };
-
- const fromCosmeticFilter = async function(details) {
- if (
- typeof details.rawFilter !== 'string' ||
- details.rawFilter === ''
- ) {
- return;
- }
-
- await initWorker();
-
- const id = messageId++;
- const hostname = µBlock.hostnameFromURI(details.url);
+ // https://github.com/gorhill/uBlock/issues/536
+ // Use assetKey when there is no filter list title.
worker.postMessage({
- what: 'fromCosmeticFilter',
- id: id,
- domain: µBlock.domainFromHostname(hostname),
- hostname: hostname,
- ignoreGeneric:
- µBlock.staticNetFilteringEngine.matchRequestReverse(
- 'generichide',
- details.url
- ) === 2,
- ignoreSpecific:
- µBlock.staticNetFilteringEngine.matchRequestReverse(
- 'specifichide',
- details.url
- ) === 2,
- rawFilter: details.rawFilter
- });
-
- return new Promise(resolve => {
- pendingResponses.set(id, resolve);
+ what: 'setList',
+ details: {
+ assetKey: details.assetKey,
+ title: entry.title || details.assetKey,
+ supportURL: entry.supportURL,
+ content: details.content
+ }
});
};
- // This tells the worker that filter lists may have changed.
+ for ( const listKey in µb.availableFilterLists ) {
+ if ( µb.availableFilterLists.hasOwnProperty(listKey) === false ) {
+ continue;
+ }
+ const entry = µb.availableFilterLists[listKey];
+ if ( entry.off === true ) { continue; }
+ entries.set(listKey, {
+ title: listKey !== µb.userFiltersPath ?
+ entry.title :
+ vAPI.i18n('1pPageName'),
+ supportURL: entry.supportURL || ''
+ });
+ }
+ if ( entries.size === 0 ) {
+ return Promise.resolve();
+ }
- const resetLists = function() {
- needLists = true;
- if ( worker === null ) { return; }
- worker.postMessage({ what: 'resetLists' });
- };
+ const promises = [];
+ for ( const listKey of entries.keys() ) {
+ promises.push(
+ µb.getCompiledFilterList(listKey).then(details => {
+ onListLoaded(details);
+ })
+ );
+ }
+ return Promise.all(promises);
+};
- µBlock.staticFilteringReverseLookup = {
- fromNetFilter,
- fromCosmeticFilter,
- resetLists,
- shutdown: stopWorker
- };
-}
+const fromNetFilter = async function(rawFilter) {
+ if ( typeof rawFilter !== 'string' || rawFilter === '' ) { return; }
+
+ const writer = new CompiledListWriter();
+ const parser = new StaticFilteringParser();
+ parser.setMaxTokenLength(staticNetFilteringEngine.MAX_TOKEN_LENGTH);
+ parser.analyze(rawFilter);
+
+ if ( staticNetFilteringEngine.compile(parser, writer) === false ) {
+ return;
+ }
+
+ await initWorker();
+
+ const id = messageId++;
+ worker.postMessage({
+ what: 'fromNetFilter',
+ id: id,
+ compiledFilter: writer.last(),
+ rawFilter: rawFilter
+ });
+
+ return new Promise(resolve => {
+ pendingResponses.set(id, resolve);
+ });
+};
+
+const fromCosmeticFilter = async function(details) {
+ if (
+ typeof details.rawFilter !== 'string' ||
+ details.rawFilter === ''
+ ) {
+ return;
+ }
+
+ await initWorker();
+
+ const id = messageId++;
+ const hostname = hostnameFromURI(details.url);
+
+ worker.postMessage({
+ what: 'fromCosmeticFilter',
+ id: id,
+ domain: domainFromHostname(hostname),
+ hostname: hostname,
+ ignoreGeneric:
+ staticNetFilteringEngine.matchRequestReverse(
+ 'generichide',
+ details.url
+ ) === 2,
+ ignoreSpecific:
+ staticNetFilteringEngine.matchRequestReverse(
+ 'specifichide',
+ details.url
+ ) === 2,
+ rawFilter: details.rawFilter
+ });
+
+ return new Promise(resolve => {
+ pendingResponses.set(id, resolve);
+ });
+};
+
+// This tells the worker that filter lists may have changed.
+
+const resetLists = function() {
+ needLists = true;
+ if ( worker === null ) { return; }
+ worker.postMessage({ what: 'resetLists' });
+};
/******************************************************************************/
-// <<<<< end of local scope
-})();
+const staticFilteringReverseLookup = {
+ fromNetFilter,
+ fromCosmeticFilter,
+ resetLists,
+ shutdown: stopWorker
+};
+
+export default staticFilteringReverseLookup;
/******************************************************************************/
diff --git a/src/js/scriptlet-filtering.js b/src/js/scriptlet-filtering.js
index 5da7a0b16..73ffca877 100644
--- a/src/js/scriptlet-filtering.js
+++ b/src/js/scriptlet-filtering.js
@@ -23,28 +23,35 @@
/******************************************************************************/
+import logger from './logger.js';
+import µb from './background.js';
+import { redirectEngine } from './redirect-engine.js';
+import { sessionFirewall } from './dynamic-net-filtering.js';
+
+import {
+ StaticExtFilteringHostnameDB,
+ StaticExtFilteringSessionDB,
+} from './static-ext-filtering-db.js';
+
import {
domainFromHostname,
entityFromDomain,
hostnameFromURI,
} from './uri-utils.js';
-import µBlock from './background.js';
-
/******************************************************************************/
-const µb = µBlock;
const duplicates = new Set();
const scriptletCache = new µb.MRUCache(32);
const reEscapeScriptArg = /[\\'"]/g;
-const scriptletDB = new µb.staticExtFilteringEngine.HostnameBasedDB(1);
-const sessionScriptletDB = new µb.staticExtFilteringEngine.SessionDB();
+const scriptletDB = new StaticExtFilteringHostnameDB(1);
+const sessionScriptletDB = new StaticExtFilteringSessionDB();
let acceptedCount = 0;
let discardedCount = 0;
-const api = {
+const scriptletFilteringEngine = {
get acceptedCount() {
return acceptedCount;
},
@@ -132,7 +139,7 @@ const normalizeRawFilter = function(rawFilter) {
if ( end === -1 ) { end = rawEnd; }
const token = rawToken.slice(0, end).trim();
const alias = token.endsWith('.js') ? token.slice(0, -3) : token;
- let normalized = µb.redirectEngine.aliases.get(`${alias}.js`);
+ let normalized = redirectEngine.aliases.get(`${alias}.js`);
normalized = normalized === undefined
? alias
: normalized.slice(0, -3);
@@ -212,7 +219,7 @@ const patchScriptlet = function(content, args) {
};
const logOne = function(isException, token, details) {
- µBlock.filteringContext
+ µb.filteringContext
.duplicate()
.fromTabId(details.tabId)
.setRealm('extended')
@@ -226,19 +233,19 @@ const logOne = function(isException, token, details) {
.toLogger();
};
-api.reset = function() {
+scriptletFilteringEngine.reset = function() {
scriptletDB.clear();
duplicates.clear();
acceptedCount = 0;
discardedCount = 0;
};
-api.freeze = function() {
+scriptletFilteringEngine.freeze = function() {
duplicates.clear();
scriptletDB.collectGarbage();
};
-api.compile = function(parser, writer) {
+scriptletFilteringEngine.compile = function(parser, writer) {
writer.select(µb.compiledScriptletSection);
// Only exception filters are allowed to be global.
@@ -272,7 +279,7 @@ api.compile = function(parser, writer) {
}
};
-api.compileTemporary = function(parser) {
+scriptletFilteringEngine.compileTemporary = function(parser) {
return {
session: sessionScriptletDB,
selector: parser.result.compiled,
@@ -284,7 +291,7 @@ api.compileTemporary = function(parser) {
// ^ ^
// 4 -1
-api.fromCompiledContent = function(reader) {
+scriptletFilteringEngine.fromCompiledContent = function(reader) {
reader.select(µb.compiledScriptletSection);
while ( reader.next() ) {
@@ -301,7 +308,7 @@ api.fromCompiledContent = function(reader) {
}
};
-api.getSession = function() {
+scriptletFilteringEngine.getSession = function() {
return sessionScriptletDB;
};
@@ -309,12 +316,9 @@ const $scriptlets = new Set();
const $exceptions = new Set();
const $scriptletToCodeMap = new Map();
-api.retrieve = function(request) {
+scriptletFilteringEngine.retrieve = function(request) {
if ( scriptletDB.size === 0 ) { return; }
- const reng = µb.redirectEngine;
- if ( !reng ) { return; }
-
const hostname = request.hostname;
$scriptlets.clear();
@@ -334,16 +338,14 @@ api.retrieve = function(request) {
// Do not inject scriptlets if the site is under an `allow` rule.
if (
µb.userSettings.advancedUserEnabled &&
- µb.sessionFirewall.evaluateCellZY(hostname, hostname, '*') === 2
+ sessionFirewall.evaluateCellZY(hostname, hostname, '*') === 2
) {
return;
}
- const loggerEnabled = µb.logger.enabled;
-
// Wholly disable scriptlet injection?
if ( $exceptions.has('') ) {
- if ( loggerEnabled ) {
+ if ( logger.enabled ) {
logOne(true, '', request);
}
return;
@@ -351,7 +353,7 @@ api.retrieve = function(request) {
$scriptletToCodeMap.clear();
for ( const rawToken of $scriptlets ) {
- lookupScriptlet(rawToken, reng, $scriptletToCodeMap);
+ lookupScriptlet(rawToken, redirectEngine, $scriptletToCodeMap);
}
if ( $scriptletToCodeMap.size === 0 ) { return; }
@@ -362,7 +364,7 @@ api.retrieve = function(request) {
if ( isException === false ) {
out.push(code);
}
- if ( loggerEnabled ) {
+ if ( logger.enabled ) {
logOne(isException, rawToken, request);
}
}
@@ -390,11 +392,11 @@ api.retrieve = function(request) {
return out.join('\n');
};
-api.hasScriptlet = function(hostname, exceptionBit, scriptlet) {
+scriptletFilteringEngine.hasScriptlet = function(hostname, exceptionBit, scriptlet) {
return scriptletDB.hasStr(hostname, exceptionBit, scriptlet);
};
-api.injectNow = function(details) {
+scriptletFilteringEngine.injectNow = function(details) {
if ( typeof details.frameId !== 'number' ) { return; }
const request = {
tabId: details.tabId,
@@ -406,7 +408,7 @@ api.injectNow = function(details) {
};
request.domain = domainFromHostname(request.hostname);
request.entity = entityFromDomain(request.domain);
- const scriptlets = µb.scriptletFilteringEngine.retrieve(request);
+ const scriptlets = this.retrieve(request);
if ( scriptlets === undefined ) { return; }
let code = contentscriptCode.assemble(request.hostname, scriptlets);
if ( µb.hiddenSettings.debugScriptletInjector ) {
@@ -420,21 +422,21 @@ api.injectNow = function(details) {
});
};
-api.toSelfie = function() {
+scriptletFilteringEngine.toSelfie = function() {
return scriptletDB.toSelfie();
};
-api.fromSelfie = function(selfie) {
+scriptletFilteringEngine.fromSelfie = function(selfie) {
scriptletDB.fromSelfie(selfie);
};
-api.benchmark = async function() {
+scriptletFilteringEngine.benchmark = async function() {
const requests = await µb.loadBenchmarkDataset();
if ( Array.isArray(requests) === false || requests.length === 0 ) {
- log.print('No requests found to benchmark');
+ console.info('No requests found to benchmark');
return;
}
- log.print('Benchmarking scriptletFilteringEngine.retrieve()...');
+ console.info('Benchmarking scriptletFilteringEngine.retrieve()...');
const details = {
domain: '',
entity: '',
@@ -456,14 +458,12 @@ api.benchmark = async function() {
}
const t1 = self.performance.now();
const dur = t1 - t0;
- log.print(`Evaluated ${count} requests in ${dur.toFixed(0)} ms`);
- log.print(`\tAverage: ${(dur / count).toFixed(3)} ms per request`);
+ console.info(`Evaluated ${count} requests in ${dur.toFixed(0)} ms`);
+ console.info(`\tAverage: ${(dur / count).toFixed(3)} ms per request`);
};
/******************************************************************************/
-// Export
-
-µBlock.scriptletFilteringEngine = api;
+export default scriptletFilteringEngine;
/******************************************************************************/
diff --git a/src/js/start.js b/src/js/start.js
index 45b185435..e3514f7c8 100644
--- a/src/js/start.js
+++ b/src/js/start.js
@@ -23,7 +23,32 @@
/******************************************************************************/
-import µBlock from './background.js';
+import cacheStorage from './cachestorage.js';
+import contextMenu from './contextmenu.js';
+import io from './assets.js';
+import lz4Codec from './lz4.js';
+import staticExtFilteringEngine from './static-ext-filtering.js';
+import staticFilteringReverseLookup from './reverselookup.js';
+import staticNetFilteringEngine from './static-net-filtering.js';
+import µb from './background.js';
+import { redirectEngine } from './redirect-engine.js';
+import { ubolog } from './console.js';
+import { webRequest } from './traffic.js';
+
+import {
+ permanentFirewall,
+ sessionFirewall,
+} from './dynamic-net-filtering.js';
+
+import {
+ permanentSwitches,
+ sessionSwitches,
+} from './hnswitches.js';
+
+import {
+ permanentURLFiltering,
+ sessionURLFiltering,
+} from './url-net-filtering.js';
/******************************************************************************/
@@ -32,21 +57,19 @@ import µBlock from './background.js';
(async ( ) => {
// >>>>> start of private scope
-const µb = µBlock;
-
/******************************************************************************/
vAPI.app.onShutdown = function() {
- µb.staticFilteringReverseLookup.shutdown();
- µb.assets.updateStop();
- µb.staticNetFilteringEngine.reset();
- µb.staticExtFilteringEngine.reset();
- µb.sessionFirewall.reset();
- µb.permanentFirewall.reset();
- µb.sessionURLFiltering.reset();
- µb.permanentURLFiltering.reset();
- µb.sessionSwitches.reset();
- µb.permanentSwitches.reset();
+ staticFilteringReverseLookup.shutdown();
+ io.updateStop();
+ staticNetFilteringEngine.reset();
+ staticExtFilteringEngine.reset();
+ sessionFirewall.reset();
+ permanentFirewall.reset();
+ sessionURLFiltering.reset();
+ permanentURLFiltering.reset();
+ sessionSwitches.reset();
+ permanentSwitches.reset();
};
/******************************************************************************/
@@ -116,7 +139,7 @@ const onVersionReady = function(lastVersion) {
// Since built-in resources may have changed since last version, we
// force a reload of all resources.
- µb.redirectEngine.invalidateResourcesSelfie();
+ redirectEngine.invalidateResourcesSelfie();
// https://github.com/LiCybora/NanoDefenderFirefox/issues/196
// Toggle on the blocking of CSP reports by default for Firefox.
@@ -124,8 +147,8 @@ const onVersionReady = function(lastVersion) {
lastVersionInt <= 1031003011 &&
vAPI.webextFlavor.soup.has('firefox')
) {
- µb.sessionSwitches.toggle('no-csp-reports', '*', 1);
- µb.permanentSwitches.toggle('no-csp-reports', '*', 1);
+ sessionSwitches.toggle('no-csp-reports', '*', 1);
+ permanentSwitches.toggle('no-csp-reports', '*', 1);
µb.saveHostnameSwitches();
}
};
@@ -225,7 +248,7 @@ const onCacheSettingsReady = async function(fetched) {
}
if ( µb.selfieIsInvalid ) {
µb.selfieManager.destroy();
- µb.cacheStorage.set(µb.systemSettings);
+ cacheStorage.set(µb.systemSettings);
}
};
@@ -243,12 +266,12 @@ const onFirstFetchReady = function(fetched, adminExtra) {
fromFetch(µb.localSettings, fetched);
fromFetch(µb.restoreBackupSettings, fetched);
- µb.permanentFirewall.fromString(fetched.dynamicFilteringString);
- µb.sessionFirewall.assign(µb.permanentFirewall);
- µb.permanentURLFiltering.fromString(fetched.urlFilteringString);
- µb.sessionURLFiltering.assign(µb.permanentURLFiltering);
- µb.permanentSwitches.fromString(fetched.hostnameSwitchesString);
- µb.sessionSwitches.assign(µb.permanentSwitches);
+ permanentFirewall.fromString(fetched.dynamicFilteringString);
+ sessionFirewall.assign(permanentFirewall);
+ permanentURLFiltering.fromString(fetched.urlFilteringString);
+ sessionURLFiltering.assign(permanentURLFiltering);
+ permanentSwitches.fromString(fetched.hostnameSwitchesString);
+ sessionSwitches.assign(permanentSwitches);
onNetWhitelistReady(fetched.netWhitelist, adminExtra);
onVersionReady(fetched.version);
@@ -307,10 +330,10 @@ const createDefaultProps = function() {
try {
// https://github.com/gorhill/uBlock/issues/531
await µb.restoreAdminSettings();
- log.info(`Admin settings ready ${Date.now()-vAPI.T0} ms after launch`);
+ ubolog(`Admin settings ready ${Date.now()-vAPI.T0} ms after launch`);
await µb.loadHiddenSettings();
- log.info(`Hidden settings ready ${Date.now()-vAPI.T0} ms after launch`);
+ ubolog(`Hidden settings ready ${Date.now()-vAPI.T0} ms after launch`);
// Maybe override current network listener suspend state
if ( µb.hiddenSettings.suspendTabsUntilReady === 'no' ) {
@@ -320,42 +343,42 @@ try {
}
if ( µb.hiddenSettings.disableWebAssembly !== true ) {
- µb.staticNetFilteringEngine.enableWASM('/js').then(( ) => {
- log.info(`WASM modules ready ${Date.now()-vAPI.T0} ms after launch`);
+ staticNetFilteringEngine.enableWASM('/js').then(( ) => {
+ ubolog(`WASM modules ready ${Date.now()-vAPI.T0} ms after launch`);
});
}
- const cacheBackend = await µb.cacheStorage.select(
+ const cacheBackend = await cacheStorage.select(
µb.hiddenSettings.cacheStorageAPI
);
- log.info(`Backend storage for cache will be ${cacheBackend}`);
+ ubolog(`Backend storage for cache will be ${cacheBackend}`);
const adminExtra = await vAPI.adminStorage.get('toAdd');
- log.info(`Extra admin settings ready ${Date.now()-vAPI.T0} ms after launch`);
+ ubolog(`Extra admin settings ready ${Date.now()-vAPI.T0} ms after launch`);
// https://github.com/uBlockOrigin/uBlock-issues/issues/1365
// Wait for onCacheSettingsReady() to be fully ready.
const [ , , lastVersion ] = await Promise.all([
µb.loadSelectedFilterLists().then(( ) => {
- log.info(`List selection ready ${Date.now()-vAPI.T0} ms after launch`);
+ ubolog(`List selection ready ${Date.now()-vAPI.T0} ms after launch`);
}),
- µb.cacheStorage.get(
+ cacheStorage.get(
{ compiledMagic: 0, selfieMagic: 0 }
).then(fetched => {
- log.info(`Cache magic numbers ready ${Date.now()-vAPI.T0} ms after launch`);
+ ubolog(`Cache magic numbers ready ${Date.now()-vAPI.T0} ms after launch`);
onCacheSettingsReady(fetched);
}),
vAPI.storage.get(createDefaultProps()).then(fetched => {
- log.info(`First fetch ready ${Date.now()-vAPI.T0} ms after launch`);
+ ubolog(`First fetch ready ${Date.now()-vAPI.T0} ms after launch`);
onFirstFetchReady(fetched, adminExtra);
return fetched.version;
}),
µb.loadUserSettings().then(fetched => {
- log.info(`User settings ready ${Date.now()-vAPI.T0} ms after launch`);
+ ubolog(`User settings ready ${Date.now()-vAPI.T0} ms after launch`);
onUserSettingsReady(fetched);
}),
µb.loadPublicSuffixList().then(( ) => {
- log.info(`PSL ready ${Date.now()-vAPI.T0} ms after launch`);
+ ubolog(`PSL ready ${Date.now()-vAPI.T0} ms after launch`);
}),
]);
@@ -369,7 +392,7 @@ try {
}
// Prime the filtering engines before first use.
-µb.staticNetFilteringEngine.prime();
+staticNetFilteringEngine.prime();
// https://github.com/uBlockOrigin/uBlock-issues/issues/817#issuecomment-565730122
// Still try to load filter lists regardless of whether a serious error
@@ -378,7 +401,7 @@ let selfieIsValid = false;
try {
selfieIsValid = await µb.selfieManager.load();
if ( selfieIsValid === true ) {
- log.info(`Selfie ready ${Date.now()-vAPI.T0} ms after launch`);
+ ubolog(`Selfie ready ${Date.now()-vAPI.T0} ms after launch`);
}
} catch (ex) {
console.trace(ex);
@@ -386,7 +409,7 @@ try {
if ( selfieIsValid !== true ) {
try {
await µb.loadFilterLists();
- log.info(`Filter lists ready ${Date.now()-vAPI.T0} ms after launch`);
+ ubolog(`Filter lists ready ${Date.now()-vAPI.T0} ms after launch`);
} catch (ex) {
console.trace(ex);
}
@@ -399,21 +422,21 @@ if ( selfieIsValid !== true ) {
µb.readyToFilter = true;
// Start network observers.
-µb.webRequest.start();
+webRequest.start();
// Ensure that the resources allocated for decompression purpose (likely
// large buffers) are garbage-collectable immediately after launch.
// Otherwise I have observed that it may take quite a while before the
// garbage collection of these resources kicks in. Relinquishing as soon
// as possible ensure minimal memory usage baseline.
-µb.lz4Codec.relinquish();
+lz4Codec.relinquish();
// Initialize internal state with maybe already existing tabs.
initializeTabs();
// https://github.com/chrisaljoudi/uBlock/issues/184
// Check for updates not too far in the future.
-µb.assets.addObserver(µb.assetObserver.bind(µb));
+io.addObserver(µb.assetObserver.bind(µb));
µb.scheduleAssetUpdater(
µb.userSettings.autoUpdate
? µb.hiddenSettings.autoUpdateDelayAfterLaunch * 1000
@@ -422,7 +445,7 @@ initializeTabs();
// Force an update of the context menu according to the currently
// active tab.
-µb.contextMenu.update();
+contextMenu.update();
// Maybe install non-default popup document, or automatically select
// default UI according to platform.
@@ -455,7 +478,7 @@ browser.runtime.onUpdateAvailable.addListener(details => {
}
});
-log.info(`All ready ${Date.now()-vAPI.T0} ms after launch`);
+ubolog(`All ready ${Date.now()-vAPI.T0} ms after launch`);
// <<<<< end of private scope
})();
diff --git a/src/js/static-ext-filtering-db.js b/src/js/static-ext-filtering-db.js
new file mode 100644
index 000000000..a118485b6
--- /dev/null
+++ b/src/js/static-ext-filtering-db.js
@@ -0,0 +1,224 @@
+/*******************************************************************************
+
+ uBlock Origin - a browser extension to block requests.
+ Copyright (C) 2017-present Raymond Hill
+
+ 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';
+
+/******************************************************************************/
+
+const StaticExtFilteringHostnameDB = class {
+ constructor(nBits, selfie = undefined) {
+ this.nBits = nBits;
+ this.timer = undefined;
+ this.strToIdMap = new Map();
+ this.hostnameToSlotIdMap = new Map();
+ // Array of integer pairs
+ this.hostnameSlots = [];
+ // Array of strings (selectors and pseudo-selectors)
+ this.strSlots = [];
+ this.size = 0;
+ if ( selfie !== undefined ) {
+ this.fromSelfie(selfie);
+ }
+ }
+
+ store(hn, bits, s) {
+ this.size += 1;
+ let iStr = this.strToIdMap.get(s);
+ if ( iStr === undefined ) {
+ iStr = this.strSlots.length;
+ this.strSlots.push(s);
+ this.strToIdMap.set(s, iStr);
+ if ( this.timer === undefined ) {
+ this.collectGarbage(true);
+ }
+ }
+ const strId = iStr << this.nBits | bits;
+ let iHn = this.hostnameToSlotIdMap.get(hn);
+ if ( iHn === undefined ) {
+ this.hostnameToSlotIdMap.set(hn, this.hostnameSlots.length);
+ this.hostnameSlots.push(strId, 0);
+ return;
+ }
+ // Add as last item.
+ while ( this.hostnameSlots[iHn+1] !== 0 ) {
+ iHn = this.hostnameSlots[iHn+1];
+ }
+ this.hostnameSlots[iHn+1] = this.hostnameSlots.length;
+ this.hostnameSlots.push(strId, 0);
+ }
+
+ clear() {
+ this.hostnameToSlotIdMap.clear();
+ this.hostnameSlots.length = 0;
+ this.strSlots.length = 0;
+ this.strToIdMap.clear();
+ this.size = 0;
+ }
+
+ collectGarbage(later = false) {
+ if ( later === false ) {
+ if ( this.timer !== undefined ) {
+ self.cancelIdleCallback(this.timer);
+ this.timer = undefined;
+ }
+ this.strToIdMap.clear();
+ return;
+ }
+ if ( this.timer !== undefined ) { return; }
+ this.timer = self.requestIdleCallback(
+ ( ) => {
+ this.timer = undefined;
+ this.strToIdMap.clear();
+ },
+ { timeout: 5000 }
+ );
+ }
+
+ // modifiers = 1: return only specific items
+ // modifiers = 2: return only generic items
+ //
+ retrieve(hostname, out, modifiers = 0) {
+ if ( modifiers === 2 ) {
+ hostname = '';
+ }
+ const mask = out.length - 1; // out.length must be power of two
+ for (;;) {
+ let iHn = this.hostnameToSlotIdMap.get(hostname);
+ if ( iHn !== undefined ) {
+ do {
+ const strId = this.hostnameSlots[iHn+0];
+ out[strId & mask].add(
+ this.strSlots[strId >>> this.nBits]
+ );
+ iHn = this.hostnameSlots[iHn+1];
+ } while ( iHn !== 0 );
+ }
+ if ( hostname === '' ) { break; }
+ const pos = hostname.indexOf('.');
+ if ( pos === -1 ) {
+ if ( modifiers === 1 ) { break; }
+ hostname = '';
+ } else {
+ hostname = hostname.slice(pos + 1);
+ }
+ }
+ }
+
+ hasStr(hostname, exceptionBit, value) {
+ let found = false;
+ for (;;) {
+ let iHn = this.hostnameToSlotIdMap.get(hostname);
+ if ( iHn !== undefined ) {
+ do {
+ const strId = this.hostnameSlots[iHn+0];
+ const str = this.strSlots[strId >>> this.nBits];
+ if ( (strId & exceptionBit) !== 0 ) {
+ if ( str === value || str === '' ) { return false; }
+ }
+ if ( str === value ) { found = true; }
+ iHn = this.hostnameSlots[iHn+1];
+ } while ( iHn !== 0 );
+ }
+ if ( hostname === '' ) { break; }
+ const pos = hostname.indexOf('.');
+ if ( pos !== -1 ) {
+ hostname = hostname.slice(pos + 1);
+ } else if ( hostname !== '*' ) {
+ hostname = '*';
+ } else {
+ hostname = '';
+ }
+ }
+ return found;
+ }
+
+ toSelfie() {
+ return {
+ hostnameToSlotIdMap: Array.from(this.hostnameToSlotIdMap),
+ hostnameSlots: this.hostnameSlots,
+ strSlots: this.strSlots,
+ size: this.size
+ };
+ }
+
+ fromSelfie(selfie) {
+ if ( selfie === undefined ) { return; }
+ this.hostnameToSlotIdMap = new Map(selfie.hostnameToSlotIdMap);
+ this.hostnameSlots = selfie.hostnameSlots;
+ this.strSlots = selfie.strSlots;
+ this.size = selfie.size;
+ }
+};
+
+/******************************************************************************/
+
+const StaticExtFilteringSessionDB = class {
+ constructor() {
+ this.db = new Map();
+ }
+ compile(s) {
+ return s;
+ }
+ add(bits, s) {
+ const bucket = this.db.get(bits);
+ if ( bucket === undefined ) {
+ this.db.set(bits, new Set([ s ]));
+ } else {
+ bucket.add(s);
+ }
+ }
+ remove(bits, s) {
+ const bucket = this.db.get(bits);
+ if ( bucket === undefined ) { return; }
+ bucket.delete(s);
+ if ( bucket.size !== 0 ) { return; }
+ this.db.delete(bits);
+ }
+ retrieve(out) {
+ const mask = out.length - 1;
+ for ( const [ bits, bucket ] of this.db ) {
+ const i = bits & mask;
+ if ( out[i] instanceof Object === false ) { continue; }
+ for ( const s of bucket ) {
+ out[i].add(s);
+ }
+ }
+ }
+ has(bits, s) {
+ const selectors = this.db.get(bits);
+ return selectors !== undefined && selectors.has(s);
+ }
+ clear() {
+ this.db.clear();
+ }
+ get isNotEmpty() {
+ return this.db.size !== 0;
+ }
+};
+
+/******************************************************************************/
+
+export {
+ StaticExtFilteringHostnameDB,
+ StaticExtFilteringSessionDB,
+};
+
+/******************************************************************************/
diff --git a/src/js/static-ext-filtering.js b/src/js/static-ext-filtering.js
index 04b86795c..d6bc851b2 100644
--- a/src/js/static-ext-filtering.js
+++ b/src/js/static-ext-filtering.js
@@ -23,7 +23,12 @@
/******************************************************************************/
-import µBlock from './background.js';
+import cosmeticFilteringEngine from './cosmetic-filtering.js';
+import htmlFilteringEngine from './html-filtering.js';
+import httpheaderFilteringEngine from './httpheader-filtering.js';
+import io from './assets.js';
+import logger from './logger.js';
+import scriptletFilteringEngine from './scriptlet-filtering.js';
/*******************************************************************************
@@ -52,244 +57,49 @@ import µBlock from './background.js';
**/
-const µb = µBlock;
-
//--------------------------------------------------------------------------
// Public API
//--------------------------------------------------------------------------
-const api = {
+const staticExtFilteringEngine = {
get acceptedCount() {
- return µb.cosmeticFilteringEngine.acceptedCount +
- µb.scriptletFilteringEngine.acceptedCount +
- µb.httpheaderFilteringEngine.acceptedCount +
- µb.htmlFilteringEngine.acceptedCount;
+ return cosmeticFilteringEngine.acceptedCount +
+ scriptletFilteringEngine.acceptedCount +
+ httpheaderFilteringEngine.acceptedCount +
+ htmlFilteringEngine.acceptedCount;
},
get discardedCount() {
- return µb.cosmeticFilteringEngine.discardedCount +
- µb.scriptletFilteringEngine.discardedCount +
- µb.httpheaderFilteringEngine.discardedCount +
- µb.htmlFilteringEngine.discardedCount;
+ return cosmeticFilteringEngine.discardedCount +
+ scriptletFilteringEngine.discardedCount +
+ httpheaderFilteringEngine.discardedCount +
+ htmlFilteringEngine.discardedCount;
},
};
-//--------------------------------------------------------------------------
-// Public classes
-//--------------------------------------------------------------------------
-
-api.HostnameBasedDB = class {
- constructor(nBits, selfie = undefined) {
- this.nBits = nBits;
- this.timer = undefined;
- this.strToIdMap = new Map();
- this.hostnameToSlotIdMap = new Map();
- // Array of integer pairs
- this.hostnameSlots = [];
- // Array of strings (selectors and pseudo-selectors)
- this.strSlots = [];
- this.size = 0;
- if ( selfie !== undefined ) {
- this.fromSelfie(selfie);
- }
- }
-
- store(hn, bits, s) {
- this.size += 1;
- let iStr = this.strToIdMap.get(s);
- if ( iStr === undefined ) {
- iStr = this.strSlots.length;
- this.strSlots.push(s);
- this.strToIdMap.set(s, iStr);
- if ( this.timer === undefined ) {
- this.collectGarbage(true);
- }
- }
- const strId = iStr << this.nBits | bits;
- let iHn = this.hostnameToSlotIdMap.get(hn);
- if ( iHn === undefined ) {
- this.hostnameToSlotIdMap.set(hn, this.hostnameSlots.length);
- this.hostnameSlots.push(strId, 0);
- return;
- }
- // Add as last item.
- while ( this.hostnameSlots[iHn+1] !== 0 ) {
- iHn = this.hostnameSlots[iHn+1];
- }
- this.hostnameSlots[iHn+1] = this.hostnameSlots.length;
- this.hostnameSlots.push(strId, 0);
- }
-
- clear() {
- this.hostnameToSlotIdMap.clear();
- this.hostnameSlots.length = 0;
- this.strSlots.length = 0;
- this.strToIdMap.clear();
- this.size = 0;
- }
-
- collectGarbage(later = false) {
- if ( later === false ) {
- if ( this.timer !== undefined ) {
- self.cancelIdleCallback(this.timer);
- this.timer = undefined;
- }
- this.strToIdMap.clear();
- return;
- }
- if ( this.timer !== undefined ) { return; }
- this.timer = self.requestIdleCallback(
- ( ) => {
- this.timer = undefined;
- this.strToIdMap.clear();
- },
- { timeout: 5000 }
- );
- }
-
- // modifiers = 1: return only specific items
- // modifiers = 2: return only generic items
- //
- retrieve(hostname, out, modifiers = 0) {
- if ( modifiers === 2 ) {
- hostname = '';
- }
- const mask = out.length - 1; // out.length must be power of two
- for (;;) {
- let iHn = this.hostnameToSlotIdMap.get(hostname);
- if ( iHn !== undefined ) {
- do {
- const strId = this.hostnameSlots[iHn+0];
- out[strId & mask].add(
- this.strSlots[strId >>> this.nBits]
- );
- iHn = this.hostnameSlots[iHn+1];
- } while ( iHn !== 0 );
- }
- if ( hostname === '' ) { break; }
- const pos = hostname.indexOf('.');
- if ( pos === -1 ) {
- if ( modifiers === 1 ) { break; }
- hostname = '';
- } else {
- hostname = hostname.slice(pos + 1);
- }
- }
- }
-
- hasStr(hostname, exceptionBit, value) {
- let found = false;
- for (;;) {
- let iHn = this.hostnameToSlotIdMap.get(hostname);
- if ( iHn !== undefined ) {
- do {
- const strId = this.hostnameSlots[iHn+0];
- const str = this.strSlots[strId >>> this.nBits];
- if ( (strId & exceptionBit) !== 0 ) {
- if ( str === value || str === '' ) { return false; }
- }
- if ( str === value ) { found = true; }
- iHn = this.hostnameSlots[iHn+1];
- } while ( iHn !== 0 );
- }
- if ( hostname === '' ) { break; }
- const pos = hostname.indexOf('.');
- if ( pos !== -1 ) {
- hostname = hostname.slice(pos + 1);
- } else if ( hostname !== '*' ) {
- hostname = '*';
- } else {
- hostname = '';
- }
- }
- return found;
- }
-
- toSelfie() {
- return {
- hostnameToSlotIdMap: Array.from(this.hostnameToSlotIdMap),
- hostnameSlots: this.hostnameSlots,
- strSlots: this.strSlots,
- size: this.size
- };
- }
-
- fromSelfie(selfie) {
- if ( selfie === undefined ) { return; }
- this.hostnameToSlotIdMap = new Map(selfie.hostnameToSlotIdMap);
- this.hostnameSlots = selfie.hostnameSlots;
- this.strSlots = selfie.strSlots;
- this.size = selfie.size;
- }
-};
-
-api.SessionDB = class {
- constructor() {
- this.db = new Map();
- }
- compile(s) {
- return s;
- }
- add(bits, s) {
- const bucket = this.db.get(bits);
- if ( bucket === undefined ) {
- this.db.set(bits, new Set([ s ]));
- } else {
- bucket.add(s);
- }
- }
- remove(bits, s) {
- const bucket = this.db.get(bits);
- if ( bucket === undefined ) { return; }
- bucket.delete(s);
- if ( bucket.size !== 0 ) { return; }
- this.db.delete(bits);
- }
- retrieve(out) {
- const mask = out.length - 1;
- for ( const [ bits, bucket ] of this.db ) {
- const i = bits & mask;
- if ( out[i] instanceof Object === false ) { continue; }
- for ( const s of bucket ) {
- out[i].add(s);
- }
- }
- }
- has(bits, s) {
- const selectors = this.db.get(bits);
- return selectors !== undefined && selectors.has(s);
- }
- clear() {
- this.db.clear();
- }
- get isNotEmpty() {
- return this.db.size !== 0;
- }
-};
-
//--------------------------------------------------------------------------
// Public methods
//--------------------------------------------------------------------------
-api.reset = function() {
- µb.cosmeticFilteringEngine.reset();
- µb.scriptletFilteringEngine.reset();
- µb.httpheaderFilteringEngine.reset();
- µb.htmlFilteringEngine.reset();
+staticExtFilteringEngine.reset = function() {
+ cosmeticFilteringEngine.reset();
+ scriptletFilteringEngine.reset();
+ httpheaderFilteringEngine.reset();
+ htmlFilteringEngine.reset();
};
-api.freeze = function() {
- µb.cosmeticFilteringEngine.freeze();
- µb.scriptletFilteringEngine.freeze();
- µb.httpheaderFilteringEngine.freeze();
- µb.htmlFilteringEngine.freeze();
+staticExtFilteringEngine.freeze = function() {
+ cosmeticFilteringEngine.freeze();
+ scriptletFilteringEngine.freeze();
+ httpheaderFilteringEngine.freeze();
+ htmlFilteringEngine.freeze();
};
-api.compile = function(parser, writer) {
+staticExtFilteringEngine.compile = function(parser, writer) {
if ( parser.category !== parser.CATStaticExtFilter ) { return false; }
if ( (parser.flavorBits & parser.BITFlavorUnsupported) !== 0 ) {
const who = writer.properties.get('name') || '?';
- µb.logger.writeOne({
+ logger.writeOne({
realm: 'message',
type: 'error',
text: `Invalid extended filter in ${who}: ${parser.raw}`
@@ -299,13 +109,13 @@ api.compile = function(parser, writer) {
// Scriptlet injection
if ( (parser.flavorBits & parser.BITFlavorExtScriptlet) !== 0 ) {
- µb.scriptletFilteringEngine.compile(parser, writer);
+ scriptletFilteringEngine.compile(parser, writer);
return true;
}
// Response header filtering
if ( (parser.flavorBits & parser.BITFlavorExtResponseHeader) !== 0 ) {
- µb.httpheaderFilteringEngine.compile(parser, writer);
+ httpheaderFilteringEngine.compile(parser, writer);
return true;
}
@@ -313,67 +123,65 @@ api.compile = function(parser, writer) {
// TODO: evaluate converting Adguard's `$$` syntax into uBO's HTML
// filtering syntax.
if ( (parser.flavorBits & parser.BITFlavorExtHTML) !== 0 ) {
- µb.htmlFilteringEngine.compile(parser, writer);
+ htmlFilteringEngine.compile(parser, writer);
return true;
}
// Cosmetic filtering
- µb.cosmeticFilteringEngine.compile(parser, writer);
+ cosmeticFilteringEngine.compile(parser, writer);
return true;
};
-api.compileTemporary = function(parser) {
+staticExtFilteringEngine.compileTemporary = function(parser) {
if ( (parser.flavorBits & parser.BITFlavorExtScriptlet) !== 0 ) {
- return µb.scriptletFilteringEngine.compileTemporary(parser);
+ return scriptletFilteringEngine.compileTemporary(parser);
}
if ( (parser.flavorBits & parser.BITFlavorExtResponseHeader) !== 0 ) {
- return µb.httpheaderFilteringEngine.compileTemporary(parser);
+ return httpheaderFilteringEngine.compileTemporary(parser);
}
if ( (parser.flavorBits & parser.BITFlavorExtHTML) !== 0 ) {
- return µb.htmlFilteringEngine.compileTemporary(parser);
+ return htmlFilteringEngine.compileTemporary(parser);
}
- return µb.cosmeticFilteringEngine.compileTemporary(parser);
+ return cosmeticFilteringEngine.compileTemporary(parser);
};
-api.fromCompiledContent = function(reader, options) {
- µb.cosmeticFilteringEngine.fromCompiledContent(reader, options);
- µb.scriptletFilteringEngine.fromCompiledContent(reader, options);
- µb.httpheaderFilteringEngine.fromCompiledContent(reader, options);
- µb.htmlFilteringEngine.fromCompiledContent(reader, options);
+staticExtFilteringEngine.fromCompiledContent = function(reader, options) {
+ cosmeticFilteringEngine.fromCompiledContent(reader, options);
+ scriptletFilteringEngine.fromCompiledContent(reader, options);
+ httpheaderFilteringEngine.fromCompiledContent(reader, options);
+ htmlFilteringEngine.fromCompiledContent(reader, options);
};
-api.toSelfie = function(path) {
- return µBlock.assets.put(
+staticExtFilteringEngine.toSelfie = function(path) {
+ return io.put(
`${path}/main`,
JSON.stringify({
- cosmetic: µb.cosmeticFilteringEngine.toSelfie(),
- scriptlets: µb.scriptletFilteringEngine.toSelfie(),
- httpHeaders: µb.httpheaderFilteringEngine.toSelfie(),
- html: µb.htmlFilteringEngine.toSelfie(),
+ cosmetic: cosmeticFilteringEngine.toSelfie(),
+ scriptlets: scriptletFilteringEngine.toSelfie(),
+ httpHeaders: httpheaderFilteringEngine.toSelfie(),
+ html: htmlFilteringEngine.toSelfie(),
})
);
};
-api.fromSelfie = function(path) {
- return µBlock.assets.get(`${path}/main`).then(details => {
+staticExtFilteringEngine.fromSelfie = function(path) {
+ return io.get(`${path}/main`).then(details => {
let selfie;
try {
selfie = JSON.parse(details.content);
} catch (ex) {
}
if ( selfie instanceof Object === false ) { return false; }
- µb.cosmeticFilteringEngine.fromSelfie(selfie.cosmetic);
- µb.scriptletFilteringEngine.fromSelfie(selfie.scriptlets);
- µb.httpheaderFilteringEngine.fromSelfie(selfie.httpHeaders);
- µb.htmlFilteringEngine.fromSelfie(selfie.html);
+ cosmeticFilteringEngine.fromSelfie(selfie.cosmetic);
+ scriptletFilteringEngine.fromSelfie(selfie.scriptlets);
+ httpheaderFilteringEngine.fromSelfie(selfie.httpHeaders);
+ htmlFilteringEngine.fromSelfie(selfie.html);
return true;
});
};
/******************************************************************************/
-// Export
-
-µBlock.staticExtFilteringEngine = api;
+export default staticExtFilteringEngine;
/******************************************************************************/
diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js
index f71844ed6..0e539d057 100644
--- a/src/js/static-net-filtering.js
+++ b/src/js/static-net-filtering.js
@@ -3396,8 +3396,6 @@ FilterContainer.prototype.freeze = function() {
const filterBucketId = FilterBucket.fid;
const unserialize = CompiledListReader.unserialize;
- const t0 = Date.now();
-
for ( const line of this.goodFilters ) {
if ( this.badFilters.has(line) ) {
this.discardedCount += 1;
@@ -3487,8 +3485,6 @@ FilterContainer.prototype.freeze = function() {
this.optimize();
}, { timeout: 5000 });
}
-
- console.info(`staticNetFilteringEngine.freeze() took ${Date.now()-t0} ms`);
};
/******************************************************************************/
@@ -3499,8 +3495,6 @@ FilterContainer.prototype.optimize = function() {
this.optimizeTimerId = undefined;
}
- const t0 = Date.now();
-
for ( let bits = 0, n = this.categories.length; bits < n; bits++ ) {
const bucket = this.categories[bits];
if ( bucket === undefined ) { continue; }
@@ -3523,8 +3517,6 @@ FilterContainer.prototype.optimize = function() {
for ( let i = filterUnitWritePtr, n = filterUnits.length; i < n; i++ ) {
filterUnits[i] = null;
}
-
- console.info(`staticNetFilteringEngine.optimize() took ${Date.now()-t0} ms`);
};
/******************************************************************************/
@@ -4477,9 +4469,7 @@ FilterContainer.prototype.benchmark = async function(requests, options = {}) {
return text;
}
- const print = log.print;
-
- print(`Benchmarking staticNetFilteringEngine.matchRequest()...`);
+ console.info(`Benchmarking staticNetFilteringEngine.matchRequest()...`);
const fctxt = new FilteringContext();
@@ -4489,12 +4479,12 @@ FilterContainer.prototype.benchmark = async function(requests, options = {}) {
fctxt.setDocOriginFromURL(request.frameUrl);
fctxt.setType(request.cpt);
const r = this.matchRequest(fctxt);
- print(`Result=${r}:`);
- print(`\ttype=${fctxt.type}`);
- print(`\turl=${fctxt.url}`);
- print(`\tdocOrigin=${fctxt.getDocOrigin()}`);
+ console.info(`Result=${r}:`);
+ console.info(`\ttype=${fctxt.type}`);
+ console.info(`\turl=${fctxt.url}`);
+ console.info(`\tdocOrigin=${fctxt.getDocOrigin()}`);
if ( r !== 0 ) {
- console.log(this.toLogData());
+ console.info(this.toLogData());
}
return;
}
@@ -4524,11 +4514,11 @@ FilterContainer.prototype.benchmark = async function(requests, options = {}) {
matchCount += 1;
if ( recorded !== undefined ) { recorded.push(r); }
if ( expected !== undefined && r !== expected[i] ) {
- print(`Mismatch with reference results at ${i}:`);
- print(`\tExpected ${expected[i]}, got ${r}:`);
- print(`\ttype=${fctxt.type}`);
- print(`\turl=${fctxt.url}`);
- print(`\tdocOrigin=${fctxt.getDocOrigin()}`);
+ console.info(`Mismatch with reference results at ${i}:`);
+ console.info(`\tExpected ${expected[i]}, got ${r}:`);
+ console.info(`\ttype=${fctxt.type}`);
+ console.info(`\turl=${fctxt.url}`);
+ console.info(`\tdocOrigin=${fctxt.getDocOrigin()}`);
}
if ( r !== 1 ) {
if ( this.hasQuery(fctxt) ) {
@@ -4564,7 +4554,7 @@ FilterContainer.prototype.benchmark = async function(requests, options = {}) {
);
}
const s = output.join('\n');
- print(s);
+ console.info(s);
return s;
};
@@ -4576,9 +4566,9 @@ FilterContainer.prototype.test = async function(docURL, type, url) {
fctxt.setType(type);
fctxt.setURL(url);
const r = this.matchRequest(fctxt);
- console.log(`${r}`);
+ console.info(`${r}`);
if ( r !== 0 ) {
- console.log(this.toLogData());
+ console.info(this.toLogData());
}
};
@@ -4643,7 +4633,7 @@ FilterContainer.prototype.bucketHistogram = function() {
results.sort((a, b) => {
return b.size - a.size;
});
- console.log(results);
+ console.info(results);
};
/*******************************************************************************
@@ -4733,7 +4723,7 @@ FilterContainer.prototype.filterClassHistogram = function() {
const results = Array.from(filterClassDetails.values()).sort((a, b) => {
return b.count - a.count;
});
- console.log(results);
+ console.info(results);
};
/******************************************************************************/
@@ -4772,14 +4762,12 @@ FilterContainer.prototype.tokenHistograms = async function(requests) {
hitTokenMap.delete(token);
}
const tophits = Array.from(hitTokenMap).sort(customSort).slice(0, 100);
- console.log('Misses:', JSON.stringify(topmisses));
- console.log('Hits:', JSON.stringify(tophits));
+ console.info('Misses:', JSON.stringify(topmisses));
+ console.info('Hits:', JSON.stringify(tophits));
};
/******************************************************************************/
const staticNetFilteringEngine = new FilterContainer();
-/******************************************************************************/
-
-export { staticNetFilteringEngine };
+export default staticNetFilteringEngine;
diff --git a/src/js/storage.js b/src/js/storage.js
index 5ca65a30d..0bf1b392d 100644
--- a/src/js/storage.js
+++ b/src/js/storage.js
@@ -26,12 +26,24 @@
import '../lib/publicsuffixlist/publicsuffixlist.js';
import '../lib/punycode.js';
+import cosmeticFilteringEngine from './cosmetic-filtering.js';
import globals from './globals.js';
+import io from './assets.js';
+import logger from './logger.js';
+import lz4Codec from './lz4.js';
+import staticExtFilteringEngine from './static-ext-filtering.js';
+import staticFilteringReverseLookup from './reverselookup.js';
+import staticNetFilteringEngine from './static-net-filtering.js';
+import µb from './background.js';
import { hostnameFromURI } from './uri-utils.js';
-import { sparseBase64 } from './base64-custom.js';
import { LineIterator } from './text-iterators.js';
+import { permanentFirewall } from './dynamic-net-filtering.js';
+import { permanentSwitches } from './hnswitches.js';
+import { permanentURLFiltering } from './url-net-filtering.js';
+import { redirectEngine } from './redirect-engine.js';
+import { sparseBase64 } from './base64-custom.js';
import { StaticFilteringParser } from './static-filtering-parser.js';
-import µBlock from './background.js';
+import { ubolog, ubologSet } from './console.js';
import {
CompiledListReader,
@@ -40,7 +52,7 @@ import {
/******************************************************************************/
-µBlock.getBytesInUse = async function() {
+µb.getBytesInUse = async function() {
const promises = [];
let bytesInUse;
@@ -71,17 +83,16 @@ import {
if ( results.length > 1 && results[1] instanceof Object ) {
processCount(results[1].usage);
}
- µBlock.storageUsed = bytesInUse;
+ µb.storageUsed = bytesInUse;
return bytesInUse;
};
/******************************************************************************/
-µBlock.saveLocalSettings = (( ) => {
+µb.saveLocalSettings = (( ) => {
const saveAfter = 4 * 60 * 1000;
const onTimeout = ( ) => {
- const µb = µBlock;
if ( µb.localSettingsLastModified > µb.localSettingsLastSaved ) {
µb.saveLocalSettings();
}
@@ -98,7 +109,7 @@ import {
/******************************************************************************/
-µBlock.loadUserSettings = async function() {
+µb.loadUserSettings = async function() {
const usDefault = this.userSettingsDefault;
const results = await Promise.all([
@@ -126,7 +137,7 @@ import {
return usUser;
};
-µBlock.saveUserSettings = function() {
+µb.saveUserSettings = function() {
const toSave = this.getModifiedSettings(
this.userSettings,
this.userSettingsDefault
@@ -154,7 +165,7 @@ import {
// Admin hidden settings have precedence over user hidden settings.
-µBlock.loadHiddenSettings = async function() {
+µb.loadHiddenSettings = async function() {
const hsDefault = this.hiddenSettingsDefault;
const hsAdmin = this.hiddenSettingsAdmin;
const hsUser = this.hiddenSettings;
@@ -186,7 +197,7 @@ import {
hsDefault[name] = hsAdmin[name] = hsUser[name] = value;
}
}
- µBlock.noDashboard = disableDashboard === true;
+ µb.noDashboard = disableDashboard === true;
if ( Array.isArray(disabledPopupPanelParts) ) {
const partNameToBit = new Map([
[ 'globalStats', 0b00010 ],
@@ -230,7 +241,7 @@ import {
// This way the new default values in the future will properly apply for
// those which were not modified by the user.
-µBlock.saveHiddenSettings = function() {
+µb.saveHiddenSettings = function() {
vAPI.storage.set({
hiddenSettings: this.getModifiedSettings(
this.hiddenSettings,
@@ -240,8 +251,8 @@ import {
};
self.addEventListener('hiddenSettingsChanged', ( ) => {
- const µbhs = µBlock.hiddenSettings;
- self.log.verbosity = µbhs.consoleLogLevel;
+ const µbhs = µb.hiddenSettings;
+ ubologSet(µbhs.consoleLogLevel === 'info');
vAPI.net.setOptions({
cnameIgnoreList: µbhs.cnameIgnoreList,
cnameIgnore1stParty: µbhs.cnameIgnore1stParty,
@@ -255,7 +266,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
/******************************************************************************/
-µBlock.hiddenSettingsFromString = function(raw) {
+µb.hiddenSettingsFromString = function(raw) {
const out = Object.assign({}, this.hiddenSettingsDefault);
const lineIter = new LineIterator(raw);
while ( lineIter.eot() === false ) {
@@ -273,7 +284,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
return out;
};
-µBlock.hiddenSettingValueFromString = function(name, value) {
+µb.hiddenSettingValueFromString = function(name, value) {
if ( typeof name !== 'string' || typeof value !== 'string' ) { return; }
const hsDefault = this.hiddenSettingsDefault;
if ( hsDefault.hasOwnProperty(name) === false ) { return; }
@@ -305,7 +316,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
return r;
};
-µBlock.stringFromHiddenSettings = function() {
+µb.stringFromHiddenSettings = function() {
const out = [];
for ( const key of Object.keys(this.hiddenSettings).sort() ) {
out.push(key + ' ' + this.hiddenSettings[key]);
@@ -315,31 +326,31 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
/******************************************************************************/
-µBlock.savePermanentFirewallRules = function() {
+µb.savePermanentFirewallRules = function() {
vAPI.storage.set({
- dynamicFilteringString: this.permanentFirewall.toString()
+ dynamicFilteringString: permanentFirewall.toString()
});
};
/******************************************************************************/
-µBlock.savePermanentURLFilteringRules = function() {
+µb.savePermanentURLFilteringRules = function() {
vAPI.storage.set({
- urlFilteringString: this.permanentURLFiltering.toString()
+ urlFilteringString: permanentURLFiltering.toString()
});
};
/******************************************************************************/
-µBlock.saveHostnameSwitches = function() {
+µb.saveHostnameSwitches = function() {
vAPI.storage.set({
- hostnameSwitchesString: this.permanentSwitches.toString()
+ hostnameSwitchesString: permanentSwitches.toString()
});
};
/******************************************************************************/
-µBlock.saveWhitelist = function() {
+µb.saveWhitelist = function() {
vAPI.storage.set({
netWhitelist: this.arrayFromWhitelist(this.netWhitelist)
});
@@ -348,7 +359,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
/******************************************************************************/
-µBlock.loadSelectedFilterLists = async function() {
+µb.loadSelectedFilterLists = async function() {
const bin = await vAPI.storage.get('selectedFilterLists');
if ( bin instanceof Object && Array.isArray(bin.selectedFilterLists) ) {
this.selectedFilterLists = bin.selectedFilterLists;
@@ -357,11 +368,11 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
// https://github.com/gorhill/uBlock/issues/747
// Select default filter lists if first-time launch.
- const lists = await this.assets.metadata();
+ const lists = await io.metadata();
this.saveSelectedFilterLists(this.autoSelectRegionalFilterLists(lists));
};
-µBlock.saveSelectedFilterLists = function(newKeys, append = false) {
+µb.saveSelectedFilterLists = function(newKeys, append = false) {
const oldKeys = this.selectedFilterLists.slice();
if ( append ) {
newKeys = newKeys.concat(oldKeys);
@@ -380,7 +391,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
/******************************************************************************/
-µBlock.applyFilterListSelection = function(details) {
+µb.applyFilterListSelection = function(details) {
let selectedListKeySet = new Set(this.selectedFilterLists);
let importedLists = this.userSettings.importedLists.slice();
@@ -458,7 +469,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
/******************************************************************************/
-µBlock.listKeysFromCustomFilterLists = function(raw) {
+µb.listKeysFromCustomFilterLists = function(raw) {
const urls = typeof raw === 'string'
? raw.trim().split(/[\n\r]+/)
: raw;
@@ -476,20 +487,20 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
/******************************************************************************/
-µBlock.saveUserFilters = function(content) {
+µb.saveUserFilters = function(content) {
// https://github.com/gorhill/uBlock/issues/1022
// Be sure to end with an empty line.
content = content.trim();
if ( content !== '' ) { content += '\n'; }
this.removeCompiledFilterList(this.userFiltersPath);
- return this.assets.put(this.userFiltersPath, content);
+ return io.put(this.userFiltersPath, content);
};
-µBlock.loadUserFilters = function() {
- return this.assets.get(this.userFiltersPath);
+µb.loadUserFilters = function() {
+ return io.get(this.userFiltersPath);
};
-µBlock.appendUserFilters = async function(filters, options) {
+µb.appendUserFilters = async function(filters, options) {
filters = filters.trim();
if ( filters.length === 0 ) { return; }
@@ -542,8 +553,8 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
const compiledFilters = this.compileFilters(filters, {
assetKey: this.userFiltersPath
});
- const snfe = this.staticNetFilteringEngine;
- const cfe = this.cosmeticFilteringEngine;
+ const snfe = staticNetFilteringEngine;
+ const cfe = cosmeticFilteringEngine;
const acceptedCount = snfe.acceptedCount + cfe.acceptedCount;
const discardedCount = snfe.discardedCount + cfe.discardedCount;
this.applyCompiledFilters(compiledFilters, true);
@@ -557,9 +568,9 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
entry.entryCount += deltaEntryCount;
entry.entryUsedCount += deltaEntryUsedCount;
vAPI.storage.set({ 'availableFilterLists': this.availableFilterLists });
- this.staticNetFilteringEngine.freeze();
- this.redirectEngine.freeze();
- this.staticExtFilteringEngine.freeze();
+ staticNetFilteringEngine.freeze();
+ redirectEngine.freeze();
+ staticExtFilteringEngine.freeze();
this.selfieManager.destroy();
// https://www.reddit.com/r/uBlockOrigin/comments/cj7g7m/
@@ -571,18 +582,18 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
vAPI.messaging.broadcast({ what: 'userFiltersUpdated' });
};
-µBlock.createUserFilters = function(details) {
+µb.createUserFilters = function(details) {
this.appendUserFilters(details.filters, details);
// https://github.com/gorhill/uBlock/issues/1786
if ( details.docURL === undefined ) { return; }
- this.cosmeticFilteringEngine.removeFromSelectorCache(
+ cosmeticFilteringEngine.removeFromSelectorCache(
hostnameFromURI(details.docURL)
);
};
/******************************************************************************/
-µBlock.autoSelectRegionalFilterLists = function(lists) {
+µb.autoSelectRegionalFilterLists = function(lists) {
const selectedListKeys = [ this.userFiltersPath ];
for ( const key in lists ) {
if ( lists.hasOwnProperty(key) === false ) { continue; }
@@ -601,7 +612,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
/******************************************************************************/
-µBlock.getAvailableLists = async function() {
+µb.getAvailableLists = async function() {
let oldAvailableLists = {},
newAvailableLists = {};
@@ -625,7 +636,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
title: '',
};
newAvailableLists[listKey] = entry;
- this.assets.registerAssetSource(listKey, entry);
+ io.registerAssetSource(listKey, entry);
}
// Convert a no longer existing stock list into an imported list.
@@ -645,7 +656,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
title: oldEntry.title || ''
};
newAvailableLists[listURL] = newEntry;
- this.assets.registerAssetSource(listURL, newEntry);
+ io.registerAssetSource(listURL, newEntry);
importedListKeys.push(listURL);
this.userSettings.importedLists.push(listURL.trim());
this.saveUserSettings();
@@ -654,8 +665,8 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
const promises = [
vAPI.storage.get('availableFilterLists'),
- this.assets.metadata(),
- this.badLists.size === 0 ? this.assets.get('ublock-badlists') : false,
+ io.metadata(),
+ this.badLists.size === 0 ? io.get('ublock-badlists') : false,
];
// Load previously saved available lists -- these contains data
@@ -731,7 +742,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
if ( newEntry.submitter !== 'user' ) { continue; }
if ( importedListKeys.indexOf(assetKey) !== -1 ) { continue; }
delete newAvailableLists[assetKey];
- this.assets.unregisterAssetSource(assetKey);
+ io.unregisterAssetSource(assetKey);
this.removeFilterList(assetKey);
}
@@ -740,17 +751,17 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
/******************************************************************************/
-µBlock.loadFilterLists = (( ) => {
+µb.loadFilterLists = (( ) => {
const loadedListKeys = [];
let loadingPromise;
let t0 = 0;
const onDone = function() {
- log.info(`loadFilterLists() took ${Date.now()-t0} ms`);
+ ubolog(`loadFilterLists() took ${Date.now()-t0} ms`);
- this.staticNetFilteringEngine.freeze();
- this.staticExtFilteringEngine.freeze();
- this.redirectEngine.freeze();
+ staticNetFilteringEngine.freeze();
+ staticExtFilteringEngine.freeze();
+ redirectEngine.freeze();
vAPI.net.unsuspend();
vAPI.storage.set({ 'availableFilterLists': this.availableFilterLists });
@@ -763,15 +774,15 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
});
this.selfieManager.destroy();
- this.lz4Codec.relinquish();
+ lz4Codec.relinquish();
this.compiledFormatChanged = false;
loadingPromise = undefined;
};
const applyCompiledFilters = function(assetKey, compiled) {
- const snfe = this.staticNetFilteringEngine;
- const sxfe = this.staticExtFilteringEngine;
+ const snfe = staticNetFilteringEngine;
+ const sxfe = staticExtFilteringEngine;
let acceptedCount = snfe.acceptedCount + sxfe.acceptedCount,
discardedCount = snfe.discardedCount + sxfe.discardedCount;
this.applyCompiledFilters(compiled, assetKey === this.userFiltersPath);
@@ -789,15 +800,15 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
this.availableFilterLists = lists;
vAPI.net.suspend();
- this.redirectEngine.reset();
- this.staticExtFilteringEngine.reset();
- this.staticNetFilteringEngine.reset();
+ redirectEngine.reset();
+ staticExtFilteringEngine.reset();
+ staticNetFilteringEngine.reset();
this.selfieManager.destroy();
- this.staticFilteringReverseLookup.resetLists();
+ staticFilteringReverseLookup.resetLists();
// We need to build a complete list of assets to pull first: this is
// because it *may* happens that some load operations are synchronous:
- // This happens for assets which do not exist, ot assets with no
+ // This happens for assets which do not exist, or assets with no
// content.
const toLoad = [];
for ( const assetKey in lists ) {
@@ -837,7 +848,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
/******************************************************************************/
-µBlock.getCompiledFilterList = async function(assetKey) {
+µb.getCompiledFilterList = async function(assetKey) {
const compiledPath = 'compiled/' + assetKey;
// https://github.com/uBlockOrigin/uBlock-issues/issues/1365
@@ -847,7 +858,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
this.compiledFormatChanged === false &&
this.badLists.has(assetKey) === false
) {
- const compiledDetails = await this.assets.get(compiledPath);
+ const compiledDetails = await io.get(compiledPath);
if (
parseInt(compiledDetails.content, 10) ===
this.systemSettings.compiledMagic
@@ -862,7 +873,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
return { assetKey, content: '' };
}
- const rawDetails = await this.assets.get(assetKey, { silent: true });
+ const rawDetails = await io.get(assetKey, { silent: true });
// Compiling an empty string results in an empty string.
if ( rawDetails.content === '' ) {
rawDetails.assetKey = assetKey;
@@ -878,7 +889,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
const compiledContent =
this.compileFilters(rawDetails.content, { assetKey });
- this.assets.put(compiledPath, compiledContent);
+ io.put(compiledPath, compiledContent);
return { assetKey, content: compiledContent };
};
@@ -892,7 +903,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
// the whole raw filter list to be held in memory just because we cut out
// the title as a substring.
-µBlock.extractFilterListMetadata = function(assetKey, raw) {
+µb.extractFilterListMetadata = function(assetKey, raw) {
const listEntry = this.availableFilterLists[assetKey];
if ( listEntry === undefined ) { return; }
// Metadata expected to be found at the top of content.
@@ -904,13 +915,13 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
const title = matches && matches[1].trim() || '';
if ( title !== '' && title !== listEntry.title ) {
listEntry.title = this.orphanizeString(title);
- this.assets.registerAssetSource(assetKey, { title });
+ io.registerAssetSource(assetKey, { title });
}
matches = head.match(/(?:^|\n)(?:!|# )[\t ]*Homepage[\t ]*:[\t ]*(https?:\/\/\S+)\s/i);
const supportURL = matches && matches[1] || '';
if ( supportURL !== '' && supportURL !== listEntry.supportURL ) {
listEntry.supportURL = this.orphanizeString(supportURL);
- this.assets.registerAssetSource(assetKey, { supportURL });
+ io.registerAssetSource(assetKey, { supportURL });
}
}
// Extract update frequency information
@@ -924,7 +935,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
updateAfter = Math.max(updateAfter, 1);
if ( updateAfter !== listEntry.updateAfter ) {
listEntry.updateAfter = updateAfter;
- this.assets.registerAssetSource(assetKey, { updateAfter });
+ io.registerAssetSource(assetKey, { updateAfter });
}
}
}
@@ -932,18 +943,18 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
/******************************************************************************/
-µBlock.removeCompiledFilterList = function(assetKey) {
- this.assets.remove('compiled/' + assetKey);
+µb.removeCompiledFilterList = function(assetKey) {
+ io.remove('compiled/' + assetKey);
};
-µBlock.removeFilterList = function(assetKey) {
+µb.removeFilterList = function(assetKey) {
this.removeCompiledFilterList(assetKey);
- this.assets.remove(assetKey);
+ io.remove(assetKey);
};
/******************************************************************************/
-µBlock.compileFilters = function(rawText, details = {}) {
+µb.compileFilters = function(rawText, details = {}) {
const writer = new CompiledListWriter();
// Populate the writer with information potentially useful to the
@@ -957,8 +968,6 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
// Useful references:
// https://adblockplus.org/en/filter-cheatsheet
// https://adblockplus.org/en/filters
- const staticNetFilteringEngine = this.staticNetFilteringEngine;
- const staticExtFilteringEngine = this.staticExtFilteringEngine;
const lineIter = new LineIterator(this.preparseDirectives.prune(rawText));
const parser = new StaticFilteringParser({ expertMode });
@@ -990,7 +999,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
}
if ( staticNetFilteringEngine.compile(parser, writer) ) { continue; }
if ( staticNetFilteringEngine.error !== undefined ) {
- this.logger.writeOne({
+ logger.writeOne({
realm: 'message',
type: 'error',
text: staticNetFilteringEngine.error
@@ -1013,11 +1022,11 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
// Added `firstparty` argument: to avoid discarding cosmetic filters when
// applying 1st-party filters.
-µBlock.applyCompiledFilters = function(rawText, firstparty) {
+µb.applyCompiledFilters = function(rawText, firstparty) {
if ( rawText === '' ) { return; }
const reader = new CompiledListReader(rawText);
- this.staticNetFilteringEngine.fromCompiled(reader);
- this.staticExtFilteringEngine.fromCompiledContent(reader, {
+ staticNetFilteringEngine.fromCompiled(reader);
+ staticExtFilteringEngine.fromCompiledContent(reader, {
skipGenericCosmetic: this.userSettings.ignoreGenericCosmeticFilters,
skipCosmetic: !firstparty && !this.userSettings.parseAllABPHideFilters
});
@@ -1027,7 +1036,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
// https://github.com/AdguardTeam/AdguardBrowserExtension/issues/917
-µBlock.preparseDirectives = {
+µb.preparseDirectives = {
// This method returns an array of indices, corresponding to position in
// the content string which should alternatively be parsed and discarded.
split: function(content) {
@@ -1140,19 +1149,19 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
/******************************************************************************/
-µBlock.loadRedirectResources = async function() {
+µb.loadRedirectResources = async function() {
try {
- const success = await this.redirectEngine.resourcesFromSelfie();
+ const success = await redirectEngine.resourcesFromSelfie();
if ( success === true ) { return true; }
const fetchPromises = [
- this.redirectEngine.loadBuiltinResources()
+ redirectEngine.loadBuiltinResources()
];
const userResourcesLocation = this.hiddenSettings.userResourcesLocation;
if ( userResourcesLocation !== 'unset' ) {
for ( const url of userResourcesLocation.split(/\s+/) ) {
- fetchPromises.push(this.assets.fetchText(url));
+ fetchPromises.push(io.fetchText(url));
}
}
@@ -1172,10 +1181,10 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
content += '\n\n' + result.content;
}
- this.redirectEngine.resourcesFromString(content);
- this.redirectEngine.selfieFromResources();
+ redirectEngine.resourcesFromString(content);
+ redirectEngine.selfieFromResources();
} catch(ex) {
- log.info(ex);
+ ubolog(ex);
return false;
}
return true;
@@ -1183,31 +1192,31 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
/******************************************************************************/
-µBlock.loadPublicSuffixList = async function() {
+µb.loadPublicSuffixList = async function() {
const psl = globals.publicSuffixList;
if ( this.hiddenSettings.disableWebAssembly !== true ) {
psl.enableWASM('/lib/publicsuffixlist');
}
try {
- const result = await this.assets.get(`compiled/${this.pslAssetKey}`);
+ const result = await io.get(`compiled/${this.pslAssetKey}`);
if ( psl.fromSelfie(result.content, sparseBase64) ) {
return;
}
} catch (ex) {
- log.info(ex);
+ ubolog(ex);
}
- const result = await this.assets.get(this.pslAssetKey);
+ const result = await io.get(this.pslAssetKey);
if ( result.content !== '' ) {
this.compilePublicSuffixList(result.content);
}
};
-µBlock.compilePublicSuffixList = function(content) {
+µb.compilePublicSuffixList = function(content) {
const psl = globals.publicSuffixList;
psl.parse(content, globals.punycode.toASCII);
- this.assets.put(`compiled/${this.pslAssetKey}`, psl.toSelfie(sparseBase64));
+ io.put(`compiled/${this.pslAssetKey}`, psl.toSelfie(sparseBase64));
};
/******************************************************************************/
@@ -1216,8 +1225,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
// be generated if the user doesn't change his filter lists selection for
// some set time.
-µBlock.selfieManager = (( ) => {
- const µb = µBlock;
+µb.selfieManager = (( ) => {
let createTimer;
let destroyTimer;
@@ -1227,28 +1235,27 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
const create = async function() {
await Promise.all([
- µb.assets.put(
+ io.put(
'selfie/main',
JSON.stringify({
magic: µb.systemSettings.selfieMagic,
availableFilterLists: µb.availableFilterLists,
})
),
- µb.redirectEngine.toSelfie('selfie/redirectEngine'),
- µb.staticExtFilteringEngine.toSelfie(
+ redirectEngine.toSelfie('selfie/redirectEngine'),
+ staticExtFilteringEngine.toSelfie(
'selfie/staticExtFilteringEngine'
),
- µb.staticNetFilteringEngine.toSelfie(
- µb.assets,
+ staticNetFilteringEngine.toSelfie(io,
'selfie/staticNetFilteringEngine'
),
]);
- µb.lz4Codec.relinquish();
+ lz4Codec.relinquish();
µb.selfieIsInvalid = false;
};
const loadMain = async function() {
- const details = await µb.assets.get('selfie/main');
+ const details = await io.get('selfie/main');
if (
details instanceof Object === false ||
typeof details.content !== 'string' ||
@@ -1278,12 +1285,11 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
try {
const results = await Promise.all([
loadMain(),
- µb.redirectEngine.fromSelfie('selfie/redirectEngine'),
- µb.staticExtFilteringEngine.fromSelfie(
+ redirectEngine.fromSelfie('selfie/redirectEngine'),
+ staticExtFilteringEngine.fromSelfie(
'selfie/staticExtFilteringEngine'
),
- µb.staticNetFilteringEngine.fromSelfie(
- µb.assets,
+ staticNetFilteringEngine.fromSelfie(io,
'selfie/staticNetFilteringEngine'
),
]);
@@ -1292,14 +1298,14 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
}
}
catch (reason) {
- log.info(reason);
+ ubolog(reason);
}
destroy();
return false;
};
const destroy = function() {
- µb.assets.remove(/^selfie\//);
+ io.remove(/^selfie\//);
µb.selfieIsInvalid = true;
createTimer = vAPI.setTimeout(( ) => {
createTimer = undefined;
@@ -1335,7 +1341,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
// necessarily present, i.e. administrators may removed entries which
// values are left to the user's choice.
-µBlock.restoreAdminSettings = async function() {
+µb.restoreAdminSettings = async function() {
let toOverwrite = {};
let data;
try {
@@ -1368,7 +1374,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
typeof data.assetsBootstrapLocation === 'string' &&
data.assetsBootstrapLocation !== ''
) {
- µBlock.assetsBootstrapLocation = data.assetsBootstrapLocation;
+ µb.assetsBootstrapLocation = data.assetsBootstrapLocation;
}
if ( typeof data.userSettings === 'object' ) {
@@ -1409,7 +1415,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
Array.isArray(toOverwrite.trustedSiteDirectives) &&
toOverwrite.trustedSiteDirectives.length !== 0
) {
- µBlock.netWhitelistDefault = toOverwrite.trustedSiteDirectives.slice();
+ µb.netWhitelistDefault = toOverwrite.trustedSiteDirectives.slice();
bin.netWhitelist = toOverwrite.trustedSiteDirectives.slice();
binNotEmpty = true;
} else if ( Array.isArray(data.whitelist) ) {
@@ -1457,7 +1463,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
// https://github.com/gorhill/uBlock/issues/3210
// Support ability to auto-enable a filter list based on user agent.
-µBlock.listMatchesEnvironment = function(details) {
+µb.listMatchesEnvironment = function(details) {
// Matches language?
if ( typeof details.lang === 'string' ) {
let re = this.listMatchesEnvironment.reLang;
@@ -1480,7 +1486,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
/******************************************************************************/
-µBlock.scheduleAssetUpdater = (( ) => {
+µb.scheduleAssetUpdater = (( ) => {
let timer, next = 0;
return function(updateDelay) {
@@ -1502,7 +1508,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
timer = vAPI.setTimeout(( ) => {
timer = undefined;
next = 0;
- this.assets.updateStart({
+ io.updateStart({
delay: this.hiddenSettings.autoUpdateAssetFetchPeriod * 1000 ||
120000,
auto: true,
@@ -1513,7 +1519,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
/******************************************************************************/
-µBlock.assetObserver = function(topic, details) {
+µb.assetObserver = function(topic, details) {
// Do not update filter list if not in use.
// Also, ignore really bad lists, i.e. those which should not even be
// fetched from a remote server.
@@ -1544,7 +1550,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
details.content
);
if ( this.badLists.has(details.assetKey) === false ) {
- this.assets.put(
+ io.put(
'compiled/' + details.assetKey,
this.compileFilters(details.content, {
assetKey: details.assetKey
@@ -1592,7 +1598,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
this.hiddenSettings.userResourcesLocation !== 'unset' ||
vAPI.webextFlavor.soup.has('devbuild')
) {
- this.redirectEngine.invalidateResourcesSelfie();
+ redirectEngine.invalidateResourcesSelfie();
}
this.loadFilterLists();
}
diff --git a/src/js/tab.js b/src/js/tab.js
index 046df4ddf..45ee4ab02 100644
--- a/src/js/tab.js
+++ b/src/js/tab.js
@@ -23,6 +23,16 @@
/******************************************************************************/
+import contextMenu from './contextmenu.js';
+import logger from './logger.js';
+import scriptletFilteringEngine from './scriptlet-filtering.js';
+import staticNetFilteringEngine from './static-net-filtering.js';
+import µb from './background.js';
+import { PageStore } from './pagestore.js';
+import { sessionFirewall } from './dynamic-net-filtering.js';
+import { sessionSwitches } from './hnswitches.js';
+import { sessionURLFiltering } from './url-net-filtering.js';
+
import {
domainFromHostname,
hostnameFromURI,
@@ -30,8 +40,6 @@ import {
originFromURI,
} from './uri-utils.js';
-import µBlock from './background.js';
-
/******************************************************************************/
/******************************************************************************/
@@ -44,7 +52,7 @@ import µBlock from './background.js';
// hostname. This way, for a specific scheme you can create scope with
// rules which will apply only to that scheme.
-µBlock.normalizeTabURL = (( ) => {
+µb.normalizeTabURL = (( ) => {
const tabURLNormalizer = new URL('about:blank');
return (tabId, tabURL) => {
@@ -93,9 +101,7 @@ import µBlock from './background.js';
// c: close opener
// d: close target
-µBlock.onPopupUpdated = (( ) => {
- const µb = µBlock;
-
+const onPopupUpdated = (( ) => {
// https://github.com/gorhill/uBlock/commit/1d448b85b2931412508aa01bf899e0b6f0033626#commitcomment-14944764
// See if two URLs are different, disregarding scheme -- because the
// scheme can be unilaterally changed by the browser.
@@ -162,13 +168,13 @@ import µBlock from './background.js';
// popunders.
if (
popupType === 'popup' &&
- µb.sessionSwitches.evaluateZ(
+ sessionSwitches.evaluateZ(
'no-popups',
fctxt.getTabHostname()
)
) {
fctxt.filter = {
- raw: 'no-popups: ' + µb.sessionSwitches.z + ' true',
+ raw: 'no-popups: ' + sessionSwitches.z + ' true',
result: 1,
source: 'switch'
};
@@ -178,16 +184,16 @@ import µBlock from './background.js';
// https://github.com/gorhill/uBlock/issues/581
// Take into account popup-specific rules in dynamic URL
// filtering, OR generic allow rules.
- let result = µb.sessionURLFiltering.evaluateZ(
+ let result = sessionURLFiltering.evaluateZ(
fctxt.getTabHostname(),
targetURL,
popupType
);
if (
- result === 1 && µb.sessionURLFiltering.type === popupType ||
+ result === 1 && sessionURLFiltering.type === popupType ||
result === 2
) {
- fctxt.filter = µb.sessionURLFiltering.toLogData();
+ fctxt.filter = sessionURLFiltering.toLogData();
return result;
}
@@ -195,21 +201,21 @@ import µBlock from './background.js';
// Take into account `allow` rules in dynamic filtering: `block`
// rules are ignored, as block rules are not meant to block
// specific types like `popup` (just like with static filters).
- result = µb.sessionFirewall.evaluateCellZY(
+ result = sessionFirewall.evaluateCellZY(
fctxt.getTabHostname(),
fctxt.getHostname(),
popupType
);
if ( result === 2 ) {
- fctxt.filter = µb.sessionFirewall.toLogData();
+ fctxt.filter = sessionFirewall.toLogData();
return 2;
}
}
fctxt.type = popupType;
- const result = µb.staticNetFilteringEngine.matchRequest(fctxt, 0b0001);
+ const result = staticNetFilteringEngine.matchRequest(fctxt, 0b0001);
if ( result !== 0 ) {
- fctxt.filter = µb.staticNetFilteringEngine.toLogData();
+ fctxt.filter = staticNetFilteringEngine.toLogData();
return result;
}
@@ -225,11 +231,11 @@ import µBlock from './background.js';
if (
fctxt.filter === undefined ||
fctxt.filter !== 'static' ||
- fctxt.filter.token === µb.staticNetFilteringEngine.noTokenHash
+ fctxt.filter.token === staticNetFilteringEngine.noTokenHash
) {
return 0;
}
- if ( fctxt.filter.token === µb.staticNetFilteringEngine.dotTokenHash ) {
+ if ( fctxt.filter.token === staticNetFilteringEngine.dotTokenHash ) {
return result;
}
const re = new RegExp(fctxt.filter.regex, 'i');
@@ -357,7 +363,7 @@ import µBlock from './background.js';
// Log only for when there was a hit against an actual filter (allow or block).
// https://github.com/gorhill/uBlock/issues/2776
- if ( µb.logger.enabled ) {
+ if ( logger.enabled ) {
fctxt.setRealm('network').setType(popupType);
if ( popupType === 'popup' ) {
fctxt.setURL(targetURL)
@@ -463,8 +469,7 @@ housekeep itself.
*/
-µBlock.tabContextManager = (( ) => {
- const µb = µBlock;
+µb.tabContextManager = (( ) => {
const tabContexts = new Map();
// https://github.com/chrisaljoudi/uBlock/issues/1001
@@ -524,7 +529,7 @@ housekeep itself.
if ( targetTabId === candidate.opener.tabId ) {
candidate.opener.popunder = true;
}
- const result = await µb.onPopupUpdated(tabId, candidate.opener);
+ const result = onPopupUpdated(tabId, candidate.opener);
if ( result === true ) {
candidate.destroy();
} else {
@@ -864,20 +869,20 @@ vAPI.Tabs = class extends vAPI.Tabs {
super.onActivated(details);
if ( vAPI.isBehindTheSceneTabId(details.tabId) ) { return; }
// https://github.com/uBlockOrigin/uBlock-issues/issues/680
- µBlock.updateToolbarIcon(details.tabId);
- µBlock.contextMenu.update(details.tabId);
+ µb.updateToolbarIcon(details.tabId);
+ contextMenu.update(details.tabId);
}
onClosed(tabId) {
super.onClosed(tabId);
if ( vAPI.isBehindTheSceneTabId(tabId) ) { return; }
- µBlock.unbindTabFromPageStore(tabId);
- µBlock.contextMenu.update();
+ µb.unbindTabFromPageStore(tabId);
+ contextMenu.update();
}
onCreated(details) {
super.onCreated(details);
- µBlock.tabContextManager.onTabCreated(details);
+ µb.tabContextManager.onTabCreated(details);
}
// When the DOM content of root frame is loaded, this means the tab
@@ -895,7 +900,6 @@ vAPI.Tabs = class extends vAPI.Tabs {
// is not available at this point.
onNavigation(details) {
super.onNavigation(details);
- const µb = µBlock;
const { frameId, tabId, url } = details;
if ( frameId === 0 ) {
µb.tabContextManager.commit(tabId, url);
@@ -912,7 +916,7 @@ vAPI.Tabs = class extends vAPI.Tabs {
isNetworkURI(url) &&
pageStore.getNetFilteringSwitch()
) {
- µb.scriptletFilteringEngine.injectNow(details);
+ scriptletFilteringEngine.injectNow(details);
}
}
@@ -924,8 +928,8 @@ vAPI.Tabs = class extends vAPI.Tabs {
super.onUpdated(tabId, changeInfo, tab);
if ( !tab.url || tab.url === '' ) { return; }
if ( !changeInfo.url ) { return; }
- µBlock.tabContextManager.commit(tabId, changeInfo.url);
- µBlock.bindTabToPageStore(tabId, 'tabUpdated', tab);
+ µb.tabContextManager.commit(tabId, changeInfo.url);
+ µb.bindTabToPageStore(tabId, 'tabUpdated', tab);
}
};
@@ -936,7 +940,7 @@ vAPI.tabs = new vAPI.Tabs();
// Create an entry for the tab if it doesn't exist.
-µBlock.bindTabToPageStore = function(tabId, context, details = undefined) {
+µb.bindTabToPageStore = function(tabId, context, details = undefined) {
this.updateToolbarIcon(tabId, 0b111);
// Do not create a page store for URLs which are of no interests
@@ -950,7 +954,7 @@ vAPI.tabs = new vAPI.Tabs();
// Tab is not bound
if ( pageStore === undefined ) {
- pageStore = this.PageStore.factory(tabId, details);
+ pageStore = PageStore.factory(tabId, details);
this.pageStores.set(tabId, pageStore);
this.pageStoresToken = Date.now();
return pageStore;
@@ -981,7 +985,7 @@ vAPI.tabs = new vAPI.Tabs();
/******************************************************************************/
-µBlock.unbindTabFromPageStore = function(tabId) {
+µb.unbindTabFromPageStore = function(tabId) {
const pageStore = this.pageStores.get(tabId);
if ( pageStore === undefined ) { return; }
pageStore.dispose();
@@ -991,11 +995,11 @@ vAPI.tabs = new vAPI.Tabs();
/******************************************************************************/
-µBlock.pageStoreFromTabId = function(tabId) {
+µb.pageStoreFromTabId = function(tabId) {
return this.pageStores.get(tabId) || null;
};
-µBlock.mustPageStoreFromTabId = function(tabId) {
+µb.mustPageStoreFromTabId = function(tabId) {
return this.pageStores.get(tabId) || this.pageStores.get(vAPI.noTabId);
};
@@ -1008,19 +1012,19 @@ vAPI.tabs = new vAPI.Tabs();
// the document context (if present) of the network request.
{
- const NoPageStore = class extends µBlock.PageStore {
+ const NoPageStore = class extends PageStore {
getNetFilteringSwitch(fctxt) {
if ( fctxt ) {
const docOrigin = fctxt.getDocOrigin();
if ( docOrigin ) {
- return µBlock.getNetFilteringSwitch(docOrigin);
+ return µb.getNetFilteringSwitch(docOrigin);
}
}
return super.getNetFilteringSwitch();
}
};
const pageStore = new NoPageStore(vAPI.noTabId);
- µBlock.pageStores.set(pageStore.tabId, pageStore);
+ µb.pageStores.set(pageStore.tabId, pageStore);
pageStore.title = vAPI.i18n('logBehindTheScene');
}
@@ -1028,8 +1032,7 @@ vAPI.tabs = new vAPI.Tabs();
// Update visual of extension icon.
-µBlock.updateToolbarIcon = (( ) => {
- const µb = µBlock;
+µb.updateToolbarIcon = (( ) => {
const tabIdToDetails = new Map();
const computeBadgeColor = (bits) => {
@@ -1118,11 +1121,11 @@ vAPI.tabs = new vAPI.Tabs();
const checkTab = async tabId => {
const tab = await vAPI.tabs.get(tabId);
if ( tab instanceof Object && tab.discarded !== true ) { return; }
- µBlock.unbindTabFromPageStore(tabId);
+ µb.unbindTabFromPageStore(tabId);
};
const pageStoreJanitor = function() {
- const tabIds = Array.from(µBlock.pageStores.keys()).sort();
+ const tabIds = Array.from(µb.pageStores.keys()).sort();
if ( pageStoreJanitorSampleAt >= tabIds.length ) {
pageStoreJanitorSampleAt = 0;
}
diff --git a/src/js/text-encode.js b/src/js/text-encode.js
index 3eb6dc166..302df2cc4 100644
--- a/src/js/text-encode.js
+++ b/src/js/text-encode.js
@@ -23,17 +23,17 @@
/******************************************************************************/
-import µBlock from './background.js';
+import µb from './background.js';
/******************************************************************************/
-µBlock.textEncode = (function() {
+const textEncode = (( ) => {
- if ( µBlock.canFilterResponseData !== true ) { return; }
+ if ( µb.canFilterResponseData !== true ) { return; }
// charset aliases extracted from:
// https://github.com/inexorabletash/text-encoding/blob/b4e5bc26e26e51f56e3daa9f13138c79f49d3c34/lib/encoding.js#L342
- var normalizedCharset = new Map([
+ const normalizedCharset = new Map([
[ 'utf8', 'utf-8' ],
[ 'unicode-1-1-utf-8', 'utf-8' ],
[ 'utf-8', 'utf-8' ],
@@ -66,7 +66,7 @@ import µBlock from './background.js';
]);
// http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1250.TXT
- var cp1250_range0 = new Uint8Array([
+ const cp1250_range0 = new Uint8Array([
/* 0x0100 */ 0x00, 0x00, 0xC3, 0xE3, 0xA5, 0xB9, 0xC6, 0xE6,
/* 0x0108 */ 0x00, 0x00, 0x00, 0x00, 0xC8, 0xE8, 0xCF, 0xEF,
/* 0x0110 */ 0xD0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -86,7 +86,7 @@ import µBlock from './background.js';
]);
// http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT
- var cp1251_range0 = new Uint8Array([
+ const cp1251_range0 = new Uint8Array([
/* 0x0400 */ 0x00, 0xA8, 0x80, 0x81, 0xAA, 0xBD, 0xB2, 0xAF,
/* 0x0408 */ 0xA3, 0x8A, 0x8C, 0x8E, 0x8D, 0x00, 0xA1, 0x8F,
/* 0x0410 */ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
@@ -109,7 +109,7 @@ import µBlock from './background.js';
]);
// https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT
- var cp1252_range0 = new Uint8Array([
+ const cp1252_range0 = new Uint8Array([
/* 0x0150 */ 0x00, 0x00, 0x8C, 0x9C, 0x00, 0x00, 0x00, 0x00,
/* 0x0158 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x0160 */ 0x8A, 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -118,7 +118,7 @@ import µBlock from './background.js';
/* 0x0178 */ 0x9F, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x9E, 0x00
]);
- var cp125x_range0 = new Uint8Array([
+ const cp125x_range0 = new Uint8Array([
/* 0x2010 */ 0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00,
/* 0x2018 */ 0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00,
/* 0x2020 */ 0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00,
@@ -127,9 +127,9 @@ import µBlock from './background.js';
/* 0x2038 */ 0x00, 0x8B, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x00
]);
- var encoders = {
+ const encoders = {
'windows-1250': function(buf) {
- var i = 0, n = buf.byteLength, o = 0, c;
+ let i = 0, n = buf.byteLength, o = 0, c;
while ( i < n ) {
c = buf[i++];
if ( c < 0x80 ) {
@@ -174,7 +174,7 @@ import µBlock from './background.js';
return buf.slice(0, o);
},
'windows-1251': function(buf) {
- var i = 0, n = buf.byteLength, o = 0, c;
+ let i = 0, n = buf.byteLength, o = 0, c;
while ( i < n ) {
c = buf[i++];
if ( c < 0x80 ) {
@@ -211,7 +211,7 @@ import µBlock from './background.js';
return buf.slice(0, o);
},
'windows-1252': function(buf) {
- var i = 0, n = buf.byteLength, o = 0, c;
+ let i = 0, n = buf.byteLength, o = 0, c;
while ( i < n ) {
c = buf[i++];
if ( c < 0x80 ) {
@@ -267,3 +267,9 @@ import µBlock from './background.js';
}
};
})();
+
+/******************************************************************************/
+
+export default textEncode;
+
+/******************************************************************************/
diff --git a/src/js/traffic.js b/src/js/traffic.js
index d76805ca3..7dbec5677 100644
--- a/src/js/traffic.js
+++ b/src/js/traffic.js
@@ -23,13 +23,22 @@
/******************************************************************************/
+import htmlFilteringEngine from './html-filtering.js';
+import httpheaderFilteringEngine from './httpheader-filtering.js';
+import logger from './logger.js';
+import scriptletFilteringEngine from './scriptlet-filtering.js';
+import staticNetFilteringEngine from './static-net-filtering.js';
+import textEncode from './text-encode.js';
+import µb from './background.js';
+import { sessionFirewall } from './dynamic-net-filtering.js';
+import { sessionSwitches } from './hnswitches.js';
+import { sessionURLFiltering } from './url-net-filtering.js';
+
import {
entityFromDomain,
isNetworkURI,
} from './uri-utils.js';
-import µBlock from './background.js';
-
/******************************************************************************/
// Platform-specific behavior.
@@ -55,7 +64,7 @@ const supportsFloc = document.interestCohort instanceof Function;
// Intercept and filter web requests.
const onBeforeRequest = function(details) {
- const fctxt = µBlock.filteringContext.fromWebrequestDetails(details);
+ const fctxt = µb.filteringContext.fromWebrequestDetails(details);
// Special handling for root document.
// https://github.com/chrisaljoudi/uBlock/issues/1001
@@ -72,7 +81,6 @@ const onBeforeRequest = function(details) {
}
// Lookup the page store associated with this tab id.
- const µb = µBlock;
let pageStore = µb.pageStoreFromTabId(tabId);
if ( pageStore === null ) {
const tabContext = µb.tabContextManager.mustLookup(tabId);
@@ -87,7 +95,7 @@ const onBeforeRequest = function(details) {
pageStore.journalAddRequest(fctxt, result);
- if ( µb.logger.enabled ) {
+ if ( logger.enabled ) {
fctxt.setRealm('network').toLogger();
}
@@ -121,7 +129,6 @@ const onBeforeRequest = function(details) {
/******************************************************************************/
const onBeforeRootFrameRequest = function(fctxt) {
- const µb = µBlock;
const requestURL = fctxt.url;
// Special handling for root document.
@@ -129,7 +136,6 @@ const onBeforeRootFrameRequest = function(fctxt) {
// This must be executed regardless of whether the request is
// behind-the-scene
const requestHostname = fctxt.getHostname();
- const loggerEnabled = µb.logger.enabled;
let result = 0;
let logData;
@@ -137,7 +143,7 @@ const onBeforeRootFrameRequest = function(fctxt) {
const trusted = µb.getNetFilteringSwitch(requestURL) === false;
if ( trusted ) {
result = 2;
- if ( loggerEnabled ) {
+ if ( logger.enabled ) {
logData = { engine: 'u', result: 2, raw: 'whitelisted' };
}
}
@@ -145,14 +151,14 @@ const onBeforeRootFrameRequest = function(fctxt) {
// Permanently unrestricted?
if (
result === 0 &&
- µb.sessionSwitches.evaluateZ('no-strict-blocking', requestHostname)
+ sessionSwitches.evaluateZ('no-strict-blocking', requestHostname)
) {
result = 2;
- if ( loggerEnabled ) {
+ if ( logger.enabled ) {
logData = {
engine: 'u',
result: 2,
- raw: `no-strict-blocking: ${µb.sessionSwitches.z} true`
+ raw: `no-strict-blocking: ${sessionSwitches.z} true`
};
}
}
@@ -160,7 +166,7 @@ const onBeforeRootFrameRequest = function(fctxt) {
// Temporarily whitelisted?
if ( result === 0 && strictBlockBypasser.isBypassed(requestHostname) ) {
result = 2;
- if ( loggerEnabled ) {
+ if ( logger.enabled ) {
logData = {
engine: 'u',
result: 2,
@@ -171,7 +177,7 @@ const onBeforeRootFrameRequest = function(fctxt) {
// Static filtering
if ( result === 0 ) {
- ({ result, logData } = shouldStrictBlock(fctxt, loggerEnabled));
+ ({ result, logData } = shouldStrictBlock(fctxt, logger.enabled));
}
const pageStore = µb.bindTabToPageStore(fctxt.tabId, 'beforeRequest');
@@ -180,7 +186,7 @@ const onBeforeRootFrameRequest = function(fctxt) {
pageStore.journalAddRequest(fctxt, result);
}
- if ( loggerEnabled ) {
+ if ( logger.enabled ) {
fctxt.setFilter(logData);
}
@@ -190,12 +196,12 @@ const onBeforeRootFrameRequest = function(fctxt) {
result !== 1 &&
trusted === false &&
pageStore !== null &&
- µb.staticNetFilteringEngine.hasQuery(fctxt)
+ staticNetFilteringEngine.hasQuery(fctxt)
) {
pageStore.redirectNonBlockedRequest(fctxt);
}
- if ( loggerEnabled ) {
+ if ( logger.enabled ) {
fctxt.setRealm('network').toLogger();
}
@@ -259,8 +265,7 @@ const onBeforeRootFrameRequest = function(fctxt) {
// --------+--------+--------+--------+--------+--------+
const shouldStrictBlock = function(fctxt, loggerEnabled) {
- const µb = µBlock;
- const snfe = µb.staticNetFilteringEngine;
+ const snfe = staticNetFilteringEngine;
// Explicit filtering: `document` option
const rs = snfe.matchRequest(fctxt, 0b0011);
@@ -358,7 +363,6 @@ const validateStrictBlock = function(fctxt, logData) {
// Intercept and filter behind-the-scene requests.
const onBeforeBehindTheSceneRequest = function(fctxt) {
- const µb = µBlock;
const pageStore = µb.pageStoreFromTabId(fctxt.tabId);
if ( pageStore === null ) { return; }
@@ -403,7 +407,7 @@ const onBeforeBehindTheSceneRequest = function(fctxt) {
// https://github.com/uBlockOrigin/uBlock-issues/issues/1204
onBeforeBehindTheSceneRequest.journalAddRequest(fctxt, result);
- if ( µb.logger.enabled ) {
+ if ( logger.enabled ) {
fctxt.setRealm('network').toLogger();
}
@@ -440,7 +444,7 @@ const onBeforeBehindTheSceneRequest = function(fctxt) {
const gc = ( ) => {
gcTimer = undefined;
- if ( pageStoresToken !== µBlock.pageStoresToken ) { return reset(); }
+ if ( pageStoresToken !== µb.pageStoresToken ) { return reset(); }
gcTimer = vAPI.setTimeout(gc, 30011);
};
@@ -448,15 +452,15 @@ const onBeforeBehindTheSceneRequest = function(fctxt) {
const docHostname = fctxt.getDocHostname();
if (
docHostname !== hostname ||
- pageStoresToken !== µBlock.pageStoresToken
+ pageStoresToken !== µb.pageStoresToken
) {
hostname = docHostname;
pageStores = new Set();
- for ( const pageStore of µBlock.pageStores.values() ) {
+ for ( const pageStore of µb.pageStores.values() ) {
if ( pageStore.tabHostname !== docHostname ) { continue; }
pageStores.add(pageStore);
}
- pageStoresToken = µBlock.pageStoresToken;
+ pageStoresToken = µb.pageStoresToken;
if ( gcTimer !== undefined ) {
clearTimeout(gcTimer);
}
@@ -486,7 +490,6 @@ const onHeadersReceived = function(details) {
return;
}
- const µb = µBlock;
const fctxt = µb.filteringContext.fromWebrequestDetails(details);
const isRootDoc = fctxt.itype === fctxt.MAIN_FRAME;
@@ -511,7 +514,7 @@ const onHeadersReceived = function(details) {
if ( isRootDoc === false && µb.hiddenSettings.filterOnHeaders === true ) {
const result = pageStore.filterOnHeaders(fctxt, responseHeaders);
if ( result !== 0 ) {
- if ( µb.logger.enabled ) {
+ if ( logger.enabled ) {
fctxt.setRealm('network').toLogger();
}
if ( result === 1 ) {
@@ -542,7 +545,7 @@ const onHeadersReceived = function(details) {
µb.canFilterResponseData && filterDocument(fctxt, details) === true;
let modifiedHeaders = false;
- if ( µb.httpheaderFilteringEngine.apply(fctxt, responseHeaders) === true ) {
+ if ( httpheaderFilteringEngine.apply(fctxt, responseHeaders) === true ) {
modifiedHeaders = true;
}
if ( injectCSP(fctxt, pageStore, responseHeaders) === true ) {
@@ -622,7 +625,6 @@ const normalizeBehindTheSceneResponseHeaders = function(details) {
**/
const filterDocument = (( ) => {
- const µb = µBlock;
const filterers = new Map();
let domParser, xmlSerializer,
utf8TextDecoder, textDecoder, textEncoder;
@@ -749,7 +751,7 @@ const filterDocument = (( ) => {
filterer.mime
);
charsetFound = charsetFromDoc(doc);
- charsetUsed = µb.textEncode.normalizeCharset(charsetFound);
+ charsetUsed = textEncode.normalizeCharset(charsetFound);
if ( charsetUsed === undefined ) {
return streamClose(filterer);
}
@@ -764,7 +766,7 @@ const filterDocument = (( ) => {
// In case of no explicit charset found, try to find one again, but
// this time with the whole document parsed.
if ( charsetFound === undefined ) {
- charsetFound = µb.textEncode.normalizeCharset(charsetFromDoc(doc));
+ charsetFound = textEncode.normalizeCharset(charsetFromDoc(doc));
if ( charsetFound !== charsetUsed ) {
if ( charsetFound === undefined ) {
return streamClose(filterer);
@@ -779,7 +781,7 @@ const filterDocument = (( ) => {
let modified = false;
if ( filterer.selectors !== undefined ) {
- if ( µb.htmlFilteringEngine.apply(doc, filterer) ) {
+ if ( htmlFilteringEngine.apply(doc, filterer) ) {
modified = true;
}
}
@@ -799,7 +801,7 @@ const filterDocument = (( ) => {
doc.documentElement.outerHTML
);
if ( charsetUsed !== 'utf-8' ) {
- encodedStream = µb.textEncode.encode(
+ encodedStream = textEncode.encode(
charsetUsed,
encodedStream
);
@@ -837,7 +839,7 @@ const filterDocument = (( ) => {
charset: undefined
};
- request.selectors = µb.htmlFilteringEngine.retrieve(request);
+ request.selectors = htmlFilteringEngine.retrieve(request);
if ( request.selectors === undefined ) { return; }
const headers = extras.responseHeaders;
@@ -847,7 +849,7 @@ const filterDocument = (( ) => {
if ( request.mime === undefined ) { return; }
let charset = charsetFromContentType(contentType);
if ( charset !== undefined ) {
- charset = µb.textEncode.normalizeCharset(charset);
+ charset = textEncode.normalizeCharset(charset);
if ( charset === undefined ) { return; }
request.charset = charset;
}
@@ -869,8 +871,6 @@ const filterDocument = (( ) => {
/******************************************************************************/
const injectCSP = function(fctxt, pageStore, responseHeaders) {
- const µb = µBlock;
- const loggerEnabled = µb.logger.enabled;
const cspSubsets = [];
const requestType = fctxt.type;
@@ -881,8 +881,8 @@ const injectCSP = function(fctxt, pageStore, responseHeaders) {
const builtinDirectives = [];
if ( pageStore.filterScripting(fctxt, true) === 1 ) {
- builtinDirectives.push(µBlock.cspNoScripting);
- if ( loggerEnabled ) {
+ builtinDirectives.push(µb.cspNoScripting);
+ if ( logger.enabled ) {
fctxt.setRealm('network').setType('scripting').toLogger();
}
}
@@ -896,9 +896,9 @@ const injectCSP = function(fctxt, pageStore, responseHeaders) {
fctxt2.setDocOriginFromURL(fctxt.url);
const result = pageStore.filterRequest(fctxt2);
if ( result === 1 ) {
- builtinDirectives.push(µBlock.cspNoInlineScript);
+ builtinDirectives.push(µb.cspNoInlineScript);
}
- if ( result === 2 && loggerEnabled ) {
+ if ( result === 2 && logger.enabled ) {
fctxt2.setRealm('network').toLogger();
}
}
@@ -907,8 +907,8 @@ const injectCSP = function(fctxt, pageStore, responseHeaders) {
// - Use a CSP to also forbid inline fonts if remote fonts are blocked.
fctxt.type = 'inline-font';
if ( pageStore.filterRequest(fctxt) === 1 ) {
- builtinDirectives.push(µBlock.cspNoInlineFont);
- if ( loggerEnabled ) {
+ builtinDirectives.push(µb.cspNoInlineFont);
+ if ( logger.enabled ) {
fctxt.setRealm('network').toLogger();
}
}
@@ -923,7 +923,7 @@ const injectCSP = function(fctxt, pageStore, responseHeaders) {
fctxt.type = requestType;
const staticDirectives =
- µb.staticNetFilteringEngine.matchAndFetchModifiers(fctxt, 'csp');
+ staticNetFilteringEngine.matchAndFetchModifiers(fctxt, 'csp');
if ( staticDirectives !== undefined ) {
for ( const directive of staticDirectives ) {
if ( directive.result !== 1 ) { continue; }
@@ -934,16 +934,16 @@ const injectCSP = function(fctxt, pageStore, responseHeaders) {
// URL filtering `allow` rules override static filtering.
if (
cspSubsets.length !== 0 &&
- µb.sessionURLFiltering.evaluateZ(
+ sessionURLFiltering.evaluateZ(
fctxt.getTabHostname(),
fctxt.url,
'csp'
) === 2
) {
- if ( loggerEnabled ) {
+ if ( logger.enabled ) {
fctxt.setRealm('network')
.setType('csp')
- .setFilter(µb.sessionURLFiltering.toLogData())
+ .setFilter(sessionURLFiltering.toLogData())
.toLogger();
}
return;
@@ -953,16 +953,16 @@ const injectCSP = function(fctxt, pageStore, responseHeaders) {
if (
cspSubsets.length !== 0 &&
µb.userSettings.advancedUserEnabled &&
- µb.sessionFirewall.evaluateCellZY(
+ sessionFirewall.evaluateCellZY(
fctxt.getTabHostname(),
fctxt.getTabHostname(),
'*'
) === 2
) {
- if ( loggerEnabled ) {
+ if ( logger.enabled ) {
fctxt.setRealm('network')
.setType('csp')
- .setFilter(µb.sessionFirewall.toLogData())
+ .setFilter(sessionFirewall.toLogData())
.toLogger();
}
return;
@@ -972,7 +972,7 @@ const injectCSP = function(fctxt, pageStore, responseHeaders) {
// Static CSP policies will be applied.
- if ( loggerEnabled && staticDirectives !== undefined ) {
+ if ( logger.enabled && staticDirectives !== undefined ) {
fctxt.setRealm('network')
.pushFilters(staticDirectives.map(a => a.logData()))
.toLogger();
@@ -1006,7 +1006,7 @@ const injectCSP = function(fctxt, pageStore, responseHeaders) {
const foilFloc = function(fctxt, responseHeaders) {
const hn = fctxt.getHostname();
- if ( µBlock.scriptletFilteringEngine.hasScriptlet(hn, 1, 'no-floc') === false ) {
+ if ( scriptletFilteringEngine.hasScriptlet(hn, 1, 'no-floc') === false ) {
return false;
}
responseHeaders.push({
@@ -1029,7 +1029,7 @@ const foilLargeMediaElement = function(details, fctxt, pageStore) {
if ( details.fromCache === true ) { return; }
let size = 0;
- if ( µBlock.userSettings.largeMediaSize !== 0 ) {
+ if ( µb.userSettings.largeMediaSize !== 0 ) {
const headers = details.responseHeaders;
const i = headerIndexFromName('content-length', headers);
if ( i === -1 ) { return; }
@@ -1039,7 +1039,7 @@ const foilLargeMediaElement = function(details, fctxt, pageStore) {
const result = pageStore.filterLargeMediaElement(fctxt, size);
if ( result === 0 ) { return; }
- if ( µBlock.logger.enabled ) {
+ if ( logger.enabled ) {
fctxt.setRealm('network').toLogger();
}
@@ -1083,14 +1083,14 @@ const strictBlockBypasser = {
if ( typeof hostname !== 'string' || hostname === '' ) { return; }
this.hostnameToDeadlineMap.set(
hostname,
- Date.now() + µBlock.hiddenSettings.strictBlockingBypassDuration * 1000
+ Date.now() + µb.hiddenSettings.strictBlockingBypassDuration * 1000
);
},
isBypassed: function(hostname) {
if ( this.hostnameToDeadlineMap.size === 0 ) { return false; }
let bypassDuration =
- µBlock.hiddenSettings.strictBlockingBypassDuration * 1000;
+ µb.hiddenSettings.strictBlockingBypassDuration * 1000;
if ( this.cleanupTimer === undefined ) {
this.cleanupTimer = vAPI.setTimeout(
( ) => {
@@ -1122,9 +1122,7 @@ const strictBlockBypasser = {
/******************************************************************************/
-// Export
-
-µBlock.webRequest = {
+const webRequest = {
start: (( ) => {
vAPI.net = new vAPI.Net();
vAPI.net.suspend();
@@ -1147,3 +1145,7 @@ const strictBlockBypasser = {
};
/******************************************************************************/
+
+export { webRequest };
+
+/******************************************************************************/
diff --git a/src/js/ublock.js b/src/js/ublock.js
index bef20f8a3..d6567e545 100644
--- a/src/js/ublock.js
+++ b/src/js/ublock.js
@@ -23,8 +23,26 @@
/******************************************************************************/
+import contextMenu from './contextmenu.js';
+import cosmeticFilteringEngine from './cosmetic-filtering.js';
+import µb from './background.js';
import { hostnameFromURI } from './uri-utils.js';
-import µBlock from './background.js';
+import { redirectEngine } from './redirect-engine.js';
+
+import {
+ permanentFirewall,
+ sessionFirewall,
+} from './dynamic-net-filtering.js';
+
+import {
+ permanentSwitches,
+ sessionSwitches,
+} from './hnswitches.js';
+
+import {
+ permanentURLFiltering,
+ sessionURLFiltering,
+} from './url-net-filtering.js';
/******************************************************************************/
/******************************************************************************/
@@ -90,7 +108,7 @@ const matchBucket = function(url, hostname, bucket, start) {
/******************************************************************************/
-µBlock.getNetFilteringSwitch = function(url) {
+µb.getNetFilteringSwitch = function(url) {
const hostname = hostnameFromURI(url);
let key = hostname;
for (;;) {
@@ -109,7 +127,7 @@ const matchBucket = function(url, hostname, bucket, start) {
/******************************************************************************/
-µBlock.toggleNetFilteringSwitch = function(url, scope, newState) {
+µb.toggleNetFilteringSwitch = function(url, scope, newState) {
const currentState = this.getNetFilteringSwitch(url);
if ( newState === undefined ) {
newState = !currentState;
@@ -179,7 +197,7 @@ const matchBucket = function(url, hostname, bucket, start) {
/******************************************************************************/
-µBlock.arrayFromWhitelist = function(whitelist) {
+µb.arrayFromWhitelist = function(whitelist) {
const out = new Set();
for ( const bucket of whitelist.values() ) {
for ( const directive of bucket ) {
@@ -189,13 +207,13 @@ const matchBucket = function(url, hostname, bucket, start) {
return Array.from(out).sort((a, b) => a.localeCompare(b));
};
-µBlock.stringFromWhitelist = function(whitelist) {
+µb.stringFromWhitelist = function(whitelist) {
return this.arrayFromWhitelist(whitelist).join('\n');
};
/******************************************************************************/
-µBlock.whitelistFromArray = function(lines) {
+µb.whitelistFromArray = function(lines) {
const whitelist = new Map();
// Comment bucket must always be ready to be used.
@@ -273,27 +291,27 @@ const matchBucket = function(url, hostname, bucket, start) {
return whitelist;
};
-µBlock.whitelistFromString = function(s) {
+µb.whitelistFromString = function(s) {
return this.whitelistFromArray(s.split('\n'));
};
// https://github.com/gorhill/uBlock/issues/3717
-µBlock.reWhitelistBadHostname = /[^a-z0-9.\-_\[\]:]/;
-µBlock.reWhitelistHostnameExtractor = /([a-z0-9.\-_\[\]]+)(?::[\d*]+)?\/(?:[^\x00-\x20\/]|$)[^\x00-\x20]*$/;
+µb.reWhitelistBadHostname = /[^a-z0-9.\-_\[\]:]/;
+µb.reWhitelistHostnameExtractor = /([a-z0-9.\-_\[\]]+)(?::[\d*]+)?\/(?:[^\x00-\x20\/]|$)[^\x00-\x20]*$/;
/******************************************************************************/
-µBlock.changeUserSettings = function(name, value) {
+µb.changeUserSettings = function(name, value) {
let us = this.userSettings;
// Return all settings if none specified.
if ( name === undefined ) {
us = JSON.parse(JSON.stringify(us));
- us.noCosmeticFiltering = this.sessionSwitches.evaluate('no-cosmetic-filtering', '*') === 1;
- us.noLargeMedia = this.sessionSwitches.evaluate('no-large-media', '*') === 1;
- us.noRemoteFonts = this.sessionSwitches.evaluate('no-remote-fonts', '*') === 1;
- us.noScripting = this.sessionSwitches.evaluate('no-scripting', '*') === 1;
- us.noCSPReports = this.sessionSwitches.evaluate('no-csp-reports', '*') === 1;
+ us.noCosmeticFiltering = sessionSwitches.evaluate('no-cosmetic-filtering', '*') === 1;
+ us.noLargeMedia = sessionSwitches.evaluate('no-large-media', '*') === 1;
+ us.noRemoteFonts = sessionSwitches.evaluate('no-remote-fonts', '*') === 1;
+ us.noScripting = sessionSwitches.evaluate('no-scripting', '*') === 1;
+ us.noCSPReports = sessionSwitches.evaluate('no-csp-reports', '*') === 1;
return us;
}
@@ -338,11 +356,11 @@ const matchBucket = function(url, hostname, bucket, start) {
break;
case 'collapseBlocked':
if ( value === false ) {
- this.cosmeticFilteringEngine.removeFromSelectorCache('*', 'net');
+ cosmeticFilteringEngine.removeFromSelectorCache('*', 'net');
}
break;
case 'contextMenuEnabled':
- this.contextMenu.update(null);
+ contextMenu.update(null);
break;
case 'hyperlinkAuditingDisabled':
if ( this.privacySettingsSupported ) {
@@ -371,8 +389,8 @@ const matchBucket = function(url, hostname, bucket, start) {
}
if ( switchName === undefined ) { break; }
let switchState = value ? 1 : 0;
- this.sessionSwitches.toggle(switchName, '*', switchState);
- if ( this.permanentSwitches.toggle(switchName, '*', switchState) ) {
+ sessionSwitches.toggle(switchName, '*', switchState);
+ if ( permanentSwitches.toggle(switchName, '*', switchState) ) {
this.saveHostnameSwitches();
}
break;
@@ -399,13 +417,13 @@ const matchBucket = function(url, hostname, bucket, start) {
// https://www.reddit.com/r/uBlockOrigin/comments/8524cf/my_custom_scriptlets_doesnt_work_what_am_i_doing/
-µBlock.changeHiddenSettings = function(hs) {
+µb.changeHiddenSettings = function(hs) {
const mustReloadResources =
hs.userResourcesLocation !== this.hiddenSettings.userResourcesLocation;
this.hiddenSettings = hs;
this.saveHiddenSettings();
if ( mustReloadResources ) {
- this.redirectEngine.invalidateResourcesSelfie();
+ redirectEngine.invalidateResourcesSelfie();
this.loadRedirectResources();
}
this.fireDOMEvent('hiddenSettingsChanged');
@@ -413,7 +431,7 @@ const matchBucket = function(url, hostname, bucket, start) {
/******************************************************************************/
-µBlock.elementPickerExec = async function(
+µb.elementPickerExec = async function(
tabId,
frameId,
targetElement,
@@ -451,18 +469,18 @@ const matchBucket = function(url, hostname, bucket, start) {
// Always set own rules, trying to be fancy to avoid setting seemingly
// (but not really) redundant rules led to this issue.
-µBlock.toggleFirewallRule = function(details) {
+µb.toggleFirewallRule = function(details) {
let { srcHostname, desHostname, requestType, action } = details;
if ( action !== 0 ) {
- this.sessionFirewall.setCell(
+ sessionFirewall.setCell(
srcHostname,
desHostname,
requestType,
action
);
} else {
- this.sessionFirewall.unsetCell(
+ sessionFirewall.unsetCell(
srcHostname,
desHostname,
requestType
@@ -472,14 +490,14 @@ const matchBucket = function(url, hostname, bucket, start) {
// https://github.com/chrisaljoudi/uBlock/issues/731#issuecomment-73937469
if ( details.persist ) {
if ( action !== 0 ) {
- this.permanentFirewall.setCell(
+ permanentFirewall.setCell(
srcHostname,
desHostname,
requestType,
action
);
} else {
- this.permanentFirewall.unsetCell(
+ permanentFirewall.unsetCell(
srcHostname,
desHostname,
requestType,
@@ -506,7 +524,7 @@ const matchBucket = function(url, hostname, bucket, start) {
}
// https://github.com/chrisaljoudi/uBlock/issues/420
- this.cosmeticFilteringEngine.removeFromSelectorCache(srcHostname, 'net');
+ cosmeticFilteringEngine.removeFromSelectorCache(srcHostname, 'net');
if ( details.tabId === undefined ) { return; }
@@ -525,8 +543,8 @@ const matchBucket = function(url, hostname, bucket, start) {
/******************************************************************************/
-µBlock.toggleURLFilteringRule = function(details) {
- let changed = this.sessionURLFiltering.setRule(
+µb.toggleURLFilteringRule = function(details) {
+ let changed = sessionURLFiltering.setRule(
details.context,
details.url,
details.type,
@@ -534,11 +552,11 @@ const matchBucket = function(url, hostname, bucket, start) {
);
if ( changed === false ) { return; }
- this.cosmeticFilteringEngine.removeFromSelectorCache(details.context, 'net');
+ cosmeticFilteringEngine.removeFromSelectorCache(details.context, 'net');
if ( details.persist !== true ) { return; }
- changed = this.permanentURLFiltering.setRule(
+ changed = permanentURLFiltering.setRule(
details.context,
details.url,
details.type,
@@ -552,8 +570,8 @@ const matchBucket = function(url, hostname, bucket, start) {
/******************************************************************************/
-µBlock.toggleHostnameSwitch = function(details) {
- let changed = this.sessionSwitches.toggleZ(
+µb.toggleHostnameSwitch = function(details) {
+ let changed = sessionSwitches.toggleZ(
details.name,
details.hostname,
!!details.deep,
@@ -582,7 +600,7 @@ const matchBucket = function(url, hostname, bucket, start) {
if ( details.persist !== true ) { return; }
- changed = this.permanentSwitches.toggleZ(
+ changed = permanentSwitches.toggleZ(
details.name,
details.hostname,
!!details.deep,
@@ -595,29 +613,28 @@ const matchBucket = function(url, hostname, bucket, start) {
/******************************************************************************/
-µBlock.blockingModeFromHostname = function(hn) {
+µb.blockingModeFromHostname = function(hn) {
let bits = 0;
- if ( this.sessionSwitches.evaluateZ('no-scripting', hn) ) {
+ if ( sessionSwitches.evaluateZ('no-scripting', hn) ) {
bits |= 0b00000010;
}
if ( this.userSettings.advancedUserEnabled ) {
- const fw = this.sessionFirewall;
- if ( fw.evaluateCellZY(hn, '*', '3p') === 1 ) {
+ if ( sessionFirewall.evaluateCellZY(hn, '*', '3p') === 1 ) {
bits |= 0b00000100;
}
- if ( fw.evaluateCellZY(hn, '*', '3p-script') === 1 ) {
+ if ( sessionFirewall.evaluateCellZY(hn, '*', '3p-script') === 1 ) {
bits |= 0b00001000;
}
- if ( fw.evaluateCellZY(hn, '*', '3p-frame') === 1 ) {
+ if ( sessionFirewall.evaluateCellZY(hn, '*', '3p-frame') === 1 ) {
bits |= 0b00010000;
}
}
return bits;
};
-µBlock.parseBlockingProfiles = (( ) => {
+µb.parseBlockingProfiles = (( ) => {
const parse = function() {
- const s = µBlock.hiddenSettings.blockingProfiles;
+ const s = µb.hiddenSettings.blockingProfiles;
const profiles = [];
s.split(/\s+/).forEach(s => {
let pos = s.indexOf('/');
@@ -629,8 +646,8 @@ const matchBucket = function(url, hostname, bucket, start) {
const color = s.slice(pos + 1);
profiles.push({ bits, color: color !== '' ? color : '#666' });
});
- µBlock.liveBlockingProfiles = profiles;
- µBlock.blockingProfileColorCache.clear();
+ µb.liveBlockingProfiles = profiles;
+ µb.blockingProfileColorCache.clear();
};
parse();
@@ -642,7 +659,7 @@ const matchBucket = function(url, hostname, bucket, start) {
/******************************************************************************/
-µBlock.scriptlets = (function() {
+µb.scriptlets = (function() {
const pendingEntries = new Map();
const Entry = class {
diff --git a/src/js/url-net-filtering.js b/src/js/url-net-filtering.js
index c5f1e2283..7ee40a3b8 100644
--- a/src/js/url-net-filtering.js
+++ b/src/js/url-net-filtering.js
@@ -23,8 +23,8 @@
/******************************************************************************/
+import µb from './background.js';
import { LineIterator } from './text-iterators.js';
-import µBlock from './background.js';
/*******************************************************************************
@@ -200,7 +200,7 @@ URLNetFiltering.prototype.evaluateZ = function(context, target, type) {
if ( this.rules.size === 0 ) {
return 0;
}
- µBlock.decomposeHostname(context, this.decomposedSource);
+ µb.decomposeHostname(context, this.decomposedSource);
for ( let shn of this.decomposedSource ) {
this.context = shn;
let entries = this.rules.get(shn + ' ' + type);
@@ -370,11 +370,9 @@ URLNetFiltering.prototype.removeFromRuleParts = function(parts) {
/******************************************************************************/
-// Export
+const sessionURLFiltering = new URLNetFiltering();
+const permanentURLFiltering = new URLNetFiltering();
-µBlock.URLNetFiltering = URLNetFiltering;
-
-µBlock.sessionURLFiltering = new URLNetFiltering();
-µBlock.permanentURLFiltering = new URLNetFiltering();
+export { permanentURLFiltering, sessionURLFiltering };
/******************************************************************************/
diff --git a/src/js/utils.js b/src/js/utils.js
index 955ce8ceb..4308cdc0e 100644
--- a/src/js/utils.js
+++ b/src/js/utils.js
@@ -23,12 +23,13 @@
/******************************************************************************/
+import io from './assets.js';
+import µb from './background.js';
import { LineIterator } from './text-iterators.js';
-import µBlock from './background.js';
/******************************************************************************/
-µBlock.formatCount = function(count) {
+µb.formatCount = function(count) {
if ( typeof count !== 'number' ) {
return '';
}
@@ -53,7 +54,7 @@ import µBlock from './background.js';
/******************************************************************************/
-µBlock.dateNowToSensibleString = function() {
+µb.dateNowToSensibleString = function() {
const now = new Date(Date.now() - (new Date()).getTimezoneOffset() * 60000);
return now.toISOString().replace(/\.\d+Z$/, '')
.replace(/:/g, '.')
@@ -62,7 +63,7 @@ import µBlock from './background.js';
/******************************************************************************/
-µBlock.openNewTab = function(details) {
+µb.openNewTab = function(details) {
if ( details.url.startsWith('logger-ui.html') ) {
if ( details.shiftKey ) {
this.changeUserSettings(
@@ -92,7 +93,7 @@ import µBlock from './background.js';
/******************************************************************************/
-µBlock.MRUCache = class {
+µb.MRUCache = class {
constructor(size) {
this.size = size;
this.array = [];
@@ -136,13 +137,13 @@ import µBlock from './background.js';
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
-µBlock.escapeRegex = function(s) {
+µb.escapeRegex = function(s) {
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
};
/******************************************************************************/
-µBlock.decomposeHostname = (( ) => {
+µb.decomposeHostname = (( ) => {
// For performance purpose, as simple tests as possible
const reHostnameVeryCoarse = /[g-z_-]/;
const reIPv4VeryCoarse = /\.\d+$/;
@@ -196,7 +197,7 @@ import µBlock from './background.js';
// TODO: evaluate using TextEncoder/TextDecoder
-µBlock.orphanizeString = function(s) {
+µb.orphanizeString = function(s) {
return JSON.parse(JSON.stringify(s));
};
@@ -217,10 +218,6 @@ import µBlock from './background.js';
// From uBO's dev console, launch the benchmark:
// µBlock.staticNetFilteringEngine.benchmark();
//
-// The advanced setting `consoleLogLevel` must be set to `info` to see the
-// results in uBO's dev console, see:
-// https://github.com/gorhill/uBlock/wiki/Advanced-settings#consoleloglevel
-//
// The usual browser dev tools can be used to obtain useful profiling
// data, i.e. start the profiler, call the benchmark method from the
// console, then stop the profiler when it completes.
@@ -232,7 +229,7 @@ import µBlock from './background.js';
// Rename ./tmp/requests.json.gz to something else if you no longer want
// ./assets/requests.json in the build.
-µBlock.loadBenchmarkDataset = (( ) => {
+µb.loadBenchmarkDataset = (( ) => {
let datasetPromise;
let ttlTimer;
@@ -251,13 +248,13 @@ import µBlock from './background.js';
return datasetPromise;
}
- const datasetURL = µBlock.hiddenSettings.benchmarkDatasetURL;
+ const datasetURL = µb.hiddenSettings.benchmarkDatasetURL;
if ( datasetURL === 'unset' ) {
console.info(`No benchmark dataset available.`);
return Promise.resolve();
}
console.info(`Loading benchmark dataset...`);
- datasetPromise = µBlock.assets.fetchText(datasetURL).then(details => {
+ datasetPromise = io.fetchText(datasetURL).then(details => {
console.info(`Parsing benchmark dataset...`);
const requests = [];
const lineIter = new LineIterator(details.content);
@@ -288,7 +285,7 @@ import µBlock from './background.js';
/******************************************************************************/
-µBlock.fireDOMEvent = function(name) {
+µb.fireDOMEvent = function(name) {
if (
window instanceof Object &&
window.dispatchEvent instanceof Function &&
@@ -302,7 +299,7 @@ import µBlock from './background.js';
// TODO: properly compare arrays
-µBlock.getModifiedSettings = function(edit, orig = {}) {
+µb.getModifiedSettings = function(edit, orig = {}) {
const out = {};
for ( const prop in edit ) {
if ( orig.hasOwnProperty(prop) && edit[prop] !== orig[prop] ) {
@@ -312,7 +309,7 @@ import µBlock from './background.js';
return out;
};
-µBlock.settingValueFromString = function(orig, name, s) {
+µb.settingValueFromString = function(orig, name, s) {
if ( typeof name !== 'string' || typeof s !== 'string' ) { return; }
if ( orig.hasOwnProperty(name) === false ) { return; }
let r;