forked from mirrors/gecko-dev
		
	 3494ccd426
			
		
	
	
		3494ccd426
		
	
	
	
	
		
			
			This patch offers the Rule type and updateSessionRules and getSessionRules to register rules. The actual evaluation of rules and most of the associated validation is not part of this patch. Differential Revision: https://phabricator.services.mozilla.com/D154801
		
			
				
	
	
		
			116 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| // Each extension that uses DNR has one RuleManager. All registered RuleManagers
 | |
| // are checked whenever a network request occurs. Individual extensions may
 | |
| // occasionally modify their rules (e.g. via the updateSessionRules API).
 | |
| const gRuleManagers = [];
 | |
| 
 | |
| // The RuleCondition class represents a rule's "condition" type as described in
 | |
| // schemas/declarative_net_request.json. This class exists to allow the JS
 | |
| // engine to use one Shape for all Rule instances.
 | |
| class RuleCondition {
 | |
|   constructor(cond) {
 | |
|     this.urlFilter = cond.urlFilter;
 | |
|     this.regexFilter = cond.regexFilter;
 | |
|     this.isUrlFilterCaseSensitive = cond.isUrlFilterCaseSensitive;
 | |
|     this.initiatorDomains = cond.initiatorDomains;
 | |
|     this.excludedInitiatorDomains = cond.excludedInitiatorDomains;
 | |
|     this.requestDomains = cond.requestDomains;
 | |
|     this.excludedRequestDomains = cond.excludedRequestDomains;
 | |
|     this.resourceTypes = cond.resourceTypes;
 | |
|     this.excludedResourceTypes = cond.excludedResourceTypes;
 | |
|     this.requestMethods = cond.requestMethods;
 | |
|     this.excludedRequestMethods = cond.excludedRequestMethods;
 | |
|     this.domainType = cond.domainType;
 | |
|     this.tabIds = cond.tabIds;
 | |
|     this.excludedTabIds = cond.excludedTabIds;
 | |
|   }
 | |
| }
 | |
| 
 | |
| class Rule {
 | |
|   constructor(rule) {
 | |
|     this.id = rule.id;
 | |
|     this.priority = rule.priority;
 | |
|     this.condition = new RuleCondition(rule.condition);
 | |
|     this.action = rule.action;
 | |
|   }
 | |
| }
 | |
| 
 | |
| class RuleValidator {
 | |
|   constructor(alreadyValidatedRules) {
 | |
|     this.rulesMap = new Map(alreadyValidatedRules.map(r => [r.id, r]));
 | |
|     this.failures = [];
 | |
|   }
 | |
| 
 | |
|   removeRuleIds(ruleIds) {
 | |
|     for (const ruleId of ruleIds) {
 | |
|       this.rulesMap.delete(ruleId);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   addRules(rules) {
 | |
|     for (const rule of rules) {
 | |
|       if (this.rulesMap.has(rule.id)) {
 | |
|         this.#collectInvalidRule(rule, `Duplicate rule ID: ${rule.id}`);
 | |
|         continue;
 | |
|       }
 | |
|       const newRule = new Rule(rule);
 | |
| 
 | |
|       // TODO bug 1745758: Need more validation, before rules are evaluated.
 | |
| 
 | |
|       this.rulesMap.set(rule.id, newRule);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   #collectInvalidRule(rule, message) {
 | |
|     this.failures.push({ rule, message });
 | |
|   }
 | |
| 
 | |
|   getValidatedRules() {
 | |
|     return Array.from(this.rulesMap.values());
 | |
|   }
 | |
| 
 | |
|   getFailures() {
 | |
|     return this.failures;
 | |
|   }
 | |
| }
 | |
| 
 | |
| class RuleManager {
 | |
|   constructor(extension) {
 | |
|     this.extension = extension;
 | |
|     this.sessionRules = [];
 | |
|   }
 | |
| 
 | |
|   setSessionRules(validatedSessionRules) {
 | |
|     this.sessionRules = validatedSessionRules;
 | |
|   }
 | |
| 
 | |
|   getSessionRules() {
 | |
|     return this.sessionRules;
 | |
|   }
 | |
| }
 | |
| 
 | |
| function getRuleManager(extension, createIfMissing = true) {
 | |
|   let ruleManager = gRuleManagers.find(rm => rm.extension === extension);
 | |
|   if (!ruleManager && createIfMissing) {
 | |
|     ruleManager = new RuleManager(extension);
 | |
|     // TODO bug 1786059: order extensions by "installation time".
 | |
|     gRuleManagers.push(ruleManager);
 | |
|   }
 | |
|   return ruleManager;
 | |
| }
 | |
| 
 | |
| function clearRuleManager(extension) {
 | |
|   let i = gRuleManagers.findIndex(rm => rm.extension === extension);
 | |
|   if (i !== -1) {
 | |
|     gRuleManagers.splice(i, 1);
 | |
|   }
 | |
| }
 | |
| 
 | |
| export const ExtensionDNR = {
 | |
|   RuleValidator,
 | |
|   getRuleManager,
 | |
|   clearRuleManager,
 | |
| };
 |