Skip to content

Commit cdca974

Browse files
committed
Apply DNR rules
1 parent d531288 commit cdca974

File tree

3 files changed

+139
-98
lines changed

3 files changed

+139
-98
lines changed

extension-manifest-v3/src/background/dnr.js

+30-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,28 @@
1010
*/
1111

1212
import { observe, ENGINES } from '/store/options.js';
13+
import { setDNRRules } from '/utils/custom-filters.js';
14+
15+
async function updateDNRRules(dnrRules) {
16+
const dynamicRules = await chrome.declarativeNetRequest.getDynamicRules();
17+
18+
await chrome.declarativeNetRequest.updateDynamicRules({
19+
removeRuleIds: dynamicRules
20+
// ids between 1 and 2 million are reserved for dynamic rules
21+
.filter(({ id }) => id >= 1000000 && id < 2000000)
22+
.map(({ id }) => id),
23+
});
24+
25+
const addRules = dnrRules.map((rule, index) => ({
26+
...rule,
27+
id: 1000000 + index,
28+
}));
29+
await chrome.declarativeNetRequest.updateDynamicRules({ addRules });
30+
31+
await setDNRRules(dnrRules);
32+
33+
return dnrRules;
34+
}
1335

1436
if (__PLATFORM__ !== 'firefox') {
1537
const DNR_RESOURCES = chrome.runtime
@@ -110,8 +132,15 @@ if (__PLATFORM__ !== 'firefox') {
110132
});
111133
} else if (dynamicRules.length) {
112134
chrome.declarativeNetRequest.updateDynamicRules({
113-
removeRuleIds: dynamicRules.map(({ id }) => id),
135+
removeRuleIds: __PLATFORM__ === 'safari' ? [1] : [1, 2],
114136
});
115137
}
116138
});
139+
140+
chrome.runtime.onMessage.addListener((msg, _, sendResponse) => {
141+
if (msg.action === 'custom-filters:update-dnr') {
142+
updateDNRRules(msg.dnrRules).then(sendResponse);
143+
return true;
144+
}
145+
});
117146
}

extension-manifest-v3/src/pages/settings/components/custom-filters.js

+57-97
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,39 @@
1212
import { html, store } from 'hybrids';
1313
import { detectFilterType } from '@cliqz/adblocker';
1414
import convert from '../dnr-converter.js';
15+
import { getDNRRules } from '/utils/custom-filters.js';
1516
import CustomFiltersInput from '../store/custom-filters-input.js';
1617

