| Index: lib/matcher.js |
| =================================================================== |
| --- a/lib/matcher.js |
| +++ b/lib/matcher.js |
| @@ -216,6 +216,8 @@ |
| { |
| this.blacklist = new Matcher(); |
| this.whitelist = new Matcher(); |
| + this.userBlacklist = new Matcher(); |
| + this.userWhitelist = new Matcher(); |
| this.resultCache = Object.create(null); |
| } |
| exports.CombinedMatcher = CombinedMatcher; |
| @@ -241,6 +243,18 @@ |
| whitelist: null, |
| /** |
| + * Matcher for user-defined blocking rules. |
| + * @type Matcher |
| + */ |
| + userBlacklist: null, |
| + |
| + /** |
| + * Matcher for user-defined exception rules. |
| + * @type Matcher |
| + */ |
| + userWhitelist: null, |
| + |
| + /** |
| * Lookup table of previous matchesAny results |
| * @type Object |
| */ |
| @@ -252,6 +266,24 @@ |
| */ |
| cacheEntries: 0, |
| + _getMatcher: function(filter) |
| + { |
| + if (filter.isUserDefined) |
| + { |
| + if (filter instanceof WhitelistFilter) |
| + return this.userWhitelist; |
| + else |
| + return this.userBlacklist; |
| + } |
| + else |
| + { |
| + if (filter instanceof WhitelistFilter) |
| + return this.whitelist; |
| + else |
| + return this.blacklist; |
| + } |
| + }, |
| + |
| /** |
| * @see Matcher#clear |
| */ |
| @@ -259,6 +291,8 @@ |
| { |
| this.blacklist.clear(); |
| this.whitelist.clear(); |
| + this.userBlacklist.clear(); |
| + this.userWhitelist.clear(); |
| this.resultCache = Object.create(null); |
| this.cacheEntries = 0; |
| }, |
| @@ -268,10 +302,7 @@ |
| */ |
| add: function(filter) |
| { |
| - if (filter instanceof WhitelistFilter) |
| - this.whitelist.add(filter); |
| - else |
| - this.blacklist.add(filter); |
| + this._getMatcher(filter).add(filter); |
| if (this.cacheEntries > 0) |
| { |
| @@ -285,10 +316,7 @@ |
| */ |
| remove: function(filter) |
| { |
| - if (filter instanceof WhitelistFilter) |
| - this.whitelist.remove(filter); |
| - else |
| - this.blacklist.remove(filter); |
| + this._getMatcher(filter).remove(filter); |
| if (this.cacheEntries > 0) |
| { |
| @@ -302,10 +330,7 @@ |
| */ |
| findKeyword: function(filter) |
| { |
| - if (filter instanceof WhitelistFilter) |
| - return this.whitelist.findKeyword(filter); |
| - else |
| - return this.blacklist.findKeyword(filter); |
| + return this._getMatcher(filter).findKeyword(filter); |
| }, |
| /** |
| @@ -313,10 +338,7 @@ |
| */ |
| hasFilter: function(filter) |
| { |
| - if (filter instanceof WhitelistFilter) |
| - return this.whitelist.hasFilter(filter); |
| - else |
| - return this.blacklist.hasFilter(filter); |
| + return this._getMatcher(filter).hasFilter(filter); |
| }, |
| /** |
| @@ -324,10 +346,7 @@ |
| */ |
| getKeywordForFilter: function(filter) |
| { |
| - if (filter instanceof WhitelistFilter) |
| - return this.whitelist.getKeywordForFilter(filter); |
| - else |
| - return this.blacklist.getKeywordForFilter(filter); |
| + return this._getMatcher(filter).getKeywordForFilter(filter); |
| }, |
| /** |
| @@ -335,7 +354,7 @@ |
| */ |
| isSlowFilter: function(/**RegExpFilter*/ filter) /**Boolean*/ |
| { |
| - let matcher = (filter instanceof WhitelistFilter ? this.whitelist : this.blacklist); |
| + let matcher = this._getMatcher(filter); |
| if (matcher.hasFilter(filter)) |
| return !matcher.getKeywordForFilter(filter); |
| else |
| @@ -344,28 +363,23 @@ |
| /** |
| * Optimized filter matching testing both whitelist and blacklist matchers |
| - * simultaneously. For parameters see Matcher.matchesAny(). |
| + * simultaneously. |
| * @see Matcher#matchesAny |
| */ |
| - matchesAnyInternal: function(location, contentType, docDomain, thirdParty, sitekey) |
| + matchesAnyInternal: function(blacklist, whitelist, candidates, location, contentType, docDomain, thirdParty, sitekey) |
| { |
| - let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); |
| - if (candidates === null) |
| - candidates = []; |
| - candidates.push(""); |
| - |
| let blacklistHit = null; |
| for (let i = 0, l = candidates.length; i < l; i++) |
| { |
| let substr = candidates[i]; |
| - if (substr in this.whitelist.filterByKeyword) |
| + if (substr in whitelist.filterByKeyword) |
| { |
| - let result = this.whitelist._checkEntryMatch(substr, location, contentType, docDomain, thirdParty, sitekey); |
| + let result = whitelist._checkEntryMatch(substr, location, contentType, docDomain, thirdParty, sitekey); |
| if (result) |
| return result; |
| } |
| - if (substr in this.blacklist.filterByKeyword && blacklistHit === null) |
| - blacklistHit = this.blacklist._checkEntryMatch(substr, location, contentType, docDomain, thirdParty, sitekey); |
| + if (substr in blacklist.filterByKeyword && blacklistHit === null) |
| + blacklistHit = blacklist._checkEntryMatch(substr, location, contentType, docDomain, thirdParty, sitekey); |
| } |
| return blacklistHit; |
| }, |
| @@ -379,7 +393,13 @@ |
| if (key in this.resultCache) |
| return this.resultCache[key]; |
| - let result = this.matchesAnyInternal(location, contentType, docDomain, thirdParty, sitekey); |
| + let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); |
| + if (candidates === null) |
| + candidates = []; |
| + candidates.push(""); |
| + |
| + let result = (this.matchesAnyInternal(this.userBlacklist, this.userWhitelist, candidates, location, contentType, docDomain, thirdParty, sitekey) || |
| + this.matchesAnyInternal(this.blacklist, this.whitelist, candidates, location, contentType, docDomain, thirdParty, sitekey)); |
| if (this.cacheEntries >= CombinedMatcher.maxCacheEntries) |
| { |