Skip to content

Commit ff66ba3

Browse files
authored
Merge pull request #1101 from NotAProton/tracker-block
Mv3: Add tracker bypass and IP logger blocking
2 parents 4af0cb9 + 02571be commit ff66ba3

File tree

18 files changed

+628
-362
lines changed

18 files changed

+628
-362
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
},
1111
"scripts": {
1212
"lint": "eslint",
13-
"build": "./scripts/build.js"
13+
"build": "node ./scripts/build.js"
1414
}
15-
}
15+
}

platform_spec/chromium/manifest.json

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,19 @@
1818
"alarms",
1919
"storage",
2020
"webNavigation",
21-
"tabs"
21+
"tabs",
22+
"declarativeNetRequestWithHostAccess"
2223
],
24+
"host_permissions": [
25+
"<all_urls>"
26+
],
2327
"options_ui": {
2428
"page": "html/options.html",
2529
"open_in_tab": true
2630
},
2731
"background": {
28-
"service_worker": "background.js"
32+
"service_worker": "background.js",
33+
"type": "module"
2934
},
3035
"action": {
3136
"default_popup": "html/popup.html"
@@ -46,11 +51,25 @@
4651
"html/before-navigate.html",
4752
"html/blocked.html",
4853
"html/crowd-bypassed.html",
54+
"html/tracker-bypass.html",
4955
"html/options.html",
5056
"icon/48.png",
5157
"injection_script.js",
5258
"bypasses/*",
5359
"helpers/*"],
5460
"matches": ["<all_urls>"]
55-
}]
61+
}],
62+
63+
"declarative_net_request": {
64+
"rule_resources": [{
65+
"id": "ipLoggerRuleset",
66+
"enabled": true,
67+
"path": "ip_logger_blocker.json"
68+
},
69+
{
70+
"id": "trackerRuleset",
71+
"enabled": false,
72+
"path": "tracker_bypass.json"
73+
}]
74+
}
5675
}

platform_spec/firefox/manifest.json

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,26 @@
1616
"browser_specific_settings": {
1717
"gecko": {
1818
19-
"strict_min_version": "109.0"
19+
"strict_min_version": "113.0"
2020
}
2121
},
2222
"permissions": [
2323
"alarms",
2424
"storage",
2525
"webNavigation",
26-
"tabs"
26+
"tabs",
27+
"declarativeNetRequestWithHostAccess"
28+
],
29+
"host_permissions": [
30+
"<all_urls>"
2731
],
2832
"options_ui": {
2933
"page": "html/options.html",
3034
"open_in_tab": true
3135
},
3236
"background": {
33-
"scripts": ["background.js"]
37+
"scripts": ["background.js"],
38+
"type": "module"
3439
},
3540
"action": {
3641
"default_popup": "html/popup.html"
@@ -51,11 +56,27 @@
5156
"html/before-navigate.html",
5257
"html/blocked.html",
5358
"html/crowd-bypassed.html",
59+
"html/tracker-bypass.html",
5460
"html/options.html",
5561
"icon/48.png",
5662
"injection_script.js",
5763
"bypasses/*",
58-
"helpers/*"],
64+
"helpers/*",
65+
"rules.json"
66+
],
5967
"matches": ["<all_urls>"]
60-
}]
68+
}],
69+
"declarative_net_request": {
70+
"rule_resources": [{
71+
"id": "ipLoggerRuleset",
72+
"enabled": true,
73+
"path": "ip_logger_blocker.json"
74+
},
75+
{
76+
"id": "trackerRuleset",
77+
"enabled": false,
78+
"path": "tracker_bypass.json"
79+
}]
80+
81+
}
6182
}

scripts/build.js

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,9 @@ import fs from 'fs-extra';
1010
import ejs from 'ejs';
1111
import process from 'process';
1212
import path from 'path';
13-
import {
14-
copyArray,
15-
changeCwdtoRoot,
16-
getNumberOfCommits,
17-
} from './build_js/utils.js';
13+
import * as utils from './build_js/utils.js';
1814

