diff --git a/1p-filters.html b/1p-filters.html index e474dbf60..7f6695a79 100644 --- a/1p-filters.html +++ b/1p-filters.html @@ -12,9 +12,6 @@ div > p:first-child { div > p:last-child { margin-bottom: 0; } -.dim { - color: #444; - } .userFilters { font-size: smaller; width: 48em; diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 94e1ce53a..b710a30df 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -19,6 +19,10 @@ "message":"Deine Filter", "description":"appears as tab name in dashboard." }, + "whitelistPageName":{ + "message":"Whitelist", + "description":"appears as tab name in dashboard." + }, "statsPageName":{ "message":"Statistiken", "description":"appears as tab name in dashboard." @@ -139,6 +143,22 @@ "message":"Änderungen anwenden", "description":"English: Apply changes" }, + "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." + }, + "whitelistImport":{ + "message":"Import and append", + "description":"English: Import and append" + }, + "whitelistExport":{ + "message":"Export", + "description":"English: Export" + }, + "whitelistApply":{ + "message":"Apply changes", + "description":"English: Apply changes" + }, "logBlockedRequestsPrompt":{ "message":"Protokollieren von blockierten Elementen aktivieren", "description":"English: Enable the logging of blocked requests" diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 275da84ed..1b5f5dc30 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -19,6 +19,10 @@ "message":"Your filters", "description":"appears as tab name in dashboard." }, + "whitelistPageName":{ + "message":"Whitelist", + "description":"appears as tab name in dashboard." + }, "statsPageName":{ "message":"Statistics", "description":"appears as tab name in dashboard." @@ -139,6 +143,22 @@ "message":"Apply changes", "description":"English: Apply changes" }, + "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." + }, + "whitelistImport":{ + "message":"Import and append", + "description":"English: Import and append" + }, + "whitelistExport":{ + "message":"Export", + "description":"English: Export" + }, + "whitelistApply":{ + "message":"Apply changes", + "description":"English: Apply changes" + }, "logBlockedRequestsPrompt":{ "message":"Enable the logging of blocked requests", "description":"English: Enable the logging of blocked requests" diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index c4369bbd1..e0616816d 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -19,6 +19,10 @@ "message":"Vos règles", "description":"appears as tab name in dashboard." }, + "whitelistPageName":{ + "message":"Whitelist", + "description":"appears as tab name in dashboard." + }, "statsPageName":{ "message":"Statistiques", "description":"appears as tab name in dashboard." @@ -139,6 +143,22 @@ "message":"Appliquer", "description":"English: Apply changes" }, + "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." + }, + "whitelistImport":{ + "message":"Import and append", + "description":"English: Import and append" + }, + "whitelistExport":{ + "message":"Export", + "description":"English: Export" + }, + "whitelistApply":{ + "message":"Apply changes", + "description":"English: Apply changes" + }, "logBlockedRequestsPrompt":{ "message":"Activer la journalisation des requêtes bloquées", "description":"English: Enable the logging of blocked requests" diff --git a/dashboard.html b/dashboard.html index db2dba766..8df4fa1aa 100644 --- a/dashboard.html +++ b/dashboard.html @@ -83,6 +83,7 @@ iframe { µBlock + diff --git a/js/messaging-handlers.js b/js/messaging-handlers.js index d00b82864..64745fa00 100644 --- a/js/messaging-handlers.js +++ b/js/messaging-handlers.js @@ -301,6 +301,45 @@ var onMessage = function(request, sender, callback) { /******************************************************************************/ +// whitelist.js + +(function() { + +var onMessage = function(request, sender, callback) { + var µb = µBlock; + + // Async + switch ( request.what ) { + default: + break; + } + + // Sync + var response; + + switch ( request.what ) { + case 'getWhitelist': + response = µb.userSettings.netExceptionList; + break; + + case 'setWhitelist': + µb.userSettings.netExceptionList = request.whitelist; + µb.saveWhitelist(); + break; + + default: + return µb.messaging.defaultHandler(request, sender, callback); + } + + callback(response); +}; + +µBlock.messaging.listen('whitelist.js', onMessage); + +})(); + +/******************************************************************************/ + // stats.js (function() { diff --git a/js/storage.js b/js/storage.js index 6d99be233..95d449bb1 100644 --- a/js/storage.js +++ b/js/storage.js @@ -80,6 +80,15 @@ /******************************************************************************/ +µBlock.saveWhitelist = function() { + var bin = { 'netExceptionList': this.userSettings.netExceptionList }; + chrome.storage.local.set(bin, function() { + µBlock.getBytesInUse(); + }); +}; + +/******************************************************************************/ + µBlock.saveUserFilters = function(content, callback) { return this.assets.put(this.userFiltersPath, content, callback); }; diff --git a/js/whitelist.js b/js/whitelist.js new file mode 100644 index 000000000..58e34eba1 --- /dev/null +++ b/js/whitelist.js @@ -0,0 +1,162 @@ +/******************************************************************************* + + µBlock - 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/uBlock +*/ + +/* global chrome, messaging, uDom */ + +/******************************************************************************/ + +(function() { + +/******************************************************************************/ + +messaging.start('whitelist.js'); + +/******************************************************************************/ + +var cachedWhitelist = ''; + +// Could make it more fancy if needed. But speed... It's a compromise. +var reBadHostname = /[\x00-\x08\x0b\x0c\x0e-\x1f\x21-\x2c\x2f\x3a-\x40\x5b-\x60\x7b-\x7e]/; + +/******************************************************************************/ + +var validateHostname = function(s) { + var hn = punycode.toASCII(s).toLowerCase(); + if ( reBadHostname.test(hn) ) { + return ''; + } + return hn; +}; + +var whitelistFromString = function(s) { + var whitelist = {}; + var items = s.split(/\s+/); + var item; + for ( var i = 0; i < items.length; i++ ) { + item = validateHostname(items[i]); + if ( item !== '' ) { + whitelist[item] = true; + } + } + return whitelist; +}; + +var stringFromWhitelist = function(whitelist) { + var s = []; + var items = Object.keys(whitelist); + for ( var i = 0; i < items.length; i++ ) { + s.push(punycode.toUnicode(items[i])); + } + return s.sort(function(a, b) { return a.localeCompare(b); }).join('\n'); +}; + +/******************************************************************************/ + +var badWhitelist = function(s) { + return reBadHostname.test(s); +}; + +/******************************************************************************/ + +var whitelistChanged = function() { + var s = uDom('#whitelist').val().trim(); + uDom('#whitelistApply').prop( + 'disabled', + s === cachedWhitelist + ); + uDom('#whitelist').toggleClass('bad', badWhitelist(s)); +}; + +/******************************************************************************/ + +function renderWhitelist() { + var onRead = function(whitelist) { + cachedWhitelist = stringFromWhitelist(whitelist); + uDom('#whitelist').val(cachedWhitelist); + }; + messaging.ask({ what: 'getWhitelist' }, onRead); +}; + +/******************************************************************************/ + +var importWhitelistFromFile = function() { + var input = uDom('').attr({ + type: 'file', + accept: 'text/plain' + }); + var fileReaderOnLoadHandler = function() { + var textarea = uDom('#whitelist'); + textarea.val([textarea.val(), this.result].join('\n').trim()); + whitelistChanged(); + }; + var filePickerOnChangeHandler = function() { + input.off('change', filePickerOnChangeHandler); + var file = this.files[0]; + if ( !file ) { + return; + } + if ( file.type.indexOf('text') !== 0 ) { + return; + } + var fr = new FileReader(); + fr.onload = fileReaderOnLoadHandler; + fr.readAsText(file); + }; + input.on('change', filePickerOnChangeHandler); + input.trigger('click'); +}; + +/******************************************************************************/ + +var exportWhitelistToFile = function() { + chrome.downloads.download({ + 'url': 'data:text/plain,' + encodeURIComponent(uDom('#whitelist').val()), + 'filename': 'my-ublock-whitelist.txt', + 'saveAs': true + }); +}; + +/******************************************************************************/ + +var whitelistApplyHandler = function() { + cachedWhitelist = uDom('#whitelist').val().trim(); + var request = { + what: 'setWhitelist', + whitelist: whitelistFromString(cachedWhitelist) + }; + messaging.tell(request); + whitelistChanged(); +}; + +/******************************************************************************/ + +uDom.onLoad(function() { + uDom('#importWhitelistFromFile').on('click', importWhitelistFromFile); + uDom('#exportWhitelistToFile').on('click', exportWhitelistToFile); + uDom('#whitelist').on('input', whitelistChanged); + uDom('#whitelistApply').on('click', whitelistApplyHandler); + + renderWhitelist(); +}); + +/******************************************************************************/ + +})(); diff --git a/whitelist.html b/whitelist.html new file mode 100644 index 000000000..a48569107 --- /dev/null +++ b/whitelist.html @@ -0,0 +1,44 @@ + + + + +µBlock — Whitelist + + + + + + + +
+

+

+ +

+
+ + + + + + + + + +