Index: lib/matcher.js |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/lib/matcher.js |
@@ -0,0 +1,175 @@ |
+/* |
+ * 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 mimicks the API of the Matcher module in ABP/Firefox but users Opera's |
+// URLFilter API. |
+// |
+ |
+(function() |
+{ |
+ var WhitelistFilter = null; |
+ var RegExpFilter = null; |
+ var resourceTypes = [ |
+ "DOCUMENT", "FONT", "IMAGE", "MEDIA", "OBJECT", "OBJECT_SUBREQUEST", |
+ "OTHER", "SCRIPT", "STYLESHEET", "SUBDOCUMENT", "XMLHTTPREQUEST" |
+ ]; |
+ |
+ require.scopes.matcher = |
+ { |
+ defaultMatcher: |
+ { |
+ _rules: {}, |
+ |
+ /** |
+ * Converts rule text from Adblock Plus format (implicit * at beginning |
+ * and end of the rule unless there is an anchor) to Opera format (* has |
+ * to be specified explicitly). |
+ */ |
+ _getRuleText: function(/**Filter*/ filter) /**String*/ |
+ { |
+ var text = filter.regexpSource; |
+ |
+ // |foo => foo |
+ // foo => *foo |
+ // *foo and ||foo stay unchanged |
+ if (text.substr(0, 2) != "||") |
+ { |
+ var start = text.substr(0, 1); |
+ if (start == "|") |
+ text = text.slice(1); |
+ else if (start != "*") |
+ text = "*" + text; |
+ } |
+ |
+ // foo| => foo |
+ // foo => foo* |
+ // foo* stays unchanged |
+ var end = text.substr(-1); |
+ if (end == "|") |
+ text = text.slice(0, -1); |
+ else if (end != "*") |
+ text = text + "*"; |
+ |
+ return text; |
+ }, |
+ |
+ /** |
+ * Converts type options of a filter into a bit mask as expected by Opera. |
+ */ |
+ _getRuleTypes: function(/**Filter*/ filter) /**Integer*/ |
+ { |
+ var types = 0; |
+ var urlfilter = opera.extension.urlfilter; |
+ for (var i = 0; i < resourceTypes.length; i++) |
+ { |
+ var type = resourceTypes[i]; |
+ if (filter.contentType & RegExpFilter.typeMap[type]) |
+ types |= urlfilter["RESOURCE_" + type]; |
+ } |
+ return types; |
+ }, |
+ |
+ /** |
+ * Converts domain options of a filter into includeDomains/excludeDomains |
+ * options as expected by Opera. The options object has to be passed in, |
+ * properties will be added to it if necessary. |
+ */ |
+ _getRuleDomains: function(/**Filter*/ filter, /**Object*/ options) |
+ { |
+ if (filter.domainSource) |
+ { |
+ var domains = filter.domainSource.split(filter.domainSeparator); |
+ for (var i = 0; i < domains.length; i++) |
+ { |
+ var domain = domains[i]; |
+ if (domain == "") |
+ continue; |
+ |
+ var type = "includeDomains"; |
+ if (domain[0] == "~") |
+ { |
+ type = "excludeDomains"; |
+ domain = domain.substr(1); |
+ } |
+ if (!(type in options)) |
+ options[type] = []; |
+ options[type].push(domain); |
+ } |
+ } |
+ }, |
+ |
+ /** |
+ * Converts third-party filter option to the format expected by Opera. |
+ * The options object has to be passed in, a property will be added to it |
+ * if necessary. |
+ */ |
+ _getRuleThirdParty: function(/**Filter*/ filter, /**Object*/ options) |
+ { |
+ if (filter.thirdParty !== null) |
+ options.thirdParty = filter.thirdParty; |
+ }, |
+ |
+ /** |
+ * Converts an Adblock Plus filter to a rule that can be processed by |
+ * Opera. The following options will be set: |
+ * |
+ * type: urlfilter to be used, either "allow" or "block" |
+ * text: rule text |
+ * options: rule options |
+ */ |
+ _generateRule: function(/**Filter*/ filter) /**Object*/ |
+ { |
+ if (!WhitelistFilter) |
+ { |
+ WhitelistFilter = require("filterClasses").WhitelistFilter; |
+ RegExpFilter = require("filterClasses").RegExpFilter; |
+ } |
+ |
+ var rule = { |
+ type: filter instanceof WhitelistFilter ? "allow" : "block", |
+ text: this._getRuleText(filter), |
+ options: { |
+ resources: this._getRuleTypes(filter) |
+ } |
+ }; |
+ this._getRuleDomains(filter, rule.options); |
+ this._getRuleThirdParty(filter, rule.options); |
+ return rule; |
+ }, |
+ |
+ add: function(filter) |
+ { |
+ if (filter.text in this._rules) |
+ return; |
+ |
+ var rule = this._generateRule(filter); |
+ opera.extension.urlfilter[rule.type].add(rule.text, rule.options); |
+ this._rules[filter.text] = rule; |
+ }, |
+ |
+ remove: function(filter) |
+ { |
+ if (!(filter.text in this._rules)) |
+ return; |
+ |
+ var rule = this._rules[filter.text]; |
+ opera.extension.urlfilter[rule.type].remove(rule.text); |
+ delete this._rules[filter.text]; |
+ }, |
+ |
+ clear: function() |
+ { |
+ for (var text in this._rules) |
+ { |
+ var rule = this._rules[text]; |
+ opera.extension.urlfilter[rule.type].remove(rule.text); |
+ } |
+ this._rules = {}; |
+ } |
+ } |
+ }; |
+})(); |