19-
changeCwdtoRoot();
15+
utils.changeCwdtoRoot();
2016
let working_directory = process.cwd();
2117
const distribution = `${working_directory}/build/dist`;
2218
let [browser, version] = process.argv.slice(2);
@@ -48,16 +44,12 @@ fs.mkdirSync(browserDir);
4844
// Copy privacy.md and src except js
4945
let src = ['./src', './docs/PRIVACY.md'];
5046
let exceptions = ['./src/js/', 'version.txt'];
51-
await copyArray(src, browserDir, exceptions);
47+
await utils.copyArray(src, browserDir, exceptions);
5248

5349
//copy js
5450
src = ['./src/js'];
55-
exceptions = [
56-
'injection_script-original.js',
57-
'injection_script.js',
58-
'rules.json',
59-
];
60-
await copyArray(src, browserDir, exceptions);
51+
exceptions = ['injection_script-original.js', 'injection_script.js'];
52+
await utils.copyArray(src, browserDir, exceptions);
6153

6254
let bypasses = {};
6355
for (const i of fs.readdirSync(`${working_directory}/src/bypasses`)) {
@@ -87,25 +79,26 @@ fs.writeFileSync(outputPath, result);
8779
if (browser === 'all') {
8880
const chromiumDir = `${working_directory}/build/FastForward.chromium`;
8981
fs.mkdirSync(chromiumDir);
90-
await copyArray([browserDir], chromiumDir);
82+
await utils.copyArray([browserDir], chromiumDir);
9183
}
9284

93-
/*Compile*/
85+
/*version*/
9486
let packageVersion = '';
9587
if (version === 'ver') {
9688
packageVersion = fs.readFileSync('version.txt', 'utf-8').trim();
9789
} else if (version === 'nover') {
98-
const lastCommit = getNumberOfCommits();
90+
const lastCommit = utils.getNumberOfCommits();
9991
packageVersion = `0.${lastCommit}`;
10092
}
10193

10294
async function buildExtension(browser) {
10395
const targetBrowser = browser === 'firefox' ? 'firefox-desktop' : 'chromium';
104-
const browserDir = `${working_directory}/build/FastForward.${browser}`;
105-
const manfistFile = `${working_directory}/platform_spec/${browser}/manifest.json`;
106-
await copyArray([manfistFile], browserDir);
96+
const browserOutDir = `${working_directory}/build/FastForward.${browser}`;
97+
const browserSrcDir = `${working_directory}/platform_spec/${browser}`;
98+
const manfistFile = `${browserSrcDir}/manifest.json`;
99+
await utils.copyArray([manfistFile], browserOutDir);
107100
fs.writeFileSync(
108-
`${browserDir}/manifest.json`,
101+
`${browserOutDir}/manifest.json`,
109102
JSON.stringify(
110103
Object.assign(JSON.parse(fs.readFileSync(manfistFile, 'utf8')), {
111104
version: packageVersion,
@@ -114,10 +107,15 @@ async function buildExtension(browser) {
114107
4 //pretty print
115108
)
116109
);
110+
await utils.convertRulesToDNRRulesets(
111+
`${browserOutDir}/rules.json`,
112+
`${browserOutDir}/ip_logger_blocker.json`,
113+
`${browserOutDir}/tracker_bypass.json`
114+
);
117115

118116
await webExt.cmd.build(
119117
{
120-
sourceDir: browserDir,
118+
sourceDir: browserOutDir,
121119
artifactsDir: `${distribution}`,
122120
overwriteDest: true,
123121
browser: targetBrowser,

scripts/build_js/injection_script_template.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,20 @@ const bypasses = [/- bypasses -/];
22
const script_src = new URL(document.currentScript.src);
33
const ext_base_URL = script_src.searchParams.get('ext_base_URL');
44

5-
if (location.host in bypasses) {
6-
const bypass_url = bypasses[location.host];
5+
function matchingBypass(bypasses) {
6+
for (const [key] of Object.entries(bypasses)) {
7+
if (key.charAt(0) === '/' && key.charAt(key.length - 1) === '/') {
8+
let pattern = new RegExp(key.substring(1, key.length - 1));
9+
return pattern.test(location.href) ? key : null;
10+
} else if (key === location.host) {
11+
return key;
12+
}
13+
return null;
14+
}
15+
}
16+
17+
if (matchingBypass(bypasses)) {
18+
const bypass_url = bypasses[matchingBypass(bypasses)];
719

820
import(ext_base_URL.concat(bypass_url)).then(({ default: bypass }) => {
921
import(ext_base_URL.concat('helpers/dom.js')).then(

scripts/build_js/utils.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,62 @@ export function getNumberOfCommits() {
7070
console.error(error);
7171
}
7272
}
73+
74+
/**
75+
* Converts a rules.json with trackers and ip_loggers file into two
76+
* separate declarativeNetRequest rulesets and writes the resulting JSONs to file.
77+
*
78+
* @async
79+
* @function convertRulesToDeclarativeNetRequest
80+
* @param {string} rulesFilePath - The path to the input JSON file containing the rules to be converted.
81+
* @param {string} ipLoggerOutputFile - The path to the output file where the ip logger rules will be written.
82+
* @param {string} trackerOutputFile - The path to the output file where the tracker rules will be written.
83+
*
84+
* @returns {Promise<void>}
85+
*/
86+
export async function convertRulesToDNRRulesets(
87+
rulesFilePath,
88+
ipLoggerOutputFile,
89+
trackerOutputFile
90+
) {
91+
const rules = JSON.parse(await fs.readFile(rulesFilePath));
92+
const domainRegex = /:\/\/\*?\.?([^/]+)/;
93+
const ip_loggerRules = rules.ip_logger.map((urlPattern, index) => {
94+
const domainMatch = urlPattern.match(domainRegex);
95+
if (!domainMatch) console.error('Unable to parse domain for', urlPattern);
96+
return {
97+
id: index + 1,
98+
priority: 1,
99+
action: {
100+
type: 'redirect',
101+
redirect: { extensionPath: '/html/blocked.html' },
102+
},
103+
condition: {
104+
urlFilter: `||${domainMatch[1]}`,
105+
resourceTypes: ['main_frame'],
106+
},
107+
};
108+
});
109+
110+
const trackerRules = rules.tracker.map((urlPattern, index) => {
111+
const domainMatch = urlPattern.match(domainRegex);
112+
if (!domainMatch) console.error('Unable to parse domain for', urlPattern);
113+
return {
114+
id: index + 1,
115+
priority: 1,
116+
action: {
117+
type: 'redirect',
118+
redirect: {
119+
regexSubstitution: `https://fastforward.team/bypassed?type=tracker&url=\\0`,
120+
},
121+
},
122+
condition: {
123+
regexFilter: '^https?://' + domainMatch[1] + '.*',
124+
resourceTypes: ['main_frame'],
125+
},
126+
};
127+
});
128+
129+
await fs.writeFile(ipLoggerOutputFile, JSON.stringify(ip_loggerRules));
130+
await fs.writeFile(trackerOutputFile, JSON.stringify(trackerRules));
131+
}

src/_locales/en/messages.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"message": "Take me to destinations after % second(s)."
4040
},
4141
"optionsTrackerBypass": {
42-
"message": "Bypass trackers (such as bit.ly and t.co) using Apimon.de."
42+
"message": "Bypass trackers (such as bit.ly and goo.gl) using Unshorten.me."
4343
},
4444
"optionsInstantNavigationTrackers": {
4545
"message": "Instantly take me to destinations of trackers."
@@ -145,6 +145,12 @@
145145
},
146146
"crowdBypassTempDisabled":{
147147
"message":"Crowd bypass has been temporarily disabled"
148+
},
149+
"trackerBypass": {
150+
"message": "Bypassing tracker..."
151+
},
152+
"trackerBypassedError": {
153+
"message": "Oops! Something went wrong. Redirecting to the original link..."
148154
}
149155

150156
}

0 commit comments

Comments
 (0)