├── v2 ├── LICENSE ├── data │ ├── icons │ │ ├── 16.png │ │ ├── 32.png │ │ ├── 48.png │ │ ├── 64.png │ │ ├── 128.png │ │ ├── 256.png │ │ ├── 512.png │ │ ├── disabled │ │ │ ├── 16.png │ │ │ └── 32.png │ │ └── state │ │ │ ├── 1 │ │ │ ├── 16.png │ │ │ └── 32.png │ │ │ ├── 2 │ │ │ ├── 16.png │ │ │ └── 32.png │ │ │ ├── 3 │ │ │ ├── 16.png │ │ │ └── 32.png │ │ │ └── 4 │ │ │ ├── 16.png │ │ │ └── 32.png │ ├── inject │ │ ├── ff.js │ │ ├── iframe.js │ │ └── uncode.js │ ├── ui │ │ ├── ui.html │ │ ├── wot.js │ │ ├── ui.css │ │ └── ui.js │ ├── popup │ │ ├── index.html │ │ ├── index.css │ │ └── index.js │ └── options │ │ ├── index.css │ │ ├── index.html │ │ └── index.js ├── actions │ ├── disabled.js │ └── enabled.js ├── config.js ├── manifest.json └── _locales │ ├── zh_CN │ └── messages.json │ ├── ko │ └── messages.json │ ├── tr │ └── messages.json │ ├── en │ └── messages.json │ ├── ar │ └── messages.json │ ├── sv │ └── messages.json │ ├── it │ └── messages.json │ ├── de │ └── messages.json │ ├── fr │ └── messages.json │ └── es │ └── messages.json ├── v3 ├── data │ ├── inject │ │ ├── test.js │ │ ├── disabled.js │ │ └── block │ │ │ ├── isolated.css │ │ │ └── isolated.js │ ├── icons │ │ ├── 16.png │ │ ├── 32.png │ │ ├── 48.png │ │ ├── 64.png │ │ ├── 128.png │ │ ├── 256.png │ │ ├── 512.png │ │ └── state │ │ │ ├── 0 │ │ │ ├── 16.png │ │ │ └── 32.png │ │ │ ├── 1 │ │ │ ├── 16.png │ │ │ └── 32.png │ │ │ ├── 2 │ │ │ ├── 16.png │ │ │ └── 32.png │ │ │ ├── 3 │ │ │ ├── 16.png │ │ │ └── 32.png │ │ │ └── 4 │ │ │ ├── 16.png │ │ │ └── 32.png │ ├── popup │ │ ├── ReadMe │ │ ├── health.js │ │ ├── index.css │ │ ├── index.html │ │ └── index.mjs │ ├── ui │ │ ├── index.html │ │ └── index.css │ └── options │ │ ├── index.css │ │ ├── index.html │ │ └── index.js ├── _locales │ ├── ko │ │ └── messages.json │ ├── tr │ │ └── messages.json │ ├── en │ │ └── messages.json │ └── pt_BR │ │ └── messages.json ├── manifest.json ├── badge.js └── config.js ├── imgs ├── one.xcf └── two.xcf ├── test ├── example.txt ├── popup-blocker-iframe.html └── blocking-ui.html ├── .github └── FUNDING.yml └── README.md /v2/LICENSE: -------------------------------------------------------------------------------- 1 | ../../LICENSE -------------------------------------------------------------------------------- /v3/data/inject/test.js: -------------------------------------------------------------------------------- 1 | console.info('testing script'); 2 | -------------------------------------------------------------------------------- /imgs/one.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/imgs/one.xcf -------------------------------------------------------------------------------- /imgs/two.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/imgs/two.xcf -------------------------------------------------------------------------------- /v2/data/icons/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/16.png -------------------------------------------------------------------------------- /v2/data/icons/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/32.png -------------------------------------------------------------------------------- /v2/data/icons/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/48.png -------------------------------------------------------------------------------- /v2/data/icons/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/64.png -------------------------------------------------------------------------------- /v3/data/icons/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/16.png -------------------------------------------------------------------------------- /v3/data/icons/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/32.png -------------------------------------------------------------------------------- /v3/data/icons/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/48.png -------------------------------------------------------------------------------- /v3/data/icons/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/64.png -------------------------------------------------------------------------------- /v2/data/icons/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/128.png -------------------------------------------------------------------------------- /v2/data/icons/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/256.png -------------------------------------------------------------------------------- /v2/data/icons/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/512.png -------------------------------------------------------------------------------- /v3/data/icons/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/128.png -------------------------------------------------------------------------------- /v3/data/icons/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/256.png -------------------------------------------------------------------------------- /v3/data/icons/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/512.png -------------------------------------------------------------------------------- /v2/data/icons/disabled/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/disabled/16.png -------------------------------------------------------------------------------- /v2/data/icons/disabled/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/disabled/32.png -------------------------------------------------------------------------------- /v2/data/icons/state/1/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/state/1/16.png -------------------------------------------------------------------------------- /v2/data/icons/state/1/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/state/1/32.png -------------------------------------------------------------------------------- /v2/data/icons/state/2/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/state/2/16.png -------------------------------------------------------------------------------- /v2/data/icons/state/2/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/state/2/32.png -------------------------------------------------------------------------------- /v2/data/icons/state/3/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/state/3/16.png -------------------------------------------------------------------------------- /v2/data/icons/state/3/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/state/3/32.png -------------------------------------------------------------------------------- /v2/data/icons/state/4/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/state/4/16.png -------------------------------------------------------------------------------- /v2/data/icons/state/4/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v2/data/icons/state/4/32.png -------------------------------------------------------------------------------- /v3/data/icons/state/0/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/state/0/16.png -------------------------------------------------------------------------------- /v3/data/icons/state/0/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/state/0/32.png -------------------------------------------------------------------------------- /v3/data/icons/state/1/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/state/1/16.png -------------------------------------------------------------------------------- /v3/data/icons/state/1/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/state/1/32.png -------------------------------------------------------------------------------- /v3/data/icons/state/2/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/state/2/16.png -------------------------------------------------------------------------------- /v3/data/icons/state/2/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/state/2/32.png -------------------------------------------------------------------------------- /v3/data/icons/state/3/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/state/3/16.png -------------------------------------------------------------------------------- /v3/data/icons/state/3/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/state/3/32.png -------------------------------------------------------------------------------- /v3/data/icons/state/4/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/state/4/16.png -------------------------------------------------------------------------------- /v3/data/icons/state/4/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schomery/popup-blocker/HEAD/v3/data/icons/state/4/32.png -------------------------------------------------------------------------------- /v3/data/inject/disabled.js: -------------------------------------------------------------------------------- 1 | chrome.runtime.sendMessage({ 2 | 'cmd': 'state', 3 | 'active': false 4 | }); 5 | 6 | -------------------------------------------------------------------------------- /v3/_locales/ko/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_description": { 3 | "message": "웹사이트의 모든 팝업 요청을 엄격하게 차단하십시오." 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /v2/actions/disabled.js: -------------------------------------------------------------------------------- 1 | /* global prefs */ 2 | 3 | window.enabled = false; 4 | 5 | if (typeof prefs === 'object') { 6 | prefs.enabled = window.enabled; 7 | } 8 | -------------------------------------------------------------------------------- /v3/data/popup/ReadMe: -------------------------------------------------------------------------------- 1 | tld.js (MD5 = 2cffb104667a9f2ba4f78999907178a3) 2 | 3 | https://cdn.jsdelivr.net/npm/tldjs@2.3.1/tld.js 4 | 5 | Manual verification 6 | npm install tldjs@2.3.1 7 | md5 ./node_modules/tldjs/tld.js 8 | -------------------------------------------------------------------------------- /v2/actions/enabled.js: -------------------------------------------------------------------------------- 1 | /* global prefs */ 2 | 3 | if (!('enabled' in window)) { // in case disabled.js is called first 4 | window.enabled = true; 5 | } 6 | 7 | if (typeof prefs === 'object') { 8 | prefs.enabled = window.enabled; 9 | } 10 | -------------------------------------------------------------------------------- /v3/data/popup/health.js: -------------------------------------------------------------------------------- 1 | const check = () => { 2 | if (confirm(chrome.i18n.getMessage('pp_health'))) { 3 | chrome.runtime.reload(); 4 | } 5 | }; 6 | check.id = setTimeout(check, 2000); 7 | 8 | chrome.runtime.sendMessage({ 9 | method: 'echo' 10 | }, r => { 11 | if (r) { 12 | clearTimeout(check.id); 13 | console.info('health check passed'); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /v2/data/inject/ff.js: -------------------------------------------------------------------------------- 1 | // Firefox issue; document.activeElement is always 2 | 3 | let activeElement = document.documentElement; 4 | 5 | document.addEventListener('click', e => activeElement = e.target, true); 6 | 7 | Object.defineProperty(document, 'activeElement', { 8 | get() { 9 | return activeElement; 10 | } 11 | }); 12 | 13 | window.isFirefox = /Firefox/.test(navigator.userAgent) || typeof InstallTrigger !== 'undefined'; 14 | -------------------------------------------------------------------------------- /v3/data/inject/block/isolated.css: -------------------------------------------------------------------------------- 1 | @layer { 2 | iframe.pp-blocker { 3 | all: initial; 4 | z-index: calc(infinity) !important; 5 | color-scheme: light !important; 6 | position: fixed !important; 7 | width: var(--width, 420px) !important; 8 | max-width: 80vw !important; 9 | height: var(--height, 65px) !important; 10 | background: transparent !important; 11 | border-radius: 0 !important; 12 | border: none !important; 13 | } 14 | 15 | #ppop-port { 16 | display: none; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/example.txt: -------------------------------------------------------------------------------- 1 | 1. https://andrewgillum.com/news/ -> Sharing buttons 2 | 2. https://andrewgillum.com/2018/08/statement-dolores-huerta-labor-civil-rights-womens-icon-endorses-andrew-gillum/ 3 | -> refresh to get "https://www.facebook.com/tr/" and "https://syndication.twitter.com/i/jot" popup requests; the base is set so the popups are ignored 4 | 3. https://www.virustotal.com/ 5 | -> Check a text file 6 | 4. https://apps.facebook.com/criminalcase -> should allow target 7 | 5. http://www.tagindex.net/html/frame/example_t04.html -> should allow target 8 | 6. https://sadd.io/ 9 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: webextension?product=popup-blocker 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | thanks_dev: # Replace with a single thanks.dev username 15 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 16 | -------------------------------------------------------------------------------- /test/popup-blocker-iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 34 | 35 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /v2/data/ui/ui.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /v2/config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const config = window.config = { 4 | 'enabled': true, 5 | 'numbers': 5, 6 | 'timeout': 30, 7 | 'countdown': 5, 8 | 'default-action': 'ignore', 9 | 'immediate-action': false, 10 | 'simulate-allow': true, 11 | 'aggressive': false, 12 | 'wot': false, 13 | 'domain': false, // allow popups from the same domain 14 | 'badge': true, 15 | 'badge-color': '#6e6e6e', 16 | 'whitelist-mode': 'popup-hosts', 17 | // the following hostnames can issue popup on every website 18 | 'popup-hosts': [ 19 | 'google.com', 'bing.com', 't.co', 'twitter.com', 'disqus.com', 'login.yahoo.com', 20 | 'mail.google.com', 'doubleclick.net' 21 | ], 22 | // popup blocker is disabled in the following hostname tabs 23 | 'top-hosts': ['github.com', 'twitter.com', 'webextension.org', 'google.com', 'www.paypal.com'], 24 | // these protocols are accepted 25 | 'protocols': ['magnet:'], 26 | 'blacklist': [], 27 | 'silent': [], 28 | 'issue': true, 29 | 'block-page-redirection': false, 30 | 'target': true, 31 | 'version': null, 32 | 'faqs': true, 33 | 'last-update': 0 34 | }; 35 | 36 | config.get = arr => new Promise(resolve => { 37 | const ps = arr.reduce((p, c) => { 38 | p[c] = config[c]; 39 | return p; 40 | }, {}); 41 | chrome.storage.local.get(ps, resolve); 42 | }); 43 | -------------------------------------------------------------------------------- /v3/data/ui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /v2/data/popup/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 | 25 | 26 |

