mirror of
https://github.com/gorhill/uBlock.git
synced 2026-03-11 09:04:36 +00:00
another round of work re dynamic filtering
This commit is contained in:
parent
ceaf920cff
commit
3c941f8309
18 changed files with 397 additions and 87 deletions
|
|
@ -2,7 +2,7 @@
|
|||
"manifest_version": 2,
|
||||
|
||||
"name": "µBlock",
|
||||
"version": "0.8.2.3",
|
||||
"version": "0.8.5.0",
|
||||
|
||||
"default_locale": "en",
|
||||
"description": "__MSG_extShortDesc__",
|
||||
|
|
|
|||
|
|
@ -425,7 +425,7 @@ vAPI.onLoadAllCompleted = function() {
|
|||
vAPI.tabs.injectScript(tabId, {
|
||||
file: 'js/contentscript-start.js',
|
||||
allFrames: true,
|
||||
runAt: 'document_idle'
|
||||
runAt: 'document_start'
|
||||
}, function(){ scriptEnd(tabId); });
|
||||
};
|
||||
var bindToTabs = function(tabs) {
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@
|
|||
|
||||
<div>
|
||||
<p data-i18n="1pFormatHint"></p>
|
||||
<p><button id="importUserFiltersFromFile" data-i18n="1pImport"></button>   <button id="exportUserFiltersToFile" data-i18n="1pExport"></button></p>
|
||||
<input id="importFilePicker" type="file" accept="text/plain" class="hiddenFileInput">
|
||||
<textarea class="userFilters" id="userFilters" dir="auto" spellcheck="false"></textarea>
|
||||
<p><button id="userFiltersApply" disabled="true" data-i18n="1pApplyChanges"></button></p>
|
||||
<textarea class="userFilters" id="userFilters" dir="auto" spellcheck="false"></textarea>
|
||||
<p><button id="importUserFiltersFromFile" data-i18n="1pImport"></button>  
|
||||
<button id="exportUserFiltersToFile" data-i18n="1pExport"></button>
|
||||
<input id="importFilePicker" type="file" accept="text/plain" class="hiddenFileInput"></p>
|
||||
</div>
|
||||
|
||||
<script src="js/vapi-common.js"></script>
|
||||
|
|
|
|||
|
|
@ -13,27 +13,31 @@
|
|||
},
|
||||
"settingsPageName":{
|
||||
"message":"Settings",
|
||||
"description":"appears as tab name in dashboard."
|
||||
"description":"appears as tab name in dashboard"
|
||||
},
|
||||
"3pPageName":{
|
||||
"message":"3rd-party filters",
|
||||
"description":"appears as tab name in dashboard."
|
||||
"description":"appears as tab name in dashboard"
|
||||
},
|
||||
"1pPageName":{
|
||||
"message":"Your filters",
|
||||
"description":"appears as tab name in dashboard."
|
||||
"message":"My filters",
|
||||
"description":"appears as tab name in dashboard"
|
||||
},
|
||||
"rulesPageName": {
|
||||
"message": "My rules",
|
||||
"description": "appears as tab name in dashboard"
|
||||
},
|
||||
"whitelistPageName":{
|
||||
"message":"Whitelist",
|
||||
"description":"appears as tab name in dashboard."
|
||||
"description":"appears as tab name in dashboard"
|
||||
},
|
||||
"statsPageName":{
|
||||
"message":"Statistics",
|
||||
"description":"appears as tab name in dashboard."
|
||||
"description":"appears as tab name in dashboard"
|
||||
},
|
||||
"aboutPageName":{
|
||||
"message":"About",
|
||||
"description":"appears as tab name in dashboard."
|
||||
"description":"appears as tab name in dashboard"
|
||||
},
|
||||
"popupPowerSwitchInfo":{
|
||||
"message":"Click: disable\/enable µBlock for this site.\n\nCtrl+click: disable µBlock only on this page.",
|
||||
|
|
@ -147,6 +151,30 @@
|
|||
"message":"3rd-party frames are <b>blocked<\/b> everywhere by default",
|
||||
"description":""
|
||||
},
|
||||
"popupImageRulePrompt":{
|
||||
"message":"images",
|
||||
"description":""
|
||||
},
|
||||
"popupInlineScriptRulePrompt":{
|
||||
"message":"inline scripts",
|
||||
"description":""
|
||||
},
|
||||
"popup1pScriptRulePrompt":{
|
||||
"message":"1st-party scripts",
|
||||
"description":""
|
||||
},
|
||||
"popup3pScriptRulePrompt":{
|
||||
"message":"3rd-party scripts",
|
||||
"description":""
|
||||
},
|
||||
"popup3pFrameRulePrompt":{
|
||||
"message":"3rd-party frames",
|
||||
"description":""
|
||||
},
|
||||
"popupHitDomainCountPrompt":{
|
||||
"message":"Connected to {{count}} distinct domain(s)",
|
||||
"description":"appear in dynamic filtering pane"
|
||||
},
|
||||
"pickerCreate":{
|
||||
"message":"Create",
|
||||
"description":"English: Create"
|
||||
|
|
@ -295,6 +323,30 @@
|
|||
"message":"Apply changes",
|
||||
"description":"English: Apply changes"
|
||||
},
|
||||
"rulesEdit": {
|
||||
"message": "Edit",
|
||||
"description": "Will enable manual-edit mode (textarea)"
|
||||
},
|
||||
"rulesEditSave": {
|
||||
"message": "Save",
|
||||
"description": "Will save manually-edited content and exit manual-edit mode"
|
||||
},
|
||||
"rulesEditDiscard": {
|
||||
"message": "Discard",
|
||||
"description": "Will discard manually-edited content and exit manual-edit mode"
|
||||
},
|
||||
"rulesImport": {
|
||||
"message": "Import from file...",
|
||||
"description": ""
|
||||
},
|
||||
"rulesExport": {
|
||||
"message": "Export to file...",
|
||||
"description": ""
|
||||
},
|
||||
"rulesDefaultFileName": {
|
||||
"message": "my-ublock-dynamic-rules.txt",
|
||||
"description": "default file name to use"
|
||||
},
|
||||
"whitelistPrompt":{
|
||||
"message":"Your list of host names for which µBlock will be disabled. One entry per line. Invalid host names will be silently ignored.",
|
||||
"description":"English: Your list of host names for which µBlock will be disabled. One host name per line. Invalid host names will be silently ignored."
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ div > p:last-child {
|
|||
margin-bottom: 0;
|
||||
}
|
||||
.userFilters {
|
||||
font-size: smaller;
|
||||
font-size: small;
|
||||
width: 48em;
|
||||
height: 40em;
|
||||
white-space: pre;
|
||||
|
|
|
|||
13
src/css/dyna-rules.css
Normal file
13
src/css/dyna-rules.css
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
div > p:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
div > p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#rulesEditor {
|
||||
font-size: small;
|
||||
width: 48em;
|
||||
height: 40em;
|
||||
white-space: pre;
|
||||
text-align: left;
|
||||
}
|
||||
|
|
@ -168,6 +168,9 @@ body.dynamicFilteringEnabled #dynamicFilteringContainer > div:hover {
|
|||
padding: 4px 0;
|
||||
text-align: center;
|
||||
}
|
||||
#dynamicFilteringContainer > div.isDomain {
|
||||
margin-top: 2px;
|
||||
}
|
||||
#dynamicFilteringContainer > div > span {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
|
|
@ -204,28 +207,28 @@ body.dynamicFilteringEnabled #dynamicFilteringContainer > div > span {
|
|||
#dynamicFilteringContainer > div.isDomain > span:nth-of-type(1) {
|
||||
font-weight: bold;
|
||||
}
|
||||
body.dynamicFilteringEnabled #dynamicFilteringContainer > div > span:nth-of-type(3) {
|
||||
#dynamicFilteringContainer > div > span:nth-of-type(3) {
|
||||
color: #666;
|
||||
pointer-events: auto;
|
||||
}
|
||||
#dynamicFilteringContainer span.aRule {
|
||||
#dynamicFilteringContainer > div > span.aRule {
|
||||
background-color: rgba(0, 160, 0, 0.3);
|
||||
}
|
||||
#dynamicFilteringContainer span.bRule {
|
||||
#dynamicFilteringContainer > div > span.bRule {
|
||||
background-color: rgba(192, 0, 0, 0.3);
|
||||
}
|
||||
#dynamicFilteringContainer span.nRule {
|
||||
#dynamicFilteringContainer > div > span.nRule {
|
||||
background-color: rgba(96, 96, 96, 0.3);
|
||||
}
|
||||
#dynamicFilteringContainer span.aRule.ownRule {
|
||||
#dynamicFilteringContainer > div > span.aRule.ownRule {
|
||||
background-color: rgba(0, 160, 0, 1);
|
||||
color: white;
|
||||
}
|
||||
#dynamicFilteringContainer span.bRule.ownRule {
|
||||
#dynamicFilteringContainer > div > span.bRule.ownRule {
|
||||
background-color: rgba(192, 0, 0, 1);
|
||||
color: white;
|
||||
}
|
||||
#dynamicFilteringContainer span.nRule.ownRule {
|
||||
#dynamicFilteringContainer > div > span.nRule.ownRule {
|
||||
background-color: rgba(108, 108, 108, 1);
|
||||
color: white;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ div > p:last-child {
|
|||
margin-bottom: 0;
|
||||
}
|
||||
#whitelist {
|
||||
font-size: smaller;
|
||||
font-size: small;
|
||||
width: 48em;
|
||||
height: 40em;
|
||||
white-space: pre;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
<span data-i18n="extName"></span>
|
||||
<a class="tabButton" href="#3p-filters.html" data-i18n="3pPageName"></a>
|
||||
<a class="tabButton" href="#1p-filters.html" data-i18n="1pPageName"></a>
|
||||
<a class="tabButton" href="#dyna-rules.html" data-i18n="rulesPageName"></a>
|
||||
<a class="tabButton" href="#whitelist.html" data-i18n="whitelistPageName"></a>
|
||||
<a class="tabButton" href="#settings.html" data-i18n="settingsPageName"></a>
|
||||
<a class="tabButton" href="#stats.html" data-i18n="statsPageName"></a>
|
||||
|
|
|
|||
31
src/dyna-rules.html
Normal file
31
src/dyna-rules.html
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>µMatrix — Dynamic filtering rules</title>
|
||||
<link rel="stylesheet" type="text/css" href="css/common.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/dashboard-common.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/dyna-rules.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div>
|
||||
<p data-i18n="rulesFormatHint"></p>
|
||||
<p><button id="rulesApply" disabled="true" data-i18n="1pApplyChanges"></button></p>
|
||||
<textarea id="rulesEditor" spellcheck="false"></textarea>
|
||||
<p><button id="importButton" type="button" data-i18n="1pImport"></button>  
|
||||
<button id="exportButton" type="button" data-i18n="1pExport"></button>
|
||||
<input class="hidden" id="importFilePicker" type="file" accept="text/plain" style="display: none;"></p>
|
||||
<span class="hidden" data-i18n="rulesDefaultFileName" style="display: none;"></span>
|
||||
</div>
|
||||
|
||||
<script src="js/vapi-common.js"></script>
|
||||
<script src="js/vapi-client.js"></script>
|
||||
<script src="js/udom.js"></script>
|
||||
<script src="js/i18n.js"></script>
|
||||
<script src="js/dashboard-common.js"></script>
|
||||
<script src="js/dyna-rules.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
155
src/js/dyna-rules.js
Normal file
155
src/js/dyna-rules.js
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/*******************************************************************************
|
||||
|
||||
µMatrix - a Chromium browser extension to block requests.
|
||||
Copyright (C) 2014 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/uMatrix
|
||||
*/
|
||||
|
||||
/* global chrome, messaging, uDom */
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var messager = vAPI.messaging.channel('dyna-rules.js');
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Switches before, rules after
|
||||
|
||||
var normalizeRawRules = function(s) {
|
||||
return s.replace(/[ \t]+/g, ' ')
|
||||
.split(/\s*\n+\s*/)
|
||||
.sort(directiveSort)
|
||||
.join('\n')
|
||||
.trim();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// This is to give a visual hint that the content of user blacklist has changed.
|
||||
|
||||
function rulesChanged() {
|
||||
uDom('#rulesApply').prop(
|
||||
'disabled',
|
||||
normalizeRawRules(uDom('#rulesEditor').val()) === cachedRawRules
|
||||
);
|
||||
}
|
||||
|
||||
var cachedRawRules = '';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Switches before, rules after
|
||||
|
||||
var directiveSort = function(a, b) {
|
||||
var aIsSwitch = a.indexOf(':') !== -1;
|
||||
var bIsSwitch = b.indexOf(':') !== -1;
|
||||
if ( aIsSwitch === bIsSwitch ) {
|
||||
return a.localeCompare(b);
|
||||
}
|
||||
return aIsSwitch ? -1 : 1;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var processRules = function(rawRules) {
|
||||
cachedRawRules = normalizeRawRules(rawRules);
|
||||
uDom('#rulesEditor').val(cachedRawRules);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var rulesApplyHandler = function() {
|
||||
var onWritten = function(response) {
|
||||
processRules(response);
|
||||
rulesChanged();
|
||||
};
|
||||
var request = {
|
||||
what: 'setDynamicRules',
|
||||
rawRules: uDom('#rulesEditor').val()
|
||||
};
|
||||
messager.send(request, onWritten);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
function handleImportFilePicker() {
|
||||
var fileReaderOnLoadHandler = function() {
|
||||
if ( typeof this.result !== 'string' || this.result === '' ) {
|
||||
return;
|
||||
}
|
||||
var request = {
|
||||
'what': 'setDynamicRules',
|
||||
'rawRules': uDom('#rulesEditor').val()
|
||||
};
|
||||
messager.send(request, processRules);
|
||||
};
|
||||
var file = this.files[0];
|
||||
if ( file === undefined || file.name === '' ) {
|
||||
return;
|
||||
}
|
||||
if ( file.type.indexOf('text') !== 0 ) {
|
||||
return;
|
||||
}
|
||||
var fr = new FileReader();
|
||||
fr.onload = fileReaderOnLoadHandler;
|
||||
fr.readAsText(file);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var startImportFilePicker = function() {
|
||||
var input = document.getElementById('importFilePicker');
|
||||
// Reset to empty string, this will ensure an change event is properly
|
||||
// triggered if the user pick a file, even if it is the same as the last
|
||||
// one picked.
|
||||
input.value = '';
|
||||
input.click();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
function exportUserRulesToFile() {
|
||||
chrome.downloads.download({
|
||||
'url': 'data:text/plain,' + encodeURIComponent(rulesFromHTML('#diff .left li')),
|
||||
'filename': uDom('[data-i18n="userRulesDefaultFileName"]').text(),
|
||||
'saveAs': true
|
||||
});
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uDom.onLoad(function() {
|
||||
// Handle user interaction
|
||||
uDom('#importButton').on('click', startImportFilePicker);
|
||||
uDom('#importFilePicker').on('change', handleImportFilePicker);
|
||||
uDom('#exportButton').on('click', exportUserRulesToFile);
|
||||
uDom('#rulesEditor').on('input', rulesChanged);
|
||||
uDom('#rulesApply').on('click', rulesApplyHandler);
|
||||
|
||||
messager.send({ what: 'getDynamicRules' }, processRules);
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
|
||||
|
|
@ -47,13 +47,13 @@ var typeBitOffsets = {
|
|||
'image': 10
|
||||
};
|
||||
|
||||
var stateToNameMap = {
|
||||
var actionToNameMap = {
|
||||
'1': 'block',
|
||||
'2': 'allow',
|
||||
'3': 'noop'
|
||||
};
|
||||
|
||||
var nameToStateMap = {
|
||||
var nameToActionMap = {
|
||||
'block': 1,
|
||||
'allow': 2,
|
||||
'noop': 3
|
||||
|
|
@ -187,6 +187,7 @@ Matrix.prototype.clearRegisters = function() {
|
|||
this.type = '';
|
||||
this.y = '';
|
||||
this.z = '';
|
||||
return this;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
@ -320,7 +321,7 @@ Matrix.prototype.toString = function() {
|
|||
punycode.toUnicode(srcHostname) + ' ' +
|
||||
punycode.toUnicode(desHostname) + ' ' +
|
||||
type + ' ' +
|
||||
stateToNameMap[val]
|
||||
actionToNameMap[val]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -332,11 +333,12 @@ Matrix.prototype.toString = function() {
|
|||
Matrix.prototype.fromString = function(text, append) {
|
||||
var textEnd = text.length;
|
||||
var lineBeg = 0, lineEnd;
|
||||
var line, pos;
|
||||
var fields, fieldVal;
|
||||
var srcHostname = '';
|
||||
var desHostname = '';
|
||||
var type, state;
|
||||
var line, pos, fields;
|
||||
var srcHostname, desHostname, type, action;
|
||||
|
||||
if ( append !== true ) {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
while ( lineBeg < textEnd ) {
|
||||
lineEnd = text.indexOf('\n', lineBeg);
|
||||
|
|
@ -357,59 +359,33 @@ Matrix.prototype.fromString = function(text, append) {
|
|||
continue;
|
||||
}
|
||||
|
||||
fields = line.split(/\s+/);
|
||||
|
||||
// Less than 2 fields makes no sense
|
||||
if ( fields.length < 2 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fieldVal = fields[0];
|
||||
|
||||
// Valid rule syntax:
|
||||
|
||||
// srcHostname desHostname [type [state]]
|
||||
// srcHostname desHostname type state
|
||||
// type = a valid request type
|
||||
// state = [`block`, `allow`, `inherit`]
|
||||
|
||||
// srcHostname desHostname type
|
||||
// type = a valid request type
|
||||
// state = `allow`
|
||||
|
||||
// srcHostname desHostname
|
||||
// type = `*`
|
||||
// state = `allow`
|
||||
// state = [`block`, `allow`, `noop`]
|
||||
|
||||
// Lines with invalid syntax silently ignored
|
||||
|
||||
fields = line.split(/\s+/);
|
||||
if ( fields.length !== 4 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
srcHostname = punycode.toASCII(fields[0]);
|
||||
desHostname = punycode.toASCII(fields[1]);
|
||||
|
||||
fieldVal = fields[2];
|
||||
|
||||
if ( fieldVal !== undefined ) {
|
||||
type = fieldVal;
|
||||
// Unknown type: reject
|
||||
if ( typeBitOffsets.hasOwnProperty(type) === false ) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
type = '*';
|
||||
type = fields[2];
|
||||
if ( typeBitOffsets.hasOwnProperty(type) === false ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fieldVal = fields[3];
|
||||
|
||||
if ( fieldVal !== undefined ) {
|
||||
// Unknown state: reject
|
||||
if ( nameToStateMap.hasOwnProperty(fieldVal) === false ) {
|
||||
continue;
|
||||
}
|
||||
state = nameToStateMap[fieldVal];
|
||||
} else {
|
||||
state = 2;
|
||||
action = nameToActionMap[fields[3]];
|
||||
if ( typeof action !== 'number' || action < 0 || action > 3 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.setCell(srcHostname, desHostname, type, state);
|
||||
this.setCell(srcHostname, desHostname, type, action);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -640,6 +640,55 @@ vAPI.messaging.listen('1p-filters.js', onMessage);
|
|||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// dyna-rules.js
|
||||
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var µb = µBlock;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var onMessage = function(request, sender, callback) {
|
||||
// Async
|
||||
switch ( request.what ) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Sync
|
||||
var response;
|
||||
|
||||
switch ( request.what ) {
|
||||
case 'getDynamicRules':
|
||||
response = µb.dynamicNetFilteringEngine.toString();
|
||||
break;
|
||||
|
||||
case 'setDynamicRules':
|
||||
µb.dynamicNetFilteringEngine.fromString(request.rawRules);
|
||||
µb.saveDynamicRules();
|
||||
response = µb.dynamicNetFilteringEngine.toString();
|
||||
break;
|
||||
|
||||
default:
|
||||
return vAPI.messaging.UNHANDLED;
|
||||
}
|
||||
|
||||
callback(response);
|
||||
};
|
||||
|
||||
vAPI.messaging.listen('dyna-rules.js', onMessage);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// whitelist.js
|
||||
|
||||
(function() {
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ var threePlus = '+++';
|
|||
var threeMinus = '−−−';
|
||||
var sixSpace = '\u2007\u2007\u2007\u2007\u2007\u2007';
|
||||
var dynaHotspots = null;
|
||||
var hostnameToSortableTokenMap = {};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
|
@ -59,11 +60,30 @@ var messager = vAPI.messaging.channel('popup.js');
|
|||
/******************************************************************************/
|
||||
|
||||
var cachePopupData = function(data) {
|
||||
if ( data ) {
|
||||
stats = data;
|
||||
scopeToSrcHostnameMap['.'] = data.pageHostname || '';
|
||||
stats = {};
|
||||
scopeToSrcHostnameMap['.'] = '';
|
||||
hostnameToSortableTokenMap = {};
|
||||
if ( typeof data !== 'object' ) {
|
||||
return stats;
|
||||
}
|
||||
stats = data;
|
||||
scopeToSrcHostnameMap['.'] = stats.pageHostname || '';
|
||||
var hostnameDict = stats.hostnameDict;
|
||||
if ( typeof hostnameDict === 'object' ) {
|
||||
var domain, prefix;
|
||||
for ( var hostname in hostnameDict ) {
|
||||
if ( hostnameDict.hasOwnProperty(hostname) === false ) {
|
||||
continue;
|
||||
}
|
||||
domain = hostnameDict[hostname].domain;
|
||||
if ( domain === stats.pageDomain ) {
|
||||
domain = '\u0020';
|
||||
}
|
||||
prefix = hostname.slice(0, 0 - domain.length);
|
||||
hostnameToSortableTokenMap[hostname] = domain + prefix.split('.').reverse().join('.');
|
||||
}
|
||||
}
|
||||
return data;
|
||||
return stats;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
@ -80,11 +100,11 @@ var formatNumber = function(count) {
|
|||
var rulekeyCompare = function(a, b) {
|
||||
var ha = a.slice(2, a.indexOf(' ', 2));
|
||||
if ( !reIP.test(ha) ) {
|
||||
ha = ha.split('.').reverse().join('.').replace(reRulekeyCompareNoise, '~');
|
||||
ha = hostnameToSortableTokenMap[ha] || '';
|
||||
}
|
||||
var hb = b.slice(2, b.indexOf(' ', 2));
|
||||
if ( !reIP.test(hb) ) {
|
||||
hb = hb.split('.').reverse().join('.').replace(reRulekeyCompareNoise, '~');
|
||||
hb = hostnameToSortableTokenMap[hb] || '';
|
||||
}
|
||||
return ha.localeCompare(hb);
|
||||
};
|
||||
|
|
@ -142,7 +162,7 @@ var syncDynamicFilterCell = function(scope, des, type, result) {
|
|||
var matches = reSrcHostnameFromResult.exec(result);
|
||||
if ( matches !== null ) {
|
||||
ownRule = matches[2] === des &&
|
||||
matches[1] === scopeToSrcHostnameMap[scope];
|
||||
matches[1] === scopeToSrcHostnameMap[scope];
|
||||
}
|
||||
cell.toggleClass('ownRule', ownRule);
|
||||
|
||||
|
|
@ -194,7 +214,7 @@ var syncAllDynamicFilters = function() {
|
|||
syncDynamicFilterCell(key.charAt(0), key.slice(2, key.indexOf(' ', 2)), '*', rules[key]);
|
||||
}
|
||||
|
||||
uDom('#privacyInfo > b').text(Object.keys(touchedDomains).length);
|
||||
uDom('#privacyInfo').text(vAPI.i18n('popupHitDomainCountPrompt').replace('{{count}}', Object.keys(touchedDomains).length));
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
|||
|
|
@ -86,6 +86,13 @@
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
µBlock.saveDynamicRules = function() {
|
||||
this.userSettings.dynamicFilteringString = this.dynamicNetFilteringEngine.toString();
|
||||
this.XAL.keyvalSetOne('dynamicFilteringString', this.userSettings.dynamicFilteringString);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
µBlock.saveWhitelist = function() {
|
||||
var bin = {
|
||||
'netWhitelist': this.stringFromWhitelist(this.netWhitelist)
|
||||
|
|
|
|||
|
|
@ -350,7 +350,8 @@ var matchWhitelistDirective = function(url, hostname, directive) {
|
|||
// evaluation of static filtering.
|
||||
// Dynamic filtering evaluation is ordered from most-specific to least-
|
||||
// specific.
|
||||
var df = this.dynamicNetFilteringEngine;
|
||||
var df = this.dynamicNetFilteringEngine.clearRegisters();
|
||||
|
||||
var rootHostname = context.rootHostname;
|
||||
var requestHostname = context.requestHostname;
|
||||
var requestType = context.requestType;
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@
|
|||
<h4 title="popupTipDashboard">v<span id="version"></span></h4>
|
||||
<div>
|
||||
<div id="dynamicFilteringContainer">
|
||||
<div><span>images</span><span data-src="/" data-des="*" data-type="image"> </span><span data-src="." data-des="*" data-type="image"></span></div>
|
||||
<div><span>inline scripts</span><span data-src="/" data-des="*" data-type="inline-script"> </span><span data-src="." data-des="*" data-type="inline-script"> </span></div>
|
||||
<div><span>1st-party scripts</span><span data-src="/" data-des="*" data-type="1p-script"> </span><span data-src="." data-des="*" data-type="1p-script"> </span></div>
|
||||
<div><span>3rd-party scripts</span><span data-src="/" data-des="*" data-type="3p-script"> </span><span data-src="." data-des="*" data-type="3p-script"> </span></div>
|
||||
<div><span>3rd-party frames</span><span data-src="/" data-des="*" data-type="3p-frame"> </span><span data-src="." data-des="*" data-type="3p-frame"> </span></div>
|
||||
<div id="privacyInfo"><b>?</b> distinct domains touched</div>
|
||||
<div><span data-i18n="popupImageRulePrompt"></span><span data-src="/" data-des="*" data-type="image"> </span><span data-src="." data-des="*" data-type="image"></span></div>
|
||||
<div><span data-i18n="popupInlineScriptRulePrompt"></span><span data-src="/" data-des="*" data-type="inline-script"> </span><span data-src="." data-des="*" data-type="inline-script"> </span></div>
|
||||
<div><span data-i18n="popup1pScriptRulePrompt"></span><span data-src="/" data-des="*" data-type="1p-script"> </span><span data-src="." data-des="*" data-type="1p-script"> </span></div>
|
||||
<div><span data-i18n="popup3pScriptRulePrompt"></span><span data-src="/" data-des="*" data-type="3p-script"> </span><span data-src="." data-des="*" data-type="3p-script"> </span></div>
|
||||
<div><span data-i18n="popup3pFrameRulePrompt"></span><span data-src="/" data-des="*" data-type="3p-frame"> </span><span data-src="." data-des="*" data-type="3p-frame"> </span></div>
|
||||
<div id="privacyInfo"></div>
|
||||
</div>
|
||||
</div><!-- DO NOT REMOVE --><div>
|
||||
<p id="switch" data-i18n-tip="popupPowerSwitchInfo"><span class="fa"></span></p>
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@
|
|||
|
||||
<div>
|
||||
<p data-i18n="whitelistPrompt"></p>
|
||||
<p><button id="importWhitelistFromFile" data-i18n="whitelistImport"></button>   <button id="exportWhitelistToFile" data-i18n="whitelistExport"></button></p>
|
||||
<input id="importFilePicker" type="file" accept="text/plain" class="hiddenFileInput">
|
||||
<textarea id="whitelist" dir="auto" spellcheck="false"></textarea>
|
||||
<p><button id="whitelistApply" type="button" disabled="true" data-i18n="whitelistApply"></button></p>
|
||||
<textarea id="whitelist" dir="auto" spellcheck="false"></textarea>
|
||||
<p><button id="importWhitelistFromFile" data-i18n="whitelistImport"></button>  
|
||||
<button id="exportWhitelistToFile" data-i18n="whitelistExport"></button>
|
||||
<input id="importFilePicker" type="file" accept="text/plain" class="hiddenFileInput"></p>
|
||||
</div>
|
||||
|
||||
<script src="lib/punycode.min.js"></script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue