diff --git a/chromium/background-scripts/background.js b/chromium/background-scripts/background.js index f0b9ba36cdcf..25ac4e4e279d 100644 --- a/chromium/background-scripts/background.js +++ b/chromium/background-scripts/background.js @@ -887,6 +887,10 @@ chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){ chrome.tabs.reload(); }); }, + get_user_rules: () => { + store.get_promise(all_rules.USER_RULE_KEY, []).then(userRules => sendResponse(userRules)); + return true; + }, add_new_rule: () => { all_rules.addNewRuleAndStore(message.object).then(() => { sendResponse(true); @@ -894,7 +898,23 @@ chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){ return true; }, remove_rule: () => { - all_rules.removeRuleAndStore(message.object); + all_rules.removeRuleAndStore(message.object.ruleset, message.object.src) + .then(() => { + /** + * FIXME: initializeAllRules is needed for calls from the option pages. + * Since message.object is not of type Ruleset, rules.removeUserRule + * is not usable... + */ + if (message.object.src === 'options') { + return initializeAllRules(); + } + }) + .then(() => { + if (sendResponse !== null) { + sendResponse(true); + } + }) + return true; }, get_ruleset_timestamps: () => { update.getRulesetTimestamps().then(timestamps => sendResponse(timestamps)); diff --git a/chromium/background-scripts/rules.js b/chromium/background-scripts/rules.js index 5eba395ae6c3..6b42cc6885a5 100644 --- a/chromium/background-scripts/rules.js +++ b/chromium/background-scripts/rules.js @@ -221,7 +221,7 @@ RuleSets.prototype = { this.store = store; this.ruleActiveStates = await this.store.get_promise('ruleActiveStates', {}); await applyStoredFunc(this); - this.loadStoredUserRules(); + await this.loadStoredUserRules(); await this.addStoredCustomRulesets(); }, @@ -257,6 +257,9 @@ RuleSets.prototype = { var default_off = ruletag["default_off"]; if (default_off) { default_state = false; + if (default_off === "user rule") { + default_state = true; + } note += default_off + "\n"; } @@ -320,18 +323,14 @@ RuleSets.prototype = { */ 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, scope, "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; }, @@ -341,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; }, @@ -369,13 +381,12 @@ RuleSets.prototype = { /** * Load all stored user rules into this RuleSet object */ - loadStoredUserRules: async function() { - const scope = getScope(); - const user_rules = await this.getStoredUserRules(); - for (let user_rule of user_rules) { - this.addUserRule(user_rule, scope); - } - 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`); + }); }, /** @@ -401,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); } }, @@ -456,6 +474,9 @@ RuleSets.prototype = { 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"; } diff --git a/chromium/background-scripts/store.js b/chromium/background-scripts/store.js index 3b555c7311d5..c41ccd0a5cc2 100644 --- a/chromium/background-scripts/store.js +++ b/chromium/background-scripts/store.js @@ -51,29 +51,51 @@ function local_set_promise(key, value) { async function performMigrations() { - const migration_version = await get_promise('migration_version', 0); - - if (migration_version < 1) { - - let ls; - try { - ls = localStorage; - } catch(e) {} - - let ruleActiveStates = {}; - for (const key in ls) { - if (ls.hasOwnProperty(key)) { - if (key == rules.RuleSets().USER_RULE_KEY){ - await set_promise(rules.RuleSets().USER_RULE_KEY, JSON.parse(ls[key])); - } else { - ruleActiveStates[key] = (ls[key] == "true"); + let migration_version = await get_promise('migration_version', 0); + + try { + if (migration_version === 0) { + let ls = localStorage; + let ruleActiveStates = {}; + + for (let key in ls) { + if (ls.hasOwnProperty(key)) { + if (rules.RuleSets().USER_RULE_KEY === key) { + await set_promise(rules.RuleSets().USER_RULE_KEY, JSON.parse(ls[key])); + } else { + ruleActiveStates[key] = (ls[key] === "true"); + } } } + migration_version = 1; + await set_promise('migration_version', migration_version); + await set_promise('ruleActiveStates', ruleActiveStates); } - await set_promise('ruleActiveStates', ruleActiveStates); + + } catch (e) { + // do nothing } - await set_promise('migration_version', 1); + if (migration_version <= 1) { + await get_promise(rules.RuleSets().USER_RULE_KEY, []) + .then(userRules => { + userRules = userRules.map(userRule => { + return { + name: userRule.host, + target: [userRule.host], + rule: [{ from: userRule.urlMatcher, to: userRule.redirectTo }], + default_off: "user rule" + } + }) + return userRules; + }) + .then(userRules => { + return set_promise(rules.RuleSets().USER_RULE_KEY, userRules); + }) + + migration_version = 2; + await set_promise('migration_version', migration_version); + } } const local = { diff --git a/chromium/pages/options/index.html b/chromium/pages/options/index.html index aee189319074..f351d1773c45 100644 --- a/chromium/pages/options/index.html +++ b/chromium/pages/options/index.html @@ -19,6 +19,9 @@ +