18+
function parseFilters(text = '') {
19+
return text
20+
.split('\n')
21+
.map((f) => f.trim())
22+
.filter(Boolean)
23+
.reduce(
24+
(filters, filter) => {
25+
const filterType = detectFilterType(filter);
26+
if (filterType === 1) {
27+
// NETWORK
28+
filters.networkFilters.push(filter);
29+
} else if (filterType === 2) {
30+
// COSMETIC
31+
filters.cosmeticFilters.push(filter);
32+
} else {
33+
filters.errors.push(`Filter not supported: '${filter}'`);
34+
}
35+
return filters;
36+
},
37+
{
38+
networkFilters: [],
39+
cosmeticFilters: [],
40+
errors: [],
41+
},
42+
);
43+
}
44+
1745
async function onSave(host) {
1846
const { networkFilters, cosmeticFilters } = host.filters;
19-
const output = {
20-
networkFilters,
21-
cosmeticFilters,
22-
dnrRules: [],
23-
};
47+
const dnrRules = [];
2448
const dnrErrors = [];
2549

2650
const results = await Promise.allSettled(
@@ -29,92 +53,34 @@ async function onSave(host) {
2953

3054
for (const result of results) {
3155
dnrErrors.push(...result.value.errors);
32-
output.dnrRules.push(...result.value.rules);
56+
dnrRules.push(...result.value.rules);
3357
}
3458

3559
host.dnrErrors = dnrErrors;
3660

3761
if (!dnrErrors.length) {
3862
store.submit(host.input);
39-
host.output = output;
63+
host.dnrRules = await chrome.runtime.sendMessage({
64+
action: 'custom-filters:update-dnr',
65+
dnrRules,
66+
});
4067
}
4168
}
4269

4370
export default {
4471
input: store(CustomFiltersInput, { draft: true }),
45-
output: {
46-
get: async () => {
47-
const {
48-
networkFilters = [],
49-
cosmeticFilters = [],
50-
dnrRules = [],
51-
} = (await chrome.storage.local.get(['custom-filters-output']))[
52-
'custom-filters-output'
53-
] || {};
54-
55-
return {
56-
networkFilters,
57-
cosmeticFilters,
58-
dnrRules,
59-
};
72+
dnrRules: {
73+
value: undefined,
74+
connect: (host, key) => {
75+
getDNRRules().then((dnrRules) => {
76+
host[key] = dnrRules;
77+
});
6078
},
61-
set: async (
62-
_,
63-
{ networkFilters = [], cosmeticFilters = [], dnrRules = [] } = {},
64-
lastValue,
65-
) => {
66-
if (lastValue) {
67-
await chrome.storage.local.set({
68-
'custom-filters-output': {
69-
networkFilters,
70-
cosmeticFilters,
71-
dnrRules,
72-
},
73-
});
74-
}
75-
return {
76-
networkFilters,
77-
cosmeticFilters,
78-
dnrRules,
79-
};
80-
},
81-
},
82-
dnrErrors: { set: (_, values = []) => values },
83-
filters: (host) => {
84-
const networkFilters = [];
85-
const cosmeticFilters = [];
86-
const errors = [];
87-
88-
let filters = [];
89-
90-
if (store.ready(host.input)) {
91-
filters = host.input.text
92-
.split('\n')
93-
.map((f) => f.trim())
94-
.filter(Boolean);
95-
}
96-
97-
for (const filter of filters) {
98-
const filterType = detectFilterType(filter);
99-
switch (filterType) {
100-
case 1: // NETWORK
101-
networkFilters.push(filter);
102-
break;
103-
case 2: // COSMETIC
104-
cosmeticFilters.push(filter);
105-
break;
106-
default:
107-
errors.push(`Filter not supported: '${filter}'`);
108-
}
109-
}
110-
111-
return {
112-
networkFilters,
113-
cosmeticFilters,
114-
errors,
115-
};
11679
},
117-
content: ({ input, filters, output, dnrErrors }) => html`
80+
filters: ({ input }) => parseFilters(store.ready(input) ? input.text : ''),
81+
dnrErrors: undefined,
82+
errors: ({ filters, dnrErrors = [] }) => [...filters.errors, ...dnrErrors],
83+
content: ({ input, filters, dnrRules, errors }) => html`
11884
<template layout="column gap:3">
11985
${store.ready(input) &&
12086
html`
@@ -125,8 +91,8 @@ ${input.text}</textarea
12591
<div layout="row gap items:center">
12692
<ui-button
12793
size="small"
128-
type=${filters.errors.length > 0 ? 'outline-error' : 'outline'}
129-
disabled=${filters.errors.length > 0 || dnrErrors.length > 0}
94+
type=${errors.length > 0 ? 'outline-error' : 'outline'}
95+
disabled=${errors.length > 0}
13096
onclick="${onSave}"
13197
layout="shrink:0"
13298
>
@@ -136,7 +102,7 @@ ${input.text}</textarea
136102
<section layout="gap items:center">
137103
<h4>Errors</h4>
138104
<ul>
139-
${[...filters.errors, ...dnrErrors].map(
105+
${errors.map(
140106
(error) =>
141107
html`<li>
142108
<ui-text color="danger-500">${error}</ui-text>
@@ -147,22 +113,16 @@ ${input.text}</textarea
147113
<div>Network filters: ${filters.networkFilters.length}</div>
148114
<div>Cosmetic filters: ${filters.cosmeticFilters.length}</div>
149115
<div>Filter errors: ${filters.errors.length}</div>
150-
${html.resolve(
151-
output.then(
152-
({ networkFilters, cosmeticFilters, dnrRules }) =>
153-
html`
154-
<h4>Output</h4>
155-
<div>Network filters: ${networkFilters.length}</div>
156-
<div>Cosmetic filters: ${cosmeticFilters.length}</div>
157-
<div>DNR rules: ${dnrRules.length}</div>
158-
<ul>
159-
${dnrRules.map(
160-
(rule) => html`<li>${JSON.stringify(rule, null, 2)}</li>`,
161-
)}
162-
</ul>
163-
`,
164-
),
165-
)}
116+
${dnrRules &&
117+
html`
118+
<h4>Output</h4>
119+
<div>DNR rules: ${dnrRules.length}</div>
120+
<ul>
121+
${dnrRules.map(
122+
(rule) => html`<li>${JSON.stringify(rule, null, 2)}</li>`,
123+
)}
124+
</ul>
125+
`},
166126
</section>
167127
</template>
168128
`,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* Ghostery Browser Extension
3+
* https://www.ghostery.com/
4+
*
5+
* Copyright 2017-present Ghostery GmbH. All rights reserved.
6+
*
7+
* This Source Code Form is subject to the terms of the Mozilla Public
8+
* License, v. 2.0. If a copy of the MPL was not distributed with this
9+
* file, You can obtain one at http://mozilla.org/MPL/2.0
10+
*/
11+
12+
const KEY_DNR_RULES = 'custom-filters-dnr';
13+
const KEY_NETWORK_FILTERS = 'custom-filters-network';
14+
const KEY_COSMETIC_FILTERS = 'custom-filters-cosmetic';
15+
16+
export async function getDNRRules() {
17+
return (await chrome.storage.local.get([KEY_DNR_RULES]))[KEY_DNR_RULES] || [];
18+
}
19+
20+
export async function setDNRRules(filters = []) {
21+
await chrome.storage.local.set({
22+
[KEY_DNR_RULES]: filters,
23+
});
24+
}
25+
26+
export async function getNetworkFilters() {
27+
return (
28+
(await chrome.storage.local.get([KEY_NETWORK_FILTERS]))[
29+
KEY_NETWORK_FILTERS
30+
] || []
31+
);
32+
}
33+
34+
export async function setNetworkFilters(filters = []) {
35+
await chrome.storage.local.set({
36+
[KEY_NETWORK_FILTERS]: filters,
37+
});
38+
}
39+
40+
export async function getCosmeticFilters() {
41+
return (
42+
(await chrome.storage.local.get([KEY_COSMETIC_FILTERS]))[
43+
KEY_COSMETIC_FILTERS
44+
] || []
45+
);
46+
}
47+
48+
export async function setCosmeticFilters(filters = []) {
49+
await chrome.storage.local.set({
50+
[KEY_COSMETIC_FILTERS]: filters,
51+
});
52+
}

0 commit comments

Comments
 (0)