├── 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 | --------------------------------------------------------------------------------