this addresses half of #58: find list(s) from which a static network filter originates

This commit is contained in:
gorhill 2015-06-11 12:12:23 -04:00
parent 74ad47bc71
commit 060a43fe81
11 changed files with 505 additions and 110 deletions

View File

@ -459,6 +459,10 @@
"message":"even if", "message":"even if",
"description":"Used in the static filtering wizard" "description":"Used in the static filtering wizard"
}, },
"loggerStaticFilteringFinderSentence1":{
"message":"Static filter {{filter}} found in:",
"description":"Below this sentence, the filter lists in which the filter was found"
},
"aboutChangelog":{ "aboutChangelog":{
"message":"Change log", "message":"Change log",
"description":"English: Change log" "description":"English: Change log"

View File

@ -29,6 +29,7 @@
<script src="js/tab.js"></script> <script src="js/tab.js"></script>
<script src="js/traffic.js"></script> <script src="js/traffic.js"></script>
<script src="js/contextmenu.js"></script> <script src="js/contextmenu.js"></script>
<script src="js/reverselookup.js"></script>
<script src="js/start.js"></script> <script src="js/start.js"></script>
</body> </body>
</html> </html>

View File

@ -189,6 +189,9 @@ body:not(.popupOn) #content tr.canMtx td:nth-of-type(2) {
body:not(.popupOn) #content tr.canMtx td:nth-of-type(2):hover { body:not(.popupOn) #content tr.canMtx td:nth-of-type(2):hover {
background: #ccc; background: #ccc;
} }
#content tr.cat_net[data-filter] td:nth-of-type(3) {
cursor: zoom-in;
}
#content tr.cat_net td:nth-of-type(4), #content tr.cat_net td:nth-of-type(4),
#content tr.cat_cosmetic td:nth-of-type(4) { #content tr.cat_cosmetic td:nth-of-type(4) {
font: 12px monospace; font: 12px monospace;
@ -275,7 +278,7 @@ body[dir="rtl"] #popupContainer > div {
display: none; display: none;
} }
#urlFilteringMenu { .modalDialog {
background-color: rgba(0, 0, 0, 0.5); background-color: rgba(0, 0, 0, 0.5);
border: 0; border: 0;
bottom: 0; bottom: 0;
@ -287,9 +290,10 @@ body[dir="rtl"] #popupContainer > div {
z-index: 400; z-index: 400;
} }
#urlFilteringMenu .dialog { .modalDialog .dialog {
background-color: white; background-color: white;
border: 2px solid white; border: 2px solid white;
box-sizing: border-box;
left: 10%; left: 10%;
position: absolute; position: absolute;
top: 50%; top: 50%;
@ -298,11 +302,11 @@ body[dir="rtl"] #popupContainer > div {
width: 80%; width: 80%;
} }
#urlFilteringMenu .dialog p { #netFilteringDialog .dialog p {
line-height: 2em; line-height: 2em;
} }
#urlFilteringMenu .dialog select { #netFilteringDialog .dialog select {
appearance: none; appearance: none;
-webkit-appearance: none; -webkit-appearance: none;
-moz-appearance: none; -moz-appearance: none;
@ -313,7 +317,7 @@ body[dir="rtl"] #popupContainer > div {
padding: 0.2em; padding: 0.2em;
} }
#urlFilteringMenu .dialog > div.preview { #netFilteringDialog .dialog > div.preview {
/* http://lea.verou.me/css3patterns/ */ /* http://lea.verou.me/css3patterns/ */
background-color: #aaa; background-color: #aaa;
background-image: background-image:
@ -337,33 +341,33 @@ body[dir="rtl"] #popupContainer > div {
background-size: 18px 18px; background-size: 18px 18px;
text-align: center; text-align: center;
} }
#urlFilteringMenu .dialog > div.preview > * { #netFilteringDialog .dialog > div.preview > * {
max-width: 100%; max-width: 100%;
max-height: 40vh; max-height: 40vh;
} }
#urlFilteringMenu .dialog table { #netFilteringDialog .dialog table {
border: 0; border: 0;
border-collapse: collapse; border-collapse: collapse;
table-layout: fixed; table-layout: fixed;
width: 100%; width: 100%;
} }
#urlFilteringMenu .dialog table > colgroup > col:nth-of-type(1) { #netFilteringDialog .dialog table > colgroup > col:nth-of-type(1) {
width: 3.8em; width: 3.8em;
} }
#urlFilteringMenu .dialog table > colgroup > col:nth-of-type(2) { #netFilteringDialog .dialog table > colgroup > col:nth-of-type(2) {
} }
#urlFilteringMenu .dialog td { #netFilteringDialog .dialog td {
border: 0; border: 0;
padding: 0; padding: 0;
vertical-align: middle; vertical-align: middle;
} }
#urlFilteringMenu .dialog > div.headers { #netFilteringDialog .dialog > div.headers {
border-bottom: 1px solid #888; border-bottom: 1px solid #888;
position: relative; position: relative;
} }
#urlFilteringMenu .dialog > div.headers > span.header { #netFilteringDialog .dialog > div.headers > span.header {
background-color: #eee; background-color: #eee;
border: 1px solid #aaa; border: 1px solid #aaa;
border-bottom: 1px solid #888; border-bottom: 1px solid #888;
@ -380,45 +384,45 @@ body[dir="rtl"] #popupContainer > div {
text-align: center; text-align: center;
top: 1px; top: 1px;
} }
#urlFilteringMenu .dialog > div.headers > span.header.selected { #netFilteringDialog .dialog > div.headers > span.header.selected {
background-color: white; background-color: white;
border-color: #888; border-color: #888;
border-bottom: 1px solid white; border-bottom: 1px solid white;
color: black; color: black;
} }
#urlFilteringMenu .dialog > div.headers > span.tools { #netFilteringDialog .dialog > div.headers > span.tools {
display: inline-block; display: inline-block;
position: absolute; position: absolute;
top: 50%; top: 50%;
transform: translate(0, -50%); transform: translate(0, -50%);
} }
body[dir="ltr"] #urlFilteringMenu .dialog > div.headers > span.tools { body[dir="ltr"] #netFilteringDialog .dialog > div.headers > span.tools {
right: 0.1em; right: 0.1em;
} }
body[dir="rtl"] #urlFilteringMenu .dialog > div.headers > span.tools { body[dir="rtl"] #netFilteringDialog .dialog > div.headers > span.tools {
left: 0.1em; left: 0.1em;
} }
#urlFilteringMenu .dialog > div.headers > span.tools > span { #netFilteringDialog .dialog > div.headers > span.tools > span {
cursor: pointer; cursor: pointer;
font-size: 1.2em; font-size: 1.2em;
text-align: center; text-align: center;
} }
#urlFilteringMenu .dialog > div.containers { #netFilteringDialog .dialog > div.containers {
height: 40vh; height: 40vh;
overflow: hidden; overflow: hidden;
overflow-y: auto; overflow-y: auto;
} }
#urlFilteringMenu .dialog > div.containers > div { #netFilteringDialog .dialog > div.containers > div {
display: none; display: none;
} }
#urlFilteringMenu .dialog > div.containers > div.selected { #netFilteringDialog .dialog > div.containers > div.selected {
display: block; display: block;
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic > table.toolbar select { #netFilteringDialog .dialog > div.containers > div.dynamic > table.toolbar select {
font: 14px; font: 14px;
height: 2em; height: 2em;
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic > table.toolbar #saveRules { #netFilteringDialog .dialog > div.containers > div.dynamic > table.toolbar #saveRules {
background-color: #ffe; background-color: #ffe;
border: 1px solid #ddc; border: 1px solid #ddc;
border-radius: 4px; border-radius: 4px;
@ -428,37 +432,37 @@ body[dir="rtl"] #urlFilteringMenu .dialog > div.headers > span.tools {
padding: 0.25em 0.5em; padding: 0.25em 0.5em;
visibility: hidden; visibility: hidden;
} }
body.dirty #urlFilteringMenu .dialog > div.containers > div.dynamic > table.toolbar #saveRules { body.dirty #netFilteringDialog .dialog > div.containers > div.dynamic > table.toolbar #saveRules {
visibility: visible; visibility: visible;
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic > table.toolbar #saveRules:hover { #netFilteringDialog .dialog > div.containers > div.dynamic > table.toolbar #saveRules:hover {
color: black; color: black;
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic > table.toolbar tr.entry { #netFilteringDialog .dialog > div.containers > div.dynamic > table.toolbar tr.entry {
display: none; display: none;
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry {
background-color: #e6e6e6; background-color: #e6e6e6;
border: 0; border: 0;
border-bottom: 1px solid white; border-bottom: 1px solid white;
font-size: 13px; font-size: 13px;
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry:hover { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry:hover {
background-color: #f0f0f0; background-color: #f0f0f0;
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td:first-of-type { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td:first-of-type {
border: 0; border: 0;
border-right: 1px solid white; border-right: 1px solid white;
text-align: center; text-align: center;
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action {
background-color: transparent; background-color: transparent;
border: 0; border: 0;
cursor: pointer; cursor: pointer;
height: 2em; height: 2em;
width: 100%; width: 100%;
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action > span { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action > span {
background-color: transparent; background-color: transparent;
border: 0; border: 0;
display: inline-block; display: inline-block;
@ -467,80 +471,98 @@ body.dirty #urlFilteringMenu .dialog > div.containers > div.dynamic > table.tool
visibility: hidden; visibility: hidden;
width: 33.33%; width: 33.33%;
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action.allow { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action.allow {
background-color: rgba(0, 160, 0, 0.3); background-color: rgba(0, 160, 0, 0.3);
} }
body.colorBlind #urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action.allow { body.colorBlind #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action.allow {
background-color: rgba(255, 194, 57, 0.4); background-color: rgba(255, 194, 57, 0.4);
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action.noop { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action.noop {
background-color: rgba(108, 108, 108, 0.3); background-color: rgba(108, 108, 108, 0.3);
} }
body.colorBlind #urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action.noop { body.colorBlind #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action.noop {
background-color: rgba(96, 96, 96, 0.4); background-color: rgba(96, 96, 96, 0.4);
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action.block { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action.block {
background-color: rgba(192, 0, 0, 0.3); background-color: rgba(192, 0, 0, 0.3);
} }
body.colorBlind #urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action.block { body.colorBlind #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action.block {
background-color: rgba(0, 19, 110, 0.4); background-color: rgba(0, 19, 110, 0.4);
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action.own.allow { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action.own.allow {
background-color: rgba(0, 160, 0, 1); background-color: rgba(0, 160, 0, 1);
} }
body.colorBlind #urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action.own.allow { body.colorBlind #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action.own.allow {
background-color: rgba(255, 194, 57, 1); background-color: rgba(255, 194, 57, 1);
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action.own.noop { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action.own.noop {
background-color: rgba(108, 108, 108, 1); background-color: rgba(108, 108, 108, 1);
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action.own.block { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action.own.block {
background-color: rgba(192, 0, 0, 1); background-color: rgba(192, 0, 0, 1);
} }
body.colorBlind #urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action.own.block { body.colorBlind #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action.own.block {
background-color: rgba(0, 19, 110, 1); background-color: rgba(0, 19, 110, 1);
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action:not(.own):hover > span { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action:not(.own):hover > span {
opacity: 0.2; opacity: 0.2;
visibility: visible; visibility: visible;
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action:not(.own):hover > span:hover { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action:not(.own):hover > span:hover {
opacity: 0.75; opacity: 0.75;
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action > span.allow { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action > span.allow {
background-color: rgb(0, 160, 0); background-color: rgb(0, 160, 0);
} }
body.colorBlind #urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action > span.allow { body.colorBlind #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action > span.allow {
background-color: rgb(255, 194, 57); background-color: rgb(255, 194, 57);
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action > span.noop { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action > span.noop {
background-color: rgb(108, 108, 108); background-color: rgb(108, 108, 108);
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action > span.block { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action > span.block {
background-color: rgb(192, 0, 0); background-color: rgb(192, 0, 0);
} }
body.colorBlind #urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td > div.action > span.block { body.colorBlind #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td > div.action > span.block {
background-color: rgb(0, 19, 110); background-color: rgb(0, 19, 110);
} }
#urlFilteringMenu .dialog > div.containers > div.dynamic tr.entry > td.url { #netFilteringDialog .dialog > div.containers > div.dynamic tr.entry > td.url {
overflow: hidden; overflow: hidden;
padding-left: 4px; padding-left: 4px;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
#urlFilteringMenu .dialog > div.containers > div.static > p { #netFilteringDialog .dialog > div.containers > div.static > p {
margin: 0.75em 0; margin: 0.75em 0;
} }
#urlFilteringMenu .dialog > div.containers > div.static textarea { #netFilteringDialog .dialog > div.containers > div.static textarea {
box-sizing: border-box; box-sizing: border-box;
direction: ltr; direction: ltr;
height: 6em; height: 6em;
resize: none; resize: none;
width: 100%; width: 100%;
} }
#urlFilteringMenu .dialog > div.containers > div.static > p:nth-of-type(2) { #netFilteringDialog .dialog > div.containers > div.static > p:nth-of-type(2) {
text-align: center; text-align: center;
} }
#filterFinderDialog .dialog {
padding: 1em;
}
#filterFinderDialog .dialog code {
background: #eee;
padding: 3px;
}
#filterFinderDialog .dialog ul {
font-size: larger;
}
#filterFinderDialog .dialog > *:first-child {
margin-top: 0;
}
#filterFinderDialog .dialog > *:last-child {
margin-bottom: 0;
}
.hide { .hide {
display: none; display: none;
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
uMatrix - a browser extension to benchmark browser session. uBlock Origin - a browser extension to block requests.
Copyright (C) 2015 Raymond Hill Copyright (C) 2015 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
@ -16,7 +16,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see {http://www.gnu.org/licenses/}. along with this program. If not, see {http://www.gnu.org/licenses/}.
Home: https://github.com/gorhill/sessbench Home: https://github.com/gorhill/uBlock
*/ */
/* jshint boss: true */ /* jshint boss: true */
@ -32,9 +32,9 @@
// Adjust top padding of content table, to match that of toolbar height. // Adjust top padding of content table, to match that of toolbar height.
document.getElementById('content').style.setProperty( uDom.nodeFromId('content').style.setProperty(
'margin-top', 'margin-top',
document.getElementById('toolbar').offsetHeight + 'px' uDom.nodeFromId('toolbar').offsetHeight + 'px'
); );
/******************************************************************************/ /******************************************************************************/
@ -51,7 +51,8 @@ var allTabIds = {};
var allTabIdsToken; var allTabIdsToken;
var hiddenTemplate = document.querySelector('#hiddenTemplate > span'); var hiddenTemplate = document.querySelector('#hiddenTemplate > span');
var reRFC3986 = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#]*)(\?[^#]*)?(#.*)?/; var reRFC3986 = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#]*)(\?[^#]*)?(#.*)?/;
var urlFilteringMenu = document.querySelector('#urlFilteringMenu'); var netFilteringDialog = uDom.nodeFromId('netFilteringDialog');
var filterFinderDialog = uDom.nodeFromId('filterFinderDialog');
var prettyRequestTypes = { var prettyRequestTypes = {
'main_frame': 'doc', 'main_frame': 'doc',
@ -159,19 +160,19 @@ var filterDecompiler = (function() {
var opts = []; var opts = [];
var vfields = compiled.split('\v'); var vfields = compiled.split('\v');
var filter = ''; var filter = '';
var bits = parseInt(vfields[1], 16) | 0; var bits = parseInt(vfields[0], 16) | 0;
if ( bits & 0x01 ) { if ( bits & 0x01 ) {
filter += '@@'; filter += '@@';
} }
var fid = vfields[2] === '.' ? '.' : vfields[3]; var fid = vfields[1] === '.' ? '.' : vfields[2];
var tfields = fid !== '.' ? vfields[4].split('\t') : []; var tfields = fid !== '.' ? vfields[3].split('\t') : [];
var tfield0 = tfields[0]; var tfield0 = tfields[0];
switch ( fid ) { switch ( fid ) {
case '.': case '.':
filter += '||' + vfields[3] + '^'; filter += '||' + vfields[2] + '^';
break; break;
case 'a': case 'a':
case 'ah': case 'ah':
@ -258,14 +259,13 @@ var filterDecompiler = (function() {
var toRegex = function(compiled) { var toRegex = function(compiled) {
var vfields = compiled.split('\v'); var vfields = compiled.split('\v');
var fid = vfields[2] === '.' ? '.' : vfields[3]; var fid = vfields[1] === '.' ? '.' : vfields[2];
var tfields = fid !== '.' ? vfields[4].split('\t') : []; var tfields = fid !== '.' ? vfields[3].split('\t') : [];
var reStr; var reStr;
switch ( fid ) { switch ( fid ) {
case '.': case '.':
reStr = vfields[3] reStr = vfields[2].replace(reEscape, '\\$&');
.replace(reEscape, '\\$&');
break; break;
case 'a': case 'a':
case 'ah': case 'ah':
@ -343,6 +343,7 @@ var createRow = function(layout) {
tr.className = ''; tr.className = '';
tr.removeAttribute('data-hn-page'); tr.removeAttribute('data-hn-page');
tr.removeAttribute('data-hn-frame'); tr.removeAttribute('data-hn-frame');
tr.removeAttribute('data-filter');
} else { } else {
tr = document.createElement('tr'); tr = document.createElement('tr');
} }
@ -431,6 +432,7 @@ var renderNetLogEntry = function(tr, entry) {
filter = filter.slice(3); filter = filter.slice(3);
if ( filteringType === 's' ) { if ( filteringType === 's' ) {
td.textContent = filterDecompiler.toString(filter); td.textContent = filterDecompiler.toString(filter);
tr.setAttribute('data-filter', filter);
} else { } else {
td.textContent = filter; td.textContent = filter;
} }
@ -587,7 +589,7 @@ var synchronizeTabIds = function(newTabIds) {
} }
} }
var select = document.getElementById('pageSelector'); var select = uDom.nodeFromId('pageSelector');
var selectValue = select.value; var selectValue = select.value;
var tabIds = Object.keys(newTabIds).sort(function(a, b) { var tabIds = Object.keys(newTabIds).sort(function(a, b) {
return newTabIds[a].localeCompare(newTabIds[b]); return newTabIds[a].localeCompare(newTabIds[b]);
@ -692,8 +694,8 @@ var readLogBuffer = function() {
/******************************************************************************/ /******************************************************************************/
var pageSelectorChanged = function() { var pageSelectorChanged = function() {
var style = document.getElementById('tabFilterer'); var style = uDom.nodeFromId('tabFilterer');
var tabClass = document.getElementById('pageSelector').value; var tabClass = uDom.nodeFromId('pageSelector').value;
var sheet = style.sheet; var sheet = style.sheet;
while ( sheet.cssRules.length !== 0 ) { while ( sheet.cssRules.length !== 0 ) {
sheet.deleteRule(0); sheet.deleteRule(0);
@ -713,7 +715,7 @@ var pageSelectorChanged = function() {
/******************************************************************************/ /******************************************************************************/
var reloadTab = function() { var reloadTab = function() {
var tabClass = document.getElementById('pageSelector').value; var tabClass = uDom.nodeFromId('pageSelector').value;
var tabId = tabIdFromClassName(tabClass); var tabId = tabIdFromClassName(tabClass);
if ( tabId === 'bts' || tabId === '' ) { if ( tabId === 'bts' || tabId === '' ) {
return; return;
@ -746,7 +748,7 @@ var onMaxEntriesChanged = function() {
/******************************************************************************/ /******************************************************************************/
/******************************************************************************/ /******************************************************************************/
var filteringDialog = (function() { var netFilteringManager = (function() {
var targetRow = null; var targetRow = null;
var dialog = null; var dialog = null;
var createdStaticFilters = {}; var createdStaticFilters = {};
@ -856,8 +858,8 @@ var filteringDialog = (function() {
var onClick = function(ev) { var onClick = function(ev) {
var target = ev.target; var target = ev.target;
// click outside the url filtering menu // click outside the dialog proper
if ( target.id === 'urlFilteringMenu' ) { if ( target.classList.contains('modalDialog') ) {
toggleOff(); toggleOff();
return; return;
} }
@ -1217,14 +1219,14 @@ var filteringDialog = (function() {
createPreview(targetType, targetURLs[0]); createPreview(targetType, targetURLs[0]);
fillDynamicPane(); fillDynamicPane();
fillStaticPane(); fillStaticPane();
document.body.appendChild(urlFilteringMenu); document.body.appendChild(netFilteringDialog);
urlFilteringMenu.addEventListener('click', onClick, true); netFilteringDialog.addEventListener('click', onClick, true);
urlFilteringMenu.addEventListener('change', onSelectChange, true); netFilteringDialog.addEventListener('change', onSelectChange, true);
urlFilteringMenu.addEventListener('input', onInputChange, true); netFilteringDialog.addEventListener('input', onInputChange, true);
}; };
var toggleOn = function(ev) { var toggleOn = function(ev) {
dialog = urlFilteringMenu.querySelector('.dialog'); dialog = netFilteringDialog.querySelector('.dialog');
targetRow = ev.target.parentElement; targetRow = ev.target.parentElement;
targetTabId = tabIdFromClassName(targetRow.className); targetTabId = tabIdFromClassName(targetRow.className);
targetType = targetRow.cells[4].textContent.trim() || ''; targetType = targetRow.cells[4].textContent.trim() || '';
@ -1245,10 +1247,104 @@ var filteringDialog = (function() {
dialog = null; dialog = null;
targetRow = null; targetRow = null;
targetURLs = []; targetURLs = [];
urlFilteringMenu.removeEventListener('click', onClick, true); netFilteringDialog.removeEventListener('click', onClick, true);
urlFilteringMenu.removeEventListener('change', onSelectChange, true); netFilteringDialog.removeEventListener('change', onSelectChange, true);
urlFilteringMenu.removeEventListener('input', onInputChange, true); netFilteringDialog.removeEventListener('input', onInputChange, true);
document.body.removeChild(urlFilteringMenu); document.body.removeChild(netFilteringDialog);
};
return {
toggleOn: toggleOn
};
})();
/******************************************************************************/
/******************************************************************************/
var reverseLookupManager = (function() {
var rawFilter = '';
var reSentence1 = /\{\{filter\}\}/g;
var sentence1Template = vAPI.i18n('loggerStaticFilteringFinderSentence1');
var removeAllChildren = function(node) {
while ( node.firstChild ) {
node.removeChild(node.firstChild);
}
};
var onClick = function(ev) {
var target = ev.target;
// click outside the dialog proper
if ( target.classList.contains('modalDialog') ) {
toggleOff();
return;
}
ev.stopPropagation();
};
var reverseLookupDone = function(response) {
var lists = response.matches;
if ( Array.isArray(lists) === false ) {
return;
}
var dialog = filterFinderDialog.querySelector('.dialog');
var p = dialog.querySelector('p');
removeAllChildren(p);
var node;
reSentence1.lastIndex = 0;
var matches = reSentence1.exec(sentence1Template);
if ( matches === null ) {
node = document.createTextNode(sentence1Template);
} else {
node = uDom.nodeFromSelector('#filterFinderDialogSentence1 > span').cloneNode(true);
node.childNodes[0].textContent = sentence1Template.slice(0, matches.index);
node.childNodes[1].textContent = rawFilter;
node.childNodes[2].textContent = sentence1Template.slice(reSentence1.lastIndex);
}
p.appendChild(node);
var ul = dialog.querySelector('ul');
removeAllChildren(ul);
var list, li;
for ( var i = 0; i < lists.length; i++ ) {
list = lists[i];
li = document.createElement('li');
if ( list.supportURL ) {
node = document.createElement('a');
node.textContent = list.title;
node.setAttribute('href', list.supportURL);
node.setAttribute('target', '_blank');
} else {
node = document.createTextNode(list.title);
}
li.appendChild(node);
ul.appendChild(li);
}
document.body.appendChild(filterFinderDialog);
filterFinderDialog.addEventListener('click', onClick, true);
};
var toggleOn = function(ev) {
var row = ev.target.parentElement;
var filter = row.getAttribute('data-filter') || '';
if ( filter === '' ) {
return;
}
rawFilter = row.cells[2].textContent;
messager.send({
what: 'reverseLookupFilter',
filter: filter
}, reverseLookupDone);
};
var toggleOff = function() {
filterFinderDialog.removeEventListener('click', onClick, true);
document.body.removeChild(filterFinderDialog);
}; };
return { return {
@ -1489,7 +1585,7 @@ var popupManager = (function() {
realTabId = noTabId; realTabId = noTabId;
} }
container = document.getElementById('popupContainer'); container = uDom.nodeFromId('popupContainer');
container.querySelector('div > span:nth-of-type(1)').addEventListener('click', toggleSize); container.querySelector('div > span:nth-of-type(1)').addEventListener('click', toggleSize);
container.querySelector('div > span:nth-of-type(2)').addEventListener('click', toggleOff); container.querySelector('div > span:nth-of-type(2)').addEventListener('click', toggleOff);
@ -1500,7 +1596,7 @@ var popupManager = (function() {
popupObserver = new MutationObserver(resizePopup); popupObserver = new MutationObserver(resizePopup);
container.appendChild(popup); container.appendChild(popup);
style = document.getElementById('popupFilterer'); style = uDom.nodeFromId('popupFilterer');
style.textContent = styleTemplate.replace('{{tabId}}', localTabId); style.textContent = styleTemplate.replace('{{tabId}}', localTabId);
document.body.classList.add('popupOn'); document.body.classList.add('popupOn');
@ -1559,7 +1655,8 @@ uDom.onLoad(function() {
uDom('#clear').on('click', clearBuffer); uDom('#clear').on('click', clearBuffer);
uDom('#maxEntries').on('change', onMaxEntriesChanged); uDom('#maxEntries').on('change', onMaxEntriesChanged);
uDom('#content table').on('click', 'tr.canMtx > td:nth-of-type(2)', popupManager.toggleOn); uDom('#content table').on('click', 'tr.canMtx > td:nth-of-type(2)', popupManager.toggleOn);
uDom('#content').on('click', 'tr.cat_net > td:nth-of-type(4)', filteringDialog.toggleOn); uDom('#content').on('click', 'tr.cat_net > td:nth-of-type(4)', netFilteringManager.toggleOn);
uDom('#content').on('click', 'tr[data-filter] > td:nth-of-type(3)', reverseLookupManager.toggleOn);
}); });
/******************************************************************************/ /******************************************************************************/

View File

@ -66,6 +66,10 @@ var onMessage = function(request, sender, callback) {
µb.reloadAllFilters(callback); µb.reloadAllFilters(callback);
return; return;
case 'reverseLookupFilter':
µb.staticFilteringReverseLookup.lookup(request.filter, callback);
return;
default: default:
break; break;
} }

View File

@ -0,0 +1,79 @@
/*******************************************************************************
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 onmessage, postMessage */
'use strict';
/******************************************************************************/
var listEntries = Object.create(null);
/******************************************************************************/
var lookup = function(details) {
var matches = [];
var entry, pos;
for ( var path in listEntries ) {
entry = listEntries[path];
if ( entry === undefined ) {
continue;
}
pos = entry.content.indexOf(details.filter);
if ( pos === -1 ) {
continue;
}
matches.push({
title: entry.title,
supportURL: entry.supportURL
});
}
postMessage({
id: details.id,
response: {
filter: details.filter,
matches: matches
}
});
};
/******************************************************************************/
onmessage = function(e) {
var msg = e.data;
switch ( msg.what ) {
case 'resetLists':
listEntries = Object.create(null);
break;
case 'setList':
listEntries[msg.details.path] = msg.details;
break;
case 'reverseLookup':
lookup(msg);
break;
}
};
/******************************************************************************/

177
src/js/reverselookup.js Normal file
View File

@ -0,0 +1,177 @@
/*******************************************************************************
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 µBlock */
/******************************************************************************/
µBlock.staticFilteringReverseLookup = (function() {
'use strict';
/******************************************************************************/
var worker = null;
var workerTTL = 11 * 60 * 1000;
var workerTTLTimer = null;
var needLists = true;
var messageId = 1;
var pendingResponses = Object.create(null);
/******************************************************************************/
var onWorkerMessage = function(e) {
var msg = e.data;
var callback = pendingResponses[msg.id];
delete pendingResponses[msg.id];
callback(msg.response);
};
/******************************************************************************/
var stopWorker = function() {
workerTTLTimer = null;
if ( worker === null ) {
return;
}
worker.terminate();
worker = null;
needLists = true;
pendingResponses = Object.create(null);
};
/******************************************************************************/
var initWorker = function(callback) {
if ( worker === null ) {
worker = new Worker('js/reverselookup-worker.js');
worker.onmessage = onWorkerMessage;
}
if ( needLists === false ) {
callback();
return;
}
needLists = false;
var entries = Object.create(null);
var countdown = 0;
var path, entry;
var onListLoaded = function(details) {
var entry = entries[details.path];
worker.postMessage({
what: 'setList',
details: {
path: details.path,
title: entry.title || '',
supportURL: entry.supportURL,
content: details.content
}
});
countdown -= 1;
if ( countdown === 0 ) {
callback();
}
};
var µb = µBlock;
for ( path in µb.remoteBlacklists ) {
if ( µb.remoteBlacklists.hasOwnProperty(path) === false ) {
continue;
}
entry = µb.remoteBlacklists[path];
if ( entry.off === true ) {
continue;
}
entries[path] = {
title: entry.title,
supportURL: entry.supportURL || ''
};
countdown += 1;
}
if ( countdown === 0 ) {
callback();
return;
}
for ( path in entries ) {
µb.getCompiledFilterList(path, onListLoaded);
}
};
/******************************************************************************/
var lookup = function(compiledFilter, callback) {
if ( typeof callback !== 'function' ) {
return;
}
if ( workerTTLTimer !== null ) {
clearTimeout(workerTTLTimer);
workerTTLTimer = null;
}
var onWorkerReady = function() {
var id = messageId++;
var message = {
what: 'reverseLookup',
id: id,
filter: compiledFilter
};
pendingResponses[id] = callback;
worker.postMessage(message);
// The worker will be shutdown after n minutes without being used.
workerTTLTimer = vAPI.setTimeout(stopWorker, workerTTL);
};
initWorker(onWorkerReady);
};
/******************************************************************************/
// This tells the worker that filter lists may have changed.
var resetLists = function() {
needLists = true;
if ( worker === null ) {
return;
}
worker.postMessage({ what: 'resetLists' });
};
/******************************************************************************/
return {
lookup: lookup,
resetLists: resetLists,
shutdown: stopWorker
};
/******************************************************************************/
})();
/******************************************************************************/

View File

@ -37,6 +37,18 @@ var µb = µBlock;
/******************************************************************************/ /******************************************************************************/
vAPI.app.onShutdown = function() {
µb.staticFilteringReverseLookup.shutdown();
µb.staticNetFilteringEngine.reset();
µb.sessionFirewall.reset();
µb.permanentFirewall.reset();
µb.permanentFirewall.reset();
µb.sessionURLFiltering.reset();
µb.permanentURLFiltering.reset();
};
/******************************************************************************/
// Final initialization steps after all needed assets are in memory. // Final initialization steps after all needed assets are in memory.
// - Initialize internal state with maybe already existing tabs. // - Initialize internal state with maybe already existing tabs.
// - Schedule next update operation. // - Schedule next update operation.

View File

@ -160,11 +160,6 @@ histogram = function(label, categories) {
// Local helpers // Local helpers
// Could be replaced with encodeURIComponent/decodeURIComponent,
// which seems faster on Firefox.
var encode = JSON.stringify;
var decode = JSON.parse;
var cachedParseInt = parseInt; var cachedParseInt = parseInt;
var atoi = function(s) { var atoi = function(s) {
@ -1651,12 +1646,10 @@ FilterContainer.prototype.toSelfie = function() {
var categoryToSelfie = function(dict) { var categoryToSelfie = function(dict) {
var selfie = []; var selfie = [];
var bucket, ff, n, i, f; var bucket, ff, n, i, f;
for ( var k in dict ) { for ( var token in dict ) {
// No need for hasOwnProperty() here: there is no prototype chain. // No need for hasOwnProperty() here: there is no prototype chain.
// We need to encode the key because there could be a `\n` or '\t' selfie.push('k2\t' + token);
// character in it, which would trip the code at parse time. bucket = dict[token];
selfie.push('k2\t' + encode(k));
bucket = dict[k];
selfie.push(bucket.fid + '\t' + bucket.toSelfie()); selfie.push(bucket.fid + '\t' + bucket.toSelfie());
if ( bucket.fid !== '[]' ) { if ( bucket.fid !== '[]' ) {
continue; continue;
@ -1673,12 +1666,10 @@ FilterContainer.prototype.toSelfie = function() {
var categoriesToSelfie = function(dict) { var categoriesToSelfie = function(dict) {
var selfie = []; var selfie = [];
for ( var k in dict ) { for ( var key in dict ) {
// No need for hasOwnProperty() here: there is no prototype chain. // No need for hasOwnProperty() here: there is no prototype chain.
// We need to encode the key because there could be a `\n` or '\t' selfie.push('k1\t' + key);
// character in it, which would trip the code at parse time. selfie.push(categoryToSelfie(dict[key]));
selfie.push('k1\t' + encode(k));
selfie.push(categoryToSelfie(dict[k]));
} }
return selfie.join('\n'); return selfie.join('\n');
}; };
@ -1722,13 +1713,13 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
pos = line.indexOf('\t'); pos = line.indexOf('\t');
what = line.slice(0, pos); what = line.slice(0, pos);
if ( what === 'k1' ) { if ( what === 'k1' ) {
catKey = decode(line.slice(pos + 1)); catKey = line.slice(pos + 1);
subdict = dict[catKey] = Object.create(null); subdict = dict[catKey] = Object.create(null);
bucket = null; bucket = null;
continue; continue;
} }
if ( what === 'k2' ) { if ( what === 'k2' ) {
tokenKey = decode(line.slice(pos + 1)); tokenKey = line.slice(pos + 1);
bucket = null; bucket = null;
continue; continue;
} }
@ -2015,18 +2006,18 @@ FilterContainer.prototype.filterStringFromCompiled = function(compiled) {
var opts = []; var opts = [];
var vfields = compiled.split('\v'); var vfields = compiled.split('\v');
var filter = ''; var filter = '';
var bits = parseInt(vfields[1], 16) | 0; var bits = parseInt(vfields[0], 16) | 0;
if ( bits & 0x01 ) { if ( bits & 0x01 ) {
filter += '@@'; filter += '@@';
} }
var rfid = vfields[2] === '.' ? '.' : vfields[3]; var rfid = vfields[1] === '.' ? '.' : vfields[2];
var tfields = rfid !== '.' ? vfields[4].split('\t') : []; var tfields = rfid !== '.' ? vfields[3].split('\t') : [];
switch ( rfid ) { switch ( rfid ) {
case '.': case '.':
filter += '||' + vfields[3] + '^'; filter += '||' + vfields[2] + '^';
break; break;
case 'a': case 'a':
case 'ah': case 'ah':
@ -2102,13 +2093,13 @@ FilterContainer.prototype.filterStringFromCompiled = function(compiled) {
FilterContainer.prototype.filterRegexFromCompiled = function(compiled, flags) { FilterContainer.prototype.filterRegexFromCompiled = function(compiled, flags) {
var vfields = compiled.split('\v'); var vfields = compiled.split('\v');
var rfid = vfields[2] === '.' ? '.' : vfields[3]; var rfid = vfields[1] === '.' ? '.' : vfields[2];
var tfields = rfid !== '.' ? vfields[4].split('\t') : []; var tfields = rfid !== '.' ? vfields[3].split('\t') : [];
var re = null; var re = null;
switch ( rfid ) { switch ( rfid ) {
case '.': case '.':
re = strToRegex(vfields[3], 0, flags); re = strToRegex(vfields[2], 0, flags);
break; break;
case 'a': case 'a':
case 'ah': case 'ah':
@ -2476,7 +2467,7 @@ FilterContainer.prototype.toResultString = function(verbose) {
if ( !verbose ) { if ( !verbose ) {
return s; return s;
} }
s += 'n\v' + this.keyRegister + '\v' + this.tokenRegister + '\v'; s += this.keyRegister + '\v' + this.tokenRegister + '\v';
if ( this.tokenRegister === '.' ) { if ( this.tokenRegister === '.' ) {
s += this.fRegister.rtCompile(); s += this.fRegister.rtCompile();
} else { } else {

View File

@ -400,6 +400,7 @@
µb.cosmeticFilteringEngine.reset(); µb.cosmeticFilteringEngine.reset();
µb.staticNetFilteringEngine.reset(); µb.staticNetFilteringEngine.reset();
µb.destroySelfie(); µb.destroySelfie();
µb.staticFilteringReverseLookup.resetLists();
// We need to build a complete list of assets to pull first: this is // We need to build a complete list of assets to pull first: this is
// because it *may* happens that some load operations are synchronous: // because it *may* happens that some load operations are synchronous:

View File

@ -41,7 +41,7 @@
<div id="templates" style="display: none;"> <div id="templates" style="display: none;">
<div id="renderedURLTemplate"><span><span></span><b></b><span></span></span></div> <div id="renderedURLTemplate"><span><span></span><b></b><span></span></span></div>
<div id="hiddenTemplate"><span style="display:none;"></span></div> <div id="hiddenTemplate"><span style="display:none;"></span></div>
<div id="urlFilteringMenu"> <div id="netFilteringDialog" class="modalDialog">
<div class="dialog"> <div class="dialog">
<div class="hide preview"></div> <div class="hide preview"></div>
<div class="headers"> <div class="headers">
@ -79,6 +79,13 @@
</div> </div>
</div> </div>
</div> </div>
<div id="filterFinderDialog" class="modalDialog">
<div class="dialog">
<p></p>
<ul></ul>
</div>
</div>
<div id="filterFinderDialogSentence1"><span><span></span><code></code><span></span></span></div>
</div> </div>
<script src="js/vapi-common.js"></script> <script src="js/vapi-common.js"></script>