diff --git a/.eslintrc.js b/.eslintrc.js index d1af6c8b8..98d8b4329 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -40,7 +40,7 @@ module.exports = { rules: { 'arrow-parens': [2, 'as-needed', { 'requireForBlockBody': true }], 'camelcase': [0], - 'class-methods-use-this': [0], + 'class-methods-use-this': [1], 'comma-dangle': [2, { 'arrays': 'only-multiline', 'objects': 'only-multiline', @@ -54,24 +54,30 @@ module.exports = { 'lines-between-class-members': [1], 'max-len': [0], 'newline-per-chained-call': [0, { 'ignoreChainWithDepth': 2 }], - 'no-mixed-operators': [0], + 'no-mixed-operators': [1], 'no-nested-ternary': [0], - 'no-param-reassign': [0], // TODO: enable this check + 'no-param-reassign': ['error', { + props: true, + ignorePropertyModificationsFor: [ + 'acc', // for reduce accumulators + 'trackerEl', // for trackers.forEach() + 'categoryEl' // for categories.forEach() + ] + }], 'no-plusplus': [0], - 'no-prototype-builtins': [0], // TODO: enable this check - 'no-restricted-syntax': [0], // TODO: enable this check + 'no-prototype-builtins': [1], + 'no-restricted-syntax': [1], 'no-tabs': [0], 'no-underscore-dangle': [0], 'no-unused-vars': [1], 'no-useless-escape': [1], 'operator-linebreak': [0], - 'prefer-object-spread': [0], // TODO: enable this check + 'prefer-object-spread': [1], 'space-before-function-paren': [2, 'never'], - 'template-curly-spacing': [0], // Plugin: Import 'import/no-cycle': [0], - 'import/prefer-default-export': [0], + 'import/prefer-default-export': [1], // Plugin: React 'react/destructuring-assignment': [0], @@ -79,12 +85,12 @@ module.exports = { 'react/jsx-curly-newline': [0], 'react/jsx-indent': [1, 'tab'], 'react/jsx-indent-props': [1, 'tab'], - 'react/jsx-props-no-spreading': [0], // TODO: enable this check - 'react/no-access-state-in-setstate': [0], // TODO: enable this check + 'react/jsx-props-no-spreading': [1], + 'react/no-access-state-in-setstate': [1], 'react/no-danger': [0], 'react/prop-types': [0], 'react/jsx-fragments': [1, 'element'], - 'react/sort-comp': [2, { + 'react/sort-comp': [0, { //TODO: enable this check order: [ "static-variables", "instance-variables", diff --git a/app/Account/AccountReducer.js b/app/Account/AccountReducer.js index 48076f6b0..8365f113a 100644 --- a/app/Account/AccountReducer.js +++ b/app/Account/AccountReducer.js @@ -39,61 +39,62 @@ export default (state = initialState, action) => { case UPDATE_PANEL_DATA: { const { account } = action.data; if (account === null) { - return Object.assign({}, initialState); + return { ...initialState }; } const { userID, user, userSettings, subscriptionData } = account; - return Object.assign({}, state, { + return { + ...state, loggedIn: true, userID, user, userSettings, - subscriptionData, - }); + subscriptionData + }; } case REGISTER_SUCCESS: case LOGIN_SUCCESS: { - return Object.assign({}, state, { - loggedIn: true, - }); + return { ...state, loggedIn: true }; } case LOGOUT_SUCCESS: { - return Object.assign({}, initialState); + return { ...initialState }; } case GET_USER_SUCCESS: { const { user } = action.payload; - return Object.assign({}, state, { + return { + ...state, loggedIn: true, user - }); + }; } case GET_USER_SETTINGS_SUCCESS: { const { settings } = action.payload; - return Object.assign({}, state, { + return { + ...state, loggedIn: true, userSettings: settings - }); + }; } case GET_USER_SUBSCRIPTION_DATA_FAIL: { const { subscriptionData } = initialState; - return Object.assign({}, state, { - subscriptionData, - }); + return { ...state, subscriptionData }; } case GET_USER_SUBSCRIPTION_DATA_SUCCESS: { const { subscriptionData } = action.payload; - return Object.assign({}, state, { + return { + ...state, loggedIn: true, subscriptionData - }); + }; } case RESET_PASSWORD_SUCCESS: { const toastMessage = t('banner_check_your_email_title'); - return Object.assign({}, state, { + return { + ...state, toastMessage, resetPasswordError: false - }); + }; } case RESET_PASSWORD_FAIL: { const { errors } = action.payload; @@ -108,10 +109,11 @@ export default (state = initialState, action) => { errorText = t('server_error_message'); } }); - return Object.assign({}, state, { + return { + ...state, toastMessage: errorText, resetPasswordError: true - }); + }; } default: return state; diff --git a/app/content-scripts/blocked_redirect.js b/app/content-scripts/blocked_redirect.js index 0a4185f1a..e94acc1de 100644 --- a/app/content-scripts/blocked_redirect.js +++ b/app/content-scripts/blocked_redirect.js @@ -40,7 +40,8 @@ const { sendMessage, sendMessageInPromise } = msg; * but another one, down the chain of redirects - is. It is loaded * by app/blocked_redirect.html when we navigate browser to it. */ - (function BlockedRedirectContentScript(window, document) { + (function BlockedRedirectContentScript(window, doc) { + const document = doc; /** * Calculate window height. * @memberof BlockedRedirectContentScript diff --git a/app/content-scripts/click_to_play.js b/app/content-scripts/click_to_play.js index 95c329857..7a41c9c82 100644 --- a/app/content-scripts/click_to_play.js +++ b/app/content-scripts/click_to_play.js @@ -57,11 +57,12 @@ const Click2PlayContentScript = (function(win, doc) { * @memberof Click2PlayContentScript * @package * - * @param {Object} c2pFrame iframe DOM element + * @param {Object} c2pFrameEl iframe DOM element * @param {Object} c2pAppDef replacement data * @param {string} html a fragment of html to be used in replacement. */ - const buildC2P = function(c2pFrame, c2pAppDef, html) { + const buildC2P = function(c2pFrameEl, c2pAppDef, html) { + const c2pFrame = c2pFrameEl; c2pFrame.addEventListener('load', () => { const idoc = c2pFrame.contentDocument; idoc.documentElement.innerHTML = html; @@ -160,8 +161,10 @@ const Click2PlayContentScript = (function(win, doc) { if (name === 'c2p') { if (message) { // Dequeue C2P data stored while the script injection was taking place - for (const app_id in message) { - if (message.hasOwnProperty(app_id)) { + const messageKeys = Object.keys(message); + for (let i = 0; i < messageKeys.length; i++) { + const app_id = messageKeys[i]; + if (Object.prototype.hasOwnProperty.call(message, app_id)) { applyC2P(app_id, message[app_id].data, message[app_id].html); delete message[app_id]; } diff --git a/app/content-scripts/page_performance.js b/app/content-scripts/page_performance.js index 2360367dc..467333c4d 100644 --- a/app/content-scripts/page_performance.js +++ b/app/content-scripts/page_performance.js @@ -27,7 +27,8 @@ const { sendMessage } = msg; * Use to call init to initialize functionality * @var {Object} initialized to an object with init method as its property */ -const PageInfo = (function(window, document) { +const PageInfo = (function(window, doc) { + const document = doc; let state = document.readyState; /** * Calculate page domain and latency. Send pageInfo to background.js. diff --git a/app/hub/Views/AppView/AppViewContainer.jsx b/app/hub/Views/AppView/AppViewContainer.jsx index 2d98688d3..8cf81288e 100644 --- a/app/hub/Views/AppView/AppViewContainer.jsx +++ b/app/hub/Views/AppView/AppViewContainer.jsx @@ -36,11 +36,13 @@ class AppViewContainer extends Component { * @return {JSX} JSX for rendering the Home View of the Hub app */ render() { - const childProps = { - ...this.props, - exitToast: this._exitToast, - }; - return ; + const { app, children } = this.props; + + return ( + + {children} + + ); } } diff --git a/app/hub/Views/AppView/AppViewReducer.js b/app/hub/Views/AppView/AppViewReducer.js index 970f51132..94ee686f2 100644 --- a/app/hub/Views/AppView/AppViewReducer.js +++ b/app/hub/Views/AppView/AppViewReducer.js @@ -19,12 +19,13 @@ function AppViewReducer(state = initialState, action) { switch (action.type) { case SET_TOAST: { const { toastMessage, toastClass } = action.data; - return Object.assign({}, state, { - app: Object.assign({}, { + return { + ...state, + app: { toastMessage, toastClass - }), - }); + } + }; } default: return state; } diff --git a/app/hub/Views/AppView/index.js b/app/hub/Views/AppView/index.js index 8fc86ded9..9d9d20ffc 100644 --- a/app/hub/Views/AppView/index.js +++ b/app/hub/Views/AppView/index.js @@ -23,7 +23,7 @@ import AppViewReducer from './AppViewReducer'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.app); +const mapStateToProps = state => ({ ...state.app }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -32,7 +32,7 @@ const mapStateToProps = state => Object.assign({}, state.app); * @memberof SetupContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, { setToast }), dispatch), + actions: bindActionCreators({ setToast }, dispatch), }); export const reducer = AppViewReducer; diff --git a/app/hub/Views/CreateAccountView/CreateAccountViewContainer.jsx b/app/hub/Views/CreateAccountView/CreateAccountViewContainer.jsx index f0099d3b2..f71c46f97 100644 --- a/app/hub/Views/CreateAccountView/CreateAccountViewContainer.jsx +++ b/app/hub/Views/CreateAccountView/CreateAccountViewContainer.jsx @@ -172,30 +172,26 @@ class CreateAccountViewContainer extends Component { passwordInvalidError, passwordLengthError, } = this.state; - const createAccountChildProps = { - email, - emailError, - confirmEmail, - confirmEmailError, - firstName, - lastName, - legalConsentChecked, - legalConsentNotCheckedError, - password, - passwordInvalidError, - passwordLengthError, - handleInputChange: this._handleInputChange, - handleLegalConsentCheckboxChange: this._handleLegalConsentCheckboxChange, - handleSubmit: this._handleCreateAccountAttempt - }; - const signedInChildProps = { - email: user && user.email || email, - }; return loggedIn ? ( - + ) : ( - + ); } } diff --git a/app/hub/Views/CreateAccountView/index.js b/app/hub/Views/CreateAccountView/index.js index 2fe88b9f9..da18f1190 100644 --- a/app/hub/Views/CreateAccountView/index.js +++ b/app/hub/Views/CreateAccountView/index.js @@ -24,7 +24,7 @@ import { setToast } from '../AppView/AppViewActions'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.account); +const mapStateToProps = state => ({ ...state.account }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -33,11 +33,11 @@ const mapStateToProps = state => Object.assign({}, state.account); * @memberof SetupContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, { + actions: bindActionCreators({ setToast, register, - getUser, - }), dispatch), + getUser + }, dispatch), }); export default connect(mapStateToProps, mapDispatchToProps)(CreateAccountViewContainer); diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index c98e55b78..719651a5d 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -117,22 +117,13 @@ class HomeViewContainer extends Component { _render() { const { justInstalled } = this.state; const { home, user } = this.props; - const isPlus = user && user.subscriptionsPlus || false; + const isPlus = (user && user.subscriptionsPlus) || false; const { premium_promo_modal_shown, setup_complete, tutorial_complete, enable_metrics, } = home; - const childProps = { - justInstalled, - setup_complete, - tutorial_complete, - enable_metrics, - changeMetrics: this._handleToggleMetrics, - email: user ? user.email : '', - isPlus, - }; const showPromoModal = !premium_promo_modal_shown && !this._premiumSubscriber(); @@ -147,7 +138,15 @@ class HomeViewContainer extends Component { handleGetPlusClick={this._handleGetPlusClick} handleTryMidnightClick={this._handleTryMidnightClick} /> - + ); } diff --git a/app/hub/Views/HomeView/HomeViewReducer.js b/app/hub/Views/HomeView/HomeViewReducer.js index 1582d7e62..2461abac6 100644 --- a/app/hub/Views/HomeView/HomeViewReducer.js +++ b/app/hub/Views/HomeView/HomeViewReducer.js @@ -23,26 +23,25 @@ function HomeViewReducer(state = initialState, action) { tutorial_complete, enable_metrics, } = action.data; - return Object.assign({}, state, { - home: Object.assign({}, state.home, { + return { + ...state, + home: { + ...state.home, setup_complete, tutorial_complete, - enable_metrics, - }), - }); + enable_metrics + } + }; } case MARK_PREMIUM_PROMO_MODAL_SHOWN: { - return Object.assign({}, state, { - home: Object.assign({}, state.home, { - premium_promo_modal_shown: true, - }) - }); + return { + ...state, + home: { ...state.home, premium_promo_modal_shown: true } + }; } case SET_METRICS: { const { enable_metrics } = action.data; - return Object.assign({}, state, { - home: Object.assign({}, state.home, { enable_metrics }), - }); + return { ...state, home: { ...state.home, enable_metrics } }; } default: return state; diff --git a/app/hub/Views/HomeView/index.js b/app/hub/Views/HomeView/index.js index 4e4a35da3..9a947b809 100644 --- a/app/hub/Views/HomeView/index.js +++ b/app/hub/Views/HomeView/index.js @@ -25,7 +25,7 @@ import { getUser } from '../../../Account/AccountActions'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.home, state.account); +const mapStateToProps = state => ({ ...state.home, ...state.account }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -34,7 +34,7 @@ const mapStateToProps = state => Object.assign({}, state.home, state.account); * @memberof SetupContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, HomeViewActions, { getUser }), dispatch), + actions: bindActionCreators({ ...HomeViewActions, getUser }, dispatch), }); export const reducer = HomeViewReducer; diff --git a/app/hub/Views/LogInView/LogInViewContainer.jsx b/app/hub/Views/LogInView/LogInViewContainer.jsx index fb9cd1289..6c5ef5859 100644 --- a/app/hub/Views/LogInView/LogInViewContainer.jsx +++ b/app/hub/Views/LogInView/LogInViewContainer.jsx @@ -128,22 +128,18 @@ class LogInViewContainer extends Component { emailError, passwordError, } = this.state; - const logInChildProps = { - email, - password, - emailError, - passwordError, - handleInputChange: this._handleInputChange, - handleSubmit: this._handleLoginAttempt, - }; - const signedInChildProps = { - email: user && user.email || 'email', - }; return loggedIn ? ( - + ) : ( - + ); } } diff --git a/app/hub/Views/LogInView/index.js b/app/hub/Views/LogInView/index.js index e53caf771..ebcd60244 100644 --- a/app/hub/Views/LogInView/index.js +++ b/app/hub/Views/LogInView/index.js @@ -25,7 +25,7 @@ import { setToast } from '../AppView/AppViewActions'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.account); +const mapStateToProps = state => ({ ...state.account }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -34,13 +34,13 @@ const mapStateToProps = state => Object.assign({}, state.account); * @memberof SetupContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, { + actions: bindActionCreators({ setToast, login, getUser, getUserSettings, - getTheme, - }), dispatch), + getTheme + }, dispatch), }); export default connect(mapStateToProps, mapDispatchToProps)(LogInViewContainer); diff --git a/app/hub/Views/PlusView/PlusViewContainer.jsx b/app/hub/Views/PlusView/PlusViewContainer.jsx index 5d8332ddc..bcd3b0d67 100644 --- a/app/hub/Views/PlusView/PlusViewContainer.jsx +++ b/app/hub/Views/PlusView/PlusViewContainer.jsx @@ -43,12 +43,12 @@ class PlusViewContainer extends Component { * @return {JSX} JSX for rendering the Plus View of the Hub app */ render() { - const childProps = { - isPlus: this.props.user && this.props.user.subscriptionsPlus || false, - onPlusClick: this._sendPlusPing, - }; - - return ; + return ( + + ); } } diff --git a/app/hub/Views/PlusView/index.js b/app/hub/Views/PlusView/index.js index ee753c74b..cd19404b6 100644 --- a/app/hub/Views/PlusView/index.js +++ b/app/hub/Views/PlusView/index.js @@ -24,7 +24,7 @@ import { getUser } from '../../../Account/AccountActions'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.account); +const mapStateToProps = state => ({ ...state.account }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -33,10 +33,10 @@ const mapStateToProps = state => Object.assign({}, state.account); * @memberof TutorialContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, { + actions: bindActionCreators({ sendPing, - getUser, - }), dispatch), + getUser + }, dispatch), }); export default connect(mapStateToProps, mapDispatchToProps)(PlusViewContainer); diff --git a/app/hub/Views/ProductsView/index.js b/app/hub/Views/ProductsView/index.js index 977e4bf28..955600e4c 100644 --- a/app/hub/Views/ProductsView/index.js +++ b/app/hub/Views/ProductsView/index.js @@ -24,7 +24,7 @@ import { sendPing } from '../AppView/AppViewActions'; * @memberof TutorialContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, { sendPing }), dispatch), + actions: bindActionCreators({ sendPing }, dispatch), }); export default connect(null, mapDispatchToProps)(ProductsViewContainer); diff --git a/app/hub/Views/SetupView/SetupView.jsx b/app/hub/Views/SetupView/SetupView.jsx index 690d2b475..8db394a37 100644 --- a/app/hub/Views/SetupView/SetupView.jsx +++ b/app/hub/Views/SetupView/SetupView.jsx @@ -36,7 +36,7 @@ const SetupView = (props) => { path={step.path} render={() => (
- +
)} diff --git a/app/hub/Views/SetupView/SetupViewReducer.js b/app/hub/Views/SetupView/SetupViewReducer.js index e17dcf514..46c5c51a1 100644 --- a/app/hub/Views/SetupView/SetupViewReducer.js +++ b/app/hub/Views/SetupView/SetupViewReducer.js @@ -32,9 +32,7 @@ function SetupViewReducer(state = initialState, action) { case GET_SETUP_SHOW_WARNING_OVERRIDE: // Same as SET_SETUP_SHOW_WARNING_OVERRIDE case SET_SETUP_SHOW_WARNING_OVERRIDE: { const { setup_show_warning_override } = action.data; - return Object.assign({}, state, { - setup: Object.assign({}, state.setup, { setup_show_warning_override }), - }); + return { ...state, setup: { ...state.setup, setup_show_warning_override } }; } case INIT_SETUP_PROPS: { const { @@ -56,7 +54,8 @@ function SetupViewReducer(state = initialState, action) { textNext, textDone, } = navigation; - return Object.assign({}, state, { + return { + ...state, setup: { navigation: { activeIndex, @@ -74,8 +73,8 @@ function SetupViewReducer(state = initialState, action) { enable_smart_block, enable_ghostery_rewards, enable_human_web, - }, - }); + } + }; } case SET_SETUP_NAVIGATION: { const { @@ -87,8 +86,10 @@ function SetupViewReducer(state = initialState, action) { textNext, textDone, } = action.data; - return Object.assign({}, state, { - setup: Object.assign({}, state.setup, { + return { + ...state, + setup: { + ...state.setup, navigation: { activeIndex, hrefPrev, @@ -97,51 +98,39 @@ function SetupViewReducer(state = initialState, action) { textPrev, textNext, textDone, - }, - }), - }); + } + } + }; } // Setup Blocking View case SET_BLOCKING_POLICY: { const { blockingPolicy } = action.data; - return Object.assign({}, state, { - setup: Object.assign({}, state.setup, { blockingPolicy }), - }); + return { ...state, setup: { ...state.setup, blockingPolicy } }; } // Setup Anti-Suite View case SET_ANTI_TRACKING: { const { enable_anti_tracking } = action.data; - return Object.assign({}, state, { - setup: Object.assign({}, state.setup, { enable_anti_tracking }), - }); + return { ...state, setup: { ...state.setup, enable_anti_tracking } }; } case SET_AD_BLOCK: { const { enable_ad_block } = action.data; - return Object.assign({}, state, { - setup: Object.assign({}, state.setup, { enable_ad_block }), - }); + return { ...state, setup: { ...state.setup, enable_ad_block } }; } case SET_SMART_BLOCK: { const { enable_smart_block } = action.data; - return Object.assign({}, state, { - setup: Object.assign({}, state.setup, { enable_smart_block }), - }); + return { ...state, setup: { ...state.setup, enable_smart_block } }; } case SET_GHOSTERY_REWARDS: { const { enable_ghostery_rewards } = action.data; - return Object.assign({}, state, { - setup: Object.assign({}, state.setup, { enable_ghostery_rewards }), - }); + return { ...state, setup: { ...state.setup, enable_ghostery_rewards } }; } // Setup Human Web View case SET_HUMAN_WEB: { const { enable_human_web } = action.data; - return Object.assign({}, state, { - setup: Object.assign({}, state.setup, { enable_human_web }), - }); + return { ...state, setup: { ...state.setup, enable_human_web } }; } default: return state; diff --git a/app/hub/Views/SetupView/index.js b/app/hub/Views/SetupView/index.js index ab86ba273..5bd10681d 100644 --- a/app/hub/Views/SetupView/index.js +++ b/app/hub/Views/SetupView/index.js @@ -18,15 +18,15 @@ import { withRouter } from 'react-router-dom'; import SetupViewContainer from './SetupViewContainer'; import SetupViewReducer from './SetupViewReducer'; import * as SetupViewActions from './SetupViewActions'; -import { setBlockingPolicy } from '../SetupViews/SetupBlockingView/SetupBlockingViewActions'; +import setBlockingPolicy from '../SetupViews/SetupBlockingView/SetupBlockingViewActions'; import { setAntiTracking, setAdBlock, setSmartBlocking, setGhosteryRewards } from '../SetupViews/SetupAntiSuiteView/SetupAntiSuiteViewActions'; -import { setHumanWeb } from '../SetupViews/SetupHumanWebView/SetupHumanWebViewActions'; -import { setSetupComplete } from '../SetupViews/SetupDoneView/SetupDoneViewActions'; +import setHumanWeb from '../SetupViews/SetupHumanWebView/SetupHumanWebViewActions'; +import setSetupComplete from '../SetupViews/SetupDoneView/SetupDoneViewActions'; /** * Map redux store state properties to the component's own properties. @@ -34,7 +34,7 @@ import { setSetupComplete } from '../SetupViews/SetupDoneView/SetupDoneViewActio * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.setup, state.account); +const mapStateToProps = state => ({ ...state.setup, ...state.account }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -43,15 +43,16 @@ const mapStateToProps = state => Object.assign({}, state.setup, state.account); * @memberof SetupContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, SetupViewActions, { + actions: bindActionCreators({ + ...SetupViewActions, setBlockingPolicy, setAntiTracking, setAdBlock, setSmartBlocking, setGhosteryRewards, setHumanWeb, - setSetupComplete, - }), dispatch), + setSetupComplete + }, dispatch), }); export const reducer = SetupViewReducer; diff --git a/app/hub/Views/SetupViews/SetupAntiSuiteView/index.js b/app/hub/Views/SetupViews/SetupAntiSuiteView/index.js index d07fd0ecc..9d5dfcf5d 100644 --- a/app/hub/Views/SetupViews/SetupAntiSuiteView/index.js +++ b/app/hub/Views/SetupViews/SetupAntiSuiteView/index.js @@ -24,7 +24,7 @@ import { setSetupStep, setSetupNavigation } from '../../SetupView/SetupViewActio * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.setup); +const mapStateToProps = state => ({ ...state.setup }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -33,10 +33,11 @@ const mapStateToProps = state => Object.assign({}, state.setup); * @memberof SetupContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, SetupAntiSuiteViewActions, { + actions: bindActionCreators({ + ...SetupAntiSuiteViewActions, setSetupStep, - setSetupNavigation, - }), dispatch), + setSetupNavigation + }, dispatch), }); export default connect(mapStateToProps, mapDispatchToProps)(SetupAntiSuiteViewContainer); diff --git a/app/hub/Views/SetupViews/SetupBlockingDropdown/index.js b/app/hub/Views/SetupViews/SetupBlockingDropdown/index.js index 3eedd4039..2c9066551 100644 --- a/app/hub/Views/SetupViews/SetupBlockingDropdown/index.js +++ b/app/hub/Views/SetupViews/SetupBlockingDropdown/index.js @@ -24,7 +24,7 @@ import * as SettingsActions from '../../../../panel/actions/SettingsActions'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.settings); +const mapStateToProps = state => ({ ...state.settings }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -33,7 +33,7 @@ const mapStateToProps = state => Object.assign({}, state.settings); * @memberof SetupContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, SettingsActions), dispatch), + actions: bindActionCreators({ ...SettingsActions }, dispatch), }); export default withRouter(connect(mapStateToProps, mapDispatchToProps)(SetupBlockingDropdownContainer)); diff --git a/app/hub/Views/SetupViews/SetupBlockingView/SetupBlockingViewActions.js b/app/hub/Views/SetupViews/SetupBlockingView/SetupBlockingViewActions.js index ce9eb31b9..de4b436ed 100644 --- a/app/hub/Views/SetupViews/SetupBlockingView/SetupBlockingViewActions.js +++ b/app/hub/Views/SetupViews/SetupBlockingView/SetupBlockingViewActions.js @@ -14,7 +14,7 @@ import { log, sendMessageInPromise } from '../../../utils'; import { SET_BLOCKING_POLICY } from '../../SetupView/SetupViewConstants'; -export function setBlockingPolicy(actionData) { +export default function setBlockingPolicy(actionData) { return function(dispatch) { return sendMessageInPromise(SET_BLOCKING_POLICY, actionData).then((data) => { dispatch({ diff --git a/app/hub/Views/SetupViews/SetupBlockingView/__tests__/SetupBlockingViewActions.test.js b/app/hub/Views/SetupViews/SetupBlockingView/__tests__/SetupBlockingViewActions.test.js index 23504c3db..cfa80c6f0 100644 --- a/app/hub/Views/SetupViews/SetupBlockingView/__tests__/SetupBlockingViewActions.test.js +++ b/app/hub/Views/SetupViews/SetupBlockingView/__tests__/SetupBlockingViewActions.test.js @@ -14,7 +14,7 @@ import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import * as utils from '../../../../utils'; -import * as SetupBlockingViewActions from '../SetupBlockingViewActions'; +import setBlockingPolicy from '../SetupBlockingViewActions'; import { SET_BLOCKING_POLICY } from '../../../SetupView/SetupViewConstants'; const middlewares = [thunk]; @@ -39,7 +39,7 @@ describe('app/hub/Views/SetupViews/SetupBlockingView actions', () => { const data = testData; const expectedPayload = { data, type: SET_BLOCKING_POLICY }; - return store.dispatch(SetupBlockingViewActions.setBlockingPolicy(data)).then(() => { + return store.dispatch(setBlockingPolicy(data)).then(() => { const actions = store.getActions(); expect(actions).toEqual([expectedPayload]); }); diff --git a/app/hub/Views/SetupViews/SetupBlockingView/index.js b/app/hub/Views/SetupViews/SetupBlockingView/index.js index 2c4e76a68..383bda7ff 100644 --- a/app/hub/Views/SetupViews/SetupBlockingView/index.js +++ b/app/hub/Views/SetupViews/SetupBlockingView/index.js @@ -16,7 +16,7 @@ import { bindActionCreators } from 'redux'; import { withRouter } from 'react-router-dom'; import SetupBlockingViewContainer from './SetupBlockingViewContainer'; -import * as SetupBlockingViewActions from './SetupBlockingViewActions'; +import setBlockingPolicy from './SetupBlockingViewActions'; import { setSetupStep, setSetupNavigation } from '../../SetupView/SetupViewActions'; /** @@ -25,7 +25,7 @@ import { setSetupStep, setSetupNavigation } from '../../SetupView/SetupViewActio * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.setup); +const mapStateToProps = state => ({ ...state.setup }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -34,10 +34,11 @@ const mapStateToProps = state => Object.assign({}, state.setup); * @memberof SetupContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, SetupBlockingViewActions, { + actions: bindActionCreators({ + setBlockingPolicy, setSetupStep, - setSetupNavigation, - }), dispatch), + setSetupNavigation + }, dispatch), }); export default withRouter(connect(mapStateToProps, mapDispatchToProps)(SetupBlockingViewContainer)); diff --git a/app/hub/Views/SetupViews/SetupDoneView/SetupDoneViewActions.js b/app/hub/Views/SetupViews/SetupDoneView/SetupDoneViewActions.js index 10ce3e7b4..8c11c0d6e 100644 --- a/app/hub/Views/SetupViews/SetupDoneView/SetupDoneViewActions.js +++ b/app/hub/Views/SetupViews/SetupDoneView/SetupDoneViewActions.js @@ -14,7 +14,7 @@ import { log, sendMessageInPromise } from '../../../utils'; import { SET_SETUP_COMPLETE } from '../../SetupView/SetupViewConstants'; -export function setSetupComplete(actionData) { +export default function setSetupComplete(actionData) { return function(dispatch) { return sendMessageInPromise(SET_SETUP_COMPLETE, actionData).then((data) => { dispatch({ diff --git a/app/hub/Views/SetupViews/SetupDoneView/__tests__/SetupDoneViewActions.test.js b/app/hub/Views/SetupViews/SetupDoneView/__tests__/SetupDoneViewActions.test.js index 5c66ecd65..1e8a99a74 100644 --- a/app/hub/Views/SetupViews/SetupDoneView/__tests__/SetupDoneViewActions.test.js +++ b/app/hub/Views/SetupViews/SetupDoneView/__tests__/SetupDoneViewActions.test.js @@ -14,7 +14,7 @@ import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import * as utils from '../../../../utils'; -import * as SetupDoneViewActions from '../SetupDoneViewActions'; +import setSetupComplete from '../SetupDoneViewActions'; import { SET_SETUP_COMPLETE } from '../../../SetupView/SetupViewConstants'; const middlewares = [thunk]; @@ -39,7 +39,7 @@ describe('app/hub/Views/SetupViews/SetupDoneView actions', () => { const data = testData; const expectedPayload = { data, type: SET_SETUP_COMPLETE }; - return store.dispatch(SetupDoneViewActions.setSetupComplete(data)).then(() => { + return store.dispatch(setSetupComplete(data)).then(() => { const actions = store.getActions(); expect(actions).toEqual([expectedPayload]); }); diff --git a/app/hub/Views/SetupViews/SetupDoneView/index.js b/app/hub/Views/SetupViews/SetupDoneView/index.js index bcce6c53d..47199b305 100644 --- a/app/hub/Views/SetupViews/SetupDoneView/index.js +++ b/app/hub/Views/SetupViews/SetupDoneView/index.js @@ -15,7 +15,7 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import SetupDoneViewContainer from './SetupDoneViewContainer'; -import * as SetupDoneViewActions from './SetupDoneViewActions'; +import setSetupComplete from './SetupDoneViewActions'; import { setSetupStep, setSetupNavigation } from '../../SetupView/SetupViewActions'; /** @@ -24,7 +24,7 @@ import { setSetupStep, setSetupNavigation } from '../../SetupView/SetupViewActio * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.setup); +const mapStateToProps = state => ({ ...state.setup }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -33,10 +33,11 @@ const mapStateToProps = state => Object.assign({}, state.setup); * @memberof SetupContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, SetupDoneViewActions, { + actions: bindActionCreators({ + setSetupComplete, setSetupStep, - setSetupNavigation, - }), dispatch), + setSetupNavigation + }, dispatch), }); export default connect(mapStateToProps, mapDispatchToProps)(SetupDoneViewContainer); diff --git a/app/hub/Views/SetupViews/SetupHumanWebView/SetupHumanWebViewActions.js b/app/hub/Views/SetupViews/SetupHumanWebView/SetupHumanWebViewActions.js index 16cf28b1a..b18500b8a 100644 --- a/app/hub/Views/SetupViews/SetupHumanWebView/SetupHumanWebViewActions.js +++ b/app/hub/Views/SetupViews/SetupHumanWebView/SetupHumanWebViewActions.js @@ -14,7 +14,7 @@ import { log, sendMessageInPromise } from '../../../utils'; import { SET_HUMAN_WEB } from '../../SetupView/SetupViewConstants'; -export function setHumanWeb(actionData) { +export default function setHumanWeb(actionData) { return function(dispatch) { return sendMessageInPromise(SET_HUMAN_WEB, actionData).then((data) => { dispatch({ diff --git a/app/hub/Views/SetupViews/SetupHumanWebView/SetupHumanWebViewContainer.jsx b/app/hub/Views/SetupViews/SetupHumanWebView/SetupHumanWebViewContainer.jsx index 3e6415082..e6bce8b7b 100644 --- a/app/hub/Views/SetupViews/SetupHumanWebView/SetupHumanWebViewContainer.jsx +++ b/app/hub/Views/SetupViews/SetupHumanWebView/SetupHumanWebViewContainer.jsx @@ -58,11 +58,12 @@ class SetupHumanWebViewContainer extends Component { * @return {JSX} JSX for rendering the Setup Human Web View of the Hub app */ render() { - const childProps = { - enableHumanWeb: this.props.setup.enable_human_web, - changeHumanWeb: this._handleToggle, - }; - return ; + return ( + + ); } } diff --git a/app/hub/Views/SetupViews/SetupHumanWebView/__tests__/SetupHumanWebViewActions.test.js b/app/hub/Views/SetupViews/SetupHumanWebView/__tests__/SetupHumanWebViewActions.test.js index e00a40c89..3b21c84be 100644 --- a/app/hub/Views/SetupViews/SetupHumanWebView/__tests__/SetupHumanWebViewActions.test.js +++ b/app/hub/Views/SetupViews/SetupHumanWebView/__tests__/SetupHumanWebViewActions.test.js @@ -14,7 +14,7 @@ import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import * as utils from '../../../../utils'; -import * as SetupHumanWebViewActions from '../SetupHumanWebViewActions'; +import setHumanWeb from '../SetupHumanWebViewActions'; import { SET_HUMAN_WEB } from '../../../SetupView/SetupViewConstants'; const middlewares = [thunk]; @@ -39,7 +39,7 @@ describe('app/hub/Views/SetupViews/SetupHumanWebView actions', () => { const data = testData; const expectedPayload = { data, type: SET_HUMAN_WEB }; - return store.dispatch(SetupHumanWebViewActions.setHumanWeb(data)).then(() => { + return store.dispatch(setHumanWeb(data)).then(() => { const actions = store.getActions(); expect(actions).toEqual([expectedPayload]); }); diff --git a/app/hub/Views/SetupViews/SetupHumanWebView/index.js b/app/hub/Views/SetupViews/SetupHumanWebView/index.js index 9b207c564..745d9904e 100644 --- a/app/hub/Views/SetupViews/SetupHumanWebView/index.js +++ b/app/hub/Views/SetupViews/SetupHumanWebView/index.js @@ -15,7 +15,7 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import SetupHumanWebViewContainer from './SetupHumanWebViewContainer'; -import * as SetupHumanWebViewActions from './SetupHumanWebViewActions'; +import setHumanWeb from './SetupHumanWebViewActions'; import { setSetupStep, setSetupNavigation } from '../../SetupView/SetupViewActions'; /** @@ -24,7 +24,7 @@ import { setSetupStep, setSetupNavigation } from '../../SetupView/SetupViewActio * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.setup); +const mapStateToProps = state => ({ ...state.setup }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -33,10 +33,11 @@ const mapStateToProps = state => Object.assign({}, state.setup); * @memberof SetupContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, SetupHumanWebViewActions, { + actions: bindActionCreators({ + setHumanWeb, setSetupStep, setSetupNavigation - }), dispatch), + }, dispatch), }); export default connect(mapStateToProps, mapDispatchToProps)(SetupHumanWebViewContainer); diff --git a/app/hub/Views/SetupViews/SetupNavigation/SetupNavigationContainer.jsx b/app/hub/Views/SetupViews/SetupNavigation/SetupNavigationContainer.jsx index 3a55f163a..072ba9d07 100644 --- a/app/hub/Views/SetupViews/SetupNavigation/SetupNavigationContainer.jsx +++ b/app/hub/Views/SetupViews/SetupNavigation/SetupNavigationContainer.jsx @@ -22,12 +22,19 @@ import { SteppedNavigation } from '../../../../shared-components'; */ const SetupNavigationContainer = (props) => { const { totalSteps, setup } = props; - const childProps = { - totalSteps, - ...setup.navigation, - }; - return ; + return ( + + ); }; // PropTypes ensure we pass required props of the correct type diff --git a/app/hub/Views/SetupViews/SetupNavigation/index.js b/app/hub/Views/SetupViews/SetupNavigation/index.js index 9f40ac618..cc9ae5f59 100644 --- a/app/hub/Views/SetupViews/SetupNavigation/index.js +++ b/app/hub/Views/SetupViews/SetupNavigation/index.js @@ -20,6 +20,6 @@ import SetupNavigationContainer from './SetupNavigationContainer'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.setup); +const mapStateToProps = state => ({ ...state.setup }); export default connect(mapStateToProps)(SetupNavigationContainer); diff --git a/app/hub/Views/SideNavigationView/SideNavigationViewContainer.jsx b/app/hub/Views/SideNavigationView/SideNavigationViewContainer.jsx index 1388a5ea7..c91e2cda3 100644 --- a/app/hub/Views/SideNavigationView/SideNavigationViewContainer.jsx +++ b/app/hub/Views/SideNavigationView/SideNavigationViewContainer.jsx @@ -68,13 +68,14 @@ class SideNavigationViewContainer extends Component { icon: 'profile', }, ]; - const childProps = { - menuItems, - bottomItems, - disableNav: disableRegEx.test(location.pathname), - }; - return ; + return ( + + ); } } diff --git a/app/hub/Views/SideNavigationView/index.js b/app/hub/Views/SideNavigationView/index.js index adf9d60dc..da287bf7d 100644 --- a/app/hub/Views/SideNavigationView/index.js +++ b/app/hub/Views/SideNavigationView/index.js @@ -25,7 +25,7 @@ import { setToast } from '../AppView/AppViewActions'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.account); +const mapStateToProps = state => ({ ...state.account }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -34,11 +34,11 @@ const mapStateToProps = state => Object.assign({}, state.account); * @memberof SetupContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, { + actions: bindActionCreators({ setToast, getUser, - logout, - }), dispatch), + logout + }, dispatch), }); export default withRouter(connect(mapStateToProps, mapDispatchToProps)(SideNavigationViewContainer)); diff --git a/app/hub/Views/TutorialView/TutorialViewReducer.js b/app/hub/Views/TutorialView/TutorialViewReducer.js index 3a4fc9016..cbbf8bed1 100644 --- a/app/hub/Views/TutorialView/TutorialViewReducer.js +++ b/app/hub/Views/TutorialView/TutorialViewReducer.js @@ -27,7 +27,8 @@ function TutorialViewReducer(state = initialState, action) { textNext, textDone, } = action.data.navigation; - return Object.assign({}, state, { + return { + ...state, tutorial: { navigation: { activeIndex, @@ -38,8 +39,8 @@ function TutorialViewReducer(state = initialState, action) { textNext, textDone, } - }, - }); + } + }; } case SET_TUTORIAL_NAVIGATION: { const { @@ -51,8 +52,10 @@ function TutorialViewReducer(state = initialState, action) { textNext, textDone, } = action.data; - return Object.assign({}, state, { - tutorial: Object.assign({}, state.tutorial, { + return { + ...state, + tutorial: { + ...state.tutorial, navigation: { activeIndex, hrefPrev, @@ -61,9 +64,9 @@ function TutorialViewReducer(state = initialState, action) { textPrev, textNext, textDone, - }, - }), - }); + } + } + }; } default: return state; diff --git a/app/hub/Views/TutorialView/index.js b/app/hub/Views/TutorialView/index.js index f9c1a0157..1b2d90d3b 100644 --- a/app/hub/Views/TutorialView/index.js +++ b/app/hub/Views/TutorialView/index.js @@ -26,7 +26,7 @@ import { sendPing } from '../AppView/AppViewActions'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.tutorial); +const mapStateToProps = state => ({ ...state.tutorial }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -35,7 +35,7 @@ const mapStateToProps = state => Object.assign({}, state.tutorial); * @memberof SetupContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, TutorialViewActions, { sendPing }), dispatch), + actions: bindActionCreators({ ...TutorialViewActions, sendPing }, dispatch), }); export const reducer = TutorialViewReducer; diff --git a/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteViewActions.js b/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteViewActions.js index 019754ba7..ddf87b787 100644 --- a/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteViewActions.js +++ b/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteViewActions.js @@ -14,7 +14,7 @@ import { log, sendMessageInPromise } from '../../../utils'; import { SET_TUTORIAL_COMPLETE } from '../../TutorialView/TutorialViewConstants'; -export function setTutorialComplete(actionData) { +export default function setTutorialComplete(actionData) { return function(dispatch) { return sendMessageInPromise(SET_TUTORIAL_COMPLETE, actionData).then((data) => { dispatch({ diff --git a/app/hub/Views/TutorialViews/TutorialAntiSuiteView/__test__/TutorialAntiSuiteViewActions.test.js b/app/hub/Views/TutorialViews/TutorialAntiSuiteView/__test__/TutorialAntiSuiteViewActions.test.js index 7864a354a..d0866e007 100644 --- a/app/hub/Views/TutorialViews/TutorialAntiSuiteView/__test__/TutorialAntiSuiteViewActions.test.js +++ b/app/hub/Views/TutorialViews/TutorialAntiSuiteView/__test__/TutorialAntiSuiteViewActions.test.js @@ -14,7 +14,7 @@ import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import * as utils from '../../../../utils'; -import * as TutorialAntiSuiteViewActions from '../TutorialAntiSuiteViewActions'; +import setTutorialComplete from '../TutorialAntiSuiteViewActions'; import { SET_TUTORIAL_COMPLETE } from '../../../TutorialView/TutorialViewConstants'; const middlewares = [thunk]; @@ -39,7 +39,7 @@ describe('app/hub/Views/TutorialViews/TutorialAntiSuiteView actions', () => { const data = testData; const expectedPayload = { data, type: SET_TUTORIAL_COMPLETE }; - return store.dispatch(TutorialAntiSuiteViewActions.setTutorialComplete(data)).then(() => { + return store.dispatch(setTutorialComplete(data)).then(() => { const actions = store.getActions(); expect(actions).toEqual([expectedPayload]); }); diff --git a/app/hub/Views/TutorialViews/TutorialAntiSuiteView/index.js b/app/hub/Views/TutorialViews/TutorialAntiSuiteView/index.js index c0faf59dd..df5d858e3 100644 --- a/app/hub/Views/TutorialViews/TutorialAntiSuiteView/index.js +++ b/app/hub/Views/TutorialViews/TutorialAntiSuiteView/index.js @@ -15,7 +15,7 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import TutorialAntiSuiteViewContainer from './TutorialAntiSuiteViewContainer'; -import * as TutorialAntiSuiteViewActions from './TutorialAntiSuiteViewActions'; +import setTutorialComplete from './TutorialAntiSuiteViewActions'; import { setTutorialNavigation } from '../../TutorialView/TutorialViewActions'; /** @@ -24,7 +24,7 @@ import { setTutorialNavigation } from '../../TutorialView/TutorialViewActions'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.tutorial); +const mapStateToProps = state => ({ ...state.tutorial }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -33,7 +33,7 @@ const mapStateToProps = state => Object.assign({}, state.tutorial); * @memberof TutorialContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, TutorialAntiSuiteViewActions, { setTutorialNavigation }), dispatch), + actions: bindActionCreators({ setTutorialComplete, setTutorialNavigation }, dispatch), }); export default connect(mapStateToProps, mapDispatchToProps)(TutorialAntiSuiteViewContainer); diff --git a/app/hub/Views/TutorialViews/TutorialBlockingView/index.js b/app/hub/Views/TutorialViews/TutorialBlockingView/index.js index a2f19348a..9e8be0d15 100644 --- a/app/hub/Views/TutorialViews/TutorialBlockingView/index.js +++ b/app/hub/Views/TutorialViews/TutorialBlockingView/index.js @@ -23,7 +23,7 @@ import { setTutorialNavigation } from '../../TutorialView/TutorialViewActions'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.tutorial); +const mapStateToProps = state => ({ ...state.tutorial }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -32,7 +32,7 @@ const mapStateToProps = state => Object.assign({}, state.tutorial); * @memberof TutorialContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, { setTutorialNavigation }), dispatch), + actions: bindActionCreators({ setTutorialNavigation }, dispatch), }); export default connect(mapStateToProps, mapDispatchToProps)(TutorialBlockingViewContainer); diff --git a/app/hub/Views/TutorialViews/TutorialLayoutView/index.js b/app/hub/Views/TutorialViews/TutorialLayoutView/index.js index 9929161b9..14f8e4bdf 100644 --- a/app/hub/Views/TutorialViews/TutorialLayoutView/index.js +++ b/app/hub/Views/TutorialViews/TutorialLayoutView/index.js @@ -23,7 +23,7 @@ import { setTutorialNavigation } from '../../TutorialView/TutorialViewActions'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.tutorial); +const mapStateToProps = state => ({ ...state.tutorial }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -32,7 +32,7 @@ const mapStateToProps = state => Object.assign({}, state.tutorial); * @memberof TutorialContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, { setTutorialNavigation }), dispatch), + actions: bindActionCreators({ setTutorialNavigation }, dispatch), }); export default connect(mapStateToProps, mapDispatchToProps)(TutorialLayoutViewContainer); diff --git a/app/hub/Views/TutorialViews/TutorialNavigation/TutorialNavigationContainer.jsx b/app/hub/Views/TutorialViews/TutorialNavigation/TutorialNavigationContainer.jsx index f64c4f6d1..ed57d61eb 100644 --- a/app/hub/Views/TutorialViews/TutorialNavigation/TutorialNavigationContainer.jsx +++ b/app/hub/Views/TutorialViews/TutorialNavigation/TutorialNavigationContainer.jsx @@ -22,11 +22,19 @@ import { SteppedNavigation } from '../../../../shared-components'; */ const TutorialNavigationContainer = (props) => { const { totalSteps, tutorial } = props; - const childProps = { - totalSteps, - ...tutorial.navigation, - }; - return ; + + return ( + + ); }; // PropTypes ensure we pass required props of the correct type diff --git a/app/hub/Views/TutorialViews/TutorialNavigation/index.js b/app/hub/Views/TutorialViews/TutorialNavigation/index.js index c4e9ae922..f83a26627 100644 --- a/app/hub/Views/TutorialViews/TutorialNavigation/index.js +++ b/app/hub/Views/TutorialViews/TutorialNavigation/index.js @@ -20,6 +20,6 @@ import TutorialNavigationContainer from './TutorialNavigationContainer'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.tutorial); +const mapStateToProps = state => ({ ...state.tutorial }); export default connect(mapStateToProps)(TutorialNavigationContainer); diff --git a/app/hub/Views/TutorialViews/TutorialTrackerListView/index.js b/app/hub/Views/TutorialViews/TutorialTrackerListView/index.js index bc09a915a..677b18f4f 100644 --- a/app/hub/Views/TutorialViews/TutorialTrackerListView/index.js +++ b/app/hub/Views/TutorialViews/TutorialTrackerListView/index.js @@ -23,7 +23,7 @@ import { setTutorialNavigation } from '../../TutorialView/TutorialViewActions'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.tutorial); +const mapStateToProps = state => ({ ...state.tutorial }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -32,7 +32,7 @@ const mapStateToProps = state => Object.assign({}, state.tutorial); * @memberof TutorialContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, { setTutorialNavigation }), dispatch), + actions: bindActionCreators({ setTutorialNavigation }, dispatch), }); export default connect(mapStateToProps, mapDispatchToProps)(TutorialTrackerListViewContainer); diff --git a/app/hub/Views/TutorialViews/TutorialTrustView/index.js b/app/hub/Views/TutorialViews/TutorialTrustView/index.js index 56ab74c4b..f839f8805 100644 --- a/app/hub/Views/TutorialViews/TutorialTrustView/index.js +++ b/app/hub/Views/TutorialViews/TutorialTrustView/index.js @@ -23,7 +23,7 @@ import { setTutorialNavigation } from '../../TutorialView/TutorialViewActions'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.tutorial); +const mapStateToProps = state => ({ ...state.tutorial }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -32,7 +32,7 @@ const mapStateToProps = state => Object.assign({}, state.tutorial); * @memberof TutorialContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, { setTutorialNavigation }), dispatch), + actions: bindActionCreators({ setTutorialNavigation }, dispatch), }); export default connect(mapStateToProps, mapDispatchToProps)(TutorialTrustViewContainer); diff --git a/app/hub/Views/TutorialViews/TutorialVideoView/index.js b/app/hub/Views/TutorialViews/TutorialVideoView/index.js index bd4d12e0b..3171af418 100644 --- a/app/hub/Views/TutorialViews/TutorialVideoView/index.js +++ b/app/hub/Views/TutorialViews/TutorialVideoView/index.js @@ -23,7 +23,7 @@ import { setTutorialNavigation } from '../../TutorialView/TutorialViewActions'; * @return {function} this function returns a plain object, which will be merged into the component's props * @memberof HubContainers */ -const mapStateToProps = state => Object.assign({}, state.tutorial); +const mapStateToProps = state => ({ ...state.tutorial }); /** * Bind the component's action creators using Redux's bindActionCreators. @@ -32,7 +32,7 @@ const mapStateToProps = state => Object.assign({}, state.tutorial); * @memberof TutorialContainers */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, { setTutorialNavigation }), dispatch), + actions: bindActionCreators({ setTutorialNavigation }, dispatch), }); export default connect(mapStateToProps, mapDispatchToProps)(TutorialVideoViewContainer); diff --git a/app/licenses/License.jsx b/app/licenses/License.jsx index e6951aab5..8f2e737d2 100644 --- a/app/licenses/License.jsx +++ b/app/licenses/License.jsx @@ -33,7 +33,7 @@ class License extends React.Component { * Toggle expansion of a license full text. */ toggleLicenseText() { - this.setState({ expanded: !this.state.expanded }); + this.setState(prevState => ({ expanded: !prevState.expanded })); } /** diff --git a/app/licenses/Licenses.jsx b/app/licenses/Licenses.jsx index cd9aaf339..fb083fc9e 100644 --- a/app/licenses/Licenses.jsx +++ b/app/licenses/Licenses.jsx @@ -31,7 +31,7 @@ class Licenses extends React.Component { * Wrapper function for dangerouslySetInnerHTML. Provides extra security * @return {Object} */ - createFooterMarkup() { + static createFooterMarkup() { return { __html: t('license_footer') }; } @@ -60,7 +60,7 @@ class Licenses extends React.Component {
{ list }
@@ -275,13 +275,13 @@ class Tracker extends React.Component { ); } - _renderCliqzCookieStat(count) { return this._renderCliqzStat(count, 'cookie'); } + static _renderCliqzCookieStat(count) { return Tracker._renderCliqzStat(count, 'cookie'); } - _renderCliqzFingerprintStat(count) { return this._renderCliqzStat(count, 'fingerprint'); } + static _renderCliqzFingerprintStat(count) { return Tracker._renderCliqzStat(count, 'fingerprint'); } - _renderCliqzAdStat(count) { return this._renderCliqzStat(count, 'ad'); } + static _renderCliqzAdStat(count) { return Tracker._renderCliqzStat(count, 'ad'); } - _renderCliqzStat(count, type) { + static _renderCliqzStat(count, type) { const exactlyOne = count === 1; const label = exactlyOne ? t(`${type}`) : diff --git a/app/panel/components/BuildingBlocks/CliqzFeature.jsx b/app/panel/components/BuildingBlocks/CliqzFeature.jsx index b699e387a..353cf635c 100644 --- a/app/panel/components/BuildingBlocks/CliqzFeature.jsx +++ b/app/panel/components/BuildingBlocks/CliqzFeature.jsx @@ -46,15 +46,15 @@ class CliqzFeature extends React.Component { clickButton({ feature: `enable_${featureType}`, status: active, - text: this._getAlertText(active, type), + text: CliqzFeature._getAlertText(active, type), }); } - _getStatus(active) { + static _getStatus(active) { return active ? t('on') : t('off'); } - _getTooltipBodyText(active, isTooltipBody, type) { + static _getTooltipBodyText(active, isTooltipBody, type) { if (!isTooltipBody) return false; if (active) { @@ -82,7 +82,7 @@ class CliqzFeature extends React.Component { } } - _getTooltipHeaderText(isTooltipHeader, type) { + static _getTooltipHeaderText(isTooltipHeader, type) { if (!isTooltipHeader) return false; switch (type) { @@ -97,7 +97,7 @@ class CliqzFeature extends React.Component { } } - _getAlertText(active, type) { + static _getAlertText(active, type) { return active ? t(`alert_${type}_off`) : t(`alert_${type}_on`); @@ -145,11 +145,11 @@ class CliqzFeature extends React.Component { return (
-
{this._getStatus(active)}
+
{CliqzFeature._getStatus(active)}
diff --git a/app/panel/components/BuildingBlocks/DonutGraph.jsx b/app/panel/components/BuildingBlocks/DonutGraph.jsx index 67a9bd90a..dec7cb5da 100644 --- a/app/panel/components/BuildingBlocks/DonutGraph.jsx +++ b/app/panel/components/BuildingBlocks/DonutGraph.jsx @@ -142,14 +142,14 @@ class DonutGraph extends React.Component { /** * Helper function that calculates domain value for greyscale / redscale rendering */ - getTone(catCount, catIndex) { - return catCount > 1 ? 100 / (catCount - 1) * catIndex * 0.01 : 0; + static getTone(catCount, catIndex) { + return catCount > 1 ? (100 / (catCount - 1)) * catIndex * 0.01 : 0; } /** * Helper to retrieve a category's tooltip from the DOM */ - grabTooltip(d) { + static grabTooltip(d) { return document.getElementById(`${d.data.id}_tooltip`); } @@ -264,9 +264,11 @@ class DonutGraph extends React.Component { this._endAngles.set(catId, d.endAngle); return function(t) { - d.startAngle = lerpStartAngle(t); - d.endAngle = lerpEndAngle(t); - return trackerArc(d); + return trackerArc({ + ...d, + startAngle: lerpStartAngle(t), + endAngle: lerpEndAngle(t), + }); }; }); @@ -276,10 +278,10 @@ class DonutGraph extends React.Component { .append('path') .style('fill', (d, i) => { if (renderGreyscale) { - return this.colors.greyscale(this.getTone(categoryCount, i)); + return this.colors.greyscale(DonutGraph.getTone(categoryCount, i)); } if (renderRedscale) { - return this.colors.redscale(this.getTone(categoryCount, i)); + return this.colors.redscale(DonutGraph.getTone(categoryCount, i)); } return this.colors.regular(d.data.id); }) @@ -293,7 +295,7 @@ class DonutGraph extends React.Component { const centroid = trackerArc.centroid(d); const pX = centroid[0] + this.donutRadius; const pY = centroid[1] + this.donutRadius; - const tooltip = this.grabTooltip(d); + const tooltip = DonutGraph.grabTooltip(d); if (tooltip) { tooltip.style.left = `${pX - (tooltip.offsetWidth / 2)}px`; tooltip.style.top = `${pY - (tooltip.offsetHeight + 8)}px`; @@ -301,7 +303,7 @@ class DonutGraph extends React.Component { } }) .on('mouseout', (d) => { - const tooltip = this.grabTooltip(d); + const tooltip = DonutGraph.grabTooltip(d); if (tooltip) { tooltip.classList.remove('DonutGraph__tooltip--show'); } @@ -320,8 +322,10 @@ class DonutGraph extends React.Component { const i = interpolate(d.startAngle, d.endAngle); return function(t) { - d.endAngle = i(t); - return trackerArc(d); + return trackerArc({ + ...d, + endAngle: i(t) + }); }; }) .ease(easeLinear); diff --git a/app/panel/components/BuildingBlocks/GhosteryFeature.jsx b/app/panel/components/BuildingBlocks/GhosteryFeature.jsx index afd498a35..8d127474e 100644 --- a/app/panel/components/BuildingBlocks/GhosteryFeature.jsx +++ b/app/panel/components/BuildingBlocks/GhosteryFeature.jsx @@ -40,7 +40,7 @@ class GhosteryFeature extends React.Component { this.props.handleClick(this.props.type); } - _getButtonText(sitePolicy, showText, type) { + static _getButtonText(sitePolicy, showText, type) { if (!showText) { return ''; } @@ -59,7 +59,7 @@ class GhosteryFeature extends React.Component { } } - _getTooltipText(sitePolicy, type) { + static _getTooltipText(sitePolicy, type) { switch (type) { case 'trust': return (sitePolicy === WHITELISTED ? @@ -74,7 +74,7 @@ class GhosteryFeature extends React.Component { } } - _isFeatureActive(type, sitePolicy) { + static _isFeatureActive(type, sitePolicy) { switch (type) { case 'trust': return sitePolicy === WHITELISTED; @@ -96,7 +96,7 @@ class GhosteryFeature extends React.Component { type } = this.props; - const active = this._isFeatureActive(type, sitePolicy); + const active = GhosteryFeature._isFeatureActive(type, sitePolicy); // TODO Foundation dependency: button const ghosteryFeatureClassNames = ClassNames( 'button', @@ -120,10 +120,10 @@ class GhosteryFeature extends React.Component {
- {this._getButtonText(sitePolicy, showText, type)} + {GhosteryFeature._getButtonText(sitePolicy, showText, type)} - +
); } diff --git a/app/panel/components/BuildingBlocks/StatsGraph.jsx b/app/panel/components/BuildingBlocks/StatsGraph.jsx index 80e89ec4d..5b9b34088 100644 --- a/app/panel/components/BuildingBlocks/StatsGraph.jsx +++ b/app/panel/components/BuildingBlocks/StatsGraph.jsx @@ -14,7 +14,7 @@ import { isEqual } from 'underscore'; import React from 'react'; import * as D3 from 'd3'; -import { ThemeContext } from '../../contexts/ThemeContext'; +import ThemeContext from '../../contexts/ThemeContext'; /** * Generates an animated graph displaying locally stored stats * @memberof PanelBuildingBlocks @@ -79,7 +79,8 @@ class StatsGraph extends React.Component { } const data = JSON.parse(JSON.stringify(this.props.data)); - data.forEach((entry) => { + data.forEach((e) => { + const entry = e; entry.date = parseMonth(entry.date); }); diff --git a/app/panel/components/BuildingBlocks/ToggleSlider.jsx b/app/panel/components/BuildingBlocks/ToggleSlider.jsx index 1f467cbca..185e4ee5b 100644 --- a/app/panel/components/BuildingBlocks/ToggleSlider.jsx +++ b/app/panel/components/BuildingBlocks/ToggleSlider.jsx @@ -50,9 +50,7 @@ class ToggleSlider extends React.Component { if (typeof this.props.onChange === 'function') { this.props.onChange(event); } else { - this.setState({ - checked: !this.state.checked, - }); + this.setState(prevState => ({ checked: !prevState.checked })); } } diff --git a/app/panel/components/DetailMenu.jsx b/app/panel/components/DetailMenu.jsx index 9443029d5..275174694 100644 --- a/app/panel/components/DetailMenu.jsx +++ b/app/panel/components/DetailMenu.jsx @@ -41,12 +41,14 @@ class DetailMenu extends React.Component { * @param {Object} event click event */ setActiveTab(event) { - const menu = Object.assign({}, this.state.menu); const selectionId = event.currentTarget.id; - - Object.keys(menu).forEach((key) => { menu[key] = selectionId === key; }); sendMessage('ping', DetailMenu.pings[selectionId]); - this.setState({ menu }); + + this.setState((prevState) => { + const menu = { ...prevState.menu }; + Object.keys(menu).forEach((key) => { menu[key] = selectionId === key; }); + return { menu }; + }); } /** diff --git a/app/panel/components/Header.jsx b/app/panel/components/Header.jsx index 5f31d701a..ac3e19448 100644 --- a/app/panel/components/Header.jsx +++ b/app/panel/components/Header.jsx @@ -65,7 +65,7 @@ class Header extends React.Component { * Handles toggling the drop-down pane open/closed */ toggleDropdown = () => { - this.setState({ dropdownOpen: !this.state.dropdownOpen }); + this.setState(prevState => ({ dropdownOpen: !prevState.dropdownOpen })); } handleSignin = () => { @@ -109,7 +109,7 @@ class Header extends React.Component { } let accountIcon; - if (!loggedIn || loggedIn && user && !user.emailValidated) { + if (!loggedIn || (loggedIn && user && !user.emailValidated)) { accountIcon = (
diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index 77055f519..dc4321cf8 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -15,8 +15,8 @@ import React from 'react'; import { NavLink } from 'react-router-dom'; import Header from '../containers/HeaderContainer'; import PromoModalContainer from '../../shared-components/PromoModal/PromoModalContainer'; -import { ThemeContext } from '../contexts/ThemeContext'; -import { DynamicUIPortContext } from '../contexts/DynamicUIPortContext'; +import ThemeContext from '../contexts/ThemeContext'; +import DynamicUIPortContext from '../contexts/DynamicUIPortContext'; import { sendMessage } from '../utils/msg'; import { setTheme } from '../utils/utils'; diff --git a/app/panel/components/Rewards.jsx b/app/panel/components/Rewards.jsx index 3b70cc19d..9f8cd6c1e 100644 --- a/app/panel/components/Rewards.jsx +++ b/app/panel/components/Rewards.jsx @@ -15,7 +15,7 @@ import React, { Fragment } from 'react'; import ClassNames from 'classnames'; import { Route } from 'react-router-dom'; import { ToggleSlider } from './BuildingBlocks'; -import { DynamicUIPortContext } from '../contexts/DynamicUIPortContext'; +import DynamicUIPortContext from '../contexts/DynamicUIPortContext'; import { sendMessage } from '../utils/msg'; import globals from '../../../src/classes/Globals'; import { log } from '../../../src/utils/common'; @@ -45,7 +45,6 @@ class Rewards extends React.Component { // helper render functions this.renderRewardListComponent = this.renderRewardListComponent.bind(this); - this.handleFaqClick = this.handleFaqClick.bind(this); this.handlePortMessage = this.handlePortMessage.bind(this); @@ -141,7 +140,7 @@ class Rewards extends React.Component { /** * Handles clicking the learn more button */ - handleFaqClick() { + static handleFaqClick() { sendMessage('openNewTab', { url: 'https://www.ghostery.com/faqs/what-new-ghostery-features-can-we-expect-in-the-future/', become_active: true, @@ -202,7 +201,7 @@ class Rewards extends React.Component { * Helper render function for Reward Icon SVG * @return {JSX} JSX for the Rewards Icon SVG */ - renderRewardSvg() { + static renderRewardSvg() { return ( @@ -212,15 +211,15 @@ class Rewards extends React.Component { ); } - renderCLIQZtext() { + static renderCLIQZtext() { return (
- { this.renderRewardSvg() } + { Rewards.renderRewardSvg() }
{ t('panel_detail_rewards_cliqz_text') }

{ t('panel_detail_learn_more') }
@@ -228,19 +227,19 @@ class Rewards extends React.Component { ); } - renderRewardsTurnoffText() { + static renderRewardsTurnoffText() { return (
- { this.renderRewardSvg() } + { Rewards.renderRewardSvg() }
{ t('panel_detail_rewards_off') }
); } - renderRewardsNoneFoundText() { + static renderRewardsNoneFoundText() { return (
- { this.renderRewardSvg() } + { Rewards.renderRewardSvg() }
{ t('panel_detail_rewards_none_found') }
); @@ -251,9 +250,9 @@ class Rewards extends React.Component { * @return {JSX} JSX for the Rewards Items List */ renderRewardListComponent() { - if (IS_CLIQZ) { return this.renderCLIQZtext(); } + if (IS_CLIQZ) { return Rewards.renderCLIQZtext(); } const { enable_offers, is_expanded } = this.props; - if (!enable_offers) { return this.renderRewardsTurnoffText(); } + if (!enable_offers) { return Rewards.renderRewardsTurnoffText(); } const { shouldHideRewards, @@ -261,7 +260,7 @@ class Rewards extends React.Component { iframeHeight, rewardsCount, } = this.state; - if (shouldHideRewards) { return this.renderRewardsNoneFoundText(); } + if (shouldHideRewards) { return Rewards.renderRewardsNoneFoundText(); } const src = chrome.runtime.getURL('cliqz/offers-templates/control-center.html?cross-origin'); const text = t(`panel_rewards_view__reward${rewardsCount === 1 ? '' : 's'}`); diff --git a/app/panel/components/Settings.jsx b/app/panel/components/Settings.jsx index 52f528caa..25e613b63 100644 --- a/app/panel/components/Settings.jsx +++ b/app/panel/components/Settings.jsx @@ -24,7 +24,7 @@ import Notifications from './Settings/Notifications'; import OptIn from './Settings/OptIn'; import Purplebox from './Settings/Purplebox'; import Account from './Settings/Account'; -import { DynamicUIPortContext } from '../contexts/DynamicUIPortContext'; +import DynamicUIPortContext from '../contexts/DynamicUIPortContext'; /** * @class Implement base Settings view which routes navigation to all settings subviews * @memberof PanelClasses diff --git a/app/panel/components/Settings/TrustAndRestrict.jsx b/app/panel/components/Settings/TrustAndRestrict.jsx index d6e6371b8..183092754 100644 --- a/app/panel/components/Settings/TrustAndRestrict.jsx +++ b/app/panel/components/Settings/TrustAndRestrict.jsx @@ -43,15 +43,11 @@ class TrustAndRestrict extends React.Component { */ setActivePane(event) { this.showWarning(''); - const newMenuState = Object.assign({}, this.state.menu); - Object.keys(newMenuState).forEach((key) => { - if (key === event.currentTarget.id) { - newMenuState[key] = true; - } else { - newMenuState[key] = false; - } - }); - this.setState({ menu: newMenuState }); + const menu = { + showTrustedSites: event.currentTarget.id === 'showTrustedSites', + showRestrictedSites: event.currentTarget.id === 'showRestrictedSites', + }; + this.setState({ menu }); } /** @@ -120,7 +116,7 @@ class TrustAndRestrict extends React.Component { // Check for Validity if (pageHost.length >= 2083 - || !this.isValidUrlorWildcard(pageHost)) { + || !TrustAndRestrict.isValidUrlorWildcard(pageHost)) { this.showWarning(t('white_black_list_error_invalid_url')); return; } @@ -144,7 +140,7 @@ class TrustAndRestrict extends React.Component { } } - isValidUrlorWildcard(pageHost) { + static isValidUrlorWildcard(pageHost) { // Only allow valid host name characters, ':' for port numbers and '*' for wildcards const isSafePageHost = /^[a-zA-Z0-9-.:*]*$/; if (!isSafePageHost.test(pageHost)) { return false; } diff --git a/app/panel/components/Settings/__tests__/TrustAndRestrict.jsx b/app/panel/components/Settings/__tests__/TrustAndRestrict.jsx index 1904a38a6..299ebe5af 100644 --- a/app/panel/components/Settings/__tests__/TrustAndRestrict.jsx +++ b/app/panel/components/Settings/__tests__/TrustAndRestrict.jsx @@ -15,7 +15,6 @@ import React from 'react'; import renderer from 'react-test-renderer'; -import { shallow } from 'enzyme'; import { when } from 'jest-when'; import TrustAndRestrict from '../TrustAndRestrict'; @@ -32,124 +31,114 @@ describe('app/panel/components/Settings/TrustAndRestrict', () => { describe('app/panel/components/Settings/', () => { test('isValidUrlorWildcard should return true with url entered', () => { - const wrapper = shallow(); let input = 'ghostery.com'; - - let fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + let fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - let returnValue = wrapper.instance().isValidUrlorWildcard(input); + let returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(true); input = 'localhost:3000'; - fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - returnValue = wrapper.instance().isValidUrlorWildcard(input); + returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(true); }); test('isValidUrlorWildcard should return true with wildcard URL entered', () => { - const wrapper = shallow(); - let input = 'developer.*.org'; - let fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + let fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - let returnValue = wrapper.instance().isValidUrlorWildcard(input); + let returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(true); input = '*.com'; - fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - returnValue = wrapper.instance().isValidUrlorWildcard(input); + returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(true); input = '*'; - fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - returnValue = wrapper.instance().isValidUrlorWildcard(input); + returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(true); input = 'developer.*'; - fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - returnValue = wrapper.instance().isValidUrlorWildcard(input); + returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(true); input = '****'; - fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - returnValue = wrapper.instance().isValidUrlorWildcard(input); + returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(true); }); test('isValidUrlorWildcard should return false with wildcard URL entered', () => { - const wrapper = shallow(); - let input = ''; - let fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + let fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - let returnValue = wrapper.instance().isValidUrlorWildcard(input); + let returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(false); input = '+$@@#$*'; - fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - returnValue = wrapper.instance().isValidUrlorWildcard(input); + returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(false); input = 'αράδειγμα.δοκιμ.*'; - fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - returnValue = wrapper.instance().isValidUrlorWildcard(input); + returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(false); input = 'SELECT * FROM USERS'; - fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - returnValue = wrapper.instance().isValidUrlorWildcard(input); + returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(false); }); test('isValidUrlorWildcard should return false with regex entered', () => { - const wrapper = shallow(); - let input = ')'; - let fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + let fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - let returnValue = wrapper.instance().isValidUrlorWildcard(input); + let returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(false); input = '++'; - fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - returnValue = wrapper.instance().isValidUrlorWildcard(input); + returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(false); input = '/foo(?)/'; - fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - returnValue = wrapper.instance().isValidUrlorWildcard(input); + returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(false); }); test('isValidUrlorWildcard should return false with unsafe test entered', () => { - const wrapper = shallow(); - let input = '/^(\w+\s?)*$/'; - let fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + let fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - let returnValue = wrapper.instance().isValidUrlorWildcard(input); + let returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(false); input = '/^([0-9]+)*$/'; - fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - returnValue = wrapper.instance().isValidUrlorWildcard(input); + returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(false); input = '(x\w{1,10})+y'; - fn = jest.spyOn(wrapper.instance(), 'isValidUrlorWildcard'); + fn = jest.spyOn(TrustAndRestrict, 'isValidUrlorWildcard'); when(fn).calledWith(input); - returnValue = wrapper.instance().isValidUrlorWildcard(input); + returnValue = TrustAndRestrict.isValidUrlorWildcard(input); expect(returnValue).toBe(false); }); }); diff --git a/app/panel/components/Stats.jsx b/app/panel/components/Stats.jsx index 8ec7ac7c7..18a06d8a6 100644 --- a/app/panel/components/Stats.jsx +++ b/app/panel/components/Stats.jsx @@ -156,7 +156,7 @@ class Stats extends React.Component { if (!this._isPlus(this.props)) { return; } - const state = Object.assign({}, this.state); + const state = { ...this.state }; const { selection } = state; if (event.currentTarget.id !== selection.view) { selection.view = event.currentTarget.id; @@ -180,7 +180,7 @@ class Stats extends React.Component { if (!this._isPlus(this.props)) { return; } - const state = Object.assign({}, this.state); + const state = { ...this.state }; const { selection } = state; if (event.currentTarget.id !== selection.type) { const lastType = selection.type; @@ -230,7 +230,7 @@ class Stats extends React.Component { if (!this._isPlus(this.props)) { return; } - const state = Object.assign({}, this.state); + const state = { ...this.state }; const data = state.selection.type === 'daily' ? state.dailyData : state.monthlyData; if (e.target.id === 'stats-forward') { state.selection.currentIndex += 6; @@ -343,7 +343,7 @@ class Stats extends React.Component { * Save it in component's state */ _init = () => { - const state = Object.assign({}, this.state); + const state = { ...this.state }; this._getAllStats().then((allData) => { if (Array.isArray(allData)) { if (allData.length === 0) { @@ -497,7 +497,7 @@ class Stats extends React.Component { * Determine data selection for Stats Graph according to parameters in state * Save it in component's state */ - _determineSelectionData = (state = Object.assign({}, this.state)) => { + _determineSelectionData = (state = ({ ...this.state })) => { const { dailyData, monthlyData, cumulativeMonthlyData, selection } = state; diff --git a/app/panel/components/Summary.jsx b/app/panel/components/Summary.jsx index 4b9463999..7f71a51fc 100644 --- a/app/panel/components/Summary.jsx +++ b/app/panel/components/Summary.jsx @@ -15,7 +15,7 @@ import React from 'react'; import { ReactSVG } from 'react-svg'; import ClassNames from 'classnames'; import Tooltip from './Tooltip'; -import { DynamicUIPortContext } from '../contexts/DynamicUIPortContext'; +import DynamicUIPortContext from '../contexts/DynamicUIPortContext'; import { sendMessage } from '../utils/msg'; import globals from '../../../src/classes/Globals'; import { @@ -328,7 +328,7 @@ class Summary extends React.Component { enable_ad_block, } = this.props; - return enable_ad_block && adBlock && adBlock.trackerCount || 0; + return (enable_ad_block && adBlock && adBlock.trackerCount) || 0; } _antiTrackUnsafe() { @@ -337,7 +337,7 @@ class Summary extends React.Component { enable_anti_tracking, } = this.props; - return enable_anti_tracking && antiTracking && antiTracking.trackerCount || 0; + return (enable_anti_tracking && antiTracking && antiTracking.trackerCount) || 0; } _requestsModifiedCount() { @@ -353,7 +353,7 @@ class Summary extends React.Component { _sbBlocked() { const { smartBlock, trackerCounts } = this.props; - let sbBlocked = smartBlock && smartBlock.blocked && Object.keys(smartBlock.blocked).length || 0; + let sbBlocked = (smartBlock && smartBlock.blocked && Object.keys(smartBlock.blocked).length) || 0; if (sbBlocked === trackerCounts.sbBlocked) { sbBlocked = 0; } @@ -364,7 +364,7 @@ class Summary extends React.Component { _sbAllowed() { const { smartBlock, trackerCounts } = this.props; - let sbAllowed = smartBlock && smartBlock.unblocked && Object.keys(smartBlock.unblocked).length || 0; + let sbAllowed = (smartBlock && smartBlock.unblocked && Object.keys(smartBlock.unblocked).length) || 0; if (sbAllowed === trackerCounts.sbAllowed) { sbAllowed = 0; } @@ -375,7 +375,7 @@ class Summary extends React.Component { _sbAdjust() { const { enable_smart_block } = this.props; - return enable_smart_block && (this._sbBlocked() - this._sbAllowed()) || 0; + return enable_smart_block && ((this._sbBlocked() - this._sbAllowed()) || 0); } _totalTrackersBlockedCount() { diff --git a/app/panel/components/__tests__/PauseButton.jsx b/app/panel/components/__tests__/PauseButton.jsx index 5c7ea3660..4d89ba7b0 100644 --- a/app/panel/components/__tests__/PauseButton.jsx +++ b/app/panel/components/__tests__/PauseButton.jsx @@ -27,72 +27,80 @@ jest.mock('../Tooltip'); describe('app/panel/components/BuildingBlocks/PauseButton.jsx', () => { describe('Snapshot tests with react-test-renderer', () => { test('unpaused state in simple view', () => { - const initialState = { - isPaused: false, - isPausedTimeout: null, - clickPause: () => {}, - dropdownItems: [ - { name: t('pause_30_min'), name_condensed: t('pause_30_min_condensed'), val: 30 }, - { name: t('pause_1_hour'), name_condensed: t('pause_1_hour_condensed'), val: 60 }, - { name: t('pause_24_hours'), name_condensed: t('pause_24_hours_condensed'), val: 1440 }, - ], - isCentered: true, - isCondensed: false, - }; - const component = renderer.create().toJSON(); + const dropdownItems = [ + { name: t('pause_30_min'), name_condensed: t('pause_30_min_condensed'), val: 30 }, + { name: t('pause_1_hour'), name_condensed: t('pause_1_hour_condensed'), val: 60 }, + { name: t('pause_24_hours'), name_condensed: t('pause_24_hours_condensed'), val: 1440 }, + ]; + const component = renderer.create( + {}} + dropdownItems={dropdownItems} + isCentered + isCondensed={false} + /> + ).toJSON(); expect(component).toMatchSnapshot(); }); test('paused state in detailed view', () => { - const initialState = { - isPaused: true, - isPausedTimeout: null, - clickPause: () => {}, - dropdownItems: [ - { name: t('pause_30_min'), name_condensed: t('pause_30_min_condensed'), val: 30 }, - { name: t('pause_1_hour'), name_condensed: t('pause_1_hour_condensed'), val: 60 }, - { name: t('pause_24_hours'), name_condensed: t('pause_24_hours_condensed'), val: 1440 }, - ], - isCentered: false, - isCondensed: false, - }; - const component = renderer.create().toJSON(); + const dropdownItems = [ + { name: t('pause_30_min'), name_condensed: t('pause_30_min_condensed'), val: 30 }, + { name: t('pause_1_hour'), name_condensed: t('pause_1_hour_condensed'), val: 60 }, + { name: t('pause_24_hours'), name_condensed: t('pause_24_hours_condensed'), val: 1440 }, + ]; + const component = renderer.create( + {}} + dropdownItems={dropdownItems} + isCentered={false} + isCondensed={false} + /> + ).toJSON(); expect(component).toMatchSnapshot(); }); test('paused state in detailed condensed view', () => { - const initialState = { - isPaused: true, - isPausedTimeout: null, - clickPause: () => {}, - dropdownItems: [ - { name: t('pause_30_min'), name_condensed: t('pause_30_min_condensed'), val: 30 }, - { name: t('pause_1_hour'), name_condensed: t('pause_1_hour_condensed'), val: 60 }, - { name: t('pause_24_hours'), name_condensed: t('pause_24_hours_condensed'), val: 1440 }, - ], - isCentered: false, - isCondensed: true, - }; - const component = renderer.create().toJSON(); + const dropdownItems = [ + { name: t('pause_30_min'), name_condensed: t('pause_30_min_condensed'), val: 30 }, + { name: t('pause_1_hour'), name_condensed: t('pause_1_hour_condensed'), val: 60 }, + { name: t('pause_24_hours'), name_condensed: t('pause_24_hours_condensed'), val: 1440 }, + ]; + const component = renderer.create( + {}} + dropdownItems={dropdownItems} + isCentered={false} + isCondensed + /> + ).toJSON(); expect(component).toMatchSnapshot(); }); }); describe('Shallow snapshot tests rendered with Enzyme', () => { test('the state of the pause button correctly when Ghostery is not paused', () => { - const initialState = { - isPaused: false, - isPausedTimeout: null, - clickPause: () => {}, - dropdownItems: [ - { name: t('pause_30_min'), name_condensed: t('pause_30_min_condensed'), val: 30 }, - { name: t('pause_1_hour'), name_condensed: t('pause_1_hour_condensed'), val: 60 }, - { name: t('pause_24_hours'), name_condensed: t('pause_24_hours_condensed'), val: 1440 }, - ], - isCentered: false, - isCondensed: false, - }; - const component = shallow(); + const dropdownItems = [ + { name: t('pause_30_min'), name_condensed: t('pause_30_min_condensed'), val: 30 }, + { name: t('pause_1_hour'), name_condensed: t('pause_1_hour_condensed'), val: 60 }, + { name: t('pause_24_hours'), name_condensed: t('pause_24_hours_condensed'), val: 1440 }, + ]; + const component = shallow( + {}} + dropdownItems={dropdownItems} + isCentered={false} + isCondensed={false} + /> + ); expect(component.find('.button').length).toBe(2); expect(component.find('.button.button-pause').length).toBe(1); expect(component.find('.button.button-pause.active').length).toBe(0); @@ -110,19 +118,21 @@ describe('app/panel/components/BuildingBlocks/PauseButton.jsx', () => { }); test('the state of the pause button correctly when Ghostery is paused', () => { - const initialState = { - isPaused: true, - isPausedTimeout: 1800000, - clickPause: () => {}, - dropdownItems: [ - { name: t('pause_30_min'), name_condensed: t('pause_30_min_condensed'), val: 30 }, - { name: t('pause_1_hour'), name_condensed: t('pause_1_hour_condensed'), val: 60 }, - { name: t('pause_24_hours'), name_condensed: t('pause_24_hours_condensed'), val: 1440 }, - ], - isCentered: true, - isCondensed: false, - }; - const component = shallow(); + const dropdownItems = [ + { name: t('pause_30_min'), name_condensed: t('pause_30_min_condensed'), val: 30 }, + { name: t('pause_1_hour'), name_condensed: t('pause_1_hour_condensed'), val: 60 }, + { name: t('pause_24_hours'), name_condensed: t('pause_24_hours_condensed'), val: 1440 }, + ]; + const component = shallow( + {}} + dropdownItems={dropdownItems} + isCentered + isCondensed={false} + /> + ); expect(component.find('.button').length).toBe(2); expect(component.find('.button.button-pause').length).toBe(1); expect(component.find('.button.button-pause.active').length).toBe(1); @@ -140,19 +150,21 @@ describe('app/panel/components/BuildingBlocks/PauseButton.jsx', () => { }); test('the pause button correctly it is centered and condensed', () => { - const initialState = { - isPaused: false, - isPausedTimeout: null, - clickPause: () => {}, - dropdownItems: [ - { name: t('pause_30_min'), name_condensed: t('pause_30_min_condensed'), val: 30 }, - { name: t('pause_1_hour'), name_condensed: t('pause_1_hour_condensed'), val: 60 }, - { name: t('pause_24_hours'), name_condensed: t('pause_24_hours_condensed'), val: 1440 }, - ], - isCentered: true, - isCondensed: true, - }; - const component = shallow(); + const dropdownItems = [ + { name: t('pause_30_min'), name_condensed: t('pause_30_min_condensed'), val: 30 }, + { name: t('pause_1_hour'), name_condensed: t('pause_1_hour_condensed'), val: 60 }, + { name: t('pause_24_hours'), name_condensed: t('pause_24_hours_condensed'), val: 1440 }, + ]; + const component = shallow( + {}} + dropdownItems={dropdownItems} + isCentered + isCondensed + /> + ); expect(component.find('.button').length).toBe(2); expect(component.find('.button.button-pause').length).toBe(1); expect(component.find('.button.button-pause.smaller').length).toBe(0); diff --git a/app/panel/components/__tests__/Rewards.jsx b/app/panel/components/__tests__/Rewards.jsx index 5af0ace52..13fe9fbcf 100644 --- a/app/panel/components/__tests__/Rewards.jsx +++ b/app/panel/components/__tests__/Rewards.jsx @@ -15,7 +15,7 @@ import React from 'react'; import renderer from 'react-test-renderer'; import { MemoryRouter } from 'react-router'; import Rewards from '../Rewards'; -import { DynamicUIPortContext } from '../../contexts/DynamicUIPortContext'; +import DynamicUIPortContext from '../../contexts/DynamicUIPortContext'; // Fake the translation function to only return the translation key @@ -31,21 +31,22 @@ describe('app/panel/components/Rewards.jsx', () => { describe('Snapshot tests with react-test-renderer', () => { test('rewards is rendered correctly when rewards is on and rewards is null', () => { - const initialState = { - actions: { - updateRewardsData: () => {}, - sendSignal: () => {}, - }, - location: { - pathname: '/detail/rewards/list', - }, - enable_offers: true, - is_expanded: false + const actions = { + updateRewardsData: () => {}, + sendSignal: () => {}, + }; + const location = { + pathname: '/detail/rewards/list', }; const component = renderer.create( - + ).toJSON(); @@ -53,21 +54,22 @@ describe('app/panel/components/Rewards.jsx', () => { }); test('rewards is rendered correctly when rewards is off and rewards is null', () => { - const initialState = { - actions: { - updateRewardsData: () => {}, - sendSignal: () => {}, - }, - location: { - pathname: '/detail/rewards/list', - }, - enable_offers: false, - is_expanded: false + const actions = { + updateRewardsData: () => {}, + sendSignal: () => {}, + }; + const location = { + pathname: '/detail/rewards/list', }; const component = renderer.create( - + ).toJSON(); diff --git a/app/panel/containers/AccountSuccessContainer.js b/app/panel/containers/AccountSuccessContainer.js index 1c868b362..4e139965a 100644 --- a/app/panel/containers/AccountSuccessContainer.js +++ b/app/panel/containers/AccountSuccessContainer.js @@ -24,10 +24,11 @@ import AccountSuccess from '../components/AccountSuccess'; * @todo We are not using ownProps, so we better not specify it explicitly, * in this case it won't be passed by React (see https://github.com/reactjs/react-redux/blob/master/docs/api.md). */ -const mapStateToProps = state => Object.assign({}, state.accountSuccess, { +const mapStateToProps = state => ({ + ...state.accountSuccess, // get properties from panel redux store email: state.panel.email, - is_expert: state.panel.is_expert, + is_expert: state.panel.is_expert }); /** * Connects AccountSuccess component to the Redux store. diff --git a/app/panel/containers/BlockingContainer.js b/app/panel/containers/BlockingContainer.js index 681194a9c..ab4509022 100644 --- a/app/panel/containers/BlockingContainer.js +++ b/app/panel/containers/BlockingContainer.js @@ -26,7 +26,8 @@ import { showNotification, toggleCliqzFeature } from '../actions/PanelActions'; * @todo We are not using ownProps, so we better not specify it explicitly, * in this case it won't be passed by React (see https://github.com/reactjs/react-redux/blob/master/docs/api.md). */ -const mapStateToProps = state => Object.assign({}, state.blocking, { +const mapStateToProps = state => ({ + ...state.blocking, is_expanded: state.panel.is_expanded, language: state.panel.language, smartBlock: state.panel.smartBlock, @@ -34,7 +35,7 @@ const mapStateToProps = state => Object.assign({}, state.blocking, { pageHost: state.summary.pageHost, paused_blocking: state.summary.paused_blocking, sitePolicy: state.summary.sitePolicy, - smartBlockActive: state.panel.enable_smart_block, + smartBlockActive: state.panel.enable_smart_block }); /** * Bind Blocking view component action creators using Redux's bindActionCreators diff --git a/app/panel/containers/CreateAccountContainer.js b/app/panel/containers/CreateAccountContainer.js index 0811d6cd7..c88ae9bbb 100644 --- a/app/panel/containers/CreateAccountContainer.js +++ b/app/panel/containers/CreateAccountContainer.js @@ -26,10 +26,11 @@ import { register, getUser } from '../../Account/AccountActions'; * @todo We are not using ownProps, so we better not specify it explicitly, * in this case it won't be passed by React (see https://github.com/reactjs/react-redux/blob/master/docs/api.md). */ -const mapStateToProps = state => Object.assign({}, state.createAccount, { +const mapStateToProps = state => ({ + ...state.createAccount, // get properties from panel redux store is_expert: state.panel.is_expert, - language: state.panel.language, + language: state.panel.language }); /** * Bind CreateAccount view component action creators using Redux's bindActionCreators diff --git a/app/panel/containers/DetailContainer.js b/app/panel/containers/DetailContainer.js index b2e734998..f114667da 100644 --- a/app/panel/containers/DetailContainer.js +++ b/app/panel/containers/DetailContainer.js @@ -14,7 +14,7 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import Detail from '../components/Detail'; -import * as actions from '../actions/DetailActions'; +import toggleExpanded from '../actions/DetailActions'; /** * Map redux store state properties to Detailed view own properties. * @memberOf PanelContainers @@ -24,9 +24,11 @@ import * as actions from '../actions/DetailActions'; * @todo We are not using ownProps, so we better not specify it explicitly, * in this case it won't be passed by React (see https://github.com/reactjs/react-redux/blob/master/docs/api.md). */ -const mapStateToProps = state => Object.assign({}, state.detail, state.account, { +const mapStateToProps = state => ({ + ...state.detail, + ...state.account, is_expanded: state.panel.is_expanded, - enable_offers: state.panel.enable_offers, + enable_offers: state.panel.enable_offers }); /** * Bind Detailed view action creators using Redux's bindActionCreators @@ -35,7 +37,7 @@ const mapStateToProps = state => Object.assign({}, state.detail, state.account, * @param {Object} ownProps Detailed view component own props * @return {function} to be used as an argument in redux connect call */ -const mapDispatchToProps = dispatch => ({ actions: bindActionCreators(actions, dispatch) }); +const mapDispatchToProps = dispatch => ({ actions: bindActionCreators({ toggleExpanded }, dispatch) }); /** * Connects Detailed view component to the Redux store. * @memberOf PanelContainers diff --git a/app/panel/containers/HeaderContainer.js b/app/panel/containers/HeaderContainer.js index 5d375a4ea..65c22c8af 100644 --- a/app/panel/containers/HeaderContainer.js +++ b/app/panel/containers/HeaderContainer.js @@ -26,12 +26,13 @@ import { logout } from '../../Account/AccountActions'; * @todo We are not using ownProps, so we better not specify it explicitly, * in this case it won't be passed by React (see https://github.com/reactjs/react-redux/blob/master/docs/api.md). */ -const mapStateToProps = state => Object.assign({}, state.account, { +const mapStateToProps = state => ({ + ...state.account, // get properties from panel redux store is_expanded: state.panel.is_expanded, is_expert: state.panel.is_expert, language: state.panel.language, - tab_id: state.panel.tab_id, + tab_id: state.panel.tab_id }); /** * Bind Header component action creators using Redux's bindActionCreators. Pass updated match, location, and history props to the wrapped component. diff --git a/app/panel/containers/LoginContainer.js b/app/panel/containers/LoginContainer.js index f1a5c2c6d..e5e8650b9 100644 --- a/app/panel/containers/LoginContainer.js +++ b/app/panel/containers/LoginContainer.js @@ -25,9 +25,8 @@ import { login, getUser, getUserSettings } from '../../Account/AccountActions'; * @todo We are not using ownProps, so we better not specify it explicitly, * in this case it won't be passed by React (see https://github.com/reactjs/react-redux/blob/master/docs/api.md). */ -const mapStateToProps = state => Object.assign({}, { - // get properties from panel redux store - is_expert: state.panel.is_expert, +const mapStateToProps = state => ({ // get properties from panel redux store + is_expert: state.panel.is_expert }); /** * Bind Login view component action creators using Redux's bindActionCreators diff --git a/app/panel/containers/PanelContainer.js b/app/panel/containers/PanelContainer.js index 2a4b9e007..9657b87b7 100644 --- a/app/panel/containers/PanelContainer.js +++ b/app/panel/containers/PanelContainer.js @@ -27,10 +27,13 @@ import { updateBlockingData } from '../actions/BlockingActions'; * @todo We are not using ownProps, so we better not specify it explicitly, * in this case it won't be passed by React (see https://github.com/reactjs/react-redux/blob/master/docs/api.md). */ -const mapStateToProps = state => Object.assign({}, state.panel, state.drawer, state.account, { +const mapStateToProps = state => ({ + ...state.panel, + ...state.drawer, + ...state.account, paused_blocking: state.summary.paused_blocking, sitePolicy: state.summary.sitePolicy, - trackerCounts: state.summary.trackerCounts, + trackerCounts: state.summary.trackerCounts }); /** * Bind Panel view component action creators using Redux's bindActionCreators @@ -40,7 +43,9 @@ const mapStateToProps = state => Object.assign({}, state.panel, state.drawer, st * @return {function} to be used as an argument in redux connect call */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, panelActions, { filterTrackers, updateSummaryData }, { updateBlockingData }), dispatch), + actions: bindActionCreators({ + ...panelActions, filterTrackers, updateSummaryData, updateBlockingData + }, dispatch), }); /** * Connects Panel component to the Redux store. Pass updated match, location, and history props to the wrapped component. diff --git a/app/panel/containers/RewardsContainer.js b/app/panel/containers/RewardsContainer.js index e289896f4..8568970de 100644 --- a/app/panel/containers/RewardsContainer.js +++ b/app/panel/containers/RewardsContainer.js @@ -27,9 +27,7 @@ import { showNotification } from '../actions/PanelActions'; * @todo We are not using ownProps, so we better not specify it explicitly, * in this case it won't be passed by React (see https://github.com/reactjs/react-redux/blob/master/docs/api.md). */ -const mapStateToProps = state => Object.assign({}, state.rewards, { - is_expanded: state.panel.is_expanded, -}); +const mapStateToProps = state => ({ ...state.rewards, is_expanded: state.panel.is_expanded }); /** * Bind Rewards view action creators using Redux's bindActionCreators diff --git a/app/panel/containers/SettingsContainer.js b/app/panel/containers/SettingsContainer.js index 131a3f994..b2c8c1d50 100644 --- a/app/panel/containers/SettingsContainer.js +++ b/app/panel/containers/SettingsContainer.js @@ -14,7 +14,7 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import Settings from '../components/Settings'; import * as settingsActions from '../actions/SettingsActions'; -import { toggleExpanded } from '../actions/DetailActions'; +import toggleExpanded from '../actions/DetailActions'; import { updateSitePolicy } from '../actions/SummaryActions'; import { sendSignal } from '../actions/RewardsActions'; /** @@ -26,7 +26,8 @@ import { sendSignal } from '../actions/RewardsActions'; * @todo We are not using ownProps, so we better not specify it explicitly, * in this case it won't be passed by React (see https://github.com/reactjs/react-redux/blob/master/docs/api.md). */ -const mapStateToProps = state => Object.assign({}, state.settings, { +const mapStateToProps = state => ({ + ...state.settings, user: state.account.user, is_expanded: state.panel.is_expanded, language: state.panel.language, @@ -37,7 +38,7 @@ const mapStateToProps = state => Object.assign({}, state.settings, { site_blacklist: state.summary.site_blacklist, site_whitelist: state.summary.site_whitelist, trackers_banner_status: state.panel.trackers_banner_status, - trackerCounts: state.summary.trackerCounts, + trackerCounts: state.summary.trackerCounts }); /** * Bind Settings view component action creators using Redux's bindActionCreators diff --git a/app/panel/containers/StatsContainer.js b/app/panel/containers/StatsContainer.js index 5819bd7f7..6bb8fe379 100644 --- a/app/panel/containers/StatsContainer.js +++ b/app/panel/containers/StatsContainer.js @@ -22,7 +22,7 @@ import Stats from '../components/Stats'; * @todo We are not using ownProps, so we better not specify it explicitly, * in this case it won't be passed by React (see https://github.com/reactjs/react-redux/blob/master/docs/api.md). */ -const mapStateToProps = state => Object.assign({}, state.account); +const mapStateToProps = state => ({ ...state.account }); /** * Connects Subscription view component to the Redux store. Pass updated match, location, and history props to the wrapped component. diff --git a/app/panel/containers/SubscriptionContainer.js b/app/panel/containers/SubscriptionContainer.js index f0e2555a1..15e80c661 100644 --- a/app/panel/containers/SubscriptionContainer.js +++ b/app/panel/containers/SubscriptionContainer.js @@ -25,11 +25,12 @@ import { getUserSubscriptionData } from '../../Account/AccountActions'; * @todo We are not using ownProps, so we better not specify it explicitly, * in this case it won't be passed by React (see https://github.com/reactjs/react-redux/blob/master/docs/api.md). */ -const mapStateToProps = state => Object.assign({}, state.account, { +const mapStateToProps = state => ({ + ...state.account, theme: state.panel.theme, current_theme: state.panel.current_theme, subscriber: state.panel.subscriber, - language: state.panel.language, + language: state.panel.language }); /** * Bind Subscription view component action creators using Redux's bindActionCreators @@ -39,10 +40,10 @@ const mapStateToProps = state => Object.assign({}, state.account, { * @return {function} to be used as an argument in redux connect call */ const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(Object.assign({}, { + actions: bindActionCreators({ getTheme, getUserSubscriptionData - }), dispatch), + }, dispatch), }); /** * Connects Subscription view component to the Redux store. Pass updated match, location, and history props to the wrapped component. diff --git a/app/panel/containers/SummaryContainer.js b/app/panel/containers/SummaryContainer.js index fac24f3ba..993081cac 100644 --- a/app/panel/containers/SummaryContainer.js +++ b/app/panel/containers/SummaryContainer.js @@ -25,12 +25,14 @@ import * as panelActions from '../actions/PanelActions'; * @todo We are not using ownProps, so we better not specify it explicitly, * in this case it won't be passed by React (see https://github.com/reactjs/react-redux/blob/master/docs/api.md). */ -const mapStateToProps = state => Object.assign({}, state.summary, state.panel, { +const mapStateToProps = state => ({ + ...state.summary, + ...state.panel, is_expanded: state.panel.is_expanded, is_expert: state.panel.is_expert, tab_id: state.panel.tab_id, user: state.account.user, - current_theme: state.panel.current_theme, + current_theme: state.panel.current_theme }); /** * Bind Summary view component action creators using Redux's bindActionCreators diff --git a/app/panel/contexts/DynamicUIPortContext.js b/app/panel/contexts/DynamicUIPortContext.js index a43890801..370f0ab78 100644 --- a/app/panel/contexts/DynamicUIPortContext.js +++ b/app/panel/contexts/DynamicUIPortContext.js @@ -13,4 +13,5 @@ import React from 'react'; -export const DynamicUIPortContext = React.createContext(null); +const DynamicUIPortContext = React.createContext(null); +export default DynamicUIPortContext; diff --git a/app/panel/contexts/ThemeContext.js b/app/panel/contexts/ThemeContext.js index f47652914..92bf5e6fa 100644 --- a/app/panel/contexts/ThemeContext.js +++ b/app/panel/contexts/ThemeContext.js @@ -13,4 +13,5 @@ import React from 'react'; -export const ThemeContext = React.createContext(null); +const ThemeContext = React.createContext(null); +export default ThemeContext; diff --git a/app/panel/reducers/blocking.js b/app/panel/reducers/blocking.js index 2aebc09bb..213b15bc7 100644 --- a/app/panel/reducers/blocking.js +++ b/app/panel/reducers/blocking.js @@ -63,44 +63,44 @@ const initialState = { export default (state = initialState, action) => { switch (action.type) { case UPDATE_BLOCKING_DATA: { - return Object.assign({}, state, action.data); + return { ...state, ...action.data }; } case FILTER_TRACKERS: { if (state.filter.type === action.data.type && state.filter.name === action.data.name) { // prevent re-render if filter hasn't changed return state; } - return Object.assign({}, state, { filter: action.data }); + return { ...state, filter: action.data }; } case UPDATE_BLOCK_ALL_TRACKERS: { const updated = updateBlockAllTrackers(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case UPDATE_CATEGORIES: { - return Object.assign({}, state, { categories: action.data }); + return { ...state, categories: action.data }; } case UPDATE_UNKNOWN_CATEGORY_HIDE: { - return Object.assign({}, state, { unknownCategory: action.data }); + return { ...state, unknownCategory: action.data }; } case UPDATE_CATEGORY_BLOCKED: { const updated = updateCategoryBlocked(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case UPDATE_TRACKER_BLOCKED: { const updated = updateTrackerBlocked(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case TOGGLE_EXPAND_ALL: { const updated = toggleExpandAll(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case UPDATE_TRACKER_TRUST_RESTRICT: { const updated = _updateTrackerTrustRestrict(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case UPDATE_CLIQZ_MODULE_WHITELIST: { const unknownCategory = _updateCliqzModuleWhitelist(state, action); - return Object.assign({}, state, { unknownCategory }); + return { ...state, unknownCategory }; } case UPDATE_CLIQZ_MODULE_DATA: case UPDATE_SUMMARY_DATA: { @@ -112,10 +112,10 @@ export default (state = initialState, action) => { trackerCount: antiTracking.trackerCount + adBlock.trackerCount, unknownTrackerCount: antiTracking.unknownTrackerCount + adBlock.unknownTrackerCount, unknownTrackers: Array.from(new Set(antiTracking.unknownTrackers.concat(adBlock.unknownTrackers))), - whitelistedUrls: Object.assign({}, antiTracking.whitelistedUrls, adBlock.whitelistedUrls), + whitelistedUrls: { ...antiTracking.whitelistedUrls, ...adBlock.whitelistedUrls }, hide: state.unknownCategory.hide, }; - return Object.assign({}, state, { unknownCategory }); + return { ...state, unknownCategory }; } return state; } @@ -142,8 +142,8 @@ const _updateTrackerTrustRestrict = (state, action) => { const { pageHost } = action; const siteSpecificUnblocks = state.site_specific_unblocks; const siteSpecificBlocks = state.site_specific_blocks; - const pageUnblocks = siteSpecificUnblocks[pageHost] && siteSpecificUnblocks[pageHost].slice(0) || []; // clone - const pageBlocks = siteSpecificBlocks[pageHost] && siteSpecificBlocks[pageHost].slice(0) || []; // clone + const pageUnblocks = (siteSpecificUnblocks[pageHost] && siteSpecificUnblocks[pageHost].slice(0)) || []; // clone + const pageBlocks = (siteSpecificBlocks[pageHost] && siteSpecificBlocks[pageHost].slice(0)) || []; // clone // Site specific un-blocking if (msg.trust) { @@ -168,11 +168,11 @@ const _updateTrackerTrustRestrict = (state, action) => { // update tracker category for site-specific blocking const updated_category = updated_categories[updated_categories.findIndex(item => item.id === msg.cat_id)]; - updated_category.trackers.forEach((tracker) => { - if (tracker.shouldShow) { - if (tracker.id === app_id) { - tracker.ss_allowed = msg.trust; - tracker.ss_blocked = msg.restrict; + updated_category.trackers.forEach((trackerEl) => { + if (trackerEl.shouldShow) { + if (trackerEl.id === app_id) { + trackerEl.ss_allowed = msg.trust; + trackerEl.ss_blocked = msg.restrict; } } }); @@ -206,7 +206,7 @@ const _updateCliqzModuleWhitelist = (state, action) => { const addToWhitelist = () => { unknownTracker.domains.forEach((domain) => { - if (whitelistedUrls.hasOwnProperty(domain)) { + if (Object.prototype.hasOwnProperty.call(whitelistedUrls, domain)) { whitelistedUrls[domain].name = unknownTracker.name; whitelistedUrls[domain].hosts.push(pageHost); } else { @@ -242,9 +242,9 @@ const _updateCliqzModuleWhitelist = (state, action) => { addToWhitelist(); } - updatedUnknownCategory.unknownTrackers.forEach((tracker) => { - if (tracker.name === unknownTracker.name) { - tracker.whitelisted = !tracker.whitelisted; + updatedUnknownCategory.unknownTrackers.forEach((trackerEl) => { + if (trackerEl.name === unknownTracker.name) { + trackerEl.whitelisted = !trackerEl.whitelisted; } }); diff --git a/app/panel/reducers/panel.js b/app/panel/reducers/panel.js index 756db8c47..b6f644fc2 100644 --- a/app/panel/reducers/panel.js +++ b/app/panel/reducers/panel.js @@ -73,33 +73,35 @@ const initialState = { export default (state = initialState, action) => { switch (action.type) { case UPDATE_PANEL_DATA: { - return Object.assign({}, state, action.data, { initialized: true }); + return { ...state, ...action.data, initialized: true }; } case SET_THEME: { const { name, css } = action.data; setTheme(document, name, { themeData: { [name]: { name, css } } }); - return Object.assign({}, state, { current_theme: name }); + return { ...state, current_theme: name }; } case CLEAR_THEME: { setTheme(document, initialState.current_theme); - return Object.assign({}, state, { current_theme: initialState.current_theme }); + return { ...state, current_theme: initialState.current_theme }; } case SHOW_NOTIFICATION: { const updated = _showNotification(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case CLOSE_NOTIFICATION: { const updated = _closeNotification(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case LOGIN_SUCCESS: { - action.payload.text = `${t('panel_signin_success')} ${action.payload.email}`; - action.payload.classes = 'success'; - action.payload.overrideNotificationShown = true; - const updated = _showNotification(state, action); - return Object.assign({}, state, updated, { - loggedIn: true, - }); + const notificationAction = { + payload: { + text: `${t('panel_signin_success')} ${action.payload.email}`, + classes: 'success', + overrideNotificationShown: true, + } + }; + const updated = _showNotification(state, notificationAction); + return { ...state, ...updated, loggedIn: true }; } case LOGIN_FAIL: { const { errors } = action.payload; @@ -114,21 +116,27 @@ export default (state = initialState, action) => { errorText = t('server_error_message'); } }); - action.payload.text = errorText; - action.payload.classes = 'alert'; - action.payload.overrideNotificationShown = true; - const updated = _showNotification(state, action); - return Object.assign({}, state, updated); + const notificationAction = { + payload: { + text: errorText, + classes: 'alert', + overrideNotificationShown: true, + } + }; + const updated = _showNotification(state, notificationAction); + return { ...state, ...updated }; } case REGISTER_SUCCESS: { const { email } = action.payload; - action.payload.text = t('panel_email_verification_sent', email); - action.payload.classes = 'success'; - action.payload.overrideNotificationShown = true; - const updated = _showNotification(state, action); - return Object.assign({}, state, updated, { - email - }); + const notificationAction = { + payload: { + text: t('panel_email_verification_sent', email), + classes: 'success', + overrideNotificationShown: true, + } + }; + const updated = _showNotification(state, notificationAction); + return { ...state, ...updated, email }; } case REGISTER_FAIL: { const { errors } = action.payload; @@ -145,33 +153,41 @@ export default (state = initialState, action) => { errorText = t('server_error_message'); } }); - action.payload.text = errorText; - action.payload.classes = 'alert'; - action.payload.overrideNotificationShown = true; - const updated = _showNotification(state, action); - return Object.assign({}, state, updated); + const notificationAction = { + payload: { + text: errorText, + classes: 'alert', + overrideNotificationShown: true, + } + }; + const updated = _showNotification(state, notificationAction); + return { ...state, ...updated }; } case LOGOUT_SUCCESS: { setTheme(document); - return Object.assign({}, state, { current_theme: initialState.current_theme }); + return { ...state, current_theme: initialState.current_theme }; } // @TODO? // case LOGOUT_SUCCESS: { - // action.payload = { - // text: 'Logged out successfully.', - // classes: 'success', + // const notificationAction = { + // payload: { + // text: 'Logged out successfully.', + // classes: 'success', + // } // }; - // const updated = _showNotification(state, action); + // const updated = _showNotification(state, notificationAction); // return Object.assign({}, state, updated); // } case RESET_PASSWORD_SUCCESS: { - action.payload = { - text: t('banner_check_your_email_title'), - classes: 'success', - overrideNotificationShown: true, + const notificationAction = { + payload: { + text: t('banner_check_your_email_title'), + classes: 'success', + overrideNotificationShown: true, + } }; - const updated = _showNotification(state, action); - return Object.assign({}, state, updated); + const updated = _showNotification(state, notificationAction); + return { ...state, ...updated }; } case RESET_PASSWORD_FAIL: { const { errors } = action.payload; @@ -186,11 +202,15 @@ export default (state = initialState, action) => { errorText = t('server_error_message'); } }); - action.payload.text = errorText; - action.payload.classes = 'alert'; - action.payload.overrideNotificationShown = true; - const updated = _showNotification(state, action); - return Object.assign({}, state, updated); + const notificationAction = { + payload: { + text: errorText, + classes: 'alert', + overrideNotificationShown: true, + } + }; + const updated = _showNotification(state, notificationAction); + return { ...state, ...updated }; } case TOGGLE_CLIQZ_FEATURE: { let pingName = ''; @@ -212,13 +232,13 @@ export default (state = initialState, action) => { sendMessage('ping', pingName); } }); - return Object.assign({}, state, { [action.data.featureName]: !action.data.isEnabled }); + return { ...state, [action.data.featureName]: !action.data.isEnabled }; } case TOGGLE_EXPANDED: { sendMessage('setPanelData', { is_expanded: !state.is_expanded }); sendMessage('ping', state.is_expanded ? 'viewchange_from_expanded' : 'viewchange_from_detailed'); - return Object.assign({}, state, { is_expanded: !state.is_expanded }); + return { ...state, is_expanded: !state.is_expanded }; } case TOGGLE_EXPERT: { sendMessage('setPanelData', { is_expert: !state.is_expert }); @@ -233,22 +253,22 @@ export default (state = initialState, action) => { pingName = 'viewchange_from_simple'; } sendMessage('ping', pingName); - return Object.assign({}, state, { is_expert: !state.is_expert }); + return { ...state, is_expert: !state.is_expert }; } case UPDATE_NOTIFICATION_STATUS: { const updated = _updateNotificationStatus(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case TOGGLE_CHECKBOX: { if (action.data.event === 'enable_offers') { const enable_offers = action.data.checked; - return Object.assign({}, state, { enable_offers }); + return { ...state, enable_offers }; } return state; } case TOGGLE_OFFERS_ENABLED: { const enable_offers = action.data.enabled; - return Object.assign({}, state, { enable_offers }); + return { ...state, enable_offers }; } case TOGGLE_PROMO_MODAL: { return { @@ -283,14 +303,14 @@ const _showNotification = (state, action) => { updated_needsReload = { ...state.needsReload, changes: { ...state.needsReload.changes } }; // handle case where user clicks 'whitelist' then 'blacklist', or inverse - if (msg.updated === 'blacklist' && updated_needsReload.changes.hasOwnProperty('whitelist')) { + if (msg.updated === 'blacklist' && Object.prototype.hasOwnProperty.call(updated_needsReload.changes, 'whitelist')) { delete updated_needsReload.changes.whitelist; - } else if (msg.updated === 'whitelist' && updated_needsReload.changes.hasOwnProperty('blacklist')) { + } else if (msg.updated === 'whitelist' && Object.prototype.hasOwnProperty.call(updated_needsReload.changes, 'blacklist')) { delete updated_needsReload.changes.blacklist; } // update the 'changes' object. if the changed item already exists, remove it to signal a disable has occurred - if (updated_needsReload.changes.hasOwnProperty(msg.updated)) { + if (Object.prototype.hasOwnProperty.call(updated_needsReload.changes, msg.updated)) { delete updated_needsReload.changes[msg.updated]; } else if (msg.updated !== 'init') { // ignore the 'init' change, which comes from Panel.jsx to persist banners updated_needsReload.changes[msg.updated] = true; diff --git a/app/panel/reducers/rewards.js b/app/panel/reducers/rewards.js index 52a6f2b6c..fb98cd7b4 100644 --- a/app/panel/reducers/rewards.js +++ b/app/panel/reducers/rewards.js @@ -33,11 +33,11 @@ const initialState = { export default (state = initialState, action) => { switch (action.type) { case UPDATE_REWARDS_DATA: { - return Object.assign({}, state, action.data); + return { ...state, ...action.data }; } case TOGGLE_OFFERS_ENABLED: { const enable_offers = action.data.enabled; - return Object.assign({}, state, { enable_offers }); + return { ...state, enable_offers }; } case SEND_SIGNAL: { diff --git a/app/panel/reducers/settings.js b/app/panel/reducers/settings.js index 10e9f29c8..6ce7b4252 100644 --- a/app/panel/reducers/settings.js +++ b/app/panel/reducers/settings.js @@ -34,7 +34,6 @@ import { updateTrackerBlocked, updateCategoryBlocked, updateBlockAllTrackers, toggleExpandAll } from '../utils/blocking'; import { sendMessage } from '../utils/msg'; -import { objectEntries } from '../../../src/utils/common'; const initialState = { expand_all_trackers: false, @@ -58,60 +57,61 @@ const initialState = { export default (state = initialState, action) => { switch (action.type) { case GET_SETTINGS_DATA: { - return Object.assign({}, state, action.data); + return { ...state, ...action.data }; } case EXPORT_SETTINGS: { const updated = _exportSettings(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case IMPORT_SETTINGS_DIALOG: { const updated = _importSettingsDialog(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case IMPORT_SETTINGS_NATIVE: { const updated = _importSettingsNative(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case IMPORT_SETTINGS_FAILED: { - return Object.assign({}, state, { + return { + ...state, importResultText: t('settings_import_file_error'), - actionSuccess: false, - }); + actionSuccess: false + }; } case SELECT_ITEM: { const updated = _updateSelectValue(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case TOGGLE_CHECKBOX: { const updated = _updateSettingsCheckbox(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case UPDATE_DATABASE: { const updated = _updateTrackerDatabase(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case UPDATE_SETTINGS_BLOCK_ALL_TRACKERS: { const updated = updateBlockAllTrackers(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case UPDATE_SETTINGS_CATEGORY_BLOCKED: { const updated = updateCategoryBlocked(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case SETTINGS_TOGGLE_EXPAND_ALL: { const updated = toggleExpandAll(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case UPDATE_SETTINGS_TRACKER_BLOCKED: { const updated = updateTrackerBlocked(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case SETTINGS_UPDATE_SEARCH_VALUE: { const updated = _updateSearchValue(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case SETTINGS_FILTER: { const updated = _filter(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } default: return state; @@ -165,14 +165,14 @@ const _exportSettings = (state, action) => { */ const _importSettingsDialog = (state, action) => { const result = action.data; - const updated_actionSuccess = state.actionSuccess; + let updated_actionSuccess = state.actionSuccess; let updated_importResultText = state.importResultText; if (result === true) { // showBrowseWindow was successful window.close(); } else { - state.updated_actionSuccess = false; + updated_actionSuccess = false; updated_importResultText = t('settings_import_dialog_error'); } @@ -194,8 +194,10 @@ const _importSettingsDialog = (state, action) => { const _importSettingsNative = (state, action) => { const { settings } = action; const updated_state = {}; - // eslint-disable-next-line prefer-const - for (let [key, value] of objectEntries(settings)) { + const settingsKeys = Object.keys(settings); + for (let i = 0; i < settingsKeys.length; i++) { + const key = settingsKeys[i]; + let value = settings[key]; if (key === 'alert_bubble_timeout') { value = (value > 30) ? 30 : value; } @@ -283,19 +285,19 @@ const _updateTrackerDatabase = (state, action) => { const _updateSearchValue = (state, action) => { const query = action.data || ''; const updated_categories = JSON.parse(JSON.stringify(state.categories)) || []; // deep clone - updated_categories.forEach((category) => { - category.num_total = 0; - category.num_blocked = 0; - category.trackers.forEach((tracker) => { + updated_categories.forEach((categoryEl) => { + categoryEl.num_total = 0; + categoryEl.num_blocked = 0; + categoryEl.trackers.forEach((trackerEl) => { if (query) { - tracker.shouldShow = !!(tracker.name.toLowerCase().indexOf(query) !== -1); + trackerEl.shouldShow = !!(trackerEl.name.toLowerCase().indexOf(query) !== -1); } else { - tracker.shouldShow = true; + trackerEl.shouldShow = true; } - if (tracker.shouldShow) { - category.num_total++; - if (tracker.blocked) { - category.num_blocked++; + if (trackerEl.shouldShow) { + categoryEl.num_total++; + if (trackerEl.blocked) { + categoryEl.num_blocked++; } } }); @@ -319,34 +321,34 @@ const _updateSearchValue = (state, action) => { const _filter = (state, action) => { const updated_categories = JSON.parse(JSON.stringify(state.categories)) || []; // deep clone const new_app_ids = state.new_app_ids || []; - updated_categories.forEach((category) => { - category.num_total = 0; - category.num_blocked = 0; - category.trackers.forEach((tracker) => { + updated_categories.forEach((categoryEl) => { + categoryEl.num_total = 0; + categoryEl.num_blocked = 0; + categoryEl.trackers.forEach((trackerEl) => { switch (action.data) { case 'all': - tracker.shouldShow = true; - category.num_total++; - if (tracker.blocked) { - category.num_blocked++; + trackerEl.shouldShow = true; + categoryEl.num_total++; + if (trackerEl.blocked) { + categoryEl.num_blocked++; } break; case 'blocked': - tracker.shouldShow = tracker.blocked; - if (tracker.shouldShow) { - category.num_total++; + trackerEl.shouldShow = trackerEl.blocked; + if (trackerEl.shouldShow) { + categoryEl.num_total++; } break; case 'unblocked': - tracker.shouldShow = !tracker.blocked; - if (tracker.shouldShow) { - category.num_total++; + trackerEl.shouldShow = !trackerEl.blocked; + if (trackerEl.shouldShow) { + categoryEl.num_total++; } break; case 'new': - tracker.shouldShow = !!(new_app_ids.indexOf(+tracker.id) !== -1); - if (tracker.shouldShow) { - category.num_total++; + trackerEl.shouldShow = !!(new_app_ids.indexOf(+trackerEl.id) !== -1); + if (trackerEl.shouldShow) { + categoryEl.num_total++; } break; default: diff --git a/app/panel/reducers/summary.js b/app/panel/reducers/summary.js index 41c575daf..17b7cd9c8 100644 --- a/app/panel/reducers/summary.js +++ b/app/panel/reducers/summary.js @@ -66,17 +66,18 @@ export default (state = initialState, action) => { switch (action.type) { case UPDATE_SUMMARY_DATA: case UPDATE_CLIQZ_MODULE_DATA: { - return Object.assign({}, state, action.data); + return { ...state, ...action.data }; } case UPDATE_GHOSTERY_PAUSED: { - return Object.assign({}, state, { paused_blocking: action.data.ghosteryPaused, paused_blocking_timeout: action.data.time }); + return { ...state, paused_blocking: action.data.ghosteryPaused, paused_blocking_timeout: action.data.time }; } case UPDATE_SITE_POLICY: { const updated = _updateSitePolicy(state, action); - return Object.assign({}, state, updated); + return { ...state, ...updated }; } case UPDATE_TRACKER_COUNTS: { - return Object.assign({}, state, { + return { + ...state, trackerCounts: { blocked: action.data.num_blocked, allowed: action.data.num_total - action.data.num_blocked, @@ -84,8 +85,8 @@ export default (state = initialState, action) => { ssAllowed: action.data.num_ss_allowed, sbBlocked: action.data.num_sb_blocked, sbAllowed: action.data.num_sb_allowed, - }, - }); + } + }; } default: return state; } diff --git a/app/panel/utils/blocking.js b/app/panel/utils/blocking.js index c797e87df..b710fa3ce 100644 --- a/app/panel/utils/blocking.js +++ b/app/panel/utils/blocking.js @@ -30,19 +30,19 @@ export function updateSummaryBlockingCount(categories = [], smartBlock, updateTr let numTotalSbBlocked = 0; let numTotalSbUnblocked = 0; - categories.forEach((category) => { - category.trackers.forEach((tracker) => { + categories.forEach((categoryEl) => { + categoryEl.trackers.forEach((trackerEl) => { numTotal++; - const sbBlocked = smartBlock.blocked.hasOwnProperty(tracker.id); - const sbUnblocked = smartBlock.unblocked.hasOwnProperty(tracker.id); + const sbBlocked = Object.prototype.hasOwnProperty.call(smartBlock.blocked, trackerEl.id); + const sbUnblocked = Object.prototype.hasOwnProperty.call(smartBlock.unblocked, trackerEl.id); - if (tracker.ss_blocked || sbBlocked || (tracker.blocked && !tracker.ss_allowed && !sbUnblocked)) { + if (trackerEl.ss_blocked || sbBlocked || (trackerEl.blocked && !trackerEl.ss_allowed && !sbUnblocked)) { numTotalBlocked++; } - if (tracker.ss_blocked) { + if (trackerEl.ss_blocked) { numTotalSsBlocked++; } - if (tracker.ss_allowed) { + if (trackerEl.ss_allowed) { numTotalSsUnblocked++; } if (sbBlocked) { @@ -76,19 +76,19 @@ export function updateBlockAllTrackers(state, action) { const updated_app_ids = JSON.parse(JSON.stringify(state.selected_app_ids)) || {}; const updated_categories = JSON.parse(JSON.stringify(state.categories)) || []; const { smartBlockActive } = action.data; - const smartBlock = smartBlockActive && action.data.smartBlock || { blocked: {}, unblocked: {} }; + const smartBlock = (smartBlockActive && action.data.smartBlock) || { blocked: {}, unblocked: {} }; - updated_categories.forEach((category) => { - category.num_blocked = 0; - category.trackers.forEach((tracker) => { - const sbBlocked = smartBlock.blocked.hasOwnProperty(tracker.id); - const sbUnblocked = smartBlock.unblocked.hasOwnProperty(tracker.id); + updated_categories.forEach((categoryEl) => { + categoryEl.num_blocked = 0; + categoryEl.trackers.forEach((trackerEl) => { + const sbBlocked = Object.prototype.hasOwnProperty.call(smartBlock.blocked, trackerEl.id); + const sbUnblocked = Object.prototype.hasOwnProperty.call(smartBlock.unblocked, trackerEl.id); - if (tracker.shouldShow) { - tracker.blocked = blocked; - const key = tracker.id; + if (trackerEl.shouldShow) { + trackerEl.blocked = blocked; + const key = trackerEl.id; if (sbBlocked || (blocked && !sbUnblocked)) { - category.num_blocked++; + categoryEl.num_blocked++; } if (blocked) { updated_app_ids[key] = 1; @@ -117,19 +117,19 @@ export function updateBlockAllTrackers(state, action) { */ export function updateCategoryBlocked(state, action) { const { blocked, smartBlockActive } = action.data; - const smartBlock = smartBlockActive && action.data.smartBlock || { blocked: {}, unblocked: {} }; + const smartBlock = (smartBlockActive && action.data.smartBlock) || { blocked: {}, unblocked: {} }; const updated_app_ids = JSON.parse(JSON.stringify(state.selected_app_ids)) || {}; const updated_categories = JSON.parse(JSON.stringify(state.categories)); // deep clone const catIndex = updated_categories.findIndex(item => item.id === action.data.category); const updated_category = updated_categories[catIndex]; updated_category.num_blocked = 0; - updated_category.trackers.forEach((tracker) => { - const sbBlocked = smartBlock.blocked.hasOwnProperty(tracker.id); - const sbUnblocked = smartBlock.unblocked.hasOwnProperty(tracker.id); + updated_category.trackers.forEach((trackerEl) => { + const sbBlocked = Object.prototype.hasOwnProperty.call(smartBlock.blocked, trackerEl.id); + const sbUnblocked = Object.prototype.hasOwnProperty.call(smartBlock.unblocked, trackerEl.id); - if (tracker.shouldShow) { - tracker.blocked = blocked; - const key = tracker.id; + if (trackerEl.shouldShow) { + trackerEl.blocked = blocked; + const key = trackerEl.id; if (sbBlocked || (blocked && !sbUnblocked)) { updated_category.num_blocked++; } @@ -160,8 +160,8 @@ export function updateCategoryBlocked(state, action) { export function toggleExpandAll(state, action) { sendMessage('setPanelData', { expand_all_trackers: action.data }); const updated_categories = JSON.parse(JSON.stringify(state.categories)); // deep clone - updated_categories.forEach((category) => { - category.expanded = action.data; + updated_categories.forEach((categoryEl) => { + categoryEl.expanded = action.data; }); return { categories: updated_categories, @@ -186,28 +186,28 @@ export function updateTrackerBlocked(state, action) { } const { blocked, smartBlockActive } = action.data; - const smartBlock = smartBlockActive && action.data.smartBlock || { blocked: {}, unblocked: {} }; + const smartBlock = (smartBlockActive && action.data.smartBlock) || { blocked: {}, unblocked: {} }; const updated_app_ids = JSON.parse(JSON.stringify(state.selected_app_ids)) || {}; const updated_categories = JSON.parse(JSON.stringify(state.categories)) || []; // deep clone const catIndex = updated_categories.findIndex(item => item.id === action.data.cat_id); const updated_category = updated_categories[catIndex]; updated_category.num_blocked = 0; - updated_category.trackers.forEach((tracker) => { - const sbBlocked = smartBlock.blocked.hasOwnProperty(tracker.id); - const sbUnblocked = smartBlock.unblocked.hasOwnProperty(tracker.id); - - if (tracker.shouldShow) { - if (tracker.id === action.data.app_id) { - tracker.blocked = blocked; - const key = tracker.id; + updated_category.trackers.forEach((trackerEl) => { + const sbBlocked = Object.prototype.hasOwnProperty.call(smartBlock.blocked, trackerEl.id); + const sbUnblocked = Object.prototype.hasOwnProperty.call(smartBlock.unblocked, trackerEl.id); + + if (trackerEl.shouldShow) { + if (trackerEl.id === action.data.app_id) { + trackerEl.blocked = blocked; + const key = trackerEl.id; if (blocked) { updated_app_ids[key] = 1; } else { delete updated_app_ids[key]; } } - if (sbBlocked || (tracker.blocked && !sbUnblocked)) { + if (sbBlocked || (trackerEl.blocked && !sbUnblocked)) { updated_category.num_blocked++; } } diff --git a/app/panel/utils/utils.js b/app/panel/utils/utils.js index 2e4a07148..ce438df33 100644 --- a/app/panel/utils/utils.js +++ b/app/panel/utils/utils.js @@ -24,7 +24,7 @@ import { log } from '../../../src/utils/common'; export function updateObject(obj, key, value) { const output = {}; output[key] = value; - return Object.assign({}, obj, output); + return { ...obj, ...output }; } /** @@ -35,9 +35,9 @@ export function updateObject(obj, key, value) { * @return {Object} new object */ export function removeFromObject(obj, key) { - return Object.keys(obj).filter(k => k !== key.toString()).reduce((result, k) => { - result[k] = obj[k]; - return result; + return Object.keys(obj).filter(k => k !== key.toString()).reduce((acc, k) => { + acc[k] = obj[k]; + return acc; }, {}); } @@ -135,7 +135,7 @@ export function validateConfirmEmail(email, confirmEmail) { } const lEmail = email.toLowerCase(); const lConfirmEmail = confirmEmail.toLowerCase(); - return validateEmail(confirmEmail) && (lEmail === lConfirmEmail) || false; + return (validateEmail(confirmEmail) && (lEmail === lConfirmEmail)) || false; } /** diff --git a/app/scss/partials/_upgrade_banner.scss b/app/scss/partials/_upgrade_banner.scss index 13f405cd6..d942e8dae 100644 --- a/app/scss/partials/_upgrade_banner.scss +++ b/app/scss/partials/_upgrade_banner.scss @@ -19,7 +19,7 @@ } .UpgradeBanner--normal { - height: 50px; + height: 25px; .UpgradeBanner__text { font-size: 12px; @@ -33,7 +33,7 @@ } .UpgradeBanner--small { - height: 50px; + height: 20px; .UpgradeBanner__text { font-size: 10px; diff --git a/app/shared-components/ForgotPassword/ForgotPasswordContainer.js b/app/shared-components/ForgotPassword/ForgotPasswordContainer.js index 0add4b2dc..6f1d3b41c 100644 --- a/app/shared-components/ForgotPassword/ForgotPasswordContainer.js +++ b/app/shared-components/ForgotPassword/ForgotPasswordContainer.js @@ -26,7 +26,7 @@ import { resetPassword } from '../../Account/AccountActions'; * @todo We are not using ownProps, so we better not specify it explicitly, * in this case it won't be passed by React (see https://github.com/reactjs/react-redux/blob/master/docs/api.md). */ -const mapStateToProps = () => Object.assign({}); +const mapStateToProps = () => ({}); /** * Bind ForgotPassword component action creators using Redux's bindActionCreators * @memberOf PanelContainers diff --git a/app/shared-components/PromoModal/PromoModal.jsx b/app/shared-components/PromoModal/PromoModal.jsx index 603de8cae..b968cbaf2 100644 --- a/app/shared-components/PromoModal/PromoModal.jsx +++ b/app/shared-components/PromoModal/PromoModal.jsx @@ -124,7 +124,9 @@ class PromoModal extends React.Component { }; renderModalContent() { - const { type, loggedIn } = this.props; + const { + type, loggedIn, location, isPlus, handleKeepBasicClick + } = this.props; switch (type) { case INSIGHTS: return ( @@ -132,7 +134,6 @@ class PromoModal extends React.Component { handleGoAwayClick={() => this._handlePromoGoAwayClick(INSIGHTS)} handleTryInsightsClick={() => this._handlePromoTryProductClick(INSIGHTS, 'in_app_upgrade')} handleSignInClick={this._handlePromoSignInClick} - {...this.props} /> ); case PLUS: @@ -150,11 +151,19 @@ class PromoModal extends React.Component { handleGoAwayClick={() => this._handlePromoGoAwayClick(PREMIUM)} handleTryMidnightClick={() => this._handlePromoTryProductClick(PREMIUM, 'in_app')} handleGetPlusClick={() => this._handlePromoTryProductClick(PLUS, 'in_app')} - {...this.props} + handleKeepBasicClick={handleKeepBasicClick} + location={location} + isPlus={isPlus} /> ); default: - return ; + return ( + this._handlePromoGoAwayClick(INSIGHTS)} + handleTryInsightsClick={() => this._handlePromoTryProductClick(INSIGHTS, 'in_app_upgrade')} + handleSignInClick={this._handlePromoSignInClick} + /> + ); } } diff --git a/app/shared-components/PromoModal/PromoModalContainer.js b/app/shared-components/PromoModal/PromoModalContainer.js index 50585c692..44e106050 100644 --- a/app/shared-components/PromoModal/PromoModalContainer.js +++ b/app/shared-components/PromoModal/PromoModalContainer.js @@ -40,10 +40,10 @@ import { togglePromoModal, showNotification } from '../../panel/actions/PanelAct */ const mapDispatchToProps = dispatch => ({ actions: bindActionCreators( - Object.assign({ + { togglePromoModal, showNotification - }), dispatch + }, dispatch ) }); /** diff --git a/package.json b/package.json index ee161a7d3..ade3fd5ce 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,8 @@ "test": "cross-env BABEL_ENV=test jest", "test.watch": "cross-env BABEL_ENV=test jest --watch", "test.snapshot": "jest --updateSnapshot", - "lint": "eslint --ext .js,.jsx ./app ./src", - "lint.fix": "eslint --ext .js,.jsx ./app ./src --fix", + "lint": "eslint --ext .js,.jsx ./app ./src ./test ./tools", + "lint.fix": "eslint --ext .js,.jsx ./app ./src ./test ./tools --fix", "lint.raw": "eslint --ext .js,.jsx", "docs": "jsdoc -c jsdoc.json -d docs -r", "leet": "node ./tools/leet/leet-en.js", diff --git a/src/background.js b/src/background.js index e4fbc0e53..5bf91a15c 100644 --- a/src/background.js +++ b/src/background.js @@ -23,6 +23,7 @@ import moment from 'moment/min/moment-with-locales.min'; import cliqz from './classes/Cliqz'; // object class import Events from './classes/EventHandlers'; +import Policy from './classes/Policy'; // static classes import panelData from './classes/PanelData'; import bugDb from './classes/BugDb'; @@ -39,7 +40,7 @@ import globals from './classes/Globals'; import surrogatedb from './classes/SurrogateDb'; import tabInfo from './classes/TabInfo'; import metrics from './classes/Metrics'; -import rewards from './classes/Rewards'; +import Rewards from './classes/Rewards'; import account from './classes/Account'; import GhosteryModule from './classes/Module'; import promoModals from './classes/PromoModals'; @@ -49,7 +50,7 @@ import { allowAllwaysC2P } from './utils/click2play'; import * as common from './utils/common'; import * as utils from './utils/utils'; import { _getJSONAPIErrorsObject } from './utils/api'; -import { importCliqzSettings } from './utils/cliqzSettingImport'; +import importCliqzSettings from './utils/cliqzSettingImport'; import { sendCliqzModuleCounts } from './utils/cliqzModulesData'; // For debug purposes, provide Access to the internals of `browser-core` @@ -71,7 +72,7 @@ const IS_FIREFOX = (BROWSER_INFO.name === 'firefox'); const VERSION_CHECK_URL = `${CDN_BASE_URL}/update/version`; const REAL_ESTATE_ID = 'ghostery'; const onBeforeRequest = events.onBeforeRequest.bind(events); -const onHeadersReceived = events.onHeadersReceived.bind(events); +const { onHeadersReceived } = Events; // Cliqz Modules const moduleMock = { @@ -125,11 +126,13 @@ function setGhosteryDefaultBlocking() { const categoriesBlock = ['advertising', 'pornvertising', 'site_analytics']; log('Blocking all trackers in categories:', ...categoriesBlock); const selected_app_ids = {}; - for (const app_id in bugDb.db.apps) { - if (bugDb.db.apps.hasOwnProperty(app_id)) { + const app_ids = Object.keys(bugDb.db.apps); + for (let i = 0; i < app_ids.length; i++) { + const app_id = app_ids[i]; + if (Object.prototype.hasOwnProperty.call(bugDb.db.apps, app_id)) { const category = bugDb.db.apps[app_id].cat; if (categoriesBlock.indexOf(category) >= 0 && - !selected_app_ids.hasOwnProperty(app_id)) { + !Object.prototype.hasOwnProperty.call(selected_app_ids, app_id)) { selected_app_ids[app_id] = 1; } } @@ -489,14 +492,14 @@ function handleBlockedRedirect(name, message, tab_id, callback) { function handleRewards(name, message, callback) { switch (name) { case 'rewardSignal': // e.g. hub_open | hub_closed - rewards.sendSignal(message); + Rewards.sendSignal(message); break; case 'ping': metrics.ping(message); break; case 'setPanelData': - if (message.hasOwnProperty('enable_offers')) { - rewards.sendSignal(message.signal); + if (Object.prototype.hasOwnProperty.call(message, 'enable_offers')) { + Rewards.sendSignal(message.signal); panelData.set({ enable_offers: message.enable_offers }); } return callback(); @@ -574,8 +577,10 @@ function handleGhosteryHub(name, message, callback) { case 'BLOCKING_POLICY_EVERYTHING': { panelData.set({ setup_block: 3 }); const selected_app_ids = {}; - for (const app_id in bugDb.db.apps) { - if (!selected_app_ids.hasOwnProperty(app_id)) { + const app_ids = Object.keys(bugDb.db.apps); + for (let i = 0; i < app_ids.length; i++) { + const app_id = app_ids[i]; + if (!Object.prototype.hasOwnProperty.call(selected_app_ids, app_id)) { selected_app_ids[app_id] = 1; } } @@ -594,7 +599,7 @@ function handleGhosteryHub(name, message, callback) { } case 'SET_GHOSTERY_REWARDS': { const { enable_ghostery_rewards = true } = message; - rewards.sendSignal({ + Rewards.sendSignal({ actionId: `rewards_${enable_ghostery_rewards ? 'on' : 'off'}`, origin: 'ghostery-setup-flow', type: 'action-signal', @@ -771,7 +776,7 @@ function onMessageHandler(request, sender, callback) { const { email, password } = message; account.login(email, password) .then((response) => { - if (!response.hasOwnProperty('errors')) { + if (!Object.prototype.hasOwnProperty.call(response, 'errors')) { metrics.ping('sign_in_success'); } callback(response); @@ -788,7 +793,7 @@ function onMessageHandler(request, sender, callback) { } = message; account.register(email, confirmEmail, password, firstName, lastName) .then((response) => { - if (!response.hasOwnProperty('errors')) { + if (!Object.prototype.hasOwnProperty.call(response, 'errors')) { metrics.ping('create_account_success'); } callback(response); @@ -879,10 +884,11 @@ function onMessageHandler(request, sender, callback) { if (name === 'account.getUser') { account.getUser(message) .then((user) => { - if (user) { - user.subscriptionsPlus = account.hasScopesUnverified(['subscriptions:plus']); + const foundUser = user; + if (foundUser) { + foundUser.subscriptionsPlus = account.hasScopesUnverified(['subscriptions:plus']); } - callback({ user }); + callback({ user: foundUser }); }) .catch((err) => { callback({ errors: _getJSONAPIErrorsObject(err) }); @@ -1007,7 +1013,7 @@ function initializeDispatcher() { const { db } = bugDb; db.noneSelected = (num_selected === 0); // can't simply compare num_selected and size(db.apps) since apps get removed sometimes - db.allSelected = (!!num_selected && every(db.apps, (app, app_id) => appIds.hasOwnProperty(app_id))); + db.allSelected = (!!num_selected && every(db.apps, (app, app_id) => Object.prototype.hasOwnProperty.call(appIds, app_id))); }); dispatcher.on('conf.save.site_whitelist', () => { // TODO debounce with below @@ -1182,7 +1188,7 @@ function initialiseWebRequestPipeline() { spec: 'collect', before: existingSteps.onHeadersReceived, fn: (state) => { - events.onHeadersReceived(state); + Events.onHeadersReceived(state); return true; } }) @@ -1198,7 +1204,7 @@ function initialiseWebRequestPipeline() { */ function isWhitelisted(state) { // state.ghosteryWhitelisted is sometimes undefined so force to bool - return Boolean(globals.SESSION.paused_blocking || events.policy.getSitePolicy(state.tabUrl, state.url) === 2 || state.ghosteryWhitelisted); + return Boolean(globals.SESSION.paused_blocking || Policy.getSitePolicy(state.tabUrl, state.url) === 2 || state.ghosteryWhitelisted); } /** * Set listener for 'enabled' event for Antitracking module which replaces @@ -1338,10 +1344,10 @@ function initializeEventListeners() { chrome.webNavigation.onCommitted.addListener(events.onCommitted.bind(events)); // Fired when the page's DOM is fully constructed, but the referenced resources may not finish loading - chrome.webNavigation.onDOMContentLoaded.addListener(events.onDOMContentLoaded.bind(events)); + chrome.webNavigation.onDOMContentLoaded.addListener(Events.onDOMContentLoaded.bind(events)); // Fired when a document, including the resources it refers to, is completely loaded and initialized - chrome.webNavigation.onCompleted.addListener(events.onNavigationCompleted.bind(events)); + chrome.webNavigation.onCompleted.addListener(Events.onNavigationCompleted.bind(events)); // Fired when a new window, or a new tab in an existing window, is created to host a navigation. // chrome.webNavigation.onCreatedNavigationTarget @@ -1366,7 +1372,7 @@ function initializeEventListeners() { // chrome.webRequest.onBeforeRequest // Fires when a request is about to send headers - chrome.webRequest.onBeforeSendHeaders.addListener(events.onBeforeSendHeaders.bind(events), { + chrome.webRequest.onBeforeSendHeaders.addListener(Events.onBeforeSendHeaders.bind(events), { urls: [ 'https://l.ghostery.com/*', 'https://d.ghostery.com/*', @@ -1394,17 +1400,17 @@ function initializeEventListeners() { }); // Fires when a request could not be processed successfully - chrome.webRequest.onErrorOccurred.addListener(events.onRequestErrorOccurred.bind(events), { + chrome.webRequest.onErrorOccurred.addListener(Events.onRequestErrorOccurred.bind(events), { urls: ['http://*/*', 'https://*/*'] }); /** * TABS ** */ // Fired when a new tab is created by user or internally - chrome.tabs.onCreated.addListener(events.onTabCreated.bind(events)); + chrome.tabs.onCreated.addListener(Events.onTabCreated.bind(events)); // Fires when the active tab in a window changes - chrome.tabs.onActivated.addListener(events.onTabActivated.bind(events)); + chrome.tabs.onActivated.addListener(Events.onTabActivated.bind(events)); // Fired when a tab is replaced with another tab due to prerendering chrome.tabs.onReplaced.addListener(events.onTabReplaced.bind(events)); @@ -1587,7 +1593,7 @@ function initializeGhosteryModules() { cliqz.events.subscribe('myoffrz:turnoff', () => { panelData.set({ enable_offers: false }); - rewards.sendSignal({ + Rewards.sendSignal({ actionId: 'rewards_off', type: 'action-signal', }); diff --git a/src/classes/ABTest.js b/src/classes/ABTest.js index df7a235fb..51a47110c 100644 --- a/src/classes/ABTest.js +++ b/src/classes/ABTest.js @@ -34,7 +34,7 @@ class ABTest { * @param {string} name test name */ hasTest(name) { - return this.tests.hasOwnProperty(name); + return Object.prototype.hasOwnProperty.call(this.tests, name); } /** diff --git a/src/classes/Account.js b/src/classes/Account.js index 4dfd48a30..51fea7f2e 100644 --- a/src/classes/Account.js +++ b/src/classes/Account.js @@ -40,7 +40,8 @@ class Account { const opts = { errorHandler: errors => ( new Promise((resolve, reject) => { - for (const err of errors) { + for (let i = 0; i < errors.length; i++) { + const err = errors[i]; switch (err.code) { case '10020': // token is not valid case '10060': // user id does not match @@ -346,10 +347,12 @@ class Account { // check scopes if (userScopes.indexOf('god') >= 0) { return true; } - for (const sArr of required) { + for (let i = 0; i < required.length; i++) { + const sArr = required[i]; let matches = true; if (sArr.length > 0) { - for (const s of sArr) { + for (let j = 0; j < sArr.length; j++) { + const s = sArr[j]; if (userScopes.indexOf(s) === -1) { matches = false; break; @@ -490,7 +493,7 @@ class Account { conf.account.themeData = {}; } const { name } = data; - conf.account.themeData[name] = Object.assign({ timestamp: Date.now() }, data); + conf.account.themeData[name] = { timestamp: Date.now(), ...data }; dispatcher.trigger('conf.save.account'); } @@ -520,7 +523,8 @@ class Account { * * @return {Promise} user settings json or error */ - _setConfUserSettings = (settings) => { + _setConfUserSettings = (s) => { + const settings = s; log('SET USER SETTINGS', settings); if (IS_CLIQZ) { settings.enable_human_web = false; diff --git a/src/classes/BrowserButton.js b/src/classes/BrowserButton.js index 5037166d1..279cbfd09 100644 --- a/src/classes/BrowserButton.js +++ b/src/classes/BrowserButton.js @@ -31,7 +31,6 @@ class BrowserButton { alert: [255, 157, 0, 230], default: [51, 0, 51, 230] }; - this.policy = new Policy(); } /** @@ -140,7 +139,7 @@ class BrowserButton { return; } - const { appsCount, appsAlertCount } = this._getTrackerCount(tabId); + const { appsCount, appsAlertCount } = BrowserButton._getTrackerCount(tabId); const adBlockingCount = getCliqzData(tabId, tabHostUrl).trackerCount; const antiTrackingCount = getCliqzData(tabId, tabHostUrl, true).trackerCount; @@ -151,7 +150,7 @@ class BrowserButton { if (trackerCount === '') { this._setIcon(false, tabId, trackerCount, alert); } else { - this._setIcon(!globals.SESSION.paused_blocking && !this.policy.checkSiteWhitelist(tab.url), tabId, trackerCount, alert); + this._setIcon(!globals.SESSION.paused_blocking && !Policy.checkSiteWhitelist(tab.url), tabId, trackerCount, alert); } } @@ -161,7 +160,7 @@ class BrowserButton { * @param {string} tabUrl the Tab URL * @return {Object} the number of total trackers and alerted trackers in an Object */ - _getTrackerCount(tabId, tabUrl) { + static _getTrackerCount(tabId, tabUrl) { const apps = foundBugs.getAppsCountByIssues(tabId, tabUrl); return { appsCount: apps.all, diff --git a/src/classes/BugDb.js b/src/classes/BugDb.js index ea1885ae6..612974771 100644 --- a/src/classes/BugDb.js +++ b/src/classes/BugDb.js @@ -37,7 +37,7 @@ class BugDb extends Updatable { * @param {Object} old_apps trackers in the original database * @return {Object} list of all new trackers */ - updateNewAppIds(new_apps, old_apps) { + static updateNewAppIds(new_apps, old_apps) { log('updating newAppIds...'); const new_app_ids = difference( @@ -54,7 +54,7 @@ class BugDb extends Updatable { * Apply block to all new trackers * @param {Object} new_app_ids list of new trackers */ - applyBlockByDefault(new_app_ids) { + static applyBlockByDefault(new_app_ids) { if (conf.block_by_default) { log('applying block-by-default...'); const { selected_app_ids } = conf; @@ -74,7 +74,7 @@ class BugDb extends Updatable { * @param {Object} db bugs database object * @return {array} array of categories */ - _buildCategories(db) { + static _buildCategories(db) { const selectedApps = conf.selected_app_ids || {}; let appId; let category; @@ -84,13 +84,15 @@ class BugDb extends Updatable { const categoryArray = []; const categories = {}; - for (appId in db.apps) { - if (db.apps.hasOwnProperty(appId)) { + const appIds = Object.keys(db.apps); + for (let i = 0; i < appIds.length; i++) { + appId = appIds[i]; + if (Object.prototype.hasOwnProperty.call(db.apps, appId)) { category = db.apps[appId].cat; if (t(`category_${category}`) === `category_${category}`) { category = 'uncategorized'; } - blocked = selectedApps.hasOwnProperty(appId); + blocked = Object.prototype.hasOwnProperty.call(selectedApps, appId); // Because we have two trackers in the DB with the same name if ((categories[category] && categories[category].trackers[db.apps[appId].name])) { @@ -98,7 +100,7 @@ class BugDb extends Updatable { continue; } - if (categories.hasOwnProperty(category)) { + if (Object.prototype.hasOwnProperty.call(categories, category)) { categories[category].num_total++; if (blocked) { categories[category].num_blocked++; @@ -126,8 +128,10 @@ class BugDb extends Updatable { } } - for (categoryName in categories) { - if (categories.hasOwnProperty(categoryName)) { + const categoryNames = Object.keys(categories); + for (let i = 0; i < categoryNames.length; i++) { + categoryName = categoryNames[i]; + if (Object.prototype.hasOwnProperty.call(categories, categoryName)) { const category = categories[categoryName]; if (category.trackers) { category.trackers.sort((a, b) => { @@ -179,8 +183,10 @@ class BugDb extends Updatable { log('initializing bugdb regexes...'); - for (const id in regexes) { - if (regexes.hasOwnProperty(id)) { + const regexesKeys = Object.keys(regexes); + for (let i = 0; i < regexesKeys.length; i++) { + const id = regexesKeys[i]; + if (Object.prototype.hasOwnProperty.call(regexes, id)) { db.patterns.regex[id] = new RegExp(regexes[id], 'i'); } } @@ -193,7 +199,7 @@ class BugDb extends Updatable { // since allSelected is slow to eval, make it lazy defineLazyProperty(db, 'allSelected', () => { const num_selected = size(conf.selected_app_ids); - return (!!num_selected && every(db.apps, (app, app_id) => conf.selected_app_ids.hasOwnProperty(app_id))); + return (!!num_selected && every(db.apps, (app, app_id) => Object.prototype.hasOwnProperty.call(conf.selected_app_ids, app_id))); }); log('processed bugdb...'); @@ -204,25 +210,25 @@ class BugDb extends Updatable { // if there is an older bugs object in storage, // update newAppIds and apply block-by-default if (old_bugs) { - if (old_bugs.hasOwnProperty('version') && bugs.version > old_bugs.version) { - new_app_ids = this.updateNewAppIds(bugs.apps, old_bugs.apps); + if (Object.prototype.hasOwnProperty.call(old_bugs, 'version') && bugs.version > old_bugs.version) { + new_app_ids = BugDb.updateNewAppIds(bugs.apps, old_bugs.apps); if (new_app_ids.length) { - this.applyBlockByDefault(new_app_ids); + BugDb.applyBlockByDefault(new_app_ids); db.JUST_UPDATED_WITH_NEW_TRACKERS = true; } // pre-trie/legacy db - } else if (old_bugs.hasOwnProperty('bugsVersion') && bugs.version !== old_bugs.bugsVersion) { + } else if (Object.prototype.hasOwnProperty.call(old_bugs, 'bugsVersion') && bugs.version !== old_bugs.bugsVersion) { const old_apps = reduce(old_bugs.bugs, (memo, bug) => { memo[bug.aid] = true; return memo; }, {}); - new_app_ids = this.updateNewAppIds(bugs.apps, old_apps); + new_app_ids = BugDb.updateNewAppIds(bugs.apps, old_apps); if (new_app_ids.length) { - this.applyBlockByDefault(new_app_ids); + BugDb.applyBlockByDefault(new_app_ids); // don't claim new trackers when db got downgraded by version if (bugs.version > old_bugs.bugsVersion) { @@ -235,7 +241,7 @@ class BugDb extends Updatable { conf.bugs = bugs; } - db.categories = this._buildCategories(db); + db.categories = BugDb._buildCategories(db); this.db = db; diff --git a/src/classes/CMP.js b/src/classes/CMP.js index e22ad49d4..0c674c0d9 100644 --- a/src/classes/CMP.js +++ b/src/classes/CMP.js @@ -52,7 +52,8 @@ class CMP { return getJson(URL).then((data) => { if (data && (!conf.cmp_version || data.Version > conf.cmp_version)) { // set default dismiss - data.Campaigns.forEach((campaign) => { + data.Campaigns.forEach((c) => { + const campaign = c; if (campaign.Dismiss === 0) { campaign.Dismiss = 10; } diff --git a/src/classes/Click2PlayDb.js b/src/classes/Click2PlayDb.js index 40324e497..43d892ad5 100644 --- a/src/classes/Click2PlayDb.js +++ b/src/classes/Click2PlayDb.js @@ -43,7 +43,7 @@ class Click2PlayDb extends Updatable { log('processing c2p...'); try { - db = this._buildDb(data.click2play, data.click2playVersion); + db = Click2PlayDb._buildDb(data.click2play, data.click2playVersion); } catch (e) { log('Click2PlayDb processList() error', e); return false; @@ -66,11 +66,13 @@ class Click2PlayDb extends Updatable { // TODO memory leak when you close tabs before reset() can run? reset(tab_id) { - if (!this.allowOnceList.hasOwnProperty(tab_id)) { return; } + if (!Object.prototype.hasOwnProperty.call(this.allowOnceList, tab_id)) { return; } - const entries = Object.entries(this.allowOnceList[tab_id]); let keep = false; - for (const [appID, count] of entries) { + const allowKeys = Object.keys(this.allowOnceList[tab_id]); + for (let i = 0; i < allowKeys.length; i++) { + const appID = allowKeys[i]; + const count = this.allowOnceList[tab_id][appID]; const newCount = count - 1; this.allowOnceList[tab_id][appID] = newCount; if (newCount > 0) { @@ -84,8 +86,8 @@ class Click2PlayDb extends Updatable { allowedOnce(tab_id, aid) { return ( - this.allowOnceList.hasOwnProperty(tab_id) && - this.allowOnceList[tab_id].hasOwnProperty(aid) && + Object.prototype.hasOwnProperty.call(this.allowOnceList, tab_id) && + Object.prototype.hasOwnProperty.call(this.allowOnceList[tab_id], aid) && this.allowOnceList[tab_id][aid] > 0 ); } @@ -108,12 +110,12 @@ class Click2PlayDb extends Updatable { * @param {string} version database version * @return {Object} reconfigured database object */ - _buildDb(entries, version) { + static _buildDb(entries, version) { const apps = {}; let allow; entries.forEach((entry) => { - if (!apps.hasOwnProperty(entry.aid)) { + if (!Object.prototype.hasOwnProperty.call(apps, entry.aid)) { apps[entry.aid] = []; } diff --git a/src/classes/CompatibilityDb.js b/src/classes/CompatibilityDb.js index 914e7d613..163281bd8 100644 --- a/src/classes/CompatibilityDb.js +++ b/src/classes/CompatibilityDb.js @@ -36,7 +36,7 @@ class CompatibilityDb extends Updatable { log('processing comp...'); try { - db = this._buildDb(comp.compatibility, comp.compatibilityVersion); + db = CompatibilityDb._buildDb(comp.compatibility, comp.compatibilityVersion); } catch (e) { log('CompatibilityDb processList() error', e); return false; @@ -66,7 +66,7 @@ class CompatibilityDb extends Updatable { * @return {Boolean} */ hasIssue(aid, tab_url) { - return this.db.list && this.db.list.hasOwnProperty(aid) && fuzzyUrlMatcher(tab_url, this.db.list[aid]); + return this.db.list && Object.prototype.hasOwnProperty.call(this.db.list, aid) && fuzzyUrlMatcher(tab_url, this.db.list[aid]); } /** @@ -79,7 +79,7 @@ class CompatibilityDb extends Updatable { * @param {string} version database version * @return {Object} Refactored database */ - _buildDb(bugs, version) { + static _buildDb(bugs, version) { const map = {}; bugs.forEach((s) => { diff --git a/src/classes/ConfData.js b/src/classes/ConfData.js index cd62556e2..69c4e20e3 100644 --- a/src/classes/ConfData.js +++ b/src/classes/ConfData.js @@ -37,7 +37,7 @@ const IS_FIREFOX = (BROWSER_INFO.name === 'firefox'); class ConfData { constructor() { // language does not get persisted - this.language = this._getDefaultLanguage(); + this.language = ConfData._getDefaultLanguage(); this.SYNC_SET = new Set(globals.SYNC_ARRAY); } @@ -47,7 +47,8 @@ class ConfData { * This method is called once on startup. */ init() { - return prefsGet().then((data) => { + return prefsGet().then((d) => { + const data = d; const nowTime = Number(new Date().getTime()); const _initProperty = (name, value) => { if (data[name] === null || typeof (data[name]) === 'undefined') { @@ -165,7 +166,7 @@ class ConfData { }); } - _getDefaultLanguage() { + static _getDefaultLanguage() { const SUPPORTED_LANGUAGES = { de: 'Deutsch', en: 'English', @@ -185,12 +186,12 @@ class ConfData { let lang = window.navigator.language.replace('-', '_'); - if (SUPPORTED_LANGUAGES.hasOwnProperty(lang)) { + if (Object.prototype.hasOwnProperty.call(SUPPORTED_LANGUAGES, lang)) { return lang; } lang = lang.slice(0, 2); - if (SUPPORTED_LANGUAGES.hasOwnProperty(lang)) { + if (Object.prototype.hasOwnProperty.call(SUPPORTED_LANGUAGES, lang)) { return lang; } diff --git a/src/classes/EventHandlers.js b/src/classes/EventHandlers.js index f84b7a6db..69e2c5ffe 100644 --- a/src/classes/EventHandlers.js +++ b/src/classes/EventHandlers.js @@ -72,7 +72,7 @@ class EventHandlers { log(`❤ ❤ ❤ Tab ${tabId} navigating to ${url} ❤ ❤ ❤`); this._clearTabData(tabId); - this._resetNotifications(); + EventHandlers._resetNotifications(); // TODO understand why this does not work when placed in the 'reload' branch in onCommitted panelData.clearPageLoadTime(tabId); @@ -80,7 +80,7 @@ class EventHandlers { tabInfo.create(tabId, url); foundBugs.update(tabId); button.update(tabId); - this._eventReset(details.tabId); + EventHandlers._eventReset(details.tabId); // Workaround for foundBugs/tabInfo memory leak when the user triggers // prefetching/prerendering but never loads the page. Wait two minutes @@ -89,7 +89,7 @@ class EventHandlers { utils.getTab(tabId, null, () => { log('Clearing orphan tab data for tab', tabId); this._clearTabData(tabId); - this._resetNotifications(); + EventHandlers._resetNotifications(); }); }, 120000); } @@ -143,7 +143,7 @@ class EventHandlers { * * @param {Object} details event data */ - onDOMContentLoaded(details) { + static onDOMContentLoaded(details) { const tab_id = details.tabId; // ignore if this is a sub-frame @@ -280,7 +280,7 @@ class EventHandlers { * * @param {Object} details event data */ - onNavigationCompleted(details) { + static onNavigationCompleted(details) { if (!utils.isValidTopLevelNavigation(details)) { return; } @@ -289,7 +289,7 @@ class EventHandlers { log(`foundBugs: ${foundBugs.getAppsCount(details.tabId)}, tab_id: ${details.tabId}`); // inject page_performance script to display page latency on Summary view - if (this._isValidUrl(utils.processUrl(details.url))) { + if (EventHandlers._isValidUrl(utils.processUrl(details.url))) { utils.injectScript(details.tabId, 'dist/page_performance.js', '', 'document_idle').catch((err) => { log('onNavigationCompleted injectScript error', err); }); @@ -310,13 +310,13 @@ class EventHandlers { // TODO what other webRequest-restricted pages are out there? if (details.url.startsWith('https://chrome.google.com/webstore/')) { this._clearTabData(tab_id); - this._resetNotifications(); + EventHandlers._resetNotifications(); } return; } - this._eventReset(tab_id); + EventHandlers._eventReset(tab_id); } /** @@ -328,10 +328,11 @@ class EventHandlers { * + Speed this up by making it asynchronous when blocking is disabled? * + Also speed it up for blocking-whitelisted pages (by delaying isBug scanning)? * - * @param {Object} details event data + * @param {Object} d event data * @return {Object} optionaly return {cancel: true} to force dropping the request */ - onBeforeRequest(details) { + onBeforeRequest(d) { + const details = d; const tab_id = details.tabId; const request_id = details.requestId; @@ -361,7 +362,7 @@ class EventHandlers { }); } - if (!this._checkRedirect(details.type, request_id)) { + if (!EventHandlers._checkRedirect(details.type, request_id)) { return { cancel: false }; } @@ -371,8 +372,8 @@ class EventHandlers { /* ** SMART BLOCKING - Privacy ** */ // block HTTP request on HTTPS page - if (this.policySmartBlock.isInsecureRequest(tab_id, page_protocol, processed.scheme, processed.hostname)) { - return this._blockHelper(details, tab_id, null, null, request_id, from_redirect, true); + if (PolicySmartBlock.isInsecureRequest(tab_id, page_protocol, processed.scheme, processed.hostname)) { + return EventHandlers._blockHelper(details, tab_id, null, null, request_id, from_redirect, true); } // TODO fuse this into a single call to improve performance @@ -392,7 +393,7 @@ class EventHandlers { /* ** SMART BLOCKING - Breakage ** */ // allow first party trackers - if (this.policySmartBlock.isFirstPartyRequest(tab_id, page_domain, processed.generalDomain)) { + if (PolicySmartBlock.isFirstPartyRequest(tab_id, page_domain, processed.generalDomain)) { return { cancel: false }; } @@ -401,7 +402,7 @@ class EventHandlers { const incognito = tabInfo.getTabInfo(tab_id, 'incognito'); const tab_host = tabInfo.getTabInfo(tab_id, 'host'); const fromRedirect = globals.REDIRECT_MAP.has(request_id); - const { block, reason } = this._checkBlocking(app_id, cat_id, tab_id, tab_host, page_url, request_id); + const { block, reason } = EventHandlers._checkBlocking(app_id, cat_id, tab_id, tab_host, page_url, request_id); if (!block && reason === BLOCK_REASON_SS_UNBLOCKED) { // The way to pass this flag to Cliqz handlers details.ghosteryWhitelisted = true; @@ -440,7 +441,7 @@ class EventHandlers { }, 1); if ((block && !smartUnblocked) || smartBlocked) { - return this._blockHelper(details, tab_id, app_id, bug_id, request_id, fromRedirect); + return EventHandlers._blockHelper(details, tab_id, app_id, bug_id, request_id, fromRedirect); } return { cancel: false }; @@ -450,10 +451,11 @@ class EventHandlers { * Handler for webRequest.onBeforeSendHeaders event. * Called each time that an HTTP(S) request is about to send headers * - * @param {Object} details event data + * @param {Object} d event data * @return {Object} optionally return headers to send */ - onBeforeSendHeaders(details) { + static onBeforeSendHeaders(d) { + const details = d; for (let i = 0; i < details.requestHeaders.length; ++i) { // Fetch requests in Firefox web-extension has a flaw. They attach // origin: moz-extension//ID , which is specific to a user. @@ -475,7 +477,7 @@ class EventHandlers { * * @param {Object} details event data */ - onHeadersReceived(details) { + static onHeadersReceived(details) { // Skip content-length collection if it's a 3XX (redirect) if (details.statusCode >> 8 === 1) { } // eslint-disable-line } @@ -509,7 +511,7 @@ class EventHandlers { if (!details || details.tabId <= 0) { return; } - this._clearRedirects(details.requestId); + EventHandlers._clearRedirects(details.requestId); if (details.type !== 'main_frame') { const appWithLatencyId = latency.logLatency(details); @@ -527,9 +529,9 @@ class EventHandlers { * * @param {Object} details event data */ - onRequestErrorOccurred(details) { + static onRequestErrorOccurred(details) { latency.logLatency(details); - this._clearRedirects(details.requestId); + EventHandlers._clearRedirects(details.requestId); } /** @@ -538,7 +540,7 @@ class EventHandlers { * * @param {Object} tab Details of the tab that was created */ - onTabCreated(tab) { + static onTabCreated(tab) { const { url } = tab; metrics.handleBrokenPageTrigger(globals.BROKEN_PAGE_NEW_TAB, url); @@ -550,9 +552,9 @@ class EventHandlers { * * @param {Object} activeInfo tab data */ - onTabActivated(activeInfo) { + static onTabActivated(activeInfo) { button.update(activeInfo.tabId); - this._resetNotifications(); + EventHandlers._resetNotifications(); } /** @@ -584,7 +586,7 @@ class EventHandlers { */ onTabRemoved(tab_id) { this._clearTabData(tab_id); - this._resetNotifications(); + EventHandlers._resetNotifications(); } /** @@ -644,7 +646,7 @@ class EventHandlers { * @param {boolean} fromRedirect * @return {string|boolean} */ - _blockHelper(details, tabId, appId, bugId, requestId, fromRedirect, upgradeInsecure) { + static _blockHelper(details, tabId, appId, bugId, requestId, fromRedirect, upgradeInsecure) { if (upgradeInsecure) { // attempt to redirect request to HTTPS. NOTE: Redirects from URLs // with ws:// and wss:// schemes are ignored. @@ -673,7 +675,7 @@ class EventHandlers { if (details.type === 'script' && bugId) { let code = ''; if (appId === 2575) { // Hubspot - code = this._getHubspotFormSurrogate(details.url); + code = EventHandlers._getHubspotFormSurrogate(details.url); } else { const ti = tabInfo.getTabInfo(tabId); const surrogates = surrogatedb.getForTracker(details.url, appId, bugId, ti.host); @@ -715,7 +717,7 @@ class EventHandlers { * @param {URL} parsedURL * @return {Boolean} */ - _isValidUrl(parsedURL) { + static _isValidUrl(parsedURL) { if (parsedURL && parsedURL.protocol.startsWith('http') && parsedURL.isValidHost() && !parsedURL.pathname.includes('_/chrome/newtab')) { return true; } @@ -731,7 +733,7 @@ class EventHandlers { * @param {string} form request url * @return {string} surrogate code */ - _getHubspotFormSurrogate(url) { + static _getHubspotFormSurrogate(url) { // Hubspot url has a fixed format // https://forms.hubspot.com/embed/v3/form/532040/95b5de3a-6d4a-4729-bebf-07c41268d773?callback=hs_reqwest_0&hutk=941df50e9277ee76755310cd78647a08 // The following three parameters are privacy-safe: @@ -784,7 +786,7 @@ class EventHandlers { * * @param {number} requestId */ - _clearRedirects(requestId) { + static _clearRedirects(requestId) { globals.REDIRECT_MAP.delete(requestId); globals.LET_REDIRECTS_THROUGH = false; } @@ -798,7 +800,7 @@ class EventHandlers { * @param {number} request_id request id * @return {boolean} */ - _checkRedirect(type, request_id) { + static _checkRedirect(type, request_id) { const fromRedirect = globals.REDIRECT_MAP.has(request_id); // if the request is part of the main_frame and not a redirect, we don't proceed if (type === 'main_frame' && !fromRedirect) { @@ -827,7 +829,7 @@ class EventHandlers { * @param {number} request_id request id * @return {BlockWithReason} block result with reason */ - _checkBlocking(app_id, cat_id, tab_id, tab_host, page_url, request_id) { + static _checkBlocking(app_id, cat_id, tab_id, tab_host, page_url, request_id) { const fromRedirect = globals.REDIRECT_MAP.has(request_id); let block; @@ -836,7 +838,7 @@ class EventHandlers { if (fromRedirect && globals.LET_REDIRECTS_THROUGH) { block = { block: false, reason: BLOCK_REASON_C2P_ALLOWED_THROUGH }; } else { - block = this.policy.shouldBlock(app_id, cat_id, tab_id, tab_host, page_url); + block = Policy.shouldBlock(app_id, cat_id, tab_id, tab_host, page_url); } return block; @@ -849,7 +851,7 @@ class EventHandlers { * * @param {number} tab_id tab id */ - _eventReset(tab_id) { + static _eventReset(tab_id) { c2pDb.reset(tab_id); globals.REDIRECT_MAP.clear(); globals.LET_REDIRECTS_THROUGH = false; @@ -877,7 +879,7 @@ class EventHandlers { * @private * */ - _resetNotifications() { + static _resetNotifications() { globals.NOTIFICATIONS_LOADED = false; } } diff --git a/src/classes/ExtMessenger.js b/src/classes/ExtMessenger.js index badcc0ecc..ecd068438 100644 --- a/src/classes/ExtMessenger.js +++ b/src/classes/ExtMessenger.js @@ -21,15 +21,15 @@ import { log } from '../utils/common'; * @memberOf BackgroundClasses */ export class ExtMessenger { - addListener(fn) { + static addListener(fn) { chrome.runtime.onMessageExternal.addListener(fn); } - removeListener(fn) { + static removeListener(fn) { chrome.runtime.onMessageExternal.removeListener(fn); } - sendMessage(extensionId, message) { + static sendMessage(extensionId, message) { chrome.runtime.sendMessage(extensionId, message, () => { if (chrome.runtime.lastError) { log('ExtMessenger sendMessage error:', chrome.runtime.lastError); @@ -44,18 +44,17 @@ export class ExtMessenger { */ export default class KordInjector { constructor() { - this.messenger = new ExtMessenger(); this.extensionId = 'cliqz@cliqz.com'; this.moduleWrappers = new Map(); this._messageHandler = this._messageHandler.bind(this); } init() { - this.messenger.addListener(this._messageHandler); + ExtMessenger.addListener(this._messageHandler); } unload() { - this.messenger.removeListener(this._messageHandler); + ExtMessenger.removeListener(this._messageHandler); } module(moduleName) { @@ -67,9 +66,10 @@ export default class KordInjector { } _createModuleWrapper(moduleName) { - return new Spanan((message) => { + return new Spanan((m) => { + const message = m; message.moduleName = moduleName; - this.messenger.sendMessage(this.extensionId, message); + ExtMessenger.sendMessage(this.extensionId, message); }); } diff --git a/src/classes/FoundBugs.js b/src/classes/FoundBugs.js index 2d1dd854a..1d956743e 100644 --- a/src/classes/FoundBugs.js +++ b/src/classes/FoundBugs.js @@ -139,7 +139,7 @@ class FoundBugs { if (app_id) { const { appsById } = this._foundApps[tab_id]; - if (appsById.hasOwnProperty(app_id)) { + if (Object.prototype.hasOwnProperty.call(appsById, app_id)) { apps_arr.push(apps[appsById[app_id]]); } } else { @@ -200,12 +200,14 @@ class FoundBugs { } // squish all the bugs into categories first - for (id in bugs) { - if (bugs.hasOwnProperty(id)) { + const ids = Object.keys(bugs); + for (let i = 0; i < ids.length; i++) { + id = ids[i]; + if (Object.prototype.hasOwnProperty.call(bugs, id)) { aid = db.bugs[id].aid; // eslint-disable-line prefer-destructuring cid = db.apps[aid].cat; - if (cats_obj.hasOwnProperty(cid)) { + if (Object.prototype.hasOwnProperty.call(cats_obj, cid)) { if (!cats_obj[cid].appIds.includes(aid)) { cats_obj[cid].appIds.push(aid); cats_obj[cid].trackers.push({ @@ -239,17 +241,19 @@ class FoundBugs { } // convert categories hash to array - for (cid in cats_obj) { - if (cats_obj.hasOwnProperty(cid)) { + const cids = Object.keys(cats_obj); + for (let i = 0; i < cids.length; i++) { + cid = cids[i]; + if (Object.prototype.hasOwnProperty.call(cats_obj, cid)) { cats_arr.push(cats_obj[cid]); } } if (sorted) { cats_arr.sort((a, b) => { - a = a.name.toLowerCase(); - b = b.name.toLowerCase(); - return (a > b ? 1 : (a < b ? -1 : 0)); + const a1 = a.name.toLowerCase(); + const b1 = b.name.toLowerCase(); + return (a1 > b1 ? 1 : (a1 < b1 ? -1 : 0)); }); } @@ -360,7 +364,7 @@ class FoundBugs { const { aid } = bugDb.db.bugs[bug_id]; const { apps, appsById, issueCounts } = this._foundApps[tab_id]; - if (appsById.hasOwnProperty(aid)) { + if (Object.prototype.hasOwnProperty.call(appsById, aid)) { const app = apps[appsById[aid]]; if (!app.hasLatencyIssue) { issueCounts.latency++; @@ -391,11 +395,11 @@ class FoundBugs { return false; } - if (!this._foundBugs.hasOwnProperty(tab_id)) { + if (!Object.prototype.hasOwnProperty.call(this._foundBugs, tab_id)) { this._foundBugs[tab_id] = {}; } - if (!this._foundApps.hasOwnProperty(tab_id)) { + if (!Object.prototype.hasOwnProperty.call(this._foundApps, tab_id)) { this._foundApps[tab_id] = { apps: [], appsMetadata: {}, @@ -420,7 +424,8 @@ class FoundBugs { */ _checkForCompatibilityIssues(tab_id, tab_url) { const { apps, appsMetadata, issueCounts } = this._foundApps[tab_id]; - apps.forEach((app) => { + apps.forEach((a) => { + const app = a; const { id } = app; if (appsMetadata[id].needsCompatibilityCheck) { app.hasCompatibilityIssue = app.blocked ? compDb.hasIssue(id, tab_url) : false; @@ -440,7 +445,7 @@ class FoundBugs { * @param {string} type */ _updateFoundBugs(tab_id, bug_id, src, blocked, type) { - if (!this._foundBugs[tab_id].hasOwnProperty(bug_id)) { + if (!Object.prototype.hasOwnProperty.call(this._foundBugs[tab_id], bug_id)) { this._foundBugs[tab_id][bug_id] = { sources: [], hasLatencyIssue: false, @@ -482,7 +487,7 @@ class FoundBugs { apps, appsMetadata, appsById, issueCounts } = this._foundApps[tab_id]; - if (appsById.hasOwnProperty(aid)) { + if (Object.prototype.hasOwnProperty.call(appsById, aid)) { const app = apps[appsById[aid]]; if (!app.hasLatencyIssue && hasLatencyIssue) { issueCounts.latency++; } diff --git a/src/classes/Latency.js b/src/classes/Latency.js index f5b331111..f8acc509f 100644 --- a/src/classes/Latency.js +++ b/src/classes/Latency.js @@ -33,7 +33,7 @@ class Latency { const request_id = details.requestId; const tab_id = details.tabId; - if (!this.latencies.hasOwnProperty(request_id)) { + if (!Object.prototype.hasOwnProperty.call(this.latencies, request_id)) { return 0; } // If the latencies object for this request id is empty then this is @@ -46,7 +46,7 @@ class Latency { // TRACKER1 --> NON-TRACKER --> TRACKER2 // TRACKER2's onBeforeRequest sync callback could maybe fire before // NON-TRACKER's onBeforeRedirect async callback - if (!this.latencies[request_id].hasOwnProperty(details.url)) { + if (!Object.prototype.hasOwnProperty.call(this.latencies[request_id], details.url)) { return 0; } diff --git a/src/classes/Metrics.js b/src/classes/Metrics.js index 1ef073f08..7843f6774 100644 --- a/src/classes/Metrics.js +++ b/src/classes/Metrics.js @@ -132,13 +132,13 @@ class Metrics { getActiveTab((tab) => { const tabUrl = tab && tab.url ? tab.url : ''; - this._brokenPageWatcher = Object.assign({}, { + this._brokenPageWatcher = { on: true, triggerId, triggerTime: Date.now(), timeoutId: setTimeout(this._clearBrokenPageWatcherTimeout.bind(this), BROKEN_PAGE_METRICS_THRESHOLD), - url: tabUrl, - }); + url: tabUrl + }; }); } @@ -149,13 +149,13 @@ class Metrics { _unplugBrokenPageWatcher() { this._clearBrokenPageWatcherTimeout(); - this._brokenPageWatcher = Object.assign({}, { + this._brokenPageWatcher = { on: false, triggerId: '', triggerTime: '', timeoutId: null, - url: '', - }); + url: '' + }; } _clearBrokenPageWatcherTimeout() { @@ -346,21 +346,21 @@ class Metrics { // Type of blocking selected during setup `&sb=${encodeURIComponent(conf.setup_block.toString())}` + // Recency, days since last active daily ping - `&rc=${encodeURIComponent(this._getRecencyActive(type, frequency).toString())}` + + `&rc=${encodeURIComponent(Metrics._getRecencyActive(type, frequency).toString())}` + // New parameters to Ghostery 8.3 // Subscription Type - `&st=${encodeURIComponent(this._getSubscriptionType().toString())}` + + `&st=${encodeURIComponent(Metrics._getSubscriptionType().toString())}` + // Whether the computer ever had a Paid Subscription `&ps=${encodeURIComponent(conf.paid_subscription ? '1' : '0')}` + // Active Velocity - `&va=${encodeURIComponent(this._getVelocityActive(type).toString())}` + + `&va=${encodeURIComponent(Metrics._getVelocityActive(type).toString())}` + // Engaged Recency - `&re=${encodeURIComponent(this._getRecencyEngaged(type, frequency).toString())}` + + `&re=${encodeURIComponent(Metrics._getRecencyEngaged(type, frequency).toString())}` + // Engaged Velocity - `&ve=${encodeURIComponent(this._getVelocityEngaged(type).toString())}` + + `&ve=${encodeURIComponent(Metrics._getVelocityEngaged(type).toString())}` + // Theme - `&th=${encodeURIComponent(this._getThemeValue().toString())}`; + `&th=${encodeURIComponent(Metrics._getThemeValue().toString())}`; if (CAMPAIGN_METRICS.includes(type)) { // only send campaign attribution when necessary @@ -439,7 +439,7 @@ class Metrics { * * @return {number} in days since the last daily active ping */ - _getRecencyActive(type, frequency) { + static _getRecencyActive(type, frequency) { if (conf.metrics.active_daily && (type === 'active' || type === 'engaged') && frequency === 'daily') { return Math.floor((Number(new Date().getTime()) - conf.metrics.active_daily) / 86400000); } @@ -453,7 +453,7 @@ class Metrics { * * @return {number} in days since the last daily engaged ping */ - _getRecencyEngaged(type, frequency) { + static _getRecencyEngaged(type, frequency) { if (conf.metrics.engaged_daily && (type === 'active' || type === 'engaged') && frequency === 'daily') { return Math.floor((Number(new Date().getTime()) - conf.metrics.engaged_daily) / 86400000); } @@ -465,7 +465,7 @@ class Metrics { * @private * @return {number} The Active Velocity */ - _getVelocityActive(type) { + static _getVelocityActive(type) { if (type !== 'active' && type !== 'engaged') { return -1; } @@ -479,7 +479,7 @@ class Metrics { * @private * @return {number} The Engaged Velocity */ - _getVelocityEngaged(type) { + static _getVelocityEngaged(type) { if (type !== 'active' && type !== 'engaged') { return -1; } @@ -492,7 +492,7 @@ class Metrics { * Get the Subscription Type * @return {string} Subscription Name */ - _getSubscriptionType() { + static _getSubscriptionType() { if (!conf.account) { return -1; } @@ -508,7 +508,7 @@ class Metrics { * @private * @return {number} value associated with the Current Theme */ - _getThemeValue() { + static _getThemeValue() { const { current_theme } = conf; switch (current_theme) { case 'midnight-theme': @@ -531,7 +531,7 @@ class Metrics { * @param {string} frequency one of 'all', 'daily', 'weekly' * @return {number} number in milliseconds over the frequency since the last ping */ - _timeToExpired(type, frequency) { + static _timeToExpired(type, frequency) { if (frequency === 'all') { return 0; } @@ -552,7 +552,7 @@ class Metrics { * @return {boolean} true/false */ _checkPing(type, frequency) { - const result = this._timeToExpired(type, frequency); + const result = Metrics._timeToExpired(type, frequency); if (result > 0) { return false; } @@ -629,7 +629,7 @@ class Metrics { } conf.metrics.active_daily_velocity = active_daily_velocity; - const daily = this._timeToExpired('active', 'daily'); + const daily = Metrics._timeToExpired('active', 'daily'); if (daily > 0) { setTimeout(() => { this._sendReq('active', ['daily']); @@ -644,7 +644,7 @@ class Metrics { }, FREQUENCIES.daily); } - const weekly = this._timeToExpired('active', 'weekly'); + const weekly = Metrics._timeToExpired('active', 'weekly'); if (weekly > 0) { setTimeout(() => { this._sendReq('active', ['weekly']); @@ -659,7 +659,7 @@ class Metrics { }, FREQUENCIES.weekly); } - const monthly = this._timeToExpired('active', 'monthly'); + const monthly = Metrics._timeToExpired('active', 'monthly'); if (monthly > 0) { if (monthly <= FREQUENCIES.biweekly) { setTimeout(() => { diff --git a/src/classes/Module.js b/src/classes/Module.js index 60170f87b..e1ec1a13a 100644 --- a/src/classes/Module.js +++ b/src/classes/Module.js @@ -30,7 +30,7 @@ const background = baseBackground({ }); class GhosteryModule extends Module { - get _module() { + static get _module() { return background; } } diff --git a/src/classes/PanelData.js b/src/classes/PanelData.js index 281433511..9b38ee70b 100644 --- a/src/classes/PanelData.js +++ b/src/classes/PanelData.js @@ -23,17 +23,16 @@ import globals from './Globals'; import metrics from './Metrics'; import Policy from './Policy'; import tabInfo from './TabInfo'; -import rewards from './Rewards'; +import Rewards from './Rewards'; import account from './Account'; import dispatcher from './Dispatcher'; import promoModals from './PromoModals'; import { getCliqzGhosteryBugs, sendCliqzModuleCounts } from '../utils/cliqzModulesData'; import { getActiveTab, flushChromeMemoryCache, processUrl } from '../utils/utils'; -import { objectEntries, log } from '../utils/common'; +import { log } from '../utils/common'; const SYNC_SET = new Set(globals.SYNC_ARRAY); const { IS_CLIQZ } = globals; -const policy = new Policy(); /** * PanelData coordinates the assembly and transmission of data to the extension panel @@ -76,7 +75,7 @@ class PanelData { const { url } = tab; this._activeTab = tab; - this._activeTab.pageHost = url && processUrl(url).hostname || ''; + this._activeTab.pageHost = (url && processUrl(url).hostname) || ''; this._attachListeners(); @@ -118,16 +117,16 @@ class PanelData { break; case 'RewardsComponentDidMount': this._mountedComponents.rewards = true; - this._panelPort.onDisconnect.addListener(rewards.panelHubClosedListener); + this._panelPort.onDisconnect.addListener(Rewards.panelHubClosedListener); this._postRewardsData(); break; case 'RewardsComponentWillUnmount': this._mountedComponents.rewards = false; - this._panelPort.onDisconnect.removeListener(rewards.panelHubClosedListener); + this._panelPort.onDisconnect.removeListener(Rewards.panelHubClosedListener); break; case 'SettingsComponentDidMount': this._mountedComponents.settings = true; - this._postMessage('settings', this._getSettingsData()); + this._postMessage('settings', PanelData._getSettingsData()); break; case 'SettingsComponentWillUnmount': this._mountedComponents.settings = false; @@ -167,13 +166,13 @@ class PanelData { get(view, tab) { // Hub and Android panel if (view === 'settings') { - return this._getSettingsData(); + return PanelData._getSettingsData(); } // Android panel only const { url } = tab; this._activeTab = tab; - this._activeTab.pageHost = url && processUrl(url).hostname || ''; + this._activeTab.pageHost = (url && processUrl(url).hostname) || ''; this._setTrackerListAndCategories(); switch (view) { case 'panel': @@ -247,21 +246,22 @@ class PanelData { site_specific_blocks, site_specific_unblocks, toggle_individual_trackers, } = conf; - return Object.assign({}, { + return { expand_all_trackers, selected_app_ids, show_tracker_urls, site_specific_blocks, site_specific_unblocks, - toggle_individual_trackers - }, this._getDynamicBlockingData()); + toggle_individual_trackers, + ...this._getDynamicBlockingData() + }; } /** * Helper that retrieves the current account information * @return {Object|null} the current account object or null */ - _getCurrentAccount() { + static _getCurrentAccount() { const currentAccount = conf.account; if (currentAccount && currentAccount.user) { currentAccount.user.subscriptionsPlus = account.hasScopesUnverified(['subscriptions:plus']); @@ -301,7 +301,7 @@ class PanelData { return { needsReload: needsReload || { changes: {} }, smartBlock, - account: this._getCurrentAccount(), + account: PanelData._getCurrentAccount(), }; } @@ -336,7 +336,7 @@ class PanelData { trackers_banner_status, } = conf; - return Object.assign({}, { + return { current_theme, enable_ad_block, enable_anti_tracking, @@ -350,7 +350,8 @@ class PanelData { reload_banner_status, tab_id, trackers_banner_status, - }, this._getDynamicPanelData(tab_id)); + ...this._getDynamicPanelData(tab_id) + }; } /** @@ -369,7 +370,7 @@ class PanelData { * Get rewards data for the Rewards View * @return {Object} Rewards view data */ - _getRewardsData() { + static _getRewardsData() { return { enable_offers: conf.enable_offers, }; @@ -380,25 +381,23 @@ class PanelData { * Called when and only when the Settings component is mounted * @return {Object} Settings View data */ - _getSettingsData() { + static _getSettingsData() { const { bugs_last_updated, language, new_app_ids, settings_last_exported, settings_last_imported } = conf; - return Object.assign( - {}, - { - bugs_last_updated, - categories: this._buildGlobalCategories(), - language, // required for the setup page that does not have access to panelView data - new_app_ids, - offer_human_web: true, - settings_last_exported, - settings_last_imported, - }, - this._getUserSettingsForSettingsView(conf), - ); + return { + + bugs_last_updated, + categories: PanelData._buildGlobalCategories(), + language, // required for the setup page that does not have access to panelView data + new_app_ids, + offer_human_web: true, + settings_last_exported, + settings_last_imported, + ...PanelData._getUserSettingsForSettingsView(conf), + }; } /** @@ -412,20 +411,18 @@ class PanelData { const { paused_blocking, paused_blocking_timeout } = globals.SESSION; const { site_blacklist, site_whitelist } = conf; - return Object.assign( - {}, - { - paused_blocking, - paused_blocking_timeout, - site_blacklist, - site_whitelist, - pageHost, - pageUrl: url || '', - siteNotScanned: !this._trackerList || false, - sitePolicy: policy.getSitePolicy(url) || false, - }, - this._getDynamicSummaryData() - ); + return { + + paused_blocking, + paused_blocking_timeout, + site_blacklist, + site_whitelist, + pageHost, + pageUrl: url || '', + siteNotScanned: !this._trackerList || false, + sitePolicy: Policy.getSitePolicy(url) || false, + ...this._getDynamicSummaryData() + }; } /** @@ -433,7 +430,7 @@ class PanelData { * Invoked if Blocking component is mounted when account.getUserSettings() resolves, max one time per panel open. * @param {Object} userSettings the settings retrieved by account.getUserSettings() in _initPort */ - _getUserSettingsForBlockingView(userSettings) { + static _getUserSettingsForBlockingView(userSettings) { const { expand_all_trackers, selected_app_ids, show_tracker_urls, site_specific_blocks, site_specific_unblocks, toggle_individual_trackers, @@ -454,7 +451,7 @@ class PanelData { * Invoked if Panel is still open account.getUserSettings() resolves, max one time per panel open. * @param {Object} userSettings the settings retrieved by account.getUserSettings() in _initPort */ - _getUserSettingsForPanelView(userSettings) { + static _getUserSettingsForPanelView(userSettings) { const { current_theme, enable_ad_block, enable_anti_tracking, enable_smart_block, enable_offers, is_expanded, is_expert, reload_banner_status, trackers_banner_status, @@ -470,7 +467,7 @@ class PanelData { is_expert, reload_banner_status, trackers_banner_status, - account: this._getCurrentAccount(), + account: PanelData._getCurrentAccount(), }; } @@ -479,7 +476,7 @@ class PanelData { * Invoked if Settings component is mounted when account.getUserSettings() resolves, max one time per panel open. * @param {Object} userSettings the settings retrieved by account.getUserSettings() in _initPort, or the conf object provided by getSettings */ - _getUserSettingsForSettingsView(userSettingsSource) { + static _getUserSettingsForSettingsView(userSettingsSource) { const { alert_bubble_pos, alert_bubble_timeout, block_by_default, cliqz_adb_mode, enable_autoupdate, enable_click2play, enable_click2play_social, enable_human_web, enable_offers, @@ -545,7 +542,7 @@ class PanelData { * @private */ _postRewardsData() { - this._postMessage('rewards', this._getRewardsData()); + this._postMessage('rewards', PanelData._getRewardsData()); } /** @@ -556,16 +553,16 @@ class PanelData { _postUserSettings(userSettings) { if (!this._panelPort || !this._activeTab) { return; } - this._postMessage('panel', this._getUserSettingsForPanelView(userSettings)); + this._postMessage('panel', PanelData._getUserSettingsForPanelView(userSettings)); const { blocking, settings } = this._mountedComponents; if (blocking) { - this._postMessage('blocking', this._getUserSettingsForBlockingView(userSettings)); + this._postMessage('blocking', PanelData._getUserSettingsForBlockingView(userSettings)); } if (settings) { - this._postMessage('settings', this._getUserSettingsForSettingsView(userSettings)); + this._postMessage('settings', PanelData._getUserSettingsForSettingsView(userSettings)); } } // [/DATA TRANSFER] @@ -575,9 +572,10 @@ class PanelData { /** * Update Conf properties with new data from the UI. * Called via setPanelData message. - * @param {Object} data + * @param {Object} d */ - set(data) { + set(d) { + const data = d; let syncSetDataChanged = false; if (IS_CLIQZ) { @@ -588,9 +586,11 @@ class PanelData { } // Set the conf from data - // TODO can this now be replaced by Object.entries? - for (const [key, value] of objectEntries(data)) { - if (conf.hasOwnProperty(key) && !isEqual(conf[key], value)) { + const dataKeys = Object.keys(data); + for (let i = 0; i < dataKeys.length; i++) { + const key = dataKeys[i]; + const value = data[key]; + if (Object.prototype.hasOwnProperty.call(conf, key) && !isEqual(conf[key], value)) { conf[key] = value; syncSetDataChanged = SYNC_SET.has(key) ? true : syncSetDataChanged; // TODO refactor - this work should probably be the direct responsibility of Globals @@ -602,13 +602,13 @@ class PanelData { setTimeout(() => { globals.SESSION.paused_blocking = false; - this._toggleBlockingHelper(); + PanelData._toggleBlockingHelper(); }, value); } else { globals.SESSION.paused_blocking = value; globals.SESSION.paused_blocking_timeout = 0; } - this._toggleBlockingHelper(); + PanelData._toggleBlockingHelper(); } } @@ -633,7 +633,7 @@ class PanelData { /** * Notifies interested parties when blocking is paused / unpaused */ - _toggleBlockingHelper() { + static _toggleBlockingHelper() { button.update(); flushChromeMemoryCache(); dispatcher.trigger('globals.save.paused_blocking'); @@ -659,13 +659,13 @@ class PanelData { cat = 'uncategorized'; } - if (categories.hasOwnProperty(cat)) { + if (Object.prototype.hasOwnProperty.call(categories, cat)) { categories[cat].num_total++; - if (this._addsUpToBlocked(trackerState)) { categories[cat].num_blocked++; } + if (PanelData._addsUpToBlocked(trackerState)) { categories[cat].num_blocked++; } } else { - categories[cat] = this._buildCategory(cat, trackerState); + categories[cat] = PanelData._buildCategory(cat, trackerState); } - categories[cat].trackers.push(this._buildTracker(tracker, trackerState, smartBlock)); + categories[cat].trackers.push(PanelData._buildTracker(tracker, trackerState, smartBlock)); }); const categoryArray = Object.values(categories); @@ -684,7 +684,7 @@ class PanelData { * @param {Object} trackerState object containing various block/allow states of a tracker * @return {boolean} is the tracker blocked in one of the possible ways? */ - _addsUpToBlocked({ + static _addsUpToBlocked({ ss_blocked, sb_blocked, blocked, ss_allowed, sb_allowed }) { return (ss_blocked || sb_blocked || (blocked && !ss_allowed && !sb_allowed)); @@ -696,7 +696,7 @@ class PanelData { * @param {Object} trackerState object containing various block/allow states of a tracker * @return {Object} an object with data for a new category */ - _buildCategory(category, trackerState) { + static _buildCategory(category, trackerState) { return { id: category, name: t(`category_${category}`), @@ -704,7 +704,7 @@ class PanelData { img_name: (category === 'advertising') ? 'adv' : // Because AdBlock blocks images with 'advertising' in the name. (category === 'social_media') ? 'smed' : category, // Because AdBlock blocks images with 'social' in the name. num_total: 1, - num_blocked: this._addsUpToBlocked(trackerState) ? 1 : 0, + num_blocked: PanelData._addsUpToBlocked(trackerState) ? 1 : 0, trackers: [] }; } @@ -718,7 +718,7 @@ class PanelData { * @param {Object} smartBlock smart blocking stats for the active tab * @return {Object} object of tracker data */ - _buildTracker(tracker, trackerState, smartBlock) { + static _buildTracker(tracker, trackerState, smartBlock) { const { cat, cliqzAdCount, @@ -746,7 +746,7 @@ class PanelData { warningCompatibility: hasCompatibilityIssue, warningInsecure: hasInsecureIssue, warningSlow: hasLatencyIssue, - warningSmartBlock: (smartBlock.blocked.hasOwnProperty(id) && 'blocked') || (smartBlock.unblocked.hasOwnProperty(id) && 'unblocked') || false, + warningSmartBlock: (Object.prototype.hasOwnProperty.call(smartBlock.blocked, id) && 'blocked') || (Object.prototype.hasOwnProperty.call(smartBlock.unblocked, id) && 'unblocked') || false, cliqzAdCount, cliqzCookieCount, cliqzFingerprintCount, @@ -771,11 +771,11 @@ class PanelData { const pageBlocks = (pageHost && conf.site_specific_blocks[pageHost]) || []; return { - blocked: selectedAppIds.hasOwnProperty(trackerId), + blocked: Object.prototype.hasOwnProperty.call(selectedAppIds, trackerId), ss_allowed: pageUnblocks.includes(+trackerId), ss_blocked: pageBlocks.includes(+trackerId), - sb_blocked: smartBlockActive && smartBlock.blocked.hasOwnProperty(`${trackerId}`), - sb_allowed: smartBlockActive && smartBlock.unblocked.hasOwnProperty(`${trackerId}`) + sb_blocked: smartBlockActive && Object.prototype.hasOwnProperty.call(smartBlock.blocked, `${trackerId}`), + sb_allowed: smartBlockActive && Object.prototype.hasOwnProperty.call(smartBlock.unblocked, `${trackerId}`) }; } @@ -784,16 +784,16 @@ class PanelData { * @private * @return {array} array of categories */ - _buildGlobalCategories() { + static _buildGlobalCategories() { const categories = bugDb.db.categories || []; const selectedApps = conf.selected_app_ids || {}; - categories.forEach((category) => { - const { trackers } = category; - category.num_blocked = 0; - trackers.forEach((tracker) => { - tracker.blocked = selectedApps.hasOwnProperty(tracker.id); - if (tracker.blocked) { - category.num_blocked++; + categories.forEach((categoryEl) => { + const { trackers } = categoryEl; + categoryEl.num_blocked = 0; + trackers.forEach((trackerEl) => { + trackerEl.blocked = Object.prototype.hasOwnProperty.call(selectedApps, trackerEl.id); + if (trackerEl.blocked) { + categoryEl.num_blocked++; } }); }); diff --git a/src/classes/Policy.js b/src/classes/Policy.js index d8b30f814..50b9f23a8 100644 --- a/src/classes/Policy.js +++ b/src/classes/Policy.js @@ -45,11 +45,11 @@ class Policy { * @param {string} url site url * @return {boolean} */ - getSitePolicy(hostUrl, trackerUrl) { - if (this.blacklisted(hostUrl)) { + static getSitePolicy(hostUrl, trackerUrl) { + if (Policy.blacklisted(hostUrl)) { return globals.BLACKLISTED; } - if (this.checkSiteWhitelist(hostUrl) || this.checkCliqzModuleWhitelist(hostUrl, trackerUrl)) { + if (Policy.checkSiteWhitelist(hostUrl) || Policy.checkCliqzModuleWhitelist(hostUrl, trackerUrl)) { return globals.WHITELISTED; } return false; @@ -60,7 +60,7 @@ class Policy { * @param {string} url site url * @return {string|boolean} corresponding whitelist entry or false, if none */ - checkSiteWhitelist(url) { + static checkSiteWhitelist(url) { const hostUrl = processUrl(url).host; if (hostUrl) { const replacedUrl = hostUrl.replace(/^www\./, ''); @@ -73,7 +73,7 @@ class Policy { if (!sites[i].includes('*') && replacedUrl === sites[i]) { return sites[i]; } - if (this.matchesWildcard(replacedUrl, sites[i])) { + if (Policy.matchesWildcard(replacedUrl, sites[i])) { return sites[i]; } } @@ -87,7 +87,7 @@ class Policy { * @param {string} url site url * @return {string|boolean} corresponding whitelist entry or false, if none */ - checkCliqzModuleWhitelist(hostUrl, trackerUrl) { + static checkCliqzModuleWhitelist(hostUrl, trackerUrl) { let isWhitelisted = false; const processedHostUrl = processUrl(hostUrl).host; const processedTrackerUrl = processUrl(trackerUrl).host; @@ -111,7 +111,7 @@ class Policy { * @param {string} url site url * @return {string|boolean} corresponding blacklist entry or false, if none */ - blacklisted(url) { + static blacklisted(url) { const hostUrl = processUrl(url).host; if (hostUrl) { const replacedUrl = hostUrl.replace(/^www\./, ''); @@ -124,7 +124,7 @@ class Policy { if (!sites[i].includes('*') && replacedUrl === sites[i]) { return sites[i]; } - if (this.matchesWildcard(replacedUrl, sites[i])) { + if (Policy.matchesWildcard(replacedUrl, sites[i])) { return sites[i]; } } @@ -149,24 +149,24 @@ class Policy { * @param {string} tab_url tab url * @return {BlockWithReason} block result with reason */ - shouldBlock(app_id, cat_id, tab_id, tab_host, tab_url) { + static shouldBlock(app_id, cat_id, tab_id, tab_host, tab_url) { if (globals.SESSION.paused_blocking) { return { block: false, reason: BLOCK_REASON_BLOCK_PAUSED }; } const allowedOnce = c2pDb.allowedOnce(tab_id, app_id); // The app_id has been globally blocked - if (conf.selected_app_ids.hasOwnProperty(app_id)) { + if (Object.prototype.hasOwnProperty.call(conf.selected_app_ids, app_id)) { // The app_id is on the site-specific allow list for this tab_host - if (conf.toggle_individual_trackers && conf.site_specific_unblocks.hasOwnProperty(tab_host) && conf.site_specific_unblocks[tab_host].includes(+app_id)) { + if (conf.toggle_individual_trackers && Object.prototype.hasOwnProperty.call(conf.site_specific_unblocks, tab_host) && conf.site_specific_unblocks[tab_host].includes(+app_id)) { // Site blacklist overrides all block settings except C2P allow once - if (this.blacklisted(tab_url)) { + if (Policy.blacklisted(tab_url)) { return { block: !allowedOnce, reason: allowedOnce ? BLOCK_REASON_C2P_ALLOWED_ONCE : BLOCK_REASON_BLACKLISTED }; } return { block: false, reason: BLOCK_REASON_SS_UNBLOCKED }; } // Check for site white-listing - if (this.checkSiteWhitelist(tab_url)) { + if (Policy.checkSiteWhitelist(tab_url)) { return { block: false, reason: BLOCK_REASON_WHITELISTED }; } // The app_id is globally blocked @@ -175,23 +175,23 @@ class Policy { // The app_id has not been globally blocked // Check to see if the app_id is on the site-specific block list for this tab_host - if (conf.toggle_individual_trackers && conf.site_specific_blocks.hasOwnProperty(tab_host) && conf.site_specific_blocks[tab_host].includes(+app_id)) { + if (conf.toggle_individual_trackers && Object.prototype.hasOwnProperty.call(conf.site_specific_blocks, tab_host) && conf.site_specific_blocks[tab_host].includes(+app_id)) { // Site white-listing overrides blocking settings - if (this.checkSiteWhitelist(tab_url)) { + if (Policy.checkSiteWhitelist(tab_url)) { return { block: false, reason: BLOCK_REASON_WHITELISTED }; } return { block: !allowedOnce, reason: allowedOnce ? BLOCK_REASON_C2P_ALLOWED_ONCE : BLOCK_REASON_SS_BLOCKED }; } // Check to see if the app_id is on the site-specific allow list for this tab_host - if (conf.toggle_individual_trackers && conf.site_specific_unblocks.hasOwnProperty(tab_host) && conf.site_specific_unblocks[tab_host].includes(+app_id)) { + if (conf.toggle_individual_trackers && Object.prototype.hasOwnProperty.call(conf.site_specific_unblocks, tab_host) && conf.site_specific_unblocks[tab_host].includes(+app_id)) { // Site blacklist overrides all block settings except C2P allow once - if (this.blacklisted(tab_url)) { + if (Policy.blacklisted(tab_url)) { return { block: !allowedOnce, reason: allowedOnce ? BLOCK_REASON_C2P_ALLOWED_ONCE : BLOCK_REASON_BLACKLISTED }; } return { block: false, reason: BLOCK_REASON_SS_UNBLOCKED }; } // Check for site black-listing - if (this.blacklisted(tab_url)) { + if (Policy.blacklisted(tab_url)) { return { block: !allowedOnce, reason: allowedOnce ? BLOCK_REASON_C2P_ALLOWED_ONCE : BLOCK_REASON_BLACKLISTED }; } // The app_id is globally unblocked @@ -204,7 +204,7 @@ class Policy { * @param {string} pattern regex pattern * @return {boolean} */ - matchesWildcard(url, pattern) { + static matchesWildcard(url, pattern) { if (pattern && pattern.includes('*')) { const wildcardPattern = pattern.replace(/\*/g, '.*'); try { diff --git a/src/classes/PolicySmartBlock.js b/src/classes/PolicySmartBlock.js index 8bed9ea1d..7aa1cf834 100644 --- a/src/classes/PolicySmartBlock.js +++ b/src/classes/PolicySmartBlock.js @@ -51,17 +51,17 @@ class PolicySmartBlock { * applicable to this url, or none are met. */ shouldUnblock(appId, catId, tabId, pageURL, requestType) { - if (!this.shouldCheck(tabId, appId)) { return false; } + if (!PolicySmartBlock.shouldCheck(tabId, appId)) { return false; } let reason; - if (this._appHasKnownIssue(tabId, appId, pageURL)) { + if (PolicySmartBlock._appHasKnownIssue(tabId, appId, pageURL)) { reason = 'hasIssue'; // allow if tracker is in compatibility list } else if (this._allowedCategories(tabId, appId, catId)) { reason = 'allowedCategory'; // allow if tracker is in breaking category } else if (this._allowedTypes(tabId, appId, requestType)) { reason = 'allowedType'; // allow if tracker is in breaking type - } else if (this._pageWasReloaded(tabId, appId)) { + } else if (PolicySmartBlock._pageWasReloaded(tabId, appId)) { reason = 'pageReloaded'; // allow if page has been reloaded recently } @@ -85,21 +85,21 @@ class PolicySmartBlock { * applicable to this url, or none are met. */ shouldBlock(appId, catId, tabId, pageURL, requestType, requestTimestamp) { - if (!this.shouldCheck(tabId, appId)) { return false; } + if (!PolicySmartBlock.shouldCheck(tabId, appId)) { return false; } let reason; // Block all trackers that load after 5 seconds from when page load started - if (this._requestWasSlow(tabId, appId, requestTimestamp)) { + if (PolicySmartBlock._requestWasSlow(tabId, appId, requestTimestamp)) { reason = 'slow'; - if (this._appHasKnownIssue(tabId, appId, pageURL)) { + if (PolicySmartBlock._appHasKnownIssue(tabId, appId, pageURL)) { reason = 'hasIssue'; // allow if tracker is in compatibility list } else if (this._allowedCategories(tabId, appId, catId)) { reason = 'allowedCategory'; // allow if tracker is in breaking category } else if (this._allowedTypes(tabId, appId, requestType)) { reason = 'allowedType'; // allow if tracker is in breaking type - } else if (this._pageWasReloaded(tabId, appId)) { + } else if (PolicySmartBlock._pageWasReloaded(tabId, appId)) { reason = 'pageReloaded'; // allow if page has been reloaded recently } } @@ -127,17 +127,17 @@ class PolicySmartBlock { * @param {string | boolean} appId tracker id * @return {boolean} */ - shouldCheck(tabId, appId = false) { + static shouldCheck(tabId, appId = false) { const tabUrl = tabInfo.getTabInfo(tabId, 'url'); const tabHost = tabInfo.getTabInfo(tabId, 'host'); return ( conf.enable_smart_block && !globals.SESSION.paused_blocking && - !this.policy.getSitePolicy(tabUrl) && - ((appId && (!conf.site_specific_unblocks.hasOwnProperty(tabHost) || !conf.site_specific_unblocks[tabHost].includes(+appId))) || appId === false) && - ((appId && (!conf.site_specific_blocks.hasOwnProperty(tabHost) || !conf.site_specific_blocks[tabHost].includes(+appId))) || appId === false) && - (c2pDb.db.apps && !c2pDb.db.apps.hasOwnProperty(appId)) + !Policy.getSitePolicy(tabUrl) && + ((appId && (!Object.prototype.hasOwnProperty.call(conf.site_specific_unblocks, tabHost) || !conf.site_specific_unblocks[tabHost].includes(+appId))) || appId === false) && + ((appId && (!Object.prototype.hasOwnProperty.call(conf.site_specific_blocks, tabHost) || !conf.site_specific_blocks[tabHost].includes(+appId))) || appId === false) && + (c2pDb.db.apps && !Object.prototype.hasOwnProperty.call(c2pDb.db.apps, appId)) ); } @@ -148,8 +148,8 @@ class PolicySmartBlock { * @param {string} requestDomain domain of the request * @return {boolean} */ - isFirstPartyRequest(tabId, pageDomain = '', requestDomain = '') { - if (!this.shouldCheck(tabId)) { return false; } + static isFirstPartyRequest(tabId, pageDomain = '', requestDomain = '') { + if (!PolicySmartBlock.shouldCheck(tabId)) { return false; } return pageDomain === requestDomain; } @@ -159,7 +159,7 @@ class PolicySmartBlock { * @param {number} tabId tab id * @return {boolean} */ - _pageWasReloaded(tabId) { + static _pageWasReloaded(tabId) { return tabInfo.getTabInfo(tabId, 'reloaded') || false; } @@ -170,7 +170,7 @@ class PolicySmartBlock { * @param {string} pageURL tab url * @return {boolean} */ - _appHasKnownIssue(tabId, appId, pageURL) { + static _appHasKnownIssue(tabId, appId, pageURL) { return compDb.hasIssue(appId, pageURL); } @@ -182,8 +182,8 @@ class PolicySmartBlock { * @param {string} requestHost host of the request url * @return {boolean} */ - isInsecureRequest(tabId, pageProtocol, requestProtocol, requestHost) { - if (!this.shouldCheck(tabId)) { return false; } + static isInsecureRequest(tabId, pageProtocol, requestProtocol, requestHost) { + if (!PolicySmartBlock.shouldCheck(tabId)) { return false; } // don't block mixed content from localhost if (requestHost === 'localhost' || requestHost === '127.0.0.1' || requestHost === '[::1]') { @@ -192,7 +192,7 @@ class PolicySmartBlock { return ( pageProtocol === 'https' && - (requestProtocol === 'http' || requestProtocol === 'ws') || false + ((requestProtocol === 'http' || requestProtocol === 'ws') || false) ); } @@ -223,8 +223,8 @@ class PolicySmartBlock { * @param {string} tabId tab id * @return {boolean} */ - checkReloadThreshold(tabId) { - if (!this.shouldCheck(tabId)) { return false; } + static checkReloadThreshold(tabId) { + if (!PolicySmartBlock.shouldCheck(tabId)) { return false; } // Note that this threshold is different from the broken page ping threshold in Metrics, which is 60 seconds // see GH-1797 for more details @@ -232,7 +232,7 @@ class PolicySmartBlock { return ( tabInfo.getTabInfoPersist(tabId, 'numOfReloads') > 1 && - ((Date.now() - tabInfo.getTabInfoPersist(tabId, 'firstLoadTimestamp')) < SMART_BLOCK_BEHAVIOR_THRESHOLD) || false + (((Date.now() - tabInfo.getTabInfoPersist(tabId, 'firstLoadTimestamp')) < SMART_BLOCK_BEHAVIOR_THRESHOLD) || false) ); } @@ -243,7 +243,7 @@ class PolicySmartBlock { * @param {number} requestTimestamp timestamp of the request * @return {boolean} */ - _requestWasSlow(tabId, appId, requestTimestamp) { + static _requestWasSlow(tabId, appId, requestTimestamp) { const THRESHHOLD = 5000; // 5 seconds const pageTimestamp = tabInfo.getTabInfo(tabId, 'timestamp'); // TODO: account for lazy-load or widgets triggered by user interaction beyond 5sec diff --git a/src/classes/PromoModals.js b/src/classes/PromoModals.js index 2f49320a9..292ea0d9c 100644 --- a/src/classes/PromoModals.js +++ b/src/classes/PromoModals.js @@ -102,7 +102,7 @@ class PromoModals { static _hasEngagedFrequently() { const { engaged_daily_count } = conf.metrics || []; - const very_engaged_days = engaged_daily_count.reduce((acc, count) => (count >= DAILY_INSIGHTS_TARGET ? ++acc : acc), 0); + const very_engaged_days = engaged_daily_count.reduce((acc, count) => (count >= DAILY_INSIGHTS_TARGET ? acc + 1 : acc), 0); return very_engaged_days >= WEEKLY_INSIGHTS_TARGET; } diff --git a/src/classes/PurpleBox.js b/src/classes/PurpleBox.js index 8f3cf7bbb..baa62631f 100644 --- a/src/classes/PurpleBox.js +++ b/src/classes/PurpleBox.js @@ -30,7 +30,6 @@ const t = chrome.i18n.getMessage; */ class PurpleBox { constructor() { - this.policy = new Policy(); this.channelsSupported = (typeof chrome.runtime.onConnect === 'object'); this.ports = new Map(); } @@ -48,7 +47,7 @@ class PurpleBox { // Skip in the event of pause, trust, prefetching, newtab page, or Firefox about:pages if (!conf.show_alert || globals.SESSION.paused_blocking || - (conf.hide_alert_trusted && !!this.policy.checkSiteWhitelist(tab.url)) || + (conf.hide_alert_trusted && !!Policy.checkSiteWhitelist(tab.url)) || !tab || tab.purplebox || tab.path.includes('_/chrome/newtab') || tab.protocol === 'about' || globals.EXCLUDES.includes(tab.host)) { return Promise.resolve(false); } diff --git a/src/classes/Rewards.js b/src/classes/Rewards.js index b38c06cbb..e8182648a 100644 --- a/src/classes/Rewards.js +++ b/src/classes/Rewards.js @@ -20,11 +20,7 @@ import { log } from '../utils/common'; * @memberOf BackgroundClasses */ class Rewards { - constructor() { - this.panelHubClosedListener = this.panelHubClosedListener.bind(this); - } - - sendSignal(message) { + static sendSignal(message) { if (!conf.enable_offers) { return; } @@ -45,8 +41,8 @@ class Rewards { cliqz.modules['offers-v2'].background.actions.processRealEstateMessage(signal); } - panelHubClosedListener() { - this.sendSignal({ + static panelHubClosedListener() { + Rewards.sendSignal({ offerId: null, actionId: 'hub_closed', origin: 'rewards-hub', @@ -55,4 +51,4 @@ class Rewards { } } -export default new Rewards(); +export default Rewards; diff --git a/src/classes/SurrogateDb.js b/src/classes/SurrogateDb.js index 5fc99ba05..f5856f102 100644 --- a/src/classes/SurrogateDb.js +++ b/src/classes/SurrogateDb.js @@ -47,7 +47,7 @@ class SurrogateDb extends Updatable { * @override * */ - update() {} + static update() {} /** * Process surrogates from fetched json @@ -57,29 +57,30 @@ class SurrogateDb extends Updatable { processList(fromMemory, data) { log('processing surrogates...'); - data.mappings.forEach((s) => { + data.mappings.forEach((souragate) => { + const s = souragate; s.code = data.surrogates[s.sid]; // convert single values to arrays first ['pattern_id', 'app_id', 'sites', 'match'].forEach((prop) => { - if (s.hasOwnProperty(prop) && !isArray(s[prop])) { + if (Object.prototype.hasOwnProperty.call(s, prop) && !isArray(s[prop])) { s[prop] = [s[prop]]; } }); // initialize regexes - if (s.hasOwnProperty('match')) { + if (Object.prototype.hasOwnProperty.call(s, 'match')) { s.match = map(s.match, match => new RegExp(match, '')); } - if (s.hasOwnProperty('pattern_id') || s.hasOwnProperty('app_id')) { + if (Object.prototype.hasOwnProperty.call(s, 'pattern_id') || Object.prototype.hasOwnProperty.call(s, 'app_id')) { // tracker-level surrogate - if (s.hasOwnProperty('pattern_id')) { + if (Object.prototype.hasOwnProperty.call(s, 'pattern_id')) { this._buildDb(s, 'pattern_id', 'pattern_ids'); - } else if (s.hasOwnProperty('app_id')) { + } else if (Object.prototype.hasOwnProperty.call(s, 'app_id')) { this._buildDb(s, 'app_id', 'app_ids'); } - } else if (s.hasOwnProperty('sites')) { + } else if (Object.prototype.hasOwnProperty.call(s, 'sites')) { // we have a "sites" property, but not pattern_id/app_id: // it's a site surrogate this._buildDb(s, 'sites', 'site_surrogates'); @@ -103,23 +104,23 @@ class SurrogateDb extends Updatable { getForTracker(script_src, app_id, pattern_id, host_name) { let candidates = []; - if (this.db.app_ids.hasOwnProperty(app_id)) { + if (Object.prototype.hasOwnProperty.call(this.db.app_ids, app_id)) { candidates = candidates.concat(this.db.app_ids[app_id]); } - if (this.db.pattern_ids.hasOwnProperty(pattern_id)) { + if (Object.prototype.hasOwnProperty.call(this.db.pattern_ids, pattern_id)) { candidates = candidates.concat(this.db.pattern_ids[pattern_id]); } return filter(candidates, (surrogate) => { // note: does not support *.example.com (exact matches only) - if (surrogate.hasOwnProperty('sites')) { // array of site hosts + if (Object.prototype.hasOwnProperty.call(surrogate, 'sites')) { // array of site hosts if (!surrogate.sites.includes(host_name)) { return false; } } - if (surrogate.hasOwnProperty('match')) { + if (Object.prototype.hasOwnProperty.call(surrogate, 'match')) { if (!any(surrogate.match, match => script_src.match(match))) { return false; } @@ -141,7 +142,7 @@ class SurrogateDb extends Updatable { */ _buildDb(surrogate, property, db_name) { surrogate[property].forEach((val) => { - if (!this.db[db_name].hasOwnProperty(val)) { + if (!Object.prototype.hasOwnProperty.call(this.db[db_name], val)) { this.db[db_name][val] = []; } this.db[db_name][val].push(surrogate); diff --git a/src/classes/TabInfo.js b/src/classes/TabInfo.js index accadfdea..17ea679b3 100644 --- a/src/classes/TabInfo.js +++ b/src/classes/TabInfo.js @@ -39,8 +39,6 @@ import { processUrl } from '../utils/utils'; */ class TabInfo { constructor() { - this.policySmartBlock = new PolicySmartBlock(); - // @private this._tabInfo = {}; this._tabInfoPersist = {}; @@ -62,8 +60,8 @@ class TabInfo { timestamp: Date.now(), // assign only when smartBlock is enabled so avoid false positives // when enabling smartBlock is enabled for the first time - firstLoadTimestamp: this.policySmartBlock.shouldCheck(tab_id) && (numOfReloads === 0 ? Date.now() : (this.getTabInfoPersist(tab_id, 'firstLoadTimestamp') || 0)) || 0, - reloaded: this.policySmartBlock.checkReloadThreshold(tab_id), + firstLoadTimestamp: PolicySmartBlock.shouldCheck(tab_id) && (numOfReloads === 0 ? Date.now() : ((this.getTabInfoPersist(tab_id, 'firstLoadTimestamp') || 0)) || 0), + reloaded: PolicySmartBlock.checkReloadThreshold(tab_id), numOfReloads, smartBlock: { blocked: {}, @@ -87,7 +85,7 @@ class TabInfo { // TODO consider improving handling of what happens if we mistype the property name. Always // returning an object where property would otherwise have returned false could result in subtle bugs. getTabInfo(tab_id, property) { - if (this._tabInfo.hasOwnProperty(tab_id)) { + if (Object.prototype.hasOwnProperty.call(this._tabInfo, tab_id)) { if (property) { return this._tabInfo[tab_id][property]; } @@ -103,7 +101,7 @@ class TabInfo { * @return {Object} persistent data for this tab */ getTabInfoPersist(tab_id, property) { - if (this._tabInfoPersist.hasOwnProperty(tab_id)) { + if (Object.prototype.hasOwnProperty.call(this._tabInfoPersist, tab_id)) { if (property) { return this._tabInfoPersist[tab_id][property]; } @@ -119,7 +117,7 @@ class TabInfo { * @param {*} value property value */ setTabInfo(tab_id, property, value) { - if (this._tabInfo.hasOwnProperty(tab_id)) { + if (Object.prototype.hasOwnProperty.call(this._tabInfo, tab_id)) { // check for 'url' property case if (property === 'url') { this._updateUrl(tab_id, value); @@ -137,7 +135,7 @@ class TabInfo { * @param {boolean} blocked kind of policy to set */ setTabSmartBlockAppInfo(tabId, appId, rule, blocked) { - if (!this._tabInfo.hasOwnProperty(tabId)) { return; } + if (!Object.prototype.hasOwnProperty.call(this._tabInfo, tabId)) { return; } const policy = blocked ? 'blocked' : 'unblocked'; if (typeof this._tabInfo[tabId].smartBlock[policy][appId] === 'undefined') { @@ -155,7 +153,7 @@ class TabInfo { * @param {number} tab_id tab id */ clear(tab_id) { - if (!this._tabInfo.hasOwnProperty(tab_id)) { return; } + if (!Object.prototype.hasOwnProperty.call(this._tabInfo, tab_id)) { return; } const { numOfReloads, firstLoadTimestamp } = this._tabInfo[tab_id]; // TODO potential memory leak? diff --git a/src/classes/Updatable.js b/src/classes/Updatable.js index b8a5ba576..cb191d47a 100644 --- a/src/classes/Updatable.js +++ b/src/classes/Updatable.js @@ -77,7 +77,7 @@ class Updatable { const version_property = (this.type === 'bugs' || this.type === 'surrogates' ? 'version' : (`${this.type}Version`)); // nothing in storage, or it's so old it doesn't have a version - if (!memory || !memory.hasOwnProperty(version_property)) { + if (!memory || !Object.prototype.hasOwnProperty.call(memory, version_property)) { // return what's on disk log(`fetching ${this.type} from disk`); diff --git a/src/utils/api.js b/src/utils/api.js index f2e3865f5..14de96365 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -61,7 +61,7 @@ class Api { })); } - _processResponse(res) { + static _processResponse(res) { return new Promise((resolve, reject) => { const { status } = res; if (status === 204) { @@ -95,7 +95,7 @@ class Api { _sendAuthenticatedRequest(method, path, body) { return new Promise((resolve, reject) => { this._sendReq(method, path, body) - .then(this._processResponse) + .then(Api._processResponse) .then(dataFirstTry => resolve(dataFirstTry)) .catch((data) => { let shouldRefresh = false; @@ -122,7 +122,7 @@ class Api { )).catch(err => reject(err)); } this._sendReq(method, path, body) - .then(this._processResponse) + .then(Api._processResponse) .then(dataSecondTry => resolve(dataSecondTry)) .catch((data3) => { this._errorHandler(data3.errors) diff --git a/src/utils/click2play.js b/src/utils/click2play.js index abd0ec7ce..7e6b8d94a 100644 --- a/src/utils/click2play.js +++ b/src/utils/click2play.js @@ -25,8 +25,6 @@ import { sendMessage, processUrl, injectScript } from './utils'; import c2p_tpl from '../../app/templates/click2play.html'; import c2p_images from '../../app/data-images/click2play'; -const policy = new Policy(); - /** * Builds Click2Play templates for a given tab_id. * @@ -62,7 +60,7 @@ export function buildC2P(details, app_id) { } const app_name = bugDb.db.apps[app_id].name; const c2pHtml = []; - const blacklisted = !!policy.blacklisted(tab.host); + const blacklisted = !!Policy.blacklisted(tab.host); // Generate the templates for each c2p definition (could be multiple for an app ID) c2pApp.forEach((c2pAppDef) => { @@ -104,13 +102,14 @@ export function buildC2P(details, app_id) { case 'none': tabInfo.setTabInfo(tab_id, 'c2pStatus', 'loading'); // Push current C2P data into existing queue - if (!tab.c2pQueue.hasOwnProperty(app_id)) { - tabInfo.setTabInfo(tab_id, 'c2pQueue', Object.assign({}, tab.c2pQueue, { + if (!Object.prototype.hasOwnProperty.call(tab.c2pQueue, app_id)) { + tabInfo.setTabInfo(tab_id, 'c2pQueue', { + ...tab.c2pQueue, [app_id]: { data: c2pApp, html: c2pHtml } - })); + }); } // Scripts injected at document_idle are guaranteed to run after the DOM is complete injectScript(tab_id, 'dist/click_to_play.js', '', 'document_idle').then(() => { @@ -124,13 +123,14 @@ export function buildC2P(details, app_id) { break; case 'loading': // Push C2P data to a holding queue until click_to_play.js has finished loading on the page - if (!tab.c2pQueue.hasOwnProperty(app_id)) { - tabInfo.setTabInfo(tab_id, 'c2pQueue', Object.assign({}, tab.c2pQueue, { + if (!Object.prototype.hasOwnProperty.call(tab.c2pQueue, app_id)) { + tabInfo.setTabInfo(tab_id, 'c2pQueue', { + ...tab.c2pQueue, [app_id]: { data: c2pApp, html: c2pHtml } - })); + }); } break; case 'done': @@ -164,7 +164,7 @@ export function buildRedirectC2P(redirectUrls, app_id) { globals.BLOCKED_REDIRECT_DATA = {}; globals.BLOCKED_REDIRECT_DATA.app_id = app_id; globals.BLOCKED_REDIRECT_DATA.url = redirectUrls.redirectUrl; - globals.BLOCKED_REDIRECT_DATA.blacklisted = !!policy.blacklisted(host_url); + globals.BLOCKED_REDIRECT_DATA.blacklisted = !!Policy.blacklisted(host_url); globals.BLOCKED_REDIRECT_DATA.translations = { blocked_redirect_page_title: t('blocked_redirect_page_title'), @@ -195,8 +195,7 @@ export function allowAllwaysC2P(app_id, tab_host) { conf.selected_app_ids = selected_app_ids; // Remove fron site-specific-blocked - if (conf.site_specific_blocks.hasOwnProperty(tab_host) && conf.site_specific_blocks[tab_host].includes(+app_id)) { - const index = conf.site_specific_blocks[tab_host].indexOf(+app_id); + if (Object.prototype.hasOwnProperty.call(conf.site_specific_blocks, tab_host) && conf.site_specific_blocks[tab_host].includes(+app_id)) { const { site_specific_blocks } = conf; site_specific_blocks[tab_host].splice(0, 1); conf.site_specific_blocks = site_specific_blocks; @@ -204,7 +203,7 @@ export function allowAllwaysC2P(app_id, tab_host) { // Add tracker to site-specific-allowed const { site_specific_unblocks } = conf; - if (!site_specific_unblocks.hasOwnProperty(tab_host)) { + if (!Object.prototype.hasOwnProperty.call(site_specific_unblocks, tab_host)) { // create new array of unblocks for this host site_specific_unblocks[tab_host] = []; } diff --git a/src/utils/cliqzModulesData.js b/src/utils/cliqzModulesData.js index b28e91a32..1e4555ad4 100644 --- a/src/utils/cliqzModulesData.js +++ b/src/utils/cliqzModulesData.js @@ -58,7 +58,8 @@ export function getCliqzData(tabId, tabHostUrl, antiTracking) { return tracker.ads; }; - for (const bug of bugsValues) { + for (let i = 0; i < bugsValues.length; i++) { + const bug = bugsValues[i]; const dataPoints = getDataPoints(bug); if (dataPoints) { totalUnsafeCount += dataPoints; @@ -66,7 +67,8 @@ export function getCliqzData(tabId, tabHostUrl, antiTracking) { } } - for (const other of othersValues) { + for (let i = 0; i < othersValues.length; i++) { + const other = othersValues[i]; let whitelisted = false; const dataPoints = getDataPoints(other); diff --git a/src/utils/cliqzSettingImport.js b/src/utils/cliqzSettingImport.js index 581409aa3..800601716 100644 --- a/src/utils/cliqzSettingImport.js +++ b/src/utils/cliqzSettingImport.js @@ -34,10 +34,11 @@ function _promiseTimeout(timeout) { * @private * * @param {Object} cliqz - * @param {Object} conf + * @param {Object} c conf * @return {Promise} */ -function _runCliqzSettingsImport(cliqz, conf) { +function _runCliqzSettingsImport(cliqz, c) { + const conf = c; log('CliqzSettingsImport: Run Cliqz settings importer'); const inject = new KordInjector(); inject.init(); @@ -90,9 +91,10 @@ function _runCliqzSettingsImport(cliqz, conf) { * @memberOf BackgroundUtils * * @param {Object} cliqz - * @param {Object} conf + * @param {Object} c conf */ -export function importCliqzSettings(cliqz, conf) { +export default function importCliqzSettings(cliqz, c) { + const conf = c; log('checking cliqz import', conf.cliqz_import_state); if (!conf.cliqz_import_state) { _runCliqzSettingsImport(cliqz, conf).then(() => { diff --git a/src/utils/common.js b/src/utils/common.js index 06767279e..0225fc2a5 100644 --- a/src/utils/common.js +++ b/src/utils/common.js @@ -65,14 +65,14 @@ export function prefsGet(...args) { result = items; } else if (args.length === 1) { const key = args[0]; // extract value from array - if (items && items.hasOwnProperty(key)) { + if (items && Object.prototype.hasOwnProperty.call(items, key)) { result = items[key]; } } else { result = {}; // instantiate an empty object args.forEach((key) => { result[key] = null; - if (items && items.hasOwnProperty(key)) { + if (items && Object.prototype.hasOwnProperty.call(items, key)) { result[key] = items[key]; } }); @@ -157,25 +157,6 @@ export function hashCode(str) { return hash; } -/** - * Generator which makes object iterable with for...of loop - * @memberOf BackgroundUtils - * - * @param {Object} object over which own enumerable properties we want to iterate - * @return {Object} Generator object - */ - -export function* objectEntries(obj) { - const propKeys = Object.keys(obj); - - for (const propKey of propKeys) { - // `yield` returns a value and then pauses - // the generator. Later, execution continues - // where it was previously paused. - yield [propKey, obj[propKey]]; - } -} - /** * Unescape base64-encoded string. * @private @@ -184,7 +165,7 @@ export function* objectEntries(obj) { * @return {string} unescaped str */ function _base64urlUnescape(str) { - str += new Array(5 - str.length % 4).join('='); // eslint-disable-line no-param-reassign + str += new Array(5 - (str.length % 4)).join('='); // eslint-disable-line no-param-reassign return str.replace(/\-/g, '+').replace(/_/g, '/'); // eslint-disable-line no-useless-escape } diff --git a/src/utils/matcher.js b/src/utils/matcher.js index 0e3118639..7e562e43c 100644 --- a/src/utils/matcher.js +++ b/src/utils/matcher.js @@ -119,7 +119,7 @@ function _matchesHostPath(roots, src_path) { for (i = 0; i < roots.length; i++) { root = roots[i]; - if (root.hasOwnProperty('$')) { + if (Object.prototype.hasOwnProperty.call(root, '$')) { paths = root.$; for (j = 0; j < paths.length; j++) { if (src_path.startsWith(paths[j].path)) { @@ -153,14 +153,14 @@ function _matchesHost(root, src_host, src_path) { for (let i = 0; i < host_rev_arr.length; i++) { host_part = host_rev_arr[i]; // if node has domain, advance and try to update bug_id - if (node.hasOwnProperty(host_part)) { + if (Object.prototype.hasOwnProperty.call(node, host_part)) { // advance node node = node[host_part]; - bug_id = (node.hasOwnProperty('$') ? node.$ : bug_id); + bug_id = (Object.prototype.hasOwnProperty.call(node, '$') ? node.$ : bug_id); // we store all traversed nodes that contained paths in case the final // node does not have the matching path - if (src_path !== undefined && node.hasOwnProperty('$')) { + if (src_path !== undefined && Object.prototype.hasOwnProperty.call(node, '$')) { nodes_with_paths.push(node); } @@ -196,7 +196,9 @@ function _matchesHost(root, src_host, src_path) { function _matchesRegex(src) { const regexes = bugDb.db.patterns.regex; - for (const bug_id in regexes) { + const bug_ids = Object.keys(regexes); + for (let i = 0; i < bug_ids.length; i++) { + const bug_id = bug_ids[i]; if (regexes[bug_id].test(src)) { return +bug_id; } @@ -219,7 +221,9 @@ function _matchesPath(src_path) { // NOTE: we re-add the "/" in order to match patterns that include "/" const srcPath = `/${src_path}`; - for (const path in paths) { + const pathArr = Object.keys(paths); + for (let i = 0; i < pathArr.length; i++) { + const path = pathArr[i]; if (srcPath.includes(path)) { return paths[path]; } diff --git a/src/utils/utils.js b/src/utils/utils.js index 363753e70..da02d0c80 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -22,7 +22,7 @@ import { debounce } from 'underscore'; import { URL } from '@cliqz/url-parser'; import tabInfo from '../classes/TabInfo'; import globals from '../classes/Globals'; -import { log, objectEntries } from './common'; +import { log } from './common'; const { BROWSER_INFO } = globals; const IS_FIREFOX = (BROWSER_INFO.name === 'firefox'); @@ -355,7 +355,10 @@ function _fetchJson(method, url, query, extraHeaders, referrer = 'no-referrer', Accept: 'application/json' }); if (extraHeaders) { - for (const [key, value] of objectEntries(extraHeaders)) { + const extraHeadersKeys = Object.keys(extraHeaders); + for (let i = 0; i < extraHeadersKeys.length; i++) { + const key = extraHeadersKeys[i]; + const value = extraHeaders[key]; headers.append(key, value); } } @@ -448,7 +451,10 @@ function _fetchJson(method, url, query, extraHeaders, referrer = 'no-referrer', xhr.setRequestHeader('Content-Type', 'application/json'); xhr.setRequestHeader('Accept', 'application/json'); if (extraHeaders) { - for (const [key, value] of objectEntries(extraHeaders)) { + const extraHeadersKeys = Object.keys(extraHeaders); + for (let i = 0; i < extraHeadersKeys.length; i++) { + const key = extraHeadersKeys[i]; + const value = extraHeaders[key]; xhr.setRequestHeader(key, value); } } @@ -593,7 +599,7 @@ export function injectNotifications(tab_id, importExport = false) { } const tab = tabInfo.getTabInfo(tab_id); // check for prefetching, chrome new tab page and Firefox about:pages - if (tab && tab.prefetched === true || tab.path.includes('_/chrome/newtab') || tab.protocol === 'about' || (!importExport && globals.EXCLUDES.includes(tab.host))) { + if (tab && (tab.prefetched === true || tab.path.includes('_/chrome/newtab') || tab.protocol === 'about' || (!importExport && globals.EXCLUDES.includes(tab.host)))) { // return false to prevent sendMessage calls return Promise.resolve(false); } diff --git a/test/src/Foundbugs.test.js b/test/src/Foundbugs.test.js index e9a822e71..71b0567b6 100644 --- a/test/src/Foundbugs.test.js +++ b/test/src/Foundbugs.test.js @@ -47,7 +47,7 @@ describe('src/classes/FoundBugs.js', () => { "614": {"name": "New Relic","cat": "site_analytics","tags": [48]}}, "bugs": {"2": {"aid": 13},"935": {"aid": 13},"1982": {"aid": 13},"719": {"aid": 464},"1009": {"aid": 614}}, "firstPartyExceptions": {'something': true}, - "patterns": {'something': true}, + "patterns": { regex: { 'something': true} }, "version":416 }); // Mock bugDb fetch response diff --git a/test/src/Policy.test.js b/test/src/Policy.test.js index fc1619bb4..d08dc5b8b 100644 --- a/test/src/Policy.test.js +++ b/test/src/Policy.test.js @@ -77,22 +77,22 @@ describe('src/classes/Policy.js', () => { globals.SESSION.paused_blocking = false; }); test('a blocked tracker is unblocked with reason BLOCK_REASON_BLOCK_PAUSED', () => { - const { block, reason } = policy.shouldBlock(41, 'advertising', 1, 'www.cnn.com', 'https://www.cnn.com/'); + const { block, reason } = Policy.shouldBlock(41, 'advertising', 1, 'www.cnn.com', 'https://www.cnn.com/'); expect(block).toBeFalsy(); expect(reason).toBe(BLOCK_REASON_BLOCK_PAUSED); }); test('an unblocked tracker remains unblocked with reason BLOCK_REASON_BLOCK_PAUSED', () => { - const { block, reason } = policy.shouldBlock(50, 'essential', 1, 'www.cnn.com', 'https://www.cnn.com/'); + const { block, reason } = Policy.shouldBlock(50, 'essential', 1, 'www.cnn.com', 'https://www.cnn.com/'); expect(block).toBeFalsy(); expect(reason).toBe(BLOCK_REASON_BLOCK_PAUSED); }); test('a tracker on a white-listed site is unblocked with reason BLOCK_REASON_BLOCK_PAUSED', () => { - const { block, reason } = policy.shouldBlock(41, 'advertising', 1, 'www.ghostery.com', 'https://www.ghostery.com/'); + const { block, reason } = Policy.shouldBlock(41, 'advertising', 1, 'www.ghostery.com', 'https://www.ghostery.com/'); expect(block).toBeFalsy(); expect(reason).toBe(BLOCK_REASON_BLOCK_PAUSED); }); test('a tracker on a black-listed site is unblocked with reason BLOCK_REASON_BLOCK_PAUSED', () => { - const { block, reason } = policy.shouldBlock(50, 'essential', 1, 'www.tmz.com', 'https://www.tmz.com/'); + const { block, reason } = Policy.shouldBlock(50, 'essential', 1, 'www.tmz.com', 'https://www.tmz.com/'); expect(block).toBeFalsy(); expect(reason).toBe(BLOCK_REASON_BLOCK_PAUSED); }); @@ -106,32 +106,32 @@ describe('src/classes/Policy.js', () => { c2pDb.allowedOnce.mockReturnValue(false); }); test('a blocked tracker on the site-specific allow list on a black-listed site is unblocked with reason BLOCK_REASON_C2P_ALLOWED_ONCE', () => { - const { block, reason } = policy.shouldBlock(41, 'advertising', 1, 'www.tmz.com', 'https://www.tmz.com/'); + const { block, reason } = Policy.shouldBlock(41, 'advertising', 1, 'www.tmz.com', 'https://www.tmz.com/'); expect(block).toBeFalsy(); expect(reason).toBe(BLOCK_REASON_C2P_ALLOWED_ONCE); }); test('a blocked tracker is unblocked with reason BLOCK_REASON_C2P_ALLOWED_ONCE', () => { - const { block, reason } = policy.shouldBlock(41, 'advertising', 1, 'www.cnn.com', 'https://www.cnn.com/'); + const { block, reason } = Policy.shouldBlock(41, 'advertising', 1, 'www.cnn.com', 'https://www.cnn.com/'); expect(block).toBeFalsy(); expect(reason).toBe(BLOCK_REASON_C2P_ALLOWED_ONCE); }); test('an unblocked tracker on the site-specific block list remains unblocked with reason BLOCK_REASON_C2P_ALLOWED_ONCE', () => { - const { block, reason } = policy.shouldBlock(50, 'essential', 1, 'www.espn.com', 'https://www.espn.com/'); + const { block, reason } = Policy.shouldBlock(50, 'essential', 1, 'www.espn.com', 'https://www.espn.com/'); expect(block).toBeFalsy(); expect(reason).toBe(BLOCK_REASON_C2P_ALLOWED_ONCE); }); test('an unblocked tracker on the site-specific allow list on a black-listed site remains unblocked with reason BLOCK_REASON_C2P_ALLOWED_ONCE', () => { - const { block, reason } = policy.shouldBlock(50, 'essential', 1, 'www.tmz.com', 'https://www.tmz.com/'); + const { block, reason } = Policy.shouldBlock(50, 'essential', 1, 'www.tmz.com', 'https://www.tmz.com/'); expect(block).toBeFalsy(); expect(reason).toBe(BLOCK_REASON_C2P_ALLOWED_ONCE); }); test('an unblocked tracker on a black-listed site remains unblocked with reason BLOCK_REASON_C2P_ALLOWED_ONCE', () => { - const { block, reason } = policy.shouldBlock(55, 'essential', 1, 'www.tmz.com', 'https://www.tmz.com/'); + const { block, reason } = Policy.shouldBlock(55, 'essential', 1, 'www.tmz.com', 'https://www.tmz.com/'); expect(block).toBeFalsy(); expect(reason).toBe(BLOCK_REASON_C2P_ALLOWED_ONCE); }); test('an unblocked tracker remains unblocked with reason BLOCK_REASON_C2P_ALLOWED_ONCE', () => { - const { block, reason } = policy.shouldBlock(55, 'essential', 1, 'www.cnn.com', 'https://www.cnn.com/'); + const { block, reason } = Policy.shouldBlock(55, 'essential', 1, 'www.cnn.com', 'https://www.cnn.com/'); expect(block).toBeFalsy(); expect(reason).toBe(BLOCK_REASON_C2P_ALLOWED_ONCE); }); @@ -139,22 +139,22 @@ describe('src/classes/Policy.js', () => { describe('with a globally blocked tracker', () => { test('a tracker on the site-specific allow list is unblocked with reason BLOCK_REASON_SS_UNBLOCKED', () => { - const { block, reason } = policy.shouldBlock(15, 'site_analytics', 1, 'www.cnn.com', 'https://www.cnn.com/'); + const { block, reason } = Policy.shouldBlock(15, 'site_analytics', 1, 'www.cnn.com', 'https://www.cnn.com/'); expect(block).toBeFalsy(); expect(reason).toBe(BLOCK_REASON_SS_UNBLOCKED); }); test('a tracker on the site-specific allow list on a black-listed site remains blocked with reason BLOCK_REASON_BLACKLISTED', () => { - const { block, reason } = policy.shouldBlock(41, 'advertising', 1, 'www.tmz.com', 'https://www.tmz.com/'); + const { block, reason } = Policy.shouldBlock(41, 'advertising', 1, 'www.tmz.com', 'https://www.tmz.com/'); expect(block).toBeTruthy(); expect(reason).toBe(BLOCK_REASON_BLACKLISTED); }); test('a tracker on a white-listed site is unblocked with reason BLOCK_REASON_WHITELISTED', () => { - const { block, reason } = policy.shouldBlock(41, 'advertising', 1, 'www.ghostery.com', 'https://www.ghostery.com/'); + const { block, reason } = Policy.shouldBlock(41, 'advertising', 1, 'www.ghostery.com', 'https://www.ghostery.com/'); expect(block).toBeFalsy(); expect(reason).toBe(BLOCK_REASON_WHITELISTED); }); test('a tracker is blocked with reason BLOCK_REASON_GLOBAL_BLOCKED', () => { - const { block, reason } = policy.shouldBlock(41, 'advertising', 1, 'www.cnn.com', 'https://www.cnn.com/'); + const { block, reason } = Policy.shouldBlock(41, 'advertising', 1, 'www.cnn.com', 'https://www.cnn.com/'); expect(block).toBeTruthy(); expect(reason).toBe(BLOCK_REASON_GLOBAL_BLOCKED); }); @@ -162,32 +162,32 @@ describe('src/classes/Policy.js', () => { describe('with a globally unblocked tracker', () => { test('a tracker on the site-specific block list is blocked with reason BLOCK_REASON_SS_BLOCKED', () => { - const { block, reason } = policy.shouldBlock(13, 'site_analytics', 1, 'www.cnn.com', 'https://www.cnn.com/'); + const { block, reason } = Policy.shouldBlock(13, 'site_analytics', 1, 'www.cnn.com', 'https://www.cnn.com/'); expect(block).toBeTruthy(); expect(reason).toBe(BLOCK_REASON_SS_BLOCKED); }); test('a tracker on the site-specific block list on a white-listed site is unblocked with reason BLOCK_REASON_WHITELISTED', () => { - const { block, reason } = policy.shouldBlock(15, 'site_analytics', 1, 'www.ghostery.com', 'https://www.ghostery.com/'); + const { block, reason } = Policy.shouldBlock(15, 'site_analytics', 1, 'www.ghostery.com', 'https://www.ghostery.com/'); expect(block).toBeFalsy(); expect(reason).toBe(BLOCK_REASON_WHITELISTED); }); test('a tracker on the site-specific allow list is unblocked with reason BLOCK_REASON_SS_UNBLOCKED', () => { - const { block, reason } = policy.shouldBlock(50, 'essential', 1, 'www.cnn.com', 'https://www.cnn.com/'); + const { block, reason } = Policy.shouldBlock(50, 'essential', 1, 'www.cnn.com', 'https://www.cnn.com/'); expect(block).toBeFalsy(); expect(reason).toBe(BLOCK_REASON_SS_UNBLOCKED); }); test('a tracker on the site-specific allow list on a black-listed site is blocked with reason BLOCK_REASON_BLACKLISTED', () => { - const { block, reason } = policy.shouldBlock(50, 'essential', 1, 'www.tmz.com', 'https://www.tmz.com/'); + const { block, reason } = Policy.shouldBlock(50, 'essential', 1, 'www.tmz.com', 'https://www.tmz.com/'); expect(block).toBeTruthy(); expect(reason).toBe(BLOCK_REASON_BLACKLISTED); }); test('a tracker on a black-listed site is blocked with reason BLOCK_REASON_BLACKLISTED', () => { - const { block, reason } = policy.shouldBlock(55, 'essential', 1, 'www.tmz.com', 'https://www.tmz.com/'); + const { block, reason } = Policy.shouldBlock(55, 'essential', 1, 'www.tmz.com', 'https://www.tmz.com/'); expect(block).toBeTruthy(); expect(reason).toBe(BLOCK_REASON_BLACKLISTED); }); test('a tracker is unblocked with reason BLOCK_REASON_GLOBAL_UNBLOCKED', () => { - const { block, reason } = policy.shouldBlock(55, 'essential', 1, 'www.cnn.com', 'https://www.cnn.com/'); + const { block, reason } = Policy.shouldBlock(55, 'essential', 1, 'www.cnn.com', 'https://www.cnn.com/'); expect(block).toBeFalsy(); expect(reason).toBe(BLOCK_REASON_GLOBAL_UNBLOCKED); }); @@ -198,63 +198,63 @@ describe('src/classes/Policy.js', () => { test('matchesWildcard should return true with wildcard entered ', () => { let url = 'developer.mozilla.org'; let input = 'developer.*.org'; - expect(policy.matchesWildcard(url, input)).toBeTruthy(); + expect(Policy.matchesWildcard(url, input)).toBeTruthy(); url = 'ghostery.com'; input = '*.com'; - expect(policy.matchesWildcard(url, input)).toBeTruthy(); + expect(Policy.matchesWildcard(url, input)).toBeTruthy(); url = 'ghostery.com' input = '*'; - expect(policy.matchesWildcard(url, input)).toBeTruthy(); + expect(Policy.matchesWildcard(url, input)).toBeTruthy(); url = 'developer.mozilla.org'; input = 'developer.*'; - expect(policy.matchesWildcard(url , input)).toBeTruthy(); + expect(Policy.matchesWildcard(url , input)).toBeTruthy(); url = 'developer.mozilla.org'; input = '****'; - expect(policy.matchesWildcard(url, input)).toBeTruthy(); + expect(Policy.matchesWildcard(url, input)).toBeTruthy(); }); test('matchesWildcard should return false with wildcard entered ', () => { let url = 'developer.mozilla.org'; let input = ''; - expect(policy.matchesWildcard(url, input)).toBeFalsy(); + expect(Policy.matchesWildcard(url, input)).toBeFalsy(); url = 'ghostery.com'; input = '+$@@#$*'; - expect(policy.matchesWildcard(url, input)).toBeFalsy(); + expect(Policy.matchesWildcard(url, input)).toBeFalsy(); url = 'ghostery.com' input = 'αράδειγμα.δοκιμ.*'; - expect(policy.matchesWildcard(url, input)).toBeFalsy(); + expect(Policy.matchesWildcard(url, input)).toBeFalsy(); url = 'SELECT * FROM USERS'; input = 'developer.*'; - expect(policy.matchesWildcard(url , input)).toBeFalsy(); + expect(Policy.matchesWildcard(url , input)).toBeFalsy(); }); test('matchesWildcard should return false with regex entered', () => { let url = 'foo.com'; let input = '/foo)]/'; - expect(policy.matchesWildcard(url, input)).toBeFalsy(); + expect(Policy.matchesWildcard(url, input)).toBeFalsy(); url = 'foo.com'; input = 'test\\'; - expect(policy.matchesWildcard(url, input)).toBeFalsy(); + expect(Policy.matchesWildcard(url, input)).toBeFalsy(); url = 'foo.com'; input = '/(?<=x*)foo/'; - expect(policy.matchesWildcard(url, input)).toBeFalsy(); + expect(Policy.matchesWildcard(url, input)).toBeFalsy(); url = 'foo.com'; input = '/foo(?)/'; - expect(policy.matchesWildcard(url, input)).toBeFalsy(); + expect(Policy.matchesWildcard(url, input)).toBeFalsy(); url = 'foo.com'; input = ''; - expect(policy.matchesWildcard(url, input)).toBeFalsy(); + expect(Policy.matchesWildcard(url, input)).toBeFalsy(); }); }) }); diff --git a/test/src/PolicySmartBlock.test.js b/test/src/PolicySmartBlock.test.js index 7534e9f6b..342f7acea 100644 --- a/test/src/PolicySmartBlock.test.js +++ b/test/src/PolicySmartBlock.test.js @@ -45,7 +45,7 @@ describe('src/classes/PolicySmartBlock.js', () => { describe('PolicySmartBlock isFirstPartyRequest tests', () => { beforeAll(() => { - policySmartBlock.shouldCheck = jest.fn(() => true); + PolicySmartBlock.shouldCheck = jest.fn(() => true); }); afterAll(() => { @@ -53,18 +53,18 @@ describe('src/classes/PolicySmartBlock.js', () => { }); test('PolicySmartBlock isFirstPartyRequest truthy assertion', () => { - expect(policySmartBlock.isFirstPartyRequest('tabId', 'example.com', 'example.com')).toBeTruthy(); + expect(PolicySmartBlock.isFirstPartyRequest('tabId', 'example.com', 'example.com')).toBeTruthy(); // isFirstPartyRequest() expects pre-parsed domains, so we should parse the test urls const parsedPage = processUrl('https://checkout.ghostery.com/insights'); const parsedRequest = processUrl('https://analytics.ghostery.com/piwik.js'); - expect(policySmartBlock.isFirstPartyRequest('tabId', parsedPage.generalDomain, parsedRequest.generalDomain)).toBeTruthy(); + expect(PolicySmartBlock.isFirstPartyRequest('tabId', parsedPage.generalDomain, parsedRequest.generalDomain)).toBeTruthy(); }); test('PolicySmartBlock isFirstPartyRequest falsy assertion', () => { - expect(policySmartBlock.isFirstPartyRequest('tabId', 'www.example.com', 'example.com')).toBeFalsy(); - expect(policySmartBlock.isFirstPartyRequest('tabId', 'sub.example.com', 'example.com')).toBeFalsy(); - expect(policySmartBlock.isFirstPartyRequest('tabId', 'example.com', 'test.com')).toBeFalsy(); - expect(policySmartBlock.isFirstPartyRequest('tabId', 'www.example.com', 'www.test.com')).toBeFalsy(); + expect(PolicySmartBlock.isFirstPartyRequest('tabId', 'www.example.com', 'example.com')).toBeFalsy(); + expect(PolicySmartBlock.isFirstPartyRequest('tabId', 'sub.example.com', 'example.com')).toBeFalsy(); + expect(PolicySmartBlock.isFirstPartyRequest('tabId', 'example.com', 'test.com')).toBeFalsy(); + expect(PolicySmartBlock.isFirstPartyRequest('tabId', 'www.example.com', 'www.test.com')).toBeFalsy(); }); }); }); diff --git a/test/utils/matcher.test.js b/test/utils/matcher.test.js index 87dc6f432..6c2ea466e 100644 --- a/test/utils/matcher.test.js +++ b/test/utils/matcher.test.js @@ -19,6 +19,7 @@ describe('src/utils/matcher.js', () => { beforeAll(done => { // Fake the XMLHttpRequest for fetchJson(/daabases/bugs.json) const bugsJson = JSON.stringify({ + "apps": {}, "firstPartyExceptions": { "101": [ "google.com/ig" @@ -32,6 +33,7 @@ describe('src/utils/matcher.js', () => { ] }, "patterns": { + "regex": {}, "host": { "com": { "gmodules": { diff --git a/tools/i18n-checker.js b/tools/i18n-checker.js index 0f5d96f36..9d7eb181f 100644 --- a/tools/i18n-checker.js +++ b/tools/i18n-checker.js @@ -138,7 +138,7 @@ function findDuplicates(paths) { duplicates[locale] = []; oboe(fs.createReadStream(path)).node('{message}', (val, keys) => { const key = keys[0]; - if (foundKeys.hasOwnProperty(key)) { + if (Object.prototype.hasOwnProperty.call(foundKeys, key)) { hasDuplicates = true; duplicates[locale].push(key); return; @@ -179,7 +179,7 @@ function findMissingKeys(paths) { const locale = path.match(/_locales\/(.*)\/messages.json/)[1]; missingKeys[locale] = []; Object.keys(defaultLocaleJson).forEach((key) => { - if (!localeJson.hasOwnProperty(key)) { + if (!Object.prototype.hasOwnProperty.call(localeJson, key)) { hasMissingKeys = true; missingKeys[locale].push(key); } @@ -214,7 +214,7 @@ function findExtraKeys(paths) { const locale = path.match(/_locales\/(.*)\/messages.json/)[1]; extraKeys[locale] = []; Object.keys(localeJson).forEach((key) => { - if (!defaultLocaleJson.hasOwnProperty(key)) { + if (!Object.prototype.hasOwnProperty.call(defaultLocaleJson, key)) { hasExtraKeys = true; extraKeys[locale].push(key); } @@ -247,7 +247,7 @@ function findMalformedKeys(paths) { const locale = path.match(/_locales\/(.*)\/messages.json/)[1]; malformedKeys[locale] = []; Object.keys(localeJson).forEach((key) => { - if (!localeJson[key].hasOwnProperty('message')) { + if (!Object.prototype.hasOwnProperty.call(localeJson[key], 'message')) { hasMalformedKeys = true; malformedKeys[locale].push(key); } @@ -282,8 +282,8 @@ function findMissingPlaceholders(paths) { const locale = path.match(/_locales\/(.*)\/messages.json/)[1]; missingPlaceholders[locale] = []; Object.keys(defaultLocaleJson).forEach((key) => { - if (defaultLocaleJson[key].hasOwnProperty('placeholders')) { - if (!localeJson[key] || !localeJson[key].hasOwnProperty('placeholders')) { + if (Object.prototype.hasOwnProperty.call(defaultLocaleJson[key], 'placeholders')) { + if (!localeJson[key] || !Object.prototype.hasOwnProperty.call(localeJson[key], 'placeholders')) { hasMissingPlaceholders = true; missingPlaceholders[locale].push(`${key}: missing ${Object.keys(defaultLocaleJson[key].placeholders).length} placeholder(s)`); return; @@ -326,8 +326,8 @@ function findExtraPlaceholders(paths) { const locale = path.match(/_locales\/(.*)\/messages.json/)[1]; extraPlaceholders[locale] = []; Object.keys(localeJson).forEach((key) => { - if (localeJson[key].hasOwnProperty('placeholders')) { - if (!defaultLocaleJson[key] || !defaultLocaleJson[key].hasOwnProperty('placeholders')) { + if (Object.prototype.hasOwnProperty.call(localeJson[key], 'placeholders')) { + if (!defaultLocaleJson[key] || !Object.prototype.hasOwnProperty.call(defaultLocaleJson[key], 'placeholders')) { hasExtraPlaceholders = true; extraPlaceholders[locale].push(`${key}: has ${Object.keys(localeJson[key].placeholders).length} extra placeholder(s)`); return; @@ -374,7 +374,7 @@ function findMalformedPlaceholders(paths) { if (matchedPlaceholders) { matchedPlaceholders.forEach((p) => { const placeholder = p.toLowerCase().slice(1, -1); - if (!placeholders.hasOwnProperty(placeholder)) { + if (!Object.prototype.hasOwnProperty.call(placeholders, placeholder)) { hasMalformedPlaceholders = true; malformedPlaceholders[locale].push(`${key}: needs placeholder "${placeholder}"`); } diff --git a/tools/leet/leet-en.js b/tools/leet/leet-en.js index f1c236894..2ff8dd504 100644 --- a/tools/leet/leet-en.js +++ b/tools/leet/leet-en.js @@ -62,12 +62,13 @@ const leet_convert = function(string) { // 'z': 'z', }; - let letter; let output = string || ''; output = output.replace(/cks/g, 'x'); - for (letter in characterMap) { - if (characterMap.hasOwnProperty(letter)) { + const characterKeys = Object.keys(characterMap); + for (let i = 0; i < characterKeys.length; i++) { + const letter = characterKeys[i]; + if (Object.prototype.hasOwnProperty.call(characterMap, letter)) { output = output.replace(new RegExp(letter, 'g'), characterMap[letter]); } } @@ -82,12 +83,13 @@ if (!fs.existsSync('./tools/leet/messages.en.copy.json')) { // Import the copied messages file const leet = {}; - let key; const en = jsonfile.readFileSync('./tools/leet/messages.en.copy.json'); // Create a LEETed version of the messages.json file - for (key in en) { - if (en[key].hasOwnProperty('message')) { + const enKeys = Object.keys(en); + for (let i = 0; i < enKeys.length; i++) { + const key = enKeys[i]; + if (Object.prototype.hasOwnProperty.call(en[key], 'message')) { const message = leet_convert(en[key].message); const { placeholders } = en[key]; leet[key] = { message, placeholders }; diff --git a/tools/transifex.js b/tools/transifex.js index d8086e72a..a888ebdc1 100644 --- a/tools/transifex.js +++ b/tools/transifex.js @@ -102,8 +102,8 @@ function fixMissingPlaceholders(paths) { let dirty = false; const localeJson = jsonfile.readFileSync(`.${path}`); Object.keys(defaultLocaleJson).forEach((key) => { - if (defaultLocaleJson[key].hasOwnProperty('placeholders')) { - if (localeJson[key] && !localeJson[key].hasOwnProperty('placeholders')) { + if (Object.prototype.hasOwnProperty.call(defaultLocaleJson[key], 'placeholders')) { + if (localeJson[key] && !Object.prototype.hasOwnProperty.call(localeJson[key], 'placeholders')) { dirty = true; localeJson[key].placeholders = defaultLocaleJson[key].placeholders; }