diff options
Diffstat (limited to 'data/extensions/https-everywhere@eff.org/background-scripts/rules.js')
-rw-r--r-- | data/extensions/https-everywhere@eff.org/background-scripts/rules.js | 125 |
1 files changed, 81 insertions, 44 deletions
diff --git a/data/extensions/https-everywhere@eff.org/background-scripts/rules.js b/data/extensions/https-everywhere@eff.org/background-scripts/rules.js index e2dac94..6b42cc6 100644 --- a/data/extensions/https-everywhere@eff.org/background-scripts/rules.js +++ b/data/extensions/https-everywhere@eff.org/background-scripts/rules.js @@ -25,6 +25,17 @@ const nullIterable = Object.create(null, { }, }); +/* A map of all scope RegExp objects */ +const scopes = new Map(); + +/* Returns the scope object from the map for the given scope string */ +function getScope(scope){ + if (!scopes.has(scope)) { + scopes.set(scope, new RegExp(scope)); + } + return scopes.get(scope); +} + /** * Constructs a single rule * @param from @@ -81,13 +92,14 @@ function CookieRule(host, cookiename) { * @param note Note will be displayed in popup * @constructor */ -function RuleSet(set_name, default_state, note) { +function RuleSet(set_name, default_state, scope, note) { this.name = set_name; this.rules = []; this.exclusions = null; this.cookierules = null; this.active = default_state; this.default_state = default_state; + this.scope = scope; this.note = note; } @@ -209,40 +221,45 @@ RuleSets.prototype = { this.store = store; this.ruleActiveStates = await this.store.get_promise('ruleActiveStates', {}); await applyStoredFunc(this); - this.loadStoredUserRules(); + await this.loadStoredUserRules(); await this.addStoredCustomRulesets(); }, /** * Iterate through data XML and load rulesets */ - addFromXml: function(ruleXml) { - var sets = ruleXml.getElementsByTagName("ruleset"); - for (let s of sets) { + addFromXml: function(ruleXml, scope) { + const scope_obj = getScope(scope); + const rulesets = ruleXml.getElementsByTagName("ruleset"); + for (let ruleset of rulesets) { try { - this.parseOneXmlRuleset(s); + this.parseOneXmlRuleset(ruleset, scope_obj); } catch (e) { util.log(util.WARN, 'Error processing ruleset:' + e); } } }, - addFromJson: function(ruleJson) { + addFromJson: function(ruleJson, scope) { + const scope_obj = getScope(scope); for (let ruleset of ruleJson) { try { - this.parseOneJsonRuleset(ruleset); + this.parseOneJsonRuleset(ruleset, scope_obj); } catch(e) { util.log(util.WARN, 'Error processing ruleset:' + e); } } }, - parseOneJsonRuleset: function(ruletag) { + parseOneJsonRuleset: function(ruletag, scope) { var default_state = true; var note = ""; var default_off = ruletag["default_off"]; if (default_off) { default_state = false; + if (default_off === "user rule") { + default_state = true; + } note += default_off + "\n"; } @@ -257,7 +274,7 @@ RuleSets.prototype = { note += "Platform(s): " + platform + "\n"; } - var rule_set = new RuleSet(ruletag["name"], default_state, note.trim()); + var rule_set = new RuleSet(ruletag["name"], default_state, scope, note.trim()); // Read user prefs if (rule_set.name in this.ruleActiveStates) { @@ -304,20 +321,16 @@ RuleSets.prototype = { * @param params * @returns {boolean} */ - addUserRule : function(params) { + addUserRule : function(params, scope) { util.log(util.INFO, 'adding new user rule for ' + JSON.stringify(params)); - var new_rule_set = new RuleSet(params.host, true, "user rule"); - var new_rule = getRule(params.urlMatcher, params.redirectTo); - new_rule_set.rules.push(new_rule); - if (!this.targets.has(params.host)) { - this.targets.set(params.host, []); + this.parseOneJsonRuleset(params, scope); + + // clear cache so new rule take effect immediately + for (const target of params.target) { + this.ruleCache.delete(target); } - this.ruleCache.delete(params.host); + // TODO: maybe promote this rule? - this.targets.get(params.host).push(new_rule_set); - if (new_rule_set.name in this.ruleActiveStates) { - new_rule_set.active = this.ruleActiveStates[new_rule_set.name]; - } util.log(util.INFO, 'done adding rule'); return true; }, @@ -327,20 +340,33 @@ RuleSets.prototype = { * @param params * @returns {boolean} */ - removeUserRule: function(ruleset) { + removeUserRule: function(ruleset, src) { + /** + * FIXME: We have to use ruleset.name here because the ruleset itself + * carries no information on the target it is applying on. This also + * made it impossible for users to set custom ruleset name. + */ util.log(util.INFO, 'removing user rule for ' + JSON.stringify(ruleset)); - this.ruleCache.delete(ruleset.name); + // Remove any cache from runtime + this.ruleCache.delete(ruleset.name); - var tmp = this.targets.get(ruleset.name).filter(r => - !(r.isEquivalentTo(ruleset)) - ); - this.targets.set(ruleset.name, tmp); + if (src === 'popup') { + const tmp = this.targets.get(ruleset.name).filter(r => !r.isEquivalentTo(ruleset)) + this.targets.set(ruleset.name, tmp); - if (this.targets.get(ruleset.name).length == 0) { - this.targets.delete(ruleset.name); + if (this.targets.get(ruleset.name).length == 0) { + this.targets.delete(ruleset.name); + } } + if (src === 'options') { + /** + * FIXME: There is nothing we can do if the call comes from the + * option page because isEquivalentTo cannot work reliably. + * Leave the heavy duties to background.js to call initializeAllRules + */ + } util.log(util.INFO, 'done removing rule'); return true; }, @@ -355,12 +381,12 @@ RuleSets.prototype = { /** * Load all stored user rules into this RuleSet object */ - loadStoredUserRules: async function() { - const user_rules = await this.getStoredUserRules(); - for (let user_rule of user_rules) { - this.addUserRule(user_rule); - } - util.log(util.INFO, 'loaded ' + user_rules.length + ' stored user rules'); + loadStoredUserRules: function() { + return this.getStoredUserRules() + .then(userRules => { + this.addFromJson(userRules, getScope()); + util.log(util.INFO, `loaded ${userRules.length} stored user rules`); + }); }, /** @@ -369,7 +395,7 @@ RuleSets.prototype = { * @param cb: Callback to call after success/fail * */ addNewRuleAndStore: async function(params) { - if (this.addUserRule(params)) { + if (this.addUserRule(params, getScope())) { // If we successfully added the user rule, save it in the storage // api so it's automatically applied when the extension is // reloaded. @@ -386,14 +412,21 @@ RuleSets.prototype = { * Removes a user rule * @param ruleset: the ruleset to remove * */ - removeRuleAndStore: async function(ruleset) { - if (this.removeUserRule(ruleset)) { - // If we successfully removed the user rule, remove it in local storage too + removeRuleAndStore: async function(ruleset, src) { + if (this.removeUserRule(ruleset, src)) { let userRules = await this.getStoredUserRules(); - userRules = userRules.filter(r => - !(r.host == ruleset.name && - r.redirectTo == ruleset.rules[0].to) - ); + + if (src === 'popup') { + userRules = userRules.filter(r => + !(r.name === ruleset.name && r.rule[0].to === ruleset.rules[0].to) + ); + } + + if (src === 'options') { + userRules = userRules.filter(r => + !(r.name === ruleset.name && r.rule[0].to === ruleset.rule[0].to) + ); + } await this.store.set_promise(this.USER_RULE_KEY, userRules); } }, @@ -435,12 +468,15 @@ RuleSets.prototype = { * Does the loading of a ruleset. * @param ruletag The whole <ruleset> tag to parse */ - parseOneXmlRuleset: function(ruletag) { + parseOneXmlRuleset: function(ruletag, scope) { var default_state = true; var note = ""; var default_off = ruletag.getAttribute("default_off"); if (default_off) { default_state = false; + if (default_off === "user rule") { + default_state = true; + } note += default_off + "\n"; } @@ -457,6 +493,7 @@ RuleSets.prototype = { var rule_set = new RuleSet(ruletag.getAttribute("name"), default_state, + scope, note.trim()); // Read user prefs |