1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-07-19 19:52:51 +02:00

Add filterLists property to managed storage

The entry `toOverwrite.filterLists` is an array of
string, where each string is a token identifying a
stock filter list, or a URL for an external filter
list.

This new entry is to make it easier for an
administrator to centrally configure uBO with a
custom set of filter lists.
This commit is contained in:
Raymond Hill 2021-01-08 09:18:26 -05:00
parent e4e7cbc78f
commit 0e3071dd50
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
4 changed files with 64 additions and 33 deletions

View File

@ -41,6 +41,12 @@
"title": "Settings to overwrite at launch time", "title": "Settings to overwrite at launch time",
"type": "object", "type": "object",
"properties": { "properties": {
"filterLists": {
"title": "A collection of list identifiers and/or list URLs",
"description": "The set of filter lists to use at launch time.",
"type": "array",
"items": { "type": "string" }
},
"trustedSiteDirectives": { "trustedSiteDirectives": {
"title": "A list of trusted-site directives", "title": "A list of trusted-site directives",
"type": "array", "type": "array",

View File

@ -942,6 +942,11 @@ const restoreUserData = async function(request) {
userData.hostnameSwitchesString += '\nno-csp-reports: * true'; userData.hostnameSwitchesString += '\nno-csp-reports: * true';
} }
// List of external lists is meant to be an array.
if ( typeof userData.externalLists === 'string' ) {
userData.externalLists = userData.externalLists.trim().split(/[\n\r]+/);
}
// https://github.com/chrisaljoudi/uBlock/issues/1102 // https://github.com/chrisaljoudi/uBlock/issues/1102
// Ensure all currently cached assets are flushed from storage AND memory. // Ensure all currently cached assets are flushed from storage AND memory.
µb.assets.rmrf(); µb.assets.rmrf();
@ -1041,7 +1046,6 @@ const getLists = async function(callback) {
cache: null, cache: null,
cosmeticFilterCount: µb.cosmeticFilteringEngine.getFilterCount(), cosmeticFilterCount: µb.cosmeticFilteringEngine.getFilterCount(),
current: µb.availableFilterLists, current: µb.availableFilterLists,
externalLists: µb.userSettings.externalLists,
ignoreGenericCosmeticFilters: µb.userSettings.ignoreGenericCosmeticFilters, ignoreGenericCosmeticFilters: µb.userSettings.ignoreGenericCosmeticFilters,
isUpdating: µb.assets.isUpdating(), isUpdating: µb.assets.isUpdating(),
netFilterCount: µb.staticNetFilteringEngine.getFilterCount(), netFilterCount: µb.staticNetFilteringEngine.getFilterCount(),

View File

@ -162,6 +162,12 @@ const onNetWhitelistReady = function(netWhitelistRaw, adminExtra) {
const onUserSettingsReady = function(fetched) { const onUserSettingsReady = function(fetched) {
const userSettings = µb.userSettings; const userSettings = µb.userSettings;
// List of external lists is meant to be an array
if ( typeof fetched.externalLists === 'string' ) {
fetched.externalLists =
fetched.externalLists.trim().split(/[\n\r]+/);
}
fromFetch(userSettings, fetched); fromFetch(userSettings, fetched);
if ( µb.privacySettingsSupported ) { if ( µb.privacySettingsSupported ) {

View File

@ -335,7 +335,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
µBlock.applyFilterListSelection = function(details) { µBlock.applyFilterListSelection = function(details) {
let selectedListKeySet = new Set(this.selectedFilterLists); let selectedListKeySet = new Set(this.selectedFilterLists);
let externalLists = this.userSettings.externalLists; let externalLists = this.userSettings.externalLists.slice();
// Filter lists to select // Filter lists to select
if ( Array.isArray(details.toSelect) ) { if ( Array.isArray(details.toSelect) ) {
@ -350,19 +350,13 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
// Imported filter lists to remove // Imported filter lists to remove
if ( Array.isArray(details.toRemove) ) { if ( Array.isArray(details.toRemove) ) {
const removeURLFromHaystack = (haystack, needle) => {
return haystack.replace(
new RegExp(
'(^|\\n)' +
this.escapeRegex(needle) +
'(\\n|$)', 'g'),
'\n'
).trim();
};
for ( let i = 0, n = details.toRemove.length; i < n; i++ ) { for ( let i = 0, n = details.toRemove.length; i < n; i++ ) {
const assetKey = details.toRemove[i]; const assetKey = details.toRemove[i];
selectedListKeySet.delete(assetKey); selectedListKeySet.delete(assetKey);
externalLists = removeURLFromHaystack(externalLists, assetKey); const pos = externalLists.indexOf(assetKey);
if ( pos !== -1 ) {
externalLists.splice(pos, 1);
}
this.removeFilterList(assetKey); this.removeFilterList(assetKey);
} }
} }
@ -404,11 +398,11 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
} }
selectedListKeySet.add(assetKey); selectedListKeySet.add(assetKey);
} }
externalLists = Array.from(importedSet).sort().join('\n'); externalLists = Array.from(importedSet).sort();
} }
const result = Array.from(selectedListKeySet); const result = Array.from(selectedListKeySet);
if ( externalLists !== this.userSettings.externalLists ) { if ( externalLists.join() !== this.userSettings.externalLists.join() ) {
this.userSettings.externalLists = externalLists; this.userSettings.externalLists = externalLists;
vAPI.storage.set({ externalLists }); vAPI.storage.set({ externalLists });
} }
@ -418,16 +412,17 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
/******************************************************************************/ /******************************************************************************/
µBlock.listKeysFromCustomFilterLists = function(raw) { µBlock.listKeysFromCustomFilterLists = function(raw) {
const urls = typeof raw === 'string'
? raw.trim().split(/[\n\r]+/)
: raw;
const out = new Set(); const out = new Set();
const reIgnore = /^[!#]/; const reIgnore = /^[!#]/;
const reValid = /^[a-z-]+:\/\/\S+/; const reValid = /^[a-z-]+:\/\/\S+/;
const lineIter = new this.LineIterator(raw); for ( const url of urls ) {
while ( lineIter.eot() === false ) { if ( reIgnore.test(url) || !reValid.test(url) ) { continue; }
const location = lineIter.next().trim();
if ( reIgnore.test(location) || !reValid.test(location) ) { continue; }
// Ignore really bad lists. // Ignore really bad lists.
if ( this.badLists.get(location) === true ) { continue; } if ( this.badLists.get(url) === true ) { continue; }
out.add(location); out.add(url);
} }
return Array.from(out); return Array.from(out);
}; };
@ -603,8 +598,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
newAvailableLists[listURL] = newEntry; newAvailableLists[listURL] = newEntry;
this.assets.registerAssetSource(listURL, newEntry); this.assets.registerAssetSource(listURL, newEntry);
importedListKeys.push(listURL); importedListKeys.push(listURL);
this.userSettings.externalLists += '\n' + listURL; this.userSettings.externalLists.push(listURL.trim());
this.userSettings.externalLists = this.userSettings.externalLists.trim();
vAPI.storage.set({ externalLists: this.userSettings.externalLists }); vAPI.storage.set({ externalLists: this.userSettings.externalLists });
this.saveSelectedFilterLists([ listURL ], true); this.saveSelectedFilterLists([ listURL ], true);
}; };
@ -1322,26 +1316,47 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
} }
if ( typeof data.userSettings === 'object' ) { if ( typeof data.userSettings === 'object' ) {
for ( const name in this.userSettings ) { const µbus = this.userSettings;
if ( this.userSettings.hasOwnProperty(name) === false ) { const adminus = data.userSettings;
continue; // List of external lists is meant to be an array.
if ( typeof adminus.externalLists === 'string' ) {
adminus.externalLists =
adminus.externalLists.trim().split(/[\n\r]+/);
} }
if ( data.userSettings.hasOwnProperty(name) === false ) { for ( const name in µbus ) {
continue; if ( µbus.hasOwnProperty(name) === false ) { continue; }
} if ( adminus.hasOwnProperty(name) === false ) { continue; }
bin[name] = data.userSettings[name]; bin[name] = adminus[name];
binNotEmpty = true; binNotEmpty = true;
} }
} }
// 'selectedFilterLists' is an array of filter list tokens. Each token // 'selectedFilterLists' is an array of filter list tokens. Each token
// is a reference to an asset in 'assets.json'. // is a reference to an asset in 'assets.json', or a URL for lists not
if ( Array.isArray(data.selectedFilterLists) ) { // present in 'assets.json'.
if (
Array.isArray(toOverwrite.filterLists) &&
toOverwrite.filterLists.length !== 0
) {
const externalLists = [];
for ( const list of toOverwrite.filterLists ) {
if ( /^[a-z-]+:\/\//.test(list) === false ) { continue; }
externalLists.push(list);
}
if ( externalLists.length !== 0 ) {
bin.externalLists = externalLists;
}
bin.selectedFilterLists = toOverwrite.filterLists;
binNotEmpty = true;
} else if ( Array.isArray(data.selectedFilterLists) ) {
bin.selectedFilterLists = data.selectedFilterLists; bin.selectedFilterLists = data.selectedFilterLists;
binNotEmpty = true; binNotEmpty = true;
} }
if ( Array.isArray(toOverwrite.trustedSiteDirectives) ) { if (
Array.isArray(toOverwrite.trustedSiteDirectives) &&
toOverwrite.trustedSiteDirectives.length !== 0
) {
µBlock.netWhitelistDefault = toOverwrite.trustedSiteDirectives.slice(); µBlock.netWhitelistDefault = toOverwrite.trustedSiteDirectives.slice();
bin.netWhitelist = toOverwrite.trustedSiteDirectives.slice(); bin.netWhitelist = toOverwrite.trustedSiteDirectives.slice();
binNotEmpty = true; binNotEmpty = true;