1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-11-24 19:33:01 +01:00
This commit is contained in:
Raymond Hill 2018-09-03 14:06:49 -04:00
parent 3ef4005f63
commit 6d34a52179
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
12 changed files with 406 additions and 317 deletions

View File

@ -127,7 +127,8 @@ var proceedPermanent = function() {
name: 'no-strict-blocking',
hostname: getTargetHostname(),
deep: true,
state: true
state: true,
persist: true
},
proceedToURL
);

View File

@ -1,7 +1,7 @@
/*******************************************************************************
uBlock Origin - a browser extension to block requests.
Copyright (C) 2014-2018 Raymond Hill
Copyright (C) 2014-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
@ -67,12 +67,12 @@ var differ;
// ... and modified as needed.
var updateOverlay = (function() {
var reFilter;
var mode = {
let reFilter;
let mode = {
token: function(stream) {
if ( reFilter !== undefined ) {
reFilter.lastIndex = stream.pos;
var match = reFilter.exec(stream.string);
let match = reFilter.exec(stream.string);
if ( match !== null ) {
if ( match.index === stream.pos ) {
stream.pos += match[0].length || 1;
@ -100,35 +100,38 @@ var updateOverlay = (function() {
// - Minimum amount of text updated
var rulesToDoc = function(clearHistory) {
for ( var key in unfilteredRules ) {
for ( let key in unfilteredRules ) {
if ( unfilteredRules.hasOwnProperty(key) === false ) { continue; }
var doc = unfilteredRules[key].doc;
var rules = filterRules(key);
if ( doc.lineCount() === 1 && doc.getValue() === '' || rules.length === 0 ) {
let doc = unfilteredRules[key].doc;
let rules = filterRules(key);
if (
doc.lineCount() === 1 && doc.getValue() === '' ||
rules.length === 0
) {
doc.setValue(rules.length !== 0 ? rules.join('\n') : '');
continue;
}
if ( differ === undefined ) { differ = new diff_match_patch(); }
var beforeText = doc.getValue();
var afterText = rules.join('\n');
var diffs = differ.diff_main(beforeText, afterText);
let beforeText = doc.getValue();
let afterText = rules.join('\n');
let diffs = differ.diff_main(beforeText, afterText);
doc.startOperation();
var i = diffs.length,
let i = diffs.length,
iedit = beforeText.length;
while ( i-- ) {
var diff = diffs[i];
let diff = diffs[i];
if ( diff[0] === 0 ) {
iedit -= diff[1].length;
continue;
}
var end = doc.posFromIndex(iedit);
let end = doc.posFromIndex(iedit);
if ( diff[0] === 1 ) {
doc.replaceRange(diff[1], end, end);
continue;
}
/* diff[0] === -1 */
iedit -= diff[1].length;
var beg = doc.posFromIndex(iedit);
let beg = doc.posFromIndex(iedit);
doc.replaceRange('', beg, end);
}
doc.endOperation();
@ -143,11 +146,11 @@ var rulesToDoc = function(clearHistory) {
/******************************************************************************/
var filterRules = function(key) {
var rules = unfilteredRules[key].rules;
var filter = uDom('#ruleFilter input').val();
let rules = unfilteredRules[key].rules;
let filter = uDom.nodeFromSelector('#ruleFilter input').value;
if ( filter !== '' ) {
rules = rules.slice();
var i = rules.length;
let i = rules.length;
while ( i-- ) {
if ( rules[i].indexOf(filter) === -1 ) {
rules.splice(i, 1);
@ -160,16 +163,23 @@ var filterRules = function(key) {
/******************************************************************************/
var renderRules = (function() {
var firstVisit = true;
let firstVisit = true;
let reIsSwitchRule = /^[a-z-]+: /;
// Switches always listed at the top.
let customSort = (a, b) => {
let aIsSwitch = reIsSwitchRule.test(a);
if ( reIsSwitchRule.test(b) === aIsSwitch ) {
return a.localeCompare(b);
}
return aIsSwitch ? -1 : 1;
};
return function(details) {
details.hnSwitches.sort();
details.permanentRules.sort();
details.sessionRules.sort();
unfilteredRules.orig.rules =
details.hnSwitches.concat(details.permanentRules);
unfilteredRules.edit.rules =
details.hnSwitches.concat(details.sessionRules);
details.permanentRules.sort(customSort);
details.sessionRules.sort(customSort);
unfilteredRules.orig.rules = details.permanentRules;
unfilteredRules.edit.rules = details.sessionRules;
rulesToDoc(firstVisit);
if ( firstVisit ) {
firstVisit = false;
@ -206,20 +216,19 @@ mergeView.options.revertChunk = function(
) {
// https://github.com/gorhill/uBlock/issues/3611
if ( document.body.getAttribute('dir') === 'rtl' ) {
var tmp;
tmp = from; from = to; to = tmp;
let tmp = from; from = to; to = tmp;
tmp = fromStart; fromStart = toStart; toStart = tmp;
tmp = fromEnd; fromEnd = toEnd; toEnd = tmp;
}
if ( typeof fromStart.ch !== 'number' ) { fromStart.ch = 0; }
if ( fromEnd.ch !== 0 ) { fromEnd.line += 1; }
var toAdd = from.getRange(
let toAdd = from.getRange(
{ line: fromStart.line, ch: 0 },
{ line: fromEnd.line, ch: 0 }
);
if ( typeof toStart.ch !== 'number' ) { toStart.ch = 0; }
if ( toEnd.ch !== 0 ) { toEnd.line += 1; }
var toRemove = to.getRange(
let toRemove = to.getRange(
{ line: toStart.line, ch: 0 },
{ line: toEnd.line, ch: 0 }
);
@ -229,12 +238,12 @@ mergeView.options.revertChunk = function(
/******************************************************************************/
function handleImportFilePicker() {
var fileReaderOnLoadHandler = function() {
let fileReaderOnLoadHandler = function() {
if ( typeof this.result !== 'string' || this.result === '' ) { return; }
// https://github.com/chrisaljoudi/uBlock/issues/757
// Support RequestPolicy rule syntax
var result = this.result;
var matches = /\[origins-to-destinations\]([^\[]+)/.exec(result);
let result = this.result;
let matches = /\[origins-to-destinations\]([^\[]+)/.exec(result);
if ( matches && matches.length === 2 ) {
result = matches[1].trim()
.replace(/\|/g, ' ')
@ -242,10 +251,10 @@ function handleImportFilePicker() {
}
applyDiff(false, result, '');
};
var file = this.files[0];
let file = this.files[0];
if ( file === undefined || file.name === '' ) { return; }
if ( file.type.indexOf('text') !== 0 ) { return; }
var fr = new FileReader();
let fr = new FileReader();
fr.onload = fileReaderOnLoadHandler;
fr.readAsText(file);
}
@ -253,7 +262,7 @@ function handleImportFilePicker() {
/******************************************************************************/
var startImportFilePicker = function() {
var input = document.getElementById('importFilePicker');
let 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.
@ -264,7 +273,7 @@ var startImportFilePicker = function() {
/******************************************************************************/
function exportUserRulesToFile() {
var filename = vAPI.i18n('rulesDefaultFileName')
let filename = vAPI.i18n('rulesDefaultFileName')
.replace('{{datetime}}', uBlockDashboard.dateNowToSensibleString())
.replace(/ +/g, '_');
vAPI.download({
@ -279,14 +288,14 @@ function exportUserRulesToFile() {
/******************************************************************************/
var onFilterChanged = (function() {
var timer,
let timer,
overlay = null,
last = '';
var process = function() {
let process = function() {
timer = undefined;
if ( mergeView.editor().isClean(cleanEditToken) === false ) { return; }
var filter = uDom('#ruleFilter input').val();
let filter = uDom.nodeFromSelector('#ruleFilter input').value;
if ( filter === last ) { return; }
last = filter;
if ( overlay !== null ) {
@ -311,12 +320,12 @@ var onFilterChanged = (function() {
/******************************************************************************/
var onTextChanged = (function() {
var timer;
let timer;
var process = function(now) {
let process = function(now) {
timer = undefined;
var isClean = mergeView.editor().isClean(cleanEditToken);
var diff = document.getElementById('diff');
let isClean = mergeView.editor().isClean(cleanEditToken);
let diff = document.getElementById('diff');
if (
now &&
isClean === false &&
@ -331,7 +340,7 @@ var onTextChanged = (function() {
'disabled',
isClean
);
var input = document.querySelector('#ruleFilter input');
let input = document.querySelector('#ruleFilter input');
if ( isClean ) {
input.removeAttribute('disabled');
CodeMirror.commands.save = undefined;
@ -350,15 +359,15 @@ var onTextChanged = (function() {
/******************************************************************************/
var revertAllHandler = function() {
var toAdd = [], toRemove = [];
var left = mergeView.leftOriginal(),
let toAdd = [], toRemove = [];
let left = mergeView.leftOriginal(),
edit = mergeView.editor();
for ( var chunk of mergeView.leftChunks() ) {
var addedLines = left.getRange(
for ( let chunk of mergeView.leftChunks() ) {
let addedLines = left.getRange(
{ line: chunk.origFrom, ch: 0 },
{ line: chunk.origTo, ch: 0 }
);
var removedLines = edit.getRange(
let removedLines = edit.getRange(
{ line: chunk.editFrom, ch: 0 },
{ line: chunk.editTo, ch: 0 }
);
@ -371,15 +380,15 @@ var revertAllHandler = function() {
/******************************************************************************/
var commitAllHandler = function() {
var toAdd = [], toRemove = [];
var left = mergeView.leftOriginal(),
let toAdd = [], toRemove = [];
let left = mergeView.leftOriginal(),
edit = mergeView.editor();
for ( var chunk of mergeView.leftChunks() ) {
var addedLines = edit.getRange(
for ( let chunk of mergeView.leftChunks() ) {
let addedLines = edit.getRange(
{ line: chunk.editFrom, ch: 0 },
{ line: chunk.editTo, ch: 0 }
);
var removedLines = left.getRange(
let removedLines = left.getRange(
{ line: chunk.origFrom, ch: 0 },
{ line: chunk.origTo, ch: 0 }
);
@ -392,16 +401,16 @@ var commitAllHandler = function() {
/******************************************************************************/
var editSaveHandler = function() {
var editor = mergeView.editor();
var editText = editor.getValue().trim();
let editor = mergeView.editor();
let editText = editor.getValue().trim();
if ( editText === cleanEditText ) {
onTextChanged(true);
return;
}
if ( differ === undefined ) { differ = new diff_match_patch(); }
var toAdd = [], toRemove = [];
var diffs = differ.diff_main(cleanEditText, editText);
for ( var diff of diffs ) {
let toAdd = [], toRemove = [];
let diffs = differ.diff_main(cleanEditText, editText);
for ( let diff of diffs ) {
if ( diff[0] === 1 ) {
toAdd.push(diff[1]);
} else if ( diff[0] === -1 ) {

View File

@ -107,45 +107,59 @@ Matrix.prototype.assign = function(other) {
/******************************************************************************/
Matrix.prototype.copyRules = function(other, srcHostname, desHostnames) {
Matrix.prototype.copyRules = function(from, srcHostname, desHostnames) {
// Specific types
var bits = other.rules.get('* *');
if ( bits !== undefined ) {
this.rules.set('* *', bits);
} else {
this.rules.delete('* *');
let thisBits = this.rules.get('* *');
let fromBits = from.rules.get('* *');
if ( fromBits !== thisBits ) {
if ( fromBits !== undefined ) {
this.rules.set('* *', fromBits);
} else {
this.rules.delete('* *');
}
this.changed = true;
}
var key = srcHostname + ' *';
bits = other.rules.get(key);
if ( bits !== undefined ) {
this.rules.set(key, bits);
} else {
this.rules.delete(key);
let key = srcHostname + ' *';
thisBits = this.rules.get(key);
fromBits = from.rules.get(key);
if ( fromBits !== thisBits ) {
if ( fromBits !== undefined ) {
this.rules.set(key, fromBits);
} else {
this.rules.delete(key);
}
this.changed = true;
}
// Specific destinations
for ( var desHostname in desHostnames ) {
for ( let desHostname in desHostnames ) {
if ( desHostnames.hasOwnProperty(desHostname) === false ) { continue; }
key = '* ' + desHostname;
bits = other.rules.get(key);
if ( bits !== undefined ) {
this.rules.set(key, bits);
} else {
this.rules.delete(key);
thisBits = this.rules.get(key);
fromBits = from.rules.get(key);
if ( fromBits !== thisBits ) {
if ( fromBits !== undefined ) {
this.rules.set(key, fromBits);
} else {
this.rules.delete(key);
}
this.changed = true;
}
key = srcHostname + ' ' + desHostname ;
bits = other.rules.get(key);
if ( bits !== undefined ) {
this.rules.set(key, bits);
} else {
this.rules.delete(key);
thisBits = this.rules.get(key);
fromBits = from.rules.get(key);
if ( fromBits !== thisBits ) {
if ( fromBits !== undefined ) {
this.rules.set(key, fromBits);
} else {
this.rules.delete(key);
}
this.changed = true;
}
}
this.changed = true;
return true;
return this.changed;
};
/******************************************************************************/

View File

@ -80,17 +80,54 @@ HnSwitches.prototype.reset = function() {
/******************************************************************************/
HnSwitches.prototype.assign = function(from) {
// Remove rules not in other
for ( let hn of this.switches.keys() ) {
if ( from.switches.has(hn) === false ) {
this.switches.delete(hn);
this.changed = true;
}
}
// Add/change rules in other
for ( let [hn, bits] of from.switches ) {
if ( this.switches.get(hn) !== bits ) {
this.switches.set(hn, bits);
this.changed = true;
}
}
};
/******************************************************************************/
HnSwitches.prototype.copyRules = function(from, srcHostname) {
let thisBits = this.switches.get(srcHostname);
let fromBits = from.switches.get(srcHostname);
if ( fromBits !== thisBits ) {
if ( fromBits !== undefined ) {
this.switches.set(srcHostname, fromBits);
} else {
this.switches.delete(srcHostname);
}
this.changed = true;
}
return this.changed;
};
/******************************************************************************/
HnSwitches.prototype.hasSameRules = function(other, srcHostname) {
return this.switches.get(srcHostname) === other.switches.get(srcHostname);
};
/******************************************************************************/
// If value is undefined, the switch is removed
HnSwitches.prototype.toggle = function(switchName, hostname, newVal) {
var bitOffset = switchBitOffsets[switchName];
if ( bitOffset === undefined ) {
return false;
}
if ( newVal === this.evaluate(switchName, hostname) ) {
return false;
}
var bits = this.switches.get(hostname) || 0;
let bitOffset = switchBitOffsets[switchName];
if ( bitOffset === undefined ) { return false; }
if ( newVal === this.evaluate(switchName, hostname) ) { return false; }
let bits = this.switches.get(hostname) || 0;
bits &= ~(3 << bitOffset);
bits |= newVal << bitOffset;
if ( bits === 0 ) {
@ -105,18 +142,14 @@ HnSwitches.prototype.toggle = function(switchName, hostname, newVal) {
/******************************************************************************/
HnSwitches.prototype.toggleOneZ = function(switchName, hostname, newState) {
var bitOffset = switchBitOffsets[switchName];
if ( bitOffset === undefined ) {
return false;
}
var state = this.evaluateZ(switchName, hostname);
if ( newState === state ) {
return false;
}
let bitOffset = switchBitOffsets[switchName];
if ( bitOffset === undefined ) { return false; }
let state = this.evaluateZ(switchName, hostname);
if ( newState === state ) { return false; }
if ( newState === undefined ) {
newState = !state;
}
var bits = this.switches.get(hostname) || 0;
let bits = this.switches.get(hostname) || 0;
bits &= ~(3 << bitOffset);
if ( bits === 0 ) {
this.switches.delete(hostname);
@ -138,17 +171,11 @@ HnSwitches.prototype.toggleBranchZ = function(switchName, targetHostname, newSta
// Turn off all descendant switches, they will inherit the state of the
// branch's origin.
var targetLen = targetHostname.length;
for ( var hostname of this.switches.keys() ) {
if ( hostname === targetHostname ) {
continue;
}
if ( hostname.length <= targetLen ) {
continue;
}
if ( hostname.endsWith(targetHostname) === false ) {
continue;
}
let targetLen = targetHostname.length;
for ( let hostname of this.switches.keys() ) {
if ( hostname === targetHostname ) { continue; }
if ( hostname.length <= targetLen ) { continue; }
if ( hostname.endsWith(targetHostname) === false ) { continue; }
if ( hostname.charAt(hostname.length - targetLen - 1) !== '.' ) {
continue;
}
@ -174,11 +201,11 @@ HnSwitches.prototype.toggleZ = function(switchName, hostname, deep, newState) {
// 2 = forced default state (to override a broader non-default state)
HnSwitches.prototype.evaluate = function(switchName, hostname) {
var bits = this.switches.get(hostname);
let bits = this.switches.get(hostname);
if ( bits === undefined ) {
return 0;
}
var bitOffset = switchBitOffsets[switchName];
let bitOffset = switchBitOffsets[switchName];
if ( bitOffset === undefined ) {
return 0;
}
@ -188,7 +215,7 @@ HnSwitches.prototype.evaluate = function(switchName, hostname) {
/******************************************************************************/
HnSwitches.prototype.evaluateZ = function(switchName, hostname) {
var bitOffset = switchBitOffsets[switchName];
let bitOffset = switchBitOffsets[switchName];
if ( bitOffset === undefined ) {
this.r = 0;
return false;
@ -223,14 +250,14 @@ HnSwitches.prototype.toLogData = function() {
/******************************************************************************/
HnSwitches.prototype.toArray = function() {
var out = [],
let out = [],
toUnicode = punycode.toUnicode;
for ( var hostname of this.switches.keys() ) {
for ( let hostname of this.switches.keys() ) {
for ( var switchName in switchBitOffsets ) {
if ( switchBitOffsets.hasOwnProperty(switchName) === false ) {
continue;
}
var val = this.evaluate(switchName, hostname);
let val = this.evaluate(switchName, hostname);
if ( val === 0 ) { continue; }
if ( hostname.indexOf('xn--') !== -1 ) {
hostname = toUnicode(hostname);
@ -248,7 +275,7 @@ HnSwitches.prototype.toString = function() {
/******************************************************************************/
HnSwitches.prototype.fromString = function(text, append) {
var lineIter = new µBlock.LineIterator(text);
let lineIter = new µBlock.LineIterator(text);
if ( append !== true ) { this.reset(); }
while ( lineIter.eot() === false ) {
this.addFromRuleParts(lineIter.next().trim().split(/\s+/));
@ -270,7 +297,7 @@ HnSwitches.prototype.validateRuleParts = function(parts) {
HnSwitches.prototype.addFromRuleParts = function(parts) {
if ( this.validateRuleParts(parts) !== undefined ) {
var switchName = parts[0].slice(0, -1);
let switchName = parts[0].slice(0, -1);
if ( switchBitOffsets.hasOwnProperty(switchName) ) {
this.toggle(switchName, parts[1], nameToSwitchStateMap[parts[2]]);
return true;
@ -297,6 +324,7 @@ return HnSwitches;
/******************************************************************************/
µBlock.hnSwitches = new µBlock.HnSwitches();
µBlock.sessionSwitches = new µBlock.HnSwitches();
µBlock.permanentSwitches = new µBlock.HnSwitches();
/******************************************************************************/

View File

@ -279,9 +279,10 @@ var getFirewallRules = function(srcHostname, desHostnames) {
/******************************************************************************/
var popupDataFromTabId = function(tabId, tabTitle) {
var tabContext = µb.tabContextManager.mustLookup(tabId),
let tabContext = µb.tabContextManager.mustLookup(tabId),
rootHostname = tabContext.rootHostname;
var r = {
let r = {
advancedUserEnabled: µb.userSettings.advancedUserEnabled,
appName: vAPI.app.name,
appVersion: vAPI.app.version,
@ -305,7 +306,7 @@ var popupDataFromTabId = function(tabId, tabTitle) {
tooltipsDisabled: µb.userSettings.tooltipsDisabled
};
var pageStore = µb.pageStoreFromTabId(tabId);
let pageStore = µb.pageStoreFromTabId(tabId);
if ( pageStore ) {
// https://github.com/gorhill/uBlock/issues/2105
// Be sure to always include the current page's hostname -- it might
@ -325,23 +326,30 @@ var popupDataFromTabId = function(tabId, tabTitle) {
r.contentLastModified = pageStore.contentLastModified;
r.firewallRules = getFirewallRules(rootHostname, r.hostnameDict);
r.canElementPicker = µb.URI.isNetworkURI(r.rawURL);
r.noPopups = µb.hnSwitches.evaluateZ('no-popups', rootHostname);
r.noPopups = µb.sessionSwitches.evaluateZ('no-popups', rootHostname);
r.popupBlockedCount = pageStore.popupBlockedCount;
r.noCosmeticFiltering = µb.hnSwitches.evaluateZ('no-cosmetic-filtering', rootHostname);
r.noLargeMedia = µb.hnSwitches.evaluateZ('no-large-media', rootHostname);
r.noCosmeticFiltering = µb.sessionSwitches.evaluateZ('no-cosmetic-filtering', rootHostname);
r.noLargeMedia = µb.sessionSwitches.evaluateZ('no-large-media', rootHostname);
r.largeMediaCount = pageStore.largeMediaCount;
r.noRemoteFonts = µb.hnSwitches.evaluateZ('no-remote-fonts', rootHostname);
r.noRemoteFonts = µb.sessionSwitches.evaluateZ('no-remote-fonts', rootHostname);
r.remoteFontCount = pageStore.remoteFontCount;
r.noScripting = µb.hnSwitches.evaluateZ('no-scripting', rootHostname);
r.noScripting = µb.sessionSwitches.evaluateZ('no-scripting', rootHostname);
} else {
r.hostnameDict = {};
r.firewallRules = getFirewallRules();
}
r.matrixIsDirty = !µb.sessionFirewall.hasSameRules(
r.matrixIsDirty = µb.sessionFirewall.hasSameRules(
µb.permanentFirewall,
rootHostname,
r.hostnameDict
);
) === false;
if ( r.matrixIsDirty === false ) {
r.matrixIsDirty = µb.sessionSwitches.hasSameRules(
µb.permanentSwitches,
rootHostname
) === false;
}
return r;
};
@ -409,18 +417,41 @@ var onMessage = function(request, sender, callback) {
request.srcHostname,
request.desHostnames
);
µb.sessionSwitches.copyRules(
µb.permanentSwitches,
request.srcHostname
);
// https://github.com/gorhill/uBlock/issues/188
µb.cosmeticFilteringEngine.removeFromSelectorCache(request.srcHostname, 'net');
µb.cosmeticFilteringEngine.removeFromSelectorCache(
request.srcHostname,
'net'
);
response = popupDataFromTabId(request.tabId);
break;
case 'saveFirewallRules':
µb.permanentFirewall.copyRules(
µb.sessionFirewall,
request.srcHostname,
request.desHostnames
);
µb.savePermanentFirewallRules();
if (
µb.permanentFirewall.copyRules(
µb.sessionFirewall,
request.srcHostname,
request.desHostnames
)
) {
µb.savePermanentFirewallRules();
}
if (
µb.permanentSwitches.copyRules(
µb.sessionSwitches,
request.srcHostname
)
) {
µb.saveHostnameSwitches();
}
break;
case 'toggleHostnameSwitch':
µb.toggleHostnameSwitch(request);
response = popupDataFromTabId(request.tabId);
break;
case 'toggleFirewallRule':
@ -745,7 +776,7 @@ var backupUserData = function(callback) {
netWhitelist: µb.stringFromWhitelist(µb.netWhitelist),
dynamicFilteringString: µb.permanentFirewall.toString(),
urlFilteringString: µb.permanentURLFiltering.toString(),
hostnameSwitchesString: µb.hnSwitches.toString(),
hostnameSwitchesString: µb.permanentSwitches.toString(),
userFilters: ''
};
@ -880,44 +911,55 @@ var getLists = function(callback) {
var getRules = function() {
return {
permanentRules: µb.permanentFirewall.toArray().concat(
µb.permanentURLFiltering.toArray()
),
sessionRules: µb.sessionFirewall.toArray().concat(
µb.sessionURLFiltering.toArray()
),
hnSwitches: µb.hnSwitches.toArray()
permanentRules:
µb.permanentFirewall.toArray().concat(
µb.permanentSwitches.toArray(),
µb.permanentURLFiltering.toArray()
),
sessionRules:
µb.sessionFirewall.toArray().concat(
µb.sessionSwitches.toArray(),
µb.sessionURLFiltering.toArray()
)
};
};
var modifyRuleset = function(details) {
var swRuleset = µb.hnSwitches,
hnRuleset, urlRuleset;
let swRuleset, hnRuleset, urlRuleset;
if ( details.permanent ) {
swRuleset = µb.permanentSwitches;
hnRuleset = µb.permanentFirewall;
urlRuleset = µb.permanentURLFiltering;
} else {
swRuleset = µb.sessionSwitches;
hnRuleset = µb.sessionFirewall;
urlRuleset = µb.sessionURLFiltering;
}
var toRemove = new Set(details.toRemove.trim().split(/\s*[\n\r]+\s*/));
var rule, parts, _;
for ( rule of toRemove ) {
let toRemove = new Set(details.toRemove.trim().split(/\s*[\n\r]+\s*/));
for ( let rule of toRemove ) {
if ( rule === '' ) { continue; }
parts = rule.split(/\s+/);
_ = hnRuleset.removeFromRuleParts(parts) ||
swRuleset.removeFromRuleParts(parts) ||
urlRuleset.removeFromRuleParts(parts);
let parts = rule.split(/\s+/);
if ( hnRuleset.removeFromRuleParts(parts) === false ) {
if ( swRuleset.removeFromRuleParts(parts) === false ) {
urlRuleset.removeFromRuleParts(parts);
}
}
}
var toAdd = new Set(details.toAdd.trim().split(/\s*[\n\r]+\s*/));
for ( rule of toAdd ) {
let toAdd = new Set(details.toAdd.trim().split(/\s*[\n\r]+\s*/));
for ( let rule of toAdd ) {
if ( rule === '' ) { continue; }
parts = rule.split(/\s+/);
_ = hnRuleset.addFromRuleParts(parts) ||
swRuleset.addFromRuleParts(parts) ||
urlRuleset.addFromRuleParts(parts);
let parts = rule.split(/\s+/);
if ( hnRuleset.addFromRuleParts(parts) === false ) {
if ( swRuleset.addFromRuleParts(parts) === false ) {
urlRuleset.addFromRuleParts(parts);
}
}
}
if ( details.permanent ) {
if ( swRuleset.changed ) {
µb.saveHostnameSwitches();
swRuleset.changed = false;
}
if ( hnRuleset.changed ) {
µb.savePermanentFirewallRules();
hnRuleset.changed = false;
@ -927,10 +969,6 @@ var modifyRuleset = function(details) {
urlRuleset.changed = false;
}
}
if ( swRuleset.changed ) {
µb.saveHostnameSwitches();
swRuleset.changed = false;
}
};
/******************************************************************************/

View File

@ -297,7 +297,7 @@ PageStore.prototype.init = function(tabId, context) {
this.netFilteringCache = NetFilteringResultCache.factory();
this.internalRedirectionCount = 0;
this.noCosmeticFiltering = µb.hnSwitches.evaluateZ(
this.noCosmeticFiltering = µb.sessionSwitches.evaluateZ(
'no-cosmetic-filtering',
tabContext.rootHostname
) === true;
@ -309,7 +309,7 @@ PageStore.prototype.init = function(tabId, context) {
µb.logger.writeOne(
tabId,
'cosmetic',
µb.hnSwitches.toLogData(),
µb.sessionSwitches.toLogData(),
'dom',
tabContext.rawURL,
this.tabHostname,
@ -677,9 +677,9 @@ PageStore.prototype.collapsibleResources = {
/******************************************************************************/
PageStore.prototype.filterCSPReport = function(context) {
if ( µb.hnSwitches.evaluateZ('no-csp-reports', context.requestHostname) ) {
if ( µb.sessionSwitches.evaluateZ('no-csp-reports', context.requestHostname) ) {
if ( µb.logger.isEnabled() ) {
this.logData = µb.hnSwitches.toLogData();
this.logData = µb.sessionSwitches.toLogData();
}
return 1;
}
@ -708,9 +708,9 @@ PageStore.prototype.filterFont = function(context) {
if ( context.requestType === 'font' ) {
this.remoteFontCount += 1;
}
if ( µb.hnSwitches.evaluateZ('no-remote-fonts', context.rootHostname) !== false ) {
if ( µb.sessionSwitches.evaluateZ('no-remote-fonts', context.rootHostname) !== false ) {
if ( µb.logger.isEnabled() ) {
this.logData = µb.hnSwitches.toLogData();
this.logData = µb.sessionSwitches.toLogData();
}
return 1;
}
@ -725,12 +725,12 @@ PageStore.prototype.filterScripting = function(rootHostname, netFiltering) {
}
if (
netFiltering === false ||
µb.hnSwitches.evaluateZ('no-scripting', rootHostname) === false
µb.sessionSwitches.evaluateZ('no-scripting', rootHostname) === false
) {
return 0;
}
if ( µb.logger.isEnabled() ) {
this.logData = µb.hnSwitches.toLogData();
this.logData = µb.sessionSwitches.toLogData();
}
return 1;
};
@ -745,7 +745,7 @@ PageStore.prototype.filterLargeMediaElement = function(size) {
if ( Date.now() < this.allowLargeMediaElementsUntil ) {
return 0;
}
if ( µb.hnSwitches.evaluateZ('no-large-media', this.tabHostname) !== true ) {
if ( µb.sessionSwitches.evaluateZ('no-large-media', this.tabHostname) !== true ) {
return 0;
}
if ( (size >>> 10) < µb.userSettings.largeMediaSize ) {
@ -761,7 +761,7 @@ PageStore.prototype.filterLargeMediaElement = function(size) {
}
if ( µb.logger.isEnabled() ) {
this.logData = µb.hnSwitches.toLogData();
this.logData = µb.sessionSwitches.toLogData();
}
return 1;

View File

@ -391,6 +391,30 @@ var renderPrivacyExposure = function() {
/******************************************************************************/
let updateHnSwitches = function() {
uDom.nodeFromId('no-popups').classList.toggle(
'on',
popupData.noPopups === true
);
uDom.nodeFromId('no-large-media').classList.toggle(
'on', popupData.noLargeMedia === true
);
uDom.nodeFromId('no-cosmetic-filtering').classList.toggle(
'on',
popupData.noCosmeticFiltering === true
);
uDom.nodeFromId('no-remote-fonts').classList.toggle(
'on',
popupData.noRemoteFonts === true
);
uDom.nodeFromId('no-scripting').classList.toggle(
'on',
popupData.noScripting === true
);
};
/******************************************************************************/
// Assume everything has to be done incrementally.
var renderPopup = function() {
@ -435,11 +459,7 @@ var renderPopup = function() {
renderPrivacyExposure();
// Extra tools
uDom.nodeFromId('no-popups').classList.toggle('on', popupData.noPopups === true);
uDom.nodeFromId('no-large-media').classList.toggle('on', popupData.noLargeMedia === true);
uDom.nodeFromId('no-cosmetic-filtering').classList.toggle('on', popupData.noCosmeticFiltering === true);
uDom.nodeFromId('no-remote-fonts').classList.toggle('on', popupData.noRemoteFonts === true);
uDom.nodeFromId('no-scripting').classList.toggle('on', popupData.noScripting === true);
updateHnSwitches();
// Report blocked popup count on badge
total = popupData.popupBlockedCount;
@ -458,7 +478,7 @@ var renderPopup = function() {
// https://github.com/chrisaljoudi/uBlock/issues/470
// This must be done here, to be sure the popup is resized properly
var dfPaneVisible = popupData.dfEnabled;
let dfPaneVisible = popupData.dfEnabled;
// https://github.com/chrisaljoudi/uBlock/issues/1068
// Remember the last state of the firewall pane. This allows to
@ -774,14 +794,13 @@ var mouseleaveCellHandler = function() {
var setFirewallRule = function(src, des, type, action, persist) {
// This can happen on pages where uBlock does not work
if ( typeof popupData.pageHostname !== 'string' || popupData.pageHostname === '' ) {
if (
typeof popupData.pageHostname !== 'string' ||
popupData.pageHostname === ''
) {
return;
}
var onFirewallRuleChanged = function(response) {
cachePopupData(response);
updateAllFirewallCells();
hashFromPopupData();
};
messaging.send(
'popupPanel',
{
@ -794,14 +813,18 @@ var setFirewallRule = function(src, des, type, action, persist) {
action: action,
persist: persist
},
onFirewallRuleChanged
response => {
cachePopupData(response);
updateAllFirewallCells();
hashFromPopupData();
}
);
};
/******************************************************************************/
var unsetFirewallRuleHandler = function(ev) {
var cell = uDom(this);
let cell = uDom(ev.target);
setFirewallRule(
cell.attr('data-src') === '/' ? '*' : popupData.pageHostname,
cell.attr('data-des'),
@ -815,13 +838,11 @@ var unsetFirewallRuleHandler = function(ev) {
/******************************************************************************/
var setFirewallRuleHandler = function(ev) {
var hotspot = uDom(this);
var cell = hotspot.ancestors('[data-src]');
if ( cell.length === 0 ) {
return;
}
var action = 0;
var hotspotId = hotspot.attr('id');
let hotspot = uDom(ev.target);
let cell = hotspot.ancestors('[data-src]');
if ( cell.length === 0 ) { return; }
let action = 0;
let hotspotId = hotspot.attr('id');
if ( hotspotId === 'dynaAllow' ) {
action = 2;
} else if ( hotspotId === 'dynaNoop' ) {
@ -885,9 +906,9 @@ var toggleMinimize = function(ev) {
return;
}
popupData.firewallPaneMinimized = uDom.nodeFromId('firewallContainer')
.classList
.toggle('minimized');
popupData.firewallPaneMinimized =
uDom.nodeFromId('firewallContainer').classList.toggle('minimized');
messaging.send(
'popupPanel',
{
@ -916,11 +937,6 @@ var saveFirewallRules = function() {
/******************************************************************************/
var revertFirewallRules = function() {
var onFirewallRuleChanged = function(response) {
cachePopupData(response);
updateAllFirewallCells();
hashFromPopupData();
};
messaging.send(
'popupPanel',
{
@ -929,7 +945,12 @@ var revertFirewallRules = function() {
desHostnames: popupData.hostnameDict,
tabId: popupData.tabId
},
onFirewallRuleChanged
response => {
cachePopupData(response);
updateAllFirewallCells();
updateHnSwitches();
hashFromPopupData();
}
);
uDom.nodeFromId('firewallContainer').classList.remove('dirty');
};
@ -937,8 +958,8 @@ var revertFirewallRules = function() {
/******************************************************************************/
var toggleHostnameSwitch = function(ev) {
var target = ev.currentTarget;
var switchName = target.getAttribute('id');
let target = ev.currentTarget;
let switchName = target.getAttribute('id');
if ( !switchName ) { return; }
target.classList.toggle('on');
messaging.send(
@ -948,11 +969,16 @@ var toggleHostnameSwitch = function(ev) {
name: switchName,
hostname: popupData.pageHostname,
state: target.classList.contains('on'),
tabId: popupData.tabId
tabId: popupData.tabId,
persist: popupData.dfEnabled === false || ev.ctrlKey || ev.metaKey
},
response => {
cachePopupData(response);
updateAllFirewallCells();
hashFromPopupData();
}
);
renderTooltips('#' + switchName);
hashFromPopupData();
};
/******************************************************************************/

View File

@ -42,7 +42,8 @@ vAPI.app.onShutdown = function() {
µb.permanentFirewall.reset();
µb.sessionURLFiltering.reset();
µb.permanentURLFiltering.reset();
µb.hnSwitches.reset();
µb.sessionSwitches.reset();
µb.permanentSwitches.reset();
};
/******************************************************************************/
@ -124,52 +125,11 @@ var onVersionReady = function(lastVersion) {
// release. This will be done only for release versions of Firefox.
if (
vAPI.webextFlavor.soup.has('firefox') &&
/(b|rc)\d+$/.test(vAPI.app.version) === false
vAPI.webextFlavor.soup.has('devbuild') === false
) {
µb.redirectEngine.invalidateResourcesSelfie();
}
// From 1.15.19b9 and above, the `behind-the-scene` scope is no longer
// whitelisted by default, and network requests from that scope will be
// subject to filtering by default.
//
// Following code is to remove the `behind-the-scene` scope when updating
// from a version older than 1.15.19b9.
// This will apply only to webext versions of uBO, as the following would
// certainly cause too much breakage in Firefox legacy given that uBO can
// see ALL network requests.
// Remove when everybody is beyond 1.15.19b8.
(function patch1015019008(s) {
if ( vAPI.firefox !== undefined ) { return; }
var match = /^(\d+)\.(\d+)\.(\d+)(?:\D+(\d+))?/.exec(s);
if ( match === null ) { return; }
var v =
parseInt(match[1], 10) * 1000 * 1000 * 1000 +
parseInt(match[2], 10) * 1000 * 1000 +
parseInt(match[3], 10) * 1000 +
(match[4] ? parseInt(match[4], 10) : 0);
if ( /rc\d+$/.test(s) ) { v += 100; }
if ( v > 1015019008 ) { return; }
if ( µb.getNetFilteringSwitch('http://behind-the-scene/') ) { return; }
var fwRules = [
'behind-the-scene * * noop',
'behind-the-scene * image noop',
'behind-the-scene * 3p noop',
'behind-the-scene * inline-script noop',
'behind-the-scene * 1p-script noop',
'behind-the-scene * 3p-script noop',
'behind-the-scene * 3p-frame noop'
].join('\n');
µb.sessionFirewall.fromString(fwRules, true);
µb.permanentFirewall.fromString(fwRules, true);
µb.savePermanentFirewallRules();
µb.hnSwitches.fromString([
'no-large-media: behind-the-scene false'
].join('\n'), true);
µb.saveHostnameSwitches();
µb.toggleNetFilteringSwitch('http://behind-the-scene/', '', true);
})(lastVersion);
vAPI.storage.set({ version: vAPI.app.version });
};
@ -206,7 +166,8 @@ var onUserSettingsReady = function(fetched) {
µb.sessionFirewall.assign(µb.permanentFirewall);
µb.permanentURLFiltering.fromString(fetched.urlFilteringString);
µb.sessionURLFiltering.assign(µb.permanentURLFiltering);
µb.hnSwitches.fromString(fetched.hostnameSwitchesString);
µb.permanentSwitches.fromString(fetched.hostnameSwitchesString);
µb.sessionSwitches.assign(µb.permanentSwitches);
// https://github.com/gorhill/uBlock/issues/1892
// For first installation on a battery-powered device, disable generic
@ -295,7 +256,8 @@ var onSelectedFilterListsLoaded = function() {
].join('\n'),
'urlFilteringString': '',
'hostnameSwitchesString': [
'no-large-media: behind-the-scene false'
'no-large-media: behind-the-scene false',
'no-scripting: behind-the-scene false'
].join('\n'),
'lastRestoreFile': '',
'lastRestoreTime': 0,

View File

@ -64,14 +64,6 @@
/******************************************************************************/
µBlock.keyvalSetOne = function(key, val, callback) {
var bin = {};
bin[key] = val;
vAPI.storage.set(bin, callback || this.noopFunc);
};
/******************************************************************************/
µBlock.saveLocalSettings = (function() {
let saveAfter = 4 * 60 * 1000;
@ -206,25 +198,33 @@
/******************************************************************************/
µBlock.savePermanentFirewallRules = function() {
this.keyvalSetOne('dynamicFilteringString', this.permanentFirewall.toString());
vAPI.storage.set({
dynamicFilteringString: this.permanentFirewall.toString()
});
};
/******************************************************************************/
µBlock.savePermanentURLFilteringRules = function() {
this.keyvalSetOne('urlFilteringString', this.permanentURLFiltering.toString());
vAPI.storage.set({
urlFilteringString: this.permanentURLFiltering.toString()
});
};
/******************************************************************************/
µBlock.saveHostnameSwitches = function() {
this.keyvalSetOne('hostnameSwitchesString', this.hnSwitches.toString());
vAPI.storage.set({
hostnameSwitchesString: this.permanentSwitches.toString()
});
};
/******************************************************************************/
µBlock.saveWhitelist = function() {
this.keyvalSetOne('netWhitelist', this.stringFromWhitelist(this.netWhitelist));
vAPI.storage.set({
netWhitelist: this.stringFromWhitelist(this.netWhitelist)
});
this.netWhitelistModifyTime = Date.now();
};

View File

@ -1,7 +1,7 @@
/*******************************************************************************
uBlock Origin - a browser extension to block requests.
Copyright (C) 2014-2018 Raymond Hill
Copyright (C) 2014-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
@ -610,10 +610,10 @@ vAPI.tabs.onPopupUpdated = (function() {
// popunders.
if (
popupType === 'popup' &&
µb.hnSwitches.evaluateZ('no-popups', openerHostname)
µb.sessionSwitches.evaluateZ('no-popups', openerHostname)
) {
logData = {
raw: 'no-popups: ' + µb.hnSwitches.z + ' true',
raw: 'no-popups: ' + µb.sessionSwitches.z + ' true',
result: 1,
source: 'switch'
};

View File

@ -246,10 +246,10 @@ var onBeforeRootFrameRequest = function(details) {
}
// Permanently unrestricted?
if ( result === 0 && µb.hnSwitches.evaluateZ('no-strict-blocking', requestHostname) ) {
if ( result === 0 && µb.sessionSwitches.evaluateZ('no-strict-blocking', requestHostname) ) {
result = 2;
if ( logEnabled === true ) {
logData = { engine: 'u', result: 2, raw: 'no-strict-blocking: ' + µb.hnSwitches.z + ' true' };
if ( logEnabled ) {
logData = { engine: 'u', result: 2, raw: 'no-strict-blocking: ' + µb.sessionSwitches.z + ' true' };
}
}

View File

@ -1,7 +1,7 @@
/*******************************************************************************
uBlock Origin - a browser extension to block requests.
Copyright (C) 2014-2018 Raymond Hill
Copyright (C) 2014-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
@ -278,22 +278,20 @@ var matchBucket = function(url, hostname, bucket, start) {
/******************************************************************************/
µBlock.changeUserSettings = function(name, value) {
var us = this.userSettings;
let us = this.userSettings;
// Return all settings if none specified.
if ( name === undefined ) {
us = JSON.parse(JSON.stringify(us));
us.noCosmeticFiltering = this.hnSwitches.evaluate('no-cosmetic-filtering', '*') === 1;
us.noLargeMedia = this.hnSwitches.evaluate('no-large-media', '*') === 1;
us.noRemoteFonts = this.hnSwitches.evaluate('no-remote-fonts', '*') === 1;
us.noScripting = this.hnSwitches.evaluate('no-scripting', '*') === 1;
us.noCSPReports = this.hnSwitches.evaluate('no-csp-reports', '*') === 1;
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;
return us;
}
if ( typeof name !== 'string' || name === '' ) {
return;
}
if ( typeof name !== 'string' || name === '' ) { return; }
if ( value === undefined ) {
return us[name];
@ -312,7 +310,7 @@ var matchBucket = function(url, hostname, bucket, start) {
}
// Change -- but only if the user setting actually exists.
var mustSave = us.hasOwnProperty(name) && value !== us[name];
let mustSave = us.hasOwnProperty(name) && value !== us[name];
if ( mustSave ) {
us[name] = value;
}
@ -341,27 +339,29 @@ var matchBucket = function(url, hostname, bucket, start) {
}
break;
case 'noCosmeticFiltering':
if ( this.hnSwitches.toggle('no-cosmetic-filtering', '*', value ? 1 : 0) ) {
this.saveHostnameSwitches();
}
break;
case 'noLargeMedia':
if ( this.hnSwitches.toggle('no-large-media', '*', value ? 1 : 0) ) {
this.saveHostnameSwitches();
}
break;
case 'noRemoteFonts':
if ( this.hnSwitches.toggle('no-remote-fonts', '*', value ? 1 : 0) ) {
this.saveHostnameSwitches();
}
break;
case 'noScripting':
if ( this.hnSwitches.toggle('no-scripting', '*', value ? 1 : 0) ) {
this.saveHostnameSwitches();
}
break;
case 'noCSPReports':
if ( this.hnSwitches.toggle('no-csp-reports', '*', value ? 1 : 0) ) {
let switchName;
switch ( name ) {
case 'noCosmeticFiltering':
switchName = 'no-cosmetic-filtering'; break;
case 'noLargeMedia':
switchName = 'no-large-media'; break;
case 'noRemoteFonts':
switchName = 'no-remote-fonts'; break;
case 'noScripting':
switchName = 'no-scripting'; break;
case 'noCSPReports':
switchName = 'no-csp-reports'; break;
default:
break;
}
if ( switchName === undefined ) { break; }
let switchState = value ? 1 : 0;
this.sessionSwitches.toggle(switchName, '*', switchState);
if ( this.permanentSwitches.toggle(switchName, '*', switchState) ) {
this.saveHostnameSwitches();
}
break;
@ -429,7 +429,7 @@ var matchBucket = function(url, hostname, bucket, start) {
// (but not really) redundant rules led to this issue.
µBlock.toggleFirewallRule = function(details) {
var requestType = details.requestType;
let requestType = details.requestType;
if ( details.action !== 0 ) {
this.sessionFirewall.setCell(details.srcHostname, details.desHostname, requestType, details.action);
@ -451,7 +451,7 @@ var matchBucket = function(url, hostname, bucket, start) {
// Flush all cached `net` cosmetic filters if we are dealing with a
// collapsible type: any of the cached entries could be a resource on the
// target page.
var srcHostname = details.srcHostname;
let srcHostname = details.srcHostname;
if (
(srcHostname !== '*') &&
(requestType === '*' || requestType === 'image' || requestType === '3p' || requestType === '3p-frame')
@ -466,22 +466,17 @@ var matchBucket = function(url, hostname, bucket, start) {
/******************************************************************************/
µBlock.toggleURLFilteringRule = function(details) {
var changed = this.sessionURLFiltering.setRule(
let changed = this.sessionURLFiltering.setRule(
details.context,
details.url,
details.type,
details.action
);
if ( !changed ) {
return;
}
if ( changed === false ) { return; }
this.cosmeticFilteringEngine.removeFromSelectorCache(details.context, 'net');
if ( !details.persist ) {
return;
}
if ( details.persist !== true ) { return; }
changed = this.permanentURLFiltering.setRule(
details.context,
@ -498,9 +493,13 @@ var matchBucket = function(url, hostname, bucket, start) {
/******************************************************************************/
µBlock.toggleHostnameSwitch = function(details) {
if ( this.hnSwitches.toggleZ(details.name, details.hostname, !!details.deep, details.state) ) {
this.saveHostnameSwitches();
}
let changed = this.sessionSwitches.toggleZ(
details.name,
details.hostname,
!!details.deep,
details.state
);
if ( changed === false ) { return; }
// Take action if needed
switch ( details.name ) {
@ -517,6 +516,18 @@ var matchBucket = function(url, hostname, bucket, start) {
}
break;
}
if ( details.persist !== true ) { return; }
changed = this.permanentSwitches.toggleZ(
details.name,
details.hostname,
!!details.deep,
details.state
);
if ( changed ) {
this.saveHostnameSwitches();
}
};
/******************************************************************************/