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.thunderbird = Services.appinfo.ID === '{3550f703-e582-4d05-9a08-453d09bdfdc6}';
if ( vAPI.fennec ) {
vAPI.battery = true;
}
/******************************************************************************/
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;
<button class="custom important disabled" id="buttonUpdate" data-i18n="3pUpdateNow"></button>
<button id="buttonPurgeAll" class="custom disabled" data-i18n="3pPurgeAll"></button>
<li><input type="checkbox" id="parseCosmeticFilters"><label data-i18n="3pParseAllABPHideFiltersPrompt1" for="parseCosmeticFilters"></label>
<button class="whatisthis"></button>
<div class="whatisthis-expandable para" data-i18n="3pParseAllABPHideFiltersInfo"></div>
<li><input type="checkbox" id="parseCosmeticFilters"><label data-i18n="3pParseAllABPHideFiltersPrompt1" for="parseCosmeticFilters"></label><button class="whatisthis"></button>
<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>
</ul>
<ul id="lists"></ul>

View file

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

View file

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

View file

@ -280,7 +280,8 @@ var runXpathJob = function(job, fn) {
/******************************************************************************/
var domFilterer = {
commitMissCount: 0,
addedNodesHandlerMissCount: 0,
removedNodesHandlerMissCount: 0,
disabledId: vAPI.randomToken(),
enabled: true,
hiddenId: vAPI.randomToken(),
@ -387,7 +388,7 @@ var domFilterer = {
mustCommit = true;
}
if ( mustCommit && commitIfNeeded ) {
this.commit();
this.commit('all');
}
return mustCommit;
},
@ -397,6 +398,8 @@ var domFilterer = {
return;
}
vAPI.executionCost.start();
var beforeHiddenNodeCount = this.hiddenNodeCount,
styleText = '', i, n;
@ -452,9 +455,9 @@ var domFilterer = {
var commitHit = this.hiddenNodeCount !== beforeHiddenNodeCount;
if ( commitHit ) {
this.commitMissCount = 0;
this.addedNodesHandlerMissCount = 0;
} else {
this.commitMissCount += 1;
this.addedNodesHandlerMissCount += 1;
}
// Un-hide nodes previously hidden.
@ -478,11 +481,13 @@ var domFilterer = {
503
);
}
vAPI.executionCost.stop('domFilterer.commit_');
},
commit: function(nodes, commitNow) {
var firstCommit = stagedNodes.length === 0;
if ( nodes === undefined ) {
if ( nodes === 'all' ) {
stagedNodes = [ document.documentElement ];
} else if ( stagedNodes[0] !== document.documentElement ) {
stagedNodes = stagedNodes.concat(nodes);
@ -601,6 +606,29 @@ var domFilterer = {
if ( shadow && shadow[shadowId] && shadow.firstElementChild !== null ) {
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 ) {
domFilterer.addExceptions(cfeDetails.cosmeticDonthide);
domFilterer.addSelectors(cfeDetails.cosmeticHide);
domFilterer.commit(undefined, true);
domFilterer.commit('all', true);
}
}
@ -759,7 +787,7 @@ vAPI.domWatcher = (function() {
}
}
addedNodeLists.length = 0;
if ( addedNodes.length !== 0 ) {
if ( addedNodes.length !== 0 || removedNodes ) {
listeners[0](addedNodes, removedNodes);
if ( listeners[1] ) {
listeners[1](addedNodes, removedNodes);
@ -825,26 +853,16 @@ vAPI.domWatcher = (function() {
domLayoutObserver = null;
};
var stop = function() {
if ( domLayoutObserver !== null ) {
domLayoutObserver.disconnect();
domLayoutObserver = null;
}
if ( safeObserverHandlerTimer !== null ) {
window.cancelAnimationFrame(safeObserverHandlerTimer);
}
};
var start = function() {
// Observe changes in the DOM only if...
// - there is a document.body
// - there is at least one `script` tag
if ( document.body === null || document.querySelector('script') === null ) {
vAPI.domWatcher = null;
return;
}
// https://github.com/gorhill/uMatrix/issues/144
vAPI.shutdown.add(stop);
vAPI.shutdown.add(function() {
if ( domLayoutObserver !== null ) {
domLayoutObserver.disconnect();
domLayoutObserver = null;
}
if ( safeObserverHandlerTimer !== null ) {
window.cancelAnimationFrame(safeObserverHandlerTimer);
}
});
};
return {
@ -887,16 +905,11 @@ vAPI.domCollapser = (function() {
if ( !response ) {
return;
}
// https://github.com/gorhill/uMatrix/issues/144
if ( response.shutdown ) {
vAPI.shutdown.exec();
return;
}
var requests = response.result;
if ( requests === null || Array.isArray(requests) === false ) {
return;
}
vAPI.executionCost.start();
var selectors = [],
netSelectorCacheCountMax = response.netSelectorCacheCountMax,
aa = [ null ],
@ -947,9 +960,11 @@ vAPI.domCollapser = (function() {
}
);
}
vAPI.executionCost.stop('domCollapser/onProcessed');
};
var send = function() {
vAPI.executionCost.start();
timer = null;
messaging.send(
'contentscript',
@ -961,6 +976,7 @@ vAPI.domCollapser = (function() {
}, onProcessed
);
roundtripRequests = [];
vAPI.executionCost.stop('domCollapser/send');
};
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 node;
for ( var i = 0, ni = nodes.length; i < ni; i++ ) {
@ -1101,13 +1124,6 @@ vAPI.domCollapser = (function() {
process();
};
var onResourceFailed = function(ev) {
vAPI.executionCost.start();
vAPI.domCollapser.add(ev.target);
vAPI.domCollapser.process();
vAPI.executionCost.stop('domIsLoaded/onResourceFailed');
};
var start = function() {
// Listener to collapse blocked resources.
// - Future requests not blocked yet
@ -1131,15 +1147,13 @@ vAPI.domCollapser = (function() {
process(0);
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() {
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() {
// 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,
messaging = vAPI.messaging,
surveyPhase3Nodes = [],
cosmeticSurveyingMissCount = 0,
highGenerics = null,
lowGenericSelectors = [],
queriedSelectors = Object.create(null),
removedNodesHandlerMissCount = 0;
queriedSelectors = Object.create(null);
// Handle main process' response.
var surveyPhase3 = function(response) {
// https://github.com/gorhill/uMatrix/issues/144
if ( response && response.shutdown ) {
vAPI.shutdown.exec();
return;
}
vAPI.executionCost.start();
var result = response && response.result,
@ -1232,7 +1234,7 @@ vAPI.domSurveyor = (function() {
domFilterer.commit(surveyPhase3Nodes);
surveyPhase3Nodes = [];
vAPI.executionCost.stop('domIsLoaded/surveyPhase2');
vAPI.executionCost.stop('domSurveyor/surveyPhase3');
};
// Query main process.
@ -1465,31 +1467,27 @@ vAPI.domSurveyor = (function() {
};
var domChangedHandler = function(addedNodes, removedNodes) {
if ( cosmeticSurveyingMissCount < 256 ) {
surveyPhase1(addedNodes);
} else {
domFilterer.commit(addedNodes);
if ( cosmeticSurveyingMissCount > 255 ) {
vAPI.domWatcher.removeListener(domChangedHandler);
vAPI.domSurveyor = null;
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.
if ( removedNodes && removedNodesHandlerMissCount < 16 ) {
if ( domFilterer.checkStyleTags(true) === false ) {
removedNodesHandlerMissCount += 1;
}
surveyPhase1(addedNodes);
if ( removedNodes ) {
domFilterer.domChangedHandler([], true);
}
};
var start = function() {
domFilterer = vAPI.domFilterer;
if ( domFilterer === null ) {
return;
}
domFilterer.checkStyleTags(false);
domFilterer.commit();
domChangedHandler([ document.documentElement ]);
if ( vAPI.domWatcher ) {
vAPI.domWatcher.addListener(domChangedHandler);
}
vAPI.domWatcher.addListener(domChangedHandler);
vAPI.shutdown.add(function() {
vAPI.domWatcher.removeListener(domChangedHandler);
});
};
return {
@ -1514,16 +1512,20 @@ vAPI.domIsLoaded = function(ev) {
vAPI.executionCost.start();
if ( vAPI.domWatcher ) {
vAPI.domWatcher.start();
}
vAPI.domWatcher.start();
vAPI.domCollapser.start();
if ( vAPI.domCollapser ) {
vAPI.domCollapser.start();
}
if ( vAPI.domFilterer && vAPI.domSurveyor ) {
vAPI.domSurveyor.start();
if ( vAPI.domFilterer ) {
// 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.
vAPI.domFilterer.checkStyleTags(false);
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
@ -1533,30 +1535,26 @@ vAPI.domIsLoaded = function(ev) {
// as nuisance popups.
// 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() {
if ( window !== window.top || !vAPI.domFilterer ) {
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);
// https://github.com/gorhill/uMatrix/issues/144

View file

@ -690,9 +690,12 @@ FilterContainer.prototype.reset = function() {
this.selectorCacheTimer = null;
}
// permanent
// generic filters
this.hasGenericHide = false;
// [class], [id]
this.lowGenericHide = {};
this.lowGenericHideCount = 0;
// [alt="..."], [title="..."]
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
// Detect and report invalid CSS selectors.
@ -1006,26 +1036,23 @@ FilterContainer.prototype.compileEntitySelector = function(hostname, parsed, out
/******************************************************************************/
FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) {
if ( skip ) {
return this.skipCompiledContent(text, lineBeg);
FilterContainer.prototype.fromCompiledContent = function(lineIter, skipGenericCosmetic, skipCosmetic) {
if ( skipCosmetic ) {
this.skipCompiledContent(lineIter);
return;
}
if ( skipGenericCosmetic ) {
this.skipGenericCompiledContent(lineIter);
return;
}
var lineEnd;
var textEnd = text.length;
var line, fields, filter, key, bucket;
while ( lineBeg < textEnd ) {
if ( text.charCodeAt(lineBeg) !== 0x63 /* 'c' */ ) {
return lineBeg;
while ( lineIter.eot() === false ) {
if ( lineIter.text.charCodeAt(lineIter.offset) !== 0x63 /* 'c' */ ) {
return;
}
lineEnd = text.indexOf('\n', lineBeg);
if ( lineEnd === -1 ) {
lineEnd = textEnd;
}
line = text.slice(lineBeg + 2, lineEnd);
lineBeg = lineEnd + 1;
line = lineIter.next().slice(2);
this.acceptedCount += 1;
if ( this.duplicateBuster.hasOwnProperty(line) ) {
@ -1069,6 +1096,7 @@ FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) {
} else {
this.lowGenericHide[fields[1]] = new FilterBucket(bucket, filter);
}
this.lowGenericHideCount += 1;
continue;
}
@ -1124,30 +1152,114 @@ FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) {
// Generic exception filters: expected to be a rare occurrence.
if ( fields[0] === 'g1' ) {
this.genericDonthide.push(fields[1]);
continue;
}
this.discardedCount += 1;
}
return textEnd;
};
/******************************************************************************/
FilterContainer.prototype.skipCompiledContent = function(text, lineBeg) {
var lineEnd;
var textEnd = text.length;
FilterContainer.prototype.skipGenericCompiledContent = function(lineIter) {
var line, fields, filter, bucket;
while ( lineBeg < textEnd ) {
if ( text.charCodeAt(lineBeg) !== 0x63 /* 'c' */ ) {
return lineBeg;
}
lineEnd = text.indexOf('\n', lineBeg);
if ( lineEnd === -1 ) {
lineEnd = textEnd;
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');
// 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;
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() {
var selfieFromDict = function(dict) {
var selfie = [];
@ -1312,7 +1403,9 @@ FilterContainer.prototype.toSelfie = function() {
discardedCount: this.discardedCount,
hostnameSpecificFilters: selfieFromDict(this.hostnameFilters),
entitySpecificFilters: this.entityFilters,
hasGenericHide: this.hasGenericHide,
lowGenericHide: selfieFromDict(this.lowGenericHide),
lowGenericHideCount: this.lowGenericHideCount,
highLowGenericHide: this.highLowGenericHide,
highLowGenericHideCount: this.highLowGenericHideCount,
highMediumGenericHide: this.highMediumGenericHide,
@ -1378,7 +1471,9 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
this.discardedCount = selfie.discardedCount;
this.hostnameFilters = dictFromSelfie(selfie.hostnameSpecificFilters);
this.entityFilters = selfie.entitySpecificFilters;
this.hasGenericHide = selfie.hasGenericHide;
this.lowGenericHide = dictFromSelfie(selfie.lowGenericHide);
this.lowGenericHideCount = selfie.lowGenericHideCount;
this.highLowGenericHide = selfie.highLowGenericHide;
this.highLowGenericHideCount = selfie.highLowGenericHideCount;
this.highMediumGenericHide = selfie.highMediumGenericHide;
@ -1573,7 +1668,7 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request, noCosmetic
ready: this.frozen,
domain: domain,
entity: pos === -1 ? domain : domain.slice(0, pos - domain.length),
noDOMSurveying: false,
noDOMSurveying: this.hasGenericHide === false,
cosmeticHide: [],
cosmeticDonthide: [],
netHide: [],
@ -1600,7 +1695,9 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request, noCosmetic
// cached cosmetic filters.
if ( cacheEntry ) {
cacheEntry.retrieve('cosmetic', r.cosmeticHide);
r.noDOMSurveying = cacheEntry.cosmeticSurveyingMissCount > cosmeticSurveyingMissCountMax;
if ( r.noDOMSurveying === false ) {
r.noDOMSurveying = cacheEntry.cosmeticSurveyingMissCount > cosmeticSurveyingMissCountMax;
}
}
// Exception cosmetic filters.

View file

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

View file

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

View file

@ -1,7 +1,7 @@
/*******************************************************************************
uBlock - a browser extension to block requests.
Copyright (C) 2014-2015 Raymond Hill
uBlock Origin - a browser extension to block requests.
Copyright (C) 2014-2016 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
@ -19,7 +19,9 @@
Home: https://github.com/gorhill/uBlock
*/
/* global publicSuffixList, vAPI, µBlock */
/* global publicSuffixList */
'use strict';
/******************************************************************************/
@ -27,8 +29,6 @@
µBlock.restart = (function() {
'use strict';
//quickProfiler.start('start.js');
/******************************************************************************/
@ -178,6 +178,13 @@ var onUserSettingsReady = function(fetched) {
µb.sessionURLFiltering.assign(µb.permanentURLFiltering);
µ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
delete userSettings.logRequests;
vAPI.storage.remove('logRequests');

View file

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

View file

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

View file

@ -1,7 +1,7 @@
/*******************************************************************************
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
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
/******************************************************************************/
µ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;
};
/******************************************************************************/