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

Unified Diff: lib/matcher.js

Issue 8790183: Added handling of whitelisting rules like @@||example.com^$document (Closed)
Patch Set: Created Nov. 14, 2012, 1:46 p.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
« no previous file with comments | « background.js ('k') | options.html » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/matcher.js
===================================================================
--- a/lib/matcher.js
+++ b/lib/matcher.js
@@ -25,25 +25,33 @@
// Make sure that filters don't apply to extension pages. We shouldn't allow
// users to break our options page unintentionally, recovering is very hard
// if they do.
opera.extension.urlfilter.allow.add("widget://*");
var WhitelistFilter = null;
var RegExpFilter = null;
var resourceTypes = [
- "DOCUMENT", "FONT", "IMAGE", "MEDIA", "OBJECT", "OBJECT_SUBREQUEST",
+ "FONT", "IMAGE", "MEDIA", "OBJECT", "OBJECT_SUBREQUEST",
"OTHER", "SCRIPT", "STYLESHEET", "SUBDOCUMENT", "XMLHTTPREQUEST"
];
require.scopes.matcher =
{
+ init: function()
+ {
+ WhitelistFilter = require("filterClasses").WhitelistFilter;
+ RegExpFilter = require("filterClasses").RegExpFilter;
+ },
+
defaultMatcher:
{
_rules: {},
+ _domainExceptions: {},
+ _domainExceptionsTimeout: null,
/**
* 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*/
{
@@ -134,61 +142,116 @@
* 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;
},
+ /**
+ * Checks whether the filter is a domain exception and adds/removes it
+ * according to the add parameter. Returns true if a domain exception
+ * has been processed, false otherwise.
+ */
+ _processDomainException: function(/**Filter*/ filter, /**Boolean*/ add) /**Boolean*/
+ {
+ if (!(filter instanceof WhitelistFilter) ||
+ filter.contentType != RegExpFilter.typeMap.DOCUMENT ||
+ filter.domainSource)
+ {
+ return false;
+ }
+
+ var match = /^\|\|([^\/]+)\^$/.exec(filter.regexpSource);
+ if (!match)
+ return false;
+
+ var domain = match[1];
+ if (add)
+ this._domainExceptions[domain] = true;
+ else
+ delete this._domainExceptions[domain];
+
+ this._updateDomainExceptions();
+ return true;
+ },
+
+ /**
+ * Updates domain exceptions rule, execution happens delayed to prevent
+ * multiple subsequent updates.
+ */
+ _updateDomainExceptions: function()
+ {
+ if (this._domainExceptionsTimeout)
+ window.clearTimeout(this._domainExceptionsTimeout);
+
+ this._domainExceptionsTimeout = window.setTimeout(function()
+ {
+ this._domainExceptionsTimeout = null;
+ opera.extension.urlfilter.allow.remove("*:*");
+
+ var domains = Object.keys(this._domainExceptions);
+ if (domains.length)
+ {
+ opera.extension.urlfilter.allow.add("*:*", {
+ includeDomains: domains
+ });
+ }
+ }.bind(this), 0);
+ },
+
add: function(filter)
{
+ if (this._processDomainException(filter, true))
+ return;
+
if (filter.text in this._rules)
return;
if (!filter.regexpSource) // Regular expressions aren't supported
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 (this._processDomainException(filter, false))
+ return;
+
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 = {};
+
+ this._domainExceptions = {};
+ this._updateDomainExceptions();
}
}
};
})();
« no previous file with comments | « background.js ('k') | options.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld