├── list
├── hosts.json
├── index.html
└── index.js
├── v2
├── _locales
│ ├── bg
│ │ └── messages.json
│ ├── cs
│ │ └── messages.json
│ ├── da
│ │ └── messages.json
│ ├── de
│ │ └── messages.json
│ ├── el
│ │ └── messages.json
│ ├── en
│ │ └── messages.json
│ ├── et
│ │ └── messages.json
│ ├── fi
│ │ └── messages.json
│ ├── fr
│ │ └── messages.json
│ ├── hu
│ │ └── messages.json
│ ├── nl
│ │ └── messages.json
│ └── zh_CN
│ │ └── messages.json
├── background.js
├── data
│ ├── assets
│ │ └── hosts.json
│ ├── icons
│ │ ├── 128.png
│ │ ├── 16.png
│ │ ├── 256.png
│ │ ├── 32.png
│ │ ├── 48.png
│ │ ├── 512.png
│ │ ├── 64.png
│ │ └── disabled
│ │ │ ├── 16.png
│ │ │ ├── 32.png
│ │ │ ├── 48.png
│ │ │ └── 64.png
│ ├── inject
│ │ └── hide.css
│ └── options
│ │ ├── index.html
│ │ └── index.js
├── hosts.js
└── manifest.json
└── v3
├── _locales
├── bg
│ └── messages.json
├── cs
│ └── messages.json
├── da
│ └── messages.json
├── de
│ └── messages.json
├── el
│ └── messages.json
├── en
│ └── messages.json
├── et
│ └── messages.json
├── fi
│ └── messages.json
├── fr
│ └── messages.json
├── hu
│ └── messages.json
├── nl
│ └── messages.json
└── zh_CN
│ └── messages.json
├── _metadata
└── generated_indexed_rulesets
│ └── _ruleset1
├── data
├── icons
│ ├── 128.png
│ ├── 16.png
│ ├── 256.png
│ ├── 32.png
│ ├── 48.png
│ ├── 512.png
│ ├── 64.png
│ └── disabled
│ │ ├── 16.png
│ │ ├── 32.png
│ │ ├── 48.png
│ │ └── 64.png
├── inject
│ └── hide.css
└── options
│ ├── index.css
│ ├── index.html
│ └── index.js
├── manifest.json
├── rules.json
└── worker.js
/list/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/list/index.js:
--------------------------------------------------------------------------------
1 | /* global tldjs */
2 |
3 | const domains = {};
4 |
5 | const blocked = {
6 | keywords: {
7 | list: [
8 | /ads(\d+)?[.-]/,
9 | /adv(\d+)?[.-]/,
10 | /ad(\d+)?[.-]/,
11 | /survey(\d+)?[.-]/,
12 | /track[.-]/,
13 | /analytics\./,
14 | /banner/,
15 | /adserve/,
16 | /advert/,
17 | /tracker/,
18 | /tracking/,
19 | /affiliate/
20 | ],
21 | count: 0
22 | },
23 | // domains that use many hostnames for advertising
24 | domains: {
25 | list: [
26 | 'reporo.net', 'voluumtrk.com', 'dol.ru', '2cnt.net', 'ivwbox.de', 'adtech.fr', 'justclick.ru', 'appier.net',
27 | 'vmsn.de', 'adk2.co', 'surf-town.net'
28 | ],
29 | count: 0
30 | },
31 | // domain is in the list of hostnames
32 | duplicates: 0,
33 | sdups: 0
34 | };
35 |
36 | fetch('hosts.json').then(r => r.json()).then(a => {
37 | // reduce by blocked words
38 | a = a.filter(host => {
39 | if (blocked.keywords.list.some(w => w.test(host))) {
40 | blocked.keywords.count += 1;
41 | return false;
42 | }
43 | return true;
44 | });
45 | console.log('"blocked keywords" -> reduced by', blocked.keywords.count);
46 |
47 | a.forEach(hostname => {
48 | const d = tldjs.getDomain(hostname);
49 | domains[d] = domains[d] || [];
50 | if (d) {
51 | domains[d].push(hostname);
52 | }
53 | });
54 |
55 | // reduce if domain is in the hostname list
56 | for (const [key, value] of Object.entries(domains)) {
57 | if (value.length > 1 && value.indexOf(key) !== -1) {
58 | blocked.duplicates += value.length - 1;
59 | domains[key] = [key];
60 | }
61 | }
62 | console.log('"blocked domains" -> reduced by', blocked.duplicates);
63 |
64 | // reduce by bad reputation domains
65 | for (const d of blocked.domains.list) {
66 | blocked.domains.count += domains[d].length - 1;
67 | domains[d] = [d];
68 | }
69 | console.log('"blocked bad reputation" -> reduced by', blocked.domains.count);
70 |
71 | for (const [key, value] of Object.entries(domains)) {
72 | if (value.length > 50) {
73 | console.log('do we need to block', key, value);
74 | }
75 | }
76 |
77 | // remove by duplicated hostnames
78 | for (const [key, value] of Object.entries(domains)) {
79 | const rm = [];
80 |
81 | for (const h of value) {
82 | value.forEach(hh => {
83 | if (hh.endsWith('.' + h)) {
84 | blocked.sdups += 1;
85 | rm.push(hh);
86 | }
87 | });
88 | }
89 |
90 | if (rm.length) {
91 | domains[key] = value.filter(v => rm.indexOf(v) === -1);
92 | }
93 | }
94 | console.log('"blocked duplicated sub-domains" -> reduced by', blocked.sdups);
95 |
96 | const rules = [];
97 | let id = 1;
98 | for (const value of Object.values(domains)) {
99 | for (const hostname of value) {
100 | rules.push({
101 | id,
102 | 'action': {'type': 'block'},
103 | 'condition': {
104 | 'urlFilter': '||' + hostname
105 | }
106 | });
107 | id += 1;
108 | }
109 | }
110 | for (const d of blocked.domains.list) {
111 | rules.push({
112 | id,
113 | 'action': {'type': 'block'},
114 | 'condition': {
115 | 'urlFilter': '||' + d
116 | }
117 | });
118 | id += 1;
119 | }
120 | for (const r of blocked.keywords.list) {
121 | rules.push({
122 | id,
123 | 'action': {'type': 'block'},
124 | 'condition': {
125 | 'regexFilter': r.source
126 | }
127 | });
128 | id += 1;
129 | }
130 |
131 | // download
132 | const link = document.createElement('a');
133 | link.download = 'rules.json';
134 | link.href = 'data:application/json;base64,' + btoa(JSON.stringify(rules));
135 | link.click();
136 | });
137 |
--------------------------------------------------------------------------------
/v2/_locales/bg/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Рекламен блокер с отворен код, базиран на DNS, който работи на базата на филтриране на хостове, за да блокира реклами, зловреден софтуер, фишинг имена на хостове"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v2/_locales/cs/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Blokátor reklam s otevřeným zdrojovým kódem DNS, který funguje na základě filtrování hostitelů a blokuje reklamy, malware a phishingové hostitelské názvy."
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v2/_locales/da/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "En open source DNS-baseret ad-blocker, der fungerer baseret på værtsfiltrering for at blokere annoncer, malware og phishing-værtsnavne"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v2/_locales/de/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Ein Open-Source-DNS-basierter Ad-Blocker, der auf Basis von Host-Filterung Werbung, Malware und Phishing-Hostnamen blockiert"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v2/_locales/el/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Ένα ad-blocker ανοιχτού κώδικα με βάση το DNS που λειτουργεί με βάση το φιλτράρισμα κεντρικών υπολογιστών για να μπλοκάρει διαφημίσεις, κακόβουλο λογισμικό, ονόματα κεντρικών υπολογιστών phishing"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v2/_locales/en/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "An open-source DNS-based ad-blocker that operates based on host filtering to block ads, malware, phishing hostnames"
4 | },
5 | "optionsTitle": {
6 | "message": "Host AdBlocker :: Options Page"
7 | },
8 | "optionsSave": {
9 | "message": "Save"
10 | },
11 | "optionsCheck": {
12 | "message": "Check"
13 | },
14 | "optionsCheckLabel": {
15 | "message": "Test hostname filtering:"
16 | },
17 | "optionsMSG1": {
18 | "message": "Options saved."
19 | },
20 | "optionsMSG2": {
21 | "message": "This hostname is blocked"
22 | },
23 | "optionsMSG3": {
24 | "message": "This hostname is not being blocked"
25 | },
26 | "optionsBlacklist": {
27 | "message": "Additional blacklist hosts: Comma-separated list of additional hostnames to be blocked."
28 | },
29 | "optionsWhitelist": {
30 | "message": "Whitelist domains: Comma-separated list of top level hostnames that Host AdBlocker is disabled on."
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/v2/_locales/et/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Avatud lähtekoodiga DNS-põhine reklaamblokeerija, mis töötab hostide filtreerimise alusel, et blokeerida reklaame, pahavara ja andmepüügi hostinimesid."
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v2/_locales/fi/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Avoimen lähdekoodin DNS-pohjainen mainosten esto, joka toimii isännän suodatuksen perusteella estääkseen mainokset, haittaohjelmat ja phishing-isännänimet."
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v2/_locales/fr/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Un bloqueur de publicité open-source basé sur le DNS qui fonctionne sur la base du filtrage des hôtes pour bloquer les publicités, les logiciels malveillants et les noms d'hôtes de phishing."
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v2/_locales/hu/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Egy nyílt forráskódú DNS-alapú hirdetésblokkoló, amely host-szűrés alapján működik a hirdetések, rosszindulatú programok és adathalász hostnevek blokkolására."
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v2/_locales/nl/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Een open-source DNS-gebaseerde ad-blocker die werkt op basis van host filtering om advertenties, malware, phishing hostnamen te blokkeren"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v2/_locales/zh_CN/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "一个开源的基于DNS的广告拦截器,基于主机过滤来拦截广告、恶意软件、钓鱼网站的主机名。"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v2/background.js:
--------------------------------------------------------------------------------
1 | /* globals hosts */
2 | 'use strict';
3 |
4 | const _ = chrome.i18n.getMessage;
5 |
6 | // icon
7 | const button = {
8 | icon: enable => chrome.browserAction.setIcon({
9 | path: {
10 | '16': '/data/icons' + (enable ? '' : '/disabled') + '/16.png',
11 | '32': '/data/icons' + (enable ? '' : '/disabled') + '/32.png',
12 | '48': '/data/icons' + (enable ? '' : '/disabled') + '/48.png',
13 | '64': '/data/icons' + (enable ? '' : '/disabled') + '/64.png'
14 | }
15 | }),
16 | mode: ({id, url = ''}) => {
17 | const enabled = url.startsWith('http');
18 | chrome.browserAction[enabled ? 'enable' : 'disable'](id);
19 | return enabled;
20 | }
21 | };
22 | chrome.tabs.query({}, tabs => {
23 | tabs.forEach(tab => button.mode(tab) && hosts.update.tab(tab));
24 | });
25 | chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => changeInfo.url && button.mode(tab));
26 |
27 | // Badge
28 | const badge = {
29 | cache: {},
30 | add: (id, hostname) => {
31 | badge.cache[id] = badge.cache[id] || {};
32 | badge.cache[id][hostname] = badge.cache[id][hostname] || 0;
33 | badge.cache[id][hostname] += 1;
34 | chrome.browserAction.setBadgeText({
35 | tabId: id,
36 | text: String(Object.values(badge.cache[id]).reduce((p, c) => p + c, 0))
37 | });
38 | chrome.browserAction.setTitle({
39 | tabId: id,
40 | title: _('appTitle') + '\n\n' +
41 | Object.entries(badge.cache[id]).map(([key, value]) => `${key}: ${value}`).join('\n')
42 | });
43 | },
44 | remove: id => delete badge.cache[id],
45 | clear: id => {
46 | badge.cache[id] = {};
47 | chrome.browserAction.setBadgeText({
48 | tabId: id,
49 | text: ''
50 | });
51 | chrome.browserAction.setTitle({
52 | tabId: id,
53 | title: _('appTitle')
54 | });
55 | },
56 | color: color => chrome.browserAction.setBadgeBackgroundColor({color})
57 | };
58 |
59 | const roots = {};
60 | chrome.tabs.onRemoved.addListener(id => {
61 | delete badge.cache[id];
62 | delete hosts.remove.tab(id);
63 | delete roots[id];
64 | });
65 | badge.color('#1c2b36');
66 |
67 | // Observe
68 | const observe = {
69 | installed: false,
70 | callback: ({url, tabId}) => {
71 | if (tabId === -1) {
72 | return;
73 | }
74 | const hostname = hosts.hostname(url);
75 |
76 | // always allow first party requests
77 | if (roots[tabId] === hostname) {
78 | return;
79 | }
80 |
81 | if (hosts.match(hostname, tabId)) {
82 | badge.add(tabId, hostname);
83 | return {cancel: true};
84 | }
85 | },
86 | onCommand: bool => {
87 | if (bool && observe.installed === false) {
88 | chrome.webRequest.onBeforeRequest.addListener(observe.callback, {
89 | urls: ['*://*/*'],
90 | types: ['sub_frame', 'script', 'xmlhttprequest']
91 | }, ['blocking']);
92 | button.icon(bool);
93 | observe.installed = true;
94 | }
95 | if (!bool && observe.installed === true) {
96 | chrome.webRequest.onBeforeRequest.removeListener(observe.callback);
97 | button.icon(bool);
98 | observe.installed = false;
99 | }
100 | }
101 | };
102 | chrome.storage.local.get({
103 | active: true
104 | }, prefs => observe.onCommand(prefs.active));
105 | chrome.storage.onChanged.addListener(prefs => prefs.active && observe.onCommand(prefs.active.newValue));
106 |
107 | // user click
108 | chrome.browserAction.onClicked.addListener(() => {
109 | chrome.storage.local.get({
110 | active: true
111 | }, prefs => chrome.storage.local.set({
112 | active: !prefs.active
113 | }));
114 | });
115 |
116 | // options
117 | chrome.runtime.onMessage.addListener((request, sender, response) => {
118 | if (request.method === 'domain-check') {
119 | response(hosts.match(request.hostname));
120 | }
121 | });
122 |
123 | // updates
124 | chrome.webRequest.onBeforeRequest.addListener(({tabId, url}) => {
125 | badge.clear(tabId);
126 | roots[tabId] = hosts.hostname(url);
127 |
128 | hosts.update.tab({
129 | id: tabId,
130 | url
131 | });
132 | }, {
133 | urls: ['*://*/*'],
134 | types: ['main_frame']
135 | }, []);
136 |
137 | /* FAQs & Feedback */
138 | {
139 | const {management, runtime: {onInstalled, setUninstallURL, getManifest}, storage, tabs} = chrome;
140 | if (navigator.webdriver !== true) {
141 | const page = getManifest().homepage_url;
142 | const {name, version} = getManifest();
143 | onInstalled.addListener(({reason, previousVersion}) => {
144 | management.getSelf(({installType}) => installType === 'normal' && storage.local.get({
145 | 'faqs': true,
146 | 'last-update': 0
147 | }, prefs => {
148 | if (reason === 'install' || (prefs.faqs && reason === 'update')) {
149 | const doUpdate = (Date.now() - prefs['last-update']) / 1000 / 60 / 60 / 24 > 45;
150 | if (doUpdate && previousVersion !== version) {
151 | tabs.query({active: true, currentWindow: true}, tbs => tabs.create({
152 | url: page + '?version=' + version + (previousVersion ? '&p=' + previousVersion : '') + '&type=' + reason,
153 | active: reason === 'install',
154 | ...(tbs && tbs.length && {index: tbs[0].index + 1})
155 | }));
156 | storage.local.set({'last-update': Date.now()});
157 | }
158 | }
159 | }));
160 | });
161 | setUninstallURL(page + '?rd=feedback&name=' + encodeURIComponent(name) + '&version=' + version);
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/v2/data/icons/128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v2/data/icons/128.png
--------------------------------------------------------------------------------
/v2/data/icons/16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v2/data/icons/16.png
--------------------------------------------------------------------------------
/v2/data/icons/256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v2/data/icons/256.png
--------------------------------------------------------------------------------
/v2/data/icons/32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v2/data/icons/32.png
--------------------------------------------------------------------------------
/v2/data/icons/48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v2/data/icons/48.png
--------------------------------------------------------------------------------
/v2/data/icons/512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v2/data/icons/512.png
--------------------------------------------------------------------------------
/v2/data/icons/64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v2/data/icons/64.png
--------------------------------------------------------------------------------
/v2/data/icons/disabled/16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v2/data/icons/disabled/16.png
--------------------------------------------------------------------------------
/v2/data/icons/disabled/32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v2/data/icons/disabled/32.png
--------------------------------------------------------------------------------
/v2/data/icons/disabled/48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v2/data/icons/disabled/48.png
--------------------------------------------------------------------------------
/v2/data/icons/disabled/64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v2/data/icons/disabled/64.png
--------------------------------------------------------------------------------
/v2/data/inject/hide.css:
--------------------------------------------------------------------------------
1 | #AdContainer,
2 | #AdMiddle,
3 | #RadAd_Skyscraper {
4 | visibility: hidden !important;
5 | display: none !important;
6 | }
7 |
--------------------------------------------------------------------------------
/v2/data/options/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
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 |
--------------------------------------------------------------------------------
/v2/data/options/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function restore() {
4 | chrome.storage.local.get({
5 | blacklist: [],
6 | whitelist: ['addons.mozilla.org', 'chrome.google.com', 'addons.opera.com', 'add0n.com']
7 | }, prefs => {
8 | document.getElementById('blacklist').value = prefs.blacklist.join(', ');
9 | document.getElementById('whitelist').value = prefs.whitelist.join(', ');
10 | });
11 | }
12 |
13 | function toArray(value) {
14 | return value.split(/\s*,\s*/)
15 | .map(s => s.trim().toLowerCase())
16 | .filter((s, i, l) => s && l.indexOf(s) === i)
17 | .filter(s => s.indexOf('.') !== -1)
18 | .filter(s => s.length > 3);
19 | }
20 |
21 | function save() {
22 | const blacklist = toArray(document.getElementById('blacklist').value);
23 | const whitelist = toArray(document.getElementById('whitelist').value);
24 | console.log(blacklist, whitelist);
25 | chrome.storage.local.set({blacklist, whitelist}, () => {
26 | const status = document.getElementById('status');
27 | status.textContent = chrome.i18n.getMessage('optionsMSG1');
28 | restore();
29 | setTimeout(() => status.textContent = '', 750);
30 | });
31 | }
32 |
33 | document.addEventListener('DOMContentLoaded', restore);
34 | document.getElementById('save').addEventListener('click', save);
35 |
36 | document.getElementById('check').addEventListener('click', e => {
37 | chrome.runtime.sendMessage({
38 | method: 'domain-check',
39 | hostname: e.target.parentNode.querySelector('[type=text]').value
40 | }, res => {
41 | const status = document.getElementById('status');
42 | status.textContent = chrome.i18n.getMessage(res ? 'optionsMSG2' : 'optionsMSG3');
43 | restore();
44 | setTimeout(() => status.textContent = '', 1500);
45 | });
46 | });
47 |
48 | [...document.querySelectorAll('[data-i18n]')].forEach(e => {
49 | e.textContent = chrome.i18n.getMessage(e.dataset.i18n);
50 | });
51 |
--------------------------------------------------------------------------------
/v2/hosts.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const hosts = (() => {
4 | let blacklist = new Set([]);
5 | let whitelist = new Set();
6 | function update() {
7 | fetch('/data/assets/hosts.json').then(r => r.json()).then(r => {
8 | blacklist = new Set(r);
9 | whitelist = new Set();
10 | }).then(() => {
11 | chrome.storage.local.get({
12 | whitelist: ['addons.mozilla.org', 'chrome.google.com', 'addons.opera.com', 'add0n.com'],
13 | blacklist: []
14 | }, prefs => {
15 | prefs.whitelist.forEach(s => whitelist.add(s));
16 | prefs.blacklist.forEach(s => blacklist.add(s));
17 | });
18 | });
19 | }
20 | chrome.storage.onChanged.addListener(prefs => {
21 | if (prefs.whitelist || prefs.blacklist) {
22 | update();
23 | }
24 | });
25 | update();
26 |
27 | function hostname(url) {
28 | const s = url.indexOf('//') + 2;
29 | if (s > 1) {
30 | let o = url.indexOf('/', s);
31 | if (o > 0) {
32 | return url.substring(s, o);
33 | }
34 | else {
35 | o = url.indexOf('?', s);
36 | if (o > 0) {
37 | return url.substring(s, o);
38 | }
39 | else {
40 | return url.substring(s);
41 | }
42 | }
43 | }
44 | else {
45 | return url;
46 | }
47 | }
48 |
49 | const tabs = {
50 | cache: {},
51 | add: tab => tabs.cache[tab.id] = hostname(tab.url)
52 | };
53 |
54 | return {
55 | hostname,
56 | match: (hostname, id) => blacklist.has(hostname) && !whitelist.has(tabs.cache[id]),
57 | update: {
58 | tab: tabs.add
59 | },
60 | remove: {
61 | tab: id => delete tabs.cache[id]
62 | }
63 | };
64 | })();
65 |
66 | // https://adaway.org/hosts.txt
67 | // https://hosts-file.net/ad_servers.txt
68 | // https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=0&mimetype=plaintext
69 | /*
70 | var url = 'data:text/plain;charset=utf-8,' + encodeURIComponent(document.body.textContent.split('\n')
71 | .map(s => s.trim())
72 | .filter(s => s && s[0] !== '#')
73 | .filter((s, i, l) => l.indexOf(s) === i)
74 | .map(s => s.split(/\s+/).pop())
75 | .filter(s => s !== 'localhost')
76 | .map(s => `'${s}'`).join(','));
77 | fetch(url).then(res => res.blob())
78 | .then(blob => {
79 | const objectURL = URL.createObjectURL(blob);
80 | Object.assign(document.createElement('a'), {
81 | href: objectURL,
82 | type: 'application/json',
83 | download: 'a.txt',
84 | }).click();
85 | });
86 |
87 | ---
88 | JSON.stringify(a.filter((s, i, l) => l.indexOf(s) === i).sort())
89 | */
90 |
--------------------------------------------------------------------------------
/v2/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 | "default_locale": "en",
4 | "name": "Host AdBlocker",
5 | "version": "0.1.4",
6 | "description": "__MSG_appDesc__",
7 | "permissions": [
8 | "*://*/*",
9 | "storage",
10 | "webRequest",
11 | "webRequestBlocking"
12 | ],
13 | "icons": {
14 | "16": "data/icons/16.png",
15 | "32": "data/icons/32.png",
16 | "48": "data/icons/48.png",
17 | "64": "data/icons/64.png",
18 | "128": "data/icons/128.png",
19 | "256": "data/icons/256.png",
20 | "512": "data/icons/512.png"
21 | },
22 | "background": {
23 | "scripts": [
24 | "hosts.js",
25 | "background.js"
26 | ]
27 | },
28 | "browser_action": {},
29 | "content_scripts": [{
30 | "run_at": "document_start",
31 | "matches": ["*://*/*"],
32 | "css": ["data//inject/hide.css"],
33 | "all_frames": true,
34 | "match_about_blank": true
35 | }],
36 | "options_ui": {
37 | "page": "/data/options/index.html",
38 | "chrome_style": true
39 | },
40 | "homepage_url": "https://add0n.com/adhost.html"
41 | }
42 |
--------------------------------------------------------------------------------
/v3/_locales/bg/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Рекламен блокер с отворен код, базиран на DNS, който работи на базата на филтриране на хостове, за да блокира реклами, зловреден софтуер, фишинг имена на хостове"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v3/_locales/cs/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Blokátor reklam s otevřeným zdrojovým kódem DNS, který funguje na základě filtrování hostitelů a blokuje reklamy, malware a phishingové hostitelské názvy."
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v3/_locales/da/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "En open source DNS-baseret ad-blocker, der fungerer baseret på værtsfiltrering for at blokere annoncer, malware og phishing-værtsnavne"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v3/_locales/de/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Ein Open-Source-DNS-basierter Ad-Blocker, der auf Basis von Host-Filterung Werbung, Malware und Phishing-Hostnamen blockiert"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v3/_locales/el/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Ένα ad-blocker ανοιχτού κώδικα με βάση το DNS που λειτουργεί με βάση το φιλτράρισμα κεντρικών υπολογιστών για να μπλοκάρει διαφημίσεις, κακόβουλο λογισμικό, ονόματα κεντρικών υπολογιστών phishing"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v3/_locales/en/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "An open-source DNS-based ad-blocker that operates based on host filtering to block ads, malware, phishing hostnames"
4 | },
5 | "optionsTitle": {
6 | "message": "Host AdBlocker :: Options Page"
7 | },
8 | "optionsSave": {
9 | "message": "Save Options"
10 | },
11 | "optionsSupport": {
12 | "message": "Support Development"
13 | },
14 | "optionsReset": {
15 | "message": "Factory Reset"
16 | },
17 | "optionsCheck": {
18 | "message": "Check"
19 | },
20 | "optionsCheckLabel": {
21 | "message": "Test hostname filtering:"
22 | },
23 | "optionsMSG1": {
24 | "message": "Options saved."
25 | },
26 | "optionsMSG2": {
27 | "message": "This hostname is blocked"
28 | },
29 | "optionsMSG3": {
30 | "message": "This hostname is not being blocked"
31 | },
32 | "optionsBlacklist": {
33 | "message": "Additional blacklist hosts: Comma-separated list of additional hostnames to be blocked."
34 | },
35 | "optionsWhitelist": {
36 | "message": "Whitelist domains: Comma-separated list of top level hostnames that Host AdBlocker is disabled on."
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/v3/_locales/et/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Avatud lähtekoodiga DNS-põhine reklaamblokeerija, mis töötab hostide filtreerimise alusel, et blokeerida reklaame, pahavara ja andmepüügi hostinimesid."
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v3/_locales/fi/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Avoimen lähdekoodin DNS-pohjainen mainosten esto, joka toimii isännän suodatuksen perusteella estääkseen mainokset, haittaohjelmat ja phishing-isännänimet."
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v3/_locales/fr/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Un bloqueur de publicité open-source basé sur le DNS qui fonctionne sur la base du filtrage des hôtes pour bloquer les publicités, les logiciels malveillants et les noms d'hôtes de phishing."
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v3/_locales/hu/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Egy nyílt forráskódú DNS-alapú hirdetésblokkoló, amely host-szűrés alapján működik a hirdetések, rosszindulatú programok és adathalász hostnevek blokkolására."
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v3/_locales/nl/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "Een open-source DNS-gebaseerde ad-blocker die werkt op basis van host filtering om advertenties, malware, phishing hostnamen te blokkeren"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v3/_locales/zh_CN/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appDesc": {
3 | "message": "一个开源的基于DNS的广告拦截器,基于主机过滤来拦截广告、恶意软件、钓鱼网站的主机名。"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/v3/_metadata/generated_indexed_rulesets/_ruleset1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v3/_metadata/generated_indexed_rulesets/_ruleset1
--------------------------------------------------------------------------------
/v3/data/icons/128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v3/data/icons/128.png
--------------------------------------------------------------------------------
/v3/data/icons/16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v3/data/icons/16.png
--------------------------------------------------------------------------------
/v3/data/icons/256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v3/data/icons/256.png
--------------------------------------------------------------------------------
/v3/data/icons/32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v3/data/icons/32.png
--------------------------------------------------------------------------------
/v3/data/icons/48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v3/data/icons/48.png
--------------------------------------------------------------------------------
/v3/data/icons/512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v3/data/icons/512.png
--------------------------------------------------------------------------------
/v3/data/icons/64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v3/data/icons/64.png
--------------------------------------------------------------------------------
/v3/data/icons/disabled/16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v3/data/icons/disabled/16.png
--------------------------------------------------------------------------------
/v3/data/icons/disabled/32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v3/data/icons/disabled/32.png
--------------------------------------------------------------------------------
/v3/data/icons/disabled/48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v3/data/icons/disabled/48.png
--------------------------------------------------------------------------------
/v3/data/icons/disabled/64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ray-lothian/adhost-adblocker/1b8b17541695e5774b23d228dab4ebbf5c70fcfd/v3/data/icons/disabled/64.png
--------------------------------------------------------------------------------
/v3/data/inject/hide.css:
--------------------------------------------------------------------------------
1 | #AdContainer,
2 | #AdMiddle,
3 | #RadAd_Skyscraper {
4 | visibility: hidden !important;
5 | display: none !important;
6 | }
7 |
--------------------------------------------------------------------------------
/v3/data/options/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-size: 13px;
3 | font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
4 | background-color: #fff;
5 | color: #4d5156;
6 | margin: 10px;
7 | }
8 | select,
9 | button,
10 | input[type=submit],
11 | input[type=button] {
12 | height: 24px;
13 | color: #444;
14 | background-image: linear-gradient(rgb(237, 237, 237), rgb(237, 237, 237) 38%, rgb(222, 222, 222));
15 | box-shadow: rgba(0, 0, 0, 0.08) 0 1px 0, rgba(255, 255, 255, 0.75) 0 1px 2px inset;
16 | text-shadow: rgb(240, 240, 240) 0 1px 0;
17 | }
18 | select,
19 | button,
20 | textarea,
21 | input {
22 | border: solid 1px rgba(0, 0, 0, 0.25);
23 | }
24 | input[type=button]:disabled {
25 | opacity: 0.5;
26 | }
27 | textarea {
28 | width: 100%;
29 | box-sizing: border-box;
30 | display: block;
31 | margin: 10px 0;
32 | }
33 | textarea,
34 | input[type=text],
35 | input[type=number] {
36 | padding: 5px;
37 | outline: none;
38 | }
39 | textarea:focus,
40 | input[type=text]:focus,
41 | input[type=number]:focus {
42 | background-color: #e5f8ff;
43 | }
44 | a,
45 | a:visited {
46 | color: #07c;
47 | }
48 |
--------------------------------------------------------------------------------
/v3/data/options/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/v3/data/options/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const toast = document.getElementById('toast');
4 |
5 | function restore() {
6 | chrome.storage.local.get({
7 | blacklist: [],
8 | whitelist: ['addons.mozilla.org', 'chrome.google.com', 'addons.opera.com', 'add0n.com', 'microsoftedge.microsoft.com']
9 | }, prefs => {
10 | document.getElementById('blacklist').value = prefs.blacklist.join(', ');
11 | document.getElementById('whitelist').value = prefs.whitelist.join(', ');
12 | });
13 | }
14 |
15 | function toArray(value) {
16 | return value.split(/\s*,\s*/)
17 | .map(s => s.trim().toLowerCase())
18 | .filter((s, i, l) => s && l.indexOf(s) === i)
19 | .filter(s => s.indexOf('.') !== -1)
20 | .filter(s => s.length > 3);
21 | }
22 |
23 | function save() {
24 | const blacklist = toArray(document.getElementById('blacklist').value);
25 | const whitelist = toArray(document.getElementById('whitelist').value);
26 | console.log(blacklist, whitelist);
27 | chrome.storage.local.set({blacklist, whitelist}, () => {
28 | toast.textContent = chrome.i18n.getMessage('optionsMSG1');
29 | restore();
30 | setTimeout(() => toast.textContent = '', 750);
31 | });
32 | }
33 |
34 | document.addEventListener('DOMContentLoaded', restore);
35 | document.getElementById('save').addEventListener('click', save);
36 |
37 | [...document.querySelectorAll('[data-i18n]')].forEach(e => {
38 | e.textContent = chrome.i18n.getMessage(e.dataset.i18n);
39 | });
40 |
41 | // reset
42 | document.getElementById('reset').addEventListener('click', e => {
43 | if (e.detail === 1) {
44 | toast.textContent = 'Double-click to reset!';
45 | window.setTimeout(() => toast.textContent = '', 750);
46 | }
47 | else {
48 | localStorage.clear();
49 | chrome.storage.local.clear(() => {
50 | chrome.runtime.reload();
51 | window.close();
52 | });
53 | }
54 | });
55 |
56 | // support
57 | document.getElementById('support').addEventListener('click', () => chrome.tabs.create({
58 | url: chrome.runtime.getManifest().homepage_url + '?rd=donate'
59 | }));
60 |
--------------------------------------------------------------------------------
/v3/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 3,
3 | "default_locale": "en",
4 | "name": "Host AdBlocker",
5 | "version": "0.2.0",
6 | "description": "__MSG_appDesc__",
7 | "permissions": [
8 | "storage",
9 | "declarativeNetRequest"
10 | ],
11 | "icons": {
12 | "16": "data/icons/16.png",
13 | "32": "data/icons/32.png",
14 | "48": "data/icons/48.png",
15 | "64": "data/icons/64.png",
16 | "128": "data/icons/128.png",
17 | "256": "data/icons/256.png",
18 | "512": "data/icons/512.png"
19 | },
20 | "background": {
21 | "service_worker": "worker.js"
22 | },
23 | "action": {},
24 | "content_scripts": [{
25 | "run_at": "document_start",
26 | "matches": ["*://*/*"],
27 | "css": ["data//inject/hide.css"],
28 | "all_frames": true,
29 | "match_about_blank": true
30 | }],
31 | "options_ui": {
32 | "page": "/data/options/index.html"
33 | },
34 | "homepage_url": "https://add0n.com/adhost.html",
35 | "declarative_net_request" : {
36 | "rule_resources" : [{
37 | "id": "default-set",
38 | "enabled": true,
39 | "path": "rules.json"
40 | }]
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/v3/worker.js:
--------------------------------------------------------------------------------
1 | chrome.declarativeNetRequest.setExtensionActionOptions({
2 | displayActionCountAsBadgeText: true
3 | });
4 |
5 | chrome.action.onClicked.addListener(async () => {
6 | const s = await chrome.declarativeNetRequest.getEnabledRulesets();
7 | if (s.indexOf('default-set') === -1) {
8 | await chrome.declarativeNetRequest.updateEnabledRulesets({
9 | enableRulesetIds: ['default-set']
10 | });
11 | }
12 | else {
13 | await chrome.declarativeNetRequest.updateEnabledRulesets({
14 | disableRulesetIds: ['default-set']
15 | });
16 | }
17 | icon();
18 | });
19 |
20 | const icon = async () => {
21 | const s = await chrome.declarativeNetRequest.getEnabledRulesets();
22 | console.log(s);
23 | if (s.indexOf('default-set') === -1) {
24 | chrome.action.setIcon({
25 | path: {
26 | '16': 'data/icons/disabled/16.png',
27 | '32': 'data/icons/disabled/32.png',
28 | '48': 'data/icons/disabled/48.png'
29 | }
30 | });
31 | }
32 | else {
33 | chrome.action.setIcon({
34 | path: {
35 | '16': 'data/icons/16.png',
36 | '32': 'data/icons/32.png',
37 | '48': 'data/icons/48.png'
38 | }
39 | });
40 | }
41 | };
42 |
43 | const user = () => chrome.storage.local.get({
44 | whitelist: ['addons.mozilla.org', 'chrome.google.com', 'addons.opera.com', 'add0n.com', 'microsoftedge.microsoft.com'],
45 | blacklist: []
46 | }, async prefs => {
47 | const rules = prefs.whitelist.map((d, n) => ({
48 | 'id': n + 1,
49 | 'action': {
50 | 'type': 'allowAllRequests'
51 | },
52 | 'condition': {
53 | 'urlFilter': '||' + d,
54 | 'resourceTypes': ['main_frame']
55 | }
56 | }));
57 | prefs.blacklist.forEach((d, n) => {
58 | rules.push({
59 | 'id': prefs.whitelist.length + n + 1,
60 | 'action': {'type': 'block'},
61 | 'condition': {
62 | 'urlFilter': '||' + d
63 | }
64 | });
65 | });
66 |
67 | chrome.declarativeNetRequest.updateSessionRules({
68 | removeRuleIds: (await chrome.declarativeNetRequest.getSessionRules()).map(o => o.id),
69 | addRules: rules
70 | });
71 | });
72 |
73 | chrome.runtime.onStartup.addListener(() => {
74 | icon();
75 | user();
76 | });
77 | chrome.runtime.onInstalled.addListener(() => {
78 | icon();
79 | user();
80 | });
81 |
82 | chrome.storage.onChanged.addListener(ps => {
83 | if (ps.whitelist || ps.blacklist) {
84 | user();
85 | }
86 | });
87 |
88 | /* FAQs & Feedback */
89 | {
90 | const {management, runtime: {onInstalled, setUninstallURL, getManifest}, storage, tabs} = chrome;
91 | if (navigator.webdriver !== true) {
92 | const page = getManifest().homepage_url;
93 | const {name, version} = getManifest();
94 | onInstalled.addListener(({reason, previousVersion}) => {
95 | management.getSelf(({installType}) => installType === 'normal' && storage.local.get({
96 | 'faqs': true,
97 | 'last-update': 0
98 | }, prefs => {
99 | if (reason === 'install' || (prefs.faqs && reason === 'update')) {
100 | const doUpdate = (Date.now() - prefs['last-update']) / 1000 / 60 / 60 / 24 > 45;
101 | if (doUpdate && previousVersion !== version) {
102 | tabs.query({active: true, currentWindow: true}, tbs => tabs.create({
103 | url: page + '?version=' + version + (previousVersion ? '&p=' + previousVersion : '') + '&type=' + reason,
104 | active: reason === 'install',
105 | ...(tbs && tbs.length && {index: tbs[0].index + 1})
106 | }));
107 | storage.local.set({'last-update': Date.now()});
108 | }
109 | }
110 | }));
111 | });
112 | setUninstallURL(page + '?rd=feedback&name=' + encodeURIComponent(name) + '&version=' + version);
113 | }
114 | }
115 |
--------------------------------------------------------------------------------