mirror of https://github.com/gorhill/uBlock.git
Add `userSettings` entry to managed storage
The managed `userSettings` entry is an array of entries, where each entry is a name/value pair encoded into an array of strings. The first item in the entry array is the name of a setting, and the second item is the stringified value for the setting. This is a more convenient way for administrators to set specific user settings. The settings set through `userSettings` policy will always be set at uBO launch time.
This commit is contained in:
parent
2f4952e769
commit
6eb1246508
|
@ -16,6 +16,15 @@
|
|||
"items": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"userSettings": {
|
||||
"title": "A list of [name,value] pairs to populate user settings",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"title": "A [name,value] pair",
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"disableDashboard": {
|
||||
"title": "Set to true to prevent access to configuration options",
|
||||
"type": "boolean"
|
||||
|
|
|
@ -83,29 +83,32 @@ const µBlock = (( ) => { // jshint ignore:line
|
|||
userResourcesLocation: 'unset',
|
||||
};
|
||||
|
||||
const userSettingsDefault = {
|
||||
advancedUserEnabled: false,
|
||||
alwaysDetachLogger: true,
|
||||
autoUpdate: true,
|
||||
cloudStorageEnabled: false,
|
||||
collapseBlocked: true,
|
||||
colorBlindFriendly: false,
|
||||
contextMenuEnabled: true,
|
||||
dynamicFilteringEnabled: false,
|
||||
externalLists: [],
|
||||
firewallPaneMinimized: true,
|
||||
hyperlinkAuditingDisabled: true,
|
||||
ignoreGenericCosmeticFilters: vAPI.webextFlavor.soup.has('mobile'),
|
||||
largeMediaSize: 50,
|
||||
parseAllABPHideFilters: true,
|
||||
popupPanelSections: 0b111,
|
||||
prefetchingDisabled: true,
|
||||
requestLogMaxEntries: 1000,
|
||||
showIconBadge: true,
|
||||
tooltipsDisabled: false,
|
||||
webrtcIPAddressHidden: false,
|
||||
};
|
||||
|
||||
return {
|
||||
userSettings: {
|
||||
advancedUserEnabled: false,
|
||||
alwaysDetachLogger: true,
|
||||
autoUpdate: true,
|
||||
cloudStorageEnabled: false,
|
||||
collapseBlocked: true,
|
||||
colorBlindFriendly: false,
|
||||
contextMenuEnabled: true,
|
||||
dynamicFilteringEnabled: false,
|
||||
externalLists: [],
|
||||
firewallPaneMinimized: true,
|
||||
hyperlinkAuditingDisabled: true,
|
||||
ignoreGenericCosmeticFilters: vAPI.webextFlavor.soup.has('mobile'),
|
||||
largeMediaSize: 50,
|
||||
parseAllABPHideFilters: true,
|
||||
popupPanelSections: 0b111,
|
||||
prefetchingDisabled: true,
|
||||
requestLogMaxEntries: 1000,
|
||||
showIconBadge: true,
|
||||
tooltipsDisabled: false,
|
||||
webrtcIPAddressHidden: false,
|
||||
},
|
||||
userSettingsDefault: userSettingsDefault,
|
||||
userSettings: Object.assign({}, userSettingsDefault),
|
||||
|
||||
hiddenSettingsDefault: hiddenSettingsDefault,
|
||||
hiddenSettingsAdmin: {},
|
||||
|
|
|
@ -912,12 +912,12 @@ const backupUserData = async function() {
|
|||
const userData = {
|
||||
timeStamp: Date.now(),
|
||||
version: vAPI.app.version,
|
||||
userSettings: µb.userSettings,
|
||||
userSettings:
|
||||
µb.getModifiedSettings(µb.userSettings, µb.userSettingsDefault),
|
||||
selectedFilterLists: µb.selectedFilterLists,
|
||||
hiddenSettings: µb.getModifiedHiddenSettings(),
|
||||
hiddenSettings:
|
||||
µb.getModifiedSettings(µb.hiddenSettings, µb.hiddenSettingsDefault),
|
||||
whitelist: µb.arrayFromWhitelist(µb.netWhitelist),
|
||||
// String representation eventually to be deprecated
|
||||
netWhitelist: µb.stringFromWhitelist(µb.netWhitelist),
|
||||
dynamicFilteringString: µb.permanentFirewall.toString(),
|
||||
urlFilteringString: µb.permanentURLFiltering.toString(),
|
||||
hostnameSwitchesString: µb.permanentSwitches.toString(),
|
||||
|
|
|
@ -160,30 +160,21 @@ const onNetWhitelistReady = function(netWhitelistRaw, adminExtra) {
|
|||
// User settings are in memory
|
||||
|
||||
const onUserSettingsReady = function(fetched) {
|
||||
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(µb.userSettings, fetched);
|
||||
|
||||
if ( µb.privacySettingsSupported ) {
|
||||
vAPI.browserSettings.set({
|
||||
'hyperlinkAuditing': !userSettings.hyperlinkAuditingDisabled,
|
||||
'prefetching': !userSettings.prefetchingDisabled,
|
||||
'webrtcIPAddress': !userSettings.webrtcIPAddressHidden
|
||||
'hyperlinkAuditing': !µb.userSettings.hyperlinkAuditingDisabled,
|
||||
'prefetching': !µb.userSettings.prefetchingDisabled,
|
||||
'webrtcIPAddress': !µb.userSettings.webrtcIPAddressHidden
|
||||
});
|
||||
}
|
||||
|
||||
µ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);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -219,8 +210,15 @@ const onFirstFetchReady = function(fetched, adminExtra) {
|
|||
|
||||
// Order is important -- do not change:
|
||||
fromFetch(µb.localSettings, fetched);
|
||||
onUserSettingsReady(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);
|
||||
|
||||
onNetWhitelistReady(fetched.netWhitelist, adminExtra);
|
||||
onVersionReady(fetched.version);
|
||||
};
|
||||
|
@ -269,7 +267,6 @@ const createDefaultProps = function() {
|
|||
fetchableProps.hostnameSwitchesString += '\nno-csp-reports: * true';
|
||||
}
|
||||
toFetch(µb.localSettings, fetchableProps);
|
||||
toFetch(µb.userSettings, fetchableProps);
|
||||
toFetch(µb.restoreBackupSettings, fetchableProps);
|
||||
return fetchableProps;
|
||||
};
|
||||
|
@ -321,6 +318,10 @@ try {
|
|||
log.info(`First fetch ready ${Date.now()-vAPI.T0} ms after launch`);
|
||||
onFirstFetchReady(fetched, adminExtra);
|
||||
}),
|
||||
µb.loadUserSettings().then(fetched => {
|
||||
log.info(`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`);
|
||||
}),
|
||||
|
|
|
@ -83,8 +83,49 @@
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
µBlock.loadUserSettings = async function() {
|
||||
const usDefault = this.userSettingsDefault;
|
||||
|
||||
const results = await Promise.all([
|
||||
vAPI.storage.get(Object.assign(usDefault)),
|
||||
vAPI.adminStorage.get('userSettings'),
|
||||
]);
|
||||
|
||||
const usUser = results[0] instanceof Object && results[0] ||
|
||||
Object.assign(usDefault);
|
||||
|
||||
if ( Array.isArray(results[1]) ) {
|
||||
const adminSettings = results[1];
|
||||
for ( const entry of adminSettings ) {
|
||||
if ( entry.length < 1 ) { continue; }
|
||||
const name = entry[0];
|
||||
if ( usDefault.hasOwnProperty(name) === false ) { continue; }
|
||||
const value = entry.length < 2
|
||||
? usDefault[name]
|
||||
: this.settingValueFromString(usDefault, name, entry[1]);
|
||||
if ( value === undefined ) { continue; }
|
||||
usUser[name] = usDefault[name] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return usUser;
|
||||
};
|
||||
|
||||
µBlock.saveUserSettings = function() {
|
||||
vAPI.storage.set(this.userSettings);
|
||||
const toSave = this.getModifiedSettings(
|
||||
this.userSettings,
|
||||
this.userSettingsDefault
|
||||
);
|
||||
const toRemove = [];
|
||||
for ( const key in this.userSettings ) {
|
||||
if ( this.userSettings.hasOwnProperty(key) === false ) { continue; }
|
||||
if ( toSave.hasOwnProperty(key) === false ) { continue; }
|
||||
toRemove.push(key);
|
||||
}
|
||||
if ( toRemove.length !== 0 ) {
|
||||
vAPI.storage.remove(toRemove);
|
||||
}
|
||||
vAPI.storage.set(toSave);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -164,24 +205,16 @@
|
|||
};
|
||||
|
||||
// Note: Save only the settings which values differ from the default ones.
|
||||
// This way the new default values in the future will properly apply for those
|
||||
// which were not modified by the user.
|
||||
|
||||
µBlock.getModifiedHiddenSettings = function() {
|
||||
const out = {};
|
||||
for ( const prop in this.hiddenSettings ) {
|
||||
if (
|
||||
this.hiddenSettings.hasOwnProperty(prop) &&
|
||||
this.hiddenSettings[prop] !== this.hiddenSettingsDefault[prop]
|
||||
) {
|
||||
out[prop] = this.hiddenSettings[prop];
|
||||
}
|
||||
}
|
||||
return out;
|
||||
};
|
||||
// This way the new default values in the future will properly apply for
|
||||
// those which were not modified by the user.
|
||||
|
||||
µBlock.saveHiddenSettings = function() {
|
||||
vAPI.storage.set({ hiddenSettings: this.getModifiedHiddenSettings() });
|
||||
vAPI.storage.set({
|
||||
hiddenSettings: this.getModifiedSettings(
|
||||
this.hiddenSettings,
|
||||
this.hiddenSettingsDefault
|
||||
)
|
||||
});
|
||||
};
|
||||
|
||||
self.addEventListener('hiddenSettingsChanged', ( ) => {
|
||||
|
@ -404,7 +437,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
|
|||
const result = Array.from(selectedListKeySet);
|
||||
if ( externalLists.join() !== this.userSettings.externalLists.join() ) {
|
||||
this.userSettings.externalLists = externalLists;
|
||||
vAPI.storage.set({ externalLists });
|
||||
this.saveUserSettings();
|
||||
}
|
||||
this.saveSelectedFilterLists(result);
|
||||
};
|
||||
|
@ -599,7 +632,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
|
|||
this.assets.registerAssetSource(listURL, newEntry);
|
||||
importedListKeys.push(listURL);
|
||||
this.userSettings.externalLists.push(listURL.trim());
|
||||
vAPI.storage.set({ externalLists: this.userSettings.externalLists });
|
||||
this.saveUserSettings();
|
||||
this.saveSelectedFilterLists([ listURL ], true);
|
||||
};
|
||||
|
||||
|
|
|
@ -684,3 +684,46 @@
|
|||
window.dispatchEvent(new CustomEvent(name));
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
µBlock.getModifiedSettings = function(edit, orig = {}) {
|
||||
const out = {};
|
||||
for ( const prop in edit ) {
|
||||
if ( orig.hasOwnProperty(prop) && edit[prop] !== orig[prop] ) {
|
||||
out[prop] = edit[prop];
|
||||
}
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
µBlock.settingValueFromString = function(orig, name, s) {
|
||||
if ( typeof name !== 'string' || typeof s !== 'string' ) { return; }
|
||||
if ( orig.hasOwnProperty(name) === false ) { return; }
|
||||
let r;
|
||||
switch ( typeof orig[name] ) {
|
||||
case 'boolean':
|
||||
if ( s === 'true' ) {
|
||||
r = true;
|
||||
} else if ( s === 'false' ) {
|
||||
r = false;
|
||||
}
|
||||
break;
|
||||
case 'string':
|
||||
r = s.trim();
|
||||
break;
|
||||
case 'number':
|
||||
if ( s.startsWith('0b') ) {
|
||||
r = parseInt(s.slice(2), 2);
|
||||
} else if ( s.startsWith('0x') ) {
|
||||
r = parseInt(s.slice(2), 16);
|
||||
} else {
|
||||
r = parseInt(s, 10);
|
||||
}
|
||||
if ( isNaN(r) ) { r = undefined; }
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue