From 81f60022e840c1080ed269e6022c2e37bad76157 Mon Sep 17 00:00:00 2001 From: Thomas Rientjes <synzvato@protonmail.com> Date: Tue, 7 Nov 2017 18:27:55 -0300 Subject: [PATCH] Refactor existing codebase --- .eslintignore | 6 ++ .eslintrc | 176 +++++++++++++++++++++++++++++-- audit/.eslintrc | 136 ++++++++++++++++++++++++ audit/run.js | 69 ++++++------ core/constants.js | 58 ++++++++++ core/interceptor.js | 31 +++--- core/main.js | 3 +- core/mappings.js | 84 +++++++-------- core/request-analyzer.js | 46 +++----- core/resources.js | 84 +++++++-------- core/state-manager.js | 57 ++++------ modules/internal/.gitkeep | 0 modules/internal/helpers.js | 169 +++++++++++++++++++++++++++++ pages/background/background.html | 3 + pages/options/options.html | 3 + pages/options/options.js | 109 +++++-------------- pages/popup/popup.html | 5 +- pages/popup/popup.js | 175 +++++------------------------- 18 files changed, 772 insertions(+), 442 deletions(-) create mode 100644 .eslintignore create mode 100644 audit/.eslintrc create mode 100644 core/constants.js delete mode 100644 modules/internal/.gitkeep create mode 100644 modules/internal/helpers.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..65658bd --- /dev/null +++ b/.eslintignore @@ -0,0 +1,6 @@ +_locales +audit +icons +modules/* +!modules/internal +resources diff --git a/.eslintrc b/.eslintrc index 978d0fa..b703040 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,11 +1,165 @@ -# Usage: `eslint --config .eslint.yml .` -extends: "eslint:recommended" -env: - browser: true -rules: - indent: - - error - - 4 - no-undef: 1 # warn - no-unused-vars: 1 - no-console: 1 \ No newline at end of file +{ + "env": { + "browser": true, + "es6": true, + "webextensions": true + }, + "extends": "eslint:recommended", + "globals": { + "Address": true, + "files": true, + "helpers": true, + "interceptor": true, + "mappings": true, + "requestAnalyzer": true, + "Resource": true, + "resources": true, + "Setting": true, + "stateManager": true, + "WebRequest": true, + "Whitelist": true + }, + "overrides": { + "files": [ + "core/constants.js", + "core/files.js", + "core/mappings.js", + "core/resources.js" + ], + "rules": { + "no-unused-vars": "off" + } + }, + "rules": { + "array-bracket-newline": "error", + "array-bracket-spacing": "error", + "arrow-body-style": "error", + "arrow-parens": "error", + "arrow-spacing": "error", + "block-spacing": "error", + "brace-style": "error", + "camelcase": "error", + "comma-spacing": "error", + "comma-style": "error", + "computed-property-spacing": "error", + "consistent-this": "error", + "curly": "error", + "eol-last": "error", + "eqeqeq": "error", + "func-call-spacing": "error", + "function-paren-newline": "error", + "generator-star-spacing": "error", + "indent": [ + "error", + 4 + ], + "key-spacing": "error", + "keyword-spacing": "error", + "linebreak-style": [ + "error", + "unix" + ], + "new-cap": "error", + "new-parens": "error", + "no-array-constructor": "error", + "no-bitwise": "error", + "no-confusing-arrow": "error", + "no-continue": "error", + "no-duplicate-imports": "error", + "no-eval": "error", + "no-extend-native": "error", + "no-implicit-coercion": "error", + "no-implied-eval": "error", + "no-invalid-this": "error", + "no-iterator": "error", + "no-label-var": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-loop-func": "error", + "no-multi-spaces": "error", + "no-multi-str": "error", + "no-multiple-empty-lines": [ + "error", { + "max": 1, + "maxEOF": 1, + "maxBOF": 0 + } + ], + "max-len": [ + "error", { + "code": 120 + } + ], + "no-negated-condition": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-object": "error", + "no-new-wrappers": "error", + "no-octal-escape": "error", + "no-proto": "error", + "no-return-assign": "error", + "no-return-await": "error", + "no-script-url": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-shadow-restricted-names": "error", + "no-tabs": "error", + "no-ternary": "error", + "no-throw-literal": "error", + "no-trailing-spaces": "error", + "no-undef-init": "error", + "no-unmodified-loop-condition": "error", + "no-unused-expressions": "error", + "no-use-before-define": "error", + "no-useless-call": "error", + "no-useless-concat": "error", + "no-useless-constructor": "error", + "no-useless-rename": "error", + "no-useless-return": "error", + "no-void": "error", + "no-warning-comments": "warn", + "no-whitespace-before-property": "error", + "no-with": "error", + "object-curly-spacing": "error", + "object-shorthand": [ + "error", + "consistent-as-needed" + ], + "operator-assignment": "error", + "operator-linebreak": "error", + "prefer-numeric-literals": "error", + "prefer-promise-reject-errors": "error", + "quote-props": "error", + "prefer-rest-params": "error", + "prefer-spread": "error", + "prefer-template": "error", + "quotes": [ + "error", + "single" + ], + "rest-spread-spacing": "error", + "require-await": "error", + "semi": "error", + "semi-spacing": "error", + "semi-style": "error", + "space-before-blocks": "error", + "space-before-function-paren": "error", + "space-in-parens": "error", + "space-infix-ops": "error", + "space-unary-ops": "error", + "spaced-comment": "error", + "strict": [ + "error", + "global" + ], + "switch-colon-spacing": "error", + "symbol-description": "error", + "template-curly-spacing": "error", + "template-tag-spacing": "error", + "unicode-bom": "error", + "vars-on-top": "error", + "wrap-regex": "error", + "yield-star-spacing": "error", + "yoda": "error" + } +} diff --git a/audit/.eslintrc b/audit/.eslintrc new file mode 100644 index 0000000..70f48be --- /dev/null +++ b/audit/.eslintrc @@ -0,0 +1,136 @@ +{ + "env": { + "es6": true, + "node": true + }, + "extends": "eslint:recommended", + "parserOptions": { + "sourceType": "module" + }, + "rules": { + "array-bracket-newline": "error", + "array-bracket-spacing": "error", + "arrow-body-style": "error", + "arrow-parens": "error", + "arrow-spacing": "error", + "block-spacing": "error", + "brace-style": "error", + "camelcase": "error", + "comma-spacing": "error", + "comma-style": "error", + "computed-property-spacing": "error", + "consistent-this": "error", + "curly": "error", + "eol-last": "error", + "eqeqeq": "error", + "func-call-spacing": "error", + "function-paren-newline": "error", + "generator-star-spacing": "error", + "indent": [ + "error", + 4 + ], + "key-spacing": "error", + "keyword-spacing": "error", + "linebreak-style": [ + "error", + "unix" + ], + "new-cap": "error", + "new-parens": "error", + "no-array-constructor": "error", + "no-bitwise": "error", + "no-confusing-arrow": "error", + "no-console": "off", + "no-continue": "error", + "no-duplicate-imports": "error", + "no-eval": "error", + "no-extend-native": "error", + "no-implicit-coercion": "error", + "no-implied-eval": "error", + "no-invalid-this": "error", + "no-iterator": "error", + "no-label-var": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-loop-func": "error", + "no-multi-spaces": "error", + "no-multi-str": "error", + "no-multiple-empty-lines": [ + "error", { + "max": 1, + "maxEOF": 1, + "maxBOF": 0 + } + ], + "no-negated-condition": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-object": "error", + "no-new-wrappers": "error", + "no-octal-escape": "error", + "no-proto": "error", + "no-return-assign": "error", + "no-return-await": "error", + "no-script-url": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-shadow-restricted-names": "error", + "no-tabs": "error", + "no-ternary": "error", + "no-trailing-spaces": "error", + "no-undef-init": "error", + "no-unmodified-loop-condition": "error", + "no-unused-expressions": "error", + "no-use-before-define": "error", + "no-useless-call": "error", + "no-useless-concat": "error", + "no-useless-constructor": "error", + "no-useless-rename": "error", + "no-useless-return": "error", + "no-void": "error", + "no-warning-comments": "warn", + "no-whitespace-before-property": "error", + "no-with": "error", + "object-curly-spacing": "error", + "object-shorthand": [ + "error", + "consistent-as-needed" + ], + "operator-assignment": "error", + "operator-linebreak": "error", + "prefer-numeric-literals": "error", + "prefer-promise-reject-errors": "error", + "prefer-rest-params": "error", + "prefer-spread": "error", + "prefer-template": "error", + "quote-props": "error", + "quotes": [ + "error", + "single" + ], + "require-await": "error", + "rest-spread-spacing": "error", + "semi": "error", + "semi-spacing": "error", + "semi-style": "error", + "space-before-blocks": "error", + "space-before-function-paren": "error", + "space-in-parens": "error", + "space-infix-ops": "error", + "space-unary-ops": "error", + "spaced-comment": "error", + "strict": [ + "error", + "global" + ], + "switch-colon-spacing": "error", + "symbol-description": "error", + "template-curly-spacing": "error", + "template-tag-spacing": "error", + "unicode-bom": "error", + "wrap-regex": "error", + "yield-star-spacing": "error", + "yoda": "error" + } +} diff --git a/audit/run.js b/audit/run.js index add84d9..eafa53f 100644 --- a/audit/run.js +++ b/audit/run.js @@ -1,4 +1,3 @@ -/* eslint-env node */ /** * Resource Audit Script * Belongs to Decentraleyes. @@ -38,11 +37,11 @@ var resourceAmount = 0; * Functions */ -function _fetchLocalResourcePaths(folderPath) { +function _fetchLocalResourcePaths (folderPath) { fileSystem.readdirSync(folderPath).forEach(function (resourceName) { - var resourcePath = folderPath + '/' + resourceName; + var resourcePath = `${folderPath}/${resourceName}`; var resourceStatistics = fileSystem.statSync(resourcePath); if (resourceStatistics && resourceStatistics.isDirectory()) { @@ -56,7 +55,7 @@ function _fetchLocalResourcePaths(folderPath) { return localResourcePaths; } -function _getLocalResourceContents(fileLocation, callback) { +function _getLocalResourceContents (fileLocation, callback) { fileSystem.exists(fileLocation, function (exists) { @@ -82,16 +81,16 @@ function _getLocalResourceContents(fileLocation, callback) { }); } -function _getRemoteResourceContents(remoteResourceRoute, callback) { +function _getRemoteResourceContents (remoteResourceRoute, callback) { - var resourceURL = 'https://ajax.googleapis.com/ajax/libs/' + remoteResourceRoute; + var resourceURL = `https://ajax.googleapis.com/ajax/libs/${remoteResourceRoute}`; https.get(resourceURL, function (response) { var resourceContents = ''; response.on('data', function (chunk) { - resourceContents = resourceContents + chunk; + resourceContents += chunk; }); response.on('end', function () { @@ -102,20 +101,20 @@ function _getRemoteResourceContents(remoteResourceRoute, callback) { } else { - resourceURL = 'https://cdnjs.cloudflare.com/ajax/libs/' + remoteResourceRoute; + resourceURL = `https://cdnjs.cloudflare.com/ajax/libs/${remoteResourceRoute}`; https.get(resourceURL, function (response) { resourceContents = ''; response.on('data', function (chunk) { - resourceContents = resourceContents + chunk; + resourceContents += chunk; }); response.on('end', function () { if (response.statusCode !== 200) { - throw 'Error: Resource ' + remoteResourceRoute + ' could not be fetched.'; + throw `Error: Resource ${remoteResourceRoute} could not be fetched.`; } callback(resourceContents, resourceURL); @@ -130,7 +129,7 @@ function _getRemoteResourceContents(remoteResourceRoute, callback) { }); } -function _hashFileContents(fileContents) { +function _hashFileContents (fileContents) { var hash; @@ -143,7 +142,27 @@ function _hashFileContents(fileContents) { return hash.read(); } -function _compareResources(localResourceContents, remoteResourceContents, URL) { +function _showCompletedMessage () { + + console.log(); + console.log(' *** FILE INTEGRITY CHECKS COMPLETED'); + console.log(` *** ${resourceAmount}/${resourceAmount} RESOURCES WERE ANALYZED`); + console.log(); +} + +function _incrementComparedResourceAmount () { + + comparedResourceAmount++; + + if (comparedResourceAmount === resourceAmount) { + + setTimeout(function () { + _showCompletedMessage(); + }, 500); + } +} + +function _compareResources (localResourceContents, remoteResourceContents, URL) { var hasSourceMappingURL = sourceMappingURL.existsIn(remoteResourceContents); var sourceMappingNotice = '[ ] REMOTE RESOURCE HAD SOURCE MAPPING URL'; @@ -156,8 +175,8 @@ function _compareResources(localResourceContents, remoteResourceContents, URL) { var localResourceHash = _hashFileContents(localResourceContents); var remoteResourceHash = _hashFileContents(remoteResourceContents); - console.log('RESOURCE HASH (SHA512): ' + localResourceHash); - console.log('RESOURCE HASH (SHA512): ' + remoteResourceHash); + console.log(`RESOURCE HASH (SHA512): ${localResourceHash}`); + console.log(`RESOURCE HASH (SHA512): ${remoteResourceHash}`); var fileHashesMatch = (localResourceHash === remoteResourceHash); @@ -174,26 +193,6 @@ function _compareResources(localResourceContents, remoteResourceContents, URL) { _incrementComparedResourceAmount(); } -function _showCompletedMessage() { - - console.log(); - console.log(' *** FILE INTEGRITY CHECKS COMPLETED'); - console.log(' *** ' + resourceAmount + '/' + resourceAmount + ' RESOURCES WERE ANALYZED'); - console.log(); -} - -function _incrementComparedResourceAmount() { - - comparedResourceAmount++; - - if (comparedResourceAmount === resourceAmount) { - - setTimeout(function () { - _showCompletedMessage(); - }, 500); - } -} - /** * Initializations */ @@ -205,7 +204,7 @@ resourceAmount = localResourcePaths.length; * Script */ -localResourcePaths.forEach(function (resourcePath, index) { +localResourcePaths.forEach(function (resourcePath) { var resourceRoute = resourcePath.substr(localResourceLocationLength + 1); resourceRoute = resourceRoute.substring(0, resourceRoute.length - 4); diff --git a/core/constants.js b/core/constants.js new file mode 100644 index 0000000..07ddd42 --- /dev/null +++ b/core/constants.js @@ -0,0 +1,58 @@ +/** + * Global Constants + * Belongs to Decentraleyes. + * + * @author Thomas Rientjes + * @since 2017-10-27 + * @license MPL 2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +'use strict'; + +/** + * Constants + */ + +const Address = { + 'ANY': '*://*/*', + 'ANY_PATH': '/*', + 'ANY_PROTOCOL': '*://', + 'DOMAIN_EXPRESSION': /:\/\/(.[^/]+)(.*)/, + 'EXAMPLE': 'example.org', + 'HTTP_EXPRESSION': /^http?:\/\//, + 'HTTPS': 'https://', + 'WWW_PREFIX': 'www.', + 'WWW_PREFIX_LENGTH': 4 +}; + +const Resource = { + 'MAPPING_EXPRESSION': /\.map$/i, + 'VERSION_EXPRESSION': /(?:\d{1,2}\.){1,3}\d{1,2}/, + 'VERSION_PLACEHOLDER': '{version}' +}; + +const Setting = { + 'AMOUNT_INJECTED': 'amountInjected', + 'BLOCK_MISSING': 'blockMissing', + 'DISABLE_PREFETCH': 'disablePrefetch', + 'SHOW_ICON_BADGE': 'showIconBadge', + 'STRIP_METADATA': 'stripMetadata', + 'WHITELISTED_DOMAINS': 'whitelistedDomains' +}; + +const WebRequest = { + 'GET': 'GET', + 'BLOCKING': 'blocking', + 'HEADERS': 'requestHeaders', + 'ORIGIN_HEADER': 'Origin', + 'REFERER_HEADER': 'Referer' +}; + +const Whitelist = { + 'TRIM_EXPRESSION': /^;+|;+$/g, + 'VALUE_SEPARATOR': ';' +}; diff --git a/core/interceptor.js b/core/interceptor.js index 57ce92a..e9b28ce 100644 --- a/core/interceptor.js +++ b/core/interceptor.js @@ -19,12 +19,6 @@ var interceptor = {}; -/** - * Constants - */ - -const HTTP_EXPRESSION = /^http?:\/\//; - /** * Public Methods */ @@ -43,24 +37,28 @@ interceptor.handleRequest = function (requestDetails, tabIdentifier, tab) { } try { - tabDomain = tab.url.match(WEB_DOMAIN_EXPRESSION)[1]; + tabDomain = tab.url.match(Address.DOMAIN_EXPRESSION)[1]; tabDomain = requestAnalyzer._normalizeDomain(tabDomain); } catch (exception) { - tabDomain = 'example.org'; + tabDomain = Address.EXAMPLE; } // Temporary list of undetectable tainted domains. let undetectableTaintedDomains = { 'cdnjs.com': true, 'dropbox.com': true, + 'glowing-bear.org': true, + 'jadi.sk': true, 'minigames.mail.ru': true, 'report-uri.io': true, + 'scotthelme.co.uk': true, 'securityheaders.io': true, 'stefansundin.github.io': true, - 'udacity.com': true + 'udacity.com': true, + 'yourvotematters.co.uk': true }; - if (undetectableTaintedDomains[tabDomain] || /yandex\./.test(tabDomain)) { + if (undetectableTaintedDomains[tabDomain] || (/yandex\./).test(tabDomain)) { if (tabDomain !== 'yandex.ru') { return interceptor._handleMissingCandidate(requestDetails.url); @@ -79,8 +77,7 @@ interceptor.handleRequest = function (requestDetails, tabIdentifier, tab) { } stateManager.requests[requestDetails.requestId] = { - 'tabIdentifier': tabIdentifier, - 'targetDetails': targetDetails + tabIdentifier, targetDetails }; return { @@ -101,12 +98,12 @@ interceptor._handleMissingCandidate = function (requestUrl) { }; } - if (requestUrl.match(HTTP_EXPRESSION)) { + if (requestUrl.match(Address.HTTP_EXPRESSION)) { - requestUrl = requestUrl.replace(HTTP_EXPRESSION, 'https://'); + let secureRequestUrl = requestUrl.replace(Address.HTTP_EXPRESSION, Address.HTTPS); return { - 'redirectUrl': requestUrl + 'redirectUrl': secureRequestUrl }; } else { @@ -119,7 +116,7 @@ interceptor._handleMissingCandidate = function (requestUrl) { interceptor._handleStorageChanged = function (changes) { - if ('blockMissing' in changes) { + if (Setting.BLOCK_MISSING in changes) { interceptor.blockMissing = changes.blockMissing.newValue; } }; @@ -131,7 +128,7 @@ interceptor._handleStorageChanged = function (changes) { interceptor.amountInjected = 0; interceptor.blockMissing = false; -chrome.storage.local.get(['amountInjected', 'blockMissing'], function (items) { +chrome.storage.local.get([Setting.AMOUNT_INJECTED, Setting.BLOCK_MISSING], function (items) { interceptor.amountInjected = items.amountInjected || 0; interceptor.blockMissing = items.blockMissing || false; diff --git a/core/main.js b/core/main.js index f1d49bc..bbb3e6d 100644 --- a/core/main.js +++ b/core/main.js @@ -54,7 +54,8 @@ main._showReleaseNotes = function (details) { let location = chrome.extension.getURL('pages/welcome/welcome.html'); - if (details.reason === 'install' || details.reason === 'update') { + if (details.reason === chrome.runtime.OnInstalledReason.INSTALL || + details.reason === chrome.runtime.OnInstalledReason.UPDATE) { if (details.temporary !== true) { diff --git a/core/mappings.js b/core/mappings.js index fca471e..3aac795 100644 --- a/core/mappings.js +++ b/core/mappings.js @@ -37,40 +37,40 @@ var mappings = { // Common Shorthand Notations [Deprecated] 'dojo/1/dojo/dojo.': { - path: 'resources/dojo/1.6.1/dojo/dojo.js.dec', - type: 'application/javascript' + 'path': 'resources/dojo/1.6.1/dojo/dojo.js.dec', + 'type': 'application/javascript' }, 'jquery/1/jquery.': { - path: 'resources/jquery/1.11.1/jquery.min.js.dec', - type: 'application/javascript' + 'path': 'resources/jquery/1.11.1/jquery.min.js.dec', + 'type': 'application/javascript' }, 'jqueryui/1/jquery-ui.js': { - path: 'resources/jqueryui/1.10.4/jquery-ui.min.js.dec', - type: 'application/javascript' + 'path': 'resources/jqueryui/1.10.4/jquery-ui.min.js.dec', + 'type': 'application/javascript' }, 'jqueryui/1/jquery-ui.min.js': { - path: 'resources/jqueryui/1.10.4/jquery-ui.min.js.dec', - type: 'application/javascript' + 'path': 'resources/jqueryui/1.10.4/jquery-ui.min.js.dec', + 'type': 'application/javascript' }, 'mootools/1/mootools-yui-compressed.': { - path: 'resources/mootools/1.1.2/mootools-yui-compressed.js.dec', - type: 'application/javascript' + 'path': 'resources/mootools/1.1.2/mootools-yui-compressed.js.dec', + 'type': 'application/javascript' }, 'prototype/1/prototype.': { - path: 'resources/prototype/1.7.1.0/prototype.js.dec', - type: 'application/javascript' + 'path': 'resources/prototype/1.7.1.0/prototype.js.dec', + 'type': 'application/javascript' }, 'scriptaculous/1/scriptaculous.': { - path: 'resources/scriptaculous/1.9.0/scriptaculous.js.dec', - type: 'application/javascript' + 'path': 'resources/scriptaculous/1.9.0/scriptaculous.js.dec', + 'type': 'application/javascript' }, 'swfobject/2/swfobject.': { - path: 'resources/swfobject/2.2/swfobject.js.dec', - type: 'application/javascript' + 'path': 'resources/swfobject/2.2/swfobject.js.dec', + 'type': 'application/javascript' }, 'webfont/1/webfont.': { - path: 'resources/webfont/1.5.18/webfont.js.dec', - type: 'application/javascript' + 'path': 'resources/webfont/1.5.18/webfont.js.dec', + 'type': 'application/javascript' } } }, @@ -118,52 +118,52 @@ var mappings = { // Common Shorthand Notations [Deprecated] 'jquery-latest.': { - path: 'resources/jquery/1.11.1/jquery.min.js.dec', - type: 'application/javascript' + 'path': 'resources/jquery/1.11.1/jquery.min.js.dec', + 'type': 'application/javascript' }, 'jquery.': { - path: 'resources/jquery/1.11.1/jquery.min.js.dec', - type: 'application/javascript' + 'path': 'resources/jquery/1.11.1/jquery.min.js.dec', + 'type': 'application/javascript' }, 'jquery-1.3.min.js': { - path: 'resources/jquery/1.3.0/jquery.min.js.dec', - type: 'application/javascript' + 'path': 'resources/jquery/1.3.0/jquery.min.js.dec', + 'type': 'application/javascript' }, 'jquery-1.3.js': { - path: 'resources/jquery/1.3.0/jquery.min.js.dec', - type: 'application/javascript' + 'path': 'resources/jquery/1.3.0/jquery.min.js.dec', + 'type': 'application/javascript' }, 'jquery-1.4.min.js': { - path: 'resources/jquery/1.4.0/jquery.min.js.dec', - type: 'application/javascript' + 'path': 'resources/jquery/1.4.0/jquery.min.js.dec', + 'type': 'application/javascript' }, 'jquery-1.4.js': { - path: 'resources/jquery/1.4.0/jquery.min.js.dec', - type: 'application/javascript' + 'path': 'resources/jquery/1.4.0/jquery.min.js.dec', + 'type': 'application/javascript' }, 'jquery-1.5.min.js': { - path: 'resources/jquery/1.5.0/jquery.min.js.dec', - type: 'application/javascript' + 'path': 'resources/jquery/1.5.0/jquery.min.js.dec', + 'type': 'application/javascript' }, 'jquery-1.5.js': { - path: 'resources/jquery/1.5.0/jquery.min.js.dec', - type: 'application/javascript' + 'path': 'resources/jquery/1.5.0/jquery.min.js.dec', + 'type': 'application/javascript' }, 'jquery-1.6.min.js': { - path: 'resources/jquery/1.6.0/jquery.min.js.dec', - type: 'application/javascript' + 'path': 'resources/jquery/1.6.0/jquery.min.js.dec', + 'type': 'application/javascript' }, 'jquery-1.6.js': { - path: 'resources/jquery/1.6.0/jquery.min.js.dec', - type: 'application/javascript' + 'path': 'resources/jquery/1.6.0/jquery.min.js.dec', + 'type': 'application/javascript' }, 'jquery-1.7.min.js': { - path: 'resources/jquery/1.7.0/jquery.min.js.dec', - type: 'application/javascript' + 'path': 'resources/jquery/1.7.0/jquery.min.js.dec', + 'type': 'application/javascript' }, 'jquery-1.7.js': { - path: 'resources/jquery/1.7.0/jquery.min.js.dec', - type: 'application/javascript' + 'path': 'resources/jquery/1.7.0/jquery.min.js.dec', + 'type': 'application/javascript' } } }, diff --git a/core/request-analyzer.js b/core/request-analyzer.js index 513a099..d84a327 100644 --- a/core/request-analyzer.js +++ b/core/request-analyzer.js @@ -19,17 +19,6 @@ var requestAnalyzer = {}; -/** - * Constants - */ - -const MAPPING_FILE_EXPRESSION = new RegExp('\.map$', 'i'); -const VERSION_EXPRESSION = /(?:\d{1,2}\.){1,3}\d{1,2}/; -const VERSION_PLACEHOLDER = '{version}'; -const WEB_DOMAIN_EXPRESSION = /:\/\/(.[^\/]+)(.*)/; -const WEB_PREFIX_VALUE = 'www.'; -const WEB_PREFIX_LENGTH = WEB_PREFIX_VALUE.length; - /** * Public Methods */ @@ -39,9 +28,9 @@ requestAnalyzer.isValidCandidate = function (requestDetails, tabDetails) { let initiatorHost; try { - initiatorHost = tabDetails.url.match(WEB_DOMAIN_EXPRESSION)[1]; + initiatorHost = tabDetails.url.match(Address.DOMAIN_EXPRESSION)[1]; } catch (exception) { - initiatorHost = 'example.org'; + initiatorHost = Address.EXAMPLE; } if (initiatorHost && requestAnalyzer.whitelistedDomains[requestAnalyzer._normalizeDomain(initiatorHost)]) { @@ -49,21 +38,21 @@ requestAnalyzer.isValidCandidate = function (requestDetails, tabDetails) { } // Only requests of type GET can be valid candidates. - return requestDetails.method === 'GET'; + return requestDetails.method === WebRequest.GET; }; requestAnalyzer.getLocalTarget = function (requestDetails) { let destinationHost, destinationPath, hostMappings, basePath, resourceMappings; - destinationHost = requestDetails.url.match(WEB_DOMAIN_EXPRESSION)[1]; - destinationPath = requestDetails.url.match(WEB_DOMAIN_EXPRESSION)[2]; + destinationHost = requestDetails.url.match(Address.DOMAIN_EXPRESSION)[1]; + destinationPath = requestDetails.url.match(Address.DOMAIN_EXPRESSION)[2]; // Use the proper mappings for the targeted host. hostMappings = mappings[destinationHost]; // Resource mapping files are never locally available. - if (MAPPING_FILE_EXPRESSION.test(destinationPath)) { + if (Resource.MAPPING_EXPRESSION.test(destinationPath)) { return false; } @@ -96,12 +85,12 @@ requestAnalyzer._matchBasePath = function (hostMappings, channelPath) { requestAnalyzer._findLocalTarget = function (resourceMappings, basePath, channelHost, channelPath) { - var resourcePath, versionNumber, resourcePattern; + let resourcePath, versionNumber, resourcePattern; resourcePath = channelPath.replace(basePath, ''); - versionNumber = resourcePath.match(VERSION_EXPRESSION); - resourcePattern = resourcePath.replace(versionNumber, VERSION_PLACEHOLDER); + versionNumber = resourcePath.match(Resource.VERSION_EXPRESSION); + resourcePattern = resourcePath.replace(versionNumber, Resource.VERSION_PLACEHOLDER); for (let resourceMold of Object.keys(resourceMappings)) { @@ -110,15 +99,15 @@ requestAnalyzer._findLocalTarget = function (resourceMappings, basePath, channel let targetPath, version; targetPath = resourceMappings[resourceMold].path; - targetPath = targetPath.replace(VERSION_PLACEHOLDER, versionNumber); + targetPath = targetPath.replace(Resource.VERSION_PLACEHOLDER, versionNumber); - version = versionNumber && versionNumber[0] || targetPath.match(VERSION_EXPRESSION); + version = versionNumber && versionNumber[0] || targetPath.match(Resource.VERSION_EXPRESSION); // Prepare and return a local target. return { - source: channelHost, - version: version, - path: targetPath + 'source': channelHost, + 'version': version, + 'path': targetPath }; } } @@ -128,8 +117,7 @@ requestAnalyzer._findLocalTarget = function (resourceMappings, basePath, channel requestAnalyzer._applyWhitelistedDomains = function () { - //noinspection JSUnresolvedVariable - chrome.storage.local.get('whitelistedDomains', function (items) { + chrome.storage.local.get(Setting.WHITELISTED_DOMAINS, function (items) { requestAnalyzer.whitelistedDomains = items.whitelistedDomains || {}; }); }; @@ -138,8 +126,8 @@ requestAnalyzer._normalizeDomain = function (domain) { domain = domain.toLowerCase().trim(); - if (domain.startsWith(WEB_PREFIX_VALUE)) { - domain = domain.slice(WEB_PREFIX_LENGTH); + if (domain.startsWith(Address.WWW_PREFIX)) { + domain = domain.slice(Address.WWW_PREFIX_LENGTH); } return domain; diff --git a/core/resources.js b/core/resources.js index 76b8d06..cbc7b77 100644 --- a/core/resources.js +++ b/core/resources.js @@ -20,73 +20,73 @@ var resources = { // AngularJS - angular: { - path: 'resources/angularjs/{version}/angular.min.js.dec', - type: 'application/javascript' + 'angular': { + 'path': 'resources/angularjs/{version}/angular.min.js.dec', + 'type': 'application/javascript' }, // Backbone.js - backbone: { - path: 'resources/backbone.js/{version}/backbone-min.js.dec', - type: 'application/javascript' + 'backbone': { + 'path': 'resources/backbone.js/{version}/backbone-min.js.dec', + 'type': 'application/javascript' }, // Dojo - dojo: { - path: 'resources/dojo/{version}/dojo/dojo.js.dec', - type: 'application/javascript' + 'dojo': { + 'path': 'resources/dojo/{version}/dojo/dojo.js.dec', + 'type': 'application/javascript' }, // Ember.js - ember: { - path: 'resources/ember.js/{version}/ember.min.js.dec', - type: 'application/javascript' + 'ember': { + 'path': 'resources/ember.js/{version}/ember.min.js.dec', + 'type': 'application/javascript' }, // Ext Core - extCore: { - path: 'resources/ext-core/{version}/ext-core.js.dec', - type: 'application/javascript' + 'extCore': { + 'path': 'resources/ext-core/{version}/ext-core.js.dec', + 'type': 'application/javascript' }, // jQuery - jQuery: { - path: 'resources/jquery/{version}/jquery.min.js.dec', - type: 'application/javascript' + 'jQuery': { + 'path': 'resources/jquery/{version}/jquery.min.js.dec', + 'type': 'application/javascript' }, // jQuery UI - jQueryUI: { - path: 'resources/jqueryui/{version}/jquery-ui.min.js.dec', - type: 'application/javascript' + 'jQueryUI': { + 'path': 'resources/jqueryui/{version}/jquery-ui.min.js.dec', + 'type': 'application/javascript' }, // Modernizr - modernizr: { - path: 'resources/modernizr/{version}/modernizr.min.js.dec', - type: 'application/javascript' + 'modernizr': { + 'path': 'resources/modernizr/{version}/modernizr.min.js.dec', + 'type': 'application/javascript' }, // MooTools - mootools: { - path: 'resources/mootools/{version}/mootools-yui-compressed.js.dec', - type: 'application/javascript' + 'mootools': { + 'path': 'resources/mootools/{version}/mootools-yui-compressed.js.dec', + 'type': 'application/javascript' }, // Prototype - prototypeJS: { - path: 'resources/prototype/{version}/prototype.js.dec', - type: 'application/javascript' + 'prototypeJS': { + 'path': 'resources/prototype/{version}/prototype.js.dec', + 'type': 'application/javascript' }, // Scriptaculous - scriptaculous: { - path: 'resources/scriptaculous/{version}/scriptaculous.js.dec', - type: 'application/javascript' + 'scriptaculous': { + 'path': 'resources/scriptaculous/{version}/scriptaculous.js.dec', + 'type': 'application/javascript' }, // SWFObject - swfobject: { - path: 'resources/swfobject/{version}/swfobject.js.dec', - type: 'application/javascript' + 'swfobject': { + 'path': 'resources/swfobject/{version}/swfobject.js.dec', + 'type': 'application/javascript' }, // Underscore.js - underscore: { - path: 'resources/underscore.js/{version}/underscore-min.js.dec', - type: 'application/javascript' + 'underscore': { + 'path': 'resources/underscore.js/{version}/underscore-min.js.dec', + 'type': 'application/javascript' }, // Web Font Loader - webfont: { - path: 'resources/webfont/{version}/webfont.js.dec', - type: 'application/javascript' + 'webfont': { + 'path': 'resources/webfont/{version}/webfont.js.dec', + 'type': 'application/javascript' } }; diff --git a/core/state-manager.js b/core/state-manager.js index e186202..48fecbc 100644 --- a/core/state-manager.js +++ b/core/state-manager.js @@ -19,15 +19,6 @@ var stateManager = {}; -/** - * Constants - */ - -const BLOCKING_ACTION = 'blocking'; -const HOST_PREFIX = '*://'; -const HOST_SUFFIX = '/*'; -const REQUEST_HEADERS = 'requestHeaders'; - /** * Public Methods */ @@ -47,22 +38,22 @@ stateManager.registerInjection = function (tabIdentifier, injection) { if (injectionCount > 0) { chrome.browserAction.setBadgeText({ - tabId: tabIdentifier, - text: injectionCount.toString() + 'tabId': tabIdentifier, + 'text': injectionCount.toString() }); } else { chrome.browserAction.setBadgeText({ - tabId: tabIdentifier, - text: '' + 'tabId': tabIdentifier, + 'text': '' }); } } if (isNaN(interceptor.amountInjected)) { - chrome.storage.local.get('amountInjected', function (items) { + chrome.storage.local.get(Setting.AMOUNT_INJECTED, function (items) { interceptor.amountInjected = items.amountInjected; @@ -126,7 +117,7 @@ stateManager._createTab = function (tab) { let tab = stateManager.tabs[tabIdentifier].details || {}; return interceptor.handleRequest(requestDetails, tabIdentifier, tab); - }, requestFilters, [BLOCKING_ACTION]); + }, requestFilters, [WebRequest.BLOCKING]); }; stateManager._removeTab = function (tabIdentifier) { @@ -147,8 +138,8 @@ stateManager._updateTab = function (details) { if (stateManager.showIconBadge === true) { chrome.browserAction.setBadgeText({ - tabId: tabIdentifier, - text: '' + 'tabId': tabIdentifier, + 'text': '' }); } @@ -161,9 +152,9 @@ stateManager._stripMetadata = function (requestDetails) { for (let i = 0; i < requestDetails.requestHeaders.length; ++i) { - if (requestDetails.requestHeaders[i].name === 'Origin') { + if (requestDetails.requestHeaders[i].name === WebRequest.ORIGIN_HEADER) { requestDetails.requestHeaders.splice(i--, 1); - } else if (requestDetails.requestHeaders[i].name === 'Referer') { + } else if (requestDetails.requestHeaders[i].name === WebRequest.REFERER_HEADER) { requestDetails.requestHeaders.splice(i--, 1); } } @@ -176,7 +167,7 @@ stateManager._stripMetadata = function (requestDetails) { stateManager._handleStorageChanged = function (changes) { if ('showIconBadge' in changes) { - + stateManager.showIconBadge = changes.showIconBadge.newValue; if (changes.showIconBadge.newValue !== true) { @@ -195,13 +186,13 @@ stateManager._handleStorageChanged = function (changes) { onBeforeSendHeaders.removeListener(stateManager._stripMetadata, { 'urls': stateManager.validHosts - }, [BLOCKING_ACTION, REQUEST_HEADERS]); + }, [WebRequest.BLOCKING, WebRequest.HEADERS]); if (changes.stripMetadata.newValue !== false) { - + onBeforeSendHeaders.addListener(stateManager._stripMetadata, { 'urls': stateManager.validHosts - }, [BLOCKING_ACTION, REQUEST_HEADERS]); + }, [WebRequest.BLOCKING, WebRequest.HEADERS]); } } }; @@ -209,8 +200,8 @@ stateManager._handleStorageChanged = function (changes) { stateManager._removeIconBadgeFromTab = function (tab) { chrome.browserAction.setBadgeText({ - tabId: tab.id, - text: '' + 'tabId': tab.id, + 'text': '' }); }; @@ -224,11 +215,7 @@ stateManager.validHosts = []; for (let mapping in mappings) { - if (!mappings.hasOwnProperty(mapping)) { - continue; - } - - let supportedHost = HOST_PREFIX + mapping + HOST_SUFFIX; + let supportedHost = Address.ANY_PROTOCOL + mapping + Address.ANY_PATH; stateManager.validHosts.push(supportedHost); } @@ -256,10 +243,10 @@ chrome.webRequest.onBeforeRequest.addListener(function (requestDetails) { } } -}, {'types': ['main_frame'], 'urls': ['*://*/*']}); +}, {'types': ['main_frame'], 'urls': [Address.ANY]}); chrome.webNavigation.onCommitted.addListener(stateManager._updateTab, { - url: [{urlContains: ':'}] + 'url': [{'urlContains': ':'}] }); chrome.webRequest.onErrorOccurred.addListener(function (requestDetails) { @@ -268,7 +255,7 @@ chrome.webRequest.onErrorOccurred.addListener(function (requestDetails) { delete stateManager.requests[requestDetails.requestId]; } -}, {'urls': ['*://*/*']}); +}, {'urls': [Address.ANY]}); chrome.webRequest.onBeforeRedirect.addListener(function (requestDetails) { @@ -280,10 +267,10 @@ chrome.webRequest.onBeforeRedirect.addListener(function (requestDetails) { delete stateManager.requests[requestDetails.requestId]; } -}, {'urls': ['*://*/*']}); +}, {'urls': [Address.ANY]}); chrome.webRequest.onBeforeSendHeaders.addListener(stateManager._stripMetadata, { 'urls': stateManager.validHosts -}, [BLOCKING_ACTION, REQUEST_HEADERS]); +}, [WebRequest.BLOCKING, WebRequest.HEADERS]); chrome.storage.onChanged.addListener(stateManager._handleStorageChanged); diff --git a/modules/internal/.gitkeep b/modules/internal/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/modules/internal/helpers.js b/modules/internal/helpers.js new file mode 100644 index 0000000..c5798f7 --- /dev/null +++ b/modules/internal/helpers.js @@ -0,0 +1,169 @@ +/** + * Internal Helper Module + * Belongs to Decentraleyes. + * + * @author Thomas Rientjes + * @since 2017-10-26 + * @license MPL 2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +'use strict'; + +/** + * Helpers + */ + +var helpers = {}; + +/** + * Public Functions + */ + +helpers.insertI18nContentIntoDocument = function (document) { + + let scriptDirection, i18nElements; + + scriptDirection = helpers.determineScriptDirection(navigator.language); + i18nElements = document.querySelectorAll('[data-i18n-content]'); + + i18nElements.forEach(function (i18nElement) { + + let i18nMessageName = i18nElement.getAttribute('data-i18n-content'); + + i18nElement.innerText = chrome.i18n.getMessage(i18nMessageName); + i18nElement.setAttribute('dir', scriptDirection); + }); +}; + +helpers.insertI18nTitlesIntoDocument = function (document) { + + let scriptDirection, i18nElements; + + scriptDirection = helpers.determineScriptDirection(navigator.language); + i18nElements = document.querySelectorAll('[data-i18n-title]'); + + i18nElements.forEach(function (i18nElement) { + + let i18nMessageName = i18nElement.getAttribute('data-i18n-title'); + + i18nElement.setAttribute('title', chrome.i18n.getMessage(i18nMessageName)); + i18nElement.setAttribute('dir', scriptDirection); + }); +}; + +helpers.languageIsFullySupported = function (language) { + + let languageSupported, supportedLanguages; + + languageSupported = false; + + supportedLanguages = [ + 'ar', 'bg', 'zh-CN', 'zh-TW', 'nl', 'en', 'et', 'fi', 'fr', 'de', 'he', + 'hu', 'is', 'id', 'pl', 'pt-PT', 'ro', 'es', 'tr' + ]; + + for (let supportedLanguage of supportedLanguages) { + + if (language.search(supportedLanguage) !== -1) { + languageSupported = true; + } + } + + return languageSupported; +}; + +helpers.determineCdnName = function (domainName) { + + switch (domainName) { + + case 'ajax.googleapis.com': + return 'Google Hosted Libraries'; + case 'ajax.aspnetcdn.com': + return 'Microsoft Ajax CDN'; + case 'ajax.microsoft.com': + return 'Microsoft Ajax CDN [Deprecated]'; + case 'cdnjs.cloudflare.com': + return 'CDNJS (Cloudflare)'; + case 'code.jquery.com': + return 'jQuery CDN (MaxCDN)'; + case 'cdn.jsdelivr.net': + return 'jsDelivr (MaxCDN)'; + case 'yastatic.net': + return 'Yandex CDN'; + case 'yandex.st': + return 'Yandex CDN [Deprecated]'; + case 'libs.baidu.com': + return 'Baidu CDN'; + case 'lib.sinaapp.com': + return 'Sina Public Resources'; + case 'upcdn.b0.upaiyun.com': + return 'UpYun Library'; + default: + return 'Unknown'; + } +}; + +helpers.determineResourceName = function (filename) { + + switch (filename) { + + case 'angular.min.js.dec': + return 'AngularJS'; + case 'backbone-min.js.dec': + return 'Backbone.js'; + case 'dojo.js.dec': + return 'Dojo'; + case 'ember.min.js.dec': + return 'Ember.js'; + case 'ext-core.js.dec': + return 'Ext Core'; + case 'jquery.min.js.dec': + return 'jQuery'; + case 'jquery-ui.min.js.dec': + return 'jQuery UI'; + case 'modernizr.min.js.dec': + return 'Modernizr'; + case 'mootools-yui-compressed.js.dec': + return 'MooTools'; + case 'prototype.js.dec': + return 'Prototype'; + case 'scriptaculous.js.dec': + return 'Scriptaculous'; + case 'swfobject.js.dec': + return 'SWFObject'; + case 'underscore-min.js.dec': + return 'Underscore.js'; + case 'webfont.js.dec': + return 'Web Font Loader'; + default: + return 'Unknown'; + } +}; + +helpers.determineScriptDirection = function (language) { + + let rightToLeftLanguages, scriptDirection; + + rightToLeftLanguages = ['ar', 'he']; + + if (rightToLeftLanguages.indexOf(language) === -1) { + scriptDirection = 'ltr'; + } else { + scriptDirection = 'rtl'; + } + + return scriptDirection; +}; + +helpers.formatVersion = function (version) { + + if (version.indexOf('beta') === -1) { + return version; + } else { + return 'BETA'; + } +}; diff --git a/pages/background/background.html b/pages/background/background.html index 06238b3..f61861d 100644 --- a/pages/background/background.html +++ b/pages/background/background.html @@ -10,6 +10,9 @@ <body> + <script src="../../modules/internal/helpers.js"></script> + + <script src="../../core/constants.js"></script> <script src="../../core/files.js"></script> <script src="../../core/resources.js"></script> <script src="../../core/mappings.js"></script> diff --git a/pages/options/options.html b/pages/options/options.html index f75f177..c184297 100644 --- a/pages/options/options.html +++ b/pages/options/options.html @@ -18,6 +18,9 @@ <body> + <script src="../../core/constants.js"></script> + <script src="../../modules/internal/helpers.js"></script> + <script src="options.js"></script> <section class="option"> diff --git a/pages/options/options.js b/pages/options/options.js index 85988c1..ed6e8e2 100644 --- a/pages/options/options.js +++ b/pages/options/options.js @@ -19,55 +19,24 @@ var options = {}; -/** - * Constants - */ - -const WEB_PREFIX_VALUE = 'www.'; -const WEB_PREFIX_LENGTH = WEB_PREFIX_VALUE.length; -const VALUE_SEPARATOR = ';'; - /** * Private Methods */ -options._determineScriptDirection = function (language) { - - let rightToLeftLanguages, scriptDirection; - - rightToLeftLanguages = ['ar', 'he']; - - if (rightToLeftLanguages.indexOf(language) !== -1) { - scriptDirection = 'rtl'; - } else { - scriptDirection = 'ltr'; - } - - return scriptDirection; +options._getOptionElement = function (optionKey) { + return document.querySelector(`[data-option=${optionKey}]`); }; -options._languageIsFullySupported = function (language) { +function _normalizeDomain (domain) { - let languageSupported, supportedLanguages; - - languageSupported = false; - - supportedLanguages = ['ar', 'bg', 'zh-CN', 'zh-TW', 'nl', 'en', 'et', 'fi', - 'fr', 'de', 'he', 'hu', 'is', 'id', 'pl', 'pt-PT', 'ro', 'es', 'tr']; - - for (let supportedLanguage of supportedLanguages) { + domain = domain.toLowerCase().trim(); - if (language.search(supportedLanguage) !== -1) { - languageSupported = true; - } + if (domain.startsWith(Address.WWW_PREFIX)) { + domain = domain.slice(Address.WWW_PREFIX_LENGTH); } - return languageSupported; -}; - -options._getOptionElement = function (optionKey) { - return document.querySelector('[data-option=' + optionKey + ']'); -}; + return domain; +} /** * Initializations @@ -75,13 +44,12 @@ options._getOptionElement = function (optionKey) { document.addEventListener('DOMContentLoaded', function () { - let i18nElements, scriptDirection, languageSupported, optionElements; + let scriptDirection, languageSupported, optionElements; - i18nElements = document.querySelectorAll('[data-i18n-content]'); - scriptDirection = options._determineScriptDirection(navigator.language); + scriptDirection = helpers.determineScriptDirection(navigator.language); document.body.setAttribute('dir', scriptDirection); - languageSupported = options._languageIsFullySupported(navigator.language); + languageSupported = helpers.languageIsFullySupported(navigator.language); if (languageSupported === false) { @@ -89,18 +57,14 @@ document.addEventListener('DOMContentLoaded', function () { localeNoticeElement.setAttribute('class', 'notice'); } - i18nElements.forEach(function (i18nElement) { - - let i18nMessageName = i18nElement.getAttribute('data-i18n-content'); - i18nElement.innerText = chrome.i18n.getMessage(i18nMessageName); - }); + helpers.insertI18nContentIntoDocument(document); optionElements = { - 'showIconBadge': options._getOptionElement('showIconBadge'), - 'blockMissing': options._getOptionElement('blockMissing'), - 'disablePrefetch': options._getOptionElement('disablePrefetch'), - 'stripMetadata': options._getOptionElement('stripMetadata'), - 'whitelistedDomains': options._getOptionElement('whitelistedDomains') + 'showIconBadge': options._getOptionElement(Setting.SHOW_ICON_BADGE), + 'blockMissing': options._getOptionElement(Setting.BLOCK_MISSING), + 'disablePrefetch': options._getOptionElement(Setting.DISABLE_PREFETCH), + 'stripMetadata': options._getOptionElement(Setting.STRIP_METADATA), + 'whitelistedDomains': options._getOptionElement(Setting.WHITELISTED_DOMAINS) }; chrome.storage.local.get(Object.keys(optionElements), function (items) { @@ -111,11 +75,11 @@ document.addEventListener('DOMContentLoaded', function () { domainWhitelist = ''; Object.keys(whitelistedDomains).forEach(function (domain) { - domainWhitelist = domainWhitelist + domain + ';'; + domainWhitelist = `${domainWhitelist}${domain};`; }); domainWhitelist = domainWhitelist.slice(0, -1); - domainWhitelist = domainWhitelist.replace(/^;+|;+$/g, ''); + domainWhitelist = domainWhitelist.replace(Whitelist.TRIM_EXPRESSION, ''); optionElements.showIconBadge.checked = items.showIconBadge; optionElements.blockMissing.checked = items.blockMissing; @@ -132,20 +96,20 @@ document.addEventListener('DOMContentLoaded', function () { optionType = target.getAttribute('type'); switch (optionType) { - case 'checkbox': - optionValue = target.checked; - break; - default: - optionValue = target.value; + case 'checkbox': + optionValue = target.checked; + break; + default: + optionValue = target.value; } - if (optionKey === 'disablePrefetch') { + if (optionKey === Setting.DISABLE_PREFETCH) { if (optionValue === false) { // Restore default values of related preference values. chrome.privacy.network.networkPredictionEnabled.clear({}); - + } else { chrome.privacy.network.networkPredictionEnabled.set({ @@ -154,13 +118,13 @@ document.addEventListener('DOMContentLoaded', function () { } } - if (optionKey === 'whitelistedDomains') { + if (optionKey === Setting.WHITELISTED_DOMAINS) { let domainWhitelist = optionValue; - + optionValue = {}; - domainWhitelist.split(VALUE_SEPARATOR).forEach(function (domain) { + domainWhitelist.split(Whitelist.VALUE_SEPARATOR).forEach(function (domain) { optionValue[_normalizeDomain(domain)] = true; }); } @@ -176,18 +140,3 @@ document.addEventListener('DOMContentLoaded', function () { optionElements.stripMetadata.addEventListener('change', optionChangedHandler); optionElements.whitelistedDomains.addEventListener('keyup', optionChangedHandler); }); - -/** - * Private Methods - */ - -function _normalizeDomain(domain) { - - domain = domain.toLowerCase().trim(); - - if (domain.startsWith(WEB_PREFIX_VALUE)) { - domain = domain.slice(WEB_PREFIX_LENGTH); - } - - return domain; -} diff --git a/pages/popup/popup.html b/pages/popup/popup.html index 53dab58..9b82ff5 100644 --- a/pages/popup/popup.html +++ b/pages/popup/popup.html @@ -18,6 +18,9 @@ <body> + <script src="../../core/constants.js"></script> + <script src="../../modules/internal/helpers.js"></script> + <script src="popup.js"></script> <header> @@ -61,7 +64,7 @@ <span id="testing-utility-link" class="link-text">decentraleyes.org/test</span> - <div id="options-button" class="button"> + <div id="options-button" class="button" data-i18n-title="optionsTitle"> <i class="fas fa-cog" data-fa-transform="grow-2"></i> </div> diff --git a/pages/popup/popup.js b/pages/popup/popup.js index fc7c623..b09f312 100644 --- a/pages/popup/popup.js +++ b/pages/popup/popup.js @@ -19,73 +19,29 @@ var popup = {}; -/** - * Constants - */ - -const WEB_DOMAIN_EXPRESSION = /:\/\/(.[^\/]+)(.*)/; -const WEB_PREFIX_VALUE = 'www.'; -const WEB_PREFIX_LENGTH = WEB_PREFIX_VALUE.length; - -/** - * Private Methods - */ - -popup._determineScriptDirection = function (language) { - - let rightToLeftLanguages, scriptDirection; - - rightToLeftLanguages = ['ar', 'he']; - - if (rightToLeftLanguages.indexOf(language) !== -1) { - scriptDirection = 'rtl'; - } else { - scriptDirection = 'ltr'; - } - - return scriptDirection; -}; - /** * Initializations */ document.addEventListener('DOMContentLoaded', function () { - let version, optionsButtonElement, optionsTitle, scriptDirection, i18nElements; - - version = chrome.runtime.getManifest().version; - - if (version.indexOf('beta') !== -1) { - version = 'BETA'; - } + let version, optionsButtonElement, scriptDirection; + version = helpers.formatVersion(browser.runtime.getManifest().version); document.getElementById('version-label').innerText = version; + scriptDirection = helpers.determineScriptDirection(navigator.language); optionsButtonElement = document.getElementById('options-button'); - optionsTitle = chrome.i18n.getMessage('optionsTitle'); - - scriptDirection = popup._determineScriptDirection(navigator.language); - - optionsButtonElement.setAttribute('title', optionsTitle); - optionsButtonElement.setAttribute('dir', scriptDirection); - i18nElements = document.querySelectorAll('[data-i18n-content]'); - - i18nElements.forEach(function (i18nElement) { - - let i18nMessageName = i18nElement.getAttribute('data-i18n-content'); - - i18nElement.innerText = chrome.i18n.getMessage(i18nMessageName); - i18nElement.setAttribute('dir', scriptDirection); - }); + helpers.insertI18nContentIntoDocument(document); + helpers.insertI18nTitlesIntoDocument(document); chrome.storage.local.get('amountInjected', function (items) { let amountInjected = items.amountInjected || 0; document.getElementById('injection-counter').innerText = amountInjected; - chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { + chrome.tabs.query({'active': true, 'currentWindow': true}, function (tabs) { chrome.runtime.getBackgroundPage(function (backgroundPage) { @@ -101,7 +57,7 @@ document.addEventListener('DOMContentLoaded', function () { injectionOverview = {}; try { - domain = tabs[0].url.match(WEB_DOMAIN_EXPRESSION)[1]; + domain = tabs[0].url.match(Address.DOMAIN_EXPRESSION)[1]; } catch (exception) { domain = null; } @@ -114,24 +70,22 @@ document.addEventListener('DOMContentLoaded', function () { protectionToggleElement = document.getElementById('protection-toggle-button'); domainIndicatorElement = document.getElementById('domain-indicator'); - if (domain.startsWith(WEB_PREFIX_VALUE)) { - domain = domain.slice(WEB_PREFIX_LENGTH); + if (domain.startsWith(Address.WWW_PREFIX)) { + domain = domain.slice(Address.WWW_PREFIX_LENGTH); } domainIndicatorElement.innerText = domain; - if (!backgroundPage.requestAnalyzer.whitelistedDomains[domain]) { + if (backgroundPage.requestAnalyzer.whitelistedDomains[domain]) { - protectionToggleElement.setAttribute('class', 'button button-toggle active'); + protectionToggleElement.setAttribute('class', 'button button-toggle'); - let disableProtectionTitle = chrome.i18n.getMessage('disableProtectionTitle'); - - protectionToggleElement.setAttribute('title', disableProtectionTitle); - protectionToggleElement.setAttribute('dir', scriptDirection); + let enableProtectionTitle = chrome.i18n.getMessage('enableProtectionTitle'); + protectionToggleElement.setAttribute('title', enableProtectionTitle); protectionToggleElement.addEventListener('click', function () { - backgroundPage.stateManager.addDomainToWhitelist(domain).then(function () { + backgroundPage.stateManager.deleteDomainFromWhitelist(domain).then(function () { chrome.tabs.reload(tabs[0].id, { 'bypassCache': true @@ -143,14 +97,16 @@ document.addEventListener('DOMContentLoaded', function () { } else { - protectionToggleElement.setAttribute('class', 'button button-toggle'); + protectionToggleElement.setAttribute('class', 'button button-toggle active'); - let enableProtectionTitle = chrome.i18n.getMessage('enableProtectionTitle'); - protectionToggleElement.setAttribute('title', enableProtectionTitle); + let disableProtectionTitle = chrome.i18n.getMessage('disableProtectionTitle'); + + protectionToggleElement.setAttribute('title', disableProtectionTitle); + protectionToggleElement.setAttribute('dir', scriptDirection); protectionToggleElement.addEventListener('click', function () { - backgroundPage.stateManager.deleteDomainFromWhitelist(domain).then(function () { + backgroundPage.stateManager.addDomainToWhitelist(domain).then(function () { chrome.tabs.reload(tabs[0].id, { 'bypassCache': true @@ -196,42 +152,7 @@ document.addEventListener('DOMContentLoaded', function () { badgeTextNode = document.createTextNode(cdn.length); badgeElement.appendChild(badgeTextNode); - switch (injectionSource) { - - case 'ajax.googleapis.com': - cdnName = 'Google Hosted Libraries'; - break; - case 'ajax.aspnetcdn.com': - cdnName = 'Microsoft Ajax CDN'; - break; - case 'ajax.microsoft.com': - cdnName = 'Microsoft Ajax CDN [Deprecated]'; - break; - case 'cdnjs.cloudflare.com': - cdnName = 'CDNJS (Cloudflare)'; - break; - case 'code.jquery.com': - cdnName = 'jQuery CDN (MaxCDN)'; - break; - case 'cdn.jsdelivr.net': - cdnName = 'jsDelivr (MaxCDN)'; - break; - case 'yastatic.net': - cdnName = 'Yandex CDN'; - break; - case 'yandex.st': - cdnName = 'Yandex CDN [Deprecated]'; - break; - case 'libs.baidu.com': - cdnName = 'Baidu CDN'; - break; - case 'lib.sinaapp.com': - cdnName = 'Sina Public Resources'; - break; - case 'upcdn.b0.upaiyun.com': - cdnName = 'UpYun Library'; - break; - } + cdnName = helpers.determineCdnName(injectionSource); cdnNameTextNode = document.createTextNode(cdnName); @@ -256,59 +177,15 @@ document.addEventListener('DOMContentLoaded', function () { resourcePathDetails = injection.path.split('/'); resourceFilename = resourcePathDetails[resourcePathDetails.length - 1]; - switch (resourceFilename) { - - case 'angular.min.js.dec': - resourceName = 'AngularJS'; - break; - case 'backbone-min.js.dec': - resourceName = 'Backbone.js'; - break; - case 'dojo.js.dec': - resourceName = 'Dojo'; - break; - case 'ember.min.js.dec': - resourceName = 'Ember.js'; - break; - case 'ext-core.js.dec': - resourceName = 'Ext Core'; - break; - case 'jquery.min.js.dec': - resourceName = 'jQuery'; - break; - case 'jquery-ui.min.js.dec': - resourceName = 'jQuery UI'; - break; - case 'modernizr.min.js.dec': - resourceName = 'Modernizr'; - break; - case 'mootools-yui-compressed.js.dec': - resourceName = 'MooTools'; - break; - case 'prototype.js.dec': - resourceName = 'Prototype'; - break; - case 'scriptaculous.js.dec': - resourceName = 'Scriptaculous'; - break; - case 'swfobject.js.dec': - resourceName = 'SWFObject'; - break; - case 'underscore-min.js.dec': - resourceName = 'Underscore.js'; - break; - case 'webfont.js.dec': - resourceName = 'Web Font Loader'; - break; - } - - resourceNameTextNode = document.createTextNode('- ' + resourceName); + resourceName = helpers.determineResourceName(resourceFilename); + + resourceNameTextNode = document.createTextNode(`- ${resourceName}`); subListItemElement.appendChild(resourceNameTextNode); sideNoteElement = document.createElement('span'); sideNoteElement.setAttribute('class', 'side-note'); - sideNoteTextNode = document.createTextNode(' v' + injection.version); + sideNoteTextNode = document.createTextNode(` v${injection.version}`); sideNoteElement.appendChild(sideNoteTextNode); subListItemElement.appendChild(sideNoteElement); @@ -326,7 +203,7 @@ document.addEventListener('DOMContentLoaded', function () { }); }); - document.getElementById('options-button').addEventListener('click', function () { + optionsButtonElement.addEventListener('mouseup', function () { chrome.runtime.openOptionsPage(); return window.close(); }); -- GitLab