From 7aadb55d839a4a64e353edf24afa6caed4f77fda Mon Sep 17 00:00:00 2001 From: Christopher Tino Date: Thu, 30 May 2019 09:34:27 -0400 Subject: [PATCH 1/8] GH-1566 adjust smart blocking to handle click 2 play --- .../components/BuildingBlocks/DonutGraph.jsx | 4 +- .../components/BuildingBlocks/StatsGraph.jsx | 4 +- app/templates/click2play.html | 4 +- app/templates/click2play.js | 16 --- package.json | 4 +- src/classes/EventHandlers.js | 36 +++-- src/classes/PanelData.js | 3 +- src/classes/Policy.js | 10 +- src/classes/PolicySmartBlock.js | 11 +- src/utils/click2play.js | 17 ++- webpack.config.js | 4 +- yarn.lock | 136 ++++-------------- 12 files changed, 74 insertions(+), 175 deletions(-) delete mode 100644 app/templates/click2play.js diff --git a/app/panel/components/BuildingBlocks/DonutGraph.jsx b/app/panel/components/BuildingBlocks/DonutGraph.jsx index a4af6d4e0..3076f12a2 100644 --- a/app/panel/components/BuildingBlocks/DonutGraph.jsx +++ b/app/panel/components/BuildingBlocks/DonutGraph.jsx @@ -11,7 +11,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0 */ -import throttle from 'lodash.throttle'; +import _ from 'underscore'; import React from 'react'; import ClassNames from 'classnames'; import { @@ -178,7 +178,7 @@ class DonutGraph extends React.Component { * @param {Array} categories list of categories detected on the site * @param {Object} options options for the graph */ - bakeDonut = throttle(this._bakeDonut.bind(this), 600, { leading: true, trailing: true }) // matches panelData#updatePanelUI throttling + bakeDonut = _.throttle(this._bakeDonut.bind(this), 600, { leading: true, trailing: true }) // matches panelData#updatePanelUI throttling _bakeDonut(categories, options) { const { diff --git a/app/panel/components/BuildingBlocks/StatsGraph.jsx b/app/panel/components/BuildingBlocks/StatsGraph.jsx index f12a4db55..b00eddf4f 100644 --- a/app/panel/components/BuildingBlocks/StatsGraph.jsx +++ b/app/panel/components/BuildingBlocks/StatsGraph.jsx @@ -11,9 +11,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0 */ +import _ from 'underscore'; import React from 'react'; import * as D3 from 'd3'; -import isEqual from 'lodash.isequal'; /** * Generates an animated graph displaying locally stored stats @@ -30,7 +30,7 @@ class StatsGraph extends React.Component { * Lifecycle event */ componentDidUpdate(prevProps) { - if (!isEqual(prevProps, this.props)) { + if (!_.isEqual(prevProps, this.props)) { this.generateGraph(); } } diff --git a/app/templates/click2play.html b/app/templates/click2play.html index 20cf5af2d..fb57e07e4 100644 --- a/app/templates/click2play.html +++ b/app/templates/click2play.html @@ -49,7 +49,9 @@

<%= data.click2play_text %>

<% } %> - + <% if (data.smartBlocked === false) { %> + + <% } %> <% if (data.blacklisted === false) { %> <% } %> diff --git a/app/templates/click2play.js b/app/templates/click2play.js deleted file mode 100644 index 29d130477..000000000 --- a/app/templates/click2play.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Ghostery Click2Play - * - * Ghostery Browser Extension - * https://www.ghostery.com/ - * - * Copyright 2019 Ghostery, Inc. All rights reserved. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -module.exports = function (t) { - let n, - l = ''; Array.prototype.join; return l += '\n\n\n\t\n\t\n\n\n\t\n\t\t\n\t\t\t\n\t\t\n\t
\n\n\t\t\t\t', t.button ? l += `\n\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\n\t\t\t\t` : (l += '\n\n\t\t\t\t\t', void 0 !== t.click2play_text && t.click2play_text && (l += `\n\t\t\t\t\t\t

${(n = t.click2play_text) == null ? '' : n}

\n\t\t\t\t\t`), l += `\n\n\t\t\t\t\t\n\n\t\t\t\t\t\n\n\t\t\t\t\t`, !1 === t.blacklisted && (l += `\n\t\t\t\t\t\t\n\t\t\t\t\t`), l += '\n\n\t\t\t\t'), l += '\n\n\t\t\t
\n\n\n'; -}; diff --git a/package.json b/package.json index b18105e8e..aa34cdae5 100644 --- a/package.json +++ b/package.json @@ -52,8 +52,6 @@ "foundation-sites": "^6.4.4-rc1", "history": "^4.7.2", "json-api-normalizer": "^0.4.10", - "lodash.isequal": "^4.5.0", - "lodash.throttle": "^4.1.1", "moment": "^2.19.1", "prop-types": "^15.6.2", "query-string": "^6.1.0", @@ -71,6 +69,7 @@ "spanan": "^2.0.0", "ua-parser-js": "^0.7.17", "underscore": "^1.8.3", + "underscore-template-loader": "^1.0.0", "url-search-params": "^0.10.2", "whatwg-fetch": "^3.0.0" }, @@ -96,7 +95,6 @@ "eslint-plugin-react": "^7.6.1", "fs-extra": "^4.0.3", "glob": "^7.1.2", - "html-loader": "^0.5.1", "jest": "^23.6.0", "jsdoc": "^3.5.5", "jsonfile": "^4.0.0", diff --git a/src/classes/EventHandlers.js b/src/classes/EventHandlers.js index 24776e50a..8467a3e89 100644 --- a/src/classes/EventHandlers.js +++ b/src/classes/EventHandlers.js @@ -35,7 +35,6 @@ import { isBug } from '../utils/matcher'; import * as utils from '../utils/utils'; const IS_EDGE = (globals.BROWSER_INFO.name === 'edge'); -const RequestsMap = new Map(); /** * This class is a collection of handlers for * webNavigation, webRequest and tabs events. @@ -66,11 +65,10 @@ class EventHandlers { onBeforeNavigate(details) { const { tabId, frameId, url } = details; - // frameId === 0 indicates the navigation event ocurred in the content window, not a subframe + // frameId === 0 indicates the navigation event occurred in the content window, not a subframe if (frameId === 0) { log(`❤ ❤ ❤ Tab ${tabId} navigating to ${url} ❤ ❤ ❤`); - RequestsMap.clear(); this._clearTabData(tabId); this._resetNotifications(); // TODO understand why this does not work when placed in the 'reload' branch in onCommitted @@ -105,7 +103,7 @@ class EventHandlers { tabId, frameId, transitionType, transitionQualifiers } = details; - // frameId === 0 indicates the navigation event ocurred in the content window, not a subframe + // frameId === 0 indicates the navigation event occurred in the content window, not a subframe if (frameId === 0) { // update reload info before creating/clearing tab info if (transitionType === 'reload' && !transitionQualifiers.includes('forward_back')) { @@ -285,8 +283,6 @@ class EventHandlers { return; } - RequestsMap.clear(); - // Code below executes for top level frame only log(`foundBugs: ${foundBugs.getAppsCount(details.tabId)}, tab_id: ${details.tabId}`); @@ -296,11 +292,11 @@ class EventHandlers { log('onNavigationCompleted injectScript error', err); }); } - // The problem is that requests may continue well after onNavigationCompleted - // This breaks allow once for C2P, as it clears too early + // Requests may continue well after onNavigationCompleted, which breaks + // C2P's "allow once" feature because the allowOnceList is cleared too early setTimeout(() => { this._eventReset(details.tabId); - }, 2000); + }, 5000); // match THRESHHOLD value in PolicySmartBlock._requestWasSlow() } /** @@ -427,6 +423,9 @@ class EventHandlers { }; } + const smartBlocked = !block ? this.policySmartBlock.shouldBlock(app_id, cat_id, tab_id, page_url, details.type, details.timeStamp) : false; + const smartUnblocked = block ? this.policySmartBlock.shouldUnblock(app_id, cat_id, tab_id, page_url, details.type) : false; + // process the tracker asynchronously // very important to block request processing as little as necessary setTimeout(() => { @@ -436,20 +435,16 @@ class EventHandlers { type: details.type, url: details.url, block, + smartBlocked, tab_id, from_frame: details.parentFrameId !== -1 }); }, 1); - if (block) { - if (this.policySmartBlock.shouldUnblock(app_id, cat_id, tab_id, page_url, details.type)) { - return { cancel: false }; - } + if ((block && !smartUnblocked) || smartBlocked) { return this._blockHelper(details, tab_id, app_id, bug_id, request_id, fromRedirect); } - if (this.policySmartBlock.shouldBlock(app_id, cat_id, tab_id, page_url, details.type, details.timeStamp)) { - return this._blockHelper(details, tab_id, app_id, bug_id, request_id); - } + return { cancel: false }; } @@ -600,13 +595,14 @@ class EventHandlers { */ _processBug(details) { const { - bug_id, app_id, type, url, block, tab_id + bug_id, app_id, type, url, block, smartBlocked, tab_id } = details; const tab = tabInfo.getTabInfo(tab_id); + const allowedOnce = c2pDb.allowedOnce(details.tab_id, app_id); let num_apps_old; - log((block ? 'Blocked' : 'Found'), type, url); + log((block || smartBlocked ? 'Blocked' : 'Found'), type, url); log(`^^^ Pattern ID ${bug_id} on tab ID ${tab_id}`); if (conf.show_alert) { @@ -620,13 +616,13 @@ class EventHandlers { // throttled in PanelData panelData.updatePanelUI(); - if (block && (conf.enable_click2play || conf.enable_click2playSocial)) { + if ((block || smartBlocked) && (conf.enable_click2play || conf.enable_click2playSocial) && !allowedOnce) { buildC2P(details, app_id); } // Note: tab.purplebox handles a race condition where this function is sometimes called before onNavigation() if (conf.show_alert && tab && !tab.prefetched && tab.purplebox) { - if (foundBugs.getAppsCount(details.tab_id) > num_apps_old || c2pDb.allowedOnce(details.tab_id, app_id)) { + if (foundBugs.getAppsCount(details.tab_id) > num_apps_old || allowedOnce) { this.purplebox.updateBox(details.tab_id, app_id); } } diff --git a/src/classes/PanelData.js b/src/classes/PanelData.js index a60fdb605..4493ac414 100644 --- a/src/classes/PanelData.js +++ b/src/classes/PanelData.js @@ -15,7 +15,6 @@ */ import _ from 'underscore'; -import throttle from 'lodash.throttle'; import button from './BrowserButton'; import conf from './Conf'; import foundBugs from './FoundBugs'; @@ -212,7 +211,7 @@ class PanelData { * Invoked in EventHandlers#onBeforeRequest when a new bug has been found * Sends updated data to the panel and blocking and/or summary components */ - updatePanelUI = throttle(this._updatePanelUI.bind(this), 600, { leading: true, trailing: true }); // matches donut redraw throttling + updatePanelUI = _.throttle(this._updatePanelUI.bind(this), 600, { leading: true, trailing: true }); // matches donut redraw throttling _updatePanelUI() { if (!this._panelPort || !this._activeTab) { return; } diff --git a/src/classes/Policy.js b/src/classes/Policy.js index 0989243bc..e6a76243f 100644 --- a/src/classes/Policy.js +++ b/src/classes/Policy.js @@ -27,6 +27,7 @@ import globals from './Globals'; */ export const BLOCK_REASON_BLOCK_PAUSED = 'BLOCK_REASON_BLOCK_PAUSED'; export const BLOCK_REASON_GLOBAL_BLOCKED = 'BLOCK_REASON_GLOBAL_BLOCKED'; +export const BLOCK_REASON_GLOBAL_UNBLOCKED = 'BLOCK_REASON_GLOBAL_UNBLOCKED'; export const BLOCK_REASON_WHITELISTED = 'BLOCK_REASON_WHITELISTED'; export const BLOCK_REASON_BLACKLISTED = 'BLOCK_REASON_BLACKLISTED'; export const BLOCK_REASON_SS_UNBLOCKED = 'BLOCK_REASON_SS_UNBLOCKED'; @@ -124,10 +125,10 @@ class Policy { return { block: false, reason: BLOCK_REASON_BLOCK_PAUSED }; } + const allowedOnce = c2pDb.allowedOnce(tab_id, app_id); if (conf.selected_app_ids.hasOwnProperty(app_id)) { if (conf.toggle_individual_trackers && conf.site_specific_unblocks.hasOwnProperty(tab_host) && conf.site_specific_unblocks[tab_host].includes(+app_id)) { if (this.blacklisted(tab_url)) { - const allowedOnce = c2pDb.allowedOnce(tab_id, app_id); return { block: !allowedOnce, reason: allowedOnce ? BLOCK_REASON_C2P_ALLOWED_ONCE : BLOCK_REASON_BLACKLISTED }; } return { block: false, reason: BLOCK_REASON_SS_UNBLOCKED }; @@ -135,22 +136,19 @@ class Policy { if (this.whitelisted(tab_url)) { return { block: false, reason: BLOCK_REASON_WHITELISTED }; } - const allowedOnce = c2pDb.allowedOnce(tab_id, app_id); return { block: !allowedOnce, reason: allowedOnce ? BLOCK_REASON_C2P_ALLOWED_ONCE : BLOCK_REASON_GLOBAL_BLOCKED }; } - // We get here when app_id is not selected for blocking + // We get here when app_id is not selected for global blocking if (conf.toggle_individual_trackers && conf.site_specific_blocks.hasOwnProperty(tab_host) && conf.site_specific_blocks[tab_host].includes(+app_id)) { if (this.whitelisted(tab_url)) { return { block: false, reason: BLOCK_REASON_WHITELISTED }; } - const allowedOnce = c2pDb.allowedOnce(tab_id, app_id); return { block: !allowedOnce, reason: allowedOnce ? BLOCK_REASON_C2P_ALLOWED_ONCE : BLOCK_REASON_SS_BLOCKED }; } if (this.blacklisted(tab_url)) { - const allowedOnce = c2pDb.allowedOnce(tab_id, app_id); return { block: !allowedOnce, reason: allowedOnce ? BLOCK_REASON_C2P_ALLOWED_ONCE : BLOCK_REASON_BLACKLISTED }; } - return { block: false, reason: BLOCK_REASON_GLOBAL_BLOCKED }; + return { block: false, reason: allowedOnce ? BLOCK_REASON_C2P_ALLOWED_ONCE : BLOCK_REASON_GLOBAL_UNBLOCKED }; } } diff --git a/src/classes/PolicySmartBlock.js b/src/classes/PolicySmartBlock.js index 988bf05d0..27c0052c5 100644 --- a/src/classes/PolicySmartBlock.js +++ b/src/classes/PolicySmartBlock.js @@ -18,6 +18,7 @@ import tabInfo from './TabInfo'; import compDb from './CompatibilityDb'; import globals from './Globals'; import Policy from './Policy'; +import c2pDb from './Click2PlayDb'; import { log } from '../utils/common'; /** * Class for handling Smart Blocking site policy. @@ -86,7 +87,7 @@ class PolicySmartBlock { let reason; - // block if it's been more than 5 seconds since page load started + // Block all trackers that load after 5 seconds from when page load started if (this._requestWasSlow(tabId, appId, requestTimestamp)) { reason = 'slow'; @@ -98,14 +99,14 @@ class PolicySmartBlock { reason = 'allowedType'; // allow if tracker is in breaking type } else if (this._pageWasReloaded(tabId, appId)) { reason = 'pageReloaded'; // allow if page has been reloaded recently + } else if (c2pDb.allowedOnce(tabId, appId)) { + reason = 'c2pAllowOnce'; // allow if the user has selected "allow once" in Click2Play } } + // We are only blocking slow trackers that do not cause page breakage const result = (reason === 'slow'); if (result) { - // We don't want record in tabInfo reasons other than 'slow' - // Smart blocking should not claim that it unblocks trackers which were unblocked - // for other reasons before shouldBlock was called for them. log('Smart Blocking blocked appId', appId, 'for reason:', reason); tabInfo.setTabSmartBlockAppInfo(tabId, appId, 'slow', true); } @@ -258,7 +259,7 @@ class PolicySmartBlock { } /** - * Check if request loaded after a threshhold time since page load. + * Check if request loaded after a threshold time since page load. * @param {string} tabId tab id * @param {string} appId tracker id * @param {number} requestTimestamp timestamp of the request diff --git a/src/utils/click2play.js b/src/utils/click2play.js index 0c087674c..211d2d6d6 100644 --- a/src/utils/click2play.js +++ b/src/utils/click2play.js @@ -22,20 +22,28 @@ import Policy from '../classes/Policy'; import tabInfo from '../classes/TabInfo'; import { log } from './common'; import { sendMessage, processUrl, injectScript } from './utils'; -import c2p_tpl from '../../app/templates/click2play'; +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. + * + * Restricted Sites: Only show the "allow once" option, since blacklisting overrides + * site-specific tracker allow settings. + * + * Smart Blocking: If the app was blocked by Smart Blocking, we only show the "allow always" option because + * the tracker was most likely a lazy-loaded widget (comment, video) and C2P will reset the allowOnceList + * before the widget has a chance to load. + * * @memberOf BackgroundUtils * * @param {Object} details request parameters * @param {number} app_id tracker id */ export function buildC2P(details, app_id) { - const { tab_id } = details; + const { tab_id, smartBlocked } = details; let c2pApp = c2pDb.db.apps && c2pDb.db.apps[app_id]; if (!c2pApp) { @@ -59,6 +67,7 @@ export function buildC2P(details, app_id) { c2pApp.forEach((c2pAppDef) => { const tplData = { blacklisted, // if the site is blacklisted, don't show allow_always button + smartBlocked, // if the app has been Smart Blocked, don't show allow_once (see comment block) button: !!c2pAppDef.button, ghostery_blocked_src: c2p_images.ghosty_blocked, allow_always_src: c2p_images.allow_unblock, @@ -81,7 +90,7 @@ export function buildC2P(details, app_id) { } } - c2pHtml.push(c2p_tpl(tplData)); + c2pHtml.push(c2p_tpl({ data: tplData })); }); if (app_id === 2575) { // Hubspot forms. Adjust selector. @@ -181,7 +190,7 @@ function _getHubspotFormSelector(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: - // 532040 - parner id + // 532040 - partner id // 95b5de3a-6d4a-4729-bebf-07c41268d773 - form id on the page // hs_reqwest_0 - function which will be called on the client after the request // diff --git a/webpack.config.js b/webpack.config.js index 969ce808e..8dd123b6c 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -11,7 +11,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -// depenencies +// dependencies const glob = require('glob'); const path = require('path'); const webpack = require('webpack'); @@ -158,7 +158,7 @@ const config = { { test: /\.(html)$/, use: { - loader: 'html-loader' + loader: 'underscore-template-loader' } },{ test: /\.(jsx|js)?/, diff --git a/yarn.lock b/yarn.lock index f60c7e197..523c08206 100644 --- a/yarn.lock +++ b/yarn.lock @@ -903,11 +903,6 @@ ast-types-flow@0.0.7, ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= -ast-types@0.9.6: - version "0.9.6" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9" - integrity sha1-ECyenpAF0+fjgpvwxPok7oYu6bk= - astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" @@ -1466,14 +1461,6 @@ callsites@^2.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= -camel-case@3.0.x: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" - integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= - dependencies: - no-case "^2.2.0" - upper-case "^1.1.1" - camelcase-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" @@ -1655,13 +1642,6 @@ classnames@^2.2.5: resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== -clean-css@4.2.x: - version "4.2.1" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17" - integrity sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g== - dependencies: - source-map "~0.6.0" - clean-webpack-plugin@^0.1.16: version "0.1.19" resolved "https://registry.yarnpkg.com/clean-webpack-plugin/-/clean-webpack-plugin-0.1.19.tgz#ceda8bb96b00fe168e9b080272960d20fdcadd6d" @@ -1802,7 +1782,7 @@ commander@2, commander@^2.11.0, commander@^2.19.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== -commander@2.17.x, commander@~2.17.1: +commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== @@ -2838,14 +2818,6 @@ es6-symbol@^3.1.0, es6-symbol@^3.1.1, es6-symbol@~3.1.1: d "1" es5-ext "~0.10.14" -es6-templates@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/es6-templates/-/es6-templates-0.2.3.tgz#5cb9ac9fb1ded6eb1239342b81d792bbb4078ee4" - integrity sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ= - dependencies: - recast "~0.11.12" - through "~2.3.6" - escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5, escape-string-regexp@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -3027,7 +2999,7 @@ esprima@^2.6.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= -esprima@^3.1.3, esprima@~3.1.0: +esprima@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= @@ -3799,11 +3771,6 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -he@1.2.x: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - history@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/history/-/history-4.7.2.tgz#22b5c7f31633c5b8021c7f4a8a954ac139ee8d5b" @@ -3877,30 +3844,6 @@ html-entities@^1.1.3: resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= -html-loader@^0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-0.5.5.tgz#6356dbeb0c49756d8ebd5ca327f16ff06ab5faea" - integrity sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog== - dependencies: - es6-templates "^0.2.3" - fastparse "^1.1.1" - html-minifier "^3.5.8" - loader-utils "^1.1.0" - object-assign "^4.1.1" - -html-minifier@^3.5.8: - version "3.5.21" - resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c" - integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA== - dependencies: - camel-case "3.0.x" - clean-css "4.2.x" - commander "2.17.x" - he "1.2.x" - param-case "2.1.x" - relateurl "0.2.x" - uglify-js "3.4.x" - htmlparser2@^3.9.0, htmlparser2@^3.9.1: version "3.10.1" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" @@ -5163,6 +5106,16 @@ loader-utils@1.1.0: emojis-list "^2.0.0" json5 "^0.5.0" +loader-utils@^0.2.11: + version "0.2.17" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" + integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= + dependencies: + big.js "^3.1.3" + emojis-list "^2.0.0" + json5 "^0.5.0" + object-assign "^4.0.1" + loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0: version "1.2.3" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" @@ -5253,11 +5206,6 @@ lodash.tail@^4.1.1: resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" integrity sha1-0jM6NtnncXyK0vfKyv7HwytERmQ= -lodash.throttle@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" - integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= - lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" @@ -5288,11 +5236,6 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" -lower-case@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" - integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= - lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" @@ -5752,13 +5695,6 @@ nise@^1.2.0: lolex "^2.3.2" path-to-regexp "^1.7.0" -no-case@^2.2.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" - integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== - dependencies: - lower-case "^1.1.1" - node-fetch@^1.0.1, node-fetch@^1.7.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" @@ -6265,13 +6201,6 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" -param-case@2.1.x: - version "2.1.1" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" - integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= - dependencies: - no-case "^2.2.0" - parse-asn1@^5.0.0: version "5.1.4" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc" @@ -6777,11 +6706,6 @@ pretty-format@^23.6.0: ansi-regex "^3.0.0" ansi-styles "^3.2.0" -private@~0.1.5: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" @@ -7293,16 +7217,6 @@ realpath-native@^1.0.0: dependencies: util.promisify "^1.0.0" -recast@~0.11.12: - version "0.11.23" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3" - integrity sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM= - dependencies: - ast-types "0.9.6" - esprima "~3.1.0" - private "~0.1.5" - source-map "~0.5.0" - redent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" @@ -7415,11 +7329,6 @@ regjsparser@^0.1.4: dependencies: jsesc "~0.5.0" -relateurl@0.2.x: - version "0.2.7" - resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= - remarkable@^1.x: version "1.7.1" resolved "https://registry.yarnpkg.com/remarkable/-/remarkable-1.7.1.tgz#aaca4972100b66a642a63a1021ca4bac1be3bff6" @@ -7987,12 +7896,12 @@ source-map@^0.4.2: dependencies: amdefine ">=0.0.4" -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0: +source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -8468,7 +8377,7 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -through@^2.3.6, through@~2.3.6: +through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -8638,7 +8547,7 @@ ua-parser-js@^0.7.12, ua-parser-js@^0.7.17, ua-parser-js@^0.7.18: resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.19.tgz#94151be4c0a7fb1d001af7022fdaca4642659e4b" integrity sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ== -uglify-js@3.4.x, uglify-js@^3.1.4: +uglify-js@^3.1.4: version "3.4.9" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q== @@ -8658,6 +8567,14 @@ underscore-contrib@~0.3.0: dependencies: underscore "1.6.0" +underscore-template-loader@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/underscore-template-loader/-/underscore-template-loader-1.0.0.tgz#e0853ee4850d22e00897c4638f36036ac08c0d7e" + integrity sha512-4tzm3DY8nLD6mKCQmPk51vu5HW8T61fSGpfkUrlrwF0oOPTinL8Zk7W08xHOmCZ2Sh9bZHVMzVgr/DUM+10iUA== + dependencies: + fastparse "^1.1.1" + loader-utils "^0.2.11" + underscore.string@~2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-2.4.0.tgz#8cdd8fbac4e2d2ea1e7e2e8097c42f442280f85b" @@ -8735,11 +8652,6 @@ upath@^1.1.0: resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== -upper-case@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" - integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= - uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" From 80d7c46e103feb5f82bd774baeef70597e9c192c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Mar=C3=ADa=20Signanini?= Date: Tue, 11 Jun 2019 13:12:51 -0400 Subject: [PATCH 2/8] Add c2p entry check to shouldBlock for smart block policy. --- src/classes/PolicySmartBlock.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/classes/PolicySmartBlock.js b/src/classes/PolicySmartBlock.js index 27c0052c5..f0db0a7cc 100644 --- a/src/classes/PolicySmartBlock.js +++ b/src/classes/PolicySmartBlock.js @@ -122,6 +122,7 @@ class PolicySmartBlock { * 3. Page is neither whitelisted or blacklisted * 4. Tracker is not site-specific unblocked * 5. Tracker is not site-specific blocked + * 6. Tracker does not have entry in Click2Play * * @param {number} tabId tab id * @param {string | boolean} appId tracker id @@ -136,7 +137,8 @@ class PolicySmartBlock { !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) + ((appId && (!conf.site_specific_blocks.hasOwnProperty(tabHost) || !conf.site_specific_blocks[tabHost].includes(+appId))) || appId === false) && + !c2pDb.db.apps.hasOwnProperty(appId) ); } From 50dc5a10742985bdf51cc849f05dbe527a15b300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Mar=C3=ADa=20Signanini?= Date: Tue, 11 Jun 2019 14:08:54 -0400 Subject: [PATCH 3/8] Implement c2p allow once for lazy loading trackers. --- app/templates/click2play.html | 4 +--- src/classes/Click2PlayDb.js | 23 ++++++++++++++++++++--- src/classes/EventHandlers.js | 6 +----- src/utils/click2play.js | 3 +-- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/app/templates/click2play.html b/app/templates/click2play.html index fb57e07e4..20cf5af2d 100644 --- a/app/templates/click2play.html +++ b/app/templates/click2play.html @@ -49,9 +49,7 @@

<%= data.click2play_text %>

<% } %> - <% if (data.smartBlocked === false) { %> - - <% } %> + <% if (data.blacklisted === false) { %> <% } %> diff --git a/src/classes/Click2PlayDb.js b/src/classes/Click2PlayDb.js index 635cfbce0..40324e497 100644 --- a/src/classes/Click2PlayDb.js +++ b/src/classes/Click2PlayDb.js @@ -66,18 +66,35 @@ class Click2PlayDb extends Updatable { // TODO memory leak when you close tabs before reset() can run? reset(tab_id) { - delete this.allowOnceList[tab_id]; + if (!this.allowOnceList.hasOwnProperty(tab_id)) { return; } + + const entries = Object.entries(this.allowOnceList[tab_id]); + let keep = false; + for (const [appID, count] of entries) { + const newCount = count - 1; + this.allowOnceList[tab_id][appID] = newCount; + if (newCount > 0) { + keep = true; + } + } + if (!keep) { + delete this.allowOnceList[tab_id]; + } } allowedOnce(tab_id, aid) { - return this.allowOnceList.hasOwnProperty(tab_id) && this.allowOnceList[tab_id].hasOwnProperty(aid); + return ( + this.allowOnceList.hasOwnProperty(tab_id) && + this.allowOnceList[tab_id].hasOwnProperty(aid) && + this.allowOnceList[tab_id][aid] > 0 + ); } allowOnce(app_ids, tab_id) { this.allowOnceList[tab_id] = {}; app_ids.forEach((app_id) => { - this.allowOnceList[tab_id][app_id] = 1; + this.allowOnceList[tab_id][app_id] = 2; }); } diff --git a/src/classes/EventHandlers.js b/src/classes/EventHandlers.js index 8467a3e89..0c4a2d9ab 100644 --- a/src/classes/EventHandlers.js +++ b/src/classes/EventHandlers.js @@ -78,6 +78,7 @@ class EventHandlers { tabInfo.create(tabId, url); foundBugs.update(tabId); button.update(tabId); + this._eventReset(details.tabId); // Workaround for foundBugs/tabInfo memory leak when the user triggers // prefetching/prerendering but never loads the page. Wait two minutes @@ -292,11 +293,6 @@ class EventHandlers { log('onNavigationCompleted injectScript error', err); }); } - // Requests may continue well after onNavigationCompleted, which breaks - // C2P's "allow once" feature because the allowOnceList is cleared too early - setTimeout(() => { - this._eventReset(details.tabId); - }, 5000); // match THRESHHOLD value in PolicySmartBlock._requestWasSlow() } /** diff --git a/src/utils/click2play.js b/src/utils/click2play.js index 211d2d6d6..f7095d2ed 100644 --- a/src/utils/click2play.js +++ b/src/utils/click2play.js @@ -43,7 +43,7 @@ const policy = new Policy(); * @param {number} app_id tracker id */ export function buildC2P(details, app_id) { - const { tab_id, smartBlocked } = details; + const { tab_id } = details; let c2pApp = c2pDb.db.apps && c2pDb.db.apps[app_id]; if (!c2pApp) { @@ -67,7 +67,6 @@ export function buildC2P(details, app_id) { c2pApp.forEach((c2pAppDef) => { const tplData = { blacklisted, // if the site is blacklisted, don't show allow_always button - smartBlocked, // if the app has been Smart Blocked, don't show allow_once (see comment block) button: !!c2pAppDef.button, ghostery_blocked_src: c2p_images.ghosty_blocked, allow_always_src: c2p_images.allow_unblock, From 1f71d11d4df69eb2be3baee28222b58e79bb8a93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Mar=C3=ADa=20Signanini?= Date: Tue, 11 Jun 2019 14:12:44 -0400 Subject: [PATCH 4/8] fix typo. --- src/classes/PolicySmartBlock.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/classes/PolicySmartBlock.js b/src/classes/PolicySmartBlock.js index f0db0a7cc..04e14310c 100644 --- a/src/classes/PolicySmartBlock.js +++ b/src/classes/PolicySmartBlock.js @@ -65,7 +65,7 @@ class PolicySmartBlock { } if (reason) { - log('Smart Blocking unblokced appId', appId, 'for reason:', reason); + log('Smart Blocking unblocked appId', appId, 'for reason:', reason); tabInfo.setTabSmartBlockAppInfo(tabId, appId, reason, false); return true; } From 80c917a973341dc55cbf7cae997f4f11101730c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Mar=C3=ADa=20Signanini?= Date: Tue, 11 Jun 2019 14:24:38 -0400 Subject: [PATCH 5/8] Destructure underscore lib imports. --- src/background.js | 10 +++++----- src/classes/Account.js | 4 ++-- src/classes/BugDb.js | 18 +++++++++--------- src/classes/EventHandlers.js | 10 +++++----- src/classes/Latency.js | 6 +++--- src/classes/PanelData.js | 6 +++--- src/classes/SurrogateDb.js | 10 +++++----- src/classes/Updatable.js | 6 +++--- src/utils/click2play.js | 4 ++-- src/utils/utils.js | 4 ++-- 10 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/background.js b/src/background.js index 6948e575e..58265a7f7 100644 --- a/src/background.js +++ b/src/background.js @@ -18,7 +18,7 @@ /** * @namespace Background */ -import _ from 'underscore'; +import { debounce, every, size } from 'underscore'; import moment from 'moment/min/moment-with-locales.min'; import cliqz, { prefs } from './classes/Cliqz'; // object class @@ -1058,11 +1058,11 @@ function onMessageHandler(request, sender, callback) { */ function initializeDispatcher() { dispatcher.on('conf.save.selected_app_ids', (appIds) => { - const num_selected = _.size(appIds); + const num_selected = size(appIds); 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))); + // 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))); }); dispatcher.on('conf.save.site_whitelist', () => { // TODO debounce with below @@ -1118,7 +1118,7 @@ function initializeDispatcher() { } }); - dispatcher.on('conf.changed.settings', _.debounce((key) => { + dispatcher.on('conf.changed.settings', debounce((key) => { log('Conf value changed for a watched user setting:', key); }, 200)); diff --git a/src/classes/Account.js b/src/classes/Account.js index 6b6e23c81..30a569f49 100644 --- a/src/classes/Account.js +++ b/src/classes/Account.js @@ -13,7 +13,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0 */ -import _ from 'underscore'; +import { isEqual } from 'underscore'; import normalize from 'json-api-normalizer'; import build from 'redux-object'; import RSVP from 'rsvp'; @@ -542,7 +542,7 @@ class Account { } SYNC_SET.forEach((key) => { if (settings[key] !== undefined && - !_.isEqual(conf[key], settings[key])) { + !isEqual(conf[key], settings[key])) { conf[key] = settings[key]; } }); diff --git a/src/classes/BugDb.js b/src/classes/BugDb.js index 1b80aefbf..b2990ed14 100644 --- a/src/classes/BugDb.js +++ b/src/classes/BugDb.js @@ -14,7 +14,7 @@ /* eslint no-param-reassign: 0 */ /* eslint no-shadow: 0 */ -import _ from 'underscore'; +import { difference, each, every, keys, reduce, size } from 'underscore'; import conf from './Conf'; import Updatable from './Updatable'; import { defineLazyProperty, flushChromeMemoryCache } from '../utils/utils'; @@ -38,9 +38,9 @@ class BugDb extends Updatable { updateNewAppIds(new_apps, old_apps) { log('updating newAppIds...'); - const new_app_ids = _.difference( - _.keys(new_apps), - _.keys(old_apps) + const new_app_ids = difference( + keys(new_apps), + keys(old_apps) ).map(Number); conf.new_app_ids = new_app_ids; @@ -55,7 +55,7 @@ class BugDb extends Updatable { if (conf.block_by_default) { log('applying block-by-default...'); const { selected_app_ids } = conf; - _.each(new_app_ids, (app_id) => { + each(new_app_ids, (app_id) => { selected_app_ids[app_id] = 1; }); conf.selected_app_ids = selected_app_ids; @@ -184,13 +184,13 @@ class BugDb extends Updatable { log('setting bugdb noneSelected/allSelected...'); - const num_selected = _.size(conf.selected_app_ids); + const num_selected = size(conf.selected_app_ids); db.noneSelected = (num_selected === 0); // 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))); + const num_selected = size(conf.selected_app_ids); + return (!!num_selected && every(db.apps, (app, app_id) => conf.selected_app_ids.hasOwnProperty(app_id))); }); log('processed bugdb...'); @@ -211,7 +211,7 @@ class BugDb extends Updatable { // pre-trie/legacy db } else if (old_bugs.hasOwnProperty('bugsVersion') && bugs.version !== old_bugs.bugsVersion) { - const old_apps = _.reduce(old_bugs.bugs, (memo, bug) => { + const old_apps = reduce(old_bugs.bugs, (memo, bug) => { memo[bug.aid] = true; return memo; }, {}); diff --git a/src/classes/EventHandlers.js b/src/classes/EventHandlers.js index 0c4a2d9ab..dbbc3ef39 100644 --- a/src/classes/EventHandlers.js +++ b/src/classes/EventHandlers.js @@ -14,7 +14,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0 */ -import _ from 'underscore'; +import { map, object, reduce, throttle } from 'underscore'; import bugDb from './BugDb'; import button from './BrowserButton'; import c2pDb from './Click2PlayDb'; @@ -51,7 +51,7 @@ class EventHandlers { // Use a 1sec interval to limit calls on pages with a large number of requests. // Don't use tabId with button.update for cases where tab is switched before throttle delay is reached. // ToDo: Remove this function when there is an event for AdBlocker:foundAd. - this._throttleButtonUpdate = _.throttle((tabId) => { + this._throttleButtonUpdate = throttle((tabId) => { button.update(tabId); }, 1000, { leading: false }); } @@ -238,7 +238,7 @@ class EventHandlers { if (result) { utils.sendMessage( tab_id, 'showUpgradeAlert', { - translations: _.object(_.map(alert_messages, key => [key, chrome.i18n.getMessage(key)])), + translations: object(map(alert_messages, key => [key, chrome.i18n.getMessage(key)])), language: conf.language, major_upgrade: globals.JUST_UPGRADED_FROM_7 }, @@ -256,7 +256,7 @@ class EventHandlers { if (result) { utils.sendMessage( tab_id, 'showLibraryUpdateAlert', { - translations: _.object(_.map(alert_messages, key => [key, chrome.i18n.getMessage(key)])), + translations: object(map(alert_messages, key => [key, chrome.i18n.getMessage(key)])), language: conf.language }, () => { @@ -670,7 +670,7 @@ class EventHandlers { const surrogates = surrogatedb.getForTracker(details.url, appId, bugId, ti.host); if (surrogates.length > 0) { - code = _.reduce(surrogates, (memo, s) => { + code = reduce(surrogates, (memo, s) => { memo += s.code; // eslint-disable-line no-param-reassign return memo; }, ''); diff --git a/src/classes/Latency.js b/src/classes/Latency.js index b4b1a32b7..f5b331111 100644 --- a/src/classes/Latency.js +++ b/src/classes/Latency.js @@ -13,7 +13,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0 */ -import _ from 'underscore'; +import { isEmpty } from 'underscore'; import foundBugs from './FoundBugs'; /** * Class for handling request latency data. @@ -38,7 +38,7 @@ class Latency { } // If the latencies object for this request id is empty then this is // not a tracker. Safe to delete object and return. - if (_.isEmpty(this.latencies[request_id])) { + if (isEmpty(this.latencies[request_id])) { delete this.latencies[request_id]; return 0; } @@ -55,7 +55,7 @@ class Latency { } = this.latencies[request_id][details.url]; delete this.latencies[request_id][details.url]; - if (_.isEmpty(this.latencies[request_id])) { + if (isEmpty(this.latencies[request_id])) { delete this.latencies[request_id]; } diff --git a/src/classes/PanelData.js b/src/classes/PanelData.js index 711c8b2cb..750e4bfc7 100644 --- a/src/classes/PanelData.js +++ b/src/classes/PanelData.js @@ -14,7 +14,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0 */ -import _ from 'underscore'; +import { isEqual, throttle } from 'underscore'; import button from './BrowserButton'; import cliqz from './Cliqz'; import conf from './Conf'; @@ -232,7 +232,7 @@ class PanelData { * Invoked in EventHandlers#onBeforeRequest when a new bug has been found * Sends updated data to the panel and blocking and/or summary components */ - updatePanelUI = _.throttle(this._updatePanelUI.bind(this), 600, { leading: true, trailing: true }); // matches donut redraw throttling + updatePanelUI = throttle(this._updatePanelUI.bind(this), 600, { leading: true, trailing: true }); // matches donut redraw throttling _updatePanelUI() { if (!this._panelPort || !this._activeTab) { return; } @@ -616,7 +616,7 @@ 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)) { + if (conf.hasOwnProperty(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 diff --git a/src/classes/SurrogateDb.js b/src/classes/SurrogateDb.js index 4410ac02c..f3d60ff69 100644 --- a/src/classes/SurrogateDb.js +++ b/src/classes/SurrogateDb.js @@ -11,7 +11,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0 */ -import _ from 'underscore'; +import { any, filter, isArray, map } from 'underscore'; import conf from './Conf'; import Updatable from './Updatable'; import { log } from '../utils/common'; @@ -59,14 +59,14 @@ class SurrogateDb extends Updatable { // convert single values to arrays first ['pattern_id', 'app_id', 'sites', 'match'].forEach((prop) => { - if (s.hasOwnProperty(prop) && !_.isArray(s[prop])) { + if (s.hasOwnProperty(prop) && !isArray(s[prop])) { s[prop] = [s[prop]]; } }); // initialize regexes if (s.hasOwnProperty('match')) { - s.match = _.map(s.match, match => new RegExp(match, '')); + s.match = map(s.match, match => new RegExp(match, '')); } if (s.hasOwnProperty('pattern_id') || s.hasOwnProperty('app_id')) { @@ -108,7 +108,7 @@ class SurrogateDb extends Updatable { candidates = candidates.concat(this.db.pattern_ids[pattern_id]); } - return _.filter(candidates, (surrogate) => { + return filter(candidates, (surrogate) => { // note: does not support *.example.com (exact matches only) if (surrogate.hasOwnProperty('sites')) { // array of site hosts if (!surrogate.sites.includes(host_name)) { @@ -117,7 +117,7 @@ class SurrogateDb extends Updatable { } if (surrogate.hasOwnProperty('match')) { - if (!_.any(surrogate.match, match => script_src.match(match))) { + if (!any(surrogate.match, match => script_src.match(match))) { return false; } } diff --git a/src/classes/Updatable.js b/src/classes/Updatable.js index 5362f7870..fc9f86321 100644 --- a/src/classes/Updatable.js +++ b/src/classes/Updatable.js @@ -11,7 +11,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0 */ -import _ from 'underscore'; +import { bind, isFunction } from 'underscore'; import globals from './Globals'; import conf from './Conf'; import { getJson, fetchLocalJSONResource } from '../utils/utils'; @@ -56,7 +56,7 @@ class Updatable { callback }; - if (_.isFunction(version)) { + if (isFunction(version)) { opts.callback = version; delete opts.version; } @@ -166,7 +166,7 @@ class Updatable { } // Fetch new bugs list from remote. Bind the callback param from _remoteFetcher() to this anonymous function - this._remoteFetcher(_.bind(function (result, list) { + this._remoteFetcher(bind(function (result, list) { // if the fetch worked and we have a list returned if (result && list) { const data = this.processList(false, list); diff --git a/src/utils/click2play.js b/src/utils/click2play.js index f7095d2ed..0c6fdf176 100644 --- a/src/utils/click2play.js +++ b/src/utils/click2play.js @@ -13,7 +13,7 @@ /* eslint no-use-before-define: 0 */ -import _ from 'underscore'; +import { reject } from 'underscore'; import bugDb from '../classes/BugDb'; import c2pDb from '../classes/Click2PlayDb'; import conf from '../classes/Conf'; @@ -52,7 +52,7 @@ export function buildC2P(details, app_id) { // click-to-play for social buttons might be disabled if (!conf.enable_click2play_social) { - c2pApp = _.reject(c2pApp, c2pAppDef => !!c2pAppDef.button); + c2pApp = reject(c2pApp, c2pAppDef => !!c2pAppDef.button); } if (!c2pApp.length) { diff --git a/src/utils/utils.js b/src/utils/utils.js index 431963149..a863095f9 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -18,7 +18,7 @@ /** * @namespace BackgroundUtils */ -import _ from 'underscore'; +import { debounce } from 'underscore'; import url from 'url'; import tabInfo from '../classes/TabInfo'; import globals from '../classes/Globals'; @@ -114,7 +114,7 @@ export function isValidTopLevelNavigation(details) { * (can default to 20 if undefined) * @memberOf BackgroundUtils */ -export const flushChromeMemoryCache = _.debounce(() => { +export const flushChromeMemoryCache = debounce(() => { chrome.webRequest.handlerBehaviorChanged(); }, 1000 * 35, true); From 93f3d7cfc099530349af385fd5dcef5b20f6c457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Mar=C3=ADa=20Signanini?= Date: Tue, 11 Jun 2019 14:26:34 -0400 Subject: [PATCH 6/8] Destructure underscore lib imports in front-end. --- app/panel/components/BuildingBlocks/DonutGraph.jsx | 4 ++-- app/panel/components/BuildingBlocks/StatsGraph.jsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/panel/components/BuildingBlocks/DonutGraph.jsx b/app/panel/components/BuildingBlocks/DonutGraph.jsx index 3076f12a2..64fdcf148 100644 --- a/app/panel/components/BuildingBlocks/DonutGraph.jsx +++ b/app/panel/components/BuildingBlocks/DonutGraph.jsx @@ -11,7 +11,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0 */ -import _ from 'underscore'; +import { throttle } from 'underscore'; import React from 'react'; import ClassNames from 'classnames'; import { @@ -178,7 +178,7 @@ class DonutGraph extends React.Component { * @param {Array} categories list of categories detected on the site * @param {Object} options options for the graph */ - bakeDonut = _.throttle(this._bakeDonut.bind(this), 600, { leading: true, trailing: true }) // matches panelData#updatePanelUI throttling + bakeDonut = throttle(this._bakeDonut.bind(this), 600, { leading: true, trailing: true }) // matches panelData#updatePanelUI throttling _bakeDonut(categories, options) { const { diff --git a/app/panel/components/BuildingBlocks/StatsGraph.jsx b/app/panel/components/BuildingBlocks/StatsGraph.jsx index b00eddf4f..02f12948c 100644 --- a/app/panel/components/BuildingBlocks/StatsGraph.jsx +++ b/app/panel/components/BuildingBlocks/StatsGraph.jsx @@ -11,7 +11,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0 */ -import _ from 'underscore'; +import { isEqual } from 'underscore'; import React from 'react'; import * as D3 from 'd3'; @@ -30,7 +30,7 @@ class StatsGraph extends React.Component { * Lifecycle event */ componentDidUpdate(prevProps) { - if (!_.isEqual(prevProps, this.props)) { + if (!isEqual(prevProps, this.props)) { this.generateGraph(); } } From 3e395a57e3c9309920e04d206c3f2efba0ada569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Mar=C3=ADa=20Signanini?= Date: Tue, 11 Jun 2019 14:30:27 -0400 Subject: [PATCH 7/8] Remove unused condition. --- src/classes/PolicySmartBlock.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/classes/PolicySmartBlock.js b/src/classes/PolicySmartBlock.js index 04e14310c..fe39b3bc3 100644 --- a/src/classes/PolicySmartBlock.js +++ b/src/classes/PolicySmartBlock.js @@ -99,12 +99,9 @@ class PolicySmartBlock { reason = 'allowedType'; // allow if tracker is in breaking type } else if (this._pageWasReloaded(tabId, appId)) { reason = 'pageReloaded'; // allow if page has been reloaded recently - } else if (c2pDb.allowedOnce(tabId, appId)) { - reason = 'c2pAllowOnce'; // allow if the user has selected "allow once" in Click2Play } } - // We are only blocking slow trackers that do not cause page breakage const result = (reason === 'slow'); if (result) { log('Smart Blocking blocked appId', appId, 'for reason:', reason); From 0207e997894818f573c9e4e253fe55a85c896de6 Mon Sep 17 00:00:00 2001 From: Christopher Tino Date: Tue, 11 Jun 2019 16:15:53 -0400 Subject: [PATCH 8/8] update comment on buildC2P --- src/utils/click2play.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/utils/click2play.js b/src/utils/click2play.js index 0c6fdf176..f87862dad 100644 --- a/src/utils/click2play.js +++ b/src/utils/click2play.js @@ -33,10 +33,6 @@ const policy = new Policy(); * Restricted Sites: Only show the "allow once" option, since blacklisting overrides * site-specific tracker allow settings. * - * Smart Blocking: If the app was blocked by Smart Blocking, we only show the "allow always" option because - * the tracker was most likely a lazy-loaded widget (comment, video) and C2P will reset the allowOnceList - * before the widget has a chance to load. - * * @memberOf BackgroundUtils * * @param {Object} details request parameters