├── .gitignore ├── source ├── assets │ ├── icon_off_48.png │ ├── icon_on_128.png │ ├── icon_on_32.png │ ├── icon_on_48.png │ ├── montserrat-v12-latin-regular.woff │ ├── montserrat-v12-latin-regular.woff2 │ ├── icon_on.svg │ └── icon_off.svg ├── manifest.json ├── options │ ├── options.html │ ├── options.css │ └── options.js ├── popup │ ├── popup.js │ ├── popup.html │ └── popup.css └── background.js ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | # build files 2 | 3 | *.pem 4 | *.crx 5 | *.zip 6 | -------------------------------------------------------------------------------- /source/assets/icon_off_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ecoify/chrome-extension/HEAD/source/assets/icon_off_48.png -------------------------------------------------------------------------------- /source/assets/icon_on_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ecoify/chrome-extension/HEAD/source/assets/icon_on_128.png -------------------------------------------------------------------------------- /source/assets/icon_on_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ecoify/chrome-extension/HEAD/source/assets/icon_on_32.png -------------------------------------------------------------------------------- /source/assets/icon_on_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ecoify/chrome-extension/HEAD/source/assets/icon_on_48.png -------------------------------------------------------------------------------- /source/assets/montserrat-v12-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ecoify/chrome-extension/HEAD/source/assets/montserrat-v12-latin-regular.woff -------------------------------------------------------------------------------- /source/assets/montserrat-v12-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ecoify/chrome-extension/HEAD/source/assets/montserrat-v12-latin-regular.woff2 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | What is Ecoify all about? 2 | ========================= 3 | 4 | Every time we ask google to search something for us, requests are sent 5 | back and forth, Internet Service Providers need power to keep the 6 | internet running and google needs power for their servers. 7 | 8 | Careful estimates believe that each google search amounts to at least 9 | 0.4 Wh, which in turn amounts to no less than 0.2 g of CO2. 10 | 11 | We want to cut down your own carbon footprint by preventing unneccessary 12 | google searches: 13 | 14 | Every time you enter the name of your favourite website and the browser 15 | triggers a google search, we intercept it and instead open the page 16 | directly for you - while also saving your time and reducing your CO2 17 | emissions! 18 | -------------------------------------------------------------------------------- /source/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "ecoify", 3 | "manifest_version": 2, 4 | "name": "Ecoify Extension", 5 | "description": "This extension will eco-ify your browsing behaviour.", 6 | "version": "2.0", 7 | "icons": { 8 | "32": "assets/icon_on_32.png", 9 | "48": "assets/icon_on_48.png", 10 | "128": "assets/icon_on_128.png" 11 | }, 12 | "browser_action": { 13 | "default_icon": "assets/icon_on_48.png", 14 | "default_popup": "popup/popup.html" 15 | }, 16 | "background": { 17 | "scripts": [ 18 | "background.js" 19 | ] 20 | }, 21 | "options_ui": { 22 | "page": "options/options.html", 23 | "open_in_tab": false 24 | }, 25 | "permissions": [ 26 | "activeTab", 27 | "webRequest", 28 | "storage", 29 | "unlimitedStorage", 30 | "webRequestBlocking", 31 | "*://*.google.com/*", 32 | "*://*.google.de/*", 33 | "https://5tepzfsmxg.execute-api.eu-central-1.amazonaws.com/*" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /source/options/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ecoify Options 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 19 | 20 | 21 |
22 |

23 | Edit redirects: 24 |

