From bee017034af4314c19ac0931034ee72ed4b5e59f Mon Sep 17 00:00:00 2001 From: gorhill Date: Sat, 2 Aug 2014 11:40:27 -0400 Subject: [PATCH] this fixes #5 --- js/abp-hide-filters.js | 10 +-- js/background.js | 5 +- js/contentscript-end.js | 23 +++--- js/messaging-handlers.js | 41 ++++++----- js/pagestore.js | 31 +++++---- js/popup.js | 7 +- js/storage.js | 21 +++++- js/tab.js | 32 ++++----- js/traffic.js | 6 +- js/ublock.js | 147 ++++++++++++++++++++++++++++++--------- js/whitelist.js | 51 ++------------ manifest.json | 2 +- 12 files changed, 223 insertions(+), 153 deletions(-) diff --git a/js/abp-hide-filters.js b/js/abp-hide-filters.js index dc5248a48..a25572cec 100644 --- a/js/abp-hide-filters.js +++ b/js/abp-hide-filters.js @@ -612,10 +612,7 @@ FilterContainer.prototype.addFilterEntry = function(filterDict, hash, f) { /******************************************************************************/ -FilterContainer.prototype.retrieveGenericSelectors = function(tabHostname, request) { - if ( !tabHostname || µb.getCosmeticFilteringSwitch(tabHostname) !== true ) { - return; - } +FilterContainer.prototype.retrieveGenericSelectors = function(request) { if ( µb.userSettings.parseAllABPHideFilters !== true ) { return; } @@ -670,10 +667,7 @@ FilterContainer.prototype.retrieveGenericSelectors = function(tabHostname, reque /******************************************************************************/ -FilterContainer.prototype.retrieveDomainSelectors = function(tabHostname, request) { - if ( !tabHostname || µb.getCosmeticFilteringSwitch(tabHostname) !== true ) { - return; - } +FilterContainer.prototype.retrieveDomainSelectors = function(request) { if ( µb.userSettings.parseAllABPHideFilters !== true ) { return; } diff --git a/js/background.js b/js/background.js index 5e9d45ffa..7c966fc0a 100644 --- a/js/background.js +++ b/js/background.js @@ -36,7 +36,8 @@ return { logBlockedRequests: false, logAllowedRequests: false, parseAllABPHideFilters: true, - netExceptionList: {}, + netExceptionList: {}, // TODO: remove once all users are up to date + netWhitelist: '', showIconBadge: true }, localSettings: { @@ -70,6 +71,8 @@ return { remoteBlacklists: { }, + netWhitelist: {}, + netWhitelistModifyTime: 0, pageStores: {}, storageQuota: chrome.storage.local.QUOTA_BYTES, diff --git a/js/contentscript-end.js b/js/contentscript-end.js index ed4d191e5..26eb0f707 100644 --- a/js/contentscript-end.js +++ b/js/contentscript-end.js @@ -420,6 +420,7 @@ var messaging = (function(name){ }); })(); +/******************************************************************************/ /******************************************************************************/ // https://github.com/gorhill/uBlock/issues/7 @@ -459,13 +460,19 @@ var messaging = (function(name){ // - Elements which resource URL changes var onResourceLoaded = function(ev) { var target = ev.target; - if ( !target || !target.src ) { - return; - } - var tag = target.tagName.toLowerCase(); - if ( tag !== 'img' && tag !== 'iframe' ) { - return; - } + if ( !target || !target.src ) { return; } + if ( target.tagName.toLowerCase() !== 'iframe' ) { return; } + var onAnswerReceived = function(details) { + if ( details.blocked ) { + hideOne(target, details.collapse); + } + }; + messaging.ask({ what: 'blockedRequest', url: target.src }, onAnswerReceived); + }; + var onResourceFailed = function(ev) { + var target = ev.target; + if ( !target || !target.src ) { return; } + if ( target.tagName.toLowerCase() !== 'img' ) { return; } var onAnswerReceived = function(details) { if ( details.blocked ) { hideOne(target, details.collapse); @@ -474,7 +481,7 @@ var messaging = (function(name){ messaging.ask({ what: 'blockedRequest', url: target.src }, onAnswerReceived); }; document.addEventListener('load', onResourceLoaded, true); - document.addEventListener('error', onResourceLoaded, true); + document.addEventListener('error', onResourceFailed, true); })(); /******************************************************************************/ diff --git a/js/messaging-handlers.js b/js/messaging-handlers.js index c7d02d2f5..c31efd151 100644 --- a/js/messaging-handlers.js +++ b/js/messaging-handlers.js @@ -19,7 +19,7 @@ Home: https://github.com/gorhill/uBlock */ -/* global chrome, µBlock */ +/* global chrome, µBlock, YaMD5 */ /******************************************************************************/ @@ -49,7 +49,7 @@ var getStats = function(request) { r.pageHostname = pageStore.pageHostname; r.pageBlockedRequestCount = pageStore.perLoadBlockedRequestCount; r.pageAllowedRequestCount = pageStore.perLoadAllowedRequestCount; - r.netFilteringSwitch = µb.getNetFilteringSwitch(pageStore.pageHostname); + r.netFilteringSwitch = pageStore.getNetFilteringSwitch(); } return r; }; @@ -73,7 +73,8 @@ var onMessage = function(request, sender, callback) { case 'toggleNetFiltering': µBlock.toggleNetFilteringSwitch( - request.hostname, + request.url, + request.scope, request.state ); µBlock.updateBadgeAsync(request.tabId); @@ -100,6 +101,8 @@ var onMessage = function(request, sender, callback) { (function() { +var µb = µBlock; + var onMessage = function(request, sender, callback) { // Async switch ( request.what ) { @@ -112,23 +115,24 @@ var onMessage = function(request, sender, callback) { var pageStore; if ( sender && sender.tab ) { - pageStore = µBlock.pageStoreFromTabId(sender.tab.id); + pageStore = µb.pageStoreFromTabId(sender.tab.id); } - var tabHostname = pageStore ? pageStore.pageHostname : ''; switch ( request.what ) { case 'retrieveDomainCosmeticSelectors': - response = µBlock.abpHideFilters.retrieveDomainSelectors(tabHostname, request); + if ( pageStore && pageStore.getNetFilteringSwitch() ) { + response = µb.abpHideFilters.retrieveDomainSelectors(request); + } break; default: - return µBlock.messaging.defaultHandler(request, sender, callback); + return µb.messaging.defaultHandler(request, sender, callback); } callback(response); }; -µBlock.messaging.listen('contentscript-start.js', onMessage); +µb.messaging.listen('contentscript-start.js', onMessage); })(); @@ -138,6 +142,8 @@ var onMessage = function(request, sender, callback) { (function() { +var µb = µBlock; + var onMessage = function(request, sender, callback) { // Async switch ( request.what ) { @@ -150,18 +156,19 @@ var onMessage = function(request, sender, callback) { var pageStore; if ( sender && sender.tab ) { - pageStore = µBlock.pageStoreFromTabId(sender.tab.id); + pageStore = µb.pageStoreFromTabId(sender.tab.id); } - var tabHostname = pageStore ? pageStore.pageHostname : ''; switch ( request.what ) { case 'retrieveGenericCosmeticSelectors': - response = µBlock.abpHideFilters.retrieveGenericSelectors(tabHostname, request); + if ( pageStore && pageStore.getNetFilteringSwitch() ) { + response = µb.abpHideFilters.retrieveGenericSelectors(request); + } break; case 'blockedRequests': response = { - collapse: µBlock.userSettings.collapseBlocked, + collapse: µb.userSettings.collapseBlocked, blockedRequests: pageStore ? pageStore.blockedRequests : {} }; break; @@ -169,19 +176,19 @@ var onMessage = function(request, sender, callback) { // Check a single request case 'blockedRequest': response = { - collapse: µBlock.userSettings.collapseBlocked, + collapse: µb.userSettings.collapseBlocked, blocked: pageStore && pageStore.blockedRequests[request.url] }; break; default: - return µBlock.messaging.defaultHandler(request, sender, callback); + return µb.messaging.defaultHandler(request, sender, callback); } callback(response); }; -µBlock.messaging.listen('contentscript-end.js', onMessage); +µb.messaging.listen('contentscript-end.js', onMessage); })(); @@ -352,11 +359,11 @@ var onMessage = function(request, sender, callback) { switch ( request.what ) { case 'getWhitelist': - response = µb.userSettings.netExceptionList; + response = µb.stringFromWhitelist(µb.netWhitelist); break; case 'setWhitelist': - µb.userSettings.netExceptionList = request.whitelist; + µb.netWhitelist = µb.whitelistFromString(request.whitelist); µb.saveWhitelist(); break; diff --git a/js/pagestore.js b/js/pagestore.js index 1d552001e..79f96f2bb 100644 --- a/js/pagestore.js +++ b/js/pagestore.js @@ -111,6 +111,8 @@ PageStore.prototype.init = function(tabId, pageURL) { this.pageHostname = µb.URI.hostnameFromURI(pageURL); this.pageDomain = µb.URI.domainFromHostname(this.pageHostname); this.frames = disposeFrameStores(this.frames); + this.netFiltering = true; + this.netFilteringReadTime = 0; this.perLoadBlockedRequestCount = 0; this.perLoadAllowedRequestCount = 0; this.blockedRequests = {}; @@ -122,16 +124,9 @@ PageStore.prototype.init = function(tabId, pageURL) { /******************************************************************************/ PageStore.prototype.reuse = function(pageURL) { - this.previousPageURL = this.pageURL; - this.pageURL = pageURL; - this.pageHostname = µb.URI.hostnameFromURI(pageURL); - this.pageDomain = µb.URI.domainFromHostname(this.pageHostname); - this.frames = disposeFrameStores(this.frames); - this.perLoadBlockedRequestCount = 0; - this.perLoadAllowedRequestCount = 0; - this.blockedRequests = {}; - this.allowedRequests = {}; - this.disposeTime = 0; + var previousPageURL = this.pageURL; + this.init(this.tabId, pageURL); + this.previousPageURL = previousPageURL; return this; }; @@ -169,6 +164,16 @@ PageStore.prototype.getFrame = function(frameId) { /******************************************************************************/ +PageStore.prototype.getNetFilteringSwitch = function() { + if ( this.netFilteringReadTime < µb.netWhitelistModifyTime ) { + this.netFiltering = µb.getNetFilteringSwitch(this.pageURL, this.pageDomain); + this.netFilteringReadTime = Date.now(); + } + return this.netFiltering; +}; + +/******************************************************************************/ + PageStore.prototype.recordRequest = function(type, url, reason) { var blocked = reason !== false && reason.slice(0, 2) !== '@@'; @@ -212,13 +217,13 @@ PageStore.prototype.updateBadge = function() { // https://github.com/gorhill/uBlock/issues/19 // TODO: need to check with µb object to see whether tab still exists. - var netFilteringSwitch = µb.getNetFilteringSwitch(this.pageHostname); - var iconPath = netFilteringSwitch ? 'img/browsericons/icon19.png' : 'img/browsericons/icon19-off.png'; + var netFiltering = this.getNetFilteringSwitch(); + var iconPath = netFiltering ? 'img/browsericons/icon19.png' : 'img/browsericons/icon19-off.png'; chrome.browserAction.setIcon({ tabId: this.tabId, path: iconPath }); var iconStr = ''; - if ( µb.userSettings.showIconBadge && netFilteringSwitch && this.perLoadBlockedRequestCount ) { + if ( µb.userSettings.showIconBadge && netFiltering && this.perLoadBlockedRequestCount ) { iconStr = this.perLoadBlockedRequestCount.toLocaleString(); } chrome.browserAction.setBadgeText({ diff --git a/js/popup.js b/js/popup.js index e028707d1..a98f9e6fa 100644 --- a/js/popup.js +++ b/js/popup.js @@ -134,14 +134,15 @@ chrome.tabs.query({ active: true, currentWindow: true }, onTabsReceived); /******************************************************************************/ -var handleNetFilteringSwitch = function() { +var toggleNetFilteringSwitch = function(ev) { if ( !stats || !stats.pageURL ) { return; } var off = uDom(this).toggleClass('off').hasClassName('off'); messaging.tell({ what: 'toggleNetFiltering', - hostname: stats.pageHostname, + url: stats.pageURL, + scope: ev.ctrlKey || ev.metaKey ? 'page' : '', state: !off, tabId: stats.tabId }); @@ -186,7 +187,7 @@ var renderHeader = function() { var installEventHandlers = function() { uDom('h1,h2,h3,h4').on('click', gotoDashboard); - uDom('#switch .fa').on('click', handleNetFilteringSwitch); + uDom('#switch .fa').on('click', toggleNetFilteringSwitch); uDom('#gotoLog').on('click', gotoStats); uDom('#gotoPick').on('click', gotoPick); }; diff --git a/js/storage.js b/js/storage.js index 6cb995cd9..1073d2c9c 100644 --- a/js/storage.js +++ b/js/storage.js @@ -72,7 +72,22 @@ µBlock.loadUserSettings = function() { var settingsLoaded = function(store) { - µBlock.userSettings = store; + var µb = µBlock; + // Backward compatibility after fix to #5 + // TODO: remove once all users are up to date with latest version. + if ( store.netExceptionList ) { + if ( store.netWhitelist === '' ) { + store.netWhitelist = Object.keys(store.netExceptionList).join('\n'); + if ( store.netWhitelist !== '' ) { + chrome.storage.local.set({ 'netWhitelist': store.netWhitelist }); + } + } + delete store.netExceptionList; + chrome.storage.local.remove('netExceptionList'); + } + µb.userSettings = store; + µb.netWhitelist = µb.whitelistFromString(store.netWhitelist); + µb.netWhitelistModifyTime = Date.now(); }; chrome.storage.local.get(this.userSettings, settingsLoaded); @@ -81,10 +96,12 @@ /******************************************************************************/ µBlock.saveWhitelist = function() { - var bin = { 'netExceptionList': this.userSettings.netExceptionList }; + this.userSettings.netWhitelist = this.stringFromWhitelist(this.netWhitelist); + var bin = { 'netWhitelist': this.userSettings.netWhitelist }; chrome.storage.local.set(bin, function() { µBlock.getBytesInUse(); }); + this.netWhitelistModifyTime = Date.now(); }; /******************************************************************************/ diff --git a/js/tab.js b/js/tab.js index b687b3d0e..b5972b585 100644 --- a/js/tab.js +++ b/js/tab.js @@ -26,13 +26,13 @@ (function(){ // When the DOM content of root frame is loaded, this means the tab // content has changed. - function onDOMContentLoaded(details) { + function onNavigationCommitted(details) { if ( details.frameId !== 0 ) { return; } - µBlock.updateBadgeAsync(details.tabId); + µBlock.bindTabToPageStats(details.tabId, details.url); } - chrome.webNavigation.onDOMContentLoaded.addListener(onDOMContentLoaded); + chrome.webNavigation.onCommitted.addListener(onNavigationCommitted); // It may happen the URL in the tab changes, while the page's document // stays the same (for instance, Google Maps). Without this listener, @@ -41,15 +41,10 @@ if ( !tab.url || tab.url === '' ) { return; } - var µb = µBlock; - if ( !changeInfo.url || !µb.pageStores[tabId] ) { + if ( !changeInfo.url ) { return; } - // If URL is unsupported scheme, unbind tab - if ( changeInfo.url && changeInfo.url.slice(0, 4) !== 'http' ) { - µb.unbindTabFromPageStats(tabId); - } - µb.updateBadgeAsync(tabId); + µBlock.bindTabToPageStats(tabId, changeInfo.url); } chrome.tabs.onUpdated.addListener(onTabUpdated); @@ -95,7 +90,7 @@ // Create an entry for the tab if it doesn't exist. -µBlock.bindTabToPageStats = function(tabId, pageURL) { +µBlock.bindTabToPageStats = function(tabId, pageURL, context) { this.updateBadgeAsync(tabId); // https://github.com/gorhill/httpswitchboard/issues/303 @@ -108,18 +103,17 @@ return null; } - //console.debug('µBlock> bindTabToPageStats(%d, "%s")', tabId, pageURL); - // Reuse page store if one exists: this allows to guess if a tab is // a popup. var pageStore = this.pageStores[tabId]; - if ( pageStore ) { - pageStore.reuse(pageURL); - } else { - pageStore = this.PageStore.factory(tabId, pageURL); - } - this.pageStores[tabId] = pageStore; + if ( pageStore ) { + if ( pageURL !== pageStore.pageURL || context === 'beforeRequest' ) { + pageStore.reuse(pageURL); + } + } else { + pageStore = this.pageStores[tabId] = this.PageStore.factory(tabId, pageURL); + } return pageStore; }; diff --git a/js/traffic.js b/js/traffic.js index a1d295bd1..06951abba 100644 --- a/js/traffic.js +++ b/js/traffic.js @@ -46,7 +46,7 @@ var onBeforeRequest = function(details) { // Special handling for root document. if ( requestType === 'main_frame' && details.parentFrameId === -1 ) { - µb.bindTabToPageStats(tabId, requestURL); + µb.bindTabToPageStats(tabId, requestURL, 'beforeRequest'); return; } @@ -79,7 +79,7 @@ var onBeforeRequest = function(details) { //} var reason = false; - if ( µb.getNetFilteringSwitch(pageStore.pageHostname) ) { + if ( pageStore.getNetFilteringSwitch() ) { reason = µb.abpFilters.matchString(requestContext, requestURL, requestType, requestHostname); } // Record what happened. @@ -167,7 +167,7 @@ var onBeforeSendHeaders = function(details) { // a page store from a URL. Have to keep in mind the same URL can appear // in multiple tabs. var reason = false; - if ( µb.getNetFilteringSwitch(pageStore.pageHostname) ) { + if ( pageStore.getNetFilteringSwitch() ) { reason = µb.abpFilters.matchStringExactType( pageDetails, requestURL, diff --git a/js/ublock.js b/js/ublock.js index 940c6c58f..169efbb97 100644 --- a/js/ublock.js +++ b/js/ublock.js @@ -19,18 +19,43 @@ Home: https://github.com/gorhill/uBlock */ -/* global chrome, µBlock */ +/* global µBlock */ /******************************************************************************/ -µBlock.getNetFilteringSwitch = function(hostname) { - var netExceptionList = this.userSettings.netExceptionList; - if ( netExceptionList[hostname] !== undefined ) { +µBlock.getNetFilteringSwitch = function(url, domain) { + var keyHostname = this.URI.hostnameFromURI(url); + var pos = url.indexOf('#'); + var keyURL = pos !== -1 ? url.slice(0, pos) : url; + + // The caller may provide an already known domain -- convenient to reduce + // overhead of extracting a domain from the url + if ( domain === undefined ) { + domain = this.URI.domainFromHostname(keyHostname); + } + if ( !domain ) { return false; } - var hostnames = this.URI.parentHostnamesFromHostname(hostname); - while ( hostname = hostnames.shift() ) { - if ( netExceptionList[hostname] !== undefined ) { + + var exceptions = this.netWhitelist[domain]; + if ( !exceptions ) { + return true; + } + + var i = exceptions.length; + var exception; + while ( i-- ) { + exception = exceptions[i]; + if ( exception.indexOf('/') !== -1 ) { + if ( exception.slice(-1) === '*' ) { + exception = exception.slice(0, -1); + if ( keyURL.slice(0, exception.length) === exception ) { + return false; + } + } else if ( keyURL === exception ) { + return false; + } + } else if ( keyHostname.slice(-exception.length) === exception ) { return false; } } @@ -39,58 +64,112 @@ /******************************************************************************/ -µBlock.toggleNetFilteringSwitch = function(hostname, newState) { - var currentState = this.getNetFilteringSwitch(hostname); +µBlock.toggleNetFilteringSwitch = function(url, scope, newState) { + var keyHostname = this.URI.hostnameFromURI(url); + var pos = url.indexOf('#'); + var keyURL = pos !== -1 ? url.slice(0, pos) : url; + var key = scope === 'page' ? keyURL : keyHostname; + + // The caller may provide an already known domain -- convenient to reduce + // overhead of extracting a domain from `key` + var domain = this.URI.domainFromHostname(keyHostname); + if ( !domain ) { + return false; + } + + var currentState = this.getNetFilteringSwitch(url, domain); if ( newState === undefined ) { newState = !currentState; } if ( newState === currentState ) { return currentState; } - var netExceptionList = this.userSettings.netExceptionList; + + var netWhitelist = this.netWhitelist; + var exceptions = netWhitelist[domain]; + if ( !exceptions ) { + exceptions = netWhitelist[domain] = []; + } // Add to exception list if ( !newState ) { - netExceptionList[hostname] = true; - this.saveExceptionList(); + exceptions.push(key); + this.saveWhitelist(); return true; } // Remove from exception list - var hostnames = this.URI.allHostnamesFromHostname(hostname); - while ( hostname = hostnames.shift() ) { - if ( netExceptionList[hostname] !== undefined ) { - delete netExceptionList[hostname]; + var i = exceptions.length; + var exception; + while ( i-- ) { + exception = exceptions[i]; + if ( exception.indexOf('/') !== -1 ) { + if ( exception.slice(-1) === '*' ) { + exception = exception.slice(0, -1); + if ( keyURL.slice(0, exception.length) === exception ) { + exceptions.splice(i, 1); + } + } else if ( keyURL === exception ) { + exceptions.splice(i, 1); + } + } else if ( keyHostname.slice(-exception.length) === exception ) { + exceptions.splice(i, 1); } } - this.saveExceptionList(); - return false; + if ( exceptions.length === 0 ) { + delete netWhitelist[domain]; + } + this.saveWhitelist(); + return true; }; /******************************************************************************/ // For now we will use the net exception list -µBlock.getCosmeticFilteringSwitch = function(hostname) { - var netExceptionList = this.userSettings.netExceptionList; - if ( netExceptionList[hostname] !== undefined ) { - return false; - } - var hostnames = this.URI.parentHostnamesFromHostname(hostname); - while ( hostname = hostnames.shift() ) { - if ( netExceptionList[hostname] !== undefined ) { - return false; - } - } - return true; +µBlock.getCosmeticFilteringSwitch = function(url, domain) { + return this.getNetFilteringSwitch(url, domain); }; /******************************************************************************/ -µBlock.saveExceptionList = function() { - chrome.storage.local.set({ - 'netExceptionList': this.userSettings.netExceptionList - }); +µBlock.stringFromWhitelist = function(exceptions) { + var r = {}; + var i, bucket; + for ( var domain in exceptions ) { + if ( exceptions.hasOwnProperty(domain) === false ) { + continue; + } + bucket = exceptions[domain]; + for ( i = 0; i < bucket.length; i++ ) { + r[bucket[i]] = true; + } + } + return Object.keys(r).sort(function(a,b){return a.localeCompare(b);}).join('\n'); +}; + +/******************************************************************************/ + +µBlock.whitelistFromString = function(s) { + var exceptions = {}; + var lines = s.split(/[\n\r]+/); + var line, domain, bucket; + for ( var i = 0; i < lines.length; i++ ) { + line = lines[i].trim(); + domain = line.indexOf('/') !== -1 ? + this.URI.domainFromURI(line) : + this.URI.domainFromHostname(line); + if ( !domain ) { + continue; + } + bucket = exceptions[domain]; + if ( bucket === undefined ) { + exceptions[domain] = [line]; + } else { + bucket.push(line); + } + } + return exceptions; }; /******************************************************************************/ diff --git a/js/whitelist.js b/js/whitelist.js index 58e34eba1..d100c2389 100644 --- a/js/whitelist.js +++ b/js/whitelist.js @@ -34,62 +34,25 @@ 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 reUnwantedChars = /[\x00-\x09\x0b\x0c\x0e-\x1f!"#$'()<>{}|\\^\[\]`~]/; /******************************************************************************/ var whitelistChanged = function() { var s = uDom('#whitelist').val().trim(); + var bad = reUnwantedChars.test(s); uDom('#whitelistApply').prop( 'disabled', - s === cachedWhitelist + s === cachedWhitelist || bad ); - uDom('#whitelist').toggleClass('bad', badWhitelist(s)); + uDom('#whitelist').toggleClass('bad', bad); }; /******************************************************************************/ -function renderWhitelist() { +var renderWhitelist = function() { var onRead = function(whitelist) { - cachedWhitelist = stringFromWhitelist(whitelist); + cachedWhitelist = whitelist; uDom('#whitelist').val(cachedWhitelist); }; messaging.ask({ what: 'getWhitelist' }, onRead); @@ -140,7 +103,7 @@ var whitelistApplyHandler = function() { cachedWhitelist = uDom('#whitelist').val().trim(); var request = { what: 'setWhitelist', - whitelist: whitelistFromString(cachedWhitelist) + whitelist: cachedWhitelist }; messaging.tell(request); whitelistChanged(); diff --git a/manifest.json b/manifest.json index 857f427d3..463e1125f 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "__MSG_extName__", "short_name": "µBlock", - "version": "0.3.1.3", + "version": "0.3.2.0", "description": "__MSG_extShortDesc__", "icons": { "16": "img/icon_16.png",