Improve "Whitelist pane"; remove now useless built-in switch rule

Related issue:
- https://github.com/uBlockOrigin/uBlock-issues/issues/214

Built-in whitelist directives are now rendered differently
than user-defined whitelist directives. Also, removing a
built-in whitelist directive will only cause that directive
to be commented out, so that users do not have to remember
built-in directives should they want to bring them back.

Related issue:
 https://github.com/uBlockOrigin/uBlock-issues/issues/494

The built-in per-site switch rule
`no-scripting: behind-the-scene false` has been removed,
it should not ever be needed since there will always be a
valid root context for main- and sub-frames.
This commit is contained in:
Raymond Hill 2019-05-18 14:20:05 -04:00
parent de41c1bf53
commit f7bbc80717
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
7 changed files with 125 additions and 81 deletions

View File

@ -10,3 +10,9 @@ body {
text-align: left;
width: 100%;
}
.codeMirrorContainer .cm-builtin {
color: #00F;
}
.codeMirrorContainer .cm-comment.cm-builtin {
color: #88F;
}

View File

@ -57,16 +57,6 @@ const µBlock = (function() { // jshint ignore:line
userResourcesLocation: 'unset'
};
const whitelistDefault = [
'about-scheme',
'chrome-extension-scheme',
'chrome-scheme',
'moz-extension-scheme',
'opera-scheme',
'vivaldi-scheme',
'wyciwyg-scheme', // Firefox's "What-You-Cache-Is-What-You-Get"
];
return {
firstInstall: false,
@ -126,7 +116,15 @@ const µBlock = (function() { // jshint ignore:line
// Whitelist directives need to be loaded once the PSL is available
netWhitelist: {},
netWhitelistModifyTime: 0,
netWhitelistDefault: whitelistDefault.join('\n'),
netWhitelistDefault: [
'about-scheme',
'chrome-extension-scheme',
'chrome-scheme',
'moz-extension-scheme',
'opera-scheme',
'vivaldi-scheme',
'wyciwyg-scheme', // Firefox's "What-You-Cache-Is-What-You-Get"
],
localSettings: {
blockedRequestCount: 0,

View File

@ -91,7 +91,7 @@
µBlock.normalizePageURL(0, details.documentUrl)
);
this.setDocOrigin(origin).setTabOrigin(origin);
} else if ( this.type === 'sub_frame' ) {
} else if ( this.type.endsWith('_frame') ) {
const origin = this.originFromURI(this.url);
this.setDocOrigin(origin).setTabOrigin(origin);
} else {

View File

@ -30,24 +30,17 @@
/******************************************************************************/
var µb = µBlock;
const µb = µBlock;
/******************************************************************************/
var getDomainNames = function(targets) {
var out = [];
var µburi = µb.URI;
var target, domain;
for ( var i = 0; i < targets.length; i++ ) {
target = targets[i];
if ( target.indexOf('/') !== -1 ) {
domain = µburi.domainFromURI(target) || '';
} else {
domain = µburi.domainFromHostname(target) || target;
}
out.push(domain);
}
return out;
const getDomainNames = function(targets) {
const µburi = µb.URI;
return targets.map(target =>
target.indexOf('/') !== -1
? µburi.domainFromURI(target) || ''
: µburi.domainFromHostname(target) || target
);
};
/******************************************************************************/
@ -128,7 +121,8 @@ const onMessage = function(request, sender, callback) {
case 'getWhitelist':
response = {
whitelist: µb.stringFromWhitelist(µb.netWhitelist),
whitelist: µb.arrayFromWhitelist(µb.netWhitelist),
whitelistDefault: µb.netWhitelistDefault,
reBadHostname: µb.reWhitelistBadHostname.source,
reHostnameExtractor: µb.reWhitelistHostnameExtractor.source
};

View File

@ -208,9 +208,11 @@ const onVersionReady = function(lastVersion) {
const lastVersionInt = intFromVersion(lastVersion);
if ( lastVersionInt <= 1016021007 ) {
µb.sessionSwitches.toggle('no-scripting', 'behind-the-scene', 2);
µb.permanentSwitches.toggle('no-scripting', 'behind-the-scene', 2);
// https://github.com/uBlockOrigin/uBlock-issues/issues/494
// Remove useless per-site switches.
if ( lastVersionInt <= 1019003007 ) {
µb.sessionSwitches.toggle('no-scripting', 'behind-the-scene', 0);
µb.permanentSwitches.toggle('no-scripting', 'behind-the-scene', 0);
µb.saveHostnameSwitches();
}
@ -347,13 +349,12 @@ const createDefaultProps = function() {
'urlFilteringString': '',
'hostnameSwitchesString': [
'no-large-media: behind-the-scene false',
'no-scripting: behind-the-scene false'
].join('\n'),
'lastRestoreFile': '',
'lastRestoreTime': 0,
'lastBackupFile': '',
'lastBackupTime': 0,
'netWhitelist': µb.netWhitelistDefault,
'netWhitelist': µb.netWhitelistDefault.join('\n'),
'selfieMagic': 0,
'version': '0.0.0.0'
};

View File

@ -177,17 +177,19 @@ var matchBucket = function(url, hostname, bucket, start) {
/******************************************************************************/
µBlock.arrayFromWhitelist = function(whitelist) {
const out = new Set();
for ( const key in whitelist ) {
const bucket = whitelist[key];
for ( const directive of bucket ) {
out.add(directive);
}
}
return Array.from(out).sort((a, b) => a.localeCompare(b));
};
µBlock.stringFromWhitelist = function(whitelist) {
var r = {};
var i, bucket;
for ( var key in whitelist ) {
bucket = whitelist[key];
i = bucket.length;
while ( i-- ) {
r[bucket[i]] = true;
}
}
return Object.keys(r).sort(function(a,b){return a.localeCompare(b);}).join('\n');
return this.arrayFromWhitelist(whitelist).join('\n');
};
/******************************************************************************/

View File

@ -25,26 +25,42 @@
/******************************************************************************/
(function() {
(( ) => {
/******************************************************************************/
const reComment = /^\s*#\s*/;
const directiveFromLine = function(line) {
const match = reComment.exec(line);
return match === null
? line.trim()
: line.slice(match.index + match[0].length).trim();
};
/******************************************************************************/
CodeMirror.defineMode("ubo-whitelist-directives", function() {
var reComment = /^\s*#/,
reRegex = /^\/.+\/$/;
const reRegex = /^\/.+\/$/;
return {
token: function(stream) {
var line = stream.string.trim();
const line = stream.string.trim();
stream.skipToEnd();
if ( reBadHostname === undefined ) {
return null;
}
if ( reComment.test(line) ) {
return 'comment';
return whitelistDefaultSet.has(directiveFromLine(line))
? 'builtin comment'
: 'comment';
}
if ( line.indexOf('/') === -1 ) {
return reBadHostname.test(line) ? 'error' : null;
if ( reBadHostname.test(line) ) { return 'error'; }
if ( whitelistDefaultSet.has(line.trim()) ) {
return 'builtin';
}
return null;
}
if ( reRegex.test(line) ) {
try {
@ -59,16 +75,18 @@ CodeMirror.defineMode("ubo-whitelist-directives", function() {
};
});
var reBadHostname,
reHostnameExtractor;
let reBadHostname;
let reHostnameExtractor;
let whitelistDefaultSet = new Set();
/******************************************************************************/
var messaging = vAPI.messaging,
cachedWhitelist = '',
noopFunc = function(){};
const messaging = vAPI.messaging;
const noopFunc = function(){};
var cmEditor = new CodeMirror(
let cachedWhitelist = '';
const cmEditor = new CodeMirror(
document.getElementById('whitelist'),
{
autofocus: true,
@ -82,11 +100,11 @@ uBlockDashboard.patchCodeMirrorEditor(cmEditor);
/******************************************************************************/
var whitelistChanged = function() {
var whitelistElem = uDom.nodeFromId('whitelist');
var bad = whitelistElem.querySelector('.cm-error') !== null;
var changedWhitelist = cmEditor.getValue().trim();
var changed = changedWhitelist !== cachedWhitelist;
const whitelistChanged = function() {
const whitelistElem = uDom.nodeFromId('whitelist');
const bad = whitelistElem.querySelector('.cm-error') !== null;
const changedWhitelist = cmEditor.getValue().trim();
const changed = changedWhitelist !== cachedWhitelist;
uDom.nodeFromId('whitelistApply').disabled = !changed || bad;
uDom.nodeFromId('whitelistRevert').disabled = !changed;
CodeMirror.commands.save = changed && !bad ? applyChanges : noopFunc;
@ -96,15 +114,39 @@ cmEditor.on('changes', whitelistChanged);
/******************************************************************************/
var renderWhitelist = function() {
var onRead = function(details) {
var first = reBadHostname === undefined;
const renderWhitelist = function() {
const onRead = details => {
const first = reBadHostname === undefined;
if ( first ) {
reBadHostname = new RegExp(details.reBadHostname);
reHostnameExtractor = new RegExp(details.reHostnameExtractor);
whitelistDefaultSet = new Set(details.whitelistDefault);
}
cachedWhitelist = details.whitelist.trim();
cmEditor.setValue(cachedWhitelist + '\n');
const toAdd = new Set(whitelistDefaultSet);
for ( const line of details.whitelist ) {
const directive = directiveFromLine(line);
if ( whitelistDefaultSet.has(directive) === false ) { continue; }
toAdd.delete(directive);
if ( toAdd.size === 0 ) { break; }
}
if ( toAdd.size !== 0 ) {
details.whitelist.push(...Array.from(toAdd).map(a => `# ${a}`));
}
details.whitelist.sort((a, b) => {
const ad = directiveFromLine(a);
const bd = directiveFromLine(b);
const abuiltin = whitelistDefaultSet.has(ad);
if ( abuiltin !== whitelistDefaultSet.has(bd) ) {
return abuiltin ? -1 : 1;
}
return ad.localeCompare(bd);
});
let whitelistStr = details.whitelist.join('\n').trim();
cachedWhitelist = whitelistStr;
if ( whitelistStr !== '' ) {
whitelistStr += '\n';
}
cmEditor.setValue(whitelistStr);
if ( first ) {
cmEditor.clearHistory();
}
@ -114,8 +156,8 @@ var renderWhitelist = function() {
/******************************************************************************/
var handleImportFilePicker = function() {
var fileReaderOnLoadHandler = function() {
const handleImportFilePicker = function() {
const fileReaderOnLoadHandler = ( ) => {
cmEditor.setValue(
[
cmEditor.getValue().trim(),
@ -123,18 +165,18 @@ var handleImportFilePicker = function() {
].join('\n').trim()
);
};
var file = this.files[0];
const file = this.files[0];
if ( file === undefined || file.name === '' ) { return; }
if ( file.type.indexOf('text') !== 0 ) { return; }
var fr = new FileReader();
const fr = new FileReader();
fr.onload = fileReaderOnLoadHandler;
fr.readAsText(file);
};
/******************************************************************************/
var startImportFilePicker = function() {
var input = document.getElementById('importFilePicker');
const startImportFilePicker = function() {
const input = document.getElementById('importFilePicker');
// Reset to empty string, this will ensure an change event is properly
// triggered if the user pick a file, even if it is the same as the last
// one picked.
@ -144,21 +186,22 @@ var startImportFilePicker = function() {
/******************************************************************************/
var exportWhitelistToFile = function() {
var val = cmEditor.getValue().trim();
const exportWhitelistToFile = function() {
const val = cmEditor.getValue().trim();
if ( val === '' ) { return; }
var filename = vAPI.i18n('whitelistExportFilename')
const filename =
vAPI.i18n('whitelistExportFilename')
.replace('{{datetime}}', uBlockDashboard.dateNowToSensibleString())
.replace(/ +/g, '_');
vAPI.download({
'url': 'data:text/plain;charset=utf-8,' + encodeURIComponent(val + '\n'),
'url': `data:text/plain;charset=utf-8,${encodeURIComponent(val + '\n')}`,
'filename': filename
});
};
/******************************************************************************/
var applyChanges = function() {
const applyChanges = function() {
cachedWhitelist = cmEditor.getValue().trim();
messaging.send(
'dashboard',
@ -170,19 +213,19 @@ var applyChanges = function() {
);
};
var revertChanges = function() {
var content = cachedWhitelist;
const revertChanges = function() {
let content = cachedWhitelist;
if ( content !== '' ) { content += '\n'; }
cmEditor.setValue(content);
};
/******************************************************************************/
var getCloudData = function() {
const getCloudData = function() {
return cmEditor.getValue();
};
var setCloudData = function(data, append) {
const setCloudData = function(data, append) {
if ( typeof data !== 'string' ) { return; }
if ( append ) {
data = uBlockDashboard.mergeNewLines(cmEditor.getValue().trim(), data);