1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-09-04 01:59:38 +02:00

report active cosmetic filters in logger

This commit is contained in:
gorhill 2015-04-25 07:28:35 -04:00
parent bcbc06b2ff
commit 3d3bd13ea1
9 changed files with 284 additions and 106 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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
View 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();
});
/******************************************************************************/
})();
/******************************************************************************/

View File

@ -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();
});

View File

@ -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));

View File

@ -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
};
/******************************************************************************/

View File

@ -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);

View File

@ -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;
})();
/******************************************************************************/
})();