27 | 28 |
29 | 30 | 31 | 32 | 33 |
34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /v2/data/ui/wot.js: -------------------------------------------------------------------------------- 1 | /* globals doTimer */ 2 | 'use strict'; 3 | 4 | var wot = { 5 | check: (url, hostname) => { 6 | if (!url || !url.startsWith('http')) { 7 | return Promise.reject(); 8 | } 9 | return new Promise(resolve => chrome.runtime.sendMessage({ 10 | cmd: 'wot', 11 | url, 12 | hostname 13 | }, r => { 14 | try { 15 | // https://www.mywot.com/wiki/API 16 | resolve(r); 17 | } 18 | catch (e) { 19 | resolve(-1); 20 | } 21 | })); 22 | }, 23 | perform: (div, prefs, url, hostname, countdown) => { 24 | const sw = document.createElement('span'); 25 | sw.textContent = 'Reputation Check'; 26 | sw.classList.add('ppblocker-wot'); 27 | div.appendChild(sw); 28 | wot.check(url, hostname).then(r => { 29 | if (r === -1) { 30 | sw.textContent = '[Unknown]'; 31 | } 32 | else if (r >= 80) { 33 | sw.textContent = '[Excellent]'; 34 | } 35 | else if (r >= 60) { 36 | sw.textContent = '[Good]'; 37 | } 38 | else if (r >= 40) { 39 | sw.textContent = '[Unsatisfactory]'; 40 | } 41 | else { 42 | sw.textContent = '[Poor]'; 43 | } 44 | 45 | if (r >= 60) { 46 | const button = div.querySelector( 47 | prefs['simulate-allow'] ? '[data-cmd="popup-accepted"]' : '[data-cmd="open-tab"]' 48 | ); 49 | doTimer(div, button, countdown); 50 | } 51 | }).catch(() => {}); 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /v2/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Popup Blocker (strict)", 3 | "description": "__MSG_app_description__", 4 | "version": "0.7.1", 5 | "manifest_version": 2, 6 | "default_locale": "en", 7 | "permissions": [ 8 | "storage", 9 | "" 10 | ], 11 | "background": { 12 | "scripts": [ 13 | "config.js", 14 | "common.js" 15 | ] 16 | }, 17 | "browser_action": { 18 | "default_popup": "data/popup/index.html" 19 | }, 20 | "content_scripts": [{ 21 | "matches": [""], 22 | "js": ["data/inject/iframe.js"], 23 | "run_at": "document_start", 24 | "all_frames": false 25 | }], 26 | "homepage_url": "https://webextension.org/listing/popup-blocker.html", 27 | "icons": { 28 | "16": "data/icons/16.png", 29 | "32": "data/icons/32.png", 30 | "48": "data/icons/48.png", 31 | "64": "data/icons/64.png", 32 | "128": "data/icons/128.png", 33 | "256": "data/icons/256.png", 34 | "512": "data/icons/512.png" 35 | }, 36 | "options_ui": { 37 | "page": "data/options/index.html", 38 | "chrome_style": true, 39 | "open_in_tab": true 40 | }, 41 | "web_accessible_resources": [ 42 | "data/ui/*" 43 | ], 44 | "commands": { 45 | "allow-last-request": { 46 | "description": "__MSG_context_item2__" 47 | }, 48 | "deny-last-request": { 49 | "description": "__MSG_context_item3__" 50 | } 51 | }, 52 | "applications": { 53 | "gecko": { 54 | "id": "{de22fd49-c9ab-4359-b722-b3febdc3a0b0}" 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /v2/data/popup/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --bg: #fff; 3 | --clr: #4d5156; 4 | --dark: #d9d9d9; 5 | --button: #f0f0f0; 6 | --border: rgba(128, 128, 128, 0.2); 7 | } 8 | @media (prefers-color-scheme: dark) { 9 | :root { 10 | color-scheme: dark; 11 | 12 | --bg: #35363a; 13 | --clr: #b1b1b1; 14 | --dark: #202124; 15 | --button: #202124; 16 | } 17 | } 18 | 19 | body { 20 | font-size: 13px; 21 | font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; 22 | width: 400px; 23 | color: var(--clr); 24 | background-color: var(--bg); 25 | margin: 0; 26 | } 27 | hr { 28 | border: none; 29 | border-bottom: solid 1px var(--border); 30 | } 31 | .button { 32 | color: var(--clr); 33 | background-color: var(--button); 34 | text-align: center; 35 | border: none; 36 | padding: 5px 10px; 37 | min-width: 80px; 38 | cursor: pointer; 39 | position: relative; 40 | } 41 | .button:not(:last-child)::after { 42 | content: ''; 43 | position: absolute; 44 | right: 0; 45 | width: 1px; 46 | height: 14px; 47 | background-color: var(--border); 48 | } 49 | 50 | input.disabled, 51 | input:disabled { 52 | opacity: 0.2; 53 | pointer-events: none; 54 | } 55 | p { 56 | padding: 0 10px; 57 | } 58 | .col2 { 59 | display: grid; 60 | grid-gap: 5px 0; 61 | grid-template-columns: 1fr min-content; 62 | } 63 | .col3 { 64 | display: grid; 65 | grid-template-columns: 1fr min-content min-content; 66 | } 67 | .spc { 68 | display: grid; 69 | grid-template-columns: repeat(4, 1fr); 70 | } 71 | .spc > span { 72 | padding: 10px; 73 | min-width: unset; 74 | } 75 | -------------------------------------------------------------------------------- /v3/data/popup/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --bg: #fff; 3 | --clr: #4d5156; 4 | --dark: #d9d9d9; 5 | --button: #f0f0f0; 6 | --border: rgba(128, 128, 128, 0.2); 7 | --blue: #0374ff; 8 | } 9 | 10 | @media (prefers-color-scheme: dark) { 11 | :root { 12 | color-scheme: dark; 13 | 14 | --bg: #35363a; 15 | --clr: #b1b1b1; 16 | --dark: #202124; 17 | --button: #202124; 18 | --blue: #9ac8ff; 19 | } 20 | } 21 | 22 | body { 23 | font-size: 13px; 24 | font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; 25 | width: 400px; 26 | color: var(--clr); 27 | background-color: var(--bg); 28 | margin: 0; 29 | } 30 | hr { 31 | border: none; 32 | border-bottom: solid 1px var(--border); 33 | } 34 | a { 35 | text-decoration: none; 36 | color: var(--blue); 37 | } 38 | .button { 39 | color: var(--clr); 40 | background-color: var(--button); 41 | text-align: center; 42 | border: none; 43 | padding: 5px 10px; 44 | min-width: 80px; 45 | cursor: pointer; 46 | position: relative; 47 | } 48 | .button:not(:last-child)::after { 49 | content: ''; 50 | position: absolute; 51 | right: 0; 52 | width: 1px; 53 | height: 14px; 54 | background-color: var(--border); 55 | } 56 | 57 | input.disabled, 58 | input:disabled { 59 | opacity: 0.5; 60 | pointer-events: none; 61 | } 62 | p { 63 | padding: 0 10px; 64 | } 65 | .col2 { 66 | display: grid; 67 | grid-gap: 5px 0; 68 | grid-template-columns: 1fr min-content; 69 | } 70 | .col3 { 71 | display: grid; 72 | grid-template-columns: 1fr min-content min-content; 73 | } 74 | .spc { 75 | display: grid; 76 | grid-template-columns: repeat(4, 1fr); 77 | } 78 | .spc > span { 79 | padding: 10px; 80 | min-width: unset; 81 | } 82 | -------------------------------------------------------------------------------- /v2/data/options/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: "Helvetica Neue", Helvetica, sans-serif; 3 | font-size: 13px; 4 | max-width: 80%; 5 | margin: 10px auto; 6 | } 7 | @media screen and (max-width: 600px) { 8 | body { 9 | margin: 10px; 10 | max-width: unset; 11 | } 12 | } 13 | @supports (-moz-appearance:none) { 14 | body { 15 | font-size: 13px; 16 | font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; 17 | margin: 15px; 18 | } 19 | button, 20 | input[type=submit], 21 | input[type=button] { 22 | height: 24px; 23 | color: rgb(68, 68, 68); 24 | background-image: linear-gradient(rgb(237, 237, 237), rgb(237, 237, 237) 38%, rgb(222, 222, 222)); 25 | box-shadow: rgba(0, 0, 0, 0.08) 0 1px 0, rgba(255, 255, 255, 0.75) 0 1px 2px inset; 26 | text-shadow: rgb(240, 240, 240) 0 1px 0; 27 | border: solid 1px rgba(0, 0, 0, 0.25); 28 | } 29 | } 30 | input[type=number] { 31 | width: 50px; 32 | } 33 | textarea, 34 | input[type=text] { 35 | width: 100%; 36 | box-sizing: border-box; 37 | } 38 | label[for=wot], 39 | input:disabled, 40 | textarea:disabled { 41 | opacity: 0.6 !important; 42 | } 43 | hr { 44 | margin: 10px 0; 45 | border: none; 46 | height: 1px; 47 | border-bottom: dashed 1px #ccc; 48 | } 49 | summary { 50 | outline: none; 51 | } 52 | a { 53 | text-decoration: none; 54 | cursor: pointer; 55 | } 56 | #status { 57 | margin-right: 10px; 58 | display: flex; 59 | align-items: center; 60 | justify-content: center; 61 | } 62 | .rtl td:last-child { 63 | text-align: right; 64 | } 65 | .checks { 66 | display: grid; 67 | grid-template-columns: 32px 1fr; 68 | grid-gap: 5px; 69 | align-items: center; 70 | } 71 | 72 | label[for="wot"] { 73 | text-decoration: line-through; 74 | } 75 | -------------------------------------------------------------------------------- /v3/data/popup/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

10 | 11 | 12 | 13 | 14 | 18 | 19 |

20 |
21 |

22 | 23 | 24 | 25 |

26 |

27 | 28 | 29 | 32 | 33 | 36 | 37 |

38 | 39 |
40 | 41 | 42 | 43 | 44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /v3/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Popup Blocker (strict)", 3 | "description": "__MSG_app_description__", 4 | "version": "0.9.0", 5 | "manifest_version": 3, 6 | "default_locale": "en", 7 | "permissions": [ 8 | "storage", 9 | "scripting" 10 | ], 11 | "host_permissions": [ 12 | "" 13 | ], 14 | "background": { 15 | "service_worker": "worker.js", 16 | "scripts": [ 17 | "config.js", 18 | "badge.js", 19 | "worker.js" 20 | ] 21 | }, 22 | "action": { 23 | "default_popup": "/data/popup/index.html" 24 | }, 25 | "homepage_url": "https://webextension.org/listing/popup-blocker.html", 26 | "icons": { 27 | "16": "/data/icons/16.png", 28 | "32": "/data/icons/32.png", 29 | "48": "/data/icons/48.png", 30 | "64": "/data/icons/64.png", 31 | "128": "/data/icons/128.png", 32 | "256": "/data/icons/256.png", 33 | "512": "/data/icons/512.png" 34 | }, 35 | "options_ui": { 36 | "page": "/data/options/index.html", 37 | "open_in_tab": true 38 | }, 39 | "web_accessible_resources": [{ 40 | "resources": ["data/ui/index.html"], 41 | "matches": ["*://*/*"] 42 | }], 43 | "commands": { 44 | "_execute_action": { 45 | "description": "Execute Action" 46 | }, 47 | "allow-last-request": { 48 | "description": "__MSG_context_item2__" 49 | }, 50 | "deny-last-request": { 51 | "description": "__MSG_context_item3__" 52 | }, 53 | "background-last-request": { 54 | "description": "__MSG_context_item4__" 55 | }, 56 | "redirect-last-request": { 57 | "description": "__MSG_context_item5__" 58 | }, 59 | "focus-last-request": { 60 | "description": "__MSG_context_item6__" 61 | } 62 | }, 63 | "browser_specific_settings": { 64 | "gecko": { 65 | "id": "{de22fd49-c9ab-4359-b722-b3febdc3a0b0}", 66 | "strict_min_version": "128.0" 67 | }, 68 | "gecko_android": { 69 | "strict_min_version": "128.0" 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /v3/data/options/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --border: solid 1px rgba(0, 0, 0, 0.25); 3 | } 4 | 5 | body { 6 | font-family: "Helvetica Neue", Helvetica, sans-serif; 7 | font-size: 13px; 8 | margin: 10px auto; 9 | width: min(800px, 100% - 2rem); 10 | } 11 | select, 12 | button, 13 | input[type=submit], 14 | input[type=button] { 15 | height: 28px; 16 | color: rgb(68, 68, 68); 17 | background-image: linear-gradient(rgb(237, 237, 237), rgb(237, 237, 237) 38%, rgb(222, 222, 222)); 18 | box-shadow: rgba(0, 0, 0, 0.08) 0 1px 0, rgba(255, 255, 255, 0.75) 0 1px 2px inset; 19 | text-shadow: rgb(240, 240, 240) 0 1px 0; 20 | } 21 | select, 22 | textarea, 23 | button, 24 | input[type=number], 25 | input[type=text] { 26 | font-size: inherit; 27 | border: var(--border); 28 | } 29 | input[type=number] { 30 | width: 50px; 31 | padding: 2px 5px; 32 | } 33 | textarea, 34 | input[type=text] { 35 | width: 100%; 36 | box-sizing: border-box; 37 | } 38 | label[for=wot], 39 | input:disabled, 40 | textarea:disabled { 41 | opacity: 0.6 !important; 42 | } 43 | textarea { 44 | padding: 5px; 45 | margin-top: 2px; 46 | } 47 | hr { 48 | margin: 10px 0; 49 | border: none; 50 | height: 1px; 51 | border-bottom: dashed 1px #ccc; 52 | } 53 | summary { 54 | outline: none; 55 | } 56 | a { 57 | text-decoration: none; 58 | cursor: pointer; 59 | color: #0074cc; 60 | } 61 | h1 { 62 | font-size: 1.1rem; 63 | } 64 | #status { 65 | margin-right: 10px; 66 | display: flex; 67 | align-items: center; 68 | justify-content: center; 69 | } 70 | .rtl td:last-child { 71 | text-align: right; 72 | } 73 | .checks { 74 | display: grid; 75 | grid-template-columns: 32px 1fr; 76 | grid-gap: 5px; 77 | align-items: center; 78 | } 79 | 80 | label[for="wot"] { 81 | text-decoration: line-through; 82 | } 83 | 84 | .bc { 85 | display: flex; 86 | gap: 5px; 87 | } 88 | 89 | .ngx { 90 | display: grid; 91 | grid-template-columns: 1fr 1fr; 92 | grid-gap: 10px; 93 | padding-block: 5px; 94 | 95 | label { 96 | display: flex; 97 | align-items: center; 98 | } 99 | :last-child { 100 | justify-self: end; 101 | } 102 | } 103 | 104 | @supports (-webkit-hyphens: none) and (not (-moz-appearance: none)) { 105 | #support { 106 | display: none; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /v2/data/inject/iframe.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | { 4 | let iframe; 5 | let requests = []; 6 | let ready = false; 7 | chrome.runtime.onMessage.addListener((request, sender) => { 8 | if (request.cmd === 'popup-request') { 9 | if (ready === false || !iframe) { 10 | // only accept requests from bg page 11 | if (request.cmd === 'popup-request' && !sender.tab) { 12 | requests.push(request); 13 | } 14 | } 15 | if (!iframe) { 16 | iframe = document.createElement('iframe'); 17 | iframe.src = chrome.runtime.getURL('data/ui/ui.html?parent=' + encodeURIComponent(location.href)); 18 | iframe.onload = () => { 19 | iframe.contentWindow.postMessage({ 20 | method: 'popup-caches', 21 | requests 22 | }, '*'); 23 | requests = []; 24 | ready = true; 25 | }; 26 | iframe.setAttribute('style', ` 27 | z-index: 2147483649 !important; 28 | color-scheme: light !important; 29 | position: fixed !important; 30 | right: 10px !important; 31 | top: 10px !important; 32 | width: 420px !important; 33 | max-width: 80vw !important; 34 | height: 85px !important; 35 | border: none !important; 36 | background: transparent !important; 37 | border-radius: 0 !important; 38 | `); 39 | // do not attach to body to make sure the notification is visible 40 | document.documentElement.appendChild(iframe); 41 | } 42 | // always reattach to make sure the iframe is accessible 43 | if (document.elementsFromPoint) { // Edge does not support elementsFromPoint 44 | const es = document.elementsFromPoint(iframe.offsetLeft, iframe.offsetTop); 45 | const index = es.indexOf(iframe); 46 | if (index !== 0) { 47 | // this is going to refresh the iframe 48 | document.body.appendChild(iframe); 49 | } 50 | } 51 | } 52 | }); 53 | window.addEventListener('message', e => { 54 | const request = e.data; 55 | if (request && request.method === 'ppp-resize') { 56 | e.preventDefault(); 57 | e.stopPropagation(); 58 | if (request.hide) { 59 | iframe.remove(); 60 | iframe = null; 61 | } 62 | else { 63 | iframe.style.height = request.height + 'px'; 64 | } 65 | } 66 | }); 67 | } 68 | -------------------------------------------------------------------------------- /v2/_locales/zh_CN/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_description": { 3 | "message": "严格拦截任何网站的所有弹窗请求" 4 | }, 5 | "context_item1": { 6 | "message": "测试您的弹窗拦截器" 7 | }, 8 | "context_item2": { 9 | "message": "允许最后的弹窗请求" 10 | }, 11 | "context_item3": { 12 | "message": "拒绝最后的弹窗请求" 13 | }, 14 | "context_item4": { 15 | "message": "在弹出请求上创建阴影窗口" 16 | }, 17 | "options_item1": { 18 | "message": "单个页面最多请求多少弹窗" 19 | }, 20 | "options_item2": { 21 | "message": "每个弹窗请求的显示超时(秒)" 22 | }, 23 | "options_item3": { 24 | "message": "不拦截同源的弹窗请求" 25 | }, 26 | "options_item4": { 27 | "message": "阻止在新标签页打开链接" 28 | }, 29 | "options_item5": { 30 | "message": "工具栏图标上显示已拦截请求总量" 31 | }, 32 | "options_item6": { 33 | "message": "白名单目的地:" 34 | }, 35 | "options_item7": { 36 | "message": "白名单源网站:" 37 | }, 38 | "options_item8": { 39 | "message": "需要刷新标签页" 40 | }, 41 | "options_item9": { 42 | "message": "执行上次动作的倒计时(秒)" 43 | }, 44 | "options_item10": { 45 | "message": "使用 0 禁用倒计时" 46 | }, 47 | "options_item11": { 48 | "message": "逗号分隔不拦截的域名列表(任何网站都可以弹出这些域的窗口)" 49 | }, 50 | "options_item12": { 51 | "message": "逗号分隔不处理的域名列表(弹窗拦截器不在这些域上运行)" 52 | }, 53 | "options_item13": { 54 | "message": "黑名单源网站:" 55 | }, 56 | "options_item14": { 57 | "message": "逗号分隔域名列表,弹窗拦截器只在这些域上显示。这意味着其他域上不使用弹窗拦截器。" 58 | }, 59 | "options_item15": { 60 | "message": "一个弹窗请求后,阻止页面在 2 秒内重定向" 61 | }, 62 | "options_item16": { 63 | "message": "在某些网站上,如果弹窗广告被拦截,则页面被重定向到另一页面。此选项可以在重定向前发出提醒,您可阻止此操作。" 64 | }, 65 | "options_item17": { 66 | "message": "弹窗请求时的默认操作" 67 | }, 68 | "options_item18": { 69 | "message": "无动作" 70 | }, 71 | "options_item19": { 72 | "message": "拒绝请求" 73 | }, 74 | "options_item20": { 75 | "message": "在后台打开" 76 | }, 77 | "options_item21": { 78 | "message": "重定向页面" 79 | }, 80 | "options_item22": { 81 | "message": "徽章背景色" 82 | }, 83 | "options_item23": { 84 | "message": "可能时忽略弹窗通知(不推荐)" 85 | }, 86 | "options_item24": { 87 | "message": "没有用户交互时,这将“忽略”或“接受”一个弹窗(不推荐)" 88 | }, 89 | "options_item25": { 90 | "message": "说明" 91 | }, 92 | "options_item26": { 93 | "message": "更新后打开 FAQ 页面" 94 | }, 95 | "options_save": { 96 | "message": "保存设置" 97 | }, 98 | "options_msg": { 99 | "message": "选项已保存" 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /v2/data/ui/ui.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: "Helvetica Neue",Helvetica,sans-serif; 4 | font-size: 12px; 5 | overflow: hidden; 6 | } 7 | 8 | input[type=button] { 9 | border: solid 1px #999; 10 | background-color: #fff; 11 | color: #000; 12 | font-size: 10px; 13 | margin: 0 3px; 14 | cursor: pointer; 15 | padding: 2px 6px; 16 | border-radius: 0; 17 | line-height: 20px; 18 | outline: none; 19 | } 20 | input[type=button][data-default=true] { 21 | font-weight: 500; 22 | } 23 | input[type=button][data-cmd="popup-close"] { 24 | position: absolute; 25 | top: 0; 26 | right: 0; 27 | background: none; 28 | border: none; 29 | font-size: 14px; 30 | } 31 | 32 | .ppblocker-div { 33 | position: relative; 34 | text-shadow: none; 35 | box-sizing: content-box; 36 | border: solid 1px #cebc7d; 37 | background-color: #f4e1a7; 38 | color: #000; 39 | padding: 5px; 40 | margin: 8px 8px 5px 0; 41 | display: flex; 42 | flex-direction: column; 43 | border-radius: 2px; 44 | box-shadow: 1px 1px 5px rgb(206,188,125); 45 | } 46 | .ppblocker-div>div { 47 | display: flex; 48 | justify-content: flex-end; 49 | } 50 | .ppblocker-div>div>span { 51 | display: flex; 52 | flex: 1; 53 | } 54 | .ppblocker-div>p:first-of-type { 55 | font-weight: 500; 56 | font-size: 13px; 57 | margin: 0; 58 | padding: 0; 59 | user-select: none; 60 | } 61 | .ppblocker-div>p:last-of-type { 62 | white-space: nowrap; 63 | overflow: hidden; 64 | text-overflow: ellipsis; 65 | margin: 0; 66 | padding: 0; 67 | line-height: 32px; 68 | } 69 | .ppblocker-div::before { 70 | content: attr(data-badge); 71 | position: absolute; 72 | top: -8px; 73 | right: -8px; 74 | border: solid 2px #fff; 75 | border-radius: 50%; 76 | background-color: #fc0d1b; 77 | color: #000; 78 | color: #fff; 79 | width: 16px; 80 | height: 16px; 81 | display: flex; 82 | align-items: center; 83 | justify-content: center; 84 | font-size: 80%; 85 | } 86 | .ppblocker-div[data-badge="1"]::before { 87 | display: none; 88 | } 89 | .ppblocker-div:not([data-page=true]) [data-cmd="white-list"], 90 | .ppblocker-div:not([data-page=true]) [data-cmd="popup-redirect"], 91 | .ppblocker-div:not([data-page=true]) [data-cmd="open-tab"] { 92 | display: none; 93 | } 94 | 95 | .ppblocker-wot { 96 | position: absolute; 97 | top: 6px; 98 | right: 25px; 99 | 100 | display: flex; 101 | align-items: center; 102 | justify-content: center; 103 | font-size: 80%; 104 | } 105 | -------------------------------------------------------------------------------- /test/blocking-ui.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Annoying popup 6 | 70 | 71 | 72 | You want to click me 73 | 74 | 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## ![img](https://raw.githubusercontent.com/schomery/popup-blocker/fe2d5bc0a03a69411520ce79c79f57c8195be077/v3/data/icons/32.png) Popup Blocker (strict) 2 | 3 | The "Popup Blocker (strict)" is a lightweight browser extension designed to prevent the opening of popup windows on websites. Unlike other popup blockers, this extension doesn't wait to block popups after they appear; instead, it intercepts and blocks them as soon as they are requested. This extension puts a halt to all requests for new windows, requiring your input to either permit or deny each request. Multiple distinct requests are presented in a list, and if a website makes repeated requests to a specific URL, a badge number will display, indicating the total number of requests for that particular web address. 4 | 5 | ### Preview 6 | 7 | [![Preview](https://img.youtube.com/vi/Jp-RaiTHzCQ/0.jpg)](https://www.youtube.com/watch?v=Jp-RaiTHzCQ) 8 | 9 | ### Features 10 | 11 | * Popup blockage triggered by the window.open method 12 | * Popup prevention through the about:blank linking technique 13 | * Previewing popup links via a notification box 14 | 15 | ### Actions 16 | 17 | 1. Deny popup request 18 | 2. Allow popup request 19 | 3. Open popup request in a background tab 20 | 4. Redirect current page to popup URL source 21 | 22 | ### Supported blocking methods: 23 | 1. `window.open` 24 | 2. `a->target=_blank` 25 | 3. Form submission 26 | 27 | ### Installation 28 | 29 | Install the latest version from your browser official store: 30 | 31 | | Browser | Address | 32 | |---|---| 33 | | Chromium / Google Chrome | https://chrome.google.com/webstore/detail/popup-blocker-strict/aefkmifgmaafnojlojpnekbpbmjiiogg | 34 | | Microsoft Edge | https://www.microsoft.com/store/p/popup-blocker/9ng26z2368n6 | 35 | | Firefox / Firefox for Android | https://addons.mozilla.org/firefox/addon/popup-blocker/ | 36 | | Opera | https://addons.opera.com/extensions/details/popup-blocker-ultimate/ | 37 | 38 | ### Links 39 | 40 | * FAQs Page: https://webextension.org/listing/popup-blocker.html 41 | * Test Page: https://webbrowsertools.com/popup-blocker/ 42 | 43 | ### Screenshot 44 | 45 | ![img](https://addons.mozilla.org/user-media/previews/full/179/179585.png) 46 | 47 | ### Make a Donation 48 | 49 | If this project help you, you can give the developer a cup of coffee :) 50 | 51 | * PayPal 52 | 53 | [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=inbasic%2ecorp%40gmail%2ecom&lc=CA&item_name=support%20extension%20development¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted) 54 | 55 | * Bitcoin Address: 56 | 57 | bc1qh7juzrxrawpr65elm4qs285m5rdhnhgsn7h2jf 58 | 59 | ### Help with Translation 60 | 61 | You can now translate Popup Blocker (strict) into your language; https://www.transifex.com/github-7/popup-blocker-strict/ 62 | 63 | ### License 64 | 65 | Popup Blocker (strict) is an open-source project released under [MPL-2.0](https://github.com/schomery/popup-blocker/blob/master/LICENSE) 66 | -------------------------------------------------------------------------------- /v3/data/ui/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --gap: 5px; 3 | --fg: #000; 4 | --bg: #fff19d; 5 | --bd: #ebde8f; 6 | --bda: #ebb28f; 7 | } 8 | body { 9 | margin: 0; 10 | overflow: hidden; 11 | font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif; 12 | font-size: 13px; 13 | background-color: transparent; 14 | padding: 8px 8px 0 0; 15 | height: fit-content; 16 | } 17 | 18 | input[type=button] { 19 | color: var(--fg); 20 | border: none; 21 | padding: 5px; 22 | font-size: 11px; 23 | outline: none; 24 | cursor: pointer; 25 | background-color: white; 26 | } 27 | input[type=button]:focus { 28 | border-color: transparent; 29 | box-shadow: 0 0 0 2px var(--bda); 30 | z-index: 2; 31 | } 32 | input[type=button][data-default=true] { 33 | font-weight: 500; 34 | } 35 | #container { 36 | display: flex; 37 | flex-direction: column; 38 | } 39 | .ppblocker-div { 40 | position: relative; 41 | text-shadow: none; 42 | box-sizing: content-box; 43 | border-left: solid 5px var(--bd); 44 | background-color: var(--bg); 45 | color: var(--fg); 46 | padding: 5px; 47 | display: grid; 48 | grid-template-columns: 1fr; 49 | grid-gap: calc(var(--gap) * 2); 50 | outline: none; 51 | } 52 | .ppblocker-div:not(:last-child)::after { 53 | content: ''; 54 | height: 1px; 55 | background: #ebde8f; 56 | width: 95%; 57 | margin: auto; 58 | } 59 | .ppblocker-div:focus-within { 60 | border-left-color: var(--bda); 61 | } 62 | .ppblocker-div > div { 63 | display: grid; 64 | grid-template-columns: 1fr min-content; 65 | } 66 | .ppblocker-div > div > div { 67 | display: flex; 68 | gap: 1px; 69 | background-color: var(--bd); 70 | } 71 | .ppblocker-div > div > input[type=button]:first-of-type { 72 | justify-self: start; 73 | } 74 | .ppblocker-div > p { 75 | white-space: nowrap; 76 | overflow: hidden; 77 | text-overflow: ellipsis; 78 | margin: 0; 79 | padding: 0; 80 | } 81 | .ppblocker-div::before { 82 | content: attr(data-badge); 83 | position: absolute; 84 | top: -8px; 85 | right: -8px; 86 | border: solid 2px var(--bg); 87 | border-radius: 50%; 88 | background-color: #fc0d1b; 89 | color: #000; 90 | color: #fff; 91 | width: 16px; 92 | height: 16px; 93 | display: flex; 94 | align-items: center; 95 | justify-content: center; 96 | font-size: 80%; 97 | } 98 | .ppblocker-div[data-badge="1"]::before { 99 | display: none; 100 | } 101 | .ppblocker-div:not([data-page=true]) div { 102 | grid-template-columns: repeat(3, min-content); 103 | justify-content: end; 104 | } 105 | .ppblocker-div:not([data-page=true]) [data-cmd="white-list"], 106 | .ppblocker-div:not([data-page=true]) [data-cmd="popup-redirect"], 107 | .ppblocker-div:not([data-page=true]) [data-cmd="open-tab"] { 108 | display: none; 109 | } 110 | 111 | .ppblocker-wot { 112 | position: absolute; 113 | top: 6px; 114 | right: 25px; 115 | display: flex; 116 | align-items: center; 117 | justify-content: center; 118 | font-size: 80%; 119 | } 120 | -------------------------------------------------------------------------------- /v3/badge.js: -------------------------------------------------------------------------------- 1 | /* global config */ 2 | 3 | 4 | /* update global icon's state */ 5 | const icon = async () => { 6 | const prefs = await config.get(['enabled']); 7 | const path = { 8 | 16: 'data/icons/' + (prefs.enabled ? 'state/0/' : 'state/3/') + '16.png', 9 | 32: 'data/icons/' + (prefs.enabled ? 'state/0/' : 'state/3/') + '32.png' 10 | }; 11 | chrome.action.setIcon({ 12 | path 13 | }); 14 | const id = prefs.enabled ? 'bg_msg_state_0' : 'bg_msg_state_3'; 15 | chrome.action.setTitle({ 16 | title: chrome.i18n.getMessage(id) 17 | }); 18 | }; 19 | 20 | /* observe preference changes */ 21 | config.changed(prefs => { 22 | if (prefs.badge && prefs.badge.newValue === false) { 23 | chrome.tabs.query({}, tabs => tabs.forEach(tab => chrome.action.setBadgeText({ 24 | tabId: tab.id, 25 | text: '' 26 | }))); 27 | } 28 | // maybe multiple prefs changed 29 | if (prefs['badge-color']) { 30 | chrome.action.setBadgeBackgroundColor({ 31 | color: prefs['badge-color'].newValue 32 | }); 33 | } 34 | // 35 | if (prefs.enabled) { 36 | icon(); 37 | } 38 | }); 39 | 40 | chrome.runtime.onMessage.addListener((request, sender) => { 41 | // update badge counter 42 | if (request.cmd === 'popup-request') { 43 | const tabId = sender.tab.id; 44 | config.get(['badge']).then(({badge}) => { 45 | if (badge) { 46 | chrome.action.getBadgeText({tabId}, text => { 47 | if (text !== 'E') { 48 | text = text ? parseInt(text) : 0; 49 | text = String(text + 1); 50 | } 51 | chrome.action.setBadgeText({ 52 | tabId, 53 | text 54 | }); 55 | }); 56 | } 57 | }); 58 | } 59 | else if (request.cmd === 'state') { 60 | if (sender.tab) { 61 | config.get(['enabled']).then(({enabled}) => { 62 | let state = 4; 63 | if (enabled && request.active) { 64 | state = 1; 65 | } 66 | else if (enabled && request.active === false) { 67 | state = 2; 68 | } 69 | else if (enabled === false && request.active === false) { 70 | state = 3; 71 | } 72 | const path = { 73 | 16: 'data/icons/state/' + state + '/16.png', 74 | 32: 'data/icons/state/' + state + '/32.png' 75 | }; 76 | chrome.action.setIcon({ 77 | tabId: sender.tab.id, 78 | path 79 | }); 80 | chrome.action.setTitle({ 81 | tabId: sender.tab.id, 82 | title: chrome.i18n.getMessage('bg_msg_state_' + state) 83 | }); 84 | }); 85 | } 86 | } 87 | }); 88 | 89 | // on startup (run once) 90 | { 91 | const once = () => { 92 | // icon 93 | icon(); 94 | // badge color 95 | config.get(['badge-color']).then(prefs => chrome.action.setBadgeBackgroundColor({ 96 | color: prefs['badge-color'] 97 | })); 98 | }; 99 | chrome.runtime.onInstalled.addListener(once); 100 | chrome.runtime.onStartup.addListener(once); 101 | } 102 | -------------------------------------------------------------------------------- /v2/_locales/ko/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "options_item12": { 3 | "message": "쉼표로 구분된 팝업이 완벽히 차단된 호스트 이름의 목록", 4 | "description": "" 5 | }, 6 | "options_msg": { 7 | "message": "옵션이 저장 됨", 8 | "description": "" 9 | }, 10 | "options_item10": { 11 | "message": "카운트 다운을 비활성화 하려면 0을 입력", 12 | "description": "" 13 | }, 14 | "context_item1": { 15 | "message": "팝업 차단기 테스트", 16 | "description": "" 17 | }, 18 | "options_item3": { 19 | "message": "동일한 출처의 팝업 차단 요청을 차단하지 않음", 20 | "description": "" 21 | }, 22 | "options_item16": { 23 | "message": "일부 웹 사이트에서 팝업 광고가 차단되면 다른 페이지로 이동하게 됩니다. 이 옵션을 사용하면 다른 페이지로 이동 되기 전에 경고가 발생합니다.", 24 | "description": "" 25 | }, 26 | "options_item4": { 27 | "message": "새 탭에서 여는 링크 열기 차단", 28 | "description": "" 29 | }, 30 | "options_item15": { 31 | "message": "팝업을 요청한 페이지에서 2초간 다른 페이지로 전송 방지", 32 | "description": "" 33 | }, 34 | "app_description": { 35 | "message": "모든 웹 사이트의 팝업 요청을 엄격하게 차단합니다.", 36 | "description": "" 37 | }, 38 | "options_item19": { 39 | "message": "요청 거부", 40 | "description": "" 41 | }, 42 | "options_item9": { 43 | "message": "마지막 작업 수행을 위한 카운트 다운 (초 단위)", 44 | "description": "" 45 | }, 46 | "options_item2": { 47 | "message": "각 팝업의 표시 제한 시간(초 단위)", 48 | "description": "" 49 | }, 50 | "options_item7": { 51 | "message": "화이트 리스트(웹 페이지)", 52 | "description": "" 53 | }, 54 | "options_save": { 55 | "message": "설정 저장", 56 | "description": "" 57 | }, 58 | "options_item22": { 59 | "message": "배지 배경 색", 60 | "description": "" 61 | }, 62 | "options_item1": { 63 | "message": "한 페이지의 최대 팝업 요청 수", 64 | "description": "" 65 | }, 66 | "options_item17": { 67 | "message": "팝업이 요청 될 때의 기본 동작", 68 | "description": "" 69 | }, 70 | "options_item14": { 71 | "message": "140/5000\n쉼표로 구분 된 호스트 차단 목록으로, 팝업 차단기가 활성화되어 있어야 합니다. 즉, 다른 모든 도메인에서 팝업 차단을 사용할 수 없습니다.", 72 | "description": "" 73 | }, 74 | "options_item11": { 75 | "message": "쉼표로 구분된 차단되지 않은 팝업 호스트 이름 목록(이 도메인은 모든 웹 페이지에서 팝업을 생성할 수 있음)", 76 | "description": "" 77 | }, 78 | "options_item18": { 79 | "message": "아무 것도 안 함", 80 | "description": "" 81 | }, 82 | "options_item21": { 83 | "message": "페이지 다시 전송", 84 | "description": "" 85 | }, 86 | "options_item8": { 87 | "message": "탭을 새로 고쳐야 함", 88 | "description": "" 89 | }, 90 | "options_item13": { 91 | "message": "블랙 리스트(웹 페이지)", 92 | "description": "" 93 | }, 94 | "options_item5": { 95 | "message": "도구 모음 아이콘에 모든 차단된 요청의 수를 표시", 96 | "description": "" 97 | }, 98 | "options_item6": { 99 | "message": "화이트 리스트(팝업):", 100 | "description": "" 101 | }, 102 | "options_item20": { 103 | "message": "백그라운드에서 열기", 104 | "description": "" 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /v2/data/popup/index.js: -------------------------------------------------------------------------------- 1 | /* globals config */ 2 | 'use strict'; 3 | 4 | // localization 5 | [...document.querySelectorAll('[data-i18n]')].forEach(e => { 6 | if (e.tagName === 'INPUT') { 7 | e.value = chrome.i18n.getMessage(e.dataset.i18n); 8 | } 9 | else { 10 | e.textContent = chrome.i18n.getMessage(e.dataset.i18n); 11 | } 12 | }); 13 | 14 | // Global 15 | config.get(['enabled']).then(prefs => { 16 | document.getElementById('global').checked = prefs.enabled; 17 | if (prefs.enabled === false) { 18 | document.getElementById('page').disabled = true; 19 | } 20 | }); 21 | document.getElementById('global').onchange = e => { 22 | chrome.storage.local.set({ 23 | enabled: e.target.checked 24 | }); 25 | document.getElementById('page').disabled = e.target.checked === false; 26 | }; 27 | 28 | // This Page 29 | chrome.tabs.executeScript({ 30 | code: `({ 31 | enabled: typeof prefs === 'object' ? prefs.enabled : undefined, 32 | hostname: location.hostname 33 | })` 34 | }, async arr => { 35 | const lastError = chrome.runtime.lastError; 36 | if (lastError || arr[0] === undefined) { 37 | document.getElementById('page').disabled = true; 38 | // force disabled 39 | document.getElementById('page').classList.add('disabled'); 40 | } 41 | else { 42 | if (arr[0].enabled === true || arr[0].enabled === false) { 43 | document.getElementById('page').checked = arr[0].enabled; 44 | } 45 | else { 46 | const prefs = await config.get(['top-hosts']); 47 | document.getElementById('page').checked = 48 | prefs['top-hosts'].some(h => h === arr[0].hostname) ? false : true; 49 | } 50 | } 51 | }); 52 | document.getElementById('page').onchange = async e => { 53 | const prefs = await config.get(['top-hosts']); 54 | chrome.tabs.executeScript({ 55 | code: 'location.hostname' 56 | }, ([hostname]) => { 57 | if (e.target.checked) { 58 | const n = prefs['top-hosts'].indexOf(hostname); 59 | if (n !== -1) { 60 | prefs['top-hosts'].splice(n, 1); 61 | } 62 | } 63 | else { 64 | prefs['top-hosts'].push(hostname); 65 | prefs['top-hosts'] = prefs['top-hosts'].filter((s, i, l) => s && l.indexOf(s) === i); 66 | } 67 | chrome.storage.local.set(prefs, () => chrome.tabs.reload()); 68 | }); 69 | }; 70 | 71 | config.get(['immediate-action']).then(prefs => { 72 | document.getElementById('immediate-action').checked = prefs['immediate-action']; 73 | }); 74 | document.getElementById('immediate-action').onchange = e => chrome.storage.local.set({ 75 | 'immediate-action': e.target.checked 76 | }); 77 | 78 | config.get(['issue']).then(prefs => { 79 | document.getElementById('issue').checked = prefs.issue; 80 | }); 81 | document.getElementById('issue').onchange = e => chrome.storage.local.set({ 82 | 'issue': e.target.checked 83 | }); 84 | 85 | document.getElementById('test-page').onclick = () => chrome.tabs.create({ 86 | url: 'https://webbrowsertools.com/popup-blocker/' 87 | }); 88 | 89 | document.getElementById('homepage').onclick = () => chrome.tabs.create({ 90 | url: chrome.runtime.getManifest().homepage_url 91 | }); 92 | 93 | document.getElementById('options').onclick = () => chrome.runtime.openOptionsPage(); 94 | 95 | chrome.tabs.query({ 96 | currentWindow: true, 97 | active: true 98 | }, tabs => { 99 | if (tabs.length) { 100 | const tab = tabs[0]; 101 | document.getElementById('use-shadow').onclick = () => chrome.tabs.sendMessage(tab.id, { 102 | cmd: 'use-shadow' 103 | }, () => window.close()); 104 | 105 | document.getElementById('allow-last-request').onclick = () => chrome.tabs.sendMessage(tab.id, { 106 | cmd: 'allow-last-request' 107 | }, () => window.close()); 108 | 109 | document.getElementById('deny-last-request').onclick = () => chrome.tabs.sendMessage(tab.id, { 110 | cmd: 'deny-last-request' 111 | }, () => window.close()); 112 | } 113 | }); 114 | -------------------------------------------------------------------------------- /v3/config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const config = { 4 | 'enabled': true, 5 | 'numbers': 5, 6 | 'timeout': 30, 7 | 'countdown': 5, 8 | 'default-action': 'ignore', 9 | 'immediate-action': false, 10 | 'simulate-allow': true, 11 | 'focus-popup': false, 12 | 'aggressive': false, 13 | 'wot': false, 14 | 'domain': false, // allow popups from the same domain 15 | 'badge': true, 16 | 'badge-color': '#6e6e6e', 17 | 'whitelist-mode': 'popup-hosts', 18 | 'placement': 'tr', 19 | // the following hostnames can issue popup on every website 20 | 'popup-hosts': [ 21 | 'google.com', 'bing.com', 't.co', 'twitter.com', 'disqus.com', 'login.yahoo.com', 22 | 'mail.google.com', 'doubleclick.net' 23 | ], 24 | // popup blocker is disabled in the following hostname tabs 25 | 'top-hosts': ['github.com', 'twitter.com', 'webextension.org', 'google.com', 'paypal.com'], 26 | // these protocols are accepted 27 | 'protocols': ['magnet:'], 28 | 'silent': [], 29 | 'rules': {}, 30 | 'issue': true, 31 | 'block-page-redirection': false, 32 | 'block-page-redirection-hostnames': [], 33 | 'block-page-redirection-same-origin': true, 34 | 'target': true, 35 | 'version': null, 36 | 'faqs': true, 37 | 'last-update': 0, 38 | 'scope': ['*://*/*'], 39 | 'width': 420 // popup width in px 40 | }; 41 | 42 | { 43 | // get the list of preferences that need to be read from chrome.sync storage 44 | config.sync = async () => { 45 | if ('synced' in config) { 46 | return; 47 | } 48 | const prefs = await chrome.storage.local.get({ 49 | synced: [] 50 | }); 51 | config.synced = prefs.synced; 52 | }; 53 | 54 | config.get = async keys => { 55 | await config.sync(); 56 | 57 | if (keys.length) { 58 | const ps = {}; 59 | 60 | for (const key of keys) { 61 | if (config.synced.includes(key)) { 62 | ps.sync = ps.sync || {}; 63 | ps.sync[key] = config[key]; 64 | } 65 | else { 66 | ps.local = ps.local || {}; 67 | ps.local[key] = config[key]; 68 | } 69 | } 70 | 71 | const prefs = {}; 72 | if ('local' in ps) { 73 | const one = await chrome.storage.local.get(ps.local); 74 | Object.assign(prefs, one); 75 | } 76 | if ('sync' in ps) { 77 | const two = await chrome.storage.sync.get(ps.sync); 78 | Object.assign(prefs, two); 79 | } 80 | return prefs; 81 | } 82 | // get all stored preference 83 | else { 84 | const one = await chrome.storage.local.get(null); 85 | const two = await chrome.storage.sync.get(null); 86 | 87 | for (const key of config.synced) { 88 | one[key] = two[key] || one[key]; 89 | } 90 | 91 | return one; 92 | } 93 | }; 94 | config.update = async prefs => { 95 | await config.sync(); 96 | 97 | const ps = {}; 98 | 99 | for (const [key, value] of Object.entries(prefs)) { 100 | if (config.synced.includes(key)) { 101 | ps.sync = ps.sync || {}; 102 | ps.sync[key] = value; 103 | } 104 | else { 105 | ps.local = ps.local || {}; 106 | ps.local[key] = value; 107 | } 108 | } 109 | if ('local' in ps) { 110 | const one = await chrome.storage.local.get(ps.local); 111 | Object.assign(prefs, one); 112 | } 113 | if ('sync' in ps) { 114 | const two = await chrome.storage.sync.get(ps.sync); 115 | Object.assign(prefs, two); 116 | } 117 | }; 118 | config.set = async prefs => { 119 | await config.sync(); 120 | 121 | const ps = {}; 122 | 123 | for (const [key, value] of Object.entries(prefs)) { 124 | if (config.synced.includes(key)) { 125 | ps.sync = ps.sync || {}; 126 | ps.sync[key] = value; 127 | } 128 | else { 129 | ps.local = ps.local || {}; 130 | ps.local[key] = value; 131 | } 132 | } 133 | 134 | if ('local' in ps) { 135 | await chrome.storage.local.set(ps.local); 136 | } 137 | if ('sync' in ps) { 138 | await chrome.storage.sync.set(ps.sync); 139 | } 140 | 141 | return; 142 | }; 143 | } 144 | 145 | config.changed = c => chrome.storage.onChanged.addListener(c); 146 | -------------------------------------------------------------------------------- /v2/_locales/tr/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "options_item12": { 3 | "message": "Virgül ile ayrılan beyaz liste sitelerinde bu eklenti tamamen kapalı olacaktır", 4 | "description": "" 5 | }, 6 | "options_msg": { 7 | "message": "Ayarlar Kaydedildi", 8 | "description": "" 9 | }, 10 | "options_item23": { 11 | "message": "Eğer mümkünse popup istekleri bildirimini engelle (önerilmez)", 12 | "description": "" 13 | }, 14 | "options_item10": { 15 | "message": "Geri sayımı kapatmak için sıfır yazın", 16 | "description": "" 17 | }, 18 | "context_item1": { 19 | "message": "Popup engleleyici test et", 20 | "description": "" 21 | }, 22 | "options_item3": { 23 | "message": "Aynı kaynaktan popup isteği alma", 24 | "description": "" 25 | }, 26 | "options_item16": { 27 | "message": "Bazı sitelerde , sayfa reklamlı link yönlendirmeli olarak verilir.Bu ayar site yönlendirmesine gitmeden önce sizi uyarır.", 28 | "description": "" 29 | }, 30 | "options_item4": { 31 | "message": "Yeni sekmede açılan linkleri engelle", 32 | "description": "" 33 | }, 34 | "options_item24": { 35 | "message": "Bu ayar otomatik olarak popup isteklerine \"Kabul\" veya \"Reddet\" komutunu uygulayacaktır (önerilmez)", 36 | "description": "" 37 | }, 38 | "options_item25": { 39 | "message": "Açıklamalar", 40 | "description": "" 41 | }, 42 | "options_item15": { 43 | "message": "Popup isteğinden 2 saniye sonra yönlendirmeyi engelle", 44 | "description": "" 45 | }, 46 | "app_description": { 47 | "message": "Kesin olarak bütün popup isteklerini engeller", 48 | "description": "" 49 | }, 50 | "options_item19": { 51 | "message": "Reddet", 52 | "description": "" 53 | }, 54 | "options_item9": { 55 | "message": "En son işlem için geri sayım süresi (saniye)", 56 | "description": "" 57 | }, 58 | "options_item2": { 59 | "message": "Popup bildirisi penceresi görünüm süresi (saniye)", 60 | "description": "" 61 | }, 62 | "options_item7": { 63 | "message": "Güvenilir kaynaklar:", 64 | "description": "" 65 | }, 66 | "options_save": { 67 | "message": "Ayarları Kaydet", 68 | "description": "" 69 | }, 70 | "options_item26": { 71 | "message": "Sıkça sorulan soruları güncellemelerde göster", 72 | "description": "" 73 | }, 74 | "options_item22": { 75 | "message": "Sayacın arka plan rengi", 76 | "description": "" 77 | }, 78 | "context_item4": { 79 | "message": "Popup isteğini gizli sekmede aç", 80 | "description": "" 81 | }, 82 | "options_item1": { 83 | "message": "Bir sayfada engellenecek en fazla popup isteği sayısı", 84 | "description": "" 85 | }, 86 | "options_item17": { 87 | "message": "Popup isteği geldiğinde yapılacak ilk komut", 88 | "description": "" 89 | }, 90 | "options_item14": { 91 | "message": "Virgül ile ayrılan kara liste sitelerde bu uygulama tamamen aktif olacaktır. Eğer bu ayarı kullanırsanız bu uygulama diğer TÜM sitelerde çalışmayacaktır.", 92 | "description": "" 93 | }, 94 | "options_item11": { 95 | "message": "Virgül ile ayrılan beyaz liste sitelerinde hiç bir engelleme olmayacaktır (bu sitelerde herhangi bir yeni pencere veya sekme çıkabilir)", 96 | "description": "" 97 | }, 98 | "options_item18": { 99 | "message": "Hiçbir şey yapma", 100 | "description": "" 101 | }, 102 | "options_item21": { 103 | "message": "Sayfayı yönlendir", 104 | "description": "" 105 | }, 106 | "options_item8": { 107 | "message": "Ayarları düzenledikten sonra sayfanızı yenileyin", 108 | "description": "" 109 | }, 110 | "options_item13": { 111 | "message": "Kara liste:", 112 | "description": "" 113 | }, 114 | "options_item5": { 115 | "message": "Engellenene isteklerin sayısını eklenti simgesinde göster", 116 | "description": "" 117 | }, 118 | "options_item6": { 119 | "message": "Güvenilir siteler:", 120 | "description": "" 121 | }, 122 | "context_item3": { 123 | "message": "En son gelen popup isteğini reddet", 124 | "description": "" 125 | }, 126 | "options_item20": { 127 | "message": "Arka planda aç", 128 | "description": "" 129 | }, 130 | "context_item2": { 131 | "message": "En son gelen popup isteğini kabul et", 132 | "description": "" 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /v2/data/options/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Options Page :: Popup Blocker (strict) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 37 | 38 | 39 | 45 | 46 | 47 | 48 | 49 | 50 | 51 |
1
2
30 | 36 |
40 | 44 |
52 | 53 |
54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
69 | 70 |

71 | 1, 3 72 | 73 |

74 |

75 | 1, 4 76 | 77 |

78 |

79 | 1, 8 80 | 81 |

82 |

83 | 1, 5 84 | 85 |

86 |

87 | 1, 9 88 | 89 |

90 | 91 |

92 | 93 | 94 |

95 |

96 | 97 | 98 |

99 |

100 | 101 | 102 | 103 | 104 | 105 |

106 | 107 |
108 | 109 |
110 | 111 |

112 | 1: 113 |
114 | 2: 115 |
116 | 3: 117 |
118 | 4: 119 |
120 | 5: 121 |
122 | 6: 123 |
124 | 7: 125 |
126 | 8: 127 |
128 | 9: 129 |

130 |
131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /v3/data/popup/index.mjs: -------------------------------------------------------------------------------- 1 | /* global config, tldjs, URLPattern */ 2 | 3 | // links 4 | for (const a of [...document.querySelectorAll('[data-href]')]) { 5 | if (a.hasAttribute('href') === false) { 6 | a.href = chrome.runtime.getManifest().homepage_url + '#' + a.dataset.href; 7 | } 8 | } 9 | 10 | // localization 11 | [...document.querySelectorAll('[data-i18n]')].forEach(e => { 12 | if (e.tagName === 'INPUT') { 13 | e.value = chrome.i18n.getMessage(e.dataset.i18n); 14 | } 15 | else { 16 | e.textContent = chrome.i18n.getMessage(e.dataset.i18n); 17 | } 18 | }); 19 | 20 | // Global 21 | config.get(['enabled']).then(prefs => { 22 | document.getElementById('global').checked = prefs.enabled; 23 | if (prefs.enabled === false) { 24 | document.getElementById('page').disabled = 25 | document.getElementById('subs').disabled = true; 26 | } 27 | }); 28 | document.getElementById('global').onchange = e => { 29 | config.set({ 30 | enabled: e.target.checked 31 | }); 32 | document.getElementById('page').disabled = 33 | document.getElementById('subs').disabled = e.target.checked === false; 34 | }; 35 | 36 | const page = {}; 37 | 38 | const match = (hostname, href) => { 39 | if (typeof URLPattern !== 'undefined') { 40 | try { 41 | const v = new URLPattern({hostname}); 42 | if (v.test(href)) { 43 | return true; 44 | } 45 | } 46 | catch (e) {} 47 | try { 48 | const v = new URLPattern({hostname: '*.' + hostname}); 49 | if (v.test(href)) { 50 | return true; 51 | } 52 | } 53 | catch (e) {} 54 | } 55 | else { 56 | try { 57 | const o = new URL(href); 58 | return hostname === o.hostname || hostname.endsWith('.' + o.hostname); 59 | } 60 | catch (e) {} 61 | } 62 | }; 63 | 64 | // Start Point 65 | chrome.tabs.query({ 66 | currentWindow: true, 67 | active: true 68 | }, tabs => { 69 | if (tabs.length) { 70 | page.tabId = tabs[0].id; 71 | 72 | chrome.scripting.executeScript({ 73 | target: { 74 | tabId: tabs[0].id 75 | }, 76 | func: () => ({ 77 | enabled: window.prefs?.enabled, 78 | hostname: location.hostname, 79 | href: location.href 80 | }) 81 | }).then(async response => { 82 | const {enabled, hostname, href} = response[0].result; 83 | 84 | page.hostname = hostname; 85 | page.href = href; 86 | if (enabled === true || enabled === false) { 87 | document.getElementById('page').checked = enabled; 88 | } 89 | else { 90 | const prefs = await config.get(['top-hosts']); 91 | document.getElementById('page').checked = 92 | prefs['top-hosts'].some(h => match(h, page.href)) ? false : true; 93 | } 94 | }).catch(() => { 95 | document.getElementById('page').disabled = 96 | document.getElementById('subs').disabled = true; 97 | // force disabled 98 | document.getElementById('page').classList.add('disabled'); 99 | document.getElementById('subs').classList.add('disabled'); 100 | }); 101 | } 102 | }); 103 | 104 | document.getElementById('page').onchange = async e => { 105 | const prefs = await config.get(['top-hosts']); 106 | 107 | const rms = new Set(); 108 | rms.add(tldjs.getDomain(page.hostname) || page.hostname); 109 | 110 | if (document.getElementById('subs').checked) { 111 | try { 112 | const r = await chrome.scripting.executeScript({ 113 | target: { 114 | tabId: page.tabId, 115 | allFrames: true 116 | }, 117 | func: () => location.hostname 118 | }); 119 | for (const o of r) { 120 | if (o?.result) { 121 | rms.add(tldjs.getDomain(o.result) || o.result); 122 | } 123 | } 124 | } 125 | catch (e) {} 126 | } 127 | 128 | if (e.target.checked) { 129 | for (const hostname of prefs['top-hosts']) { 130 | if (match(hostname, page.href)) { 131 | rms.add(hostname); 132 | } 133 | } 134 | prefs['top-hosts'] = prefs['top-hosts'].filter(s => rms.has(s) === false); 135 | } 136 | else { 137 | for (const d of rms) { 138 | prefs['top-hosts'].push(d); 139 | } 140 | prefs['top-hosts'] = prefs['top-hosts'].filter((s, i, l) => s && l.indexOf(s) === i); 141 | } 142 | config.set(prefs).then(() => chrome.tabs.reload()); 143 | }; 144 | 145 | config.get(['immediate-action']).then(prefs => { 146 | document.getElementById('immediate-action').checked = prefs['immediate-action']; 147 | }); 148 | document.getElementById('immediate-action').onchange = e => config.set({ 149 | 'immediate-action': e.target.checked 150 | }); 151 | 152 | config.get(['block-page-redirection']).then(prefs => { 153 | document.getElementById('block-page-redirection').checked = prefs['block-page-redirection']; 154 | }); 155 | document.getElementById('block-page-redirection').onchange = e => config.set({ 156 | 'block-page-redirection': e.target.checked 157 | }); 158 | 159 | config.get(['issue']).then(prefs => { 160 | document.getElementById('issue').checked = prefs.issue; 161 | }); 162 | document.getElementById('issue').onchange = e => config.set({ 163 | 'issue': e.target.checked 164 | }); 165 | 166 | document.getElementById('test-page').onclick = () => chrome.tabs.create({ 167 | url: 'https://webbrowsertools.com/popup-blocker/' 168 | }, () => window.close()); 169 | 170 | document.getElementById('homepage').onclick = () => chrome.tabs.create({ 171 | url: chrome.runtime.getManifest().homepage_url 172 | }, () => window.close()); 173 | 174 | document.getElementById('options').onclick = () => chrome.runtime.openOptionsPage(() => { 175 | window.close(); 176 | }); 177 | 178 | chrome.tabs.query({ 179 | currentWindow: true, 180 | active: true 181 | }, tabs => { 182 | if (tabs.length) { 183 | const tab = tabs[0]; 184 | document.getElementById('use-shadow').onclick = () => chrome.tabs.sendMessage(tab.id, { 185 | cmd: 'use-shadow' 186 | }, () => window.close()); 187 | 188 | document.getElementById('allow-last-request').onclick = () => chrome.tabs.sendMessage(tab.id, { 189 | cmd: 'allow-last-request' 190 | }, () => window.close()); 191 | 192 | document.getElementById('deny-last-request').onclick = () => chrome.tabs.sendMessage(tab.id, { 193 | cmd: 'deny-last-request' 194 | }, () => window.close()); 195 | } 196 | }); 197 | -------------------------------------------------------------------------------- /v2/data/options/index.js: -------------------------------------------------------------------------------- 1 | /* globals config */ 2 | 'use strict'; 3 | 4 | const isFirefox = /Firefox/.test(navigator.userAgent) || typeof InstallTrigger !== 'undefined'; 5 | 6 | // localization 7 | [...document.querySelectorAll('[data-i18n]')].forEach(e => { 8 | e.textContent = chrome.i18n.getMessage(e.dataset.i18n); 9 | }); 10 | 11 | async function restore(defaults = false) { 12 | const prefs = defaults ? config : await config.get([ 13 | 'numbers', 'timeout', 'countdown', 'badge', 'badge-color', 'domain', 'wot', 14 | 'simulate-allow', 'faqs', 'block-page-redirection', 'popup-hosts', 15 | 'top-hosts', 'blacklist', 'protocols', 'silent', 'default-action', 16 | 'whitelist-mode', 'immediate-action' 17 | ]); 18 | document.getElementById('numbers').value = prefs.numbers; 19 | document.getElementById('timeout').value = prefs.timeout; 20 | document.getElementById('countdown').value = prefs.countdown; 21 | document.getElementById('badge').checked = prefs.badge; 22 | document.getElementById('badge-color').value = prefs['badge-color']; 23 | document.getElementById('domain').checked = prefs.domain; 24 | document.getElementById('wot').checked = prefs.wot; 25 | document.getElementById('simulate-allow').checked = prefs['simulate-allow']; 26 | document.getElementById('faqs').checked = prefs.faqs; 27 | document.getElementById('block-page-redirection').checked = prefs['block-page-redirection']; 28 | document.getElementById('popup-hosts').value = prefs['popup-hosts'].join(', '); 29 | document.getElementById('top-hosts').value = prefs['top-hosts'].join(', '); 30 | document.getElementById('blacklist').value = isFirefox ? prefs.blacklist.join(', ') : ''; 31 | document.getElementById('protocols').value = prefs.protocols.join(', '); 32 | document.getElementById('silent').value = prefs.silent.join(', '); 33 | document.getElementById('default-action').value = prefs['default-action']; 34 | document.getElementById('whitelist-mode').value = prefs['whitelist-mode']; 35 | document.getElementById('immediate-action').checked = prefs['immediate-action']; 36 | } 37 | 38 | const prepare = str => str.split(/\s*,\s*/) 39 | .map(s => s.replace('http://', '').replace('https://', '').split('/')[0].trim()) 40 | .filter((h, i, l) => h && l.indexOf(h) === i); 41 | 42 | function save() { 43 | chrome.storage.local.set({ 44 | 'numbers': Math.max(1, document.getElementById('numbers').value), 45 | 'timeout': Math.max(1, document.getElementById('timeout').value), 46 | 'countdown': Math.max(0, document.getElementById('countdown').value), 47 | 'badge': document.getElementById('badge').checked, 48 | 'badge-color': document.getElementById('badge-color').value, 49 | 'domain': document.getElementById('domain').checked, 50 | 'wot': document.getElementById('wot').checked, 51 | 'simulate-allow': document.getElementById('simulate-allow').checked, 52 | 'faqs': document.getElementById('faqs').checked, 53 | 'block-page-redirection': document.getElementById('block-page-redirection').checked, 54 | 'popup-hosts': prepare(document.getElementById('popup-hosts').value), 55 | 'top-hosts': prepare(document.getElementById('top-hosts').value), 56 | 'blacklist': prepare(document.getElementById('blacklist').value), 57 | 'silent': prepare(document.getElementById('silent').value), 58 | 'protocols': document.getElementById('protocols').value 59 | .split(/\s*,\s*/).filter(s => s && s.endsWith(':')), 60 | 'default-action': document.getElementById('default-action').value, 61 | 'whitelist-mode': document.getElementById('whitelist-mode').value, 62 | 'immediate-action': document.getElementById('immediate-action').checked 63 | }, () => { 64 | const status = document.getElementById('status'); 65 | status.textContent = chrome.i18n.getMessage('options_msg'); 66 | restore(); 67 | setTimeout(() => status.textContent = '', 750); 68 | }); 69 | } 70 | 71 | document.addEventListener('DOMContentLoaded', () => restore()); 72 | document.getElementById('save').addEventListener('click', save); 73 | 74 | document.addEventListener('click', e => { 75 | if (e.target.href && e.target.href.indexOf('#') !== -1) { 76 | document.querySelector('details').open = true; 77 | } 78 | }); 79 | 80 | document.getElementById('reset').addEventListener('click', () => restore(true)); 81 | document.getElementById('export').addEventListener('click', () => { 82 | chrome.storage.local.get(null, prefs => { 83 | const text = JSON.stringify(prefs, null, '\t'); 84 | const blob = new Blob([text], {type: 'application/json'}); 85 | const objectURL = URL.createObjectURL(blob); 86 | Object.assign(document.createElement('a'), { 87 | href: objectURL, 88 | type: 'application/json', 89 | download: 'popup-blocker-preferences.json' 90 | }).dispatchEvent(new MouseEvent('click')); 91 | setTimeout(() => URL.revokeObjectURL(objectURL)); 92 | }); 93 | }); 94 | document.getElementById('import').addEventListener('click', () => { 95 | const fileInput = document.createElement('input'); 96 | fileInput.style.display = 'none'; 97 | fileInput.type = 'file'; 98 | fileInput.accept = '.json'; 99 | fileInput.acceptCharset = 'utf-8'; 100 | 101 | document.body.appendChild(fileInput); 102 | fileInput.initialValue = fileInput.value; 103 | fileInput.onchange = readFile; 104 | fileInput.click(); 105 | 106 | function readFile() { 107 | if (fileInput.value !== fileInput.initialValue) { 108 | const file = fileInput.files[0]; 109 | if (file.size > 100e6) { 110 | return console.warn('The file is too large!'); 111 | } 112 | const fReader = new FileReader(); 113 | fReader.onloadend = event => { 114 | fileInput.remove(); 115 | const json = JSON.parse(event.target.result); 116 | chrome.storage.local.set(json, () => chrome.runtime.reload()); 117 | }; 118 | fReader.readAsText(file, 'utf-8'); 119 | } 120 | } 121 | }); 122 | // support 123 | document.getElementById('support').addEventListener('click', () => chrome.tabs.create({ 124 | url: chrome.runtime.getManifest().homepage_url + '?rd=donate' 125 | })); 126 | // review 127 | document.getElementById('review').addEventListener('click', () => chrome.tabs.create({ 128 | url: 'https://www.youtube.com/watch?v=Jp-RaiTHzCQ' 129 | })); 130 | // FAQs Page 131 | document.getElementById('page').addEventListener('click', () => chrome.tabs.create({ 132 | url: chrome.runtime.getManifest().homepage_url 133 | })); 134 | 135 | 136 | if (isFirefox === false) { 137 | document.getElementById('blacklist').setAttribute('placeholder', chrome.i18n.getMessage('options_item38')); 138 | document.getElementById('blacklist').disabled = true; 139 | } 140 | -------------------------------------------------------------------------------- /v2/_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_description": { 3 | "message": "Strictly block all popup requests from any website" 4 | }, 5 | "context_item2": { 6 | "message": "Allow the last popup request" 7 | }, 8 | "context_item3": { 9 | "message": "Deny the last popup request" 10 | }, 11 | "options_item1": { 12 | "message": "Maximum number of popup requests for a single page" 13 | }, 14 | "options_item2": { 15 | "message": "Timeout for displaying each popup (in seconds)" 16 | }, 17 | "options_item3": { 18 | "message": "Do not block popup requests from same origin" 19 | }, 20 | "options_item5": { 21 | "message": "Display the total number of blocked requests in the toolbar icon" 22 | }, 23 | "options_item6": { 24 | "message": "Whitelist destinations:" 25 | }, 26 | "options_item7": { 27 | "message": "Whitelist sources:" 28 | }, 29 | "options_item8": { 30 | "message": "For this change to take effect, refresh the tab." 31 | }, 32 | "options_item9": { 33 | "message": "Countdown for performing the last action (in seconds)" 34 | }, 35 | "options_item10": { 36 | "message": "Use zero number to disable the countdown to perform the previous action." 37 | }, 38 | "options_item11": { 39 | "message": "Comma-separated list of hostnames that are not going to be blocked (these hostnames can issue popups on any website)." 40 | }, 41 | "options_item12": { 42 | "message": "Comma-separated list of hostnames that the popup blocker extension is completely disabled on them." 43 | }, 44 | "options_item13": { 45 | "message": "Blacklist sources (reverse operation mode):" 46 | }, 47 | "options_item14": { 48 | "message": "Comma-separated list of hostnames that the popup blocker should only be active on them. This means that the popup blocker is disabled on ALL other hostnames. To disable this mode, clear the blacklist input completely." 49 | }, 50 | "options_item15": { 51 | "message": "Prevent page redirection for 2 seconds after a popup is requested" 52 | }, 53 | "options_item16": { 54 | "message": "Some websites redirect the user to the advertisement page if the popup request to display an advertisement is blocked. This option can prevent this by not allowing page redirection for the specified time." 55 | }, 56 | "options_item17": { 57 | "message": "Default action when a popup is requested" 58 | }, 59 | "options_item18": { 60 | "message": "do nothing" 61 | }, 62 | "options_item19": { 63 | "message": "deny request" 64 | }, 65 | "options_item20": { 66 | "message": "open in background" 67 | }, 68 | "options_item21": { 69 | "message": "redirect page" 70 | }, 71 | "options_item22": { 72 | "message": "Badge background-color" 73 | }, 74 | "options_item23": { 75 | "message": "Ignore popup notification when possible (not recommended)" 76 | }, 77 | "options_item24": { 78 | "message": "This will \"ignore\" or \"accept\" a popup without user interaction (not recommended)" 79 | }, 80 | "options_item25": { 81 | "message": "Descriptions" 82 | }, 83 | "options_item26": { 84 | "message": "Display FAQs page on updates" 85 | }, 86 | "options_item27": { 87 | "message": "Whitelist protocols:" 88 | }, 89 | "options_item28": { 90 | "message": "The listed protocols can be opened in a new browser tab. For instance add 'magnet:' to allow magnet links to be opened in a browser tab." 91 | }, 92 | "options_item29": { 93 | "message": "Use Web of Trust (WOT) service to decide either popup is from a trusted hostname or not" 94 | }, 95 | "options_item30": { 96 | "message": "Simulate the 'allow' button to prevent your browser's internal popup blocker from blocking these requests" 97 | }, 98 | "options_item31": { 99 | "message": "When 'trust' button is pressed, add hostname to" 100 | }, 101 | "options_item32": { 102 | "message": "Whitelist destinations" 103 | }, 104 | "options_item33": { 105 | "message": "Whitelist sources" 106 | }, 107 | "options_item34": { 108 | "message": "Notification blacklist" 109 | }, 110 | "options_item35": { 111 | "message": "Comma-separated list of hostnames that the popup blocker will not display notification if a popup is requested" 112 | }, 113 | "options_item36": { 114 | "message": "Enable aggressive static IFrame detection" 115 | }, 116 | "options_item37": { 117 | "message": "When this mode is enabled, the extension installs a mutation observer to monitor static IFrames with 'JavaScript:' src attributes. This enhances the blocking power but has performance drawbacks." 118 | }, 119 | "options_item38": { 120 | "message": "This feature is deprecated! If you don't want this extension to globally block pages, right-click on the action button and limit the access to particular websites from the \"This can read and change site data\" context menu item." 121 | }, 122 | "options_support": { 123 | "message": "Support Development" 124 | }, 125 | "options_import": { 126 | "message": "Import" 127 | }, 128 | "options_export": { 129 | "message": "Export" 130 | }, 131 | "options_reset": { 132 | "message": "Reset to Defaults" 133 | }, 134 | "options_save": { 135 | "message": "Save" 136 | }, 137 | "options_msg": { 138 | "message": "Options are saved" 139 | }, 140 | "options_review": { 141 | "message": "YouTube Review" 142 | }, 143 | "options_page": { 144 | "message": "FAQs Page" 145 | }, 146 | "ui_msg": { 147 | "message": "Popup is requested for" 148 | }, 149 | "ui_button_allow": { 150 | "message": "Allow this popup" 151 | }, 152 | "ui_button_allow_value": { 153 | "message": "allow" 154 | }, 155 | "ui_button_redirect": { 156 | "message": "Redirect current page to the new destination instead of opening it in a new tab or popup" 157 | }, 158 | "ui_button_redirect_value": { 159 | "message": "redirect" 160 | }, 161 | "ui_button_background": { 162 | "message": "Open the link in a background tab" 163 | }, 164 | "ui_button_background_value": { 165 | "message": "background" 166 | }, 167 | "ui_button_deny": { 168 | "message": "Decline the popup or tab opening" 169 | }, 170 | "ui_button_deny_value": { 171 | "message": "deny" 172 | }, 173 | "ui_button_trust": { 174 | "message": "White-list this domain to open popups" 175 | }, 176 | "ui_button_trust_value": { 177 | "message": "trust" 178 | }, 179 | "bg_msg_state_1": { 180 | "message": "Popup Blocker (strict) is globally enabled and protects this tab" 181 | }, 182 | "bg_msg_state_2": { 183 | "message": "Popup Blocker (strict) is globally enabled but does not protect this tab" 184 | }, 185 | "bg_msg_state_3": { 186 | "message": "Popup Blocker (strict) is globally disabled and does not protect this tab" 187 | }, 188 | "bg_msg_state_4": { 189 | "message": "Popup Blocker (strict) is globally disabled but protects this tab" 190 | }, 191 | "pp_enabled_g": { 192 | "message": "Enabled (Globally)" 193 | }, 194 | "pp_enabled_c": { 195 | "message": "Enabled (This Hostname)" 196 | }, 197 | "pp_silent": { 198 | "message": "Display Notifications" 199 | }, 200 | "pp_ignore": { 201 | "message": "Ignore when Possible" 202 | }, 203 | "pp_last_request": { 204 | "message": "Last Request" 205 | }, 206 | "pp_test": { 207 | "message": "Test Blocker" 208 | }, 209 | "pp_homepage": { 210 | "message": "Homepage" 211 | }, 212 | "pp_options": { 213 | "message": "Options" 214 | }, 215 | "pp_shadow": { 216 | "message": "Use Shadow" 217 | }, 218 | "pp_allow": { 219 | "message": "Allow" 220 | }, 221 | "pp_block": { 222 | "message": "Block" 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /v3/data/options/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Options Page :: Popup Blocker (strict) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 41 | 42 | 43 | 44 | 50 | 51 | 52 | 53 | 61 | 62 | 63 | 64 | 65 | 66 |
1
2
34 | 40 |
45 | 49 |
54 | 60 |
67 |
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |
81 |

82 |

83 |
84 | 1 85 |
86 | 87 |
88 | 89 |

90 |

91 |

92 |
93 | 1 94 |
95 | 96 |
97 | 98 |

99 |

100 |

101 |
102 | 1 103 |
104 | 105 |
106 | 107 |

108 |

109 |

110 |
111 | 1 112 |
113 | 114 |
115 | 116 |

117 |

118 |

119 |

120 |
121 | 122 |
123 | 124 |
125 | 126 |

127 |

128 |
129 | 130 | 131 | 132 | 133 |
134 |

135 | 1 136 | 137 |

138 |

139 |

140 | 141 | 142 |

143 |

144 | 145 | 151 |

152 |

153 | 154 | 155 |

156 |

157 | 158 | 159 |

160 |

161 | 162 | 163 | 164 | 165 | 166 |

167 |
168 |
169 | 170 |

171 | 1: 172 |
173 | 2: 174 |

175 |
176 | 177 | 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /v2/data/ui/ui.js: -------------------------------------------------------------------------------- 1 | /* globals config, wot */ 2 | 'use strict'; 3 | 4 | const args = new URLSearchParams(location.search); 5 | let prefs = ''; 6 | 7 | const entry = document.getElementById('entry'); 8 | const urls = {}; 9 | const cookie = { 10 | get: host => { 11 | const key = document.cookie.split(`${host}-action=`); 12 | if (key.length > 1) { 13 | return key[1].split(';')[0]; 14 | } 15 | }, 16 | set: (host, cmd) => { 17 | const days = 10; 18 | const date = new Date(); 19 | date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); 20 | 21 | document.cookie = `${host}-action=${cmd}; expires=${date.toGMTString()}`; 22 | }, 23 | remove: host => { 24 | const cmd = cookie.get(host); 25 | if (cmd) { 26 | document.cookie = `${host}-action=${cmd}; expires=Thu, 01 Jan 1970 00:00:01 GMT`; 27 | } 28 | } 29 | }; 30 | 31 | const resize = () => window.top.postMessage({ 32 | method: 'ppp-resize', 33 | // Edge issue with document.documentElement.clientHeight 34 | height: document.documentElement.getBoundingClientRect().height, 35 | hide: Object.keys(urls).length === 0 36 | }, '*'); 37 | 38 | function Timer(callback, delay, ...args) { 39 | let timerId; 40 | let start; 41 | let remaining = delay; 42 | 43 | this.pause = function() { 44 | window.clearTimeout(timerId); 45 | remaining -= new Date() - start; 46 | }; 47 | 48 | this.resume = function() { 49 | start = new Date(); 50 | window.clearTimeout(timerId); 51 | timerId = window.setTimeout(callback, remaining, ...args); 52 | return timerId; 53 | }; 54 | 55 | this.reset = function() { 56 | remaining = delay; 57 | this.resume(); 58 | }; 59 | 60 | return this.resume(); 61 | } 62 | 63 | function remove(div, url) { 64 | delete urls[url || div.dataset.url]; 65 | div.remove(); 66 | resize(); 67 | } 68 | 69 | function onClick(e) { 70 | const target = e.target; 71 | const cmd = target.dataset.cmd; 72 | if (cmd) { 73 | const div = target.closest('.ppblocker-div'); 74 | if (div) { 75 | const {url, hostname, id, frameId, sameContext} = div.dataset; 76 | remove(div, url, id, cmd); 77 | if (cmd !== 'popup-denied' && cmd !== 'popup-close') { 78 | // on user-action use native method 79 | const msg = {cmd, id, url, 80 | frameId: Number(frameId), 81 | sameContext: sameContext === 'true' || (e.isTrusted && navigator.userAgent.indexOf('Firefox') === -1) 82 | }; 83 | msg.parent = args.get('parent'); 84 | chrome.runtime.sendMessage(msg); 85 | // https://github.com/schomery/popup-blocker/issues/90 86 | if (cmd === 'white-list') { 87 | msg.cmd = 'popup-accepted'; 88 | chrome.runtime.sendMessage(msg); 89 | } 90 | } 91 | // remember user action 92 | if (cmd === 'popup-close') { 93 | cookie.remove(hostname); 94 | } 95 | else if (hostname && ['popup-redirect', 'open-tab', 'popup-denied'].indexOf(cmd) !== -1) { 96 | cookie.set(hostname, cmd); 97 | } 98 | } 99 | } 100 | } 101 | document.addEventListener('click', onClick); 102 | 103 | const doTimer = (div, button, countdown) => { 104 | button.dataset.default = true; 105 | const label = button.value; 106 | const id = window.setInterval(() => { 107 | // skip when mouse is over 108 | if (div.dataset.hover === 'true') { 109 | return; 110 | } 111 | countdown -= 1; 112 | if (countdown) { 113 | button.value = label + ` (${countdown})`; 114 | } 115 | else { 116 | window.clearInterval(id); 117 | button.click(); 118 | } 119 | }, 1000); 120 | button.value = label + ` (${countdown})`; 121 | }; 122 | const onPopupRequest = request => { 123 | const tag = request.href && request.href !== 'about:blank' ? request.href : request.id; 124 | // already listed 125 | if (urls[tag]) { 126 | const obj = urls[tag]; 127 | const div = obj.div; 128 | div.dataset.badge = Number(div.dataset.badge || '1') + 1; 129 | obj.timer.reset(); 130 | obj.timestamp = Date.now(); 131 | } 132 | // new popup 133 | else { 134 | const clone = document.importNode(entry.content, true); 135 | const div = clone.querySelector('div'); 136 | div.dataset.id = request.id; 137 | div.dataset.frameId = request.frameId; 138 | div.dataset.sameContext = request.sameContext; 139 | div.dataset.url = tag; 140 | const page = request.href.startsWith('http') || request.href.startsWith('ftp'); 141 | div.dataset.page = page; 142 | div.dataset.hostname = request.hostname; 143 | 144 | const p = clone.querySelector('[data-id=info]'); 145 | div.title = p.textContent = '↝ ' + (request.href || 'about:blank'); 146 | // do we have an action for this popup 147 | 148 | if (page) { 149 | const action = cookie.get(div.dataset.hostname) || prefs['default-action']; 150 | // immediate action 151 | if (action && action !== 'ignore' && prefs['immediate-action']) { 152 | return onClick({ 153 | target: div.querySelector(`[data-cmd="${action}"]`) 154 | }); 155 | } 156 | // only perform automatic action when there is no native request 157 | // to prevent the native popup blocker catch our request 158 | if (prefs.countdown && request.sameContext !== true) { 159 | if (action) { 160 | // to prevent internal popup blocker from rejecting the request 161 | if (action !== 'popup-accepted' || prefs['simulate-allow']) { 162 | const button = div.querySelector(`[data-cmd="${action}"`); 163 | if (button) { 164 | doTimer(div, button, prefs.countdown); 165 | } 166 | else if (prefs.wot) { 167 | wot.perform(div, prefs, request.href, div.dataset.hostname, prefs.countdown); 168 | } 169 | } 170 | } 171 | else if (prefs.wot) { 172 | wot.perform(div, prefs, request.href, div.dataset.hostname, prefs.countdown); 173 | } 174 | } 175 | } 176 | // localization 177 | [...clone.querySelectorAll('[data-i18n]')].forEach(e => { 178 | e[e.dataset.i18nValue || 'title'] = chrome.i18n.getMessage(e.dataset.i18n); 179 | if (e.type === 'button') { 180 | e.value = chrome.i18n.getMessage(e.dataset.i18n + '_value'); 181 | } 182 | }); 183 | document.body.appendChild(clone); 184 | // hide on timeout 185 | urls[tag] = { 186 | div, 187 | timer: new Timer(remove, prefs.timeout * 1000, div), 188 | prefs, 189 | timestamp: Date.now() 190 | }; 191 | div.addEventListener('mouseenter', () => { 192 | div.dataset.hover = true; 193 | urls[tag].timer.pause(); 194 | }); 195 | div.addEventListener('mouseleave', () => { 196 | div.dataset.hover = false; 197 | urls[tag].timer.resume(); 198 | }); 199 | // remove old entries 200 | const keys = Object.keys(urls); 201 | if (keys.length > prefs.numbers) { 202 | const key = keys.sort((a, b) => urls[a].timestamp - urls[b].timestamp)[0]; 203 | if (key) { 204 | remove(urls[key].div); 205 | } 206 | } 207 | resize(); 208 | } 209 | }; 210 | 211 | const message = async (request, sender) => { 212 | prefs = prefs || await config.get([ 213 | 'numbers', 'timeout', 'countdown', 'default-action', 'immediate-action', 'simulate-allow', 'wot' 214 | ]); 215 | prefs.wot = false; // this API is deprecated 216 | 217 | // only accept requests from bg page 218 | if (request.cmd === 'popup-request' && !sender.tab) { 219 | onPopupRequest(request); 220 | } 221 | else if (request.cmd === 'allow-last-request' || request.cmd === 'deny-last-request') { 222 | const value = Object.values(urls).sort((a, b) => b.timestamp - a.timestamp).shift(); 223 | if (value) { 224 | const div = value.div; 225 | const button = div.querySelector( 226 | request.cmd === 'allow-last-request' ? '[data-cmd="popup-accepted"]' : '[data-cmd="popup-denied"]' 227 | ); 228 | if (button) { 229 | button.click(); 230 | } 231 | } 232 | } 233 | }; 234 | chrome.runtime.onMessage.addListener(message); 235 | 236 | // initial requests from top 237 | { 238 | const c = e => { 239 | const request = e.data; 240 | if (request && request.method === 'popup-caches') { 241 | window.removeEventListener('message', c); 242 | for (const o of request.requests) { 243 | message(o, { 244 | tab: false 245 | }); 246 | } 247 | } 248 | }; 249 | window.addEventListener('message', c); 250 | } 251 | -------------------------------------------------------------------------------- /v2/_locales/ar/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_description": { 3 | "message": "حظر جميع النوافذ المنبثقه من أي موقع", 4 | "description": "" 5 | }, 6 | "context_item1": { 7 | "message": "اختبر حظر النوافذ المنبثقه", 8 | "description": "" 9 | }, 10 | "context_item2": { 11 | "message": "السماح لآخر طلب نافذه منبثقه بالظهور", 12 | "description": "" 13 | }, 14 | "context_item3": { 15 | "message": "حظر آخر طلب للنافذه المنبثقه", 16 | "description": "" 17 | }, 18 | "context_item4": { 19 | "message": "استخدم ظلال النوافذ للصفحه الحاليه", 20 | "description": "" 21 | }, 22 | "context_item5": { 23 | "message": "فتح صفحه الخيارات", 24 | "description": "" 25 | }, 26 | "context_item6": { 27 | "message": "تجاهل التنبيهات المنبثقه اذا امكن ", 28 | "description": "" 29 | }, 30 | "options_item1": { 31 | "message": "اقصي عدد لطلبات النوافذ المنبثقه للثفحه الواحده", 32 | "description": "" 33 | }, 34 | "options_item2": { 35 | "message": "الوقت اللازم لظهور كل نافذه منبثقه (بالثواني)", 36 | "description": "" 37 | }, 38 | "options_item3": { 39 | "message": "لا تقم بحظر طلبات النوافذ المنبثقه لنفس الصفحات الاساسيه", 40 | "description": "" 41 | }, 42 | "options_item5": { 43 | "message": "اظهار اجمالي عدد الطلبات المحظوره علي اايقونه في شريط الادوات", 44 | "description": "" 45 | }, 46 | "options_item6": { 47 | "message": "وجه قائمه السماح:", 48 | "description": "" 49 | }, 50 | "options_item7": { 51 | "message": "مصادر قائمه السماح:", 52 | "description": "" 53 | }, 54 | "options_item8": { 55 | "message": "لتطبيق التغييرات عليك بتحديث الصفحه", 56 | "description": "" 57 | }, 58 | "options_item9": { 59 | "message": "العد التنازلي لتطبيق اخر حدث (بالثواني)", 60 | "description": "" 61 | }, 62 | "options_item10": { 63 | "message": "استخدم (الصفر) لتعطيل العد التنازلي لتطبيق اخر حدث", 64 | "description": "" 65 | }, 66 | "options_item11": { 67 | "message": "(,)للفصل بين المواقع التي تريد عدم عمل حظر لها والتي تتسبب في حدوث مشاكل (علي كل المواقع )", 68 | "description": "" 69 | }, 70 | "options_item12": { 71 | "message": "(,)للفصل بين المواقع التي تريد عمل حظر لها بالكامل", 72 | "description": "" 73 | }, 74 | "options_item13": { 75 | "message": "مصادر القائمه السوداء (وضع العمليه المعكوسه)", 76 | "description": "" 77 | }, 78 | "options_item14": { 79 | "message": "(,)للفصل بين المواقع التي تريد ان تعمل عليهم فقط مع العلم انها ستكون معطله علي باقي المواقع لتعطيل هذا الوضع قم بتظيف القائمه السوداء بالكامل", 80 | "description": "" 81 | }, 82 | "options_item15": { 83 | "message": "منع الصفحه من الانتقال التلقائي ل 2 (ثانيه)بعد الطلب المنبثق", 84 | "description": "" 85 | }, 86 | "options_item16": { 87 | "message": "بعض المواقع توجه المستخدم لصفحات اعلانات .هذا الخيار يمنع المواقع من عمل ذلك لوقت محدد.", 88 | "description": "" 89 | }, 90 | "options_item17": { 91 | "message": "الحدث الافتراضي عند ظهور نافذه منبثقه", 92 | "description": "" 93 | }, 94 | "options_item18": { 95 | "message": "لا تفعل شئ", 96 | "description": "" 97 | }, 98 | "options_item19": { 99 | "message": "حظر الطلب", 100 | "description": "" 101 | }, 102 | "options_item20": { 103 | "message": "الفتح في الخلفيه", 104 | "description": "" 105 | }, 106 | "options_item21": { 107 | "message": "توجيه الصفحه", 108 | "description": "" 109 | }, 110 | "options_item22": { 111 | "message": "تمميز background-color", 112 | "description": "" 113 | }, 114 | "options_item23": { 115 | "message": "تجاهل النوافذ المنبثقه اذا امكن (غير موصي به)", 116 | "description": "" 117 | }, 118 | "options_item24": { 119 | "message": "هذ الخيار ل \"تجاهل\" او \"الموافقه\" للنوافقذ المنبثقه بدون تدخل المستخدم ( غير موصي به)", 120 | "description": "" 121 | }, 122 | "options_item25": { 123 | "message": "الوصف", 124 | "description": "" 125 | }, 126 | "options_item26": { 127 | "message": "اظهار صفحه الاسئله الشائعه ( FAQs) عند التحديث", 128 | "description": "" 129 | }, 130 | "options_item27": { 131 | "message": "بروتوكولات قائمه السماح:", 132 | "description": "" 133 | }, 134 | "options_item28": { 135 | "message": "قائمه البروتوكولات يمكن فتحها في نافذه تصفح جديده .وللاضافه السريعه قم باضافه 'magnet:' للسماح برورابط الملتقطه يتم فتحها في نافذه جديده", 136 | "description": "" 137 | }, 138 | "options_item29": { 139 | "message": "استخدام خدمه الثقه (WOT) لتقرر السماح او لا بالنوافذ المنبثقه اعتمادا علي المواقع الموثوقه والامنه واتخاذ القرار المناسب", 140 | "description": "" 141 | }, 142 | "options_item30": { 143 | "message": "محاكاه زر السماح 'allow' لمنع مانع النوافذ المنبثقه الداخلي للمتصفح من حظر هذه الطلبات ", 144 | "description": "" 145 | }, 146 | "options_item31": { 147 | "message": "عندما ضغط زر السماح 'trust' اضافه الموقع الي ", 148 | "description": "" 149 | }, 150 | "options_item32": { 151 | "message": "وجهة قائمه السماح", 152 | "description": "" 153 | }, 154 | "options_item33": { 155 | "message": "مصادر قائمه السماح", 156 | "description": "" 157 | }, 158 | "options_item34": { 159 | "message": "تنبيهات قائمه الحظر", 160 | "description": "" 161 | }, 162 | "options_item35": { 163 | "message": "استخدم (,)للفصل بين المواقع التي تريد الغاء التبيه لها اذا تم اظهار نافذه منبثقه", 164 | "description": "" 165 | }, 166 | "options_support": { 167 | "message": "دعم المطور", 168 | "description": "" 169 | }, 170 | "options_import": { 171 | "message": "استيراد", 172 | "description": "" 173 | }, 174 | "options_export": { 175 | "message": "تصدير", 176 | "description": "" 177 | }, 178 | "options_reset": { 179 | "message": "استعاده الافتراضيه", 180 | "description": "" 181 | }, 182 | "options_save": { 183 | "message": "حفظ", 184 | "description": "" 185 | }, 186 | "options_msg": { 187 | "message": "الخيارات التي تم حفظها", 188 | "description": "" 189 | }, 190 | "ui_msg": { 191 | "message": "الطلب المنبثق ل ", 192 | "description": "" 193 | }, 194 | "ui_button_allow": { 195 | "message": "السماح لهذا", 196 | "description": "" 197 | }, 198 | "ui_button_allow_value": { 199 | "message": "اسمح", 200 | "description": "" 201 | }, 202 | "ui_button_redirect": { 203 | "message": "توجيه هذه الصفحه الحاليه الي وجهة جديده بدلا من فتها في نافذه تصفح جديده", 204 | "description": "" 205 | }, 206 | "ui_button_redirect_value": { 207 | "message": "إعادة توجيه", 208 | "description": "" 209 | }, 210 | "ui_button_background": { 211 | "message": "فتح الرابط في نافذه جديده في الخلفيه", 212 | "description": "" 213 | }, 214 | "ui_button_background_value": { 215 | "message": "في الخلفية", 216 | "description": "" 217 | }, 218 | "ui_button_deny": { 219 | "message": "حظر النافذه المنبثقه او الصفحه الجديده من الفتح", 220 | "description": "" 221 | }, 222 | "ui_button_deny_value": { 223 | "message": "رفض", 224 | "description": "" 225 | }, 226 | "ui_button_trust": { 227 | "message": "اضافه هذا النطاق الي قائمه النوافذ المنبثقه المسموح بها", 228 | "description": "" 229 | }, 230 | "ui_button_trust_value": { 231 | "message": "وثوق", 232 | "description": "" 233 | }, 234 | "bg_msg_state_1": { 235 | "message": "مانع النوافذ المنبثقة مفعل بشكل عام ويحمي هذا التبويب", 236 | "description": "" 237 | }, 238 | "bg_msg_state_2": { 239 | "message": "مانع النوافذ المنبثقة مفعل بشكل عام ولكن لا يحمي هذا التبويب", 240 | "description": "" 241 | }, 242 | "bg_msg_state_3": { 243 | "message": "مانع النوافذ المنبثقة معطل بشكل عام ولا يحمي هذا التبويب", 244 | "description": "" 245 | }, 246 | "bg_msg_state_4": { 247 | "message": "مانع النوافذ المنبثقة معطل بشكل عام ولكن يحمي هذا التبويب", 248 | "description": "" 249 | } 250 | } -------------------------------------------------------------------------------- /v3/_locales/tr/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_description": { 3 | "message": "Bir siteden gelen tüm pop-up isteklerini kesinlikle engelle" 4 | }, 5 | "context_item2": { 6 | "message": "Son pop-up isteğine izin ver" 7 | }, 8 | "context_item3": { 9 | "message": "Son popup isteğini reddet" 10 | }, 11 | "context_item4": { 12 | "message": "Son popup isteğini bir arka plan sekmesinde aç" 13 | }, 14 | "context_item5": { 15 | "message": "Geçerli sekmeyi son popup isteğine yönlendir" 16 | }, 17 | "context_item6": { 18 | "message": "Odağı sayfadan son popup isteğine taşı" 19 | }, 20 | "options_item1": { 21 | "message": "Tek bir sayfa için maksimum popup isteği sayısı" 22 | }, 23 | "options_item2": { 24 | "message": "Her popup'ın görüntülenmesi için zaman aşımı (saniye cinsinden)" 25 | }, 26 | "options_item3": { 27 | "message": "Aynı kaynaktan gelen popup isteklerini engelleme" 28 | }, 29 | "options_item5": { 30 | "message": "Engellenen toplam istek sayısını araç çubuğu simgesinde görüntüle" 31 | }, 32 | "options_item6": { 33 | "message": "Bu kaynakların popup'larını engelleme:" 34 | }, 35 | "options_item7": { 36 | "message": "Bu sayfalardaki hiçbir pop-up'ı engelleme:" 37 | }, 38 | "options_item8": { 39 | "message": "Bu değişikliğin etkili olması için sekmeyi yenile." 40 | }, 41 | "options_item9": { 42 | "message": "Son eylemi gerçekleştirmek için geri sayım (saniye cinsinden)" 43 | }, 44 | "options_item10": { 45 | "message": "Önceki eylemi gerçekleştirmek üzere geri sayımı devre dışı bırakmak için sıfır sayısını kullan." 46 | }, 47 | "options_item13": { 48 | "message": "Kara liste kaynakları (ters çalışma modu):" 49 | }, 50 | "options_item15": { 51 | "message": "Bir popup açıldıktan sonra 2 saniye boyunca sayfanın yeniden yönlendirilmesini önle" 52 | }, 53 | "options_item17": { 54 | "message": "Bir popup açıldığında yapılacak varsayılan eylem" 55 | }, 56 | "options_item18": { 57 | "message": "Hiçbir şey yapma" 58 | }, 59 | "options_item19": { 60 | "message": "Talebi reddet" 61 | }, 62 | "options_item20": { 63 | "message": "Arkaplanda aç" 64 | }, 65 | "options_item21": { 66 | "message": "Sayfayı yönlendir" 67 | }, 68 | "options_item22": { 69 | "message": "Rozet arka plan rengi" 70 | }, 71 | "options_item23": { 72 | "message": "Mümkünse popup bildirimini yoksay (önerilmez)" 73 | }, 74 | "options_item25": { 75 | "message": "Açıklamalar" 76 | }, 77 | "options_item26": { 78 | "message": "Güncellemelerde SSS sayfasını görüntüle" 79 | }, 80 | "options_item27": { 81 | "message": "Bu protokolleri engelleme:" 82 | }, 83 | "options_item28": { 84 | "message": "Aşağıdaki kaynaklara sayfa yönlendirmesine izin ver:" 85 | }, 86 | "options_item29": { 87 | "message": "Sayfanın aynı kaynağa yeniden yönlendirilmesine izin ver" 88 | }, 89 | "options_item30": { 90 | "message": "Tarayıcının dahili popup engelleyicisinin bu istekleri engellemesini önlemek için 'izin ver' düğmesini simüle et" 91 | }, 92 | "options_item31": { 93 | "message": "“Güven” düğmesine basıldığında:" 94 | }, 95 | "options_item32": { 96 | "message": "Pop-up kaynağını artık engelleme" 97 | }, 98 | "options_item33": { 99 | "message": "Üst düzey sayfanın herhangi bir pop-up göstermesine izin ver" 100 | }, 101 | "options_item34": { 102 | "message": "Bu host adlarındaki bildirimleri sessize al:" 103 | }, 104 | "options_item35": { 105 | "message": "Popup arayüzüne aşağıdaki özel CSS kurallarını uygula:" 106 | }, 107 | "options_item40": { 108 | "message": "Yeni oluşturulan popup arayüzüne odaklan. Daha sonra gizlemek için kısayolları veya Escape tuşunu kullan" 109 | }, 110 | "options_item36": { 111 | "message": "Agresif statik IFrame algılamayı etkinleştir" 112 | }, 113 | "options_item37": { 114 | "message": "Bu mod etkinleştirildiğinde, eklenti 'JavaScript:' src niteliklerine sahip statik IFrame'leri izlemek için bir mutasyon gözlemcisi yükler. Bu, engelleme gücünü artırır ancak performans dezavantajları vardır." 115 | }, 116 | "options_item38": { 117 | "message": "Sayfa Yönlendirme" 118 | }, 119 | "options_item39": { 120 | "message": "Diğer" 121 | }, 122 | "options_item41": { 123 | "message": "Yeni bir popup isteğinde yapılacak eylem" 124 | }, 125 | "options_item42": { 126 | "message": "Sayfadaki popup konumu" 127 | }, 128 | "options_item43": { 129 | "message": "Sol Üst" 130 | }, 131 | "options_item44": { 132 | "message": "Sağ Üst" 133 | }, 134 | "options_item45": { 135 | "message": "Sol Alt" 136 | }, 137 | "options_item46": { 138 | "message": "Sağ Alt" 139 | }, 140 | "options_support": { 141 | "message": "Geliştirme Desteği" 142 | }, 143 | "options_import": { 144 | "message": "İçe Aktarma Tercihleri" 145 | }, 146 | "options_export": { 147 | "message": "Dışa Aktarma Tercihleri" 148 | }, 149 | "options_reset": { 150 | "message": "Varsayılanlara Sıfırla" 151 | }, 152 | "options_save": { 153 | "message": "Ayarları Kaydet" 154 | }, 155 | "options_msg": { 156 | "message": "Ayarlar kaydedildi" 157 | }, 158 | "options_review": { 159 | "message": "YouTube İncelemesi" 160 | }, 161 | "options_page": { 162 | "message": "SSS Sayfası" 163 | }, 164 | "options_t_1": { 165 | "message": "virgülle ayrılmış sunucu adları listesi (örnek: www.google.com, www.yahoo.com)" 166 | }, 167 | "options_t_2": { 168 | "message": "virgülle ayrılmış alan adları listesi (örnek: google.com, yahoo.com)" 169 | }, 170 | "options_t_3": { 171 | "message": "Belirli bir URL'ye göre popup isteğine yanıt olarak bir işlemi yürütmesi için uzantıya yol gösteren bir JSON nesnesi. Örnekler için SSS sayfasını okuyun." 172 | }, 173 | "ui_msg": { 174 | "message": "Aşağıdakiler için popup istenir" 175 | }, 176 | "ui_button_allow": { 177 | "message": "Bu popup'a izin ver (Alt + Shift + A veya Control + Option + A)" 178 | }, 179 | "ui_button_allow_value": { 180 | "message": "izin ver" 181 | }, 182 | "ui_button_redirect": { 183 | "message": "Mevcut sayfayı yeni bir sekmede veya popup'ta açmak yerine yeni hedefe yönlendir (Alt + Shift + R veya Control + Option + R)" 184 | }, 185 | "ui_button_redirect_value": { 186 | "message": "yönlendir" 187 | }, 188 | "ui_button_background": { 189 | "message": "Bağlantıyı bir arka plan sekmesinde aç (Alt + Shift + B veya Control + Option + B)" 190 | }, 191 | "ui_button_background_value": { 192 | "message": "arkaplan" 193 | }, 194 | "ui_button_deny": { 195 | "message": "Popup veya sekme açılışını reddet (Alt + Shift + D veya Control + Option + D)" 196 | }, 197 | "ui_button_deny_value": { 198 | "message": "reddet" 199 | }, 200 | "ui_button_trust": { 201 | "message": "Popup'ları açmak için bu alan adını beyaz listeye al (Alt + Shift + T veya Control + Option + T)" 202 | }, 203 | "ui_button_trust_value": { 204 | "message": "güven" 205 | }, 206 | "ui_button_trust_confirm": { 207 | "message": "Onaylamak için Tıkla" 208 | }, 209 | "bg_msg_state_1": { 210 | "message": "Popup Blocker (strict) genel olarak etkinleştirilmiştir ve bu sekmeyi korur" 211 | }, 212 | "bg_msg_state_2": { 213 | "message": "Popup Blocker (strict) genel olarak etkinleştirilmiştir ancak bu sekmeyi korumaz" 214 | }, 215 | "bg_msg_state_3": { 216 | "message": "Popup Blocker (strict) genel olarak devre dışıdır ve bu sekmeyi korumaz" 217 | }, 218 | "bg_msg_state_4": { 219 | "message": "Popup Blocker (strict) genel olarak devre dışıdır ancak bu sekmeyi korur" 220 | }, 221 | "bg_msg_reg": { 222 | "message": "Yanlış biçimlendirilmiş bir kural nedeniyle engelleme filtresinin kaydedilmesi başarısız oldu. Düzeltmek için ayarlar sayfasını kullan." 223 | }, 224 | "pp_enabled_g": { 225 | "message": "Etkin (Global)" 226 | }, 227 | "pp_enabled_c": { 228 | "message": "Etkin (Bu Alan Adında)" 229 | }, 230 | "pp_silent": { 231 | "message": "Ekran Bildirimleri" 232 | }, 233 | "pp_ignore": { 234 | "message": "Mümkünse Harekete Geç" 235 | }, 236 | "pp_redirect": { 237 | "message": "Sayfa Yönlendirmesini Engelle" 238 | }, 239 | "pp_last_request": { 240 | "message": "Son İstek" 241 | }, 242 | "pp_test": { 243 | "message": "Test Engelleyici" 244 | }, 245 | "pp_homepage": { 246 | "message": "Ana sayfa" 247 | }, 248 | "pp_options": { 249 | "message": "Ayarlar" 250 | }, 251 | "pp_shadow": { 252 | "message": "Gölge Kullan" 253 | }, 254 | "pp_allow": { 255 | "message": "İzin ver" 256 | }, 257 | "pp_block": { 258 | "message": "Engelle" 259 | }, 260 | "pp_health": { 261 | "message": "Arka plan betiği yanıt vermiyor gibi görünüyor. Eklentiyi yeniden başlatmayı denemek ister misiniz?" 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /v2/data/inject/uncode.js: -------------------------------------------------------------------------------- 1 | /* this is the entire unprotected code */ 2 | 3 | /* 4 | aggressive: 1; basic protection 5 | aggressive: 2; basic protection + frame protection 6 | aggressive: 3; basic protection + frame protection + mutation protection 7 | */ 8 | const uncode = (aggressive = 3) => { 9 | const script = document.currentScript; 10 | script.dataset.injected = true; 11 | 12 | const post = (name, detail) => script.dispatchEvent(new CustomEvent(name, { 13 | detail 14 | })); 15 | /* ask the script to validate a request */ 16 | const policy = (type, element, event, extra = {}) => { 17 | if (script.dataset.enabled === 'false') { 18 | return { 19 | block: false 20 | }; 21 | } 22 | if (event) { 23 | extra.defaultPrevented = event.defaultPrevented; 24 | extra.metaKey = event.metaKey || event.ctrlKey; 25 | extra.button = event.button || 0; 26 | extra.isTrusted = event.isTrusted; 27 | } 28 | post('policy', { 29 | type, 30 | href: element.action || element.href, // action for form element and href for anchor element 31 | target: element.target, 32 | download: element.download, 33 | tag: element.tagName, 34 | ...extra 35 | }); 36 | return { 37 | id: script.getAttribute('eid'), 38 | block: script.getAttribute('block') === 'true' 39 | }; 40 | }; 41 | /* simulate a window */ 42 | const simulate = (name, root, id) => new Proxy({}, { // window.location.replace 43 | get(obj, key) { 44 | return typeof root[key] === 'function' ? function(...args) { 45 | post('record', { 46 | id, 47 | name, 48 | method: root[key].name || key, // window.focus 49 | args 50 | }); 51 | } : simulate(key, root[key], id); 52 | } 53 | }); 54 | const protected = new WeakMap(); // keep reference of all protected window objects 55 | 56 | /* blocker */ 57 | const blocker = {}; 58 | 59 | blocker.frame = target => { 60 | const {src, tagName} = target; 61 | if (src && (tagName === 'IFRAME' || tagName === 'FRAME')) { 62 | const s = src.toLowerCase(); 63 | if (s.startsWith('javascript:') || s.startsWith('data:')) { 64 | try { 65 | blocker.install(target.contentWindow); 66 | } 67 | catch (e) {} 68 | } 69 | } 70 | }; 71 | 72 | blocker.onclick = e => { 73 | const a = e.target.closest('[target]') || e.target.closest('a'); 74 | // if this is not a form or anchor element, ignore the click 75 | if (a && policy('element.click', a, e).block) { 76 | blocker.onclick.pointer.apply(e); 77 | return true; 78 | } 79 | }; 80 | blocker.onclick.pointer = MouseEvent.prototype.preventDefault; 81 | 82 | blocker.install = (w = window) => { 83 | if (script.dataset.enabled === 'false' || protected.has(w)) { 84 | return; 85 | } 86 | const d = w.document; 87 | protected.set(w); 88 | 89 | /* overwrites */ 90 | const {HTMLAnchorElement, HTMLFormElement} = w; 91 | HTMLAnchorElement.prototype.click = new Proxy(HTMLAnchorElement.prototype.click, { 92 | apply(target, self, args) { 93 | const {block} = policy('dynamic.a.click', self); 94 | return block ? undefined : Reflect.apply(target, self, args); 95 | } 96 | }); 97 | HTMLAnchorElement.prototype.dispatchEvent = new Proxy(HTMLAnchorElement.prototype.dispatchEvent, { 98 | apply(target, self, args) { 99 | const ev = args[0]; 100 | const {block} = policy('dynamic.a.dispatch', self, ev); 101 | return block ? false : Reflect.apply(target, self, args); 102 | } 103 | }); 104 | HTMLFormElement.prototype.submit = new Proxy(HTMLFormElement.prototype.submit, { 105 | apply(target, self, args) { 106 | const {block} = policy('dynamic.form.submit', self); 107 | return block ? false : Reflect.apply(target, self, args); 108 | } 109 | }); 110 | HTMLFormElement.prototype.dispatchEvent = new Proxy(HTMLFormElement.prototype.dispatchEvent, { 111 | apply(target, self, args) { 112 | const {block} = policy('dynamic.form.dispatch', self); 113 | return block ? false : Reflect.apply(target, self, args); 114 | } 115 | }); 116 | 117 | /* iframe mess */ 118 | if (aggressive > 1) { 119 | const {HTMLIFrameElement, HTMLFrameElement} = w; 120 | 121 | const wf = Object.getOwnPropertyDescriptor(HTMLFrameElement.prototype, 'contentWindow'); 122 | Object.defineProperty(HTMLFrameElement.prototype, 'contentWindow', { 123 | configurable: true, 124 | enumerable: true, 125 | get: function() { 126 | const w = wf.get.call(this); 127 | try { 128 | blocker.install(w); 129 | } 130 | catch (e) {} 131 | return w; 132 | } 133 | }); 134 | const wif = Object.getOwnPropertyDescriptor(HTMLIFrameElement.prototype, 'contentWindow'); 135 | Object.defineProperty(HTMLIFrameElement.prototype, 'contentWindow', { 136 | configurable: true, 137 | enumerable: true, 138 | get: function() { 139 | const w = wif.get.call(this); 140 | try { 141 | blocker.install(w); 142 | } 143 | catch (e) {} 144 | return w; 145 | } 146 | }); 147 | const cf = Object.getOwnPropertyDescriptor(HTMLFrameElement.prototype, 'contentDocument'); 148 | Object.defineProperty(HTMLFrameElement.prototype, 'contentDocument', { 149 | configurable: true, 150 | enumerable: true, 151 | get: function() { 152 | const d = cf.get.call(this); 153 | try { 154 | blocker.install(d.defaultView); 155 | } 156 | catch (e) {} 157 | return d; 158 | } 159 | }); 160 | const cif = Object.getOwnPropertyDescriptor(HTMLIFrameElement.prototype, 'contentDocument'); 161 | Object.defineProperty(HTMLIFrameElement.prototype, 'contentDocument', { 162 | configurable: true, 163 | enumerable: true, 164 | get: function() { 165 | const d = cif.get.call(this); 166 | try { 167 | blocker.install(d.defaultView); 168 | } 169 | catch (e) {} 170 | return d; 171 | } 172 | }); 173 | } 174 | 175 | /* iframe creation with innerHTML */ 176 | if (aggressive > 2) { 177 | new MutationObserver(ms => { 178 | for (const m of ms) { 179 | for (const e of m.addedNodes) { 180 | blocker.frame(e); 181 | if (e.childElementCount) { 182 | [...e.querySelectorAll('iframe')].forEach(blocker.frame); 183 | } 184 | } 185 | } 186 | }).observe(d, {childList: true, subtree: true}); 187 | } 188 | 189 | /* click */ 190 | d.addEventListener('click', blocker.onclick, true); // with capture; 191 | 192 | /* window.open */ 193 | w.open = new Proxy(w.open, { 194 | apply(target, self, args) { 195 | // do not block if window is opened inside a frame 196 | const name = args[1]; 197 | if (name && typeof name === 'string' && frames[name]) { 198 | return Reflect.apply(target, self, args); 199 | } 200 | 201 | const {id, block} = policy('window.open', { 202 | href: args.length ? args[0] : '' 203 | }, null, { 204 | args 205 | }); 206 | if (block) { // return a window or a window-liked object 207 | if (script.dataset.shadow === 'true') { 208 | const iframe = document.createElement('iframe'); 209 | iframe.style.display = 'none'; 210 | document.body.appendChild(iframe); 211 | return iframe.contentWindow; 212 | } 213 | else { 214 | return simulate('self', window, id); 215 | } 216 | } 217 | return Reflect.apply(target, self, args); 218 | } 219 | }); 220 | 221 | /* DOM replacement (document.open removes all the DOM listeners) */ 222 | let dHTML = d.documentElement; 223 | d.write = new Proxy(d.write, { 224 | apply(target, self, args) { 225 | const r = Reflect.apply(target, self, args); 226 | if (dHTML !== self.documentElement) { 227 | dHTML = self.documentElement; 228 | self.addEventListener('click', blocker.onclick, true); 229 | } 230 | return r; 231 | } 232 | }); 233 | }; 234 | blocker.remove = (w = window, d = document) => { 235 | if (script.dataset.enabled === 'false' && protected.has(w)) { 236 | protected.delete(w); 237 | d.removeEventListener('click', blocker.onclick); 238 | } 239 | }; 240 | 241 | // always install since we do not know the enabling status right now 242 | blocker.install(); 243 | 244 | // receive configure 245 | new MutationObserver(() => { 246 | blocker[script.dataset.enabled === 'false' ? 'remove' : 'install'](); 247 | }).observe(script, { 248 | attributes: true, 249 | attributeFilter: ['data-enabled'] 250 | }); 251 | }; 252 | -------------------------------------------------------------------------------- /v2/_locales/sv/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_description": { 3 | "message": "Strikt blockera alla popup-förfrågningar från alla webbplatser", 4 | "description": "" 5 | }, 6 | "context_item1": { 7 | "message": "Testa din popup-blockerare", 8 | "description": "" 9 | }, 10 | "context_item2": { 11 | "message": "Tillåt den senaste popup-förfrågan", 12 | "description": "" 13 | }, 14 | "context_item3": { 15 | "message": "Neka den senaste popup-förfrågan", 16 | "description": "" 17 | }, 18 | "context_item4": { 19 | "message": "Använd skuggfönster för den här fliken", 20 | "description": "" 21 | }, 22 | "context_item5": { 23 | "message": "Öppna sida med alternativ", 24 | "description": "" 25 | }, 26 | "context_item6": { 27 | "message": "Ignorera popup-aviseringar om möjligt", 28 | "description": "" 29 | }, 30 | "options_item1": { 31 | "message": "Maximalt antal popup-förfrågningar för en enskild sida", 32 | "description": "" 33 | }, 34 | "options_item2": { 35 | "message": "Tid för visning av varje popup (i sekunder)", 36 | "description": "" 37 | }, 38 | "options_item3": { 39 | "message": "Blockera inte popup-förfrågningar från samma ursprung", 40 | "description": "" 41 | }, 42 | "options_item5": { 43 | "message": "Visa det totala antalet blockerade förfrågningar i verktygsfältikonen", 44 | "description": "" 45 | }, 46 | "options_item6": { 47 | "message": "Vitlistans destinationer:", 48 | "description": "" 49 | }, 50 | "options_item7": { 51 | "message": "Vitlistans källor:", 52 | "description": "" 53 | }, 54 | "options_item8": { 55 | "message": "För att den här ändringen ska träda i kraft, uppdatera fliken.", 56 | "description": "" 57 | }, 58 | "options_item9": { 59 | "message": "Nedräkning för att utföra den senaste åtgärden (i sekunder)", 60 | "description": "" 61 | }, 62 | "options_item10": { 63 | "message": "Använd nummer noll för att inaktivera nedräkningen för att utföra föregående åtgärd.", 64 | "description": "" 65 | }, 66 | "options_item11": { 67 | "message": "Kommaseparerad lista över värdnamn som inte kommer att blockeras (dessa värdnamn kan utfärda popup-fönster på vilken webbplats som helst).", 68 | "description": "" 69 | }, 70 | "options_item12": { 71 | "message": "Kommaseparerad lista över värdnamn som popup-blockeraren förlängning är helt inaktiverad på dem.", 72 | "description": "" 73 | }, 74 | "options_item13": { 75 | "message": "Svartlistans källor (omvänd driftläge):", 76 | "description": "" 77 | }, 78 | "options_item14": { 79 | "message": "Kommaseparerad lista över värdnamn som popup-blockeraren bara ska vara aktiv på. Detta innebär att popup-blockeraren är inaktiverad på alla andra värdnamn. För att inaktivera det här läget, rensa den svartlistans inmatning helt.", 80 | "description": "" 81 | }, 82 | "options_item15": { 83 | "message": "Förhindra omdirigering av sidor i 2 sekunder efter att en popup har begärts", 84 | "description": "" 85 | }, 86 | "options_item16": { 87 | "message": "Vissa webbplatser omdirigera användaren till annonssidan om popup-begäran om att visa en annons blockeras. Det här alternativet kan förhindra detta genom att inte tillåta sidomdirigering för den angivna tiden.", 88 | "description": "" 89 | }, 90 | "options_item17": { 91 | "message": "Standardåtgärd vid en popup-förfrågan", 92 | "description": "" 93 | }, 94 | "options_item18": { 95 | "message": "gör ingenting", 96 | "description": "" 97 | }, 98 | "options_item19": { 99 | "message": "neka förfrågan", 100 | "description": "" 101 | }, 102 | "options_item20": { 103 | "message": "öppna i bakgrunden", 104 | "description": "" 105 | }, 106 | "options_item21": { 107 | "message": "omdirigera sida", 108 | "description": "" 109 | }, 110 | "options_item22": { 111 | "message": "Bakgrundsfärg för bricka", 112 | "description": "" 113 | }, 114 | "options_item23": { 115 | "message": "Ignorera popup-aviseringar när det är möjligt (rekommenderas inte)", 116 | "description": "" 117 | }, 118 | "options_item24": { 119 | "message": "Detta kommer att \"ignorera\" eller \"acceptera\" en popup utan användarinteraktion (rekommenderas inte)", 120 | "description": "" 121 | }, 122 | "options_item25": { 123 | "message": "Beskrivningar", 124 | "description": "" 125 | }, 126 | "options_item26": { 127 | "message": "Visa Vanliga frågor-sidan vid uppdateringar", 128 | "description": "" 129 | }, 130 | "options_item27": { 131 | "message": "Vitlistans protokoll:", 132 | "description": "" 133 | }, 134 | "options_item28": { 135 | "message": "De listade protokollen kan öppnas i en ny webbläsarflik. Till exempel lägg till \"magnet:\" så att magnetlänkar öppnas i en webbläsarflik.", 136 | "description": "" 137 | }, 138 | "options_item29": { 139 | "message": "Använd tjänsten Web of Trust (WOT) för att bestämma om popup är från ett betrott värdnamn eller inte", 140 | "description": "" 141 | }, 142 | "options_item30": { 143 | "message": "Simulera knappen \"tillåt\" för att förhindra att webbläsarens interna popup-blockerare blockerar dessa förfrågningar", 144 | "description": "" 145 | }, 146 | "options_item31": { 147 | "message": "När \"lita på\"-knappen trycks, lägg till värdnamn till", 148 | "description": "" 149 | }, 150 | "options_item32": { 151 | "message": "Vitlistans destinationer", 152 | "description": "" 153 | }, 154 | "options_item33": { 155 | "message": "Vitlistans källor", 156 | "description": "" 157 | }, 158 | "options_item34": { 159 | "message": "Svartlista för aviseringar", 160 | "description": "" 161 | }, 162 | "options_item35": { 163 | "message": "Kommaseparerad lista över värdnamn som popup-blockeraren inte kommer att visa aviseringar om en popup begärs", 164 | "description": "" 165 | }, 166 | "options_support": { 167 | "message": "Stöd utvecklingen", 168 | "description": "" 169 | }, 170 | "options_import": { 171 | "message": "Importera", 172 | "description": "" 173 | }, 174 | "options_export": { 175 | "message": "Exportera", 176 | "description": "" 177 | }, 178 | "options_reset": { 179 | "message": "Återställ till standardvärden", 180 | "description": "" 181 | }, 182 | "options_save": { 183 | "message": "Spara", 184 | "description": "" 185 | }, 186 | "options_msg": { 187 | "message": "Alternativen sparas", 188 | "description": "" 189 | }, 190 | "ui_msg": { 191 | "message": "Popup begärs för", 192 | "description": "" 193 | }, 194 | "ui_button_allow": { 195 | "message": "Tillåt den här popupen", 196 | "description": "" 197 | }, 198 | "ui_button_allow_value": { 199 | "message": "tillåt", 200 | "description": "" 201 | }, 202 | "ui_button_redirect": { 203 | "message": "Omdirigera aktuell webbplats till den nya destinationen istället för att öppna den i en ny flik eller popup", 204 | "description": "" 205 | }, 206 | "ui_button_redirect_value": { 207 | "message": "omdirigera", 208 | "description": "" 209 | }, 210 | "ui_button_background": { 211 | "message": "Öppna länken i en bakgrundsflik", 212 | "description": "" 213 | }, 214 | "ui_button_background_value": { 215 | "message": "bakgrund", 216 | "description": "" 217 | }, 218 | "ui_button_deny": { 219 | "message": "Avvisa popupen eller fliköppningen", 220 | "description": "" 221 | }, 222 | "ui_button_deny_value": { 223 | "message": "neka", 224 | "description": "" 225 | }, 226 | "ui_button_trust": { 227 | "message": "Vitlista den här domänen för att öppna popup-fönster", 228 | "description": "" 229 | }, 230 | "ui_button_trust_value": { 231 | "message": "lita på", 232 | "description": "" 233 | }, 234 | "bg_msg_state_1": { 235 | "message": "Popup Blocker (strikt) är globalt aktiverad och skyddar denna flik", 236 | "description": "" 237 | }, 238 | "bg_msg_state_2": { 239 | "message": "Popup Blocker (strikt) är globalt aktiverad men skyddar inte denna flik", 240 | "description": "" 241 | }, 242 | "bg_msg_state_3": { 243 | "message": "Popup Blocker (strikt) är globalt inaktiverad och skyddar inte denna flik", 244 | "description": "" 245 | }, 246 | "bg_msg_state_4": { 247 | "message": "Popup Blocker (strikt) är globalt inaktiverad men skyddar denna flik", 248 | "description": "" 249 | } 250 | } -------------------------------------------------------------------------------- /v2/_locales/it/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_description": { 3 | "message": "Blocca tutti i popup di ogni sito", 4 | "description": "" 5 | }, 6 | "context_item1": { 7 | "message": "Verifica il tuo blocco di popup", 8 | "description": "" 9 | }, 10 | "context_item2": { 11 | "message": "Permetti l'ultima richiesta di popup", 12 | "description": "" 13 | }, 14 | "context_item3": { 15 | "message": "Rifiuta l'ultima richiesta di popup", 16 | "description": "" 17 | }, 18 | "context_item4": { 19 | "message": "Utilizza una finestra shadow per questo tab", 20 | "description": "" 21 | }, 22 | "context_item5": { 23 | "message": "Apri la pagina delle impostazioni", 24 | "description": "" 25 | }, 26 | "context_item6": { 27 | "message": "Ignora le notifiche di popup se possibile", 28 | "description": "" 29 | }, 30 | "options_item1": { 31 | "message": "Numero massimo di richieste di popup per una singola pagina", 32 | "description": "" 33 | }, 34 | "options_item2": { 35 | "message": "Tempo per mostrare ogni popup (in secondi)", 36 | "description": "" 37 | }, 38 | "options_item3": { 39 | "message": "Non bloccare i popup che hanno la stessa origine", 40 | "description": "" 41 | }, 42 | "options_item5": { 43 | "message": "Mostra il numero di richieste bloccate nell'icona nella barra degli strumenti", 44 | "description": "" 45 | }, 46 | "options_item6": { 47 | "message": "Destinazioni in whitelist:", 48 | "description": "" 49 | }, 50 | "options_item7": { 51 | "message": "Fonti in whitelist:", 52 | "description": "" 53 | }, 54 | "options_item8": { 55 | "message": "Perché questi cambiamenti abbiano effetto, aggiornare il tab.", 56 | "description": "" 57 | }, 58 | "options_item9": { 59 | "message": "Countdown per eseguire l'ultima azione (in secondi)", 60 | "description": "" 61 | }, 62 | "options_item10": { 63 | "message": "Usa il numero zero per disabilitare il countdown per eseguire l'azione precedente.", 64 | "description": "" 65 | }, 66 | "options_item11": { 67 | "message": "Elenco separato da virgola dei domini che non saranno bloccati (questi domini potranno causare popup su ogni sito).", 68 | "description": "" 69 | }, 70 | "options_item12": { 71 | "message": "Elenco separato da virgola dei domini in cui l'estensione per bloccare i popup sarà completamente disabilitata.", 72 | "description": "" 73 | }, 74 | "options_item13": { 75 | "message": "Fonti in blacklist (modalità di funzionamento inverso):", 76 | "description": "" 77 | }, 78 | "options_item14": { 79 | "message": "Elenco separato da virgola dei soli domini in cui il blocco dei popup sarà attivo. Questo significa che il blocco dei popup sarà disabilitato in TUTTI gli altri domini. Per disabilitare questa modalità, svuotare completamente il campo della blacklist.", 80 | "description": "" 81 | }, 82 | "options_item15": { 83 | "message": "Impedire il redirect di una pagina per 2 secondi dopo che viene richiesto un popup", 84 | "description": "" 85 | }, 86 | "options_item16": { 87 | "message": "Alcuni siti redirezionano l'utente a una pagina pubblicitaria se il popup che mostra una pubblicità viene bloccato. Questa opzioni evita questo non permettendo il redirect per un certo periodo di tempo.", 88 | "description": "" 89 | }, 90 | "options_item17": { 91 | "message": "Azione di default quando viene richiesto un popup", 92 | "description": "" 93 | }, 94 | "options_item18": { 95 | "message": "non fare niente", 96 | "description": "" 97 | }, 98 | "options_item19": { 99 | "message": "nega richiesta", 100 | "description": "" 101 | }, 102 | "options_item20": { 103 | "message": "apri in background", 104 | "description": "" 105 | }, 106 | "options_item21": { 107 | "message": "pagina di redirect", 108 | "description": "" 109 | }, 110 | "options_item22": { 111 | "message": "Colore di sfondo del badge", 112 | "description": "" 113 | }, 114 | "options_item23": { 115 | "message": "Ignora le notifiche di popup quando possibile (non raccomandato)", 116 | "description": "" 117 | }, 118 | "options_item24": { 119 | "message": "Questo \"ignorerà\" o \"accetterà\" un popup senza l'interazione dell'utente (non raccomandato)", 120 | "description": "" 121 | }, 122 | "options_item25": { 123 | "message": "Descrizioni", 124 | "description": "" 125 | }, 126 | "options_item26": { 127 | "message": "Mostra la pagina delle FAQ dopo l'aggiornamento", 128 | "description": "" 129 | }, 130 | "options_item27": { 131 | "message": "Protocolli in whitelist:", 132 | "description": "" 133 | }, 134 | "options_item28": { 135 | "message": "I protocolli elencati possono essere aperti un nuovo tab del browser. Per esempio, aggiungi \"magnet:\" per permettere ai link magnet di essere aperti un un tab del browser.", 136 | "description": "" 137 | }, 138 | "options_item29": { 139 | "message": "Usa il servizio di Web of Trust (WOT) per decidere se un popup arriva da un dominio fidato o meno.", 140 | "description": "" 141 | }, 142 | "options_item30": { 143 | "message": "Simulare il bottone di \"permesso\" per prevenire al blocco dei popup del browser di bloccare queste richieste.", 144 | "description": "" 145 | }, 146 | "options_item31": { 147 | "message": "Quando il bottone \"fidati\" viene premuto, aggiungere il dominio a", 148 | "description": "" 149 | }, 150 | "options_item32": { 151 | "message": "Destinazioni in whitelist", 152 | "description": "" 153 | }, 154 | "options_item33": { 155 | "message": "Fonti in whitelist", 156 | "description": "" 157 | }, 158 | "options_item34": { 159 | "message": "Blacklist delle notifiche", 160 | "description": "" 161 | }, 162 | "options_item35": { 163 | "message": "Elenco separato da virgola dei domini per cui il blocco dei popup non mostrerà notifiche quando ne verrà richiesto uno.", 164 | "description": "" 165 | }, 166 | "options_support": { 167 | "message": "Supporto per lo sviluppo", 168 | "description": "" 169 | }, 170 | "options_import": { 171 | "message": "Importa", 172 | "description": "" 173 | }, 174 | "options_export": { 175 | "message": "Esporta", 176 | "description": "" 177 | }, 178 | "options_reset": { 179 | "message": "Resetta alle impostazioni iniziali", 180 | "description": "" 181 | }, 182 | "options_save": { 183 | "message": "Salva", 184 | "description": "" 185 | }, 186 | "options_msg": { 187 | "message": "Le opzioni sono salvate", 188 | "description": "" 189 | }, 190 | "ui_msg": { 191 | "message": "Il popup è richiesto per", 192 | "description": "" 193 | }, 194 | "ui_button_allow": { 195 | "message": "Permetti questo popup", 196 | "description": "" 197 | }, 198 | "ui_button_allow_value": { 199 | "message": "permetti", 200 | "description": "" 201 | }, 202 | "ui_button_redirect": { 203 | "message": "Redireziona la pagina corrente alla nuova destinazione invece di aprirla in un nuovo tab o in un popup", 204 | "description": "" 205 | }, 206 | "ui_button_redirect_value": { 207 | "message": "redirect", 208 | "description": "" 209 | }, 210 | "ui_button_background": { 211 | "message": "Apri il link in un tab in background", 212 | "description": "" 213 | }, 214 | "ui_button_background_value": { 215 | "message": "background", 216 | "description": "" 217 | }, 218 | "ui_button_deny": { 219 | "message": "Rifiuta il popup o l'apertura del tab", 220 | "description": "" 221 | }, 222 | "ui_button_deny_value": { 223 | "message": "rifiuta", 224 | "description": "" 225 | }, 226 | "ui_button_trust": { 227 | "message": "Metti in whitelist questo dominio in modo che possa aprire i popup", 228 | "description": "" 229 | }, 230 | "ui_button_trust_value": { 231 | "message": "fidati", 232 | "description": "" 233 | }, 234 | "bg_msg_state_1": { 235 | "message": "Popup Blocker (strict) è abilitato globalmente e protegge questo tab", 236 | "description": "" 237 | }, 238 | "bg_msg_state_2": { 239 | "message": "Popup Blocker (strict) è abilitato globalmente, ma non protegge questo tab", 240 | "description": "" 241 | }, 242 | "bg_msg_state_3": { 243 | "message": "Popup Blocker (strict) è disabilitato globalmente e non protegge questo tab", 244 | "description": "" 245 | }, 246 | "bg_msg_state_4": { 247 | "message": "Popup Blocker (strict) è disabilitato globalmente, ma protegge questo tab", 248 | "description": "" 249 | } 250 | } -------------------------------------------------------------------------------- /v3/_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_description": { 3 | "message": "Strictly block all popup requests from any website" 4 | }, 5 | "context_item2": { 6 | "message": "Allow the last popup request" 7 | }, 8 | "context_item3": { 9 | "message": "Deny the last popup request" 10 | }, 11 | "context_item4": { 12 | "message": "Open the last popup request in a background tab" 13 | }, 14 | "context_item5": { 15 | "message": "Redirect the current tab to the last popup request" 16 | }, 17 | "context_item6": { 18 | "message": "Move focus from page to the last popup request" 19 | }, 20 | "options_item1": { 21 | "message": "Maximum number of popup requests for a single page" 22 | }, 23 | "options_item2": { 24 | "message": "Timeout for displaying each popup (in seconds)" 25 | }, 26 | "options_item3": { 27 | "message": "Do not block popup requests from same origin" 28 | }, 29 | "options_item5": { 30 | "message": "Display the total number of blocked requests in the toolbar icon" 31 | }, 32 | "options_item6": { 33 | "message": "Do not block popups of these origins:" 34 | }, 35 | "options_item7": { 36 | "message": "Do not block any popup on these pages:" 37 | }, 38 | "options_item8": { 39 | "message": "For this change to take effect, refresh the tab." 40 | }, 41 | "options_item9": { 42 | "message": "Countdown for performing the last action (in seconds)" 43 | }, 44 | "options_item10": { 45 | "message": "Use zero number to disable the countdown to perform the previous action." 46 | }, 47 | "options_item13": { 48 | "message": "Blacklist sources (reverse operation mode):" 49 | }, 50 | "options_item15": { 51 | "message": "Prevent page redirection for 2 seconds after a popup is requested" 52 | }, 53 | "options_item17": { 54 | "message": "Default action when a popup is requested" 55 | }, 56 | "options_item18": { 57 | "message": "Do nothing" 58 | }, 59 | "options_item19": { 60 | "message": "Deny request" 61 | }, 62 | "options_item20": { 63 | "message": "Open in background" 64 | }, 65 | "options_item21": { 66 | "message": "Redirect page" 67 | }, 68 | "options_item22": { 69 | "message": "Badge background-color" 70 | }, 71 | "options_item23": { 72 | "message": "Ignore popup notification when possible (not recommended)" 73 | }, 74 | "options_item25": { 75 | "message": "Descriptions" 76 | }, 77 | "options_item26": { 78 | "message": "Display FAQs page on updates" 79 | }, 80 | "options_item27": { 81 | "message": "Do not block these protocols:" 82 | }, 83 | "options_item28": { 84 | "message": "Allow page redirection to the following origins:" 85 | }, 86 | "options_item29": { 87 | "message": "Allow page redirection to the same origin" 88 | }, 89 | "options_item30": { 90 | "message": "Simulate the 'allow' button to prevent your browser's internal popup blocker from blocking these requests" 91 | }, 92 | "options_item31": { 93 | "message": "When \"trust\" button is pressed:" 94 | }, 95 | "options_item32": { 96 | "message": "Do not block the popup origin anymore" 97 | }, 98 | "options_item33": { 99 | "message": "Allow the top-level page to show any popups" 100 | }, 101 | "options_item34": { 102 | "message": "Mute notifications on these hostnames:" 103 | }, 104 | "options_item35": { 105 | "message": "Apply the following custom CSS rules to the popup interface:" 106 | }, 107 | "options_item40": { 108 | "message": "Focus the newly generated popup interface. You can then use shortcuts or the Escape key to hide" 109 | }, 110 | "options_item36": { 111 | "message": "Enable aggressive static IFrame detection" 112 | }, 113 | "options_item37": { 114 | "message": "When this mode is enabled, the extension installs a mutation observer to monitor static IFrames with 'JavaScript:' src attributes. This enhances the blocking power but has performance drawbacks." 115 | }, 116 | "options_item38": { 117 | "message": "Page Redirection" 118 | }, 119 | "options_item39": { 120 | "message": "Misc" 121 | }, 122 | "options_item41": { 123 | "message": "Action on a new popup request" 124 | }, 125 | "options_item42": { 126 | "message": "Popup position on page" 127 | }, 128 | "options_item43": { 129 | "message": "Top Left" 130 | }, 131 | "options_item44": { 132 | "message": "Top Right" 133 | }, 134 | "options_item45": { 135 | "message": "Bottom Left" 136 | }, 137 | "options_item46": { 138 | "message": "Bottom Right" 139 | }, 140 | "options_item47": { 141 | "message": "Protection Scope" 142 | }, 143 | "options_item48": { 144 | "message": "Read documentation on how to configure extension's scope." 145 | }, 146 | "options_item49": { 147 | "message": "Width of the popup (in pixels)" 148 | }, 149 | "options_sync": { 150 | "message": "Sync this Preference" 151 | }, 152 | "options_support": { 153 | "message": "Support Development" 154 | }, 155 | "options_import": { 156 | "message": "Import Preferences" 157 | }, 158 | "options_export": { 159 | "message": "Export Preferences" 160 | }, 161 | "options_reset": { 162 | "message": "Reset to Defaults" 163 | }, 164 | "options_save": { 165 | "message": "Save Options" 166 | }, 167 | "options_msg": { 168 | "message": "Options are saved" 169 | }, 170 | "options_review": { 171 | "message": "YouTube Review" 172 | }, 173 | "options_page": { 174 | "message": "FAQs Page" 175 | }, 176 | "options_t_1": { 177 | "message": "comma-separated list of hostnames (e.g.: www.google.com, www.yahoo.com)" 178 | }, 179 | "options_t_2": { 180 | "message": "comma-separated list of domains (e.g.: google.com, yahoo.com)" 181 | }, 182 | "options_t_3": { 183 | "message": "A JSON object that guides the extension in executing a specific action in response to a popup request, determined by its URL. Read the FAQs page for examples." 184 | }, 185 | "options_t_4": { 186 | "message": "Enter a comma-separated list of patterns to define the global scope. Only change this if you know what you're doing, as incorrect values may break the extension. Read FAQs page for more info" 187 | }, 188 | "ui_msg": { 189 | "message": "Popup is requested for" 190 | }, 191 | "ui_button_allow": { 192 | "message": "Allow this popup (Alt + Shift + A or Control + Option + A)" 193 | }, 194 | "ui_button_allow_value": { 195 | "message": "allow" 196 | }, 197 | "ui_button_redirect": { 198 | "message": "Redirect current page to the new destination instead of opening it in a new tab or popup (Alt + Shift + R or Control + Option + R)" 199 | }, 200 | "ui_button_redirect_value": { 201 | "message": "redirect" 202 | }, 203 | "ui_button_background": { 204 | "message": "Open the link in a background tab (Alt + Shift + B or Control + Option + B)" 205 | }, 206 | "ui_button_background_value": { 207 | "message": "background" 208 | }, 209 | "ui_button_deny": { 210 | "message": "Decline the popup or tab opening (Alt + Shift + D or Control + Option + D)" 211 | }, 212 | "ui_button_deny_value": { 213 | "message": "deny" 214 | }, 215 | "ui_button_trust": { 216 | "message": "White-list this domain to open popups (Alt + Shift + T or Control + Option + T)" 217 | }, 218 | "ui_button_trust_value": { 219 | "message": "trust" 220 | }, 221 | "ui_button_trust_confirm": { 222 | "message": "Click to Confirm" 223 | }, 224 | "bg_msg_state_0": { 225 | "message": "Popup Blocker is globally enabled, but not active in this tab—likely because it's an internal page, out of scope page or still loading." 226 | }, 227 | "bg_msg_state_1": { 228 | "message": "Popup Blocker is globally enabled and protects this tab" 229 | }, 230 | "bg_msg_state_2": { 231 | "message": "Popup Blocker is globally enabled but does not protect this tab" 232 | }, 233 | "bg_msg_state_3": { 234 | "message": "Popup Blocker is globally disabled and does not protect this tab" 235 | }, 236 | "bg_msg_state_4": { 237 | "message": "Popup Blocker is globally disabled but protects this tab" 238 | }, 239 | "bg_msg_reg": { 240 | "message": "Registering blocking filter failed due to an improperly formatted rule. Use the options page to fix it." 241 | }, 242 | "pp_enabled_g": { 243 | "message": "Enabled (Globally)" 244 | }, 245 | "pp_enabled_c": { 246 | "message": "Enabled (This Domain)" 247 | }, 248 | "pp_enabled_cf": { 249 | "message": "Include/Exclude sub-frames" 250 | }, 251 | "pp_silent": { 252 | "message": "Display Notifications" 253 | }, 254 | "pp_ignore": { 255 | "message": "Run Action when Possible" 256 | }, 257 | "pp_redirect": { 258 | "message": "Block Page Redirection" 259 | }, 260 | "pp_last_request": { 261 | "message": "Last Request" 262 | }, 263 | "pp_test": { 264 | "message": "Test Blocker" 265 | }, 266 | "pp_homepage": { 267 | "message": "Homepage" 268 | }, 269 | "pp_options": { 270 | "message": "Options" 271 | }, 272 | "pp_shadow": { 273 | "message": "Use Shadow" 274 | }, 275 | "pp_allow": { 276 | "message": "Allow" 277 | }, 278 | "pp_block": { 279 | "message": "Block" 280 | }, 281 | "pp_health": { 282 | "message": "The background script seems to be unresponsive. Do you want to try restarting the extension?" 283 | } 284 | } 285 | -------------------------------------------------------------------------------- /v2/_locales/de/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_description": { 3 | "message": "Strikt alle Pop-up-Anfragen von jeder Webseite blockieren", 4 | "description": "" 5 | }, 6 | "context_item1": { 7 | "message": "Pop-up-Blocker testen", 8 | "description": "" 9 | }, 10 | "context_item2": { 11 | "message": "Letztes Pop-up zulassen", 12 | "description": "" 13 | }, 14 | "context_item3": { 15 | "message": "Letztes Pop-up blockieren", 16 | "description": "" 17 | }, 18 | "context_item4": { 19 | "message": "Schattenfenster für diesen Tab verwenden", 20 | "description": "" 21 | }, 22 | "context_item5": { 23 | "message": "Optionen", 24 | "description": "" 25 | }, 26 | "context_item6": { 27 | "message": "Pop-up-Benachrichtigungen wenn möglich unterbinden", 28 | "description": "" 29 | }, 30 | "options_item1": { 31 | "message": "Maximale Anzahl von Pop-up-Anfragen von einer einzelnen Webseite", 32 | "description": "" 33 | }, 34 | "options_item2": { 35 | "message": "Zeitüberschreitung für die Anzeige von Pop-up-Anfragen (in Sekunden)", 36 | "description": "" 37 | }, 38 | "options_item3": { 39 | "message": "Keine Pop-up-Anfragen von der gleichen Quelle blockieren", 40 | "description": "" 41 | }, 42 | "options_item5": { 43 | "message": "Gesamtanzahl der geblockten Pop-ups in der Symbolleiste anzeigen", 44 | "description": "" 45 | }, 46 | "options_item6": { 47 | "message": "Whitelist Ziele:", 48 | "description": "" 49 | }, 50 | "options_item7": { 51 | "message": "Whitelist Quellen:", 52 | "description": "" 53 | }, 54 | "options_item8": { 55 | "message": "Aktualisiere den Tab, um die Änderungen anzuwenden.", 56 | "description": "" 57 | }, 58 | "options_item9": { 59 | "message": "Countdown für das automatische Ausführen der letzten Aktion (in Sekunden)", 60 | "description": "" 61 | }, 62 | "options_item10": { 63 | "message": "Verwende die Zahl 0, um den Countdown für die vorherige Aktion zu deaktivieren.", 64 | "description": "" 65 | }, 66 | "options_item11": { 67 | "message": "Kommagetrennte Liste von Domains, die nicht blockiert werden (Diese Domains können auf jeder Webseite Pop-ups anzeigen)", 68 | "description": "" 69 | }, 70 | "options_item12": { 71 | "message": "Kommagetrennte Liste von Domains, bei denen der Pop-up Blocker vollständig deaktiviert wird.", 72 | "description": "" 73 | }, 74 | "options_item13": { 75 | "message": "Blacklist Quellen (umgekehrte Funktionsweise):", 76 | "description": "" 77 | }, 78 | "options_item14": { 79 | "message": "Kommagetrennte Liste von Domains, auf denen der Pop-up Blocker ausschließlich aktiv sein soll. Dies bedeutet, dass der Pop-up Blocker auf ALLEN anderen Domains deaktiviert ist. Um diesen Modus zu deaktivieren, muss die Blacklist vollständig leer sein.", 80 | "description": "" 81 | }, 82 | "options_item15": { 83 | "message": "Weiterleitungen für 2 Sekunden verhindern, nachdem ein Pop-up aufgerufen wurde", 84 | "description": "" 85 | }, 86 | "options_item16": { 87 | "message": "Einige Webseiten leiten den Benutzer auf eine Werbeseite weiter, falls ein Pop-up blockiert wurde. Diese Einstellung verhindert dies, indem Weiterleitungen für eine kurze Zeit verhindert werden.", 88 | "description": "" 89 | }, 90 | "options_item17": { 91 | "message": "Standardaktion bei einem neuem Pop-up", 92 | "description": "" 93 | }, 94 | "options_item18": { 95 | "message": "Keine Aktion", 96 | "description": "" 97 | }, 98 | "options_item19": { 99 | "message": "Blockieren", 100 | "description": "" 101 | }, 102 | "options_item20": { 103 | "message": "Im Hintergrund öffnen", 104 | "description": "" 105 | }, 106 | "options_item21": { 107 | "message": "Webseite weiterleiten", 108 | "description": "" 109 | }, 110 | "options_item22": { 111 | "message": "Hintergrundfarbe der Benachrichtigung", 112 | "description": "" 113 | }, 114 | "options_item23": { 115 | "message": "Ignoriere Pop-up Benachrichtigungen, falls möglich (nicht empfohlen)", 116 | "description": "" 117 | }, 118 | "options_item24": { 119 | "message": "Dies \"ignoriert\" oder \"akzeptiert\" ein Pop-up ohne Benutzerinteraktion (nicht empfohlen)", 120 | "description": "" 121 | }, 122 | "options_item25": { 123 | "message": "Beschreibungen", 124 | "description": "" 125 | }, 126 | "options_item26": { 127 | "message": "FAQ-Seite bei Aktualisierungen anzeigen", 128 | "description": "" 129 | }, 130 | "options_item27": { 131 | "message": "Whitelist Protokolle:", 132 | "description": "" 133 | }, 134 | "options_item28": { 135 | "message": "Die aufgelisteten Protokolle können in einem neuen Tab im Browser geöffnet werden. Füge zum Beispiel 'magnet:' hinzu, um das Öffnen von magnet Links in einem Tab zu erlauben.", 136 | "description": "" 137 | }, 138 | "options_item29": { 139 | "message": "Web of Trust (WOT) Service verwenden, um ein Pop-up als vertrauenswürdig oder nicht vertrauenswürdig einzustufen", 140 | "description": "" 141 | }, 142 | "options_item30": { 143 | "message": "Simuliere den 'Erlauben' Button, um zu verhindern, dass der integrierte Pop-up Blocker des Browsers diese Anfragen blockiert", 144 | "description": "" 145 | }, 146 | "options_item31": { 147 | "message": "Mit Klick auf 'Vertrauen' wird die Domain hinzugefügt zu", 148 | "description": "" 149 | }, 150 | "options_item32": { 151 | "message": "Whitelist Ziele:", 152 | "description": "" 153 | }, 154 | "options_item33": { 155 | "message": "Whitelist Quellen:", 156 | "description": "" 157 | }, 158 | "options_item34": { 159 | "message": "Blacklist für Benachrichtigungen:", 160 | "description": "" 161 | }, 162 | "options_item35": { 163 | "message": "Kommagetrennte Liste von Domains, bei denen der Pop-up Blocker keine Benachrichtigungen für Pop-ups anzeigt.", 164 | "description": "" 165 | }, 166 | "options_support": { 167 | "message": "Entwicklung unterstützen", 168 | "description": "" 169 | }, 170 | "options_import": { 171 | "message": "Importieren", 172 | "description": "" 173 | }, 174 | "options_export": { 175 | "message": "Exportieren", 176 | "description": "" 177 | }, 178 | "options_reset": { 179 | "message": "Auf Standard zurücksetzen", 180 | "description": "" 181 | }, 182 | "options_save": { 183 | "message": "Speichern", 184 | "description": "" 185 | }, 186 | "options_msg": { 187 | "message": "Einstellungen wurden gespeichert.", 188 | "description": "" 189 | }, 190 | "ui_msg": { 191 | "message": "Pop-up-Anfrage von folgender Webseite", 192 | "description": "" 193 | }, 194 | "ui_button_allow": { 195 | "message": "Dieses Pop-up zulassen", 196 | "description": "" 197 | }, 198 | "ui_button_allow_value": { 199 | "message": "Erlauben", 200 | "description": "" 201 | }, 202 | "ui_button_redirect": { 203 | "message": "Leitet die aktuelle Webseite auf das Ziel weiter, anstatt es in einem neuen Tab oder Pop-up zu öffnen", 204 | "description": "" 205 | }, 206 | "ui_button_redirect_value": { 207 | "message": "Weiterleiten", 208 | "description": "" 209 | }, 210 | "ui_button_background": { 211 | "message": "Öffne den Link in einem Tab im Hintergrund", 212 | "description": "" 213 | }, 214 | "ui_button_background_value": { 215 | "message": "Hintergrund", 216 | "description": "" 217 | }, 218 | "ui_button_deny": { 219 | "message": "Öffnen des Pop-ups oder neuen Tabs blockieren", 220 | "description": "" 221 | }, 222 | "ui_button_deny_value": { 223 | "message": "Ablehnen", 224 | "description": "" 225 | }, 226 | "ui_button_trust": { 227 | "message": "Füge diese Domain zu der Whitelist hinzu, um Pop-ups künftig immer zu erlauben", 228 | "description": "" 229 | }, 230 | "ui_button_trust_value": { 231 | "message": "Vertrauen", 232 | "description": "" 233 | }, 234 | "bg_msg_state_1": { 235 | "message": "Popup Blocker (strict) ist allgemein aktiviert und beschützt diesen Tab.", 236 | "description": "" 237 | }, 238 | "bg_msg_state_2": { 239 | "message": "Popup Blocker (strict) ist allgemein aktiviert, aber beschützt diesen Tab nicht.", 240 | "description": "" 241 | }, 242 | "bg_msg_state_3": { 243 | "message": "Popup Blocker (strict) ist allgemein deaktiviert und beschützt diesen Tab nicht.", 244 | "description": "" 245 | }, 246 | "bg_msg_state_4": { 247 | "message": "Popup Blocker (strict) ist allgemein deaktiviert, aber beschützt diesen Tab.", 248 | "description": "" 249 | } 250 | } -------------------------------------------------------------------------------- /v3/data/options/index.js: -------------------------------------------------------------------------------- 1 | /* global config */ 2 | 'use strict'; 3 | 4 | // localization 5 | [...document.querySelectorAll('[data-i18n]')].forEach(e => { 6 | if (e.dataset.i18nValue) { 7 | e.setAttribute(e.dataset.i18nValue, chrome.i18n.getMessage(e.dataset.i18n)); 8 | } 9 | else { 10 | e.textContent = chrome.i18n.getMessage(e.dataset.i18n); 11 | } 12 | }); 13 | 14 | async function restore(defaults = false) { 15 | document.getElementById('user-styling').value = localStorage.getItem('user-styling') || ''; 16 | 17 | // sync 18 | await config.sync(); 19 | for (const key of config.synced) { 20 | const e = document.querySelector(`input[type=checkbox][value="${key}"]`); 21 | if (e) { 22 | e.checked = true; 23 | } 24 | } 25 | 26 | const prefs = defaults ? config : await config.get([ 27 | 'numbers', 'timeout', 'countdown', 'badge', 'badge-color', 'domain', 28 | 'simulate-allow', 'focus-popup', 'faqs', 'popup-hosts', 29 | 'block-page-redirection', 'block-page-redirection-same-origin', 'block-page-redirection-hostnames', 30 | 'top-hosts', 'protocols', 'silent', 'default-action', 31 | 'whitelist-mode', 'immediate-action', 'rules', 'placement', 'scope', 'width' 32 | ]); 33 | 34 | document.getElementById('rules').value = JSON.stringify(prefs.rules, undefined, ' '); 35 | document.getElementById('numbers').value = prefs.numbers; 36 | document.getElementById('timeout').value = prefs.timeout; 37 | document.getElementById('countdown').value = prefs.countdown; 38 | document.getElementById('badge').checked = prefs.badge; 39 | document.getElementById('badge-color').value = prefs['badge-color']; 40 | document.getElementById('domain').checked = prefs.domain; 41 | document.getElementById('simulate-allow').checked = prefs['simulate-allow']; 42 | document.getElementById('focus-popup').checked = prefs['focus-popup']; 43 | document.getElementById('faqs').checked = prefs.faqs; 44 | document.getElementById('block-page-redirection').checked = prefs['block-page-redirection']; 45 | document.getElementById('block-page-redirection-same-origin').checked = prefs['block-page-redirection-same-origin']; 46 | document.getElementById('block-page-redirection-hostnames').value = 47 | prefs['block-page-redirection-hostnames'].join(', '); 48 | document.getElementById('popup-hosts').value = prefs['popup-hosts'].join(', '); 49 | document.getElementById('top-hosts').value = prefs['top-hosts'].join(', '); 50 | document.getElementById('protocols').value = prefs.protocols.join(', '); 51 | document.getElementById('silent').value = prefs.silent.join(', '); 52 | document.getElementById('default-action').value = prefs['default-action']; 53 | document.getElementById('whitelist-mode').value = prefs['whitelist-mode']; 54 | document.getElementById('immediate-action').checked = prefs['immediate-action']; 55 | document.getElementById('placement').value = prefs['placement']; 56 | document.getElementById('scope').value = prefs['scope'].join(', '); 57 | document.getElementById('width').value = prefs['width']; 58 | } 59 | 60 | const prepare = str => str.split(/\s*,\s*/) 61 | .map(s => s.replace('http://', '').replace('https://', '').split('/')[0].trim()) 62 | .filter((h, i, l) => h && l.indexOf(h) === i); 63 | 64 | async function save() { 65 | // first update synced storage (use chrome.storage) 66 | config.synced = [...document.querySelectorAll('input[type=checkbox][name=synced]:checked')].map(e => e.value); 67 | await chrome.storage.local.set({ 68 | synced: config.synced 69 | }); 70 | 71 | const scopes = []; 72 | const patterns = document.getElementById('scope').value.split(/\s*,\s*/).filter((s, i, l) => { 73 | return s && l.indexOf(s) === i; 74 | }); 75 | for (const pattern of patterns) { 76 | try { 77 | await chrome.scripting.registerContentScripts([{ 78 | 'id': 'test', 79 | 'js': ['/data/inject/test.js'], 80 | 'world': 'MAIN', 81 | 'matches': [pattern] 82 | }]); 83 | scopes.push(pattern); 84 | } 85 | catch (e) { 86 | console.error('[Invalid Pattern for Scope]', pattern, e); 87 | } 88 | await chrome.scripting.unregisterContentScripts({ 89 | ids: ['test'] 90 | }).catch(() => {}); 91 | } 92 | if (scopes.length === 0) { 93 | scopes.push('*://*/*'); 94 | } 95 | 96 | const settings = { 97 | 'width': Math.max(300, document.getElementById('width').value), 98 | 'numbers': Math.max(1, document.getElementById('numbers').value), 99 | 'timeout': Math.max(1, document.getElementById('timeout').value), 100 | 'countdown': Math.max(0, document.getElementById('countdown').value), 101 | 'badge': document.getElementById('badge').checked, 102 | 'badge-color': document.getElementById('badge-color').value, 103 | 'domain': document.getElementById('domain').checked, 104 | 'simulate-allow': document.getElementById('simulate-allow').checked, 105 | 'focus-popup': document.getElementById('focus-popup').checked, 106 | 'faqs': document.getElementById('faqs').checked, 107 | 'block-page-redirection': document.getElementById('block-page-redirection').checked, 108 | 'block-page-redirection-same-origin': document.getElementById('block-page-redirection-same-origin').checked, 109 | 'block-page-redirection-hostnames': prepare(document.getElementById('block-page-redirection-hostnames').value), 110 | 'popup-hosts': prepare(document.getElementById('popup-hosts').value), 111 | 'top-hosts': prepare(document.getElementById('top-hosts').value), 112 | 'silent': prepare(document.getElementById('silent').value), 113 | 'protocols': document.getElementById('protocols').value 114 | .split(/\s*,\s*/).filter(s => s && s.endsWith(':')), 115 | 'default-action': document.getElementById('default-action').value, 116 | 'whitelist-mode': document.getElementById('whitelist-mode').value, 117 | 'immediate-action': document.getElementById('immediate-action').checked, 118 | 'placement': document.getElementById('placement').value, 119 | 'scope': scopes 120 | }; 121 | 122 | let orules = ''; 123 | try { 124 | settings.rules = JSON.parse(document.getElementById('rules').value || '{}'); 125 | } 126 | catch (e) { 127 | orules = document.getElementById('rules').value; 128 | alert('Cannot parse rules: ' + e.message); 129 | } 130 | 131 | localStorage.setItem('user-styling', document.getElementById('user-styling').value || ''); 132 | 133 | config.set(settings).then(() => { 134 | const status = document.getElementById('status'); 135 | status.textContent = chrome.i18n.getMessage('options_msg'); 136 | restore(); 137 | setTimeout(() => { 138 | status.textContent = ''; 139 | if (orules) { 140 | document.getElementById('rules').value = orules; 141 | } 142 | }, 750); 143 | }); 144 | } 145 | 146 | document.addEventListener('DOMContentLoaded', () => restore()); 147 | document.getElementById('save').addEventListener('click', save); 148 | 149 | document.addEventListener('click', e => { 150 | if (e.target.href && e.target.href.indexOf('#') !== -1) { 151 | document.querySelector('details').open = true; 152 | } 153 | }); 154 | 155 | document.getElementById('reset').addEventListener('click', () => restore(true)); 156 | document.getElementById('export').addEventListener('click', () => { 157 | // get all stored prefs 158 | config.get([]).then(prefs => { 159 | const text = JSON.stringify(prefs, null, '\t'); 160 | const blob = new Blob([text], {type: 'application/json'}); 161 | const objectURL = URL.createObjectURL(blob); 162 | Object.assign(document.createElement('a'), { 163 | href: objectURL, 164 | type: 'application/json', 165 | download: 'popup-blocker-preferences.json' 166 | }).dispatchEvent(new MouseEvent('click')); 167 | setTimeout(() => URL.revokeObjectURL(objectURL)); 168 | }); 169 | }); 170 | document.getElementById('import').addEventListener('click', () => { 171 | const fileInput = document.createElement('input'); 172 | fileInput.style.display = 'none'; 173 | fileInput.type = 'file'; 174 | fileInput.accept = '.json'; 175 | fileInput.acceptCharset = 'utf-8'; 176 | 177 | document.body.appendChild(fileInput); 178 | fileInput.initialValue = fileInput.value; 179 | fileInput.onchange = readFile; 180 | fileInput.click(); 181 | 182 | function readFile() { 183 | if (fileInput.value !== fileInput.initialValue) { 184 | const file = fileInput.files[0]; 185 | if (file.size > 100e6) { 186 | return console.warn('The file is too large!'); 187 | } 188 | const fReader = new FileReader(); 189 | fReader.onloadend = event => { 190 | fileInput.remove(); 191 | const json = JSON.parse(event.target.result); 192 | config.set(json).then(() => chrome.runtime.reload()); 193 | }; 194 | fReader.readAsText(file, 'utf-8'); 195 | } 196 | } 197 | }); 198 | // support 199 | document.getElementById('support').addEventListener('click', () => chrome.tabs.create({ 200 | url: chrome.runtime.getManifest().homepage_url + '?rd=donate' 201 | })); 202 | // review 203 | document.getElementById('review').addEventListener('click', () => chrome.tabs.create({ 204 | url: 'https://www.youtube.com/watch?v=Jp-RaiTHzCQ' 205 | })); 206 | // FAQs Page 207 | document.getElementById('page').addEventListener('click', () => chrome.tabs.create({ 208 | url: chrome.runtime.getManifest().homepage_url 209 | })); 210 | 211 | // links 212 | for (const a of [...document.querySelectorAll('[data-href]')]) { 213 | if (a.hasAttribute('href') === false) { 214 | a.href = chrome.runtime.getManifest().homepage_url + '#' + a.dataset.href; 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /v2/_locales/fr/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_description": { 3 | "message": "Bloquer strictement toutes les demandes de popup provenant de n'importe quel site web", 4 | "description": "" 5 | }, 6 | "context_item1": { 7 | "message": "Testez votre bloqueur de popups", 8 | "description": "" 9 | }, 10 | "context_item2": { 11 | "message": "Autoriser la dernière demande de popup", 12 | "description": "" 13 | }, 14 | "context_item3": { 15 | "message": "Refuser la dernière demande de popup", 16 | "description": "" 17 | }, 18 | "context_item4": { 19 | "message": "Utiliser une fenêtre d'ombre pour cet onglet", 20 | "description": "" 21 | }, 22 | "context_item5": { 23 | "message": "Ouvrir la page des options", 24 | "description": "" 25 | }, 26 | "context_item6": { 27 | "message": "Ignorer la popup si possible", 28 | "description": "" 29 | }, 30 | "options_item1": { 31 | "message": "Nombre maximum de demandes de popup pour une seule page", 32 | "description": "" 33 | }, 34 | "options_item2": { 35 | "message": "Délai d'affichage de chaque popup (en secondes)", 36 | "description": "" 37 | }, 38 | "options_item3": { 39 | "message": "Ne pas bloquer les requêtes pop-up de la même origine", 40 | "description": "" 41 | }, 42 | "options_item5": { 43 | "message": "Afficher le nombre total de demandes bloquées dans l'icône de la barre d'outils", 44 | "description": "" 45 | }, 46 | "options_item6": { 47 | "message": "Destinations de la liste blanche", 48 | "description": "" 49 | }, 50 | "options_item7": { 51 | "message": "Sources de la liste blanche :", 52 | "description": "" 53 | }, 54 | "options_item8": { 55 | "message": "Pour que ce changement prenne effet, rafraîchissez l'onglet.", 56 | "description": "" 57 | }, 58 | "options_item9": { 59 | "message": "Compte à rebours pour l'exécution de la dernière action (en secondes)", 60 | "description": "" 61 | }, 62 | "options_item10": { 63 | "message": "Utilisez un zéro pour désactiver le compte à rebours pour effectuer l'action précédente.", 64 | "description": "" 65 | }, 66 | "options_item11": { 67 | "message": "Liste, séparée par des virgules, des noms d'hôtes qui ne seront pas bloqués (ces noms d'hôtes peuvent afficher des popups sur n'importe quel site web).", 68 | "description": "" 69 | }, 70 | "options_item12": { 71 | "message": "Liste de noms d'hôtes séparés par des virgules sur lesquels l'extension de blocage des pop-ups est complètement désactivée.", 72 | "description": "" 73 | }, 74 | "options_item13": { 75 | "message": "Liste noire des sources (mode de fonctionnement inverse) :", 76 | "description": "" 77 | }, 78 | "options_item14": { 79 | "message": "Liste de noms d'hôtes séparés par des virgules sur lesquels le bloqueur de popups ne doit être actif qu'à leur égard. Cela signifie que le bloqueur de pop-ups est désactivé sur TOUS les autres noms d'hôtes. Pour désactiver ce mode, effacez complètement la liste noire.", 80 | "description": "" 81 | }, 82 | "options_item15": { 83 | "message": "Empêcher la redirection des pages pendant 2 secondes après qu'une popup ai été demandée", 84 | "description": "" 85 | }, 86 | "options_item16": { 87 | "message": "Certains sites web redirigent l'utilisateur vers la page de pub si la demande d'affichage d'une annonce est bloquée. Cette option peut empêcher cela en n'autorisant pas la redirection de la page pendant la durée spécifiée.", 88 | "description": "" 89 | }, 90 | "options_item17": { 91 | "message": "Action par défaut lorsqu'une popup est demandée", 92 | "description": "" 93 | }, 94 | "options_item18": { 95 | "message": "ne rien faire", 96 | "description": "" 97 | }, 98 | "options_item19": { 99 | "message": "refuser la demande", 100 | "description": "" 101 | }, 102 | "options_item20": { 103 | "message": "ouvrir en arrière-plan", 104 | "description": "" 105 | }, 106 | "options_item21": { 107 | "message": "rediriger la page", 108 | "description": "" 109 | }, 110 | "options_item22": { 111 | "message": "Couleur de fond du badge", 112 | "description": "" 113 | }, 114 | "options_item23": { 115 | "message": "Ignorer les notifications pop-up lorsque c'est possible (non recommandé)", 116 | "description": "" 117 | }, 118 | "options_item24": { 119 | "message": "Cela permet \"d'ignorer\" ou \"d'accepter\" un popup sans interaction de l'utilisateur (non recommandé)", 120 | "description": "" 121 | }, 122 | "options_item25": { 123 | "message": "Descriptions", 124 | "description": "" 125 | }, 126 | "options_item26": { 127 | "message": "Afficher la FAQ concernant les mises à jour", 128 | "description": "" 129 | }, 130 | "options_item27": { 131 | "message": "Protocoles de la liste blanche :", 132 | "description": "" 133 | }, 134 | "options_item28": { 135 | "message": "Les protocoles énumérés peuvent être ouverts dans un nouvel onglet du navigateur. Par exemple, ajoutez \"magnet :\" pour permettre l'ouverture des liens magnétiques dans un onglet du navigateur.", 136 | "description": "" 137 | }, 138 | "options_item29": { 139 | "message": "Utiliser le service Web of Trust (WOT) pour décider si la fenêtre contextuelle provient d'un nom d'hôte de confiance ou non", 140 | "description": "" 141 | }, 142 | "options_item30": { 143 | "message": "Simulez le bouton \"autoriser\" pour empêcher le bloqueur de popup interne de votre navigateur de bloquer ces demandes", 144 | "description": "" 145 | }, 146 | "options_item31": { 147 | "message": "Lorsque vous appuyez sur le bouton \" faire confiance \", ajoutez le nom d'hôte à", 148 | "description": "" 149 | }, 150 | "options_item32": { 151 | "message": "Destinations de la liste blanche", 152 | "description": "" 153 | }, 154 | "options_item33": { 155 | "message": "Sources de la liste blanche", 156 | "description": "" 157 | }, 158 | "options_item34": { 159 | "message": "Liste noire de notification", 160 | "description": "" 161 | }, 162 | "options_item35": { 163 | "message": "Liste de noms d'hôtes séparés par des virgules que le bloqueur de popups n'affichera pas si une popup est demandé", 164 | "description": "" 165 | }, 166 | "options_support": { 167 | "message": "Soutenir le développement", 168 | "description": "" 169 | }, 170 | "options_import": { 171 | "message": "Importer", 172 | "description": "" 173 | }, 174 | "options_export": { 175 | "message": "Exporter", 176 | "description": "" 177 | }, 178 | "options_reset": { 179 | "message": "Réinitialisation des paramètres par défaut", 180 | "description": "" 181 | }, 182 | "options_save": { 183 | "message": "Sauvegarder", 184 | "description": "" 185 | }, 186 | "options_msg": { 187 | "message": "Les options sont sauvegardées", 188 | "description": "" 189 | }, 190 | "ui_msg": { 191 | "message": "La popup est demandé pour", 192 | "description": "" 193 | }, 194 | "ui_button_allow": { 195 | "message": "Autoriser cette popup", 196 | "description": "" 197 | }, 198 | "ui_button_allow_value": { 199 | "message": "Autoriser", 200 | "description": "" 201 | }, 202 | "ui_button_redirect": { 203 | "message": "Rediriger la page actuelle vers la nouvelle destination au lieu de l'ouvrir dans un nouvel onglet ou une popup", 204 | "description": "" 205 | }, 206 | "ui_button_redirect_value": { 207 | "message": "rediriger", 208 | "description": "" 209 | }, 210 | "ui_button_background": { 211 | "message": "Ouvrir le lien dans un onglet de fond", 212 | "description": "" 213 | }, 214 | "ui_button_background_value": { 215 | "message": "en arrière-plan", 216 | "description": "" 217 | }, 218 | "ui_button_deny": { 219 | "message": "Refuser l'ouverture de la fenêtre popup ou de l'onglet", 220 | "description": "" 221 | }, 222 | "ui_button_deny_value": { 223 | "message": "interdire", 224 | "description": "" 225 | }, 226 | "ui_button_trust": { 227 | "message": "Inscrivez ce domaine sur la liste blanche pour l'affichage des popups", 228 | "description": "" 229 | }, 230 | "ui_button_trust_value": { 231 | "message": "de confiance", 232 | "description": "" 233 | }, 234 | "bg_msg_state_1": { 235 | "message": "Popup Blocker (strict) est entièrement activé et protège cet onglet", 236 | "description": "" 237 | }, 238 | "bg_msg_state_2": { 239 | "message": "Popup Blocker (strict) est entièrement activé mais ne protège pas cet onglet", 240 | "description": "" 241 | }, 242 | "bg_msg_state_3": { 243 | "message": "Popup Blocker (strict) est entièrement désactivé et ne protège pas cet onglet", 244 | "description": "" 245 | }, 246 | "bg_msg_state_4": { 247 | "message": "Popup Blocker (strict) est entièrement désactivé mais protège cet onglet", 248 | "description": "" 249 | } 250 | } -------------------------------------------------------------------------------- /v3/_locales/pt_BR/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_description": { 3 | "message": "Bloqueia rigorosamente todas as solicitações pop-up de qualquer site" 4 | }, 5 | "context_item2": { 6 | "message": "Permitir a última solicitação pop-up" 7 | }, 8 | "context_item3": { 9 | "message": "Negar a última solicitação pop-up" 10 | }, 11 | "context_item4": { 12 | "message": "Abrir último pedido de pop-up em uma aba em segundo plano" 13 | }, 14 | "context_item5": { 15 | "message": "Redirecionar aba atual ao último pedido de pop-up" 16 | }, 17 | "context_item6": { 18 | "message": "Mover foco da página para a última solicitação de pop-up" 19 | }, 20 | "options_item1": { 21 | "message": "Número máximo de solicitações de pop-up para uma única página" 22 | }, 23 | "options_item2": { 24 | "message": "Tempo limite para exibição de cada pop-up (em segundos)" 25 | }, 26 | "options_item3": { 27 | "message": "Não bloquear solicitações pop-up da mesma origem" 28 | }, 29 | "options_item5": { 30 | "message": "Exibir o número total de solicitações bloqueadas no ícone da barra de ferramentas" 31 | }, 32 | "options_item6": { 33 | "message": "Não bloquear pop-ups destas origens:" 34 | }, 35 | "options_item7": { 36 | "message": "Não bloquear pop-ups destas páginas:" 37 | }, 38 | "options_item8": { 39 | "message": "Pra essa mudança fazer efeito, atualize a aba." 40 | }, 41 | "options_item9": { 42 | "message": "Contagem regressiva para executar a última ação (em segundos)" 43 | }, 44 | "options_item10": { 45 | "message": "Use o número zero para desativar a contagem regressiva para executar a ação anterior." 46 | }, 47 | "options_item13": { 48 | "message": "Fontes da lista negra (modo de operação reversa):" 49 | }, 50 | "options_item15": { 51 | "message": "Previne o redirecionamento de página por 2 segundos após a solicitação de um pop-up" 52 | }, 53 | "options_item17": { 54 | "message": "Ação padrão quando um pop-up é solicitado" 55 | }, 56 | "options_item18": { 57 | "message": "Não fazer nada" 58 | }, 59 | "options_item19": { 60 | "message": "Negar solicitação" 61 | }, 62 | "options_item20": { 63 | "message": "Abrir em segundo plano" 64 | }, 65 | "options_item21": { 66 | "message": "Página de redirecionamento" 67 | }, 68 | "options_item22": { 69 | "message": "Cor do emblema de contagem" 70 | }, 71 | "options_item23": { 72 | "message": "Ignorar notificação pop-up quando possível (não recomendado)" 73 | }, 74 | "options_item25": { 75 | "message": "Descrições" 76 | }, 77 | "options_item26": { 78 | "message": "Exibir página de FAQs nas atualizações" 79 | }, 80 | "options_item27": { 81 | "message": "Não bloquear estes protocolos:" 82 | }, 83 | "options_item28": { 84 | "message": "Permitir redirecionamento de página para as seguintes origens:" 85 | }, 86 | "options_item29": { 87 | "message": "Permitir redirecionamento de página para a mesma origem" 88 | }, 89 | "options_item30": { 90 | "message": "Simular o botão 'Permitir' para prevenir que o bloqueador interno de pop-up do seu navegador bloqueie esses pedidos" 91 | }, 92 | "options_item31": { 93 | "message": "Quando o botão \"confiar\" é pressionado:" 94 | }, 95 | "options_item32": { 96 | "message": "Não bloquear mais a origem do pop-up" 97 | }, 98 | "options_item33": { 99 | "message": "Permitir que a página principal mostre qualquer pop-up" 100 | }, 101 | "options_item34": { 102 | "message": "Silenciar notificações nestes sites:" 103 | }, 104 | "options_item35": { 105 | "message": "Aplicar as seguintes regras CSS personalizadas à interface do popup:" 106 | }, 107 | "options_item40": { 108 | "message": "Foca a interface pop-up recém-gerada. Você pode então usar atalhos ou a tecla ESC para ocultar" 109 | }, 110 | "options_item36": { 111 | "message": "Habilitar detecção agressiva de IFrame estático" 112 | }, 113 | "options_item37": { 114 | "message": "Quando este modo está ativado, a extensão instala um observador de mutação para monitorar IFrames estáticos com atributos 'JavaScript:' src. Isso aumenta o poder de bloqueio, mas tem desvantagens de desempenho." 115 | }, 116 | "options_item38": { 117 | "message": "Redirecionamento de página" 118 | }, 119 | "options_item39": { 120 | "message": "Diversos" 121 | }, 122 | "options_item41": { 123 | "message": "Ação em uma nova solicitação pop-up" 124 | }, 125 | "options_item42": { 126 | "message": "Posição do pop-up na página" 127 | }, 128 | "options_item43": { 129 | "message": "Superior esquerdo" 130 | }, 131 | "options_item44": { 132 | "message": "Superior direito" 133 | }, 134 | "options_item45": { 135 | "message": "Inferior esquerdo" 136 | }, 137 | "options_item46": { 138 | "message": "Inferior direito" 139 | }, 140 | "options_item47": { 141 | "message": "Escopo de proteção" 142 | }, 143 | "options_item48": { 144 | "message": "Leia a documentação sobre como configurar o escopo da extensão." 145 | }, 146 | "options_item49": { 147 | "message": "Largura do pop-up (em pixels)" 148 | }, 149 | "options_sync": { 150 | "message": "Sincronizar esta preferência" 151 | }, 152 | "options_support": { 153 | "message": "Apoie o desenvolvimento" 154 | }, 155 | "options_import": { 156 | "message": "Importar preferências" 157 | }, 158 | "options_export": { 159 | "message": "Exportar preferências" 160 | }, 161 | "options_reset": { 162 | "message": "Redefinir padrão" 163 | }, 164 | "options_save": { 165 | "message": "Salvar opções" 166 | }, 167 | "options_msg": { 168 | "message": "As opções foram salvas" 169 | }, 170 | "options_review": { 171 | "message": "Avaliação no YouTube" 172 | }, 173 | "options_page": { 174 | "message": "Página de Perguntas Frequentes" 175 | }, 176 | "options_t_1": { 177 | "message": "Lista de nomes de servidores separados por vírgulas (ex.: www.google.com, www.yahoo.com)" 178 | }, 179 | "options_t_2": { 180 | "message": "Lista de nomes de domínios separados por vírgulas (ex.: www.google.com, www.yahoo.com)" 181 | }, 182 | "options_t_3": { 183 | "message": "Um objeto JSON que orienta a extensão na execução de uma ação específica em resposta a uma solicitação pop-up, determinada por sua URL. Leia a página de perguntas frequentes para obter exemplos." 184 | }, 185 | "options_t_4": { 186 | "message": "Insira uma lista de padrões separados por vírgulas para definir o escopo global. Altere isso somente se souber o que está fazendo, pois valores incorretos podem danificar a extensão. Leia a página de perguntas frequentes para mais informações." 187 | }, 188 | "ui_msg": { 189 | "message": "O pop-up foi solicitado por" 190 | }, 191 | "ui_button_allow": { 192 | "message": "Permitir este popup (Alt + Shift + A ou Control + Option + A)" 193 | }, 194 | "ui_button_allow_value": { 195 | "message": "Permitir" 196 | }, 197 | "ui_button_redirect": { 198 | "message": "Redirecione a página atual para o novo destino em vez de abri-la em uma nova aba ou popup (Alt + Shift + R ou Control + Option + R)" 199 | }, 200 | "ui_button_redirect_value": { 201 | "message": "Redirecionar" 202 | }, 203 | "ui_button_background": { 204 | "message": "Abra o link em uma aba em segundo plano (Alt + Shift + B ou Control + Option + B)" 205 | }, 206 | "ui_button_background_value": { 207 | "message": "Segundo plano" 208 | }, 209 | "ui_button_deny": { 210 | "message": "Recusar a abertura do popup ou abertura de aba (Alt + Shift + D ou Control + Option + D)" 211 | }, 212 | "ui_button_deny_value": { 213 | "message": "Negar" 214 | }, 215 | "ui_button_trust": { 216 | "message": "Coloque este domínio na lista de permissões para abrir popups (Alt + Shift + T ou Control + Option + T)" 217 | }, 218 | "ui_button_trust_value": { 219 | "message": "Confiar" 220 | }, 221 | "ui_button_trust_confirm": { 222 | "message": "Clique para confirmar" 223 | }, 224 | "bg_msg_state_0": { 225 | "message": "O Popup Blocker está habilitado globalmente, mas não está ativo nesta aba, provavelmente porque é uma página interna, fora do escopo ou ainda está carregando." 226 | }, 227 | "bg_msg_state_1": { 228 | "message": "O Popup Blocker está habilitado globalmente e protege esta aba" 229 | }, 230 | "bg_msg_state_2": { 231 | "message": "O Popup Blocker está ativado globalmente, mas não protege esta aba" 232 | }, 233 | "bg_msg_state_3": { 234 | "message": "O Popup Blocker está desativado globalmente e não protege esta aba" 235 | }, 236 | "bg_msg_state_4": { 237 | "message": "O Popup Blocker está desabilitado globalmente, mas protege esta aba" 238 | }, 239 | "bg_msg_reg": { 240 | "message": "O registro do filtro de bloqueio falhou devido a uma regra formatada incorretamente. Use a página de opções para corrigi-lo." 241 | }, 242 | "pp_enabled_g": { 243 | "message": "Habilitado (Global)" 244 | }, 245 | "pp_enabled_c": { 246 | "message": "Ativado (Este domínio)" 247 | }, 248 | "pp_enabled_cf": { 249 | "message": "Incluir/excluir sub-frames" 250 | }, 251 | "pp_silent": { 252 | "message": "Mostrar notificações" 253 | }, 254 | "pp_ignore": { 255 | "message": "Executar Ação se possível" 256 | }, 257 | "pp_redirect": { 258 | "message": "Bloquear redirecionamento de página." 259 | }, 260 | "pp_last_request": { 261 | "message": "Última solicitação" 262 | }, 263 | "pp_test": { 264 | "message": "Testar boqueador" 265 | }, 266 | "pp_homepage": { 267 | "message": "Página inicial" 268 | }, 269 | "pp_options": { 270 | "message": "Opções" 271 | }, 272 | "pp_shadow": { 273 | "message": "Usar sombra" 274 | }, 275 | "pp_allow": { 276 | "message": "Permitir" 277 | }, 278 | "pp_block": { 279 | "message": "Bloquear" 280 | }, 281 | "pp_health": { 282 | "message": "O script em segundo plano parece não responder. Deseja tentar reiniciar a extensão?" 283 | } 284 | } 285 | -------------------------------------------------------------------------------- /v2/_locales/es/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_description": { 3 | "message": "Bloquear estrictamente todas las peticiones de ventanas emergentes de cualquier sitio web", 4 | "description": "" 5 | }, 6 | "context_item1": { 7 | "message": "Probar tu bloqueador de ventanas emergentes", 8 | "description": "" 9 | }, 10 | "context_item2": { 11 | "message": "Permitir la última petición de ventana emergente", 12 | "description": "" 13 | }, 14 | "context_item3": { 15 | "message": "Denegar la última petición de ventana emergente", 16 | "description": "" 17 | }, 18 | "context_item4": { 19 | "message": "Usar sombra de ventana para esta pestaña", 20 | "description": "" 21 | }, 22 | "context_item5": { 23 | "message": "Abrir página de opciones", 24 | "description": "" 25 | }, 26 | "context_item6": { 27 | "message": "Ignorar notificación de ventana emergente si es posible", 28 | "description": "" 29 | }, 30 | "options_item1": { 31 | "message": "Número máximo de peticiones de ventanas emergentes para una página", 32 | "description": "" 33 | }, 34 | "options_item2": { 35 | "message": "Tiempo de espera para mostrar cada ventana emergente (en segundos)", 36 | "description": "" 37 | }, 38 | "options_item3": { 39 | "message": "No bloquear peticiones de ventanas emergentes provenientes del mismo origen", 40 | "description": "" 41 | }, 42 | "options_item5": { 43 | "message": "Mostrar el número total de peticiones bloqueadas en el icono de la barra de herramientas", 44 | "description": "" 45 | }, 46 | "options_item6": { 47 | "message": "Destinos de lista blanca:", 48 | "description": "" 49 | }, 50 | "options_item7": { 51 | "message": "Fuentes de lista blanca:", 52 | "description": "" 53 | }, 54 | "options_item8": { 55 | "message": "Para que este cambio surta efecto, actualiza la pestaña.", 56 | "description": "" 57 | }, 58 | "options_item9": { 59 | "message": "Cuenta regresiva para realizar la última acción (en segundos)", 60 | "description": "" 61 | }, 62 | "options_item10": { 63 | "message": "Usar el número cero para deshabilitar la cuenta regresiva para realizar la acción anterior.", 64 | "description": "" 65 | }, 66 | "options_item11": { 67 | "message": "Lista de nombres de host separado por comas que no se van a bloquear (estos nombres de host pueden abrir ventanas emergentes en cualquier sitio web).", 68 | "description": "" 69 | }, 70 | "options_item12": { 71 | "message": "Lista de nombres de host separado por comas que la extensión bloqueador de ventanas emergentes está completamente deshabilitada en ellos.", 72 | "description": "" 73 | }, 74 | "options_item13": { 75 | "message": "Fuentes de lista negra (modo de operación inversa):", 76 | "description": "" 77 | }, 78 | "options_item14": { 79 | "message": "Lista de nombres de host separado por comas que el bloqueador de ventanas emergentes solo debe estar habilitado en ellos. Esto significa que el bloqueador de ventanas emergentes está deshabilitado en TODOS los demás nombres de host. Para deshabilitar este modo, borra completamente la entrada de la lista negra.", 80 | "description": "" 81 | }, 82 | "options_item15": { 83 | "message": "Impedir la redirección de la página durante 2 segundos tras una solicitud de ventana emergente", 84 | "description": "" 85 | }, 86 | "options_item16": { 87 | "message": "Algunos sitios web redirigen al usuario a una página de anuncios si la petición de ventana emergente para mostrar el anuncio está bloqueada. Esta opción puede impedir esto al no permitir la redirección de la página durante el tiempo especificado.", 88 | "description": "" 89 | }, 90 | "options_item17": { 91 | "message": "Acción predeterminada cuando se solicita una ventana emergente", 92 | "description": "" 93 | }, 94 | "options_item18": { 95 | "message": "no hacer nada", 96 | "description": "" 97 | }, 98 | "options_item19": { 99 | "message": "denegar petición", 100 | "description": "" 101 | }, 102 | "options_item20": { 103 | "message": "abrir en segundo plano", 104 | "description": "" 105 | }, 106 | "options_item21": { 107 | "message": "redirigir página", 108 | "description": "" 109 | }, 110 | "options_item22": { 111 | "message": "Color de fondo del escudo", 112 | "description": "" 113 | }, 114 | "options_item23": { 115 | "message": "Ignorar notificación de ventana emergente cuando sea posible (no recomendado)", 116 | "description": "" 117 | }, 118 | "options_item24": { 119 | "message": "Esto \"ignorará\" o \"aceptará\" un ventana emergente sin la interacción del usuario (no recomendado)", 120 | "description": "" 121 | }, 122 | "options_item25": { 123 | "message": "Descripciones", 124 | "description": "" 125 | }, 126 | "options_item26": { 127 | "message": "Mostrar página de preguntas frecuentes en actualizaciones", 128 | "description": "" 129 | }, 130 | "options_item27": { 131 | "message": "Protocolos en lista blanca:", 132 | "description": "" 133 | }, 134 | "options_item28": { 135 | "message": "Los protocolos listados pueden abrirse en una pestaña nueva del navegador. Por ejemplo, añadir 'magnet:' para permitir que los enlaces magnet se abran en una pestaña del navegador.", 136 | "description": "" 137 | }, 138 | "options_item29": { 139 | "message": "Usar el servicio Web of Trust (WOT) para decidir si una ventana emergente es de un nombre de host de confianza o no.", 140 | "description": "" 141 | }, 142 | "options_item30": { 143 | "message": "Simular el botón 'permitir' para impedir que el bloqueador de ventanas emergentes interno de tu navegador bloquee estas peticiones", 144 | "description": "" 145 | }, 146 | "options_item31": { 147 | "message": "Cuando se presiona el botón 'confiar', añadir el nombre de host a", 148 | "description": "" 149 | }, 150 | "options_item32": { 151 | "message": "Destinos de lista blanca", 152 | "description": "" 153 | }, 154 | "options_item33": { 155 | "message": "Fuentes de lista blanca", 156 | "description": "" 157 | }, 158 | "options_item34": { 159 | "message": "Notificación de lista negra", 160 | "description": "" 161 | }, 162 | "options_item35": { 163 | "message": "Lista de nombres de host separado por comas que el bloqueador de ventanas emergentes no mostrará notificación si se solicita una ventana emergente", 164 | "description": "" 165 | }, 166 | "options_item36": { 167 | "message": "Enable aggressive static IFrame detection", 168 | "description": "" 169 | }, 170 | "options_item37": { 171 | "message": "When this mode is enabled, the extension installs a mutation observer to monitor static IFrames with 'JavaScript:' src attributes. This enhances the blocking power but has performance drawbacks.", 172 | "description": "" 173 | }, 174 | "options_support": { 175 | "message": "Apoyar el desarrollo", 176 | "description": "" 177 | }, 178 | "options_import": { 179 | "message": "Importar", 180 | "description": "" 181 | }, 182 | "options_export": { 183 | "message": "Exportar", 184 | "description": "" 185 | }, 186 | "options_reset": { 187 | "message": "Restablecer los valores predeterminados", 188 | "description": "" 189 | }, 190 | "options_save": { 191 | "message": "Guardar", 192 | "description": "" 193 | }, 194 | "options_msg": { 195 | "message": "Se han guardado las opciones", 196 | "description": "" 197 | }, 198 | "options_review": { 199 | "message": "Reseña en YouTube", 200 | "description": "" 201 | }, 202 | "options_page": { 203 | "message": "Página de preguntas frecuentes", 204 | "description": "" 205 | }, 206 | "ui_msg": { 207 | "message": "Solicita una ventana emergente para", 208 | "description": "" 209 | }, 210 | "ui_button_allow": { 211 | "message": "Permitir esta ventana emergente", 212 | "description": "" 213 | }, 214 | "ui_button_allow_value": { 215 | "message": "permitir", 216 | "description": "" 217 | }, 218 | "ui_button_redirect": { 219 | "message": "Redirigir página actual al nuevo destino en lugar de abrirla en una pestaña nueva o ventana emergente", 220 | "description": "" 221 | }, 222 | "ui_button_redirect_value": { 223 | "message": "redirigir", 224 | "description": "" 225 | }, 226 | "ui_button_background": { 227 | "message": "Abrir el enlace en una pestaña en segundo plano", 228 | "description": "" 229 | }, 230 | "ui_button_background_value": { 231 | "message": "segundo plano", 232 | "description": "" 233 | }, 234 | "ui_button_deny": { 235 | "message": "Rechazar ventana emergente o apertura de pestaña", 236 | "description": "" 237 | }, 238 | "ui_button_deny_value": { 239 | "message": "denegar", 240 | "description": "" 241 | }, 242 | "ui_button_trust": { 243 | "message": "Poner en lista blanca este dominio para abrir ventanas emergentes", 244 | "description": "" 245 | }, 246 | "ui_button_trust_value": { 247 | "message": "confiar", 248 | "description": "" 249 | }, 250 | "bg_msg_state_1": { 251 | "message": "Popup Blocker (estricto) está habilitado globalmente y protege esta pestaña", 252 | "description": "" 253 | }, 254 | "bg_msg_state_2": { 255 | "message": "Popup Blocker (estricto) está habilitado globalmente pero no protege esta pestaña", 256 | "description": "" 257 | }, 258 | "bg_msg_state_3": { 259 | "message": "Popup Blocker (estricto) está deshabilitado globalmente y no protege esta pestaña", 260 | "description": "" 261 | }, 262 | "bg_msg_state_4": { 263 | "message": "Popup Blocker (estricto) está deshabilitado globalmente pero protege esta pestaña", 264 | "description": "" 265 | } 266 | } -------------------------------------------------------------------------------- /v3/data/inject/block/isolated.js: -------------------------------------------------------------------------------- 1 | /* global navigation, config */ 2 | 3 | /* Checks 4 | 1. 5 | https://chrome.google.com/webstore/detail/aefkmifgmaafnojlojpnekbpbmjiiogg 6 | FF -> The page’s settings blocked the loading of a resource at inline (“script-src”) 7 | 8 | 2. 9 | https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_win_open 10 | 11 | 3. test on incognito and private mode 12 | 13 | 4. https://webbrowsertools.com/popup-blocker/?fire_on_start 14 | 15 | 5. test reverse mode 16 | 17 | 6. 18 | https://codepen.io/pipr/pen/VwpVyZQ 19 | https://codepen.io/pipr/pen/LYWMpdR 20 | https://codepen.io/pipr/pen/XWMoPog 21 | https://codepen.io/pipr/pen/YzZdOdJ 22 | 23 | 7. 24 | https://patrickhlauke.github.io/recaptcha/ 25 | 26 | 8. simulation 27 | https://rds.live/realitatea-tv/ -> scroll to player. use "Sursa 3" player 28 | */ 29 | 30 | // we need to define global variables. Using self.scope may conflict with an element on page 31 | const scope = {}; 32 | scope.requests = []; // initial requests before interface is ready 33 | 34 | /* port is used to communicate between chrome and page scripts */ 35 | let port; 36 | try { 37 | port = document.getElementById('ppop-port'); 38 | port.remove(); 39 | } 40 | catch (e) { 41 | port = document.createElement('span'); 42 | port.id = 'ppop-port'; 43 | document.documentElement.append(port); 44 | } 45 | 46 | /* preferences */ 47 | 48 | if (window.top === window) { 49 | chrome.runtime.sendMessage({ 50 | 'cmd': 'state', 51 | 'active': true 52 | }); 53 | } 54 | const prefs = window.prefs = new Proxy({}, { 55 | set(obj, key, value) { 56 | obj[key] = value; 57 | 58 | if (key === 'enabled') { 59 | port.dataset[key] = value === true; 60 | if (window === window.top) { 61 | chrome.runtime.sendMessage({ 62 | 'cmd': 'state', 63 | 'active': value === true 64 | }); 65 | } 66 | } 67 | return true; 68 | } 69 | }); 70 | 71 | /* is enabled */ 72 | try { // SVG documents 73 | port.dataset.enabled = true; 74 | } 75 | catch (e) {} 76 | config.changed(ps => { 77 | if (ps.enabled) { 78 | prefs.enabled = ps.enabled.newValue; 79 | } 80 | }); 81 | 82 | /* record fake window's executed commands */ 83 | const records = {}; 84 | 85 | /* page redirection; prevent the page redirection when popup opening is unsuccessful for 2 seconds */ 86 | const redirect = { 87 | prefs: { 88 | 'block-page-redirection': false, 89 | 'block-page-redirection-period': 2000, 90 | 'block-page-redirection-hostnames': [], 91 | 'block-page-redirection-same-origin': true 92 | }, 93 | timeout: null, 94 | beforeunload(e) { 95 | if (redirect.href) { 96 | try { 97 | const {origin, hostname} = new URL(redirect.href); 98 | 99 | // do not block same origin 100 | if (redirect.prefs['block-page-redirection-same-origin'] && ( 101 | origin.includes(location.hostname) || 102 | location.origin.includes(hostname) 103 | )) { 104 | return true; 105 | } 106 | if (redirect.prefs['block-page-redirection-hostnames'].includes(hostname)) { 107 | return true; 108 | } 109 | } 110 | catch (e) { 111 | console.warn('block redirect error', e); 112 | } 113 | } 114 | 115 | e.returnValue = 'false'; 116 | }, 117 | block() { 118 | if (window.top === window) { 119 | if (redirect.prefs && redirect.prefs['block-page-redirection']) { 120 | addEventListener('beforeunload', redirect.beforeunload, true); 121 | clearTimeout(redirect.timeout); 122 | redirect.timeout = setTimeout(redirect.release, redirect.prefs['block-page-redirection-period']); 123 | } 124 | } 125 | }, 126 | release() { 127 | removeEventListener('beforeunload', redirect.beforeunload, true); 128 | clearTimeout(redirect.timeout); 129 | } 130 | }; 131 | // get notified on navigation 132 | if (typeof navigation !== 'undefined' && window.top === window) { 133 | navigation.addEventListener('navigate', navigateEvent => { 134 | redirect.href = navigateEvent.destination.url; 135 | }); 136 | } 137 | config.update(redirect.prefs); 138 | 139 | /* recording window.open */ 140 | const record = e => { 141 | e.stopPropagation(); 142 | const request = e.detail; 143 | records[request.id].push(request); 144 | }; 145 | port.addEventListener('record', record); 146 | 147 | /* channel */ 148 | const policy = e => { 149 | e.stopPropagation(); 150 | 151 | // make sure the request is from our script; see example 1 152 | if (e.target === port) { 153 | if (port.dataset.enabled !== 'false') { 154 | const request = e.detail; 155 | const {block, id, href, hostname} = blocker.policy(request); 156 | port.setAttribute('eid', id); 157 | port.setAttribute('block', block); 158 | 159 | if (block) { 160 | redirect.block(); 161 | 162 | chrome.runtime.sendMessage({ 163 | cmd: 'popup-request', 164 | type: request.type, 165 | href, 166 | hostname, 167 | id 168 | }); 169 | } 170 | } 171 | // when a new iframe is loaded and the blocker is disabled but the preferences are not yet ported 172 | else { 173 | port.setAttribute('block', false); 174 | } 175 | } 176 | }; 177 | port.addEventListener('policy', policy); 178 | 179 | /* blocker */ 180 | const blocker = {}; 181 | 182 | blocker.hasBase = a => { 183 | // https://github.com/schomery/popup-blocker/issues/86 184 | // only check the closest base 185 | const base = [a, ...document.querySelectorAll('base')] 186 | .map(e => e && e.target ? e.target : '') 187 | .filter(b => b).shift(); 188 | 189 | if (!base || base.toLowerCase() === '_self' || base.toLowerCase() === '_top') { 190 | return false; 191 | } 192 | // the linked page opens in a named frame 193 | if (typeof window[base] === 'object') { 194 | return false; 195 | } 196 | try { // might be cross-origin 197 | if (typeof parent[base] === 'object') { 198 | return false; 199 | } 200 | } 201 | catch (e) {} 202 | if (typeof isFirefox !== 'undefined') { 203 | try { 204 | if (document.querySelector(`[name="${base}"]`)) { 205 | return false; 206 | } 207 | } 208 | catch (e) {} 209 | try { 210 | if (parent.document.querySelector(`[name="${base}"]`)) { 211 | return false; 212 | } 213 | } 214 | catch (e) {} 215 | } 216 | return true; 217 | }; 218 | 219 | blocker.policy = request => { 220 | const target = document.activeElement || document.documentElement; 221 | const {type} = request; 222 | let href = request.href; 223 | let hostname = ''; 224 | let block = true; 225 | let sameContext = false; 226 | 227 | if (type === 'element.click') { 228 | const a = 'closest' in target ? (target.closest('[target]') || target.closest('a')) : null; 229 | href = href || (a ? a.href || a.action : ''); 230 | 231 | // we are blocking either if a is found or href is provided; see method 12/4 232 | block = Boolean(a) || href; 233 | } 234 | // always run window open on the same context 235 | if (type === 'window.open') { 236 | sameContext = true; 237 | } 238 | else { 239 | block = block && blocker.hasBase({ 240 | target: request.target 241 | }); 242 | } 243 | // block if 244 | if (request.metaKey && request.isTrusted === false) { // see method 12/5 245 | block = true; 246 | } 247 | if ('button' in request && request.button !== 0 && request.isTrusted === false) { // see method 12/2 248 | block = true; 249 | } 250 | // do not block if 251 | if (request.defaultPrevented || (request.metaKey && request.isTrusted)) { 252 | block = false; 253 | } 254 | // do not block A[download] 255 | if (request.tag === 'A' && request.download) { 256 | block = false; 257 | } 258 | 259 | console.log(request, block); 260 | 261 | // fixing 262 | if (block) { 263 | // fix relative href 264 | if (href && href.indexOf(':') === -1) { 265 | const a = document.createElement('a'); 266 | a.setAttribute('href', href); 267 | href = a.href; 268 | } 269 | // create a unique id when "href" is not usable 270 | if (!href || href.startsWith('about:')) { 271 | target.dataset.ppbid = target.dataset.ppbid || Math.random(); 272 | } 273 | if (href) { 274 | try { 275 | const configs = blocker.policy.configs; 276 | 277 | const loc = new URL(href); 278 | hostname = loc.hostname; 279 | // allow popups from the same hostname 280 | if (configs.domain) { 281 | try { // if they are not in the same origin 282 | const h = window.top.location.hostname; 283 | if (h && hostname && (h.endsWith('.' + hostname) || hostname.endsWith('.' + h) || hostname === h)) { 284 | block = false; 285 | } 286 | } 287 | catch (e) {} 288 | } 289 | // protocol matching 290 | if (loc.protocol && configs.protocols.indexOf(loc.protocol) !== -1) { 291 | block = false; 292 | } 293 | // white-list matching 294 | if (hostname) { 295 | for (const h of configs['popup-hosts']) { 296 | if (h.endsWith('.' + hostname) || hostname.endsWith('.' + h) || hostname === h) { 297 | block = false; 298 | } 299 | } 300 | } 301 | } 302 | catch (e) {} 303 | } 304 | } 305 | 306 | const id = target.dataset.ppbid || Math.random(); 307 | if (sameContext) { 308 | records[id] = []; 309 | records[id].args = request.args; 310 | } 311 | return { 312 | id, 313 | href, 314 | hostname, 315 | sameContext, 316 | block 317 | }; 318 | }; 319 | blocker.policy.configs = { 320 | 'domain': false, 321 | 'protocols': ['magnet:'], 322 | 'popup-hosts': ['google.com', 'bing.com', 't.co', 'twitter.com', 'disqus.com', 'login.yahoo.com', 'mail.google.com'] 323 | }; 324 | config.update(blocker.policy.configs); 325 | config.changed(ps => { 326 | Object.keys(ps).filter(k => k in blocker.policy.configs).forEach(k => blocker.policy.configs[k] = ps[k].newValue); 327 | }); 328 | 329 | /* messaging */ 330 | chrome.runtime.onMessage.addListener((request, sender, response) => { 331 | // apply popup-accept on the context where it is originally requested 332 | if (request.cmd === 'popup-accepted') { 333 | port.dataset.enabled = false; 334 | 335 | chrome.runtime.sendMessage({ 336 | cmd: 'run-records', 337 | url: request.url, 338 | records: records[request.id], 339 | args: records[request.id]?.args || [] 340 | }, () => { 341 | delete records[request.id]; 342 | port.dataset.enabled = prefs.enabled; 343 | }); 344 | } 345 | else if (request.cmd === 'use-shadow') { 346 | port.dataset.shadow = true; 347 | } 348 | else if (request.cmd === 'release-beforeunload') { 349 | redirect.release(); 350 | response(true); // Edge thing! 351 | } 352 | }); 353 | --------------------------------------------------------------------------------