-
Notifications
You must be signed in to change notification settings - Fork 0
/
rules.js
108 lines (97 loc) · 2.84 KB
/
rules.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
export class Rule {
constructor(host, language) {
// "host" is legacy name, better be "expr"
// The true host name is `this.canonicalDomain`
this.host = host || '';
this.language = language || '';
}
get isUniversalWidlcard() {
return this.host === '*';
}
get isSubdomainWildcard() {
return this.host.startsWith('*.');
}
get canonicalDomain() {
if (this.isUniversalWidlcard) {
return null;
} else if (this.isSubdomainWildcard) {
return new URL(`http://${this.host.slice(2)}`).host;
} else {
return new URL(`http://${this.host}`).host;
}
}
get permissionOrigins() {
if (this.isUniversalWidlcard) {
return '*://*/*';
} else {
return `*://*.${this.canonicalDomain}/*`;
}
}
get regexFilter() {
if (this.isUniversalWidlcard) {
return "https?:\\/\\/.*";
}
const escapedHost = this.canonicalDomain.replace('.', '\\.');
if (this.isSubdomainWildcard) {
return `https?:\\/\\/([^\\/]+\\.)?${escapedHost}(:\\d+)?\\/.*`;
} else {
return `https?:\\/\\/${escapedHost}(:\\d+)?\\/.*`;
}
}
get rule() {
let priority = this.host.split(".").length;
if (!this.isUniversalWidlcard && !this.isSubdomainWildcard) {
// Let `example.com` precedent `*.example.com`
priority += 1;
}
console.debug(`Rule P${priority} ${this.language} [${this.host}] /${this.regexFilter}/`)
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/declarativeNetRequest#rules
return {
id: Math.floor(Math.random() * Number.MAX_SAFE_INTEGER),
action: {
type: "modifyHeaders",
requestHeaders: [
{
header: "Accept-Language",
operation: "set",
value: this.language,
}
]
},
condition: {
excludedResourceTypes: [],
regexFilter: this.regexFilter
},
priority
};
}
get formHTML() {
let template = document.querySelector("#rule");
let content = document.importNode(template, true).content;
content.querySelector(".host").value = this.host;
content.querySelector(".language").value = this.language;
return content;
}
}
export class RuleSet {
constructor(rules) {
this.rules = rules;
}
async registerAll() {
const oldRules = await browser.declarativeNetRequest.getDynamicRules();
await browser.declarativeNetRequest.updateDynamicRules({
removeRuleIds: oldRules.map((r) => r.id),
addRules: this.rules.map((r) => r.rule),
});
console.debug(`Remove ${oldRules.length}; add ${this.rules.length} rules`);
}
}
export async function getRules() {
let opts = await browser.storage.local.get("rules");
if (opts.rules)
return opts.rules
.filter(v => v.host && v.language)
.map(v => new Rule(v.host, v.language));
else
return [];
}