mirror of
https://github.com/gorhill/uBlock.git
synced 2024-09-15 15:32:28 +02:00
report active cosmetic filters in logger
This commit is contained in:
parent
bcbc06b2ff
commit
3d3bd13ea1
@ -70,6 +70,9 @@ body.colorBlind #content table tr.allowed {
|
||||
#content table tr.maindoc {
|
||||
background-color: #eee;
|
||||
}
|
||||
#content table tr.cosmetic {
|
||||
background-color: rgba(255, 255, 0, 0.1)
|
||||
}
|
||||
body:not(.filterOff) #content table tr.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ var uBlockCollapser = (function() {
|
||||
}
|
||||
if ( selectors.length !== 0 ) {
|
||||
messager.send({
|
||||
what: 'injectedSelectors',
|
||||
what: 'cosmeticFiltersInjected',
|
||||
type: 'net',
|
||||
hostname: window.location.hostname,
|
||||
selectors: selectors
|
||||
@ -385,7 +385,7 @@ var uBlockCollapser = (function() {
|
||||
// - Injecting a style tag
|
||||
|
||||
var addStyleTag = function(selectors) {
|
||||
var selectorStr = selectors.toString();
|
||||
var selectorStr = selectors.join(',\n');
|
||||
var style = document.createElement('style');
|
||||
// The linefeed before the style block is very important: do no remove!
|
||||
style.appendChild(document.createTextNode(selectorStr + '\n{display:none !important;}'));
|
||||
@ -396,7 +396,7 @@ var uBlockCollapser = (function() {
|
||||
}
|
||||
hideElements(selectorStr);
|
||||
messager.send({
|
||||
what: 'injectedSelectors',
|
||||
what: 'cosmeticFiltersInjected',
|
||||
type: 'cosmetic',
|
||||
hostname: window.location.hostname,
|
||||
selectors: selectors
|
||||
|
@ -123,6 +123,8 @@ var netFilters = function(details) {
|
||||
};
|
||||
|
||||
var filteringHandler = function(details) {
|
||||
var styleTagCount = vAPI.styles.length;
|
||||
|
||||
vAPI.skipCosmeticFiltering = !details || details.skipCosmeticFiltering;
|
||||
if ( details ) {
|
||||
if ( details.cosmeticHide.length !== 0 || details.cosmeticDonthide.length !== 0 ) {
|
||||
@ -135,6 +137,12 @@ var filteringHandler = function(details) {
|
||||
// the browser to flush this script from memory.
|
||||
}
|
||||
|
||||
// This is just to inform the background process that cosmetic filters were
|
||||
// actually injected.
|
||||
if ( vAPI.styles.length !== styleTagCount ) {
|
||||
localMessager.send({ what: 'cosmeticFiltersInjected' });
|
||||
}
|
||||
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/587
|
||||
// If no filters were found, maybe the script was injected before uBlock's
|
||||
// process was fully initialized. When this happens, pages won't be
|
||||
|
96
src/js/cosmetic-logger.js
Normal file
96
src/js/cosmetic-logger.js
Normal file
@ -0,0 +1,96 @@
|
||||
/*******************************************************************************
|
||||
|
||||
uBlock - a browser extension to block requests.
|
||||
Copyright (C) 2015 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
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
/* global vAPI, HTMLDocument */
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/464
|
||||
if ( document instanceof HTMLDocument === false ) {
|
||||
//console.debug('cosmetic-logger.js > not a HTLMDocument');
|
||||
return;
|
||||
}
|
||||
|
||||
// This can happen
|
||||
if ( !vAPI ) {
|
||||
//console.debug('cosmetic-logger.js > vAPI not found');
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var loggedSelectors = vAPI.loggedSelectors || {};
|
||||
|
||||
var injectedSelectors = [];
|
||||
var reProperties = /\s*\{[^}]+\}\s*/;
|
||||
var i;
|
||||
var styles = vAPI.styles || [];
|
||||
|
||||
i = styles.length;
|
||||
while ( i-- ) {
|
||||
injectedSelectors = injectedSelectors.concat(styles[i].textContent.replace(reProperties, '').split(/\s*,\n\s*/));
|
||||
}
|
||||
|
||||
if ( injectedSelectors.length === 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var matchedSelectors = [];
|
||||
var selector;
|
||||
|
||||
i = injectedSelectors.length;
|
||||
while ( i-- ) {
|
||||
selector = injectedSelectors[i];
|
||||
if ( loggedSelectors.hasOwnProperty(selector) ) {
|
||||
continue;
|
||||
}
|
||||
loggedSelectors[selector] = true;
|
||||
if ( document.querySelector(selector) === null ) {
|
||||
continue;
|
||||
}
|
||||
matchedSelectors.push(selector);
|
||||
}
|
||||
|
||||
vAPI.loggedSelectors = loggedSelectors;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var localMessager = vAPI.messaging.channel('cosmetic-*.js');
|
||||
|
||||
localMessager.send({
|
||||
what: 'logCosmeticFilteringData',
|
||||
pageURL: window.location.href,
|
||||
matchedSelectors: matchedSelectors
|
||||
}, function() {
|
||||
localMessager.close();
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
|
||||
/******************************************************************************/
|
@ -31,13 +31,13 @@
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/464
|
||||
if ( document instanceof HTMLDocument === false ) {
|
||||
//console.debug('cosmetic-on.js > not a HTLMDocument');
|
||||
//console.debug('cosmetic-survey.js > not a HTLMDocument');
|
||||
return;
|
||||
}
|
||||
|
||||
// This can happen
|
||||
if ( !vAPI ) {
|
||||
//console.debug('cosmetic-count.js > no vAPI');
|
||||
//console.debug('cosmetic-survey.js > vAPI not found');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -45,23 +45,20 @@ if ( !vAPI ) {
|
||||
|
||||
// Insert all cosmetic filtering-related style tags in the DOM
|
||||
|
||||
var selectors = [];
|
||||
var injectedSelectors = [];
|
||||
var filteredElementCount = 0;
|
||||
|
||||
var reProperties = /\s*\{[^}]+\}\s*/;
|
||||
var i;
|
||||
|
||||
var styles = vAPI.styles || [];
|
||||
i = styles.length;
|
||||
while ( i-- ) {
|
||||
selectors.push(styles[i].textContent.replace(reProperties, ''));
|
||||
injectedSelectors = injectedSelectors.concat(styles[i].textContent.replace(reProperties, '').split(/\s*,\n\s*/));
|
||||
}
|
||||
|
||||
var elems = [];
|
||||
|
||||
if ( selectors.length !== 0 ) {
|
||||
try {
|
||||
elems = document.querySelectorAll(selectors.join(','));
|
||||
} catch (e) {
|
||||
}
|
||||
if ( injectedSelectors.length !== 0 ) {
|
||||
filteredElementCount = document.querySelectorAll(injectedSelectors.join(',')).length;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -69,8 +66,10 @@ if ( selectors.length !== 0 ) {
|
||||
var localMessager = vAPI.messaging.channel('cosmetic-*.js');
|
||||
|
||||
localMessager.send({
|
||||
what: 'hiddenElementCount',
|
||||
count: elems.length
|
||||
what: 'liveCosmeticFilteringData',
|
||||
pageURL: window.location.href,
|
||||
filteredElementCount: filteredElementCount,
|
||||
injectedSelectors: injectedSelectors
|
||||
}, function() {
|
||||
localMessager.close();
|
||||
});
|
@ -123,6 +123,12 @@ var createRow = function() {
|
||||
|
||||
var renderLogEntry = function(entry) {
|
||||
var tr = createRow();
|
||||
|
||||
// Cosmetic filter?
|
||||
if ( entry.result.charAt(0) === 'c' ) {
|
||||
tr.classList.add('cosmetic');
|
||||
}
|
||||
|
||||
if ( entry.result.charAt(1) === 'b' ) {
|
||||
tr.classList.add('blocked');
|
||||
tr.cells[0].textContent = ' -\u00A0';
|
||||
@ -135,13 +141,16 @@ var renderLogEntry = function(entry) {
|
||||
} else {
|
||||
tr.cells[0].textContent = '';
|
||||
}
|
||||
|
||||
if ( entry.type === 'main_frame' ) {
|
||||
tr.classList.add('maindoc');
|
||||
}
|
||||
|
||||
var filterText = entry.result.slice(3);
|
||||
if ( entry.result.lastIndexOf('sa', 0) === 0 ) {
|
||||
filterText = '@@' + filterText;
|
||||
}
|
||||
|
||||
tr.cells[1].textContent = filterText + '\t';
|
||||
tr.cells[2].textContent = (prettyRequestTypes[entry.type] || entry.type) + '\t';
|
||||
vAPI.insertHTML(tr.cells[3], renderURL(entry.url, entry.result));
|
||||
|
@ -152,7 +152,7 @@ var logBufferObsoleteAfter = 30 * 1000;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var loggerWriteOne = function(tabId, details, result) {
|
||||
var writeOne = function(tabId, details, result) {
|
||||
if ( logBuffers.hasOwnProperty(tabId) === false ) {
|
||||
return;
|
||||
}
|
||||
@ -162,7 +162,7 @@ var loggerWriteOne = function(tabId, details, result) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var loggerReadAll = function(tabId) {
|
||||
var readAll = function(tabId) {
|
||||
if ( logBuffers.hasOwnProperty(tabId) === false ) {
|
||||
logBuffers[tabId] = new LogBuffer();
|
||||
}
|
||||
@ -171,6 +171,12 @@ var loggerReadAll = function(tabId) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var isObserved = function(tabId) {
|
||||
return logBuffers.hasOwnProperty(tabId);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var loggerJanitor = function() {
|
||||
var logBuffer;
|
||||
var obsolete = Date.now() - logBufferObsoleteAfter;
|
||||
@ -195,8 +201,9 @@ setTimeout(loggerJanitor, loggerJanitorPeriod);
|
||||
/******************************************************************************/
|
||||
|
||||
return {
|
||||
writeOne: loggerWriteOne,
|
||||
readAll: loggerReadAll
|
||||
writeOne: writeOne,
|
||||
readAll: readAll,
|
||||
isObserved: isObserved
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -37,67 +37,80 @@ var onMessage = function(request, sender, callback) {
|
||||
|
||||
// Async
|
||||
switch ( request.what ) {
|
||||
case 'getAssetContent':
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/417
|
||||
µb.assets.get(request.url, callback);
|
||||
return;
|
||||
case 'getAssetContent':
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/417
|
||||
µb.assets.get(request.url, callback);
|
||||
return;
|
||||
|
||||
case 'reloadAllFilters':
|
||||
µb.reloadAllFilters(callback);
|
||||
return;
|
||||
case 'reloadAllFilters':
|
||||
µb.reloadAllFilters(callback);
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
var tabId = sender && sender.tab ? sender.tab.id : 0;
|
||||
|
||||
// Sync
|
||||
var response;
|
||||
|
||||
switch ( request.what ) {
|
||||
case 'contextMenuEvent':
|
||||
µb.contextMenuClientX = request.clientX;
|
||||
µb.contextMenuClientY = request.clientY;
|
||||
break;
|
||||
case 'contextMenuEvent':
|
||||
µb.contextMenuClientX = request.clientX;
|
||||
µb.contextMenuClientY = request.clientY;
|
||||
break;
|
||||
|
||||
case 'forceUpdateAssets':
|
||||
µb.assetUpdater.force();
|
||||
break;
|
||||
case 'cosmeticFiltersInjected':
|
||||
// Is this a request to cache selectors?
|
||||
if ( Array.isArray(request.selectors) ) {
|
||||
µb.cosmeticFilteringEngine.addToSelectorCache(request);
|
||||
}
|
||||
// Net-based cosmetic filters are of no interest for logging purpose.
|
||||
if ( µb.logger.isObserved(tabId) && request.type !== 'net' ) {
|
||||
µb.logCosmeticFilters(tabId);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'getAppData':
|
||||
response = {name: vAPI.app.name, version: vAPI.app.version};
|
||||
break;
|
||||
case 'forceUpdateAssets':
|
||||
µb.assetUpdater.force();
|
||||
break;
|
||||
|
||||
case 'getUserSettings':
|
||||
response = µb.userSettings;
|
||||
break;
|
||||
case 'getAppData':
|
||||
response = {name: vAPI.app.name, version: vAPI.app.version};
|
||||
break;
|
||||
|
||||
case 'gotoURL':
|
||||
vAPI.tabs.open(request.details);
|
||||
break;
|
||||
case 'getUserSettings':
|
||||
response = µb.userSettings;
|
||||
break;
|
||||
|
||||
case 'reloadTab':
|
||||
if ( vAPI.isBehindTheSceneTabId(request.tabId) === false ) {
|
||||
vAPI.tabs.reload(request.tabId);
|
||||
if ( request.select && vAPI.tabs.select ) {
|
||||
vAPI.tabs.select(request.tabId);
|
||||
}
|
||||
case 'gotoURL':
|
||||
vAPI.tabs.open(request.details);
|
||||
break;
|
||||
|
||||
case 'reloadTab':
|
||||
if ( vAPI.isBehindTheSceneTabId(request.tabId) === false ) {
|
||||
vAPI.tabs.reload(request.tabId);
|
||||
if ( request.select && vAPI.tabs.select ) {
|
||||
vAPI.tabs.select(request.tabId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'selectFilterLists':
|
||||
µb.selectFilterLists(request.switches);
|
||||
break;
|
||||
case 'selectFilterLists':
|
||||
µb.selectFilterLists(request.switches);
|
||||
break;
|
||||
|
||||
case 'toggleHostnameSwitch':
|
||||
µb.toggleHostnameSwitch(request);
|
||||
break;
|
||||
case 'toggleHostnameSwitch':
|
||||
µb.toggleHostnameSwitch(request);
|
||||
break;
|
||||
|
||||
case 'userSettings':
|
||||
response = µb.changeUserSettings(request.name, request.value);
|
||||
break;
|
||||
case 'userSettings':
|
||||
response = µb.changeUserSettings(request.name, request.value);
|
||||
break;
|
||||
|
||||
default:
|
||||
return vAPI.messaging.UNHANDLED;
|
||||
default:
|
||||
return vAPI.messaging.UNHANDLED;
|
||||
}
|
||||
|
||||
callback(response);
|
||||
@ -296,7 +309,7 @@ var getPopupDataLazy = function(tabId, callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
µb.getHiddenElementCount(tabId, function() {
|
||||
µb.surveyCosmeticFilters(tabId, function() {
|
||||
r.hiddenElementCount = pageStore.hiddenElementCount;
|
||||
callback(r);
|
||||
});
|
||||
@ -497,11 +510,11 @@ var filterRequests = function(pageStore, details) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var onMessage = function(details, sender, callback) {
|
||||
var onMessage = function(request, sender, callback) {
|
||||
// Async
|
||||
switch ( details.what ) {
|
||||
default:
|
||||
break;
|
||||
switch ( request.what ) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Sync
|
||||
@ -512,33 +525,29 @@ var onMessage = function(details, sender, callback) {
|
||||
pageStore = µb.pageStoreFromTabId(sender.tab.id);
|
||||
}
|
||||
|
||||
switch ( details.what ) {
|
||||
case 'retrieveGenericCosmeticSelectors':
|
||||
response = {
|
||||
shutdown: !pageStore || !pageStore.getNetFilteringSwitch(),
|
||||
result: null
|
||||
};
|
||||
if ( !response.shutdown && pageStore.getGenericCosmeticFilteringSwitch() ) {
|
||||
response.result = µb.cosmeticFilteringEngine.retrieveGenericSelectors(details);
|
||||
}
|
||||
break;
|
||||
switch ( request.what ) {
|
||||
case 'retrieveGenericCosmeticSelectors':
|
||||
response = {
|
||||
shutdown: !pageStore || !pageStore.getNetFilteringSwitch(),
|
||||
result: null
|
||||
};
|
||||
if ( !response.shutdown && pageStore.getGenericCosmeticFilteringSwitch() ) {
|
||||
response.result = µb.cosmeticFilteringEngine.retrieveGenericSelectors(request);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'injectedSelectors':
|
||||
µb.cosmeticFilteringEngine.addToSelectorCache(details);
|
||||
break;
|
||||
case 'filterRequests':
|
||||
response = {
|
||||
shutdown: !pageStore || !pageStore.getNetFilteringSwitch(),
|
||||
result: null
|
||||
};
|
||||
if ( !response.shutdown ) {
|
||||
response.result = filterRequests(pageStore, request);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'filterRequests':
|
||||
response = {
|
||||
shutdown: !pageStore || !pageStore.getNetFilteringSwitch(),
|
||||
result: null
|
||||
};
|
||||
if ( !response.shutdown ) {
|
||||
response.result = filterRequests(pageStore, details);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return vAPI.messaging.UNHANDLED;
|
||||
default:
|
||||
return vAPI.messaging.UNHANDLED;
|
||||
}
|
||||
|
||||
callback(response);
|
||||
@ -565,6 +574,28 @@ var µb = µBlock;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var logCosmeticFilters = function(tabId, details) {
|
||||
if ( µb.logger.isObserved(tabId) === false ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var context = {
|
||||
requestURL: '',
|
||||
requestHostname: µb.URI.hostnameFromURI(details.pageURL),
|
||||
requestType: 'dom'
|
||||
};
|
||||
|
||||
var selectors = details.matchedSelectors;
|
||||
|
||||
selectors.sort();
|
||||
|
||||
for ( var i = 0; i < selectors.length; i++ ) {
|
||||
µb.logger.writeOne(tabId, context, 'cb:##' + selectors[i]);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var onMessage = function(request, sender, callback) {
|
||||
// Async
|
||||
switch ( request.what ) {
|
||||
@ -575,20 +606,22 @@ var onMessage = function(request, sender, callback) {
|
||||
// Sync
|
||||
var response;
|
||||
|
||||
var pageStore;
|
||||
if ( sender && sender.tab ) {
|
||||
pageStore = µb.pageStoreFromTabId(sender.tab.id);
|
||||
}
|
||||
var tabId = sender && sender.tab ? sender.tab.id : 0;
|
||||
|
||||
switch ( request.what ) {
|
||||
case 'hiddenElementCount':
|
||||
if ( pageStore ) {
|
||||
pageStore.hiddenElementCount = request.count;
|
||||
}
|
||||
break;
|
||||
case 'liveCosmeticFilteringData':
|
||||
var pageStore = µb.pageStoreFromTabId(tabId);
|
||||
if ( pageStore ) {
|
||||
pageStore.hiddenElementCount = request.filteredElementCount;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return vAPI.messaging.UNHANDLED;
|
||||
case 'logCosmeticFilteringData':
|
||||
logCosmeticFilters(tabId, request);
|
||||
break;
|
||||
|
||||
default:
|
||||
return vAPI.messaging.UNHANDLED;
|
||||
}
|
||||
|
||||
callback(response);
|
||||
|
@ -338,15 +338,38 @@ var matchWhitelistDirective = function(url, hostname, directive) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
µBlock.getHiddenElementCount = function(tabId, callback) {
|
||||
µBlock.surveyCosmeticFilters = function(tabId, callback) {
|
||||
callback = callback || this.noopFunc;
|
||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
vAPI.tabs.injectScript(tabId, { file: 'js/cosmetic-count.js' }, callback);
|
||||
vAPI.tabs.injectScript(tabId, { file: 'js/cosmetic-survey.js' }, callback);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
µBlock.logCosmeticFilters = (function() {
|
||||
var tabIdToTimerMap = {};
|
||||
|
||||
var injectNow = function(tabId) {
|
||||
delete tabIdToTimerMap[tabId];
|
||||
vAPI.tabs.injectScript(tabId, { file: 'js/cosmetic-logger.js' });
|
||||
};
|
||||
|
||||
var injectAsync = function(tabId) {
|
||||
if ( tabIdToTimerMap.hasOwnProperty(tabId) ) {
|
||||
return;
|
||||
}
|
||||
tabIdToTimerMap[tabId] = setTimeout(
|
||||
injectNow.bind(null, tabId),
|
||||
100
|
||||
);
|
||||
};
|
||||
|
||||
return injectAsync;
|
||||
})();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user