├── tunnelbear ├── .gitignore ├── resources │ ├── img │ │ ├── logo.png │ │ ├── help16.png │ │ ├── icon01.png │ │ ├── icon02.png │ │ ├── icon03.png │ │ ├── icon_16.png │ │ ├── icon_32.png │ │ ├── logo2x.png │ │ ├── arrow_open.png │ │ ├── icon01@2x.png │ │ ├── icon02@2x.png │ │ ├── icon03@2x.png │ │ ├── icon_gear.png │ │ ├── icon_info.png │ │ ├── logo_page.png │ │ ├── arrow_close.png │ │ ├── arrow_open2x.png │ │ ├── graphic_tb4c.png │ │ ├── icon_16-off.png │ │ ├── icon_32-off.png │ │ ├── icon_gear2x.png │ │ ├── icon_info2x.png │ │ ├── page_blocked.png │ │ ├── arrow_close2x.png │ │ ├── flash_blocked.png │ │ ├── flash_blocked2x.png │ │ ├── flash_unblock.png │ │ ├── flash_unblock2x.png │ │ ├── graphic_blocky.png │ │ ├── graphic_twitter.png │ │ ├── twitter_close.png │ │ ├── extension_icon_16.png │ │ ├── extension_icon_48.png │ │ ├── report_icon_hover.png │ │ ├── extension_icon_128.png │ │ ├── report_icon_hover2x.png │ │ ├── report_icon_normal.png │ │ └── report_icon_normal2x.png │ ├── fonts │ │ ├── OpenSans-Bold.ttf │ │ ├── Rokkitt-Bold.eot │ │ ├── Rokkitt-Bold.ttf │ │ ├── Rokkitt-Bold.woff │ │ ├── Rokkitt-Light.eot │ │ ├── Rokkitt-Light.ttf │ │ ├── Rokkitt-Light.woff │ │ ├── Rokkitt-Regular.eot │ │ ├── Rokkitt-Regular.ttf │ │ ├── OpenSans-Regular.ttf │ │ ├── OpenSans-Semibold.ttf │ │ ├── Rokkitt-Regular.woff │ │ ├── Rokkitt-Light.svg │ │ └── Rokkitt-Bold.svg │ └── manifest.json ├── src │ ├── css │ │ ├── block.css │ │ ├── content.css │ │ ├── settings.css │ │ ├── popup.css │ │ └── common.css │ ├── js │ │ ├── blockbear-utils.js │ │ ├── blockbear-pagestore-patch.js │ │ ├── blockbear-filters.js │ │ ├── blockbear-contentscript-start.js │ │ ├── blockbear-contentscript-inject.js │ │ ├── blockbear-background.js │ │ ├── blockbear-page-counts.js │ │ ├── blockbear-toolbar-icon.js │ │ ├── blockbear-contentscript-end.js │ │ ├── blockbear-pixel-tracking.js │ │ ├── blockbear-settings.js │ │ └── blockbear-messaging.js │ ├── html │ │ ├── asset-viewer.html │ │ ├── background.html │ │ ├── document-blocked.html │ │ ├── popup.html │ │ └── settings.html │ └── _locales │ │ ├── zh_CN │ │ └── messages.json │ │ ├── fr │ │ └── messages.json │ │ └── en │ │ └── messages.json └── tools │ ├── make-firefox.sh │ └── make-chromium.sh ├── .gitignore ├── .gitmodules ├── package.json ├── PRIVACY.md ├── MANIFESTO.md ├── .jshintrc ├── .travis.yml ├── .github └── ISSUE_TEMPLATE.md ├── README.md └── CONTRIBUTING.md /tunnelbear/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.bak 2 | *.pem 3 | .DS_Store 4 | /dist/build/ 5 | /tmp/ 6 | /bower_components/ 7 | /node_modules/ -------------------------------------------------------------------------------- /tunnelbear/resources/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/logo.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/help16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/help16.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/icon01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/icon01.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/icon02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/icon02.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/icon03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/icon03.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/icon_16.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/icon_32.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/logo2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/logo2x.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/arrow_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/arrow_open.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/icon01@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/icon01@2x.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/icon02@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/icon02@2x.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/icon03@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/icon03@2x.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/icon_gear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/icon_gear.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/icon_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/icon_info.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/logo_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/logo_page.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/arrow_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/arrow_close.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/arrow_open2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/arrow_open2x.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/graphic_tb4c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/graphic_tb4c.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/icon_16-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/icon_16-off.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/icon_32-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/icon_32-off.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/icon_gear2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/icon_gear2x.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/icon_info2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/icon_info2x.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/page_blocked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/page_blocked.png -------------------------------------------------------------------------------- /tunnelbear/resources/fonts/OpenSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/fonts/OpenSans-Bold.ttf -------------------------------------------------------------------------------- /tunnelbear/resources/fonts/Rokkitt-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/fonts/Rokkitt-Bold.eot -------------------------------------------------------------------------------- /tunnelbear/resources/fonts/Rokkitt-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/fonts/Rokkitt-Bold.ttf -------------------------------------------------------------------------------- /tunnelbear/resources/fonts/Rokkitt-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/fonts/Rokkitt-Bold.woff -------------------------------------------------------------------------------- /tunnelbear/resources/fonts/Rokkitt-Light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/fonts/Rokkitt-Light.eot -------------------------------------------------------------------------------- /tunnelbear/resources/fonts/Rokkitt-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/fonts/Rokkitt-Light.ttf -------------------------------------------------------------------------------- /tunnelbear/resources/img/arrow_close2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/arrow_close2x.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/flash_blocked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/flash_blocked.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/flash_blocked2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/flash_blocked2x.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/flash_unblock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/flash_unblock.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/flash_unblock2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/flash_unblock2x.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/graphic_blocky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/graphic_blocky.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/graphic_twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/graphic_twitter.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/twitter_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/twitter_close.png -------------------------------------------------------------------------------- /tunnelbear/resources/fonts/Rokkitt-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/fonts/Rokkitt-Light.woff -------------------------------------------------------------------------------- /tunnelbear/resources/fonts/Rokkitt-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/fonts/Rokkitt-Regular.eot -------------------------------------------------------------------------------- /tunnelbear/resources/fonts/Rokkitt-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/fonts/Rokkitt-Regular.ttf -------------------------------------------------------------------------------- /tunnelbear/resources/img/extension_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/extension_icon_16.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/extension_icon_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/extension_icon_48.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/report_icon_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/report_icon_hover.png -------------------------------------------------------------------------------- /tunnelbear/resources/fonts/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/fonts/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /tunnelbear/resources/fonts/OpenSans-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/fonts/OpenSans-Semibold.ttf -------------------------------------------------------------------------------- /tunnelbear/resources/fonts/Rokkitt-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/fonts/Rokkitt-Regular.woff -------------------------------------------------------------------------------- /tunnelbear/resources/img/extension_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/extension_icon_128.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/report_icon_hover2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/report_icon_hover2x.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/report_icon_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/report_icon_normal.png -------------------------------------------------------------------------------- /tunnelbear/resources/img/report_icon_normal2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TunnelBear/tunnelbear-blocker/HEAD/tunnelbear/resources/img/report_icon_normal2x.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "uBlock"] 2 | path = uBlock 3 | url = https://github.com/gorhill/uBlock.git 4 | [submodule "uAssets"] 5 | path = uAssets 6 | url = https://github.com/uBlockOrigin/uAssets.git 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.tunnelbear.blocker", 3 | "description": "TunnelBear Blocker", 4 | "author": "TunnelBear", 5 | "version": "1.0.1", 6 | "license": "GPL-3.0", 7 | "dependencies": { 8 | "tko": "^4.0.0-alpha5h" 9 | }, 10 | "private": true 11 | } 12 | -------------------------------------------------------------------------------- /tunnelbear/src/css/block.css: -------------------------------------------------------------------------------- 1 | object[type$="x-shockwave-flash"]:not([classid]):not(.tb-unlock), 2 | object[type$="futuresplash"]:not([classid]):not(.tb-unlock), 3 | embed[type$="x-shockwave-flash"]:not(.tb-unlock), 4 | embed[type$="futuresplash"]:not(.tb-unlock) { 5 | display: none !important; 6 | } 7 | -------------------------------------------------------------------------------- /tunnelbear/src/js/blockbear-utils.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | if (!vAPI) { 4 | return; 5 | } 6 | vAPI.utils = { 7 | getIconUrl: function (icon) { 8 | var suffix = ".png"; 9 | if (window.devicePixelRatio.isRetina) { 10 | suffix = "2x.png"; 11 | } 12 | return "../img/" + icon + suffix; 13 | } 14 | }; 15 | 16 | })(); -------------------------------------------------------------------------------- /PRIVACY.md: -------------------------------------------------------------------------------- 1 | ### Privacy Policy 2 | 3 | TunnelBear Blocker does **NOT** collect any data in any form within the extension itself. 4 | 5 | The only data we have are as follows: 6 | 7 | 1. Installation counts, as provided by the Google Chrome store. 8 | 9 | 2. Broken site feedback reports, which are only submitted by the user's own choice. 10 | 11 | Neither of these two pieces of information will EVER be shared with third-parties. -------------------------------------------------------------------------------- /MANIFESTO.md: -------------------------------------------------------------------------------- 1 | ### TunnelBear Blocker manifesto 2 | 3 | Our beliefs are 100% in line with that of the [uBlock project](https://github.com/gorhill/uBlock/blob/master/MANIFESTO.md), 4 | and our manifesto merely serves as an extension of uBlock's manifesto. Simply put, this means the following: 5 | 6 | 1. The **user decides** what web content is acceptable or not in their browser. 7 | 8 | 2. We will provide every user with the tools and means to do so simply and effectively. -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "browser": true, 3 | "devel": true, 4 | "eqeqeq": true, 5 | "esnext": true, 6 | "globals": { 7 | "chrome": false, 8 | "Components": false, // global variable in Firefox 9 | "safari": false, 10 | "self": false, 11 | "vAPI": false, 12 | "µBlock": false 13 | }, 14 | "laxbreak": true, 15 | "newcap": false, 16 | "nonew": false, 17 | "strict": "global", 18 | "sub": true, 19 | "undef": true, 20 | "unused": true, 21 | "validthis": true, 22 | "-W058": true // suppress "Missing '()' invoking a constructor" message 23 | } 24 | -------------------------------------------------------------------------------- /tunnelbear/src/html/asset-viewer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | TunnelBear Blocker — Asset 6 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | sudo: false 3 | env: 4 | matrix: 5 | - BROWSER=chromium EXT=zip 6 | - BROWSER=firefox EXT=xpi 7 | - BROWSER=webext EXT=xpi 8 | script: ./tools/make-${BROWSER}.sh all 9 | deploy: 10 | provider: releases 11 | prerelease: true 12 | # https://github.com/travis-ci/travis-ci/issues/6772 13 | edge: 14 | branch: releases-fix 15 | api_key: 16 | secure: EnAMNsPbnS2I0JDkCWiY/6WLERsUbE2Ni5j9ap8YbZt4+sJv7aSoufWZ+0TZvSwr/w5MKCCDKhwXaPfbUwvqrI+eZv6LBXhwajK9Zla25FVjtdGCwKXQ3ZU85PHgL+5FYtuSGACmQj/ruAdSgrI7PgS08e5lqSgEk6lY4y3/6fE= 17 | file: dist/build/uBlock0.${BROWSER}.${EXT} 18 | skip_cleanup: true 19 | on: 20 | repo: gorhill/uBlock 21 | tags: true 22 | all_branches: true 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Filter issues **MUST NOT** be reported here. Read first: 2 | 3 | ### Describe the issue 4 | 5 | 6 | ### One or more specific URLs where the issue occurs 7 | 8 | [URL(s) for issue on a specific site are **mandatory**] 9 | 10 | ### Screenshot in which the issue can be seen 11 | 12 | [Screenshot(s) for visual issues are **mandatory**] 13 | 14 | ### Steps for anyone to reproduce the issue 15 | 16 | 1. Be as detailed as possible: 17 | 1. Because we are not looking over your shoulder and 18 | 1. Keep in mind: Nobody can read your mind. 19 | 20 | ### Your settings 21 | 22 | [If you fail to provide this info, I will mark the issue as invalid. Lists all settings which differs from default settings] 23 | 24 | - OS/version: 25 | - Browser/version: 26 | - uBlock Origin version: 27 | 28 | ##### Your filter lists 29 | 30 | [Example: "Default filter lists + FRA", or "Default filter lists minus uBlock -- Badware risks"] 31 | 32 | ##### Your custom filters (if any) 33 | -------------------------------------------------------------------------------- /tunnelbear/src/js/blockbear-pagestore-patch.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | 'use strict'; 4 | 5 | /******************************************************************************/ 6 | 7 | let µb = µBlock; 8 | 9 | /******************************************************************************/ 10 | 11 | // Here we override the getNetFilteringSwitch() in the PageStore prototype to 12 | // take into account the state of the global toggle. 13 | 14 | let originalFactory = µb.PageStore.factory 15 | 16 | µb.PageStore.factory = function(tabId, context) { 17 | let pageStore = originalFactory(tabId, context); 18 | let prototype = Object.getPrototypeOf(pageStore); 19 | let originalNetFilteringSwitch = prototype.getNetFilteringSwitch 20 | 21 | prototype.getNetFilteringSwitch = function () { 22 | let globalToggle = µb.blockbear.settings.blockBearEnabled; 23 | return globalToggle && originalNetFilteringSwitch.call(this); 24 | } 25 | 26 | µb.PageStore.factory = originalFactory; 27 | return pageStore; 28 | } 29 | 30 | /******************************************************************************/ 31 | 32 | })(); -------------------------------------------------------------------------------- /tunnelbear/src/css/content.css: -------------------------------------------------------------------------------- 1 | .tb-container { 2 | display: block; 3 | } 4 | 5 | .tb-block{ 6 | border: none; 7 | border-image-source: initial; 8 | border-image-slice: initial; 9 | border-image-width: initial; 10 | border-image-outset: initial; 11 | border-image-repeat: initial; 12 | cursor: pointer; 13 | display: block; 14 | min-width: 48px; 15 | min-height: 48px; 16 | overflow: hidden; 17 | padding: 0px; 18 | position: relative; 19 | visibility: visible; 20 | } 21 | 22 | .tb-block:hover::after { 23 | display: block; 24 | } 25 | 26 | .tb-block::after { 27 | color: white!important; 28 | background-color: #4a4a4a!important; 29 | border-radius: 10px!important; 30 | content: "unblock flash"!important; 31 | top: 50%!important; 32 | position: absolute!important; 33 | text-align: center!important; 34 | left: 50%!important; 35 | right: 0!important; 36 | margin: 40px -50px!important; 37 | width: 100px!important; 38 | font-size: 12px!important; 39 | line-height: 18px!important; 40 | font-family: Helvetica,Arial,sans-serif!important; 41 | display: none; 42 | } -------------------------------------------------------------------------------- /tunnelbear/src/html/background.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | TunnelBear Blocker 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 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /tunnelbear/src/js/blockbear-filters.js: -------------------------------------------------------------------------------- 1 | 2 | (function () { 3 | 4 | /******************************************************************************/ 5 | 6 | var µb = µBlock; 7 | let bb = µb.blockbear 8 | 9 | /******************************************************************************/ 10 | 11 | const adsLists = [ 12 | "ublock-filters", 13 | "ublock-unbreak", 14 | "easylist", 15 | "plowe-0" 16 | ] 17 | 18 | const privacyLists = [ 19 | "ublock-privacy", 20 | "ublock-abuse", 21 | "easyprivacy" 22 | ] 23 | 24 | const malwareLists = [ 25 | "ublock-badware", 26 | "malware-0", 27 | "malware-1" 28 | ] 29 | 30 | const socialLists = [ 31 | "fanboy-social" 32 | ] 33 | 34 | /******************************************************************************/ 35 | 36 | bb.classifyFilterList = function (list) { 37 | if (adsLists.includes(list)) { 38 | return 'ads' 39 | } else if (privacyLists.includes(list)) { 40 | return 'privacy' 41 | } else if (malwareLists.includes(list)) { 42 | return 'malware' 43 | } else if (socialLists.includes(list)) { 44 | return 'social' 45 | } 46 | return 'ads' 47 | } 48 | 49 | /******************************************************************************/ 50 | 51 | let getFilterListsToSelect = function (globalToggle, blockAds, blockPrivacy, blockMalware, blockSocial) { 52 | let ret = []; 53 | if (globalToggle === true) { 54 | if (blockAds) { 55 | ret = ret.concat(adsLists); 56 | } 57 | if (blockPrivacy) { 58 | ret = ret.concat(privacyLists); 59 | } 60 | if (blockMalware) { 61 | ret = ret.concat(malwareLists); 62 | } 63 | if (blockSocial) { 64 | ret = ret.concat(socialLists); 65 | } 66 | } 67 | return ret; 68 | } 69 | 70 | bb.updateFilters = function () { 71 | let globalToggle = bb.settings.blockBearEnabled; 72 | let blockAds = bb.settings.blockAdsEnabled; 73 | let blockPrivacy = bb.settings.blockPrivacyEnabled; 74 | let blockMalware = bb.settings.blockMalwareEnabled; 75 | let blockSocial = bb.settings.blockSocialEnabled; 76 | 77 | µb.applyFilterListSelection({ 78 | toSelect: getFilterListsToSelect(globalToggle, blockAds, blockPrivacy, blockMalware, blockSocial), 79 | toRemove: [], 80 | toImport: "" 81 | }); 82 | µb.loadFilterLists() 83 | } 84 | 85 | /******************************************************************************/ 86 | 87 | })(); -------------------------------------------------------------------------------- /tunnelbear/tools/make-firefox.sh: -------------------------------------------------------------------------------- 1 | echo "//========================================================//" 2 | echo "// Fetching uAssets //" 3 | echo "//========================================================//" 4 | pushd uAssets > /dev/null 5 | git pull origin master 6 | popd > /dev/null 7 | 8 | echo "//========================================================//" 9 | echo "// Building uBlock Origin //" 10 | echo "//========================================================//" 11 | pushd uBlock > /dev/null 12 | bash tools/make-firefox.sh 13 | popd > /dev/null 14 | 15 | echo "//========================================================//" 16 | echo "// Adding TunnelBear Blocker Files //" 17 | echo "//========================================================//" 18 | mkdir -p tunnelbear/dist/blockbear.firefox 19 | rm -rf tunnelbear/dist/blockbear.firefox/* 20 | mv -v uBlock/dist/build/uBlock0.firefox/* tunnelbear/dist/blockbear.firefox 21 | 22 | # CSS files 23 | rm tunnelbear/dist/blockbear.firefox/css/*.css 24 | cp tunnelbear/src/css/* tunnelbear/dist/blockbear.firefox/css 25 | 26 | # Font files 27 | rm tunnelbear/dist/blockbear.firefox/css/fonts/* 28 | cp tunnelbear/resources/fonts/* tunnelbear/dist/blockbear.firefox/css/fonts 29 | 30 | # # Image files 31 | rm -rf tunnelbear/dist/blockbear.firefox/img 32 | cp -R tunnelbear/resources/img tunnelbear/dist/blockbear.firefox/img 33 | 34 | # # Manifest file 35 | cp tunnelbear/resources/manifest.json tunnelbear/dist/blockbear.firefox/manifest.json 36 | 37 | # # JS files 38 | cp tunnelbear/src/js/* tunnelbear/dist/blockbear.firefox/js 39 | 40 | # # HTML files 41 | mv tunnelbear/dist/blockbear.firefox/is-webrtc-supported.html tunnelbear/dist/blockbear.firefox/is-webrtc-supported.html.keep 42 | rm tunnelbear/dist/blockbear.firefox/*.html 43 | cp tunnelbear/src/html/* tunnelbear/dist/blockbear.firefox 44 | mv tunnelbear/dist/blockbear.firefox/is-webrtc-supported.html.keep tunnelbear/dist/blockbear.firefox/is-webrtc-supported.html 45 | 46 | # # Localization files 47 | rm -rf rm tunnelbear/dist/blockbear.firefox/_locales/* 48 | cp -R tunnelbear/src/_locales/* tunnelbear/dist/blockbear.firefox/_locales 49 | 50 | # # tko js library 51 | cp node_modules/tko/dist/tko.js tunnelbear/dist/blockbear.firefox/js 52 | 53 | # # Remove unnecessary js files 54 | rm tunnelbear/dist/blockbear.firefox/js/popup.js 55 | rm tunnelbear/dist/blockbear.firefox/js/settings.js 56 | -------------------------------------------------------------------------------- /tunnelbear/resources/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | 4 | "name": "TunnelBear Blocker", 5 | "version": "1.0.1", 6 | 7 | "default_locale": "en", 8 | "description": "__MSG_extShortDesc__", 9 | "icons": { 10 | "16": "img/extension_icon_16.png", 11 | "48": "img/extension_icon_48.png", 12 | "128": "img/extension_icon_128.png" 13 | }, 14 | 15 | "browser_action": { 16 | "default_icon": { 17 | "16": "img/icon_16-off.png", 18 | "32": "img/icon_32-off.png" 19 | }, 20 | "default_title": "TunnelBear Blocker", 21 | "default_popup": "popup.html" 22 | }, 23 | 24 | "author": "TunnelBear", 25 | "background": { 26 | "page": "background.html" 27 | }, 28 | "content_scripts": [ 29 | { 30 | "matches": ["http://*/*", "https://*/*"], 31 | "js": ["/js/vapi.js", "js/vapi-client.js", "js/blockbear-contentscript-start.js", "js/contentscript.js"], 32 | "css": ["css/block.css"], 33 | "run_at": "document_start", 34 | "all_frames": true 35 | }, 36 | { 37 | "matches": ["http://*/*", "https://*/*"], 38 | "js": ["js/scriptlets/subscriber.js"], 39 | "run_at": "document_idle", 40 | "all_frames": false 41 | }, 42 | { 43 | "matches": ["http://*/*", "https://*/*"], 44 | "js": ["js/blockbear-contentscript-end.js"], 45 | "css": ["css/content.css"], 46 | "run_at": "document_end", 47 | "all_frames": false 48 | } 49 | ], 50 | "minimum_chrome_version": "51.0", 51 | "optional_permissions": [ "file:///*" ], 52 | "options_ui": { 53 | "page": "settings.html" 54 | }, 55 | "permissions": [ 56 | "privacy", 57 | "storage", 58 | "tabs", 59 | "unlimitedStorage", 60 | "webNavigation", 61 | "webRequest", 62 | "webRequestBlocking", 63 | "" 64 | ], 65 | "web_accessible_resources": [ 66 | "img/flash_blocked.png", 67 | "img/flash_blocked2x.png", 68 | "img/flash_unblock.png", 69 | "img/flash_unblock2x.png", 70 | "js/canvas-blocker.js", 71 | "js/blockbear-pixel-tracking.js", 72 | "js/blockbear-contentscript-inject.js", 73 | "/web_accessible_resources/*" 74 | ], 75 | "short_name": "TunnelBear Blocker" 76 | } 77 | -------------------------------------------------------------------------------- /tunnelbear/tools/make-chromium.sh: -------------------------------------------------------------------------------- 1 | echo "//========================================================//" 2 | echo "// Fetching uAssets //" 3 | echo "//========================================================//" 4 | pushd uAssets > /dev/null 5 | git pull origin master 6 | popd > /dev/null 7 | 8 | echo "//========================================================//" 9 | echo "// Building uBlock Origin //" 10 | echo "//========================================================//" 11 | pushd uBlock > /dev/null 12 | bash tools/make-chromium.sh 13 | popd > /dev/null 14 | 15 | echo "//========================================================//" 16 | echo "// Adding TunnelBear Blocker Files //" 17 | echo "//========================================================//" 18 | mkdir -p tunnelbear/dist/blockbear.chromium 19 | rm -rf tunnelbear/dist/blockbear.chromium/* 20 | mv -v uBlock/dist/build/uBlock0.chromium/* tunnelbear/dist/blockbear.chromium 21 | 22 | # CSS files 23 | rm tunnelbear/dist/blockbear.chromium/css/*.css 24 | cp tunnelbear/src/css/* tunnelbear/dist/blockbear.chromium/css 25 | 26 | # Font files 27 | rm tunnelbear/dist/blockbear.chromium/css/fonts/* 28 | cp tunnelbear/resources/fonts/* tunnelbear/dist/blockbear.chromium/css/fonts 29 | 30 | # # Image files 31 | rm -rf tunnelbear/dist/blockbear.chromium/img 32 | cp -R tunnelbear/resources/img tunnelbear/dist/blockbear.chromium/img 33 | 34 | # # Manifest file 35 | cp tunnelbear/resources/manifest.json tunnelbear/dist/blockbear.chromium/manifest.json 36 | 37 | # # JS files 38 | cp tunnelbear/src/js/* tunnelbear/dist/blockbear.chromium/js 39 | 40 | # # HTML files 41 | mv tunnelbear/dist/blockbear.chromium/is-webrtc-supported.html tunnelbear/dist/blockbear.chromium/is-webrtc-supported.html.keep 42 | rm tunnelbear/dist/blockbear.chromium/*.html 43 | cp tunnelbear/src/html/* tunnelbear/dist/blockbear.chromium 44 | mv tunnelbear/dist/blockbear.chromium/is-webrtc-supported.html.keep tunnelbear/dist/blockbear.chromium/is-webrtc-supported.html 45 | 46 | # # Localization files 47 | rm -rf rm tunnelbear/dist/blockbear.chromium/_locales/* 48 | cp -R tunnelbear/src/_locales/* tunnelbear/dist/blockbear.chromium/_locales 49 | 50 | # # tko js library 51 | cp node_modules/tko/dist/tko.js tunnelbear/dist/blockbear.chromium/js 52 | 53 | # # Remove unnecessary js files 54 | rm tunnelbear/dist/blockbear.chromium/js/popup.js 55 | rm tunnelbear/dist/blockbear.chromium/js/settings.js 56 | -------------------------------------------------------------------------------- /tunnelbear/src/css/settings.css: -------------------------------------------------------------------------------- 1 | /* Settings */ 2 | 3 | body#global-settings { 4 | overflow: visible; 5 | overflow-x: visible; 6 | } 7 | 8 | #settings-top-banner { 9 | height: 70px; 10 | background-color: #EBEAE8; 11 | background-image: url('../img/logo_page.png'); 12 | background-repeat: no-repeat; 13 | background-position: center; 14 | background-size: 207px 56px; 15 | } 16 | 17 | #settings-div { 18 | max-width: 580px; 19 | margin-top: 60px; 20 | margin-left: auto; 21 | margin-right: auto; 22 | margin-bottom: 200px; 23 | } 24 | 25 | #settings-title { 26 | text-align: center; 27 | } 28 | 29 | #settings-title h1 { 30 | font-family: Rokkitt, Georgia, serif; 31 | font-style: normal; 32 | font-weight: 400; 33 | font-size: 32px; 34 | letter-spacing: -0.5; 35 | -webkit-font-smoothing: antialiased; 36 | } 37 | 38 | #settings-title p { 39 | margin: 10px 0; 40 | cursor: default; 41 | font-family: OpenSans; 42 | font-weight: normal; 43 | color: #55534e; 44 | letter-spacing: -0.6px; 45 | font-size: 15px; 46 | } 47 | 48 | #settings-title a { 49 | color: #dcb150; 50 | } 51 | 52 | .section-header { 53 | border-top: none; 54 | } 55 | 56 | .section-tail { 57 | border-bottom: 1px solid #E5E2DC; 58 | } 59 | 60 | .section-header > .table-cell { 61 | padding-top: 50px; 62 | padding-bottom: 10px; 63 | } 64 | 65 | #settings-back-btn { 66 | cursor: pointer; 67 | color: #E58D2F; 68 | left: 12px; 69 | position: absolute; 70 | top: 12px; 71 | } 72 | 73 | #shortcuts-back-btn{ 74 | cursor: pointer; 75 | color: #E58D2F; 76 | left: 12px; 77 | position: absolute; 78 | top: 12px; 79 | } 80 | 81 | .menu li { 82 | border-top: 1px solid #EEE3CE; 83 | position: relative; 84 | cursor: pointer; 85 | } 86 | 87 | .menu li.has_submenu:after { 88 | background: url(../img/nav_arrow.png) no-repeat; 89 | background-size: 9px 14px; 90 | content: ""; 91 | display: inline-block; 92 | height: 14px; 93 | position: absolute; 94 | right: 12px; 95 | top: 13px; 96 | width: 9px; 97 | } 98 | 99 | .menu a { 100 | color: #55534e; 101 | display: block; 102 | padding: 12px; 103 | } 104 | 105 | .menu strong { 106 | display: inline-block; 107 | padding: 12px 0 12px 12px; 108 | } 109 | 110 | .container .status-cell { 111 | width: auto; 112 | } 113 | 114 | .container .status-label { 115 | width: auto; 116 | margin-left: 0; 117 | } 118 | /* End of Settings */ 119 | -------------------------------------------------------------------------------- /tunnelbear/src/_locales/zh_CN/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extShortDesc": { 3 | "message": "简单又英俊。TunnelBear Blocker 咬住跟踪您的网站不放,帮助保护您的网络安全与隐私。", 4 | "description": "" 5 | }, 6 | "back": { 7 | "message": "后退", 8 | "description": "" 9 | }, 10 | "on": { 11 | "message": "开", 12 | "description": "" 13 | }, 14 | "off": { 15 | "message": "关", 16 | "description": "" 17 | }, 18 | "settingsTitle": { 19 | "message": "TunnelBear Blocker 设置", 20 | "description": "" 21 | }, 22 | "settingsBlockAds": { 23 | "message": "阻挡广告", 24 | "description": "" 25 | }, 26 | "settingsBlockFlash": { 27 | "message": "Flash 需要通过我的允许", 28 | "description": "" 29 | }, 30 | "settingsBlockBrowserFingerprinting": { 31 | "message": "阻挡浏览器跟踪指纹", 32 | "description": "" 33 | }, 34 | "settingsBlockMicrophone": { 35 | "message": "阻挡麦克风", 36 | "description": "" 37 | }, 38 | "settingsBlockKeyboard": { 39 | "message": "阻挡键盘跟踪", 40 | "description": "" 41 | }, 42 | "settingsBlockMouse": { 43 | "message": "阻挡鼠标跟踪", 44 | "description": "" 45 | }, 46 | "settingsBlockEmail": { 47 | "message": "阻挡像素跟踪 (gmail)", 48 | "description": "" 49 | }, 50 | "settingsBlockwebRTC": { 51 | "message": "防止 webRTC 漏泄", 52 | "description": "" 53 | }, 54 | "settingsBlockSocial": { 55 | "message": "阻挡社交网站按钮", 56 | "description": "" 57 | }, 58 | "settingsAdditionalList": { 59 | "message": "额外的阻挡列表", 60 | "description": "" 61 | }, 62 | "settingsBlockPrivacy": { 63 | "message": "隐私保护(推荐开启)", 64 | "description": "" 65 | }, 66 | "settingsBlockMalware": { 67 | "message": "恶意软件保护", 68 | "description": "" 69 | }, 70 | "whitelist": { 71 | "message": "白名单", 72 | "description": "" 73 | }, 74 | "blacklist": { 75 | "message": "黑名单", 76 | "description": "" 77 | }, 78 | "popupBlocked": { 79 | "message": "项已被阻挡" 80 | }, 81 | "ads": { 82 | "message": "广告" 83 | }, 84 | "flash": { 85 | "message": "Flash" 86 | }, 87 | "fingerprinting": { 88 | "message": "指纹跟踪" 89 | }, 90 | "keyboard": { 91 | "message": "键盘" 92 | }, 93 | "mouse": { 94 | "message": "鼠标" 95 | }, 96 | "microphone": { 97 | "message": "超声波(麦克风)" 98 | }, 99 | "social": { 100 | "message": "社交按钮" 101 | }, 102 | "privacy": { 103 | "message": "脚本与跟踪软件" 104 | }, 105 | "malware": { 106 | "message": "恶意软件" 107 | }, 108 | "email": { 109 | "message": "电子邮件" 110 | }, 111 | "tooltipReport": { 112 | "message": "提交报告" 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /tunnelbear/src/js/blockbear-contentscript-start.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | if (typeof vAPI === 'undefined' || !vAPI) { 4 | return; 5 | } 6 | 7 | var messager = vAPI.messaging; 8 | messager.addChannelListener('blockbear-contentscript-start.js'); 9 | var notifications = []; 10 | window.addEventListener('message', function (event) { 11 | if (event && event.data && event.data.source == 'blockbear') { 12 | switch (event.data.message) { 13 | case 'restore-fingerprinting': 14 | messager.send('blockbear-contentscript-start.js', { what: 'clearFingerprintingCount' }); 15 | break; 16 | case 'restore-keyboard': 17 | messager.send('blockbear-contentscript-start.js', { what: 'clearKeyboardCount' }); 18 | break; 19 | case 'keyboard': 20 | messager.send('blockbear-contentscript-start.js', { what: 'incrementKeyboardCount', message: event.data.message, data: event.data.data }); 21 | break; 22 | case 'restore-mouse': 23 | messager.send('blockbear-contentscript-start.js', { what: 'clearMouseCount' }); 24 | break; 25 | case 'mouse': 26 | messager.send('blockbear-contentscript-start.js', { what: 'incrementMouseCount', message: event.data.message, data: event.data.data }); 27 | break; 28 | case 'restore-microphone': 29 | messager.send('blockbear-contentscript-start.js', { what: 'clearMicrophoneCount' }); 30 | break; 31 | case 'microphone': 32 | messager.send('blockbear-contentscript-start.js', { what: 'incrementMicrophoneCount', message: event.data.message, data: event.data.data }); 33 | break; 34 | default: 35 | if (notifications.indexOf(event.data.message) == -1) { 36 | console.log(event.data.message); 37 | notifications.push(event.data.message); 38 | messager.send('blockbear-contentscript-start.js', { what: 'incrementFingerprintingCount', message: event.data.message, data: event.data.data }); 39 | } 40 | break; 41 | } 42 | } 43 | }); 44 | 45 | var reset = function (blockMicrophone) { 46 | let browserObj = navigator.userAgent.indexOf("Firefox") ? browser : chrome; 47 | let script = this.document.createElement("script"); 48 | script.dataset.blockMicrophone = blockMicrophone; 49 | script.src = browserObj.runtime.getURL("js/blockbear-contentscript-inject.js"); 50 | script.onload = function() { 51 | this.remove(); 52 | }; 53 | (this.document.head || this.document.documentElement).appendChild(script); 54 | } 55 | 56 | messager.send('blockbear-contentscript-start.js', { 57 | what: 'blockBrowserFingerprinting' 58 | }, function (response) { 59 | reset(response.blockMicrophone); 60 | }); 61 | 62 | })(); 63 | -------------------------------------------------------------------------------- /tunnelbear/src/_locales/fr/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extShortDesc": { 3 | "message": "Simple and handsome. TunnelBear Blocker sinks its teeth into online tracking to keep your browsing habits a little more private.", 4 | "description": "" 5 | }, 6 | "back": { 7 | "message": "Retour", 8 | "description": "" 9 | }, 10 | "on": { 11 | "message": "ON", 12 | "description": "" 13 | }, 14 | "off": { 15 | "message": "OFF", 16 | "description": "" 17 | }, 18 | "settingsTitle": { 19 | "message": "TunnelBear Blocker Paramètres", 20 | "description": "" 21 | }, 22 | "settingsBlockAds": { 23 | "message": "Bloquer les pubs", 24 | "description": "" 25 | }, 26 | "settingsBlockFlash": { 27 | "message": "Flash a besoin de mon autorisation", 28 | "description": "" 29 | }, 30 | "settingsBlockBrowserFingerprinting": { 31 | "message": "Bloquer l'empreinte du navigateur", 32 | "description": "" 33 | }, 34 | "settingsBlockMicrophone": { 35 | "message": "Bloquer le microphone", 36 | "description": "" 37 | }, 38 | "settingsBlockKeyboard": { 39 | "message": "Bloquer le suivi du clavier", 40 | "description": "" 41 | }, 42 | "settingsBlockMouse": { 43 | "message": "Bloquer le suivi de la souris", 44 | "description": "" 45 | }, 46 | "settingsBlockEmail": { 47 | "message": "Bloquer les pixels espions (gmail)", 48 | "description": "" 49 | }, 50 | "settingsBlockwebRTC": { 51 | "message": "Empêcher les fuites WebRTC", 52 | "description": "" 53 | }, 54 | "settingsBlockSocial": { 55 | "message": "Bloquer les boutons sociaux", 56 | "description": "" 57 | }, 58 | "settingsAdditionalList": { 59 | "message": "Listes additionnelles", 60 | "description": "" 61 | }, 62 | "settingsBlockPrivacy": { 63 | "message": "Protection de votre Confidentialité (Recommandé)", 64 | "description": "" 65 | }, 66 | "settingsBlockMalware": { 67 | "message": "Protection contre les malwares", 68 | "description": "" 69 | }, 70 | "whitelist": { 71 | "message": "liste blanche", 72 | "description": "" 73 | }, 74 | "blacklist": { 75 | "message": "liste noire", 76 | "description": "" 77 | }, 78 | "popupBlocked": { 79 | "message": "Bloque(s)" 80 | }, 81 | "ads": { 82 | "message": "Pubs" 83 | }, 84 | "flash": { 85 | "message": "Flash" 86 | }, 87 | "fingerprinting": { 88 | "message": "Empreinte" 89 | }, 90 | "keyboard": { 91 | "message": "Clavier" 92 | }, 93 | "mouse": { 94 | "message": "Souris" 95 | }, 96 | "microphone": { 97 | "message": "Ultrason" 98 | }, 99 | "social": { 100 | "message": "Social" 101 | }, 102 | "privacy": { 103 | "message": "Confidentialité" 104 | }, 105 | "malware": { 106 | "message": "Malware" 107 | }, 108 | "email": { 109 | "message": "Email" 110 | }, 111 | "tooltipReport": { 112 | "message": "Rapport" 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [TunnelBear Blocker](https://www.tunnelbear.com/apps/blocker) 2 | 3 | **Simple and handsome. TunnelBear Blocker sinks its teeth into online tracking to keep your browsing habits a little more private.** 4 | 5 | **TunnelBear Blocker for Chrome is:** 6 | 7 | ✔ Handsome - Powerful online privacy protection wrapped in a simple, handsome bear design 8 | 9 | ✔ Powerful - Sure, it can block simple ads, but it can also block scripts, trackers, flash, fingerprinting (beta), email tracking, ultrasonic tracking, and more (coming soon) 10 | 11 | ✔ Whitelist - Block everything like a ruthless privacy dictator or show a little love to privacy-friendly content publishers — you decide 12 | 13 | ✔ Free and open source 14 | 15 | [Learn more about what TunnelBear Blocker blocks](https://www.tunnelbear.com/blocker/info) 16 | 17 | *** 18 | ## FAQ 19 | 20 | **Why should I use TunnelBear Blocker vs. other ad blockers?** 21 | 22 | ✔ We’ve earned the trust of over 15 million people around the globe to protect their privacy. 23 | 24 | ✔ TunnelBear Blocker blocks many types of online tracking, not just ads. 25 | 26 | ✔ Simple enough that anyone can use it. 27 | 28 | **Does TunnelBear Blocker replace TunnelBear VPN?** 29 | 30 | Not at all! TunnelBear Blocker is designed to compliment [TunnelBear VPN](https://www.tunnelbear.com/). 31 | Combine TunnelBear Blocker with TunnelBear VPN to keep your browsing habits private from more sources like ISPs, hackers, and websites that track your IP address. 32 | 33 | **Are there plans to support browsers other than Chrome?** 34 | 35 | TunnelBear Blocker is an ongoing project, and we are definitely looking to support the various popular browsers on the market today. Stay tuned! 36 | 37 | *** 38 | 39 | ## About 40 | 41 | TunnelBear Blocker is based off of [uBlock Origin](https://github.com/gorhill/uBlock), and we would like to thank its developers for all the tremendous hard work they have put in to make such a fantastic blocker. 42 | 43 | Additionally, we would like to thank the maintainers of the various list filters for their tremendous work and contribution to the community, along with the developers behind [PixelBlock](https://github.com/ramoq/PixelBlock), whose works are used as part of TunnelBear Blocker. 44 | 45 | The goal of TunnelBear Blocker is **NOT** to supersede uBlock Origin, but to offer a simpler, user-friendly alternative for a broader audience. 46 | 47 | * [Features and explanation](https://www.tunnelbear.com/apps/blocker) 48 | * [Attribution and Acknowledgement](https://www.tunnelbear.com/blocker/acknowledgement) 49 | * [Installation](https://chrome.google.com/webstore/detail/tunnelbear-blocker/bebdhgdigjiiamnkcenegafmfjoghafk) 50 | * [Manifesto](MANIFESTO.md) 51 | * [Privacy Policy](PRIVACY.md) 52 | 53 | TunnelBear Blocker was developed with love in Toronto, Canada, by [a group of privacy-loving individuals who believe in simple privacy for everyone](https://www.tunnelbear.com/about). 54 | 55 | *** 56 | 57 | ## Developers 58 | To compile TunnelBear Blocker from source: 59 | 60 | 1. Install `npm` if you don't have it yet 61 | 1. Run `npm install` 62 | 1. Run `git submodule init && git submodule update` 63 | 1. Run `bash tunnelbear/tools/make-chromium.sh` or `bash tunnelbear/tools/make-firefox.sh` for the platform that you want to build for 64 | 65 | *** 66 | 67 | ## License 68 | [GPLv3](LICENSE.txt) 69 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ### Submitting code changes 2 | 3 | For core code changes, we strongly recommend you upstream your contributions to [uBlock Origin](https://github.com/gorhill/uBlock/blob/master/CONTRIBUTING.md). 4 | Should you decide to submit it to us anyway, we will attempt to upstream any relevant changes to uBlock Origin with your authorship intact. 5 | 6 | This is a decision made out of respect for the uBlock Origin community; it is also our goal to sync with upstream periodically. 7 | 8 | For TunnelBear Blocker specific code changes, we will accept pull requests via Github and accredit you appropriately. 9 | 10 | *** 11 | 12 | ### Reporting issues 13 | For **specific site issues**, please use the report button within the extension. 14 | 15 | For **general issues**, please contact [TunnelBear support](https://www.tunnelbear.com/support). 16 | 17 | For **more technical issues**, we accept reports through the Github issues interface. 18 | 19 | In both cases, please provide us with the exact steps needed to reproduce the problem. Example of detailed steps: 20 | > 1. Browser version/TunnelBear Blocker version 21 | > 1. The settings you have enabled 22 | > 1. Do this 23 | > 1. Open this exact URL 24 | > 1. Do this 25 | > 1. Observe this 26 | > 1. Click this 27 | > 1. Observe such and such issue 28 | > 1. See screenshot 29 | > 1. etc. 30 | 31 | The fastest way for us to solve your issue is when **detailed steps** are provided. 32 | 33 | *** 34 | 35 | ### Before you submit 36 | 37 | 1. _One specific_ issue per submission. 38 | 1. Please do not post comments like "+1" or "me too!" without providing new, relevant info on the issue. It tends to drown out potentially useful information, and ends up wasting development resources. 39 | 1. Verify that the issue does **not** occur with TunnelBear Blocker disabled. 40 | 1. Verify that the issue is not caused by another extension. 41 | 1. Only report issues that can be reproduce in an official stable release or a beta release, and **NOT** on a Canary release. 42 | 43 | *** 44 | 45 | ### What to include 46 | 47 | To help diagnose and fix the bug/issue, please always include the following in your report: 48 | 49 | * A clear list of steps to reproduce the problem 50 | * **ALWAYS INCLUDE A SPECIFIC URL WHERE THE ISSUE OCCURS**, _even_ if "it happens everywhere". 51 | * Symptoms of the issue 52 | * Describe what you observe and consider broken behavior; this is what we'll be looking for after executing the steps 53 | * Example: video doesn't start playing, page layout broken 54 | * A screenshot or transcription of any TunnelBear Blocker settings that differ from the defaults 55 | * This includes a whitelisted website, enabled/disabled blocking items, etc. 56 | * Please do include everything different from the defaults whether or not it seems relevant to your issue 57 | * The version of Blocker you're having the issue with; you can find this in by going to your [extensions page](chrome://extensions/); it will be the number beside the TunnelBear Blocker title. 58 | * Example: `TunnelBear Blocker 0.9.1` 59 | * The browser you're using and its version 60 | * Examples: `Chrome 41.0.2272` 61 | * The OS you're using and its version 62 | * Examples: `Windows 10`, `Linux Mint 17.1` 63 | * A list of other extensions you have installed 64 | * Tip: try disabling them and see if your issue still occurs 65 | 66 | Otherwise, a lot of your time and ours gets spent on exchanging back and forth to get this information, rather than actually fixing the problem. That makes us sad bears. ): 67 | -------------------------------------------------------------------------------- /tunnelbear/src/js/blockbear-contentscript-inject.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | let blockMicrophone = document.currentScript.dataset.blockMicrophone === "true"; 3 | 4 | var defProperty = Object.defineProperty; 5 | var setApi = function (obj, property, isBlocked, fake, setter) { 6 | try { 7 | if (!obj[property + "_BACKUP"]) { 8 | obj[property + "_BACKUP"] = obj[property]; 9 | } 10 | defProperty(obj, property, { 11 | enumerable: true, 12 | configureable: false, 13 | get: function () { 14 | if (isBlocked()) { 15 | return fake(); 16 | } else { 17 | return obj[property + "_BACKUP"]; 18 | } 19 | }, 20 | set: setter 21 | }); 22 | } catch (e) { 23 | // console.log(e); 24 | } 25 | } 26 | 27 | Object.defineProperty = function (o, p, attributes) { 28 | return defProperty(o, p, attributes); 29 | } 30 | 31 | // https://audiofingerprint.openwpm.com/ 32 | if (blockMicrophone === true) { 33 | if (!window.blockMicrophone) { 34 | window.blockMicrophone = true; 35 | if (AudioContext) { 36 | setApi(window, "AudioContext", function () { return window.blockMicrophone }, function () { 37 | return function () { 38 | window.top.postMessage({ message: 'microphone', source: 'blockbear' }, '*'); 39 | }; 40 | }, function (audioContext) { }); 41 | } 42 | if (window.webkitAudioContext) { 43 | setApi(window, "webkitAudioContext", function () { return window.blockMicrophone }, function () { 44 | return function () { 45 | window.top.postMessage({ message: 'microphone', source: 'blockbear' }, '*'); 46 | }; 47 | }); 48 | } 49 | if (window.MediaStreamTrack) { 50 | setApi(window, "MediaStreamTrack", function () { return window.blockMicrophone }, function () { 51 | return function () { 52 | window.top.postMessage({ message: 'microphone', source: 'blockbear' }, '*'); 53 | }; 54 | }); 55 | } 56 | if (navigator) { 57 | setApi(navigator, "getUserMedia", function () { return window.blockMicrophone }, function () { 58 | return function (e, successCallback, errorCallback) { 59 | if (e.audio) { 60 | window.top.postMessage({ message: 'microphone', source: 'blockbear' }, '*'); 61 | } 62 | else { 63 | navigator["getUserMedia_BACKUP"](e, successCallback, errorCallback); 64 | } 65 | }; 66 | }, function (val) { 67 | window.top.postMessage({ message: 'microphone', source: 'blockbear' }, '*'); 68 | }); 69 | setApi(navigator, "webkitGetUserMedia", function () { return window.blockMicrophone }, function () { 70 | return function (e, successCallback, errorCallback) { 71 | if (e.audio) { 72 | window.top.postMessage({ message: 'microphone', source: 'blockbear' }, '*'); 73 | } else { 74 | navigator["webkitGetUserMedia_BACKUP"](e, successCallback, errorCallback) 75 | } 76 | }; 77 | }); 78 | setApi(navigator, "mediaDevices", function () { return window.blockMicrophone }, function () { 79 | return function () { 80 | window.top.postMessage({ message: 'microphone', source: 'blockbear' }, '*'); 81 | }; 82 | }); 83 | } 84 | } 85 | } else { 86 | window.blockMicrophone = false; 87 | window.top.postMessage({ message: 'restore-microphone', source: 'blockbear' }, '*'); 88 | } 89 | })(); -------------------------------------------------------------------------------- /tunnelbear/src/js/blockbear-background.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | 'use strict'; 4 | 5 | /******************************************************************************/ 6 | 7 | var µb = µBlock; 8 | if (µb.blockbear === undefined) { 9 | µb.blockbear = {} 10 | } 11 | var bb = µb.blockbear; 12 | 13 | /******************************************************************************/ 14 | 15 | bb.settings = { 16 | blockBearEnabled: true, 17 | blockAdsEnabled: true, 18 | flashbearEnabled: true, 19 | blockBrowserFingerprintingEnabled: true, 20 | blockMicrophoneEnabled: true, 21 | blockKeyboardEnabled: true, 22 | blockMouseEnabled: true, 23 | blockEmailEnabled: true, 24 | blockSocialEnabled: true, 25 | blockPrivacyEnabled: true, 26 | blockMalwareEnabled: true, 27 | blockerBadgeAnimationEnabled: true, 28 | showPopupDetails: false 29 | } 30 | 31 | /******************************************************************************/ 32 | 33 | bb.browserType = (window.navigator.userAgent.indexOf("Firefox") > -1) ? "firefox" : "chrome"; 34 | 35 | /******************************************************************************/ 36 | 37 | bb.loadSettingsFromStorage = function (callback) { 38 | let settingsKey = 'blockbearSettings' 39 | vAPI.storage.get(settingsKey, function (result) { 40 | if (settingsKey in result) { 41 | let settings = result[settingsKey] 42 | for (let key in settings) { 43 | if (settings.hasOwnProperty(key) && bb.settings.hasOwnProperty(key)) { 44 | bb.settings[key] = settings[key] 45 | } 46 | } 47 | } 48 | callback() 49 | }) 50 | } 51 | 52 | bb.saveSettingsToStorage = function () { 53 | vAPI.storage.set({ blockbearSettings: bb.settings }); 54 | } 55 | 56 | /******************************************************************************/ 57 | 58 | bb.fetchLatestFilterLists = function () { 59 | µb.scheduleAssetUpdater(0); 60 | µb.assets.updateStart({ 61 | delay: µb.hiddenSettings.manualUpdateAssetFetchPeriod 62 | }); 63 | } 64 | 65 | /******************************************************************************/ 66 | 67 | let _firstInstall = µb.firstInstall 68 | let timesSet = 0 69 | 70 | Object.defineProperty(µb, "firstInstall", { 71 | get() { 72 | return _firstInstall; 73 | }, 74 | set(value) { 75 | _firstInstall = value; 76 | timesSet++; 77 | if (timesSet === 2) { 78 | onStartup() 79 | } 80 | } 81 | }); 82 | 83 | let onStartup = function () { 84 | bb.loadSettingsFromStorage(function () { 85 | bb.updateFilters(); 86 | bb.fetchLatestFilterLists(); 87 | setInterval(bb.fetchLatestFilterLists, 1000 * 60 * 60 * 24) // Look for updates every day 88 | }); 89 | } 90 | 91 | /******************************************************************************/ 92 | 93 | µb.userSettings.contextMenuEnabled = false; 94 | µb.userSettings.webrtcIPAddressHidden = true; 95 | 96 | /******************************************************************************/ 97 | 98 | vAPI.storage.get(['installDate', 'promoReferenceDate'], function (result) { 99 | var setInstallDate = function setInstallDate() { 100 | var installDateObj = new Date(); 101 | vAPI.storage.set({ 102 | installDate: installDateObj.toString(), 103 | promoReferenceDate: installDateObj.toString() 104 | }); 105 | }; 106 | 107 | if (!result || !result.installDate || !result.promoReferenceDate) { 108 | setInstallDate(); 109 | } 110 | }); 111 | 112 | /******************************************************************************/ 113 | 114 | let browserObj = (bb.browserType === "firefox") ? browser : chrome; 115 | browserObj.runtime.setUninstallURL("https://www.tunnelbear.com/account#/feedback/blocker"); 116 | 117 | /******************************************************************************/ 118 | 119 | })(); 120 | -------------------------------------------------------------------------------- /tunnelbear/src/_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extShortDesc": { 3 | "message": "Simple and handsome. TunnelBear Blocker sinks its teeth into online tracking to keep your browsing habits a little more private.", 4 | "description": "" 5 | }, 6 | "back": { 7 | "message": "Back", 8 | "description": "" 9 | }, 10 | "on": { 11 | "message": "ON", 12 | "description": "" 13 | }, 14 | "off": { 15 | "message": "OFF", 16 | "description": "" 17 | }, 18 | "settingsTitle": { 19 | "message": "TunnelBear Blocker Settings", 20 | "description": "" 21 | }, 22 | "settingsBlockAds": { 23 | "message": "Block ads", 24 | "description": "" 25 | }, 26 | "settingsBlockFlash": { 27 | "message": "Flash requires my permission", 28 | "description": "" 29 | }, 30 | "settingsBlockBrowserFingerprinting": { 31 | "message": "Block browser fingerprinting", 32 | "description": "" 33 | }, 34 | "settingsBlockEmail": { 35 | "message": "Block pixel tracking (Gmail)", 36 | "description": "" 37 | }, 38 | "settingsBlockMicrophone": { 39 | "message": "Block microphone", 40 | "description": "" 41 | }, 42 | "settingsBlockSocial": { 43 | "message": "Block social buttons", 44 | "description": "" 45 | }, 46 | "settingsBlockKeyboard": { 47 | "message": "Block keyboard tracking", 48 | "description": "" 49 | }, 50 | "settingsBlockMouse": { 51 | "message": "Block mouse tracking", 52 | "description": "" 53 | }, 54 | "settingsBlockwebRTC": { 55 | "message": "Disable WebRTC", 56 | "description": "" 57 | }, 58 | "settingsBlockerBadgeAnimation": { 59 | "message": "Animate extension badge", 60 | "description": "" 61 | }, 62 | "settingsAdditionalList": { 63 | "message": "Additional Block Lists", 64 | "description": "" 65 | }, 66 | "settingsBlockPrivacy": { 67 | "message": "Privacy protection (recommended)", 68 | "description": "" 69 | }, 70 | "settingsBlockMalware": { 71 | "message": "Malware protection", 72 | "description": "" 73 | }, 74 | "docblockedPrompt1": { 75 | "message": "Blocker has prevented the following page from loading:", 76 | "description": "English: Blocker has prevented the following page from loading:" 77 | }, 78 | "docblockedPrompt2": { 79 | "message": "Because of the following filter", 80 | "description": "English: Because of the following filter" 81 | }, 82 | "docblockedNoParamsPrompt": { 83 | "message": "without parameters", 84 | "description": "label to be used for the parameter-less URL: https://cloud.githubusercontent.com/assets/585534/9832014/bfb1b8f0-593b-11e5-8a27-fba472a5529a.png" 85 | }, 86 | "docblockedFoundIn": { 87 | "message": "Found in:", 88 | "description": "English: List of filter list names follows" 89 | }, 90 | "docblockedBack": { 91 | "message": "Go back", 92 | "description": "English: Go back" 93 | }, 94 | "docblockedClose": { 95 | "message": "Close", 96 | "description": "English: Close" 97 | }, 98 | "docblockedTitle": { 99 | "message": "Page Blocked", 100 | "description": "English: Page Blocked" 101 | }, 102 | "whitelist": { 103 | "message": "whitelist", 104 | "description": "" 105 | }, 106 | "blacklist": { 107 | "message": "blacklist", 108 | "description": "" 109 | }, 110 | "popupBlocked": { 111 | "message": "Blocked" 112 | }, 113 | "ads": { 114 | "message": "Ads" 115 | }, 116 | "flash": { 117 | "message": "Flash" 118 | }, 119 | "fingerprinting": { 120 | "message": "Fingerprinting" 121 | }, 122 | "keyboard": { 123 | "message": "Keyboard" 124 | }, 125 | "mouse": { 126 | "message": "Mouse" 127 | }, 128 | "microphone": { 129 | "message": "Ultrasonic" 130 | }, 131 | "social": { 132 | "message": "Social Buttons" 133 | }, 134 | "privacy": { 135 | "message": "Scripts & Trackers" 136 | }, 137 | "malware": { 138 | "message": "Malware" 139 | }, 140 | "email": { 141 | "message": "Email" 142 | }, 143 | "tooltipReport": { 144 | "message": "Report" 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /tunnelbear/src/js/blockbear-page-counts.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | 4 | /******************************************************************************/ 5 | /******************************************************************************/ 6 | 7 | (function () { 8 | 9 | /******************************************************************************/ 10 | 11 | var µb = µBlock; 12 | var bb = µb.blockbear; 13 | 14 | /******************************************************************************/ 15 | 16 | // Store blocked counts for each tabs 17 | let tabsCounts = new Map(); 18 | 19 | function makeEmptyTabCounts(pageLoadCounter) { 20 | let ret = { 21 | adsBlocked: 0, 22 | flashBlocked: 0, 23 | fingerprintingBlocked: 0, 24 | keyboardBlocked: 0, 25 | mouseBlocked: 0, 26 | emailBlocked: 0, 27 | ultrasonicBlocked: 0, 28 | socialBlocked: 0, 29 | privacyBlocked: 0, 30 | malwareBlocked: 0 31 | } 32 | if (pageLoadCounter !== undefined) { 33 | ret.pageLoadCounter = pageLoadCounter; 34 | } 35 | return ret; 36 | } 37 | 38 | function resetTabCounters(tabId) { 39 | let newLoadCounter = 0; 40 | if (tabsCounts.has(tabId)) { 41 | newLoadCounter = (tabsCounts.get(tabId).pageLoadCounter + 1) % 0xFFFFFFFF; 42 | } 43 | tabsCounts.set(tabId, makeEmptyTabCounts(newLoadCounter)) 44 | } 45 | 46 | function pruneTabsCounts() { 47 | let tabsHandler = function (openTabs) { 48 | let openTabIds = new Set(openTabs.map(tab => tab.id)); 49 | [...tabsCounts.keys()].forEach(function (tabId) { 50 | if (!openTabIds.has(tabId)) { 51 | tabsCounts.delete(tabId); 52 | } 53 | }) 54 | } 55 | if (bb.browserType === "firefox") { 56 | browser.tabs.query({}).then(tabsHandler); 57 | } else { 58 | chrome.tabs.query({}, tabsHandler); 59 | } 60 | } 61 | 62 | setInterval(pruneTabsCounts, 30 * 1000); 63 | 64 | /******************************************************************************/ 65 | 66 | function onLogBufferRead(logEntries) { 67 | let isBlockedEntry = entry => entry.d0 !== undefined && entry.d0.result === 1 68 | let isMainFrame = entry => entry.d1 === "main_frame" 69 | 70 | let filteredEntries = logEntries 71 | .filter(entry => tabsCounts.has(entry.tab)) 72 | .filter(entry => isMainFrame(entry) || isBlockedEntry(entry)) 73 | 74 | filteredEntries.forEach(function (entry) { 75 | if (isMainFrame(entry)) { 76 | resetTabCounters(entry.tab) 77 | } else { 78 | let loadCounter = bb.getBlockedCounts(entry.tab).pageLoadCounter; 79 | classifyBlockedEntry(entry, loadCounter); 80 | } 81 | }) 82 | } 83 | 84 | function classifyBlockedEntry(entry, loadCounter, tries) { 85 | if (tries !== undefined && tries >= 5) { 86 | console.log("Unable to find list for: " + JSON.stringify(entry)); 87 | return; 88 | } 89 | let compiled = entry.d0.compiled 90 | let raw = entry.d0.raw 91 | µb.staticFilteringReverseLookup.fromNetFilter(compiled, raw, result => { 92 | let counts = µb.blockbear.getBlockedCounts(entry.tab); 93 | if (counts.pageLoadCounter !== loadCounter) { 94 | return; 95 | } 96 | 97 | if (result[raw] && result[raw].length > 0) { 98 | let filterListKey = result[raw][0].assetKey; 99 | let category = µb.blockbear.classifyFilterList(filterListKey); 100 | if (category === 'ads') { 101 | counts.adsBlocked++; 102 | } else if (category === 'privacy') { 103 | counts.privacyBlocked++; 104 | } else if (category === 'malware') { 105 | counts.malwareBlocked++; 106 | } else if (category === 'social') { 107 | counts.socialBlocked++; 108 | } 109 | } else { 110 | setTimeout(function () { 111 | classifyBlockedEntry(entry, loadCounter, tries === undefined ? 1 : tries + 1); 112 | }, 200); 113 | } 114 | }); 115 | } 116 | 117 | let loggerOwnerId = Date.now() 118 | 119 | function readLogBuffer() { 120 | let logEntries = µb.logger.readAll(loggerOwnerId); 121 | onLogBufferRead(logEntries); 122 | } 123 | 124 | setInterval(readLogBuffer, 1500) 125 | 126 | /******************************************************************************/ 127 | 128 | µb.blockbear.getBlockedCounts = function (tabId) { 129 | if (!tabsCounts.has(tabId)) { 130 | resetTabCounters(tabId); 131 | } 132 | return tabsCounts.get(tabId); 133 | } 134 | 135 | /******************************************************************************/ 136 | 137 | })(); -------------------------------------------------------------------------------- /tunnelbear/src/css/popup.css: -------------------------------------------------------------------------------- 1 | .body-mode-normal { 2 | -webkit-transition: width 0.3s, height 0.3s; 3 | transition: width 0.3s, height 0.3s; 4 | -webkit-transform: translateX(0); 5 | transform: translateX(0); 6 | width: 258px; 7 | height: 100%; 8 | } 9 | 10 | .table-row.progress-bar.hidden { 11 | background: #f2f1f0; 12 | } 13 | 14 | .report { 15 | background: url('../img/report_icon_normal2x.png'); 16 | background-size: 18px 18px; 17 | background-repeat: no-repeat; 18 | height: 18px; 19 | width: 18px; 20 | float: left; 21 | margin-left: 5px; 22 | } 23 | 24 | .report:hover { 25 | background: url('../img/report_icon_hover2x.png'); 26 | background-size: 18px 18px; 27 | background-repeat: no-repeat; 28 | } 29 | 30 | .container .caption { 31 | background: #faf9f7; 32 | padding-top: 14px; 33 | box-sizing: border-box; 34 | } 35 | 36 | .container .blocker-toggle { 37 | background: #faf9f7; 38 | } 39 | 40 | .count-tracker { 41 | border-top-color: transparent; 42 | background: #f2f1f0; 43 | border-bottom-color: #e5e2dc; 44 | border-bottom-style: solid; 45 | border-bottom-width: 1px; 46 | cursor: pointer; 47 | } 48 | 49 | .tracker-details { 50 | border-top-color: transparent; 51 | background: #faf9f7; 52 | padding-top: 5px; 53 | } 54 | 55 | .tracker-details .toggle-background.mini { 56 | background: #C6C4BF; 57 | } 58 | 59 | .tracker-details .toggle-background.mini.enabled { 60 | background: #AF9E93; 61 | } 62 | 63 | .tracker-details .progress-bar .bar { 64 | width: 238px; 65 | padding: 0 10px; 66 | } 67 | 68 | .tracker-details .progress-bar .bar span { 69 | border-radius: 4px; 70 | } 71 | 72 | .tracker-details .progress-bar { 73 | background: transparent; 74 | } 75 | 76 | .tracker-details .medium-row { 77 | height: auto; 78 | } 79 | 80 | .tracker-details .table-cell { 81 | vertical-align: top; 82 | padding-top: 2px; 83 | } 84 | 85 | .tracker-details .table-row.first .table-cell { 86 | padding-top: 10px; 87 | } 88 | 89 | .tracker-details .progress-bar .table-cell { 90 | padding-bottom: 5px; 91 | } 92 | 93 | .tracker-details .progress-bar.last .table-cell { 94 | padding-bottom: 5px; 95 | } 96 | 97 | .tracker-details .bar span:hover { 98 | text-decoration: underline; 99 | cursor: pointer; 100 | } 101 | 102 | .tracker-details .bar span.disabled{ 103 | color: #d2d0cb!important; 104 | } 105 | 106 | .tracker-details .bar.blocks span { 107 | color: #72c4d2; 108 | } 109 | 110 | .tracker-details .bar.privacy span { 111 | color: #a5ce4e; 112 | } 113 | 114 | .tracker-details .bar.fingerprinting span { 115 | color: #b979fb; 116 | } 117 | 118 | .tracker-details .bar.email span { 119 | color: #6473e5; 120 | } 121 | 122 | .tracker-details .bar.keyboard span { 123 | color: #de7045; 124 | } 125 | 126 | .tracker-details .bar.mouse span { 127 | color: #c2b523; 128 | } 129 | 130 | .tracker-details .bar.microphone span { 131 | color: #5fe197; 132 | } 133 | 134 | .tracker-details .bar.social span { 135 | color: #70db5c; 136 | } 137 | 138 | .tracker-details .bar.ads span { 139 | color: #65ade9; 140 | } 141 | 142 | .tracker-details .bar.flash span { 143 | color: #e9658d; 144 | } 145 | 146 | .tracker-details .bar.malware span { 147 | color: #ebaf38; 148 | } 149 | 150 | .tracker-details span { 151 | font-size: 14px; 152 | } 153 | 154 | .tracker-details .bar.blocks .toggle-background.mini.enabled { 155 | background: #72c4d2; 156 | } 157 | 158 | .tracker-details .bar.privacy .toggle-background.mini.enabled { 159 | background: #a5ce4e; 160 | } 161 | 162 | .tracker-details .bar.fingerprinting .toggle-background.mini.enabled { 163 | background: #b979fb; 164 | } 165 | 166 | .tracker-details .bar.email .toggle-background.mini.enabled { 167 | background: #6473e5; 168 | } 169 | 170 | .tracker-details .bar.keyboard .toggle-background.mini.enabled { 171 | background: #de7045; 172 | } 173 | 174 | .tracker-details .bar.mouse .toggle-background.mini.enabled { 175 | background: #c2b523; 176 | } 177 | 178 | .tracker-details .bar.microphone .toggle-background.mini.enabled { 179 | background: #5fe197; 180 | } 181 | 182 | .tracker-details .bar.social .toggle-background.mini.enabled { 183 | background: #70db5c; 184 | } 185 | 186 | .tracker-details .bar.ads .toggle-background.mini.enabled { 187 | background: #65ade9; 188 | } 189 | 190 | .tracker-details .bar.flash .toggle-background.mini.enabled { 191 | background: #e9658d; 192 | } 193 | 194 | .tracker-details .bar.malware .toggle-background.mini.enabled { 195 | background: #ebaf38; 196 | } 197 | 198 | /* Whitelist */ 199 | 200 | .container .whitelist { 201 | background: #f2f1f0; 202 | } 203 | 204 | .container .whitelist .toggle-background.enabled { 205 | background: #dcb150; 206 | } 207 | 208 | .container .whitelist .toggle-background { 209 | background: #C6C4BF; 210 | } 211 | 212 | /* End of Whitelist */ 213 | -------------------------------------------------------------------------------- /tunnelbear/src/js/blockbear-toolbar-icon.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | 'use strict'; 4 | 5 | /******************************************************************************/ 6 | 7 | var µb = µBlock; 8 | 9 | /******************************************************************************/ 10 | 11 | var toChromiumTabId = function (tabId) { 12 | if (typeof tabId === 'string') { 13 | tabId = parseInt(tabId, 10); 14 | } 15 | if (typeof tabId !== 'number' || isNaN(tabId) || tabId === -1) { 16 | return 0; 17 | } 18 | return tabId; 19 | }; 20 | 21 | var IconState = function (badge, img) { 22 | this.badge = badge; 23 | // ^ a number -- the badge 'value' 24 | this.img = img; 25 | // ^ a string -- 'on' or 'off' 26 | this.dirty = (1 << 1) | (1 << 0); 27 | /* ^ bitmask AB: two bits, A and B 28 | where A is whether img has changed and needs render 29 | and B is whether badge has changed and needs render */ 30 | }; 31 | var iconStateForTabId = {}; // {tabId: IconState} 32 | 33 | var ICON_PATHS = { 34 | "on": { '16': 'img/icon_16.png', '32': 'img/icon_32.png' }, 35 | "on1": { '16': 'img/icon01.png', '32': 'img/icon01@2x.png' }, 36 | "on2": { '16': 'img/icon02.png', '32': 'img/icon02@2x.png' }, 37 | "on3": { '16': 'img/icon03.png', '32': 'img/icon03@2x.png' }, 38 | "off": { '16': 'img/icon_16-off.png', '32': 'img/icon_32-off.png' } 39 | }; 40 | 41 | var iconAnimations = []; 42 | var iconAnimated = false; 43 | 44 | vAPI.setIcon = function (tabId, iconStatus, badge) { 45 | if (µb.blockbear.settings.blockerBadgeAnimationEnabled === false) { 46 | chrome.browserAction.setIcon({ path: ICON_PATHS['on'] }); 47 | return; 48 | } 49 | tabId = toChromiumTabId(tabId); 50 | if (tabId === 0) { 51 | return; 52 | } 53 | var stopIconAnimation = function () { 54 | iconAnimated = false; 55 | } 56 | var playIconAnimation = function (tabId, i, badge) { 57 | iconAnimated = true; 58 | var icon = "on"; 59 | if (!i) { 60 | i = 0; 61 | } 62 | if (i > 0 && i < 4) { 63 | icon += i; 64 | } 65 | chrome.browserAction.setIcon({ tabId: tabId, path: ICON_PATHS[icon] }, function () { 66 | if (vAPI.lastError()) { 67 | stopIconAnimation(); 68 | return; 69 | } 70 | if (badge == 0) { 71 | stopIconAnimation(); 72 | } else { 73 | setTimeout(function () { 74 | if (i == 1) { 75 | chrome.browserAction.setBadgeBackgroundColor({ tabId: tabId, color: '#666' }); 76 | chrome.browserAction.setBadgeText({ tabId: tabId, text: '' }); 77 | } else { 78 | // if (i == 3) { 79 | // chrome.browserAction.setBadgeText({ tabId: tabId, text: badge }); 80 | // } 81 | } 82 | i++; 83 | if (i < 5) { 84 | playIconAnimation(tabId, i, badge); 85 | } else { 86 | if (iconAnimations.length > 0) { 87 | var anim = iconAnimations.shift(); 88 | playIconAnimation(anim.tabId, 0, anim.badge); 89 | } else { 90 | stopIconAnimation(); 91 | chrome.browserAction.setBadgeText({ tabId: tabId, text: badge }); 92 | } 93 | } 94 | }, 100); 95 | } 96 | }); 97 | } 98 | var state = iconStateForTabId[tabId]; 99 | if (typeof state === "undefined") { 100 | state = iconStateForTabId[tabId] = new IconState(badge, iconStatus); 101 | } 102 | else { 103 | state.oldBadge = state.badge; 104 | state.dirty = ((state.badge !== badge) << 1) | ((state.img !== iconStatus) << 0); 105 | state.badge = badge; 106 | state.img = iconStatus; 107 | } 108 | if ((state.dirty & 1) || (state.dirty & 2)) { // got a new icon? 109 | if (badge && state.oldBadge < badge) { 110 | console.log('SET BADGE: ' + badge); 111 | if (iconAnimated) { 112 | iconAnimations.push({ tabId: tabId, badge: badge }); 113 | } else { 114 | playIconAnimation(tabId, 0, badge); 115 | } 116 | } else { 117 | chrome.browserAction.setIcon({ tabId: tabId, path: ICON_PATHS[iconStatus] }); 118 | } 119 | } else { 120 | chrome.browserAction.setIcon({ tabId: tabId, path: ICON_PATHS[iconStatus] }); 121 | } 122 | }; 123 | 124 | /******************************************************************************/ 125 | 126 | µb.updateToolbarIcon = (function () { 127 | var tabIdToTimer = Object.create(null); 128 | 129 | var updateBadge = function (tabId) { 130 | delete tabIdToTimer[tabId]; 131 | 132 | var state = false; 133 | var badge = ''; 134 | 135 | var pageStore = this.pageStoreFromTabId(tabId); 136 | var blockedCounts = this.blockbear.getBlockedCounts(tabId); 137 | if (pageStore !== null) { 138 | state = pageStore.getNetFilteringSwitch(); 139 | if (state && this.userSettings.showIconBadge) { 140 | badge = this.formatCount( 141 | pageStore.perLoadBlockedRequestCount + 142 | blockedCounts.flashBlocked + 143 | blockedCounts.fingerprintingBlocked + 144 | blockedCounts.emailBlocked + 145 | blockedCounts.keyboardBlocked + 146 | blockedCounts.mouseBlocked + 147 | blockedCounts.ultrasonicBlocked 148 | ); 149 | } 150 | } 151 | 152 | vAPI.setIcon(tabId, state ? 'on' : 'off', badge); 153 | }; 154 | 155 | return function (tabId) { 156 | if (tabIdToTimer[tabId]) { 157 | return; 158 | } 159 | if (vAPI.isBehindTheSceneTabId(tabId)) { 160 | return; 161 | } 162 | tabIdToTimer[tabId] = vAPI.setTimeout(updateBadge.bind(this, tabId), 666); 163 | }; 164 | })(); 165 | 166 | /******************************************************************************/ 167 | 168 | })(); -------------------------------------------------------------------------------- /tunnelbear/src/js/blockbear-contentscript-end.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | 'use strict'; 4 | 5 | if (document instanceof HTMLDocument === false) { 6 | //console.debug('contentscript-end.js > not a HTLMDocument'); 7 | return false; 8 | } 9 | 10 | if (!vAPI) { 11 | //console.debug('contentscript-end.js > vAPI not found'); 12 | return; 13 | } 14 | 15 | var messager = vAPI.messaging; 16 | messager.addChannelListener('blockbear-contentscript-end.js'); 17 | window.addEventListener('message', function (event) { 18 | if (event && event.data && event.data.source == 'blockbear-pixel-tracking') { 19 | messager.send('blockbear-contentscript-end.js', { what: 'pixel-tracking' }); 20 | } 21 | }); 22 | 23 | (function () { 24 | var getResultFromXPath = function (iterator) { 25 | var result = []; 26 | try { 27 | var node = iterator.iterateNext(); 28 | while (node) { 29 | result.push(node); 30 | node = iterator.iterateNext(); 31 | } 32 | } 33 | catch (e) { 34 | console.log(e); 35 | } 36 | return result; 37 | } 38 | var getFlashElements = function (xpath, node) { 39 | if (!xpath) { 40 | xpath = "//object[contains(@type, 'x-shockwave-flash') and not(@classid)] | //object[contains(@type,'futuresplash') and not(@classid)] | //embed[contains(@type,'x-shockwave-flash')] | //embed[contains(@type,'futuresplash')]"; 41 | } 42 | if (!node) { 43 | node = document.body; 44 | } 45 | var iterator = document.evaluate(xpath, node, null, XPathResult.ANY_TYPE, null); 46 | var list = getResultFromXPath(iterator); 47 | return list; 48 | } 49 | var getFlashContainerToBlock = function () { 50 | var result = []; 51 | getFlashElements().forEach(function (element) { 52 | var computedStyle = window.getComputedStyle(element); 53 | if (element.style.display != 'none' 54 | && computedStyle.display != 'none' 55 | && !element.classList.contains("tb-unlock")) { 56 | element.style.display = 'none'; 57 | } 58 | var iterator = document.evaluate("parent::*[not(contains(@class, 'tb-container'))]", element, null, XPathResult.ANY_TYPE, null); 59 | var container = getResultFromXPath(iterator)[0]; 60 | if (container) { 61 | result.push(container); 62 | } 63 | }, this); 64 | return result; 65 | } 66 | var getBlockStyle = function (node) { 67 | var result = getFlashElements("embed | object", node) 68 | var style = window.getComputedStyle(result[0]); 69 | return { 70 | background: getBlockBackground(), 71 | width: style.width, 72 | height: style.height, 73 | top: style.top, 74 | left: style.left, 75 | position: 'absolute' 76 | } 77 | } 78 | var getBlockBackground = function (hover) { 79 | var img = 'img/flash_blocked'; 80 | if (hover) { 81 | img = 'img/flash_unblock'; 82 | } 83 | var suffix = ".png"; 84 | if (window.devicePixelRatio > 1) { 85 | suffix = "2x.png"; 86 | } 87 | return "url(" + chrome.extension.getURL(img + suffix) + ") 50% 50% no-repeat black"; 88 | } 89 | 90 | var blockFlash = function () { 91 | var containers = getFlashContainerToBlock(); 92 | containers.forEach(function (element) { 93 | blockFlashElement(element); 94 | }, this); 95 | } 96 | 97 | var blockFlashElement = function (element) { 98 | element.classList.add('tb-container'); 99 | var btn = document.createElement("div"); 100 | btn.classList.add("tb-block"); 101 | var style = getBlockStyle(element); 102 | for (var key in style) { 103 | btn.style[key] = style[key]; 104 | } 105 | btn.addEventListener("click", function (event) { 106 | var items = getFlashElements("embed | object", element); 107 | items.forEach(function (item) { 108 | unblockFlashElement(item); 109 | }, this); 110 | btn.style.display = "none"; 111 | }); 112 | btn.addEventListener("mouseover", function (event) { 113 | btn.style["background"] = getBlockBackground(true); 114 | }); 115 | btn.addEventListener("mouseout", function (event) { 116 | btn.style["background"] = getBlockBackground(); 117 | }); 118 | element.appendChild(btn); 119 | // Delay sending message because of count synchronization issues 120 | // see https://tbears.atlassian.net/browse/TB-12402 121 | setTimeout(function () { 122 | messager.send('blockbear-contentscript-end.js', { what: 'incrementFlashCount' }); 123 | }, 1000); 124 | } 125 | 126 | var unblockFlash = function () { 127 | var elements = getFlashElements(); 128 | elements.forEach(function (element) { 129 | unblockFlashElement(element); 130 | }, this); 131 | } 132 | 133 | var unblockFlashElement = function (element) { 134 | element.classList.add("tb-unlock"); 135 | element.style.display = ""; 136 | messager.send('blockbear-contentscript-end.js', { what: 'decrementFlashCount' }); 137 | } 138 | 139 | var applyFlashbear = function () { 140 | messager.send('blockbear-contentscript-end.js', { 141 | what: 'blockFlash' 142 | }, function (response) { 143 | if (response && response.result) { 144 | blockFlash(); 145 | } else { 146 | unblockFlash(); 147 | } 148 | }); 149 | } 150 | if (document.body) { 151 | new MutationObserver(function (mutations) { 152 | applyFlashbear(); 153 | }).observe(document.body, { childList: true, subtree: true }); 154 | applyFlashbear(); 155 | } 156 | })(); 157 | 158 | messager.send('blockbear-contentscript-end.js', { 159 | what: 'blockEmailEnabled' 160 | }, function (response) { 161 | if (response) { 162 | var sm = document.createElement('script'); 163 | sm.src = chrome.extension.getURL('js/blockbear-pixel-tracking.js'); 164 | document.getElementsByTagName('body')[0].appendChild(sm); 165 | } 166 | }); 167 | 168 | })(); 169 | -------------------------------------------------------------------------------- /tunnelbear/src/js/blockbear-pixel-tracking.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | // from PixelBlock 4 | 5 | var proxyPattern = 'googleusercontent.com/proxy'; 6 | var imgSafe = '?blockbear=img-safe#'; 7 | 8 | var blacklist = [ 9 | {name:'HubSpot', pattern:'t.signaux', url:'http://getsidekick.com'}, 10 | {name:'HubSpot', pattern:'t.senal', url:'http://getsidekick.com'}, 11 | {name:'HubSpot', pattern:'t.sidekickopen', url:'http://getsidekick.com'}, 12 | {name:'HubSpot', pattern:'t.sigopn', url:'http://getsidekick.com'}, 13 | {name:'Banana Tag', pattern:'bl-1.com', url:'http://bananatag.com'}, 14 | {name:'Boomerang', pattern:'mailstat.us/tr', url:'http://boomeranggmail.com'}, 15 | {name:'Cirrus Inisght', pattern:'tracking.cirrusinsight.com', url:'http://cirrusinsight.com'}, 16 | {name:'Customer.io ', pattern:'track.customer.io/e/o', url:'http://customer.io'}, 17 | {name:'Yesware', pattern:'app.yesware.com', url:'http://yesware.com'}, 18 | {name:'Yesware', pattern:'t.yesware.com', url:'http://yesware.com'}, 19 | {name:'Streak', pattern:'mailfoogae.appspot.com', url:'http://streak.com'}, 20 | {name:'LaunchBit', pattern:'launchbit.com/taz-pixel', url:'http://launchbit.com'}, 21 | {name:'MailChimp', pattern:'list-manage.com/track', url:'http://mailchimp.com'}, 22 | {name:'Postmark', pattern:'cmail1.com/t', url:'http://postmarkapp.com'}, 23 | {name:'iContact', pattern:'click.icptrack.com/icp/', url:'http://icontact.com'}, 24 | {name:'Infusionsoft', pattern:'infusionsoft.com/app/emailOpened', url:'http://infusionsoft.com'}, 25 | {name:'Intercom', pattern:'via.intercom.io/o', url:'http://intercom.com'}, 26 | {name:'Intercom', pattern:'intercom-mail-100.com/o', url:'http://intercom.com'}, 27 | {name:'Mandrill', pattern:'mandrillapp.com/track', url:'http://mandrillapp.com'}, 28 | {name:'Hubspot', pattern:'t.hsms06.com', url:'http://hubspot.com'}, 29 | {name:'RelateIQ', pattern:'app.relateiq.com/t.png', url:'http://relateiq.com'}, 30 | {name:'RJ Metrics', pattern:'go.rjmetrics.com', url:'http://rjmetrics.com'}, 31 | {name:'Mixpanel', pattern:'api.mixpanel.com/track', url:'http://mixpanel.com'}, 32 | {name:'Front App', pattern:'web.frontapp.com/api', url:'http://frontapp.com'}, 33 | {name:'Mailtrack.io', pattern:'mailtrack.io/trace', url:'http://mailtrack.io'}, 34 | {name:'ToutApp', pattern:'go.toutapp.com', url:'http://toutapp.com'}, 35 | {name:'Outreach', pattern:'app.outreach.io', url:'http://outreach.io'}, 36 | {name:'Outreach', pattern:'outrch.com/api/mailings/opened', url:'http://outreach.io'}, 37 | {name:'Mixmax', pattern:'track.mixmax.com/api', url:'http://mixmax.com'}, 38 | {name:'Mixmax', pattern:'email.mixmax.com/e/o', url:'http://mixmax.com'}, 39 | {name:'SendGrid', pattern:'sendgrid.net/wf/open', url:'http://sendgrid.com'}, 40 | {name:'ExactTarget', pattern:'exct.net/open.aspx', url:'http://exacttarget.com'}, 41 | {name:'Litmus', pattern:'emltrk.com', url:'http://litmus.com'}, 42 | {name:'dotmailer', pattern:'trackedlink.net', url:'http://dotmailer.com'}, 43 | {name:'Unknown', pattern:'google.com/appserve/mkt/img/', url:''}, 44 | {name:'Unknown', pattern:'mailer.dzone.com/open.php', url:''}, 45 | {name:'Unknown', pattern:'give.islamicreliefcanada.org/smtp.mailopen', url:''}, 46 | {name:'Unknown', pattern:'email.airmiles.ca/O', url:''} 47 | ]; 48 | 49 | /* 50 | * 51 | */ 52 | var is_blacklisted = function (img) { 53 | var blacklisted = false; 54 | 55 | for (var index = 0; index < blacklist.length; index++) { 56 | var element = blacklist[index]; 57 | if (img.src.indexOf(element.pattern) > 0) { 58 | blacklisted = true; 59 | } 60 | } 61 | 62 | // block all images left over that are 1 x 1 (or less, regardless) 63 | if (!blacklisted) { 64 | // fetch all possible height values 65 | var w1 = clean_height_width(img.style.width); 66 | var w2 = clean_height_width(img.style.maxWidth); 67 | var w3 = clean_height_width(img.style.minWidth); 68 | 69 | var w4 = -1; 70 | // check if width attr exists (otherwise dom always returns 0) 71 | if (typeof img.width != 'undefined') { 72 | w4 = clean_height_width(img.width); 73 | } 74 | 75 | // fetch all possible width values 76 | var h1 = clean_height_width(img.style.height); 77 | var h2 = clean_height_width(img.style.maxHeight); 78 | var h3 = clean_height_width(img.style.minHeight); 79 | 80 | var h4 = -1; 81 | // check if height attr exists (otherwise dom always returns 0) 82 | if (typeof img.height != 'undefined') { 83 | h4 = clean_height_width(img.height); 84 | } 85 | 86 | if ((w1 == 0 || w1 == 1 || w2 == 0 || w2 == 1 || w3 == 0 || w3 == 1 || w4 == 0 || w4 == 1) && 87 | (h1 == 0 || h1 == 1 || h2 == 0 || h2 == 1 || h3 == 0 || h3 == 1 || h4 == 0 || h4 == 1) 88 | ) { 89 | blacklisted = true; 90 | } 91 | } 92 | 93 | // if blacklisted, hide image (ie. prevent the tracking img from loading) 94 | if (blacklisted) { 95 | img.style.display = 'none'; 96 | if (img.className.indexOf('blockbear-img-tracking') == -1) { 97 | img.className = img.className.replace('blockbear-img-safe', '') + ' blockbear-img-tracking'; 98 | window.top.postMessage({ message: 'pixel-tracking', source: 'blockbear-pixel-tracking' }, '*'); 99 | } 100 | } 101 | return blacklisted; 102 | } 103 | 104 | var clean_height_width = function (x) { 105 | if (x !== "") return parseInt(x, 10); 106 | return -1; 107 | } 108 | 109 | var whitelist_image = function (img) { 110 | if (img.src.substring(0, 4) != 'data') { 111 | if (img.src.indexOf(imgSafe) == -1) { 112 | img.src = img.src.replace('#', imgSafe); 113 | } 114 | } 115 | if (img.className.indexOf('blockbear-img-safe') == -1) { 116 | img.className = img.className.replace('blockbear-img-tracking', '') + ' blockbear-img-safe'; 117 | } 118 | } 119 | 120 | var scan_images = function () { 121 | var mailBody = document.getElementsByClassName('nH hx'); 122 | if (mailBody.length > 0) { 123 | var images = mailBody[0].getElementsByTagName('img'); 124 | for (var index = 0; index < images.length; index++) { 125 | var element = images[index]; 126 | if (element.src.indexOf(proxyPattern) > 0) { 127 | if (!is_blacklisted(element)) { 128 | whitelist_image(element); 129 | } 130 | } 131 | } 132 | } 133 | setTimeout(scan_images, 150); 134 | } 135 | setTimeout(scan_images, 500); 136 | })(); -------------------------------------------------------------------------------- /tunnelbear/src/js/blockbear-settings.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | /******************************************************************************/ 4 | 5 | var messager = vAPI.messaging; 6 | messager.addChannelListener('blockbearSettings'); 7 | 8 | /******************************************************************************/ 9 | 10 | var getSettingsData = function (callback) { 11 | var onDataReceived = function (response) { 12 | callback(response); 13 | }; 14 | messager.send('blockbearSettings', { what: 'getSettingsData' }, onDataReceived); 15 | }; 16 | 17 | function SettingsViewModel(settingsData) { 18 | this.reload = false; 19 | this.isLoaded = ko.observable(true); 20 | 21 | this.settingsBlockAdsEnabled = ko.observable(settingsData.blockAdsEnabled); 22 | this.settingsFlashEnabled = ko.observable(settingsData.flashbearEnabled); 23 | this.settingsBrowserFingerprintingEnabled = ko.observable(settingsData.blockBrowserFingerprintingEnabled); 24 | this.settingsBlockMicrophoneEnabled = ko.observable(settingsData.blockMicrophoneEnabled); 25 | this.settingsBlockKeyboardEnabled = ko.observable(settingsData.blockKeyboardEnabled); 26 | this.settingsBlockMouseEnabled = ko.observable(settingsData.blockMouseEnabled); 27 | this.settingsBlockEmailEnabled = ko.observable(settingsData.blockEmailEnabled); 28 | this.settingsBlockWebRTCEnabled = ko.observable(settingsData.blockWebRTCEnabled); 29 | this.settingsSocialEnabled = ko.observable(settingsData.blockSocialEnabled); 30 | this.settingsPrivacyEnabled = ko.observable(settingsData.blockPrivacyEnabled); 31 | this.settingsMalwareEnabled = ko.observable(settingsData.blockMalwareEnabled); 32 | this.settingsBlockerBadgeAnimationEnabled = ko.observable(settingsData.blockerBadgeAnimationEnabled); 33 | 34 | this.settingsBlockAdsText = ko.computed(function () { 35 | return this.settingsBlockAdsEnabled() ? chrome.i18n.getMessage("on") : chrome.i18n.getMessage("off"); 36 | }, this); 37 | this.settingsFlashText = ko.computed(function () { 38 | return this.settingsFlashEnabled() ? chrome.i18n.getMessage("on") : chrome.i18n.getMessage("off"); 39 | }, this); 40 | this.settingsBrowserFingerprintingText = ko.computed(function () { 41 | return this.settingsBrowserFingerprintingEnabled() ? chrome.i18n.getMessage("on") : chrome.i18n.getMessage("off"); 42 | }, this); 43 | this.settingsBlockMicrophoneText = ko.computed(function () { 44 | return this.settingsBlockMicrophoneEnabled() ? chrome.i18n.getMessage("on") : chrome.i18n.getMessage("off"); 45 | }, this); 46 | this.settingsBlockKeyboardText = ko.computed(function () { 47 | return this.settingsBlockKeyboardEnabled() ? chrome.i18n.getMessage("on") : chrome.i18n.getMessage("off"); 48 | }, this); 49 | this.settingsBlockMouseText = ko.computed(function () { 50 | return this.settingsBlockMouseEnabled() ? chrome.i18n.getMessage("on") : chrome.i18n.getMessage("off"); 51 | }, this); 52 | this.settingsBlockEmailText = ko.computed(function () { 53 | return this.settingsBlockEmailEnabled() ? chrome.i18n.getMessage("on") : chrome.i18n.getMessage("off"); 54 | }, this); 55 | this.settingsBlockWebRTCText = ko.computed(function () { 56 | return this.settingsBlockWebRTCEnabled() ? chrome.i18n.getMessage("on") : chrome.i18n.getMessage("off"); 57 | }, this); 58 | this.settingsBlockerBadgeAnimationText = ko.computed(function () { 59 | return this.settingsBlockerBadgeAnimationEnabled() ? chrome.i18n.getMessage("on") : chrome.i18n.getMessage("off"); 60 | }, this); 61 | this.settingsSocialText = ko.computed(function () { 62 | return this.settingsSocialEnabled() ? chrome.i18n.getMessage("on") : chrome.i18n.getMessage("off"); 63 | }, this); 64 | this.settingsPrivacyText = ko.computed(function () { 65 | return this.settingsPrivacyEnabled() ? chrome.i18n.getMessage("on") : chrome.i18n.getMessage("off"); 66 | }, this); 67 | this.settingsMalwareText = ko.computed(function () { 68 | return this.settingsMalwareEnabled() ? chrome.i18n.getMessage("on") : chrome.i18n.getMessage("off"); 69 | }, this); 70 | 71 | this.toggleBlockAds = function () { 72 | var self = this; 73 | this.settingsBlockAdsEnabled(!this.settingsBlockAdsEnabled()); 74 | setTimeout(function () { 75 | messager.send('blockbearSettings', { what: 'toggleBlockAds' }, function () { 76 | self.reload = true; 77 | }); 78 | }, 500); 79 | }; 80 | this.toggleFlash = function () { 81 | this.settingsFlashEnabled(!this.settingsFlashEnabled()); 82 | messager.send('blockbearSettings', { what: 'toggleFlash' }); 83 | this.reload = true; 84 | }; 85 | this.toggleBrowserFingerprinting = function () { 86 | this.settingsBrowserFingerprintingEnabled(!this.settingsBrowserFingerprintingEnabled()); 87 | messager.send('blockbearSettings', { what: 'toggleBrowserFingerprinting' }); 88 | this.reload = true; 89 | }; 90 | this.toggleBlockMicrophone = function () { 91 | this.settingsBlockMicrophoneEnabled(!this.settingsBlockMicrophoneEnabled()); 92 | messager.send('blockbearSettings', { what: 'toggleBlockMicrophone' }); 93 | this.reload = true; 94 | }; 95 | this.toggleBlockKeyboard = function () { 96 | this.settingsBlockKeyboardEnabled(!this.settingsBlockKeyboardEnabled()); 97 | messager.send('blockbearSettings', { what: 'toggleBlockKeyboard' }); 98 | this.reload = true; 99 | }; 100 | this.toggleBlockMouse = function () { 101 | this.settingsBlockMouseEnabled(!this.settingsBlockMouseEnabled()); 102 | messager.send('blockbearSettings', { what: 'toggleBlockMouse' }); 103 | this.reload = true; 104 | }; 105 | this.toggleBlockEmail = function () { 106 | this.settingsBlockEmailEnabled(!this.settingsBlockEmailEnabled()); 107 | messager.send('blockbearSettings', { what: 'toggleBlockEmail' }); 108 | this.reload = true; 109 | }; 110 | this.toggleBlockWebRTC = function () { 111 | this.settingsBlockWebRTCEnabled(!this.settingsBlockWebRTCEnabled()); 112 | messager.send('blockbearSettings', { what: 'toggleBlockWebRTC' }); 113 | this.reload = true; 114 | }; 115 | this.toggleBlockerBadgeAnimation = function () { 116 | this.settingsBlockerBadgeAnimationEnabled(!this.settingsBlockerBadgeAnimationEnabled()); 117 | messager.send('blockbearSettings', { what: 'toggleBlockerBadgeAnimation' }); 118 | this.reload = true; 119 | }; 120 | this.toggleSocial = function () { 121 | var self = this; 122 | this.settingsSocialEnabled(!this.settingsSocialEnabled()); 123 | setTimeout(function () { 124 | messager.send('blockbearSettings', { what: 'toggleSocial' }, function () { 125 | self.reload = true; 126 | }); 127 | }, 500); 128 | }; 129 | this.togglePrivacy = function () { 130 | var self = this; 131 | this.settingsPrivacyEnabled(!this.settingsPrivacyEnabled()); 132 | setTimeout(function () { 133 | messager.send('blockbearSettings', { what: 'togglePrivacy' }, function () { 134 | self.reload = true; 135 | }); 136 | }, 500); 137 | }; 138 | this.toggleMalware = function () { 139 | var self = this; 140 | this.settingsMalwareEnabled(!this.settingsMalwareEnabled()); 141 | setTimeout(function () { 142 | messager.send('blockbearSettings', { what: 'toggleMalware' }, function () { 143 | self.reload = true; 144 | }); 145 | }, 500); 146 | }; 147 | } 148 | 149 | uDom.onLoad(function () { 150 | getSettingsData(function (response) { 151 | ko.applyBindings(new SettingsViewModel(response)); 152 | }); 153 | }); 154 | 155 | if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) { 156 | document.body.classList.add("firefox"); 157 | } 158 | 159 | /******************************************************************************/ 160 | 161 | })(); 162 | -------------------------------------------------------------------------------- /tunnelbear/src/html/document-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | TunnelBear Blocker - Page Blocked 6 | 7 | 243 | 244 | 245 | 246 |
247 |
248 | 249 |
250 |
251 | 252 |
253 |
254 |

