From e5148b30b48e80871107b6f6e88b550550687fc7 Mon Sep 17 00:00:00 2001 From: Alex Ristich Date: Sun, 18 Feb 2018 13:02:03 -0800 Subject: [PATCH 01/13] Modifying content scripts to use contentScripts API for conditional injection (only FF) --- src/js/background.js | 50 +++++++++++++++++++++++++ src/js/contentscripts/fingerprinting.js | 39 ++++++++----------- src/js/contentscripts/socialwidgets.js | 9 +---- src/manifest.json | 23 ------------ 4 files changed, 67 insertions(+), 54 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index 9f4861e4f3..fe17c28fe4 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -50,6 +50,7 @@ function Badger() { self.heuristicBlocking = new HeuristicBlocking.HeuristicBlocker(thisStorage); self.updateTabList(); self.initializeDefaultSettings(); + self.registerContentScripts(); try { self.runMigrations(); } finally { @@ -700,6 +701,7 @@ Badger.prototype = { if (disabledSites.indexOf(origin) < 0) { disabledSites.push(origin); settings.setItem("disabledSites", disabledSites); + this.registerContentScripts(); } }, @@ -722,9 +724,57 @@ Badger.prototype = { if (idx >= 0) { utils.removeElementFromArray(disabledSites, idx); settings.setItem("disabledSites", disabledSites); + this.registerContentScripts(); } }, + // This handles the logic for the "checkEnabled" message being passed + // from the background page to the content scripts. + // TODO Figure out how to pass configuration with these scripts. + registerContentScripts: function() { + // This feature only works for browsers that support the contentScripts API. + if (browser && !browser.contentScripts) { + return; + } + + if (badger.activeContentScripts) { + badger.activeContentScripts.unregister(); + } + + if (badger.idleContentScripts) { + badger.idleContentScripts.unregister(); + } + + const whitelistedURLs = badger.getSettings().getItem('disabledSites') + .map((site) => 'https:\/\/' + site + '/'); + + const registerActive = browser.contentScripts.register({ + 'js': [ + {file: '/js/contentscripts/fingerprinting.js'}, + {file: '/js/contentscripts/clobbercookie.js'}, + {file: '/js/contentscripts/clobberlocalstorage.js'}], + 'matches': ["http://*/*", "https://*/*"], + 'excludeMatches': whitelistedURLs, + 'allFrames': true, + 'runAt': 'document_start' + }); + + registerActive.then((res) => {badger.activeContentScripts = res}); + + // TODO socialwidgets.js should only be loaded if widget replacement is enabled. + const registerIdle = browser.contentScripts.register({ + 'js': [ + {file: '/js/contentscripts/socialwidgets.js'}, + {file: '/js/contentscripts/supercookie.js'}], + 'matches': ["http://*/*", "https://*/*"], + 'excludeMatches': whitelistedURLs, + 'allFrames': true, + 'runAt': 'document_idle' + }); + + registerIdle.then((res) => {badger.idleContentScripts = res}); + }, + /** * Checks if local storage ( in dict) has any high-entropy keys * diff --git a/src/js/contentscripts/fingerprinting.js b/src/js/contentscripts/fingerprinting.js index 61ca56b588..dfad784ae8 100644 --- a/src/js/contentscripts/fingerprinting.js +++ b/src/js/contentscripts/fingerprinting.js @@ -320,27 +320,20 @@ function insertFpScript(text, data) { parent.removeChild(script); } -// TODO race condition; fix waiting on https://crbug.com/478183 -chrome.runtime.sendMessage({checkEnabled: true}, - function (enabled) { - if (!enabled) { - return; - } - /** - * Communicating to webrequest.js - */ - var event_id = Math.random(); - - // listen for messages from the script we are about to insert - document.addEventListener(event_id, function (e) { - // pass these on to the background page - chrome.runtime.sendMessage({ - 'fpReport': e.detail - }); - }); +/** + * Communicating to webrequest.js + */ +var event_id = Math.random(); + +// listen for messages from the script we are about to insert +document.addEventListener(event_id, function (e) { + // pass these on to the background page + chrome.runtime.sendMessage({ + 'fpReport': e.detail + }); +}); + +insertFpScript(getFpPageScript(), { + event_id: event_id +}); - insertFpScript(getFpPageScript(), { - event_id: event_id - }); - } -); diff --git a/src/js/contentscripts/socialwidgets.js b/src/js/contentscripts/socialwidgets.js index acf097fd51..803a556c32 100644 --- a/src/js/contentscripts/socialwidgets.js +++ b/src/js/contentscripts/socialwidgets.js @@ -327,11 +327,4 @@ function unblockTracker(buttonUrls, callback) { chrome.runtime.sendMessage(request, callback); } -chrome.runtime.sendMessage({ - checkSocialWidgetReplacementEnabled: true -}, function (checkSocialWidgetReplacementEnabled) { - if (!checkSocialWidgetReplacementEnabled) { - return; - } - initialize(); -}); +initialize(); diff --git a/src/manifest.json b/src/manifest.json index d3a584aaff..c30aa347e5 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -53,29 +53,6 @@ "http://twitter.com/*" ], "run_at": "document_idle" - }, - { - "js": [ - "js/contentscripts/clobbercookie.js", - "js/contentscripts/clobberlocalstorage.js", - "js/contentscripts/fingerprinting.js" - ], - "matches": [ - "" - ], - "all_frames": true, - "run_at": "document_start" - }, - { - "js": [ - "js/contentscripts/socialwidgets.js", - "js/contentscripts/supercookie.js" - ], - "matches": [ - "" - ], - "all_frames": true, - "run_at": "document_idle" } ], "default_locale": "en_US", From df870014d1449ea3e1b5cdbbd69fd213265de4b2 Mon Sep 17 00:00:00 2001 From: Alex Ristich Date: Sun, 18 Feb 2018 13:55:57 -0800 Subject: [PATCH 02/13] Updating matching syntax for whitelisted URLs --- src/js/background.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/js/background.js b/src/js/background.js index fe17c28fe4..2d2e7f29e8 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -745,8 +745,9 @@ Badger.prototype = { badger.idleContentScripts.unregister(); } + // Convert the domains in disabledSites into URLs that can be matched against. const whitelistedURLs = badger.getSettings().getItem('disabledSites') - .map((site) => 'https:\/\/' + site + '/'); + .map((site) => '*:\/\/' + site + '/*'); const registerActive = browser.contentScripts.register({ 'js': [ From a489ac755655d818a7644fc90c49ba01aab02e8c Mon Sep 17 00:00:00 2001 From: Alex Ristich Date: Sun, 18 Feb 2018 14:00:14 -0800 Subject: [PATCH 03/13] Linting --- src/js/background.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index 2d2e7f29e8..cdddd882ff 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -747,7 +747,7 @@ Badger.prototype = { // Convert the domains in disabledSites into URLs that can be matched against. const whitelistedURLs = badger.getSettings().getItem('disabledSites') - .map((site) => '*:\/\/' + site + '/*'); + .map((site) => '*://' + site + '/*'); const registerActive = browser.contentScripts.register({ 'js': [ @@ -760,7 +760,7 @@ Badger.prototype = { 'runAt': 'document_start' }); - registerActive.then((res) => {badger.activeContentScripts = res}); + registerActive.then((res) => {badger.activeContentScripts = res;}); // TODO socialwidgets.js should only be loaded if widget replacement is enabled. const registerIdle = browser.contentScripts.register({ @@ -773,7 +773,7 @@ Badger.prototype = { 'runAt': 'document_idle' }); - registerIdle.then((res) => {badger.idleContentScripts = res}); + registerIdle.then((res) => {badger.idleContentScripts = res;}); }, /** From 2788d9239569f052c751b7b616bec49d92d252f3 Mon Sep 17 00:00:00 2001 From: Alex Ristich Date: Sat, 24 Feb 2018 20:02:09 -0800 Subject: [PATCH 04/13] Wrapping register() functions if no whitelisted URLs --- src/js/background.js | 48 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index cdddd882ff..e6f40ef762 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -749,31 +749,31 @@ Badger.prototype = { const whitelistedURLs = badger.getSettings().getItem('disabledSites') .map((site) => '*://' + site + '/*'); - const registerActive = browser.contentScripts.register({ - 'js': [ - {file: '/js/contentscripts/fingerprinting.js'}, - {file: '/js/contentscripts/clobbercookie.js'}, - {file: '/js/contentscripts/clobberlocalstorage.js'}], - 'matches': ["http://*/*", "https://*/*"], - 'excludeMatches': whitelistedURLs, - 'allFrames': true, - 'runAt': 'document_start' - }); - - registerActive.then((res) => {badger.activeContentScripts = res;}); - - // TODO socialwidgets.js should only be loaded if widget replacement is enabled. - const registerIdle = browser.contentScripts.register({ - 'js': [ - {file: '/js/contentscripts/socialwidgets.js'}, - {file: '/js/contentscripts/supercookie.js'}], - 'matches': ["http://*/*", "https://*/*"], - 'excludeMatches': whitelistedURLs, - 'allFrames': true, - 'runAt': 'document_idle' - }); + if (whitelistedURLs.length > 0) { + const registerActive = browser.contentScripts.register({ + 'js': [ + {file: '/js/contentscripts/fingerprinting.js'}, + {file: '/js/contentscripts/clobbercookie.js'}, + {file: '/js/contentscripts/clobberlocalstorage.js'}], + 'matches': ["http://*/*", "https://*/*"], + 'excludeMatches': whitelistedURLs, + 'allFrames': true, + 'runAt': 'document_start' + }); + // TODO socialwidgets.js should only be loaded if widget replacement is enabled. + const registerIdle = browser.contentScripts.register({ + 'js': [ + {file: '/js/contentscripts/socialwidgets.js'}, + {file: '/js/contentscripts/supercookie.js'}], + 'matches': ["http://*/*", "https://*/*"], + 'excludeMatches': whitelistedURLs, + 'allFrames': true, + 'runAt': 'document_idle' + }); - registerIdle.then((res) => {badger.idleContentScripts = res;}); + registerActive.then((res) => {badger.activeContentScripts = res;}); + registerIdle.then((res) => {badger.idleContentScripts = res;}); + } }, /** From 0dc6f5c4246ec87cd7d024cbf6059002f570c810 Mon Sep 17 00:00:00 2001 From: Alex Ristich Date: Sat, 24 Feb 2018 20:16:44 -0800 Subject: [PATCH 05/13] Exit early if whitelistedURLs is empty --- src/js/background.js | 50 +++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index e6f40ef762..3e5f615099 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -749,31 +749,33 @@ Badger.prototype = { const whitelistedURLs = badger.getSettings().getItem('disabledSites') .map((site) => '*://' + site + '/*'); - if (whitelistedURLs.length > 0) { - const registerActive = browser.contentScripts.register({ - 'js': [ - {file: '/js/contentscripts/fingerprinting.js'}, - {file: '/js/contentscripts/clobbercookie.js'}, - {file: '/js/contentscripts/clobberlocalstorage.js'}], - 'matches': ["http://*/*", "https://*/*"], - 'excludeMatches': whitelistedURLs, - 'allFrames': true, - 'runAt': 'document_start' - }); - // TODO socialwidgets.js should only be loaded if widget replacement is enabled. - const registerIdle = browser.contentScripts.register({ - 'js': [ - {file: '/js/contentscripts/socialwidgets.js'}, - {file: '/js/contentscripts/supercookie.js'}], - 'matches': ["http://*/*", "https://*/*"], - 'excludeMatches': whitelistedURLs, - 'allFrames': true, - 'runAt': 'document_idle' - }); - - registerActive.then((res) => {badger.activeContentScripts = res;}); - registerIdle.then((res) => {badger.idleContentScripts = res;}); + if (whitelistedURLs.length === 0) { + return; } + + const registerActive = browser.contentScripts.register({ + 'js': [ + {file: '/js/contentscripts/fingerprinting.js'}, + {file: '/js/contentscripts/clobbercookie.js'}, + {file: '/js/contentscripts/clobberlocalstorage.js'}], + 'matches': ["http://*/*", "https://*/*"], + 'excludeMatches': whitelistedURLs, + 'allFrames': true, + 'runAt': 'document_start' + }); + // TODO socialwidgets.js should only be loaded if widget replacement is enabled. + const registerIdle = browser.contentScripts.register({ + 'js': [ + {file: '/js/contentscripts/socialwidgets.js'}, + {file: '/js/contentscripts/supercookie.js'}], + 'matches': ["http://*/*", "https://*/*"], + 'excludeMatches': whitelistedURLs, + 'allFrames': true, + 'runAt': 'document_idle' + }); + + registerActive.then((res) => {badger.activeContentScripts = res;}); + registerIdle.then((res) => {badger.idleContentScripts = res;}); }, /** From 901515f06c75d13ba3e0a9263c3856f1ad82ac66 Mon Sep 17 00:00:00 2001 From: Alex Ristich Date: Sat, 24 Feb 2018 21:48:53 -0800 Subject: [PATCH 06/13] Add executeScript calls to inject content scripts --- src/js/background.js | 55 ++++++++++++++++++++++++++++++++++++++++---- src/js/webrequest.js | 15 +++++++++++- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index 3e5f615099..caf61a071b 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -728,12 +728,14 @@ Badger.prototype = { } }, - // This handles the logic for the "checkEnabled" message being passed - // from the background page to the content scripts. - // TODO Figure out how to pass configuration with these scripts. + /** + * Registers content scripts using the contentScripts API; currently only + * available in FF59+. + * TODO Figure out how to pass configuration with these scripts. + */ registerContentScripts: function() { - // This feature only works for browsers that support the contentScripts API. - if (browser && !browser.contentScripts) { + // TODO 'browser' is undefined in Chrome + if (!browser || !browser.contentScripts) { return; } @@ -778,6 +780,49 @@ Badger.prototype = { registerIdle.then((res) => {badger.idleContentScripts = res;}); }, + /** + * Insert into the tab the required content scripts based on whitelisting status. + * + * @param {Integer} tab_id The ID of the tab + * @param {String} url The URL of the specified tab + */ + insertContentScripts(tab_id, url) { + if (!this.isPrivacyBadgerEnabled(url)) { + return; + } + + // Insert all scripts + // TODO Put this in a loop? + chrome.tabs.executeScript(tab_id, { + 'file': '/js/contentscripts/fingerprinting.js', + 'allFrames': true, + 'runAt': 'document_start' + }); + chrome.tabs.executeScript(tab_id, { + 'file': '/js/contentscripts/clobbercookies.js', + 'allFrames': true, + 'runAt': 'document_start' + }); + chrome.tabs.executeScript(tab_id, { + 'file': '/js/contentscripts/clobberlocalstorage.js', + 'allFrames': true, + 'runAt': 'document_start' + }); + chrome.tabs.executeScript(tab_id, { + 'file': '/js/contentscripts/supercookie.js', + 'allFrames': true, + 'runAt': 'document_idle' + }); + + if (this.isSocialWidgetReplacementEnabled()) { + chrome.tabs.executeScript(tab_id, { + 'file': '/js/contentscripts/fingerprinting.js', + 'allFrames': true, + 'runAt': 'document_start' + }); + } + }, + /** * Checks if local storage ( in dict) has any high-entropy keys * diff --git a/src/js/webrequest.js b/src/js/webrequest.js index de047b7ef7..0d906dbdfd 100644 --- a/src/js/webrequest.js +++ b/src/js/webrequest.js @@ -52,6 +52,18 @@ function onBeforeRequest(details) { type = details.type, url = details.url; + var isInternal = _isTabChromeInternal(tab_id); + + // TODO The first thing we want to do is to inject the scripts. + // This should be done in every case except for when Privacy Badger is not enabled. + if (!isInternal) { + // TODO Check if this is FF59 or up + + // TODO Can this function be async? Can we run this only on 'main_frame' and have + // it get inserted into all frames? If so, we don't need (nor want?) async. + badger.insertContentScripts(tab_id, url); + } + if (type == "main_frame") { forgetTab(tab_id); @@ -77,7 +89,8 @@ function onBeforeRequest(details) { return {cancel: true}; } - if (_isTabChromeInternal(tab_id)) { + // TODO Any danger in moving this above `main_frame` check? + if (isInternal) { return {}; } From 4535a2f2533968bd6ace3520f62887bc7b4325e9 Mon Sep 17 00:00:00 2001 From: Alex Ristich Date: Sun, 25 Feb 2018 22:01:26 -0800 Subject: [PATCH 07/13] Avoid registering content scripts if running in Chrome --- src/js/background.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index caf61a071b..547cd8cb71 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -734,8 +734,8 @@ Badger.prototype = { * TODO Figure out how to pass configuration with these scripts. */ registerContentScripts: function() { - // TODO 'browser' is undefined in Chrome - if (!browser || !browser.contentScripts) { + // If 'browser' is undefined, we are running in Chrome. + if (typeof browser === "undefined" || !browser.contentScripts) { return; } From 4c1fdaedb6b85d2528b2fe96f798db74cff66110 Mon Sep 17 00:00:00 2001 From: Alex Ristich Date: Sun, 25 Feb 2018 23:24:32 -0800 Subject: [PATCH 08/13] Prevent insertContentScripts from getting executed in FF59+ --- src/js/background.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/js/background.js b/src/js/background.js index 547cd8cb71..47394bb532 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -790,6 +790,12 @@ Badger.prototype = { if (!this.isPrivacyBadgerEnabled(url)) { return; } + // In FF 59+, content scripts are injected with registerContentScripts(). + if (typeof browser !== "undefined" && browser.contentScripts) { + return; + } + + // TODO Can we have these scripts only get inserted once for each frame? // Insert all scripts // TODO Put this in a loop? From e01a8262a6c9d2b90283a6399a51a1be6b127c87 Mon Sep 17 00:00:00 2001 From: Alex Ristich Date: Sun, 25 Feb 2018 23:32:12 -0800 Subject: [PATCH 09/13] Correctly insert content scripts when whitelist is empty --- src/js/background.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index 47394bb532..a65964a5e5 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -751,30 +751,33 @@ Badger.prototype = { const whitelistedURLs = badger.getSettings().getItem('disabledSites') .map((site) => '*://' + site + '/*'); - if (whitelistedURLs.length === 0) { - return; - } - - const registerActive = browser.contentScripts.register({ + const activeScripts = { 'js': [ {file: '/js/contentscripts/fingerprinting.js'}, {file: '/js/contentscripts/clobbercookie.js'}, {file: '/js/contentscripts/clobberlocalstorage.js'}], 'matches': ["http://*/*", "https://*/*"], - 'excludeMatches': whitelistedURLs, 'allFrames': true, 'runAt': 'document_start' - }); - // TODO socialwidgets.js should only be loaded if widget replacement is enabled. - const registerIdle = browser.contentScripts.register({ + }; + + const idleScripts = { 'js': [ {file: '/js/contentscripts/socialwidgets.js'}, {file: '/js/contentscripts/supercookie.js'}], 'matches': ["http://*/*", "https://*/*"], - 'excludeMatches': whitelistedURLs, 'allFrames': true, 'runAt': 'document_idle' - }); + }; + + if (whitelistedURLs.length > 0) { + activeScripts.excludeMatches = whitelistedURLs; + idleScripts.excludeMatches = whitelistedURLs; + } + + const registerActive = browser.contentScripts.register(activeScripts); + // TODO socialwidgets.js should only be loaded if widget replacement is enabled. + const registerIdle = browser.contentScripts.register(idleScripts); registerActive.then((res) => {badger.activeContentScripts = res;}); registerIdle.then((res) => {badger.idleContentScripts = res;}); From 12c5da4c55d86b2a3fc2c3ff5e57e84f150ffdd6 Mon Sep 17 00:00:00 2001 From: Alex Ristich Date: Sun, 25 Feb 2018 23:38:43 -0800 Subject: [PATCH 10/13] Insert social widget content script only when replacement is enabled --- src/js/background.js | 9 +++++---- src/js/contentscripts/fingerprinting.js | 1 + src/js/contentscripts/socialwidgets.js | 1 + src/js/options.js | 1 + 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index a65964a5e5..bbc105b3ff 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -762,9 +762,7 @@ Badger.prototype = { }; const idleScripts = { - 'js': [ - {file: '/js/contentscripts/socialwidgets.js'}, - {file: '/js/contentscripts/supercookie.js'}], + 'js': [{file: '/js/contentscripts/supercookie.js'}], 'matches': ["http://*/*", "https://*/*"], 'allFrames': true, 'runAt': 'document_idle' @@ -775,8 +773,11 @@ Badger.prototype = { idleScripts.excludeMatches = whitelistedURLs; } + if (badger.isSocialWidgetReplacementEnabled()) { + idleScripts.js.push({file: '/js/contentscripts/socialwidgets.js'}); + } + const registerActive = browser.contentScripts.register(activeScripts); - // TODO socialwidgets.js should only be loaded if widget replacement is enabled. const registerIdle = browser.contentScripts.register(idleScripts); registerActive.then((res) => {badger.activeContentScripts = res;}); diff --git a/src/js/contentscripts/fingerprinting.js b/src/js/contentscripts/fingerprinting.js index dfad784ae8..95afec2358 100644 --- a/src/js/contentscripts/fingerprinting.js +++ b/src/js/contentscripts/fingerprinting.js @@ -20,6 +20,7 @@ function getFpPageScript() { + console.log('inserting fp script'); // code below is not a content script: no chrome.* APIs ///////////////////// // return a string diff --git a/src/js/contentscripts/socialwidgets.js b/src/js/contentscripts/socialwidgets.js index 803a556c32..311e6d1fda 100644 --- a/src/js/contentscripts/socialwidgets.js +++ b/src/js/contentscripts/socialwidgets.js @@ -55,6 +55,7 @@ let i18n = chrome.i18n; * Initializes the content script. */ function initialize() { + console.info('insert social widget script'); // Get tracker info and check for initial blocks (that happened // before content script was attached) getTrackerData(function (trackers, trackerButtonsToReplace) { diff --git a/src/js/options.js b/src/js/options.js index 3dc4a30dc5..91f58ed56f 100644 --- a/src/js/options.js +++ b/src/js/options.js @@ -295,6 +295,7 @@ function updateShowCounter() { function updateSocialWidgetReplacement() { var replaceSocialWidgets = $("#replace_social_widgets_checkbox").prop("checked"); settings.setItem("socialWidgetReplacementEnabled", replaceSocialWidgets); + badger.registerContentScripts(); } function updateCheckingDNTPolicy() { From 19e91a2bd5eadcb646807f3e05f9ed3d4e881bed Mon Sep 17 00:00:00 2001 From: Alex Ristich Date: Wed, 28 Mar 2018 21:30:41 -0700 Subject: [PATCH 11/13] Call insertContentScripts in main_frame and sub_frame --- src/js/background.js | 13 ++++++++----- src/js/webrequest.js | 16 ++++------------ 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index bbc105b3ff..ca94ca1ecc 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -787,11 +787,13 @@ Badger.prototype = { /** * Insert into the tab the required content scripts based on whitelisting status. * - * @param {Integer} tab_id The ID of the tab + * @param {int} tab_id The ID of the tab * @param {String} url The URL of the specified tab + * @param {int} frame_id The ID from the current frame + * @param {Boolean} is_internal Whether this tab is an internal browser tab */ - insertContentScripts(tab_id, url) { - if (!this.isPrivacyBadgerEnabled(url)) { + insertContentScripts(tab_id, url, frame_id, is_internal) { + if (!this.isPrivacyBadgerEnabled(url) || is_internal) { return; } // In FF 59+, content scripts are injected with registerContentScripts(). @@ -799,7 +801,8 @@ Badger.prototype = { return; } - // TODO Can we have these scripts only get inserted once for each frame? + // TODO Add frame_id to executeScript calls + // TODO Add no-op function for executeScript // Insert all scripts // TODO Put this in a loop? @@ -809,7 +812,7 @@ Badger.prototype = { 'runAt': 'document_start' }); chrome.tabs.executeScript(tab_id, { - 'file': '/js/contentscripts/clobbercookies.js', + 'file': '/js/contentscripts/clobbercookie.js', 'allFrames': true, 'runAt': 'document_start' }); diff --git a/src/js/webrequest.js b/src/js/webrequest.js index 0d906dbdfd..ad4111038a 100644 --- a/src/js/webrequest.js +++ b/src/js/webrequest.js @@ -52,17 +52,7 @@ function onBeforeRequest(details) { type = details.type, url = details.url; - var isInternal = _isTabChromeInternal(tab_id); - - // TODO The first thing we want to do is to inject the scripts. - // This should be done in every case except for when Privacy Badger is not enabled. - if (!isInternal) { - // TODO Check if this is FF59 or up - - // TODO Can this function be async? Can we run this only on 'main_frame' and have - // it get inserted into all frames? If so, we don't need (nor want?) async. - badger.insertContentScripts(tab_id, url); - } + var is_internal = _isTabChromeInternal(tab_id); if (type == "main_frame") { forgetTab(tab_id); @@ -74,12 +64,14 @@ function onBeforeRequest(details) { } badger.recordFrame(tab_id, frame_id, details.parentFrameId, url); + badger.insertContentScripts(tab_id, url, frame_id, is_internal); return {}; } if (type == "sub_frame") { badger.recordFrame(tab_id, frame_id, details.parentFrameId, url); + badger.insertContentScripts(tab_id, url, frame_id, is_internal); } // Block ping requests sent by navigator.sendBeacon (see, #587) @@ -90,7 +82,7 @@ function onBeforeRequest(details) { } // TODO Any danger in moving this above `main_frame` check? - if (isInternal) { + if (is_internal) { return {}; } From 7053026ca17b93159d52ebcfd06c051584478380 Mon Sep 17 00:00:00 2001 From: Alex Ristich Date: Wed, 28 Mar 2018 22:04:35 -0700 Subject: [PATCH 12/13] Add frame_id to executeScript calls, empty error callback --- src/js/background.js | 29 ++++++++++++++++------------- src/js/webrequest.js | 4 ++-- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index ca94ca1ecc..dd9710bd3b 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -801,38 +801,41 @@ Badger.prototype = { return; } - // TODO Add frame_id to executeScript calls - // TODO Add no-op function for executeScript + var executeScriptCallback = function() { + if (chrome.runtime.lastError) { + // Do nothing + } + }; // Insert all scripts // TODO Put this in a loop? chrome.tabs.executeScript(tab_id, { 'file': '/js/contentscripts/fingerprinting.js', - 'allFrames': true, + 'frameId': frame_id, 'runAt': 'document_start' - }); + }, executeScriptCallback); chrome.tabs.executeScript(tab_id, { 'file': '/js/contentscripts/clobbercookie.js', - 'allFrames': true, + 'frameId': frame_id, 'runAt': 'document_start' - }); + }, executeScriptCallback); chrome.tabs.executeScript(tab_id, { 'file': '/js/contentscripts/clobberlocalstorage.js', - 'allFrames': true, + 'frameId': frame_id, 'runAt': 'document_start' - }); + }, executeScriptCallback); chrome.tabs.executeScript(tab_id, { 'file': '/js/contentscripts/supercookie.js', - 'allFrames': true, + 'frameId': frame_id, 'runAt': 'document_idle' - }); + }, executeScriptCallback); if (this.isSocialWidgetReplacementEnabled()) { chrome.tabs.executeScript(tab_id, { - 'file': '/js/contentscripts/fingerprinting.js', - 'allFrames': true, + 'file': '/js/contentscripts/socialwidgets.js', + 'frameId': frame_id, 'runAt': 'document_start' - }); + }, executeScriptCallback); } }, diff --git a/src/js/webrequest.js b/src/js/webrequest.js index ad4111038a..2c18744251 100644 --- a/src/js/webrequest.js +++ b/src/js/webrequest.js @@ -63,15 +63,15 @@ function onBeforeRequest(details) { frame_id = 0; } - badger.recordFrame(tab_id, frame_id, details.parentFrameId, url); badger.insertContentScripts(tab_id, url, frame_id, is_internal); + badger.recordFrame(tab_id, frame_id, details.parentFrameId, url); return {}; } if (type == "sub_frame") { - badger.recordFrame(tab_id, frame_id, details.parentFrameId, url); badger.insertContentScripts(tab_id, url, frame_id, is_internal); + badger.recordFrame(tab_id, frame_id, details.parentFrameId, url); } // Block ping requests sent by navigator.sendBeacon (see, #587) From ddeada1a54097243dda54eaf701ce484611a3e66 Mon Sep 17 00:00:00 2001 From: Alex Ristich Date: Sat, 14 Apr 2018 12:12:40 -0700 Subject: [PATCH 13/13] Switch to onCommitted for content script injection --- src/js/background.js | 14 +++++++------- src/js/contentscripts/fingerprinting.js | 2 -- src/js/contentscripts/socialwidgets.js | 1 - src/js/webrequest.js | 13 +++++++++++-- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index dd9710bd3b..392f0924ce 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -801,9 +801,9 @@ Badger.prototype = { return; } - var executeScriptCallback = function() { + var noop = function() { if (chrome.runtime.lastError) { - // Do nothing + // // Do nothing } }; @@ -813,29 +813,29 @@ Badger.prototype = { 'file': '/js/contentscripts/fingerprinting.js', 'frameId': frame_id, 'runAt': 'document_start' - }, executeScriptCallback); + }, noop); chrome.tabs.executeScript(tab_id, { 'file': '/js/contentscripts/clobbercookie.js', 'frameId': frame_id, 'runAt': 'document_start' - }, executeScriptCallback); + }, noop); chrome.tabs.executeScript(tab_id, { 'file': '/js/contentscripts/clobberlocalstorage.js', 'frameId': frame_id, 'runAt': 'document_start' - }, executeScriptCallback); + }, noop); chrome.tabs.executeScript(tab_id, { 'file': '/js/contentscripts/supercookie.js', 'frameId': frame_id, 'runAt': 'document_idle' - }, executeScriptCallback); + }, noop); if (this.isSocialWidgetReplacementEnabled()) { chrome.tabs.executeScript(tab_id, { 'file': '/js/contentscripts/socialwidgets.js', 'frameId': frame_id, 'runAt': 'document_start' - }, executeScriptCallback); + }, noop); } }, diff --git a/src/js/contentscripts/fingerprinting.js b/src/js/contentscripts/fingerprinting.js index 95afec2358..7578949822 100644 --- a/src/js/contentscripts/fingerprinting.js +++ b/src/js/contentscripts/fingerprinting.js @@ -19,8 +19,6 @@ */ function getFpPageScript() { - - console.log('inserting fp script'); // code below is not a content script: no chrome.* APIs ///////////////////// // return a string diff --git a/src/js/contentscripts/socialwidgets.js b/src/js/contentscripts/socialwidgets.js index 311e6d1fda..803a556c32 100644 --- a/src/js/contentscripts/socialwidgets.js +++ b/src/js/contentscripts/socialwidgets.js @@ -55,7 +55,6 @@ let i18n = chrome.i18n; * Initializes the content script. */ function initialize() { - console.info('insert social widget script'); // Get tracker info and check for initial blocks (that happened // before content script was attached) getTrackerData(function (trackers, trackerButtonsToReplace) { diff --git a/src/js/webrequest.js b/src/js/webrequest.js index 2c18744251..426210fdd8 100644 --- a/src/js/webrequest.js +++ b/src/js/webrequest.js @@ -40,6 +40,16 @@ var temporarySocialWidgetUnblock = {}; /***************** Blocking Listener Functions **************/ +function injectScripts(details) { + var frame_id = details.frameId, + tab_id = details.tabId, + url = details.url; + + if (!_isTabChromeInternal(tab_id)) { + badger.insertContentScripts(tab_id, url, frame_id); + } +} + /** * Event handling of http requests, main logic to collect data what to block * @@ -63,14 +73,12 @@ function onBeforeRequest(details) { frame_id = 0; } - badger.insertContentScripts(tab_id, url, frame_id, is_internal); badger.recordFrame(tab_id, frame_id, details.parentFrameId, url); return {}; } if (type == "sub_frame") { - badger.insertContentScripts(tab_id, url, frame_id, is_internal); badger.recordFrame(tab_id, frame_id, details.parentFrameId, url); } @@ -708,6 +716,7 @@ function startListeners() { chrome.webRequest.onBeforeRequest.addListener(onBeforeRequest, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]); chrome.webRequest.onBeforeSendHeaders.addListener(onBeforeSendHeaders, {urls: ["http://*/*", "https://*/*"]}, ["requestHeaders", "blocking"]); chrome.webRequest.onHeadersReceived.addListener(onHeadersReceived, {urls: [""]}, ["responseHeaders", "blocking"]); + chrome.webNavigation.onCommitted.addListener(injectScripts); chrome.tabs.onRemoved.addListener(onTabRemoved); chrome.tabs.onReplaced.addListener(onTabReplaced); chrome.runtime.onMessage.addListener(dispatcher);