This commit is contained in:
gorhill 2016-08-13 16:42:58 -04:00
parent 2feadb4a0d
commit e9157bafb7
12 changed files with 360 additions and 219 deletions

View file

@ -42,6 +42,10 @@ vAPI.firefox = true;
vAPI.fennec = Services.appinfo.ID === '{aa3c5121-dab2-40e2-81ca-7ea25febc110}'; vAPI.fennec = Services.appinfo.ID === '{aa3c5121-dab2-40e2-81ca-7ea25febc110}';
vAPI.thunderbird = Services.appinfo.ID === '{3550f703-e582-4d05-9a08-453d09bdfdc6}'; vAPI.thunderbird = Services.appinfo.ID === '{3550f703-e582-4d05-9a08-453d09bdfdc6}';
if ( vAPI.fennec ) {
vAPI.battery = true;
}
/******************************************************************************/ /******************************************************************************/
var deferUntil = function(testFn, mainFn, details) { var deferUntil = function(testFn, mainFn, details) {

View file

@ -19,9 +19,12 @@
<li><input type="checkbox" id="autoUpdate"><label data-i18n="3pAutoUpdatePrompt1" for="autoUpdate"></label>&ensp; <li><input type="checkbox" id="autoUpdate"><label data-i18n="3pAutoUpdatePrompt1" for="autoUpdate"></label>&ensp;
<button class="custom important disabled" id="buttonUpdate" data-i18n="3pUpdateNow"></button> <button class="custom important disabled" id="buttonUpdate" data-i18n="3pUpdateNow"></button>
<button id="buttonPurgeAll" class="custom disabled" data-i18n="3pPurgeAll"></button> <button id="buttonPurgeAll" class="custom disabled" data-i18n="3pPurgeAll"></button>
<li><input type="checkbox" id="parseCosmeticFilters"><label data-i18n="3pParseAllABPHideFiltersPrompt1" for="parseCosmeticFilters"></label> <li><input type="checkbox" id="parseCosmeticFilters"><label data-i18n="3pParseAllABPHideFiltersPrompt1" for="parseCosmeticFilters"></label><button class="whatisthis"></button>
<button class="whatisthis"></button> <div class="whatisthis-expandable para" data-i18n="3pParseAllABPHideFiltersInfo"></div>
<div class="whatisthis-expandable para" data-i18n="3pParseAllABPHideFiltersInfo"></div> <ul style="padding-left: 2em;">
<li><input type="checkbox" id="ignoreGenericCosmeticFilters"><label data-i18n="3pIgnoreGenericCosmeticFilters" for="ignoreGenericCosmeticFilters"></label><button class="whatisthis"></button>
<div class="whatisthis-expandable para" data-i18n="3pIgnoreGenericCosmeticFiltersInfo"></div>
</ul>
<li><p id="listsOfBlockedHostsPrompt"></p> <li><p id="listsOfBlockedHostsPrompt"></p>
</ul> </ul>
<ul id="lists"></ul> <ul id="lists"></ul>

View file

@ -31,7 +31,8 @@
var userListName = vAPI.i18n('1pPageName'); var userListName = vAPI.i18n('1pPageName');
var listDetails = {}; var listDetails = {};
var cosmeticSwitch = true; var parseCosmeticFilters = true;
var ignoreGenericCosmeticFilters = false;
var externalLists = ''; var externalLists = '';
var cacheWasPurged = false; var cacheWasPurged = false;
var needUpdate = false; var needUpdate = false;
@ -216,7 +217,8 @@ var renderFilterLists = function() {
var onListsReceived = function(details) { var onListsReceived = function(details) {
// Before all, set context vars // Before all, set context vars
listDetails = details; listDetails = details;
cosmeticSwitch = details.cosmetic; parseCosmeticFilters = details.parseCosmeticFilters;
ignoreGenericCosmeticFilters = details.ignoreGenericCosmeticFilters;
needUpdate = false; needUpdate = false;
hasCachedContent = false; hasCachedContent = false;
@ -257,7 +259,8 @@ var renderFilterLists = function() {
.replace('{{cosmeticFilterCount}}', renderNumber(details.cosmeticFilterCount)) .replace('{{cosmeticFilterCount}}', renderNumber(details.cosmeticFilterCount))
); );
uDom('#autoUpdate').prop('checked', listDetails.autoUpdate === true); uDom('#autoUpdate').prop('checked', listDetails.autoUpdate === true);
uDom('#parseCosmeticFilters').prop('checked', listDetails.cosmetic === true); uDom('#parseCosmeticFilters').prop('checked', listDetails.parseCosmeticFilters === true);
uDom('#ignoreGenericCosmeticFilters').prop('checked', listDetails.ignoreGenericCosmeticFilters === true);
renderWidgets(); renderWidgets();
renderBusyOverlay(details.manualUpdate, details.manualUpdateProgress); renderBusyOverlay(details.manualUpdate, details.manualUpdateProgress);
@ -302,7 +305,10 @@ var renderWidgets = function() {
// Return whether selection of lists changed. // Return whether selection of lists changed.
var listsSelectionChanged = function() { var listsSelectionChanged = function() {
if ( listDetails.cosmetic !== cosmeticSwitch ) { if (
listDetails.parseCosmeticFilters !== parseCosmeticFilters ||
listDetails.parseCosmeticFilters && listDetails.ignoreGenericCosmeticFilters !== ignoreGenericCosmeticFilters
) {
return true; return true;
} }
@ -401,14 +407,16 @@ var onPurgeClicked = function() {
var selectFilterLists = function(callback) { var selectFilterLists = function(callback) {
// Cosmetic filtering switch // Cosmetic filtering switch
messaging.send( messaging.send('dashboard', {
'dashboard', what: 'userSettings',
{ name: 'parseAllABPHideFilters',
what: 'userSettings', value: listDetails.parseCosmeticFilters
name: 'parseAllABPHideFilters', });
value: listDetails.cosmetic messaging.send('dashboard', {
} what: 'userSettings',
); name: 'ignoreGenericCosmeticFilters',
value: listDetails.ignoreGenericCosmeticFilters
});
// Filter lists // Filter lists
var switches = []; var switches = [];
@ -497,7 +505,8 @@ var autoUpdateCheckboxChanged = function() {
/******************************************************************************/ /******************************************************************************/
var cosmeticSwitchChanged = function() { var cosmeticSwitchChanged = function() {
listDetails.cosmetic = this.checked; listDetails.parseCosmeticFilters = uDom.nodeFromId('parseCosmeticFilters').checked;
listDetails.ignoreGenericCosmeticFilters = uDom.nodeFromId('ignoreGenericCosmeticFilters').checked;
renderWidgets(); renderWidgets();
}; };
@ -556,6 +565,7 @@ var groupEntryClickHandler = function() {
var getCloudData = function() { var getCloudData = function() {
var bin = { var bin = {
parseCosmeticFilters: uDom.nodeFromId('parseCosmeticFilters').checked, parseCosmeticFilters: uDom.nodeFromId('parseCosmeticFilters').checked,
ignoreGenericCosmeticFilters: uDom.nodeFromId('ignoreGenericCosmeticFilters').checked,
selectedLists: [], selectedLists: [],
externalLists: externalLists externalLists: externalLists
}; };
@ -580,9 +590,12 @@ var setCloudData = function(data, append) {
var elem, checked; var elem, checked;
elem = uDom.nodeFromId('parseCosmeticFilters'); elem = uDom.nodeFromId('parseCosmeticFilters');
checked = data.parseCosmeticFilters === true || checked = data.parseCosmeticFilters === true || append && elem.checked;
append && elem.checked; elem.checked = listDetails.parseCosmeticFilters = checked;
elem.checked = listDetails.cosmetic = checked;
elem = uDom.nodeFromId('ignoreGenericCosmeticFilters');
checked = data.ignoreGenericCosmeticFilters === true || append && elem.checked;
elem.checked = listDetails.ignoreGenericCosmeticFilters = checked;
var lis = uDom('#lists .listEntry'), li, listKey; var lis = uDom('#lists .listEntry'), li, listKey;
var i = lis.length; var i = lis.length;
@ -613,6 +626,7 @@ self.cloud.onPull = setCloudData;
uDom('#autoUpdate').on('change', autoUpdateCheckboxChanged); uDom('#autoUpdate').on('change', autoUpdateCheckboxChanged);
uDom('#parseCosmeticFilters').on('change', cosmeticSwitchChanged); uDom('#parseCosmeticFilters').on('change', cosmeticSwitchChanged);
uDom('#ignoreGenericCosmeticFilters').on('change', cosmeticSwitchChanged);
uDom('#buttonApply').on('click', buttonApplyHandler); uDom('#buttonApply').on('click', buttonApplyHandler);
uDom('#buttonUpdate').on('click', buttonUpdateHandler); uDom('#buttonUpdate').on('click', buttonUpdateHandler);
uDom('#buttonPurgeAll').on('click', buttonPurgeAllHandler); uDom('#buttonPurgeAll').on('click', buttonPurgeAllHandler);

View file

@ -59,6 +59,7 @@ return {
externalLists: defaultExternalLists, externalLists: defaultExternalLists,
firewallPaneMinimized: true, firewallPaneMinimized: true,
hyperlinkAuditingDisabled: true, hyperlinkAuditingDisabled: true,
ignoreGenericCosmeticFilters: false,
largeMediaSize: 50, largeMediaSize: 50,
parseAllABPHideFilters: true, parseAllABPHideFilters: true,
prefetchingDisabled: true, prefetchingDisabled: true,
@ -92,7 +93,7 @@ return {
// read-only // read-only
systemSettings: { systemSettings: {
compiledMagic: 'splsmclwnvoj', compiledMagic: 'splsmclwnvoj',
selfieMagic: 'splsmclwnvoj' selfieMagic: 'rkzqonintytj'
}, },
restoreBackupSettings: { restoreBackupSettings: {

View file

@ -280,7 +280,8 @@ var runXpathJob = function(job, fn) {
/******************************************************************************/ /******************************************************************************/
var domFilterer = { var domFilterer = {
commitMissCount: 0, addedNodesHandlerMissCount: 0,
removedNodesHandlerMissCount: 0,
disabledId: vAPI.randomToken(), disabledId: vAPI.randomToken(),
enabled: true, enabled: true,
hiddenId: vAPI.randomToken(), hiddenId: vAPI.randomToken(),
@ -387,7 +388,7 @@ var domFilterer = {
mustCommit = true; mustCommit = true;
} }
if ( mustCommit && commitIfNeeded ) { if ( mustCommit && commitIfNeeded ) {
this.commit(); this.commit('all');
} }
return mustCommit; return mustCommit;
}, },
@ -397,6 +398,8 @@ var domFilterer = {
return; return;
} }
vAPI.executionCost.start();
var beforeHiddenNodeCount = this.hiddenNodeCount, var beforeHiddenNodeCount = this.hiddenNodeCount,
styleText = '', i, n; styleText = '', i, n;
@ -452,9 +455,9 @@ var domFilterer = {
var commitHit = this.hiddenNodeCount !== beforeHiddenNodeCount; var commitHit = this.hiddenNodeCount !== beforeHiddenNodeCount;
if ( commitHit ) { if ( commitHit ) {
this.commitMissCount = 0; this.addedNodesHandlerMissCount = 0;
} else { } else {
this.commitMissCount += 1; this.addedNodesHandlerMissCount += 1;
} }
// Un-hide nodes previously hidden. // Un-hide nodes previously hidden.
@ -478,11 +481,13 @@ var domFilterer = {
503 503
); );
} }
vAPI.executionCost.stop('domFilterer.commit_');
}, },
commit: function(nodes, commitNow) { commit: function(nodes, commitNow) {
var firstCommit = stagedNodes.length === 0; var firstCommit = stagedNodes.length === 0;
if ( nodes === undefined ) { if ( nodes === 'all' ) {
stagedNodes = [ document.documentElement ]; stagedNodes = [ document.documentElement ];
} else if ( stagedNodes[0] !== document.documentElement ) { } else if ( stagedNodes[0] !== document.documentElement ) {
stagedNodes = stagedNodes.concat(nodes); stagedNodes = stagedNodes.concat(nodes);
@ -601,6 +606,29 @@ var domFilterer = {
if ( shadow && shadow[shadowId] && shadow.firstElementChild !== null ) { if ( shadow && shadow[shadowId] && shadow.firstElementChild !== null ) {
shadow.removeChild(shadow.firstElementChild); shadow.removeChild(shadow.firstElementChild);
} }
},
domChangedHandler: function(addedNodes, removedNodes) {
if ( addedNodes.length !== 0 ) {
this.commit(addedNodes);
}
// https://github.com/gorhill/uBlock/issues/873
// This will ensure our style elements will stay in the DOM.
if ( removedNodes && this.removedNodesHandlerMissCount < 16 ) {
if ( domFilterer.checkStyleTags(true) ) {
this.removedNodesHandlerMissCount = 0;
} else {
this.removedNodesHandlerMissCount += 1;
}
}
},
start: function() {
var domChangedHandler = this.domChangedHandler.bind(this);
vAPI.domWatcher.addListener(domChangedHandler);
vAPI.shutdown.add(function() {
vAPI.domWatcher.removeListener(domChangedHandler);
});
} }
}; };
@ -660,7 +688,7 @@ return domFilterer;
if ( cfeDetails.cosmeticHide.length !== 0 || cfeDetails.cosmeticDonthide.length !== 0 ) { if ( cfeDetails.cosmeticHide.length !== 0 || cfeDetails.cosmeticDonthide.length !== 0 ) {
domFilterer.addExceptions(cfeDetails.cosmeticDonthide); domFilterer.addExceptions(cfeDetails.cosmeticDonthide);
domFilterer.addSelectors(cfeDetails.cosmeticHide); domFilterer.addSelectors(cfeDetails.cosmeticHide);
domFilterer.commit(undefined, true); domFilterer.commit('all', true);
} }
} }
@ -759,7 +787,7 @@ vAPI.domWatcher = (function() {
} }
} }
addedNodeLists.length = 0; addedNodeLists.length = 0;
if ( addedNodes.length !== 0 ) { if ( addedNodes.length !== 0 || removedNodes ) {
listeners[0](addedNodes, removedNodes); listeners[0](addedNodes, removedNodes);
if ( listeners[1] ) { if ( listeners[1] ) {
listeners[1](addedNodes, removedNodes); listeners[1](addedNodes, removedNodes);
@ -825,26 +853,16 @@ vAPI.domWatcher = (function() {
domLayoutObserver = null; domLayoutObserver = null;
}; };
var stop = function() {
if ( domLayoutObserver !== null ) {
domLayoutObserver.disconnect();
domLayoutObserver = null;
}
if ( safeObserverHandlerTimer !== null ) {
window.cancelAnimationFrame(safeObserverHandlerTimer);
}
};
var start = function() { var start = function() {
// Observe changes in the DOM only if... vAPI.shutdown.add(function() {
// - there is a document.body if ( domLayoutObserver !== null ) {
// - there is at least one `script` tag domLayoutObserver.disconnect();
if ( document.body === null || document.querySelector('script') === null ) { domLayoutObserver = null;
vAPI.domWatcher = null; }
return; if ( safeObserverHandlerTimer !== null ) {
} window.cancelAnimationFrame(safeObserverHandlerTimer);
// https://github.com/gorhill/uMatrix/issues/144 }
vAPI.shutdown.add(stop); });
}; };
return { return {
@ -887,16 +905,11 @@ vAPI.domCollapser = (function() {
if ( !response ) { if ( !response ) {
return; return;
} }
// https://github.com/gorhill/uMatrix/issues/144
if ( response.shutdown ) {
vAPI.shutdown.exec();
return;
}
var requests = response.result; var requests = response.result;
if ( requests === null || Array.isArray(requests) === false ) { if ( requests === null || Array.isArray(requests) === false ) {
return; return;
} }
vAPI.executionCost.start();
var selectors = [], var selectors = [],
netSelectorCacheCountMax = response.netSelectorCacheCountMax, netSelectorCacheCountMax = response.netSelectorCacheCountMax,
aa = [ null ], aa = [ null ],
@ -947,9 +960,11 @@ vAPI.domCollapser = (function() {
} }
); );
} }
vAPI.executionCost.stop('domCollapser/onProcessed');
}; };
var send = function() { var send = function() {
vAPI.executionCost.start();
timer = null; timer = null;
messaging.send( messaging.send(
'contentscript', 'contentscript',
@ -961,6 +976,7 @@ vAPI.domCollapser = (function() {
}, onProcessed }, onProcessed
); );
roundtripRequests = []; roundtripRequests = [];
vAPI.executionCost.stop('domCollapser/send');
}; };
var process = function(delay) { var process = function(delay) {
@ -1084,6 +1100,13 @@ vAPI.domCollapser = (function() {
} }
}; };
var onResourceFailed = function(ev) {
vAPI.executionCost.start();
vAPI.domCollapser.add(ev.target);
vAPI.domCollapser.process();
vAPI.executionCost.stop('domCollapser/onResourceFailed');
};
var domChangedHandler = function(nodes) { var domChangedHandler = function(nodes) {
var node; var node;
for ( var i = 0, ni = nodes.length; i < ni; i++ ) { for ( var i = 0, ni = nodes.length; i < ni; i++ ) {
@ -1101,13 +1124,6 @@ vAPI.domCollapser = (function() {
process(); process();
}; };
var onResourceFailed = function(ev) {
vAPI.executionCost.start();
vAPI.domCollapser.add(ev.target);
vAPI.domCollapser.process();
vAPI.executionCost.stop('domIsLoaded/onResourceFailed');
};
var start = function() { var start = function() {
// Listener to collapse blocked resources. // Listener to collapse blocked resources.
// - Future requests not blocked yet // - Future requests not blocked yet
@ -1131,15 +1147,13 @@ vAPI.domCollapser = (function() {
process(0); process(0);
document.addEventListener('error', onResourceFailed, true); document.addEventListener('error', onResourceFailed, true);
if ( vAPI.domWatcher ) { vAPI.domWatcher.addListener(domChangedHandler);
vAPI.domWatcher.addListener(domChangedHandler);
}
// https://github.com/gorhill/uMatrix/issues/144
vAPI.shutdown.add(function() { vAPI.shutdown.add(function() {
document.removeEventListener('error', onResourceFailed, true); document.removeEventListener('error', onResourceFailed, true);
if ( vAPI.domWatcher ) { vAPI.domWatcher.removeListener(domChangedHandler);
vAPI.domWatcher.removeListener(domChangedHandler); if ( timer !== null ) {
clearTimeout(timer);
} }
}); });
}; };
@ -1159,29 +1173,17 @@ vAPI.domCollapser = (function() {
/******************************************************************************/ /******************************************************************************/
vAPI.domSurveyor = (function() { vAPI.domSurveyor = (function() {
// https://github.com/chrisaljoudi/uBlock/issues/789
// https://github.com/gorhill/uBlock/issues/873
// Be sure that our style tags used for cosmetic filtering are still
// applied.
var domFilterer = null, var domFilterer = null,
messaging = vAPI.messaging, messaging = vAPI.messaging,
surveyPhase3Nodes = [], surveyPhase3Nodes = [],
cosmeticSurveyingMissCount = 0, cosmeticSurveyingMissCount = 0,
highGenerics = null, highGenerics = null,
lowGenericSelectors = [], lowGenericSelectors = [],
queriedSelectors = Object.create(null), queriedSelectors = Object.create(null);
removedNodesHandlerMissCount = 0;
// Handle main process' response. // Handle main process' response.
var surveyPhase3 = function(response) { var surveyPhase3 = function(response) {
// https://github.com/gorhill/uMatrix/issues/144
if ( response && response.shutdown ) {
vAPI.shutdown.exec();
return;
}
vAPI.executionCost.start(); vAPI.executionCost.start();
var result = response && response.result, var result = response && response.result,
@ -1232,7 +1234,7 @@ vAPI.domSurveyor = (function() {
domFilterer.commit(surveyPhase3Nodes); domFilterer.commit(surveyPhase3Nodes);
surveyPhase3Nodes = []; surveyPhase3Nodes = [];
vAPI.executionCost.stop('domIsLoaded/surveyPhase2'); vAPI.executionCost.stop('domSurveyor/surveyPhase3');
}; };
// Query main process. // Query main process.
@ -1465,31 +1467,27 @@ vAPI.domSurveyor = (function() {
}; };
var domChangedHandler = function(addedNodes, removedNodes) { var domChangedHandler = function(addedNodes, removedNodes) {
if ( cosmeticSurveyingMissCount < 256 ) { if ( cosmeticSurveyingMissCount > 255 ) {
surveyPhase1(addedNodes); vAPI.domWatcher.removeListener(domChangedHandler);
} else { vAPI.domSurveyor = null;
domFilterer.commit(addedNodes); domFilterer.domChangedHandler(addedNodes, removedNodes);
domFilterer.start();
return;
} }
// https://github.com/gorhill/uBlock/issues/873
// This will ensure our style elements will stay in the DOM. surveyPhase1(addedNodes);
if ( removedNodes && removedNodesHandlerMissCount < 16 ) { if ( removedNodes ) {
if ( domFilterer.checkStyleTags(true) === false ) { domFilterer.domChangedHandler([], true);
removedNodesHandlerMissCount += 1;
}
} }
}; };
var start = function() { var start = function() {
domFilterer = vAPI.domFilterer; domFilterer = vAPI.domFilterer;
if ( domFilterer === null ) {
return;
}
domFilterer.checkStyleTags(false);
domFilterer.commit();
domChangedHandler([ document.documentElement ]); domChangedHandler([ document.documentElement ]);
if ( vAPI.domWatcher ) { vAPI.domWatcher.addListener(domChangedHandler);
vAPI.domWatcher.addListener(domChangedHandler); vAPI.shutdown.add(function() {
} vAPI.domWatcher.removeListener(domChangedHandler);
});
}; };
return { return {
@ -1514,16 +1512,20 @@ vAPI.domIsLoaded = function(ev) {
vAPI.executionCost.start(); vAPI.executionCost.start();
if ( vAPI.domWatcher ) { vAPI.domWatcher.start();
vAPI.domWatcher.start(); vAPI.domCollapser.start();
}
if ( vAPI.domCollapser ) { if ( vAPI.domFilterer ) {
vAPI.domCollapser.start(); // https://github.com/chrisaljoudi/uBlock/issues/789
} // https://github.com/gorhill/uBlock/issues/873
// Be sure our style tags used for cosmetic filtering are still applied.
if ( vAPI.domFilterer && vAPI.domSurveyor ) { vAPI.domFilterer.checkStyleTags(false);
vAPI.domSurveyor.start(); vAPI.domFilterer.commit('all');
if ( vAPI.domSurveyor ) {
vAPI.domSurveyor.start();
} else {
vAPI.domFilterer.start();
}
} }
// To send mouse coordinates to main process, as the chrome API fails // To send mouse coordinates to main process, as the chrome API fails
@ -1533,30 +1535,26 @@ vAPI.domIsLoaded = function(ev) {
// as nuisance popups. // as nuisance popups.
// Ref.: https://developer.mozilla.org/en-US/docs/Web/Events/contextmenu // Ref.: https://developer.mozilla.org/en-US/docs/Web/Events/contextmenu
var onMouseClick = function(ev) {
var elem = ev.target;
while ( elem !== null && elem.localName !== 'a' ) {
elem = elem.parentElement;
}
vAPI.messaging.send(
'contentscript',
{
what: 'mouseClick',
x: ev.clientX,
y: ev.clientY,
url: elem !== null ? elem.href : ''
}
);
};
(function() { (function() {
if ( window !== window.top || !vAPI.domFilterer ) { if ( window !== window.top || !vAPI.domFilterer ) {
return; return;
} }
var messaging = vAPI.messaging;
var onMouseClick = function(ev) {
vAPI.executionCost.start();
var elem = ev.target;
while ( elem !== null && elem.localName !== 'a' ) {
elem = elem.parentElement;
}
messaging.send(
'contentscript',
{
what: 'mouseClick',
x: ev.clientX,
y: ev.clientY,
url: elem !== null ? elem.href : ''
});
vAPI.executionCost.stop('domIsLoaded/onMouseClick');
};
document.addEventListener('mousedown', onMouseClick, true); document.addEventListener('mousedown', onMouseClick, true);
// https://github.com/gorhill/uMatrix/issues/144 // https://github.com/gorhill/uMatrix/issues/144

View file

@ -690,9 +690,12 @@ FilterContainer.prototype.reset = function() {
this.selectorCacheTimer = null; this.selectorCacheTimer = null;
} }
// permanent // generic filters
this.hasGenericHide = false;
// [class], [id] // [class], [id]
this.lowGenericHide = {}; this.lowGenericHide = {};
this.lowGenericHideCount = 0;
// [alt="..."], [title="..."] // [alt="..."], [title="..."]
this.highLowGenericHide = {}; this.highLowGenericHide = {};
@ -726,6 +729,33 @@ FilterContainer.prototype.reset = function() {
/******************************************************************************/ /******************************************************************************/
FilterContainer.prototype.freeze = function() {
this.duplicateBuster = {};
if ( this.highHighSimpleGenericHide !== '' ) {
this.highHighSimpleGenericHideArray.unshift(this.highHighSimpleGenericHide);
}
this.highHighSimpleGenericHide = this.highHighSimpleGenericHideArray.join(',\n');
this.highHighSimpleGenericHideArray = [];
if ( this.highHighComplexGenericHide !== '' ) {
this.highHighComplexGenericHideArray.unshift(this.highHighComplexGenericHide);
}
this.highHighComplexGenericHide = this.highHighComplexGenericHideArray.join(',\n');
this.highHighComplexGenericHideArray = [];
this.hasGenericHide = this.lowGenericHideCount !== 0 ||
this.highLowGenericHideCount !== 0 ||
this.highMediumGenericHideCount !== 0 ||
this.highHighSimpleGenericHideCount !== 0 ||
this.highHighComplexGenericHideCount !== 0;
this.parser.reset();
this.frozen = true;
};
/******************************************************************************/
// https://github.com/chrisaljoudi/uBlock/issues/1004 // https://github.com/chrisaljoudi/uBlock/issues/1004
// Detect and report invalid CSS selectors. // Detect and report invalid CSS selectors.
@ -1006,26 +1036,23 @@ FilterContainer.prototype.compileEntitySelector = function(hostname, parsed, out
/******************************************************************************/ /******************************************************************************/
FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) { FilterContainer.prototype.fromCompiledContent = function(lineIter, skipGenericCosmetic, skipCosmetic) {
if ( skip ) { if ( skipCosmetic ) {
return this.skipCompiledContent(text, lineBeg); this.skipCompiledContent(lineIter);
return;
}
if ( skipGenericCosmetic ) {
this.skipGenericCompiledContent(lineIter);
return;
} }
var lineEnd;
var textEnd = text.length;
var line, fields, filter, key, bucket; var line, fields, filter, key, bucket;
while ( lineBeg < textEnd ) { while ( lineIter.eot() === false ) {
if ( text.charCodeAt(lineBeg) !== 0x63 /* 'c' */ ) { if ( lineIter.text.charCodeAt(lineIter.offset) !== 0x63 /* 'c' */ ) {
return lineBeg; return;
} }
lineEnd = text.indexOf('\n', lineBeg); line = lineIter.next().slice(2);
if ( lineEnd === -1 ) {
lineEnd = textEnd;
}
line = text.slice(lineBeg + 2, lineEnd);
lineBeg = lineEnd + 1;
this.acceptedCount += 1; this.acceptedCount += 1;
if ( this.duplicateBuster.hasOwnProperty(line) ) { if ( this.duplicateBuster.hasOwnProperty(line) ) {
@ -1069,6 +1096,7 @@ FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) {
} else { } else {
this.lowGenericHide[fields[1]] = new FilterBucket(bucket, filter); this.lowGenericHide[fields[1]] = new FilterBucket(bucket, filter);
} }
this.lowGenericHideCount += 1;
continue; continue;
} }
@ -1124,30 +1152,114 @@ FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) {
// Generic exception filters: expected to be a rare occurrence. // Generic exception filters: expected to be a rare occurrence.
if ( fields[0] === 'g1' ) { if ( fields[0] === 'g1' ) {
this.genericDonthide.push(fields[1]); this.genericDonthide.push(fields[1]);
continue;
} }
this.discardedCount += 1;
} }
return textEnd;
}; };
/******************************************************************************/ /******************************************************************************/
FilterContainer.prototype.skipCompiledContent = function(text, lineBeg) { FilterContainer.prototype.skipGenericCompiledContent = function(lineIter) {
var lineEnd; var line, fields, filter, bucket;
var textEnd = text.length;
while ( lineBeg < textEnd ) { while ( lineIter.eot() === false ) {
if ( text.charCodeAt(lineBeg) !== 0x63 /* 'c' */ ) { if ( lineIter.text.charCodeAt(lineIter.offset) !== 0x63 /* 'c' */ ) {
return lineBeg; return;
}
lineEnd = text.indexOf('\n', lineBeg);
if ( lineEnd === -1 ) {
lineEnd = textEnd;
} }
line = lineIter.next().slice(2);
this.acceptedCount += 1; this.acceptedCount += 1;
if ( this.duplicateBuster.hasOwnProperty(line) ) {
this.discardedCount += 1;
continue;
}
fields = line.split('\v');
// h [\t] ir [\t] twitter.com [\t] .promoted-tweet
if ( fields[0] === 'h' ) {
this.duplicateBuster[line] = true;
// Special filter: script tags. Not a real CSS selector.
if ( fields[3].startsWith('script') ) {
this.createScriptFilter(fields[2], fields[3].slice(6));
continue;
}
filter = new FilterHostname(fields[3], fields[2]);
bucket = this.hostnameFilters[fields[1]];
if ( bucket === undefined ) {
this.hostnameFilters[fields[1]] = filter;
} else if ( bucket instanceof FilterBucket ) {
bucket.add(filter);
} else {
this.hostnameFilters[fields[1]] = new FilterBucket(bucket, filter);
}
continue;
}
// entity [\t] selector
if ( fields[0] === 'e' ) {
this.duplicateBuster[line] = true;
// Special filter: script tags. Not a real CSS selector.
if ( fields[2].startsWith('script') ) {
this.createScriptFilter(fields[1], fields[2].slice(6));
continue;
}
bucket = this.entityFilters[fields[1]];
if ( bucket === undefined ) {
this.entityFilters[fields[1]] = [fields[2]];
} else {
bucket.push(fields[2]);
}
continue;
}
// https://github.com/chrisaljoudi/uBlock/issues/497
// Generic exception filters: expected to be a rare occurrence.
if ( fields[0] === 'g1' ) {
this.duplicateBuster[line] = true;
this.genericDonthide.push(fields[1]);
continue;
}
this.discardedCount += 1;
}
};
/******************************************************************************/
FilterContainer.prototype.skipCompiledContent = function(lineIter) {
var line, fields;
while ( lineIter.eot() === false ) {
if ( lineIter.text.charCodeAt(lineIter.offset) !== 0x63 /* 'c' */ ) {
return;
}
line = lineIter.next().slice(2);
this.acceptedCount += 1;
if ( this.duplicateBuster.hasOwnProperty(line) ) {
this.discardedCount += 1;
continue;
}
fields = line.split('\v');
if ( fields[0] === 'h' && fields[3].startsWith('script') ) {
this.duplicateBuster[line] = true;
this.createScriptFilter(fields[2], fields[3].slice(6));
continue;
}
if ( fields[0] === 'e' && fields[2].startsWith('script') ) {
this.duplicateBuster[line] = true;
this.createScriptFilter(fields[1], fields[2].slice(6));
continue;
}
this.discardedCount += 1; this.discardedCount += 1;
lineBeg = lineEnd + 1;
} }
return textEnd;
}; };
/******************************************************************************/ /******************************************************************************/
@ -1260,27 +1372,6 @@ FilterContainer.prototype.retrieveScriptTags = function(domain, hostname) {
/******************************************************************************/ /******************************************************************************/
FilterContainer.prototype.freeze = function() {
this.duplicateBuster = {};
if ( this.highHighSimpleGenericHide !== '' ) {
this.highHighSimpleGenericHideArray.unshift(this.highHighSimpleGenericHide);
}
this.highHighSimpleGenericHide = this.highHighSimpleGenericHideArray.join(',\n');
this.highHighSimpleGenericHideArray = [];
if ( this.highHighComplexGenericHide !== '' ) {
this.highHighComplexGenericHideArray.unshift(this.highHighComplexGenericHide);
}
this.highHighComplexGenericHide = this.highHighComplexGenericHideArray.join(',\n');
this.highHighComplexGenericHideArray = [];
this.parser.reset();
this.frozen = true;
};
/******************************************************************************/
FilterContainer.prototype.toSelfie = function() { FilterContainer.prototype.toSelfie = function() {
var selfieFromDict = function(dict) { var selfieFromDict = function(dict) {
var selfie = []; var selfie = [];
@ -1312,7 +1403,9 @@ FilterContainer.prototype.toSelfie = function() {
discardedCount: this.discardedCount, discardedCount: this.discardedCount,
hostnameSpecificFilters: selfieFromDict(this.hostnameFilters), hostnameSpecificFilters: selfieFromDict(this.hostnameFilters),
entitySpecificFilters: this.entityFilters, entitySpecificFilters: this.entityFilters,
hasGenericHide: this.hasGenericHide,
lowGenericHide: selfieFromDict(this.lowGenericHide), lowGenericHide: selfieFromDict(this.lowGenericHide),
lowGenericHideCount: this.lowGenericHideCount,
highLowGenericHide: this.highLowGenericHide, highLowGenericHide: this.highLowGenericHide,
highLowGenericHideCount: this.highLowGenericHideCount, highLowGenericHideCount: this.highLowGenericHideCount,
highMediumGenericHide: this.highMediumGenericHide, highMediumGenericHide: this.highMediumGenericHide,
@ -1378,7 +1471,9 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
this.discardedCount = selfie.discardedCount; this.discardedCount = selfie.discardedCount;
this.hostnameFilters = dictFromSelfie(selfie.hostnameSpecificFilters); this.hostnameFilters = dictFromSelfie(selfie.hostnameSpecificFilters);
this.entityFilters = selfie.entitySpecificFilters; this.entityFilters = selfie.entitySpecificFilters;
this.hasGenericHide = selfie.hasGenericHide;
this.lowGenericHide = dictFromSelfie(selfie.lowGenericHide); this.lowGenericHide = dictFromSelfie(selfie.lowGenericHide);
this.lowGenericHideCount = selfie.lowGenericHideCount;
this.highLowGenericHide = selfie.highLowGenericHide; this.highLowGenericHide = selfie.highLowGenericHide;
this.highLowGenericHideCount = selfie.highLowGenericHideCount; this.highLowGenericHideCount = selfie.highLowGenericHideCount;
this.highMediumGenericHide = selfie.highMediumGenericHide; this.highMediumGenericHide = selfie.highMediumGenericHide;
@ -1573,7 +1668,7 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request, noCosmetic
ready: this.frozen, ready: this.frozen,
domain: domain, domain: domain,
entity: pos === -1 ? domain : domain.slice(0, pos - domain.length), entity: pos === -1 ? domain : domain.slice(0, pos - domain.length),
noDOMSurveying: false, noDOMSurveying: this.hasGenericHide === false,
cosmeticHide: [], cosmeticHide: [],
cosmeticDonthide: [], cosmeticDonthide: [],
netHide: [], netHide: [],
@ -1600,7 +1695,9 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request, noCosmetic
// cached cosmetic filters. // cached cosmetic filters.
if ( cacheEntry ) { if ( cacheEntry ) {
cacheEntry.retrieve('cosmetic', r.cosmeticHide); cacheEntry.retrieve('cosmetic', r.cosmeticHide);
r.noDOMSurveying = cacheEntry.cosmeticSurveyingMissCount > cosmeticSurveyingMissCountMax; if ( r.noDOMSurveying === false ) {
r.noDOMSurveying = cacheEntry.cosmeticSurveyingMissCount > cosmeticSurveyingMissCountMax;
}
} }
// Exception cosmetic filters. // Exception cosmetic filters.

View file

@ -110,5 +110,6 @@ uDom('.whatisthis').on('click', function() {
uDom(this) uDom(this)
.parent() .parent()
.descendants('.whatisthis-expandable') .descendants('.whatisthis-expandable')
.first()
.toggleClass('whatisthis-expanded'); .toggleClass('whatisthis-expanded');
}); });

View file

@ -534,23 +534,19 @@ var onMessage = function(request, sender, callback) {
break; break;
case 'retrieveGenericCosmeticSelectors': case 'retrieveGenericCosmeticSelectors':
response = { if ( pageStore && pageStore.getGenericCosmeticFilteringSwitch() ) {
shutdown: !pageStore || !pageStore.getNetFilteringSwitch(), response = {
result: null result: µb.cosmeticFilteringEngine.retrieveGenericSelectors(request)
}; };
if ( !response.shutdown && pageStore.getGenericCosmeticFilteringSwitch() ) {
response.result = µb.cosmeticFilteringEngine.retrieveGenericSelectors(request);
} }
break; break;
case 'filterRequests': case 'filterRequests':
response = { if ( pageStore && pageStore.getNetFilteringSwitch() ) {
shutdown: !pageStore || !pageStore.getNetFilteringSwitch(), response = {
result: null, result: filterRequests(pageStore, request),
netSelectorCacheCountMax: µb.cosmeticFilteringEngine.netSelectorCacheCountMax netSelectorCacheCountMax: µb.cosmeticFilteringEngine.netSelectorCacheCountMax
}; };
if ( !response.shutdown ) {
response.result = filterRequests(pageStore, request);
} }
break; break;
@ -855,9 +851,10 @@ var getLists = function(callback) {
autoUpdate: µb.userSettings.autoUpdate, autoUpdate: µb.userSettings.autoUpdate,
available: null, available: null,
cache: null, cache: null,
cosmetic: µb.userSettings.parseAllABPHideFilters, parseCosmeticFilters: µb.userSettings.parseAllABPHideFilters,
cosmeticFilterCount: µb.cosmeticFilteringEngine.getFilterCount(), cosmeticFilterCount: µb.cosmeticFilteringEngine.getFilterCount(),
current: µb.remoteBlacklists, current: µb.remoteBlacklists,
ignoreGenericCosmeticFilters: µb.userSettings.ignoreGenericCosmeticFilters,
manualUpdate: false, manualUpdate: false,
netFilterCount: µb.staticNetFilteringEngine.getFilterCount(), netFilterCount: µb.staticNetFilteringEngine.getFilterCount(),
userFiltersPath: µb.userFiltersPath userFiltersPath: µb.userFiltersPath

View file

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
uBlock - a browser extension to block requests. uBlock Origin - a browser extension to block requests.
Copyright (C) 2014-2015 Raymond Hill Copyright (C) 2014-2016 Raymond Hill
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -19,7 +19,9 @@
Home: https://github.com/gorhill/uBlock Home: https://github.com/gorhill/uBlock
*/ */
/* global publicSuffixList, vAPI, µBlock */ /* global publicSuffixList */
'use strict';
/******************************************************************************/ /******************************************************************************/
@ -27,8 +29,6 @@
µBlock.restart = (function() { µBlock.restart = (function() {
'use strict';
//quickProfiler.start('start.js'); //quickProfiler.start('start.js');
/******************************************************************************/ /******************************************************************************/
@ -178,6 +178,13 @@ var onUserSettingsReady = function(fetched) {
µb.sessionURLFiltering.assign(µb.permanentURLFiltering); µb.sessionURLFiltering.assign(µb.permanentURLFiltering);
µb.hnSwitches.fromString(fetched.hostnameSwitchesString); µb.hnSwitches.fromString(fetched.hostnameSwitchesString);
// https://github.com/gorhill/uBlock/issues/1892
// For first installation on a battery-powered device, disable generic
// cosmetic filtering.
if ( µb.firstInstall && vAPI.battery ) {
userSettings.ignoreGenericCosmeticFilters = true;
}
// Remove obsolete setting // Remove obsolete setting
delete userSettings.logRequests; delete userSettings.logRequests;
vAPI.storage.remove('logRequests'); vAPI.storage.remove('logRequests');

View file

@ -2055,22 +2055,15 @@ FilterContainer.prototype.compileToAtomicFilter = function(filterClass, parsed,
/******************************************************************************/ /******************************************************************************/
FilterContainer.prototype.fromCompiledContent = function(text, lineBeg) { FilterContainer.prototype.fromCompiledContent = function(lineIter) {
var lineEnd;
var textEnd = text.length;
var line, fields, bucket, entry, factory, filter; var line, fields, bucket, entry, factory, filter;
while ( lineBeg < textEnd ) { while ( lineIter.eot() === false ) {
if ( text.charCodeAt(lineBeg) !== 0x6E /* 'n' */ ) { if ( lineIter.text.charCodeAt(lineIter.offset) !== 0x6E /* 'n' */ ) {
return lineBeg; return;
} }
lineEnd = text.indexOf('\n', lineBeg); line = lineIter.next().slice(2);
if ( lineEnd === -1 ) {
lineEnd = textEnd;
}
line = text.slice(lineBeg + 2, lineEnd);
fields = line.split('\v'); fields = line.split('\v');
lineBeg = lineEnd + 1;
// Special cases: delegate to more specialized engines. // Special cases: delegate to more specialized engines.
// Redirect engine. // Redirect engine.
@ -2124,7 +2117,6 @@ FilterContainer.prototype.fromCompiledContent = function(text, lineBeg) {
} }
bucket[fields[1]] = new FilterBucket(entry, filter); bucket[fields[1]] = new FilterBucket(entry, filter);
} }
return textEnd;
}; };
/******************************************************************************/ /******************************************************************************/

View file

@ -632,14 +632,14 @@
// applying 1st-party filters. // applying 1st-party filters.
µBlock.applyCompiledFilters = function(rawText, firstparty) { µBlock.applyCompiledFilters = function(rawText, firstparty) {
var skipCosmetic = !firstparty && !this.userSettings.parseAllABPHideFilters; var skipCosmetic = !firstparty && !this.userSettings.parseAllABPHideFilters,
var staticNetFilteringEngine = this.staticNetFilteringEngine; skipGenericCosmetic = this.userSettings.ignoreGenericCosmeticFilters,
var cosmeticFilteringEngine = this.cosmeticFilteringEngine; staticNetFilteringEngine = this.staticNetFilteringEngine,
var lineBeg = 0; cosmeticFilteringEngine = this.cosmeticFilteringEngine,
var rawEnd = rawText.length; lineIter = new this.LineIterator(rawText);
while ( lineBeg < rawEnd ) { while ( lineIter.eot() === false ) {
lineBeg = cosmeticFilteringEngine.fromCompiledContent(rawText, lineBeg, skipCosmetic); cosmeticFilteringEngine.fromCompiledContent(lineIter, skipGenericCosmetic, skipCosmetic);
lineBeg = staticNetFilteringEngine.fromCompiledContent(rawText, lineBeg); staticNetFilteringEngine.fromCompiledContent(lineIter);
} }
}; };

View file

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
uBlock Origin - a browser extension to block requests. uBlock Origin - a browser extension to block requests.
Copyright (C) 2014-2015 Raymond Hill Copyright (C) 2014-2016 Raymond Hill
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -123,3 +123,30 @@
// https://www.youtube.com/watch?v=DyvzfyqYm_s // https://www.youtube.com/watch?v=DyvzfyqYm_s
/******************************************************************************/ /******************************************************************************/
µBlock.LineIterator = function(text, offset) {
this.text = text;
this.offset = offset || 0;
};
µBlock.LineIterator.prototype.next = function() {
if ( this.offset >= this.text.length ) {
return undefined;
}
var lineEnd = this.text.indexOf('\n', this.offset);
if ( lineEnd === -1 ) {
lineEnd = this.text.indexOf('\r', this.offset);
if ( lineEnd === -1 ) {
lineEnd = this.text.length;
}
}
var line = this.text.slice(this.offset, lineEnd);
this.offset = lineEnd + 1;
return line;
};
µBlock.LineIterator.prototype.eot = function() {
return this.offset >= this.text.length;
};
/******************************************************************************/