-
Notifications
You must be signed in to change notification settings - Fork 0
/
service-worker.js
96 lines (85 loc) · 3.74 KB
/
service-worker.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
/* eslint-disable import/extensions */
import SetupStorage from './config.js';
import CreateUserScript from './user-script.js';
/**
* Register or update our HTTP header modification rules.
*/
async function UpdateHeaderRules(config) {
const newRules = [];
// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest
[config.globalRules, ...config.siteRules].forEach((rule, index) => {
newRules.push({
id: index + 1,
priority: index > 0 ? 2 : 1,
action: {
type: 'modifyHeaders',
requestHeaders: [{
header: 'referer',
operation: rule.setReferrerValue ? 'set' : 'remove',
value: rule.setReferrerValue,
}],
},
condition: {
domainType: rule.domainType || config.globalRules.domainType,
requestMethods: rule.requestMethods || config.globalRules.requestMethods,
resourceTypes: rule.resourceTypes || config.globalRules.resourceTypes,
initiatorDomains: rule.initiatorDomains || null,
excludedRequestDomains: [
...config.globalRules.excludedRequestDomains,
...rule.excludedRequestDomains || [],
],
excludedInitiatorDomains: index > 0 ? rule.excludedInitiatorDomains : [ // skip if not globalRules
...config.globalRules.excludedInitiatorDomains,
// Ignore all site-specific initiator rules for globalRules
...config.siteRules.map((obj) => obj.initiatorDomains.reduce((domain) => domain)),
],
},
});
});
// Strip font origin header if enabled
// Font GET requests adds a origin header that is equal to referrer
if (config.globalRules.stripFontOrigin) {
const length = newRules.length + 1;
newRules.forEach((rule, index) => {
const copy = structuredClone(rule); // reuse user's referrer rules for same domain exceptions
copy.id = length + index;
copy.action.requestHeaders[0].header = 'origin';
copy.condition.resourceTypes = ['font']; // make sure we only run for fonts this time
newRules.push(copy);
});
}
const oldRules = await chrome.declarativeNetRequest.getDynamicRules();
return chrome.declarativeNetRequest.updateDynamicRules({
removeRuleIds: oldRules.map((rule) => rule.id),
addRules: newRules,
});
}
/**
* Register or update our user script that handles modifying the 'document.referrer' value.
*
* Unlike content script, a user script allows us to pass the current config object to the world JS code
* while still having the code ran at the 'document_start' event. (The chrome.scripting.executeScript() alternative is too slow)
*/
async function UpdateUserScript(config) {
const newScript = [{
id: 'referrer_privacy',
runAt: 'document_start',
world: 'MAIN',
matches: ['*://*/*'],
allFrames: false, // iframes will only show parent origin as referrer & is impossible to fully strip JS-wise anyways
js: [{ code: CreateUserScript(config) }],
excludeMatches: config.globalRules.excludedRequestDomains.map((domain) => `*://*.${domain}/*`),
}];
const oldScript = await chrome.userScripts.getScripts();
return chrome.userScripts[oldScript.length === 0 ? 'register' : 'update'](newScript);
}
/**
* Initialize the extension.
*/
chrome.runtime.onInstalled.addListener(async () => {
// try {
const config = await SetupStorage();
await UpdateHeaderRules(config);
await UpdateUserScript(config);
// catch (err) { console.log(err) };
});