Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: assets/js/Matcher.jsm

Issue 8482109: ABP/Android JavaScript code (Closed)
Patch Set: ABP/Android JavaScript code Created Nov. 12, 2012, 9:32 a.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: assets/js/Matcher.jsm
===================================================================
new file mode 100755
--- /dev/null
+++ b/assets/js/Matcher.jsm
@@ -0,0 +1,381 @@
+/*
+ * This Source Code is subject to the terms of the Mozilla Public License
+ * version 2.0 (the "License"). You can obtain a copy of the License at
+ * http://mozilla.org/MPL/2.0/.
+ */
+
+//
+// This file has been generated automatically from Adblock Plus source code
+//
+
+(function (_patchFunc0) {
+ function Matcher() {
+ this.clear();
+ }
+ Matcher.prototype = {
+ filterByKeyword: null,
+ keywordByFilter: null,
+ clear: function () {
+ this.filterByKeyword = {
+ __proto__: null
+ };
+ this.keywordByFilter = {
+ __proto__: null
+ };
+ }
+ ,
+ add: function (filter) {
+ if (filter.text in this.keywordByFilter)
+ return ;
+ var keyword = this.findKeyword(filter);
+ switch (typeof this.filterByKeyword[keyword]) {
+ case "undefined": {
+ this.filterByKeyword[keyword] = filter.text;
+ break;
+ }
+ case "string": {
+ this.filterByKeyword[keyword] = [this.filterByKeyword[keyword], filter.text];
+ break;
+ }
+ default: {
+ this.filterByKeyword[keyword].push(filter.text);
+ break;
+ }
+ }
+ this.keywordByFilter[filter.text] = keyword;
+ }
+ ,
+ remove: function (filter) {
+ if (!(filter.text in this.keywordByFilter))
+ return ;
+ var keyword = this.keywordByFilter[filter.text];
+ var list = this.filterByKeyword[keyword];
+ if (typeof list == "string")
+ delete this.filterByKeyword[keyword];
+ else {
+ var index = list.indexOf(filter.text);
+ if (index >= 0) {
+ list.splice(index, 1);
+ if (list.length == 1)
+ this.filterByKeyword[keyword] = list[0];
+ }
+ }
+ delete this.keywordByFilter[filter.text];
+ }
+ ,
+ findKeyword: function (filter) {
+ var defaultResult = (filter.contentType & RegExpFilter.typeMap.DONOTTRACK ? "donottrack" : "");
+ var text = filter.text;
+ if (Filter.regexpRegExp.test(text))
+ return defaultResult;
+ if (Filter.optionsRegExp.test(text))
+ text = RegExp.leftContext;
+ if (text.substr(0, 2) == "@@")
+ text = text.substr(2);
+ var candidates = text.toLowerCase().match(/[^a-z0-9%*][a-z0-9%]{3,}(?=[^a-z0-9%*])/g);
+ if (!candidates)
+ return defaultResult;
+ var hash = this.filterByKeyword;
+ var result = defaultResult;
+ var resultCount = 16777215;
+ var resultLength = 0;
+ for (var i = 0, l = candidates.length;
+ i < l; i++) {
+ var candidate = candidates[i].substr(1);
+ var count;
+ switch (typeof hash[candidate]) {
+ case "undefined": {
+ count = 0;
+ break;
+ }
+ case "string": {
+ count = 1;
+ break;
+ }
+ default: {
+ count = hash[candidate].length;
+ break;
+ }
+ }
+ if (count < resultCount || (count == resultCount && candidate.length > resultLength)) {
+ result = candidate;
+ resultCount = count;
+ resultLength = candidate.length;
+ }
+ }
+ return result;
+ }
+ ,
+ hasFilter: function (filter) {
+ return (filter.text in this.keywordByFilter);
+ }
+ ,
+ getKeywordForFilter: function (filter) {
+ if (filter.text in this.keywordByFilter)
+ return this.keywordByFilter[filter.text];
+ else
+ return null;
+ }
+ ,
+ _checkEntryMatch: function (keyword, location, contentType, docDomain, thirdParty) {
+ var list = this.filterByKeyword[keyword];
+ if (typeof list == "string") {
+ var filter = Filter.knownFilters[list];
+ if (!filter) {
+ delete this.filterByKeyword[keyword];
+ return null;
+ }
+ return (filter.matches(location, contentType, docDomain, thirdParty) ? filter : null);
+ }
+ else {
+ for (var i = 0;
+ i < list.length; i++) {
+ var filter = Filter.knownFilters[list[i]];
+ if (!filter) {
+ if (list.length == 1) {
+ delete this.filterByKeyword[keyword];
+ return null;
+ }
+ else {
+ list.splice(i--, 1);
+ continue;
+ }
+ }
+ if (filter.matches(location, contentType, docDomain, thirdParty))
+ return filter;
+ }
+ return null;
+ }
+ }
+ ,
+ matchesAny: function (location, contentType, docDomain, thirdParty) {
+ var candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g);
+ if (candidates === null)
+ candidates = [];
+ if (contentType == "DONOTTRACK")
+ candidates.unshift("donottrack");
+ else
+ candidates.push("");
+ for (var i = 0, l = candidates.length;
+ i < l; i++) {
+ var substr = candidates[i];
+ if (substr in this.filterByKeyword) {
+ var result = this._checkEntryMatch(substr, location, contentType, docDomain, thirdParty);
+ if (result)
+ return result;
+ }
+ }
+ return null;
+ }
+ ,
+ toCache: function (cache) {
+ cache.filterByKeyword = this.filterByKeyword;
+ }
+ ,
+ fromCache: function (cache) {
+ this.filterByKeyword = cache.filterByKeyword;
+ this.filterByKeyword.__proto__ = null;
+ delete this.keywordByFilter;
+ this.__defineGetter__("keywordByFilter", function () {
+ var result = {
+ __proto__: null
+ };
+ for (var k in this.filterByKeyword) {
+ var list = this.filterByKeyword[k];
+ if (typeof list == "string")
+ result[list] = k;
+ else
+ for (var i = 0, l = list.length;
+ i < l; i++)
+ result[list[i]] = k;
+ }
+ return this.keywordByFilter = result;
+ }
+ );
+ this.__defineSetter__("keywordByFilter", function (value) {
+ delete this.keywordByFilter;
+ return this.keywordByFilter = value;
+ }
+ );
+ }
+
+ };
+ function CombinedMatcher() {
+ this.blacklist = new Matcher();
+ this.whitelist = new Matcher();
+ this.keys = {
+ __proto__: null
+ };
+ this.resultCache = {
+ __proto__: null
+ };
+ }
+ CombinedMatcher.maxCacheEntries = 1000;
+ CombinedMatcher.prototype = {
+ blacklist: null,
+ whitelist: null,
+ keys: null,
+ resultCache: null,
+ cacheEntries: 0,
+ clear: function () {
+ this.blacklist.clear();
+ this.whitelist.clear();
+ this.keys = {
+ __proto__: null
+ };
+ this.resultCache = {
+ __proto__: null
+ };
+ this.cacheEntries = 0;
+ }
+ ,
+ add: function (filter) {
+ if (filter instanceof WhitelistFilter) {
+ if (filter.siteKeys) {
+ for (var i = 0;
+ i < filter.siteKeys.length; i++)
+ this.keys[filter.siteKeys[i]] = filter.text;
+ }
+ else
+ this.whitelist.add(filter);
+ }
+ else
+ this.blacklist.add(filter);
+ if (this.cacheEntries > 0) {
+ this.resultCache = {
+ __proto__: null
+ };
+ this.cacheEntries = 0;
+ }
+ }
+ ,
+ remove: function (filter) {
+ if (filter instanceof WhitelistFilter) {
+ if (filter.siteKeys) {
+ for (var i = 0;
+ i < filter.siteKeys.length; i++)
+ delete this.keys[filter.siteKeys[i]];
+ }
+ else
+ this.whitelist.remove(filter);
+ }
+ else
+ this.blacklist.remove(filter);
+ if (this.cacheEntries > 0) {
+ this.resultCache = {
+ __proto__: null
+ };
+ this.cacheEntries = 0;
+ }
+ }
+ ,
+ findKeyword: function (filter) {
+ if (filter instanceof WhitelistFilter)
+ return this.whitelist.findKeyword(filter);
+ else
+ return this.blacklist.findKeyword(filter);
+ }
+ ,
+ hasFilter: function (filter) {
+ if (filter instanceof WhitelistFilter)
+ return this.whitelist.hasFilter(filter);
+ else
+ return this.blacklist.hasFilter(filter);
+ }
+ ,
+ getKeywordForFilter: function (filter) {
+ if (filter instanceof WhitelistFilter)
+ return this.whitelist.getKeywordForFilter(filter);
+ else
+ return this.blacklist.getKeywordForFilter(filter);
+ }
+ ,
+ isSlowFilter: function (filter) {
+ var matcher = (filter instanceof WhitelistFilter ? this.whitelist : this.blacklist);
+ if (matcher.hasFilter(filter))
+ return !matcher.getKeywordForFilter(filter);
+ else
+ return !matcher.findKeyword(filter);
+ }
+ ,
+ matchesAnyInternal: function (location, contentType, docDomain, thirdParty) {
+ var candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g);
+ if (candidates === null)
+ candidates = [];
+ if (contentType == "DONOTTRACK")
+ candidates.unshift("donottrack");
+ else
+ candidates.push("");
+ var blacklistHit = null;
+ for (var i = 0, l = candidates.length;
+ i < l; i++) {
+ var substr = candidates[i];
+ if (substr in this.whitelist.filterByKeyword) {
+ var result = this.whitelist._checkEntryMatch(substr, location, contentType, docDomain, thirdParty);
+ if (result)
+ return result;
+ }
+ if (substr in this.blacklist.filterByKeyword && blacklistHit === null)
+ blacklistHit = this.blacklist._checkEntryMatch(substr, location, contentType, docDomain, thirdParty);
+ }
+ return blacklistHit;
+ }
+ ,
+ matchesAny: function (location, contentType, docDomain, thirdParty) {
+ var key = location + " " + contentType + " " + docDomain + " " + thirdParty;
+ if (key in this.resultCache)
+ return this.resultCache[key];
+ var result = this.matchesAnyInternal(location, contentType, docDomain, thirdParty);
+ if (this.cacheEntries >= CombinedMatcher.maxCacheEntries) {
+ this.resultCache = {
+ __proto__: null
+ };
+ this.cacheEntries = 0;
+ }
+ this.resultCache[key] = result;
+ this.cacheEntries++;
+ return result;
+ }
+ ,
+ matchesByKey: function (location, key, docDomain) {
+ key = key.toUpperCase();
+ if (key in this.keys) {
+ var filter = Filter.knownFilters[this.keys[key]];
+ if (filter && filter.matches(location, "DOCUMENT", docDomain, false))
+ return filter;
+ else
+ return null;
+ }
+ else
+ return null;
+ }
+ ,
+ toCache: function (cache) {
+ cache.matcher = {
+ whitelist: {
+
+ },
+ blacklist: {
+
+ },
+ keys: this.keys
+ };
+ this.whitelist.toCache(cache.matcher.whitelist);
+ this.blacklist.toCache(cache.matcher.blacklist);
+ }
+ ,
+ fromCache: function (cache) {
+ this.whitelist.fromCache(cache.matcher.whitelist);
+ this.blacklist.fromCache(cache.matcher.blacklist);
+ this.keys = cache.matcher.keys;
+ }
+
+ };
+ var defaultMatcher = new CombinedMatcher();
+ if (typeof _patchFunc0 != "undefined")
+ eval("(" + _patchFunc0.toString() + ")()");
+ window.Matcher = Matcher;
+ window.CombinedMatcher = CombinedMatcher;
+ window.defaultMatcher = defaultMatcher;
+}
+)(window.MatcherPatch);

Powered by Google App Engine
This is Rietveld