25 | 26 |
27 |
28 | 29 | 30 |
31 |
32 | 33 | 34 |
35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 ecoify 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /source/options/options.css: -------------------------------------------------------------------------------- 1 | /* montserrat-regular - latin */ 2 | @font-face { 3 | font-family: 'Montserrat'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: local('Montserrat Regular'), local('Montserrat-Regular'), 7 | url('../assets/montserrat-v12-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ 8 | url('../assets/montserrat-v12-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ 9 | } 10 | 11 | /* Global */ 12 | 13 | body { 14 | font-family: Montserrat; 15 | padding: 0; 16 | margin: 0; 17 | } 18 | 19 | .content { 20 | margin-top: 0em; 21 | margin-left: 2em; 22 | margin-right: 2em; 23 | margin-bottom: 2em; 24 | 25 | text-align: center; 26 | } 27 | 28 | 29 | /* Redirects */ 30 | 31 | .redirects .label { 32 | font-size: 2em; 33 | 34 | text-align: left; 35 | } 36 | 37 | #redirects-text { 38 | width: 30em; 39 | height: 20em; 40 | 41 | overflow: scroll; 42 | resize: none; 43 | outline: none; 44 | white-space: pre; 45 | 46 | font-size: 1.2em; 47 | text-align: left; 48 | } 49 | 50 | /* Save */ 51 | 52 | #save { 53 | padding: 0.5em 1em; 54 | font-size: 2em; 55 | } 56 | -------------------------------------------------------------------------------- /source/options/options.js: -------------------------------------------------------------------------------- 1 | // background page 2 | bgPage = chrome.extension.getBackgroundPage(); 3 | 4 | // Saves options to chrome.storage 5 | function save_options() { 6 | // redirects 7 | let parse_json_error = false; 8 | let newRedirects = {}; 9 | try { 10 | newRedirects = JSON.parse(document.getElementById('redirects-text').value); 11 | } catch(e) { 12 | //console.log("Error parsing JSON: ", e); 13 | parse_json_error = true; 14 | } 15 | if (!parse_json_error) { 16 | bgPage.setRedirects(newRedirects); 17 | } 18 | 19 | // stats 20 | const stats_consent = document.getElementById('stats-checkbox').checked; 21 | bgPage.setStatsConsent(stats_consent); 22 | 23 | const status = document.getElementById('status'); 24 | if (parse_json_error) { 25 | status.style.color = 'red'; 26 | status.textContent = 'Error parsing JSON. NOT SAVED! Check your JSON.'; 27 | } else { 28 | status.style.color = 'green'; 29 | status.textContent = 'Options saved.'; 30 | setTimeout(function() { 31 | status.textContent = ''; 32 | window.close(); 33 | }, 1500); 34 | } 35 | } 36 | 37 | // loads options from chrome.storage 38 | function restore_options() { 39 | // redirects 40 | document.getElementById('redirects-text').value = 41 | JSON.stringify(bgPage.getRedirects(), null, " "); 42 | document.getElementById('stats-checkbox').checked = bgPage.getStatsConsent(); 43 | } 44 | 45 | // init 46 | document.addEventListener('DOMContentLoaded', function() { 47 | document.getElementById('save').addEventListener('click', save_options); 48 | restore_options(); 49 | }); 50 | -------------------------------------------------------------------------------- /source/popup/popup.js: -------------------------------------------------------------------------------- 1 | // popup opened 2 | document.addEventListener('DOMContentLoaded', function() { 3 | // background page 4 | var bgPage = chrome.extension.getBackgroundPage(); 5 | 6 | // init share buttons 7 | bgPage.readCounter().then((counter) => { 8 | var text = "I saved "+encodeURIComponent(countToCarbon(counter))+" CO2 using Ecoify for Chrome. Join now!"; 9 | document.getElementById('share_twitter').href = "https://twitter.com/intent/tweet/?text="+text+"&url=https%3A%2F%2Fecoify.org%2F"; 10 | }); 11 | 12 | // options page 13 | document.getElementById('options_link').addEventListener('click', function() { 14 | if (chrome.runtime.openOptionsPage) { 15 | chrome.runtime.openOptionsPage(); 16 | } else { 17 | window.open(chrome.runtime.getURL('options/options.html')); 18 | } 19 | }); 20 | 21 | // toggle 22 | var toggle = document.getElementById('toggle'); 23 | bgPage.readToggle().then((new_toggle) => { 24 | toggle.checked = new_toggle; 25 | updateToggle(toggle.checked); 26 | }); 27 | toggle.addEventListener('click', function () { 28 | updateToggle(toggle.checked); 29 | }); 30 | 31 | // update carbon grams counter 32 | var carbon_grams = document.getElementById('carbon_grams'); 33 | bgPage.readCounter().then((counter) => { 34 | carbon_grams.innerHTML = countToCarbon(counter); 35 | }); 36 | 37 | }, false); 38 | 39 | function countToCarbon(count) { 40 | new_carbon_grams = count * 0.2; 41 | 42 | var new_carbon_grams_text; 43 | if (new_carbon_grams < 1000) { 44 | new_carbon_grams_text = parseFloat((new_carbon_grams).toFixed(4)) + " g"; 45 | } else if (new_carbon_grams < 1000000) { 46 | new_carbon_grams_text = parseFloat((new_carbon_grams / 1000).toFixed(4)) + " kg"; 47 | } else { 48 | new_carbon_grams_text = parseFloat((new_carbon_grams / 1000000).toFixed(4)) + " t"; 49 | } 50 | 51 | return new_carbon_grams_text; 52 | } 53 | 54 | function updateToggle(toggle) { 55 | var body = document.getElementsByTagName("BODY")[0]; 56 | var bgPage = chrome.extension.getBackgroundPage(); 57 | if (toggle) { 58 | // listener 59 | bgPage.addReqListener(); 60 | // popup background 61 | body.classList.remove('off'); 62 | body.classList.add('on'); 63 | } else { 64 | // listener 65 | bgPage.removeReqListener(); 66 | // popup background 67 | body.classList.remove('on'); 68 | body.classList.add('off'); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /source/popup/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ecoify 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | Ecoify your browsing! 18 |
19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 |
27 | Skip Google: 28 |
29 | 33 |
34 |
35 | 36 |
37 | 0 g CO2 saved! 38 |
39 | 40 |
41 | 42 | 43 | 45 | 46 | 47 | 48 | 50 | 51 |
52 | 53 |
54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /source/popup/popup.css: -------------------------------------------------------------------------------- 1 | /* montserrat-regular - latin */ 2 | @font-face { 3 | font-family: 'Montserrat'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: local('Montserrat Regular'), local('Montserrat-Regular'), 7 | url('../assets/montserrat-v12-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ 8 | url('../assets/montserrat-v12-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ 9 | } 10 | 11 | /* Global */ 12 | 13 | body { 14 | font-family: Montserrat; 15 | padding: 0; 16 | margin: 0; 17 | } 18 | 19 | body.on { 20 | background-color: #9BCB58; 21 | } 22 | 23 | body.off { 24 | background-color: #e44; 25 | } 26 | 27 | 28 | /* Head */ 29 | 30 | .branding { 31 | margin: 0 0 0.7em 0; 32 | width: 100%; 33 | 34 | height: 3em; 35 | line-height: 3em; 36 | 37 | background-color: rgba(0,0,0,0.3); 38 | color: #fff; 39 | font-size: 1.5em; 40 | text-align: center; 41 | } 42 | 43 | .info_link { 44 | position: absolute; 45 | top: 1.4em; 46 | right: 1.4em; 47 | } 48 | 49 | .info_link:focus { 50 | outline:0 !important; 51 | } 52 | 53 | .info_link svg { 54 | width: 1.8em; 55 | height: 1.8em; 56 | } 57 | 58 | #options_link { 59 | position: absolute; 60 | top: 1.4em; 61 | left: 1.4em; 62 | } 63 | 64 | #options_link:focus { 65 | outline:0 !important; 66 | } 67 | 68 | #options_link svg { 69 | width: 1.8em; 70 | height: 1.8em; 71 | } 72 | 73 | /* Content */ 74 | 75 | .content { 76 | width: 25em; 77 | text-align: center; 78 | padding: 0 0 1.5em 0; 79 | margin: 0 1em; 80 | } 81 | 82 | .container { 83 | width: 100%; 84 | } 85 | 86 | /* Toggle */ 87 | 88 | .container.toggle { 89 | display: table; 90 | 91 | font-size: 1.2em; 92 | color: rgba(0, 0, 0, 0.7); 93 | } 94 | 95 | .container.toggle .label { 96 | display: table-cell; 97 | vertical-align: middle; 98 | text-align: right; 99 | width: 54%; 100 | } 101 | 102 | .container.toggle .switch_container { 103 | display: table-cell; 104 | text-align: left; 105 | padding-left: 0.5em; 106 | } 107 | 108 | /* Saved */ 109 | 110 | .container.saved { 111 | margin-top: 1.3em; 112 | } 113 | 114 | .container.saved a { 115 | font-size: 2em; 116 | padding: 0.3em 1em; 117 | 118 | border: 0; 119 | border-radius: 25px; 120 | 121 | background-color: rgba(0, 0, 0, 0.3); 122 | color: #fff; 123 | } 124 | 125 | .container.saved a:hover { 126 | /* color: #aaa; 127 | cursor: pointer; */ 128 | } 129 | 130 | /* Share */ 131 | 132 | .container.social { 133 | margin-top: 1.5em; 134 | } 135 | 136 | .resp-sharing-button__link, 137 | .resp-sharing-button__icon { 138 | display: inline-block 139 | } 140 | 141 | .resp-sharing-button__link { 142 | text-decoration: none; 143 | color: #fff; 144 | margin: 0.5em 145 | } 146 | 147 | .resp-sharing-button { 148 | border-radius: 5px; 149 | transition: 25ms ease-out; 150 | padding: 0.5em 0.75em; 151 | font-family: Helvetica Neue,Helvetica,Arial,sans-serif 152 | } 153 | 154 | .resp-sharing-button__icon svg { 155 | width: 1em; 156 | height: 1em; 157 | margin-right: 0.4em; 158 | vertical-align: top 159 | } 160 | 161 | .resp-sharing-button--small svg { 162 | margin: 0; 163 | vertical-align: middle 164 | } 165 | 166 | /* Non solid icons get a stroke */ 167 | .resp-sharing-button__icon { 168 | stroke: #fff; 169 | fill: none 170 | } 171 | 172 | /* Solid icons get a fill */ 173 | .resp-sharing-button__icon--solid, 174 | .resp-sharing-button__icon--solidcircle { 175 | fill: #fff; 176 | stroke: none 177 | } 178 | 179 | .resp-sharing-button--twitter { 180 | background-color: #55acee 181 | } 182 | 183 | .resp-sharing-button--twitter:hover { 184 | background-color: #2795e9 185 | } 186 | 187 | .resp-sharing-button--facebook { 188 | background-color: #3b5998 189 | } 190 | 191 | .resp-sharing-button--facebook:hover { 192 | background-color: #2d4373 193 | } 194 | 195 | .resp-sharing-button--facebook { 196 | background-color: #3b5998; 197 | border-color: #3b5998; 198 | } 199 | 200 | .resp-sharing-button--facebook:hover, 201 | .resp-sharing-button--facebook:active { 202 | background-color: #2d4373; 203 | border-color: #2d4373; 204 | } 205 | 206 | .resp-sharing-button--twitter { 207 | background-color: #55acee; 208 | border-color: #55acee; 209 | } 210 | 211 | .resp-sharing-button--twitter:hover, 212 | .resp-sharing-button--twitter:active { 213 | background-color: #2795e9; 214 | border-color: #2795e9; 215 | } 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | /* The switch - the box around the slider */ 227 | .switch { 228 | position: relative; 229 | display: inline-block; 230 | width: 60px; 231 | height: 34px; 232 | } 233 | 234 | /* Hide default HTML checkbox */ 235 | .switch input {display:none;} 236 | 237 | /* The slider */ 238 | .slider { 239 | position: absolute; 240 | cursor: pointer; 241 | top: 0; 242 | left: 0; 243 | right: 0; 244 | bottom: 0; 245 | background-color: #ccc; 246 | -webkit-transition: .4s; 247 | transition: .4s; 248 | } 249 | 250 | .slider:before { 251 | position: absolute; 252 | content: ""; 253 | height: 26px; 254 | width: 26px; 255 | left: 4px; 256 | bottom: 4px; 257 | background-color: white; 258 | -webkit-transition: .4s; 259 | transition: .4s; 260 | } 261 | 262 | #toggle:checked + .slider { 263 | background-color: #2196F3; 264 | } 265 | 266 | #toggle:focus + .slider { 267 | box-shadow: 0 0 1px #2196F3; 268 | } 269 | 270 | #toggle:checked + .slider:before { 271 | -webkit-transform: translateX(26px); 272 | -ms-transform: translateX(26px); 273 | transform: translateX(26px); 274 | } 275 | 276 | /* Rounded sliders */ 277 | .slider.round { 278 | border-radius: 34px; 279 | } 280 | 281 | .slider.round:before { 282 | border-radius: 50%; 283 | } 284 | 285 | .settings.editor{ 286 | display:none; 287 | text-align: center; 288 | } 289 | .settings.editor form { 290 | text-align: center; 291 | } 292 | -------------------------------------------------------------------------------- /source/background.js: -------------------------------------------------------------------------------- 1 | // defaults 2 | const redirects_default = { 3 | 'facebook': 'https://www.facebook.com/', 4 | 'fb': 'https://www.facebook.com/', 5 | 'facebook log in': 'https://www.facebook.com/', 6 | 'facebook login': 'https://www.facebook.com/', 7 | 'facebook.com': 'https://www.facebook.com/', 8 | 'facebook.de': 'https://www.facebook.de/', 9 | 'stackoverflow': 'https://stackoverflow.com/', 10 | 'stackoverflow.com': 'https://stackoverflow.com/', 11 | 'netflix': 'https://www.netflix.com/', 12 | 'netflix.com': 'https://www.netflix.com/', 13 | 'youtube': 'https://www.youtube.com/', 14 | 'youtube.com': 'https://www.youtube.com/', 15 | 'youtube.de': 'https://www.youtube.de/', 16 | 'pinterest': 'https://www.pinterest.de/', 17 | 'gmx': 'https://www.gmx.net/', 18 | 'gmx.net': 'https://www.gmx.net/', 19 | 'gmx.de': 'https://www.gmx.de/', 20 | 'amazon': 'https://www.amazon.com/', 21 | 'amazon.com': 'https://www.amazon.com/', 22 | 'wikipedia': 'https://wikipedia.org/', 23 | 'wikipedia.de': 'https://wikipedia.de/', 24 | 'twitter': 'https://twitter.com/', 25 | 'twitter.com': 'https://twitter.com/', 26 | 'ebay': 'https://www.ebay.com/', 27 | 'ebay.com': 'https://www.ebay.com/', 28 | 'instagram': 'https://www.instagram.com/', 29 | 'instagram.com': 'https://www.instagram.com/', 30 | }; 31 | 32 | let req_listener_active = false; 33 | let userId = ''; 34 | getBrowserId() 35 | .then(result => { 36 | userId = result; 37 | }) 38 | 39 | function getRedirects() { 40 | return this.redirects; 41 | } 42 | 43 | function setRedirects(redirects) { 44 | this.redirects = redirects; 45 | setData('redirects', redirects); 46 | } 47 | 48 | function getStatsConsent() { 49 | return this.stats_consent; 50 | } 51 | 52 | function setStatsConsent(stats_consent) { 53 | this.stats_consent = stats_consent; 54 | setData('stats_consent', stats_consent); 55 | } 56 | 57 | function getDataWithDefault(sKey, default_value) { 58 | return new Promise((resolve, reject) => { 59 | const data = {} 60 | data[sKey] = default_value; 61 | chrome.storage.sync.get(data, (items) => { 62 | if (chrome.runtime.lastError) { 63 | console.error(chrome.runtime.lastError.message); 64 | reject(chrome.runtime.lastError.message); 65 | } else { 66 | resolve(items[sKey]); 67 | } 68 | }); 69 | }); 70 | } 71 | 72 | function getData(sKey) { 73 | return new Promise((resolve, reject) => { 74 | chrome.storage.sync.get(sKey, (items) => { 75 | if (chrome.runtime.lastError) { 76 | console.error(chrome.runtime.lastError.message); 77 | reject(chrome.runtime.lastError.message); 78 | } else { 79 | resolve(items[sKey]); 80 | } 81 | }); 82 | }); 83 | } 84 | 85 | function setData(sKey, sValue) { 86 | return new Promise((resolve, reject) => { 87 | const data = {} 88 | data[sKey] = sValue 89 | chrome.storage.sync.set(data, () => { 90 | if (chrome.runtime.lastError) { 91 | console.error(chrome.runtime.lastError.message); 92 | reject(chrome.runtime.lastError.message); 93 | } else { 94 | resolve(true); 95 | } 96 | }); 97 | }); 98 | } 99 | 100 | function readToggle() { 101 | return new Promise((resolve, reject) => { 102 | getData('ecoify_toggle').then((ecoify_toggle) => { 103 | if (typeof ecoify_toggle === 'undefined' || isNaN(ecoify_toggle)) { 104 | ecoify_toggle = true; 105 | } 106 | resolve(ecoify_toggle) 107 | }) 108 | }) 109 | } 110 | 111 | function setToggle(new_ecoify_toggle) { 112 | setData('ecoify_toggle', new_ecoify_toggle); 113 | } 114 | 115 | function setBrowserId() { 116 | var browserId = Date.now() + '-' + Math.floor(Math.random() * Math.floor(Date.now())); 117 | setData('browserId', browserId) 118 | return browserId 119 | } 120 | 121 | function getBrowserId() { 122 | return new Promise((resolve, reject) => { 123 | getData('browserId').then((browserId) => { 124 | if (browserId) { 125 | browserId = setBrowserId(); 126 | } 127 | resolve(browserId) 128 | }) 129 | }) 130 | } 131 | 132 | function readCounter() { 133 | return new Promise((resolve, reject) => { 134 | getData('blockedCounter').then((counter) => { 135 | if (tisNaN(counter)) { 136 | counter = 0; 137 | } 138 | resolve(counter) 139 | }) 140 | }) 141 | } 142 | 143 | function increaseCounter() { 144 | readCounter().then((counter) => { 145 | const thisCounter = counter + 1 146 | setData('blockedCounter', thisCounter); 147 | if (thisCounter % 11 == 0) { 148 | if (this.stats_consent) { 149 | const data = {carbon: thisCounter * 0.2}; 150 | const xhr = new XMLHttpRequest(); 151 | xhr.open('PUT', 'https://5tepzfsmxg.execute-api.eu-central-1.amazonaws.com/dev/carbon/' + userId, true); 152 | xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8'); 153 | xhr.send(JSON.stringify(data)); 154 | } 155 | } 156 | }) 157 | } 158 | 159 | function req_callback(details) { 160 | try { 161 | if (/[&?]q=(.+?)&/.test(details.url) && /[&?]oq=(.+?)&/.test(details.url)) { 162 | const term = details.url.match(/[&?]q=(.+?)&/)[1] 163 | if (this.redirects && this.redirects[term]) { 164 | increaseCounter() 165 | return { redirectUrl: this.redirects[term] }; 166 | } 167 | } 168 | } 169 | catch (error) { 170 | console.error(error); 171 | } 172 | }; 173 | 174 | const filter = { urls: ['*://*.google.de/*', '*://*.google.com/*'] }; 175 | const extraInfoSpec = ['blocking']; 176 | function addReqListener() { 177 | if (!req_listener_active) { 178 | chrome.webRequest.onBeforeRequest.addListener(req_callback, filter, extraInfoSpec); 179 | req_listener_active = true; 180 | setToggle(true); 181 | } 182 | chrome.browserAction.setIcon({ path: '../assets/icon_on_48.png' }); 183 | } 184 | 185 | function removeReqListener() { 186 | if (req_listener_active) { 187 | chrome.webRequest.onBeforeRequest.removeListener(req_callback); 188 | req_listener_active = false; 189 | setToggle(false); 190 | } 191 | chrome.browserAction.setIcon({ path: '../assets/icon_off_48.png' }); 192 | } 193 | 194 | const startup = () => { 195 | getDataWithDefault('redirects', redirects_default) 196 | .then((redirects) => { 197 | this.redirects = redirects; 198 | }); 199 | 200 | getDataWithDefault('stats_consent', true) 201 | .then((stats_consent) => { 202 | this.stats_consent = stats_consent; 203 | }); 204 | 205 | readToggle() 206 | .then((toggle) => { 207 | if (toggle) { 208 | addReqListener(); 209 | } else { 210 | removeReqListener(); 211 | } 212 | }); 213 | } 214 | 215 | startup(); 216 | -------------------------------------------------------------------------------- /source/assets/icon_on.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source/assets/icon_off.svg: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------