255 |
256 | 257 |
258 | 259 |
260 | 267 | 268 | 269 | 273 | 274 | 280 | 281 |
282 |
283 |

284 |
285 |
286 |

287 |
288 |
289 |
290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | -------------------------------------------------------------------------------- /tunnelbear/src/html/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | TunnelBear Blocker 10 | 11 | 12 | 13 |
14 | 77 | 102 | 103 | 104 | 105 | 114 | 115 | 124 | 125 | 136 | 137 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /tunnelbear/src/html/settings.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | TunnelBear Blocker 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 |

Blocker Global Settings

18 |

Settings below apply to all websites. If you want to change settings for just one website, then just do that from within the extension.

19 |

To enhance your privacy, install uBlock Protector and help protect Blocker from anti-adblock scripts.

20 |
21 |
22 |
23 |
24 |
25 | 26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | 34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | 47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | 69 |
70 |
71 |
72 | 73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | 86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | 112 | 129 |
130 |
131 |
132 | 133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 | 146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 | 159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 | 172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 | 180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 | 193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | -------------------------------------------------------------------------------- /tunnelbear/src/js/blockbear-messaging.js: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | /******************************************************************************/ 3 | 4 | 'use strict'; 5 | 6 | (function () { 7 | 8 | /******************************************************************************/ 9 | 10 | var µb = µBlock; 11 | let bb = µb.blockbear; 12 | 13 | /******************************************************************************/ 14 | 15 | var onMessage = function (request, sender, callback) { 16 | // Async 17 | switch (request.what) { 18 | default: 19 | break; 20 | } 21 | 22 | // Sync 23 | var response; 24 | 25 | var pageStore; 26 | if (sender && sender.tab) { 27 | pageStore = µb.pageStoreFromTabId(sender.tab.id); 28 | } 29 | let blockedCounts = bb.getBlockedCounts(sender.tab.id); 30 | 31 | switch (request.what) { 32 | case 'blockFlash': 33 | response = { 34 | result: pageStore && pageStore.getNetFilteringSwitch() && bb.settings.blockBearEnabled && bb.settings.flashbearEnabled 35 | }; 36 | break; 37 | case 'incrementFlashCount': 38 | blockedCounts.flashBlocked++ 39 | µb.updateToolbarIcon(sender.tab.id); 40 | break; 41 | case 'decrementFlashCount': 42 | if (blockedCounts.flashBlocked > 0) { 43 | blockedCounts.flashBlocked--; 44 | µb.updateToolbarIcon(sender.tab.id); 45 | } 46 | break; 47 | case 'blockEmailEnabled': 48 | response = bb.settings.blockEmailEnabled && bb.settings.blockBearEnabled; 49 | break; 50 | case 'pixel-tracking': 51 | blockedCounts.emailBlocked++ 52 | µb.updateToolbarIcon(sender.tab.id); 53 | break; 54 | default: 55 | return vAPI.messaging.UNHANDLED; 56 | } 57 | 58 | callback(response); 59 | }; 60 | 61 | vAPI.messaging.listen('blockbear-contentscript-end.js', onMessage); 62 | 63 | })(); 64 | 65 | /******************************************************************************/ 66 | /******************************************************************************/ 67 | 68 | (function () { 69 | 70 | /******************************************************************************/ 71 | 72 | var µb = µBlock; 73 | let bb = µb.blockbear; 74 | 75 | /******************************************************************************/ 76 | 77 | var onMessage = function (request, sender, callback) { 78 | // Async 79 | switch (request.what) { 80 | default: 81 | break; 82 | } 83 | 84 | // Sync 85 | var response; 86 | 87 | var pageStore; 88 | if (sender && sender.tab) { 89 | pageStore = µb.pageStoreFromTabId(sender.tab.id); 90 | } 91 | let blockedCounts = bb.getBlockedCounts(sender.tab.id); 92 | 93 | switch (request.what) { 94 | case 'blockBrowserFingerprinting': 95 | response = { 96 | blockFingerprinting: pageStore && pageStore.getNetFilteringSwitch() && bb.settings.blockBearEnabled && bb.settings.blockBrowserFingerprintingEnabled, 97 | blockMicrophone: pageStore && pageStore.getNetFilteringSwitch() && bb.settings.blockBearEnabled && bb.settings.blockMicrophoneEnabled, 98 | blockKeyboard: pageStore && pageStore.getNetFilteringSwitch() && bb.settings.blockBearEnabled && bb.settings.blockKeyboardEnabled, 99 | blockMouse: pageStore && pageStore.getNetFilteringSwitch() && bb.settings.blockBearEnabled && bb.settings.blockMouseEnabled, 100 | }; 101 | if (!response.blockFingerprinting && blockedCounts.fingerprintingBlocked > 0) { 102 | blockedCounts.fingerprintingBlocked = 0; 103 | µb.updateToolbarIcon(sender.tab.id); 104 | } 105 | break; 106 | case 'clearFingerprintingCount': 107 | blockedCounts.fingerprintingBlocked = 0; 108 | µb.updateToolbarIcon(sender.tab.id); 109 | break; 110 | case 'incrementFingerprintingCount': 111 | console.log(pageStore.tabHostname + ": " + request.message); 112 | if (request.data) { 113 | console.log(request.data); 114 | } 115 | blockedCounts.fingerprintingBlocked++; 116 | µb.updateToolbarIcon(sender.tab.id); 117 | break; 118 | case 'decrementFingerprintingCount': 119 | if (blockedCounts.fingerprintingBlocked > 0) { 120 | blockedCounts.fingerprintingBlocked--; 121 | µb.updateToolbarIcon(sender.tab.id); 122 | } 123 | break; 124 | 125 | case 'clearKeyboardCount': 126 | blockedCounts.keyboardBlocked = 0; 127 | µb.updateToolbarIcon(sender.tab.id); 128 | break; 129 | case 'incrementKeyboardCount': 130 | console.log(pageStore.tabHostname + ": " + request.message); 131 | if (request.data) { 132 | console.log(request.data); 133 | } 134 | blockedCounts.keyboardBlocked++ 135 | µb.updateToolbarIcon(sender.tab.id); 136 | break; 137 | case 'clearMouseCount': 138 | blockedCounts.mouseBlocked = 0; 139 | µb.updateToolbarIcon(sender.tab.id); 140 | break; 141 | case 'incrementMouseCount': 142 | console.log(pageStore.tabHostname + ": " + request.message); 143 | if (request.data) { 144 | console.log(request.data); 145 | } 146 | blockedCounts.mouseBlocked++; 147 | µb.updateToolbarIcon(sender.tab.id); 148 | break; 149 | case 'clearMicrophoneCount': 150 | blockedCounts.ultrasonicBlocked = 0; 151 | µb.updateToolbarIcon(sender.tab.id); 152 | break; 153 | case 'incrementMicrophoneCount': 154 | console.log(pageStore.tabHostname + ": " + request.message); 155 | if (request.data) { 156 | console.log(request.data); 157 | } 158 | blockedCounts.ultrasonicBlocked++; 159 | µb.updateToolbarIcon(sender.tab.id); 160 | break; 161 | default: 162 | return vAPI.messaging.UNHANDLED; 163 | } 164 | 165 | callback(response); 166 | }; 167 | 168 | vAPI.messaging.listen('blockbear-contentscript-start.js', onMessage); 169 | 170 | })(); 171 | 172 | /******************************************************************************/ 173 | /******************************************************************************/ 174 | 175 | (function () { 176 | 177 | /******************************************************************************/ 178 | 179 | var µb = µBlock; 180 | let bb = µb.blockbear; 181 | 182 | /******************************************************************************/ 183 | 184 | let getPopupData = function (tabId) { 185 | let tabContext = µb.tabContextManager.mustLookup(tabId); 186 | 187 | let data = { 188 | // Info 189 | tabId: tabId, 190 | pageURL: tabContext.normalURL, 191 | pageDomain: tabContext.rootDomain, 192 | 193 | // Toggles 194 | blockBearEnabled: bb.settings.blockBearEnabled, 195 | netFilteringSwitch: false, 196 | blockAdsEnabled: bb.settings.blockAdsEnabled, 197 | flashbearEnabled: bb.settings.flashbearEnabled, 198 | blockBrowserFingerprintingEnabled: bb.settings.blockBrowserFingerprintingEnabled, 199 | blockMicrophoneEnabled: bb.settings.blockMicrophoneEnabled, 200 | blockKeyboardEnabled: bb.settings.blockKeyboardEnabled, 201 | blockMouseEnabled: bb.settings.blockMouseEnabled, 202 | blockEmailEnabled: bb.settings.blockEmailEnabled, 203 | blockSocialEnabled: bb.settings.blockSocialEnabled, 204 | blockPrivacyEnabled: bb.settings.blockPrivacyEnabled, 205 | blockMalwareEnabled: bb.settings.blockMalwareEnabled, 206 | showPopupDetails: bb.settings.showPopupDetails, 207 | 208 | // Counts 209 | pageBlockedRequestCount: 0, 210 | pageBlockedAdsCount: 0, 211 | pageBlockedFlashCount: 0, 212 | pageBlockedFingerprintingCount: 0, 213 | pageBlockedEmailCount: 0, 214 | pageBlockedKeyboardCount: 0, 215 | pageBlockedMouseCount: 0, 216 | pageBlockedMicrophoneCount: 0, 217 | pageBlockedSocialCount: 0, 218 | pageBlockedPrivacyCount: 0, 219 | pageBlockedMalwareCount: 0 220 | } 221 | 222 | let pageStore = µb.pageStoreFromTabId(tabId); 223 | let blockCounts = bb.getBlockedCounts(tabId); 224 | if ( pageStore ) { 225 | data.netFilteringSwitch = pageStore.getNetFilteringSwitch(); 226 | data.pageBlockedRequestCount = pageStore.perLoadBlockedRequestCount; 227 | data.pageBlockedAdsCount = blockCounts.adsBlocked 228 | data.pageBlockedFlashCount = blockCounts.flashBlocked 229 | data.pageBlockedFingerprintingCount = blockCounts.fingerprintingBlocked 230 | data.pageBlockedEmailCount = blockCounts.emailBlocked 231 | data.pageBlockedMicrophoneCount = blockCounts.ultrasonicBlocked 232 | data.pageBlockedSocialCount = blockCounts.socialBlocked 233 | data.pageBlockedPrivacyCount = blockCounts.privacyBlocked 234 | data.pageBlockedMalwareCount = blockCounts.malwareBlocked 235 | } 236 | 237 | return data 238 | } 239 | 240 | let getActiveTab = function (callback) { 241 | vAPI.tabs.get(null, function (tab) { 242 | var tabId = ''; 243 | if (tab) { 244 | tabId = tab.id; 245 | } 246 | callback(tabId); 247 | }) 248 | } 249 | 250 | var onMessage = function (request, sender, callback) { 251 | 252 | if (request.what === 'getPopupData') { 253 | getActiveTab(function (tabId) { 254 | callback(getPopupData(tabId)); 255 | }) 256 | return; 257 | } 258 | 259 | var response; 260 | 261 | switch ( request.what ) { 262 | case 'toggleBlockBear': 263 | bb.settings.blockBearEnabled = !bb.settings.blockBearEnabled; 264 | bb.updateFilters(); 265 | break; 266 | case 'toggleDomainWhitelist': 267 | let pageStore = µb.pageStoreFromTabId(request.tabId); 268 | if ( pageStore ) { 269 | pageStore.toggleNetFilteringSwitch(request.url, request.scope, request.state); 270 | } 271 | break; 272 | case 'toggleBlockAds': 273 | bb.settings.blockAdsEnabled = !bb.settings.blockAdsEnabled; 274 | bb.updateFilters(); 275 | break; 276 | case 'toggleFlash': 277 | bb.settings.flashbearEnabled = !bb.settings.flashbearEnabled; 278 | break; 279 | case 'toggleBrowserFingerprinting': 280 | bb.settings.blockBrowserFingerprintingEnabled = !bb.settings.blockBrowserFingerprintingEnabled; 281 | break; 282 | case 'toggleBlockEmail': 283 | bb.settings.blockEmailEnabled = !bb.settings.blockEmailEnabled; 284 | break; 285 | case 'toggleBlockKeyboard': 286 | bb.settings.blockKeyboardEnabled = !bb.settings.blockKeyboardEnabled; 287 | break; 288 | case 'toggleBlockMouse': 289 | bb.settings.blockMouseEnabled = !bb.settings.blockMouseEnabled; 290 | break; 291 | case 'toggleBlockMicrophone': 292 | bb.settings.blockMicrophoneEnabled = !bb.settings.blockMicrophoneEnabled; 293 | break; 294 | case 'toggleSocial': 295 | bb.settings.blockSocialEnabled = !bb.settings.blockSocialEnabled; 296 | bb.updateFilters(); 297 | break; 298 | case 'togglePrivacy': 299 | bb.settings.blockPrivacyEnabled = !bb.settings.blockPrivacyEnabled; 300 | bb.updateFilters(); 301 | break; 302 | case 'toggleMalware': 303 | bb.settings.blockMalwareEnabled = !bb.settings.blockMalwareEnabled; 304 | bb.updateFilters(); 305 | break; 306 | case 'toggleShowPopupDetails': 307 | bb.settings.showPopupDetails = !bb.settings.showPopupDetails; 308 | break; 309 | default: 310 | return vAPI.messaging.UNHANDLED; 311 | } 312 | bb.saveSettingsToStorage(); 313 | 314 | callback(response); 315 | } 316 | 317 | vAPI.messaging.listen('blockbearPopup', onMessage); 318 | 319 | })(); 320 | 321 | /******************************************************************************/ 322 | /******************************************************************************/ 323 | 324 | (function () { 325 | 326 | /******************************************************************************/ 327 | 328 | var µb = µBlock; 329 | let bb = µb.blockbear; 330 | 331 | /******************************************************************************/ 332 | 333 | let onMessage = function (request, sender, callback) { 334 | 335 | if (request.what === "getSettingsData") { 336 | let settingsData = Object.assign({}, bb.settings); 337 | settingsData.blockWebRTCEnabled = µb.userSettings.webrtcIPAddressHidden; 338 | callback(settingsData); 339 | return; 340 | } 341 | 342 | var response; 343 | 344 | switch ( request.what ) { 345 | case 'toggleBlockAds': 346 | bb.settings.blockAdsEnabled = !bb.settings.blockAdsEnabled; 347 | bb.updateFilters(); 348 | break; 349 | case 'toggleFlash': 350 | bb.settings.flashbearEnabled = !bb.settings.flashbearEnabled; 351 | break; 352 | case 'toggleBrowserFingerprinting': 353 | bb.settings.blockBrowserFingerprintingEnabled = !bb.settings.blockBrowserFingerprintingEnabled; 354 | break; 355 | case 'toggleBlockMicrophone': 356 | bb.settings.blockMicrophoneEnabled = !bb.settings.blockMicrophoneEnabled; 357 | break; 358 | case 'toggleBlockKeyboard': 359 | bb.settings.blockKeyboardEnabled = !bb.settings.blockKeyboardEnabled; 360 | break; 361 | case 'toggleBlockMouse': 362 | bb.settings.blockMouseEnabled = !bb.settings.blockMouseEnabled; 363 | break; 364 | case 'toggleBlockEmail': 365 | bb.settings.blockEmailEnabled = !bb.settings.blockEmailEnabled; 366 | break; 367 | case 'toggleBlockWebRTC': 368 | µb.changeUserSettings('webrtcIPAddressHidden', !µb.userSettings.webrtcIPAddressHidden); 369 | break; 370 | case 'toggleBlockerBadgeAnimation': 371 | bb.settings.blockerBadgeAnimationEnabled = !bb.settings.blockerBadgeAnimationEnabled; 372 | break; 373 | case 'toggleSocial': 374 | bb.settings.blockSocialEnabled = !bb.settings.blockSocialEnabled; 375 | bb.updateFilters(); 376 | break; 377 | case 'togglePrivacy': 378 | bb.settings.blockPrivacyEnabled = !bb.settings.blockPrivacyEnabled; 379 | bb.updateFilters(); 380 | break; 381 | case 'toggleMalware': 382 | bb.settings.blockMalwareEnabled = !bb.settings.blockMalwareEnabled; 383 | bb.updateFilters(); 384 | break; 385 | default: 386 | return vAPI.messaging.UNHANDLED; 387 | } 388 | 389 | callback(response) 390 | } 391 | 392 | vAPI.messaging.listen('blockbearSettings', onMessage); 393 | 394 | })(); 395 | -------------------------------------------------------------------------------- /tunnelbear/src/css/common.css: -------------------------------------------------------------------------------- 1 | a,article,aside,body,caption,dd,dfn,div,div.hgroup,dl,dt,em,embed,fieldset,footer,form,h1,h2,h3,h4,h5,h6,header,html,iframe,img,label,legend,li,nav,object,ol,p,section,small,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,ul { 2 | margin: 0; 3 | padding: 0; 4 | border: 0; 5 | font: inherit; 6 | vertical-align: baseline; 7 | } 8 | 9 | strong { 10 | font-weight: 700; 11 | } 12 | 13 | article,aside,div.hgroup,footer,header,nav,section { 14 | display: block; 15 | } 16 | 17 | body { 18 | line-height: 1; 19 | } 20 | 21 | ol { 22 | list-style: decimal; 23 | } 24 | 25 | ul { 26 | list-style: none; 27 | } 28 | 29 | table { 30 | border-collapse: collapse; 31 | border-spacing: 0; 32 | } 33 | 34 | :active,:focus { 35 | outline: 0; 36 | } 37 | 38 | .android:active,.android:focus { 39 | -webkit-tap-highlight-color: rgba(255,255,255,0); 40 | } 41 | 42 | .android select { 43 | -webkit-tap-highlight-color: transparent; 44 | } 45 | 46 | textarea { 47 | resize: none; 48 | } 49 | 50 | .sliding-panel { 51 | min-height: 100%; 52 | width : 100%; 53 | transform:translateX(258px); 54 | position: absolute; 55 | top: 0px; 56 | background-color: #fcfaf7; 57 | } 58 | 59 | #settings-gear { 60 | margin-left: 208px; 61 | margin-top: -18px; 62 | cursor: pointer; 63 | } 64 | .img-top-settings { 65 | width: 15px; 66 | height: 15px; 67 | } 68 | #shortcuts-div { 69 | transform:translateX(516px); 70 | } 71 | 72 | @font-face { 73 | font-family: 'Rokkitt-Light'; 74 | src: url('fonts/Rokkitt-Light.eot'); 75 | src: url('fonts/Rokkitt-Light.eot?#iefix') format('embedded-opentype'), 76 | url('fonts/Rokkitt-Light.woff') format('woff'), 77 | url('fonts/Rokkitt-Light.ttf') format('truetype'), 78 | url('fonts/Rokkitt-Light.svg#Rokkitt-Light') format('svg'); 79 | } 80 | 81 | @font-face { 82 | font-family: 'Rokkitt'; 83 | src: url('fonts/Rokkitt-Regular.eot'); 84 | src: url('fonts/Rokkitt-Regular.eot?#iefix') format('embedded-opentype'), 85 | url('fonts/Rokkitt-Regular.woff') format('woff'), 86 | url('fonts/Rokkitt-Regular.ttf') format('truetype'), 87 | url('fonts/Rokkitt-Regular.svg#Rokkitt') format('svg'); 88 | } 89 | 90 | @font-face { 91 | font-family: 'Rokkitt-Bold'; 92 | src: url('fonts/Rokkitt-Bold.eot'); 93 | src: url('fonts/Rokkitt-Bold.eot?#iefix') format('embedded-opentype'), 94 | url('fonts/Rokkitt-Bold.woff') format('woff'), 95 | url('fonts/Rokkitt-Bold.ttf') format('truetype'), 96 | url('fonts/Rokkitt-Bold.svg#Rokkitt-Bold') format('svg'); 97 | } 98 | 99 | @font-face { 100 | font-family: OpenSans; 101 | font-style: normal; 102 | font-weight: 400; 103 | src: url('fonts/OpenSans-Regular.ttf'); 104 | } 105 | 106 | @font-face { 107 | font-family: OpenSans; 108 | font-style: normal; 109 | font-weight: 600; 110 | src: url('fonts/OpenSans-Semibold.ttf'); 111 | } 112 | 113 | @font-face { 114 | font-family: OpenSans; 115 | font-style: normal; 116 | font-weight: 700; 117 | src: url('fonts/OpenSans-Bold.ttf'); 118 | } 119 | 120 | /* General setup */ 121 | body { 122 | background-color: white; 123 | overflow: hidden; /* prevent from scrolling through plugin */ 124 | margin:0px !important; 125 | 126 | font: 15px Helvetica, Arial, sans-serif; 127 | color: #55534e; 128 | 129 | -webkit-font-smoothing: antialiased; 130 | -webkit-touch-callout: none; 131 | -webkit-user-select: none; 132 | -khtml-user-select: none; 133 | -moz-user-select: none; 134 | -ms-user-select: none; 135 | -o-user-select: none; 136 | user-select: none; 137 | overflow-x: hidden; 138 | overflow-y: hidden; 139 | } 140 | 141 | h1 { 142 | cursor: default; 143 | font-weight: bold; 144 | padding: 12px 0; 145 | text-align: center; 146 | } 147 | 148 | a { 149 | text-decoration: none; 150 | } 151 | 152 | .loaded { 153 | width: 258px; 154 | animation-delay: 0.2s; 155 | -webkit-animation: fadein 1s forwards; /* Safari, Chrome and Opera > 12.1 */ 156 | -moz-animation: fadein 1s forwards; /* Firefox < 16 */ 157 | animation: fadein 1s forwards; 158 | } 159 | 160 | @keyframes fadein { 161 | to { opacity: 1; } 162 | } 163 | 164 | /* Firefox < 16 */ 165 | @-moz-keyframes fadein { 166 | to { opacity: 1; } 167 | } 168 | 169 | /* Safari, Chrome and Opera > 12.1 */ 170 | @-webkit-keyframes fadein { 171 | to { opacity: 1; } 172 | } 173 | 174 | .container .settings-header .title-block { 175 | padding-top: 14px; 176 | } 177 | 178 | .container .settings-header { 179 | height: 44px; 180 | text-align: center; 181 | } 182 | .container .navigation-button { 183 | padding-top:14px; 184 | padding-left: 15px; 185 | padding-right: 15px; 186 | position: absolute; 187 | left: 0%; 188 | cursor: pointer; 189 | } 190 | 191 | .container button:focus { 192 | outline:0; 193 | } 194 | 195 | .container .settings-title { 196 | font-weight: bold !important; 197 | } 198 | 199 | .container { 200 | position: relative; 201 | opacity: 0; 202 | width: 100%; 203 | } 204 | 205 | .container button{ 206 | background-color: transparent; 207 | border: none; 208 | color: #e58d2f; 209 | font-family: Helvetica; 210 | font-size: 15px; 211 | font-weight: normal; 212 | } 213 | 214 | .container span{ 215 | cursor: default; 216 | font-family: OpenSans; 217 | font-weight: normal; 218 | color: #55534e; 219 | text-align: left; 220 | letter-spacing: -0.6px; 221 | font-size: 15px; 222 | } 223 | 224 | .container span.disabled { 225 | color: #bdbbb6; 226 | } 227 | 228 | .container .medium-row{ 229 | height: 44px; 230 | } 231 | 232 | .alernate-row-color { 233 | /* Uncomment this for orangy color background-color: #faf1e6; */ 234 | } 235 | 236 | .left-padding { 237 | padding-left: 10px; 238 | } 239 | 240 | .section-border { 241 | border-width: 1px; 242 | border-top-color: #e5e2dc; 243 | border-top-style: solid; 244 | } 245 | 246 | /* General Setup*/ 247 | .default-cursor { 248 | cursor: default !important; 249 | } 250 | 251 | /* General table things */ 252 | 253 | .table { 254 | width: 100%; 255 | display:table; 256 | border-collapse: collapse; 257 | } 258 | .table > .caption{ 259 | display:table-caption; 260 | vertical-align: middle; 261 | text-align: center; 262 | } 263 | 264 | .table-row { 265 | display:table-row; 266 | } 267 | 268 | .table-cell { 269 | vertical-align: middle; 270 | display:table-cell; 271 | } 272 | 273 | .table-cell.colspan > div { 274 | width: 1px; 275 | } 276 | 277 | .table-cell.colspan > div > div { 278 | position: relative; 279 | overflow: hidden; 280 | } 281 | 282 | .container .button { 283 | padding:8px; 284 | text-align: center; 285 | color: #E58D2F; 286 | cursor: pointer; 287 | border-color: #e5e2dc; 288 | border-style: solid; 289 | border-width: 1px; 290 | } 291 | .container .button:hover { 292 | background-color: #f8f6ef; 293 | } 294 | 295 | .button-left { 296 | margin-left:15%; 297 | width: 25%; 298 | float:left; 299 | } 300 | .button-right { 301 | width: 25%; 302 | margin-left: 54%; 303 | } 304 | 305 | /* End general table things */ 306 | 307 | /* Popup Header */ 308 | .container .img-top-logo { 309 | width: 84px; 310 | } 311 | /* End of Popup Header */ 312 | 313 | /* Connection component */ 314 | 315 | /* Status label */ 316 | .container .status-label { 317 | /* In case a margin is needed, not the case now - don't change the width of the cell, edit the margin instead 318 | margin-left: -8px;*/ 319 | padding-top: 1px; 320 | overflow: hidden; 321 | text-overflow: ellipsis; 322 | width: 170px; 323 | } 324 | /* Status label end */ 325 | 326 | /* settings-category label */ 327 | .container .settings-category-label span { 328 | font-weight: bold; 329 | } 330 | /* settings-category label end */ 331 | 332 | .container .status-cell { 333 | width: 175px; 334 | } 335 | 336 | .container .status-cell { 337 | padding-left: 10px; 338 | } 339 | 340 | .div-status-icon { 341 | margin-top: 2px; 342 | margin-left: -2px; 343 | } 344 | /* Icon */ 345 | 346 | .container .img-status { 347 | /* padding-top: 2px; */ 348 | width:13px; 349 | height:13px; 350 | } 351 | 352 | .arrow.open { 353 | background: url('../img/arrow_open2x.png'); 354 | background-size: 18px 17px; 355 | background-repeat: no-repeat; 356 | height: 17px; 357 | width: 19px; 358 | float: left; 359 | margin: 1px 0 0 15px; 360 | } 361 | 362 | .arrow.close { 363 | background: url('../img/arrow_close2x.png'); 364 | background-size: 18px 17px; 365 | background-repeat: no-repeat; 366 | height: 17px; 367 | width: 19px; 368 | float: left; 369 | margin: 1px 0 0 15px; 370 | } 371 | 372 | /* End of Status Icon */ 373 | 374 | /* ProgressBar */ 375 | 376 | .progress-bar { 377 | height: 5px!important; 378 | background: #e5e2dc; 379 | } 380 | .table-row.progress-bar .bar { 381 | width: 258px; 382 | } 383 | 384 | .progress-bar .bar, 385 | .progress-bar .bar span { 386 | height: 5px; 387 | } 388 | 389 | .progress-bar .bar span { 390 | display: block; 391 | width: 0%; 392 | -webkit-transition: width 1s ease-in-out; 393 | -moz-transition: width 1s ease-in-out; 394 | -o-transition: width 1s ease-in-out; 395 | transition: width 1s ease-in-out; 396 | } 397 | 398 | .progress-bar .bar.blocks > span { 399 | background: #72c4d2; 400 | } 401 | 402 | .progress-bar .bar.privacy > span { 403 | background: #a5ce4e; 404 | } 405 | 406 | .progress-bar .bar.fingerprinting > span { 407 | background: #b979fb; 408 | } 409 | 410 | .progress-bar .bar.email > span { 411 | background: #6473e5; 412 | } 413 | 414 | .progress-bar .bar.keyboard > span { 415 | background: #de7045; 416 | } 417 | 418 | .progress-bar .bar.mouse > span { 419 | background: #c2b523; 420 | } 421 | 422 | .progress-bar .bar.microphone > span { 423 | background: #5fe197; 424 | } 425 | 426 | .progress-bar .bar.social > span { 427 | background: #70db5c; 428 | } 429 | 430 | .progress-bar .bar.ads > span { 431 | background: #65ade9; 432 | } 433 | 434 | .progress-bar .bar.flash > span { 435 | background: #e9658d; 436 | } 437 | 438 | .progress-bar .bar.malware > span { 439 | background: #ebaf38; 440 | } 441 | 442 | /* End of ProgressBar */ 443 | 444 | /* Toggle switch */ 445 | 446 | .toggle-background { 447 | cursor: pointer; 448 | height: 29px; 449 | width: 60px; 450 | border-radius: 15px; 451 | background: #685538; 452 | transition: .25s ease-in-out; 453 | -webkit-transition: .25s ease-in-out; 454 | } 455 | 456 | .toggle-background.enabled { 457 | background: #dcb150; 458 | } 459 | 460 | .toggle-knob { 461 | height: 25px; 462 | width: 25px; 463 | border-radius: 15px; 464 | background: white; 465 | position: absolute; 466 | margin-top: 2px; 467 | margin-left: 2px; 468 | transition: .25s ease-in-out; 469 | -webkit-transition: .25s ease-in-out; 470 | } 471 | 472 | .enabled > .toggle-knob { 473 | margin-left: 33px; 474 | } 475 | 476 | .toggle-text { 477 | color: #faf9f7; 478 | font-size: 11px; 479 | position: absolute; 480 | margin-top: 9px; 481 | margin-left: 31px; 482 | } 483 | 484 | body.firefox .toggle-text { 485 | margin-top: 10px; 486 | } 487 | 488 | .enabled > .toggle-text { 489 | margin-left: 10px; 490 | } 491 | 492 | .toggle-background.mini { 493 | height: 12px; 494 | width: 20px; 495 | margin-left: 37px; 496 | margin-top: 3px; 497 | } 498 | 499 | .toggle-knob.mini { 500 | height: 10px; 501 | width: 10px; 502 | margin-top: 1px; 503 | margin-left: 1px; 504 | } 505 | 506 | .enabled > .toggle-knob.mini { 507 | margin-left: 9px; 508 | } 509 | 510 | /* End of Toggle switch */ 511 | 512 | /* End of connection component */ 513 | 514 | /* Twitter */ 515 | 516 | .container .promo-banner { 517 | height: 92px; 518 | background-color: #ffffff; 519 | } 520 | 521 | #twitter-promo-graphic { 522 | background: url(../img/graphic_twitter.png); 523 | background-size: 81px 75px; 524 | content: ""; 525 | display: block; 526 | height: 75px; 527 | position: absolute; 528 | right: 25px; 529 | margin-top: 9px; 530 | width: 81px; 531 | } 532 | 533 | #twitter-tweet-text { 534 | width: 61px; 535 | height: 17px; 536 | font-family: OpenSans; 537 | font-size: 12px; 538 | letter-spacing: -0.5px; 539 | text-align: center; 540 | color: #faf9f7; 541 | padding: 4px 8px 4px 8px; 542 | } 543 | 544 | #twitter-tweet { 545 | cursor: pointer; 546 | width: 76.4px; 547 | height: 25px; 548 | border-radius: 2px; 549 | background-color: #55534e; 550 | margin-left: 40px; 551 | margin-top: 6px; 552 | } 553 | 554 | .banner-text { 555 | width: 136.9px; 556 | height: 34px; 557 | font-family: OpenSans; 558 | font-size: 12px; 559 | letter-spacing: -0.5px; 560 | text-align: center; 561 | color: #afa194; 562 | margin-top: 14px; 563 | margin-left: 10px; 564 | cursor: default; 565 | } 566 | 567 | .banner-close { 568 | background: url(../img/twitter_close.png); 569 | background-size: 7.9px 7.9px; 570 | height: 7.9px; 571 | width: 7.9px; 572 | position: absolute; 573 | margin-top: 11.1px; 574 | right: 11.1px; 575 | cursor: pointer; 576 | } 577 | 578 | /* End Twitter */ 579 | 580 | /* TB4C */ 581 | 582 | #tb4c-promo-graphic { 583 | background: url(../img/graphic_tb4c.png); 584 | background-size: 68px 84px; 585 | content: ""; 586 | display: block; 587 | height: 84px; 588 | position: absolute; 589 | right: 20px; 590 | margin-top: 7px; 591 | width: 68px; 592 | } 593 | 594 | #tb4c-banner-text { 595 | width: 144.9px; 596 | height: 34px; 597 | font-family: OpenSans; 598 | font-size: 12px; 599 | letter-spacing: -0.5px; 600 | text-align: center; 601 | color: #afa194; 602 | margin-top: 8px; 603 | margin-left: 6px; 604 | cursor: default; 605 | padding: 4px 8px 4px 8px; 606 | } 607 | 608 | #tb4c-store { 609 | cursor: pointer; 610 | width: 127px; 611 | height: 25px; 612 | border-radius: 2px; 613 | background-color: #55534e; 614 | margin-left: 25px; 615 | margin-top: 4px; 616 | } 617 | 618 | #tb4c-text { 619 | width: 110px; 620 | height: 17px; 621 | font-family: OpenSans; 622 | font-size: 12px; 623 | letter-spacing: -0.5px; 624 | text-align: center; 625 | color: #faf9f7; 626 | padding: 4px 8px 4px 8px; 627 | } 628 | 629 | /* End TB4C */ 630 | 631 | /* Chrome Store review */ 632 | 633 | #review-banner-text { 634 | font-family: OpenSans; 635 | font-size: 12px; 636 | letter-spacing: -0.5px; 637 | text-align: center; 638 | color: #afa194; 639 | margin-top: 14px; 640 | margin-left: 12px; 641 | cursor: default; 642 | } 643 | 644 | #review-promo-graphic { 645 | background: url(../img/graphic_blocky.png); 646 | background-size: 68px 85px; 647 | content: ""; 648 | display: block; 649 | width: 68px; 650 | height: 85px; 651 | position: absolute; 652 | right: 11px; 653 | margin-top: 7px; 654 | } 655 | 656 | .review { 657 | cursor: pointer; 658 | width: 49px; 659 | height: 25px; 660 | border-radius: 2px; 661 | background-color: #55534e; 662 | margin-left: 32px; 663 | margin-top: 8px; 664 | display: inline-block; 665 | } 666 | 667 | .review-text { 668 | height: 17px; 669 | font-family: OpenSans; 670 | font-size: 12px; 671 | letter-spacing: -0.5px; 672 | text-align: center; 673 | color: #faf9f7; 674 | padding-top: 3px; 675 | } 676 | 677 | /* End Chrome Store review */ 678 | 679 | /* Tooltip */ 680 | 681 | .tooltip { 682 | display: inline-block; 683 | position: relative; 684 | } 685 | 686 | .tooltip .tooltiptext { 687 | cursor: pointer; 688 | visibility: hidden; 689 | width: 70px; 690 | height: 21px; 691 | font-size: 14px; 692 | background-color: #575550; 693 | color: #fff; 694 | text-align: center; 695 | border-radius: 6px; 696 | padding: 5px 0; 697 | position: absolute; 698 | z-index: 1; 699 | bottom: 150%; 700 | left: 50%; 701 | margin-left: -35px; 702 | opacity: 0; 703 | transition: visibility 0.5s, opacity 0.5s ease-in-out; 704 | } 705 | 706 | .tooltip .tooltiptext::after { 707 | content: " "; 708 | position: absolute; 709 | top: 100%; 710 | left: 50%; 711 | margin-left: -5px; 712 | border-width: 5px; 713 | border-style: solid; 714 | border-color: #575550 transparent transparent transparent; 715 | } 716 | 717 | .tooltip:hover .tooltiptext { 718 | visibility: visible; 719 | opacity: 1; 720 | } 721 | 722 | /* End of Tooltip */ 723 | -------------------------------------------------------------------------------- /tunnelbear/resources/fonts/Rokkitt-Light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 12 | 13 | 14 | 16 | 19 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 35 | 36 | 38 | 40 | 41 | 43 | 45 | 46 | 49 | 51 | 52 | 53 | 54 | 55 | 56 | 58 | 61 | 62 | 64 | 66 | 67 | 68 | 69 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 80 | 81 | 84 | 86 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 103 | 105 | 106 | 108 | 110 | 111 | 113 | 114 | 115 | 116 | 117 | 118 | 120 | 121 | 122 | 124 | 126 | 127 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 138 | 139 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /tunnelbear/resources/fonts/Rokkitt-Bold.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 12 | 13 | 14 | 16 | 19 | 22 | 25 | 26 | 27 | 28 | 30 | 31 | 33 | 34 | 35 | 36 | 38 | 39 | 41 | 44 | 45 | 47 | 50 | 51 | 54 | 57 | 58 | 59 | 60 | 61 | 62 | 64 | 68 | 69 | 71 | 73 | 75 | 76 | 77 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 88 | 90 | 93 | 95 | 98 | 99 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 115 | 117 | 119 | 121 | 123 | 125 | 128 | 129 | 131 | 133 | 134 | 135 | 138 | 140 | 142 | 144 | 146 | 148 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 159 | 160 | 162 | 164 | 165 | 166 | 167 | --------------------------------------------------------------------------------