diff --git a/.editorconfig b/.editorconfig new file mode 100755 index 0000000..2e9bbba --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +root=true + +[*] +end_of_line = LF +indent_size = 4 +indent_style = space +insert_final_newline = true diff --git a/README.md b/README.md index afad90f..a678c37 100644 --- a/README.md +++ b/README.md @@ -40,5 +40,12 @@ Additional contributors (in alphabetical order): ## License [CC-BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/legalcode). -See [LICENSE.txt](LICENSE.txt) or the +See [LICENSE.txt](LICENSE.txt) or the [summary](https://creativecommons.org/licenses/by-sa/3.0/). + +## Developing + +We welcome issues and pull requests! The main files are +`src/background.js` and `src/content.js`. Before committing changes, please +run `./beautify.sh` to pretty-print the source. This reduces the number +of whitespace changes and makes it easier to focus on the substance of PRs. diff --git a/beautify.sh b/beautify.sh new file mode 100755 index 0000000..b20ddaf --- /dev/null +++ b/beautify.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -o errexit +set -o pipefail +shopt -s nullglob + +for f in src/*.js src/*.css src/*.htm* ; do + echo "$f" + npx js-beautify --editorconfig -r "$f" +done diff --git a/package-lock.json b/package-lock.json new file mode 100755 index 0000000..cd577cd --- /dev/null +++ b/package-lock.json @@ -0,0 +1,236 @@ +{ + "name": "chrome-dont-add-custom-search-engines", + "version": "0.0.6", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "dev": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "js-beautify": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.10.2.tgz", + "integrity": "sha512-ZtBYyNUYJIsBWERnQP0rPN9KjkrDfJcMjuVGcvXOUJrD1zmOGwhRwQ4msG+HJ+Ni/FA7+sRQEMYVzdTQDvnzvQ==", + "dev": true, + "requires": { + "config-chain": "^1.1.12", + "editorconfig": "^0.15.3", + "glob": "^7.1.3", + "mkdirp": "~0.5.1", + "nopt": "~4.0.1" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "dev": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100755 index 0000000..11673bb --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "chrome-dont-add-custom-search-engines", + "version": "0.0.6", + "description": "Google Chrome extension that stops sites from adding custom search engines", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/gregsadetsky/chrome-dont-add-custom-search-engines.git" + }, + "author": "", + "license": "CC-BY-SA-3.0", + "bugs": { + "url": "https://github.com/gregsadetsky/chrome-dont-add-custom-search-engines/issues" + }, + "homepage": "https://github.com/gregsadetsky/chrome-dont-add-custom-search-engines#readme", + "devDependencies": { + "js-beautify": "^1.10.2" + } +} diff --git a/src/background.js b/src/background.js new file mode 100644 index 0000000..fd69c98 --- /dev/null +++ b/src/background.js @@ -0,0 +1,93 @@ +"use strict"; + +var defSitesWMut = { + 'www.nytimes.com': ['.css-10488qs'], + 'www.brico.be': ['.mxd-search-initial', 'pN', 'pN'] +}; +var sitesWMut = {}; + +var expire = 90000; + +// parse stored data (string) and populate array +// "text" is used when called from the options page (regenerates string version of data with valid syntax, and keeps comments) +function toAr(v, text) { + var r = {}, + t = {}, + n, RE = /^\s*(\S+)\s*(.*)$/, + RE2 = /^(?:"([^"]*?)"|(.+?))(?:\s+(\S.*))?\s*$/, + REcmt = /^(\s*\/\/.*|)$/; + + v = v.split('\n'); + for (let i = 0; i < v.length; i++) { + if (text) { + n = 'cmt' + i; + r[n] = { + txt: v[i].replace(/^\s+/, '') + }; + } + + if (REcmt.test(v[i])) { + if (text) r[n].cmt = 1; + continue; + } + if (!RE.test(v[i])) continue; + + var k = RegExp.$1; + + if (text && r[k]) { + r[r[k].n].cmt = 1; + } + + if (text) { + r[k] = { + n + }; + r[n].k = k; + } else r[k] = {}; + + if (RegExp.$2 == 'null') { + if (text) r[k].null = 1; + else r[k] = 0; + continue; + } + var a = [], + j = 20, + s = RegExp.$2; + while (j-- && RE2.test(s)) { + s = RegExp.$3; + a.push(RegExp.$1 || RegExp.$2); + } + if (a[0] == '!') { + r[k].fb = 1; + a.shift(); + } + r[k].length = a.length; + Object.assign(r[k], a); + if (text) { + Object.assign(r[n], a); + r[n].length = a.length; + } + } + return r; +} + +function getStor() { + var s = toAr(localStorage.sitesWMut || ''); + sitesWMut = JSON.parse(JSON.stringify(defSitesWMut)); + for (var k in s) { + sitesWMut[k] = s[k]; + } +} + +getStor(); + +// receive messages from contentscript +chrome.runtime.onMessage.addListener( + function(request, sender, sendResponse) { + if (sender.id != chrome.runtime.id) return; // not from this extension + if (request.host) { + let s, r = {}; + if (s = sitesWMut[request.host]) r.siteMut = s; + sendResponse(r); + } + }); diff --git a/src/bg.js b/src/bg.js deleted file mode 100644 index 3835ef5..0000000 --- a/src/bg.js +++ /dev/null @@ -1,10 +0,0 @@ -chrome.runtime.onMessage.addListener( - function(request, sender, sendResponse) { - if(request !== "opensearch-block") { - return; - } - chrome.browserAction.setBadgeText({ - text: '1', - tabId: sender.tab.id - }); -}); diff --git a/src/content.js b/src/content.js index f9f2881..e7221ce 100644 --- a/src/content.js +++ b/src/content.js @@ -1,11 +1,16 @@ -const DEBUG=false; -let numseen=0, numspoiled=0; -let unspoiled=[]; +const DEBUG = false; +let numseen = 0, + numspoiled = 0; +let unspoiled = []; + +var sitesWMut = {}; // called when the user clicks an element of the form (any field or button). // The parameter passed is the event object. function clickApply(e) { - if(DEBUG) console.info({'form onclick':e}); + if (DEBUG) console.info({ + 'form onclick': e + }); // remove onclick. One fix only e.srcElement.form.removeEventListener("click", clickApply); applyFix(e.srcElement.form); @@ -13,15 +18,15 @@ function clickApply(e) { // add a new
+
+ + + + + diff --git a/src/options.js b/src/options.js new file mode 100644 index 0000000..9de2b77 --- /dev/null +++ b/src/options.js @@ -0,0 +1,43 @@ +"use strict"; + +var TA = document.getElementById('list'), + b = document.getElementById('b'), + def = document.getElementById('def'), + bg = chrome.extension.getBackgroundPage(); + +var LS = localStorage.sitesWMut; + +TA.value = LS; +def.value += toStr(bg.defSitesWMut, 1); +def.style.height = def.scrollHeight + 4 + 'px'; + +// Convert array of values back to string. Including comments +function toStr(a, raw) { + var r = '', + h; + for (let k in a) { + if (!raw && a[k].txt === undefined) continue; + if (a[k].cmt) { + r += a[k].txt + '\n'; + continue; + } + h = a[k].k || k; + r += h; + if (a[h].null) r += ' null'; + else + for (let e, i = 0; e = a[h][i]; i++) { + if (i == 0) e = (a[h].fb ? '! ' : '') + '"' + e + '"'; + r += ' ' + e; + } + r += '\n' + } + return r; +} + +// Validate current config using the background page function - save - and reload data +b.onclick = function() { + var s = toStr(bg.toAr(TA.value, 1)).replace(/\n+$/, '\n'); + TA.value = s; + localStorage.setItem('sitesWMut', s); + bg.getStor(); +};