diff --git a/src/_locales/en_US/messages.json b/src/_locales/en_US/messages.json index 53fc47f061..fce290a0ec 100644 --- a/src/_locales/en_US/messages.json +++ b/src/_locales/en_US/messages.json @@ -417,6 +417,22 @@ "message": "user-controlled", "description": "Dropdown control setting on the Tracking Domains options page tab." }, + "popup_info_firstparty_protections": { + "message": "Link tracking protection active", + "description": "Clickable status header text in the popup. Shown when Privacy Badger's link tracking protection is active (for example, on facebook.com)." + }, + "popup_info_firstparty_description": { + "message": "Some websites $LINK_START$use link tracking to follow you$LINK_END$ whenever you click a link to leave the website. Privacy Badger removes tracking from such links on this website.", + "description": "Text revealed by clicking on the link tracking protection header in the popup", + "placeholders": { + "link_start": { + "content": "" + }, + "link_end": { + "content": "" + } + } + }, "popup_instructions": { "message": "$COUNT$ potential $LINK_START$trackers$LINK_END$ blocked", "description": "Popup message shown when at least one tracker was blocked.", diff --git a/src/js/background.js b/src/js/background.js index fcb48c653b..026a229d0c 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -815,6 +815,7 @@ Badger.prototype = { seenComic: false, sendDNTSignal: true, showCounter: true, + showExpandedTrackingSection: false, showIntroPage: true, showNonTrackingDomains: false, showTrackingDomains: false, diff --git a/src/js/popup.js b/src/js/popup.js index 4add6a2112..06ee978690 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -127,7 +127,7 @@ function showNagMaybe() { if (POPUP_DATA.showLearningPrompt) { _showLearningPrompt(); - } else if (!POPUP_DATA.seenComic) { + } else if (!POPUP_DATA.settings.seenComic) { chrome.tabs.query({active: true, currentWindow: true}, function (focusedTab) { // Show the popup instruction if the active tab is not firstRun.html page if (!focusedTab[0].url.startsWith(intro_page_url)) { @@ -194,6 +194,43 @@ function init() { chrome.i18n.getMessage("version", chrome.runtime.getManifest().version) ); + // add event listeners for click-to-expand blocked resources popup section + $('#tracker-list-header').on('click', toggleBlockedResourcesHandler); + + // add event listeners for click-to-expand first party protections popup section + $('#firstparty-protections-header').on('click', toggleFirstPartyInfoHandler); + + // show sliders when sliders were shown last + // or when there is at least one breakage warning + if (POPUP_DATA.settings.showExpandedTrackingSection || ( + POPUP_DATA.cookieblocked && Object.keys(POPUP_DATA.cookieblocked).some( + d => POPUP_DATA.origins[d] == constants.USER_BLOCK) + )) { + $('#expand-blocked-resources').hide(); + $('#collapse-blocked-resources').show(); + $('#blockedResources').show(); + + } else { + $('#expand-blocked-resources').show(); + $('#collapse-blocked-resources').hide(); + // show sliders regardless when the button + // that lets you toggle slider visibility + // isn't shown for whatever reason + // (for ex.: "no trackers blocked" but we need to show + // one or more "don't appear to be tracking you" sliders) + if (!$('#tracker-list-header').is(':visible')) { + $('#blockedResources').show(); + } else { + $('#blockedResources').hide(); + } + } + + // show firstparty protections message if current tab is in our content scripts + if (POPUP_DATA.enabled && POPUP_DATA.isOnFirstParty) { + $("#firstparty-protections-container").show(); + $('#expand-firstparty-popup').show(); + } + // improve on Firefox's built-in options opening logic if (typeof browser == "object" && typeof browser.runtime.getBrowserInfo == "function") { browser.runtime.getBrowserInfo().then(function (info) { @@ -436,6 +473,48 @@ function share() { $("#share_output").val(share_msg); } +/** + * Click handlers for showing/hiding the blocked resources section + */ +function toggleBlockedResourcesHandler(e) { + if (e.target.nodeName.toLowerCase() == 'a') { + // don't toggle contents when clicking links in the header + return; + } + if ($("#expand-blocked-resources").is(":visible")) { + $("#collapse-blocked-resources").show(); + $("#expand-blocked-resources").hide(); + $("#blockedResources").slideDown(); + chrome.runtime.sendMessage({ + type: "updateSettings", + data: { showExpandedTrackingSection: true } + }); + } else { + $("#collapse-blocked-resources").hide(); + $("#expand-blocked-resources").show(); + $("#blockedResources").slideUp(); + chrome.runtime.sendMessage({ + type: "updateSettings", + data: { showExpandedTrackingSection: false } + }); + } +} + +/** + * Click handler for showing/hiding the firstparty popup info text + */ +function toggleFirstPartyInfoHandler() { + if ($('#collapse-firstparty-popup').is(":visible")) { + $("#collapse-firstparty-popup").hide(); + $("#expand-firstparty-popup").show(); + $("#instructions-firstparty-description").slideUp(); + } else { + $("#collapse-firstparty-popup").show(); + $("#expand-firstparty-popup").hide(); + $("#instructions-firstparty-description").slideDown(); + } +} + /** * Handler to undo user selection for a tracker */ @@ -507,14 +586,10 @@ function refreshPopup() { } if (!originsArr.length) { - // hide the number of trackers and slider instructions message - // if no sliders will be displayed - $("#instructions-many-trackers").hide(); - // show "no trackers" message $("#instructions-no-trackers").show(); - if (POPUP_DATA.learnLocally && POPUP_DATA.showNonTrackingDomains) { + if (POPUP_DATA.settings.learnLocally && POPUP_DATA.settings.showNonTrackingDomains) { // show the "no third party resources on this site" message $("#no-third-parties").show(); } @@ -527,7 +602,8 @@ function refreshPopup() { return; } - let printable = []; + let printable = [], + printableWarningSliders = []; let unblockedTrackers = []; let nonTracking = []; originsArr = htmlUtils.sortDomains(originsArr); @@ -544,13 +620,19 @@ function refreshPopup() { action == constants.USER_BLOCK && POPUP_DATA.cookieblocked.hasOwnProperty(origin) ); - printable.push( - htmlUtils.getOriginHtml(origin, action, show_breakage_warning) - ); + let slider_html = htmlUtils.getOriginHtml(origin, action, show_breakage_warning); + if (show_breakage_warning) { + printableWarningSliders.push(slider_html); + } else { + printable.push(slider_html); + } } } - if (POPUP_DATA.learnLocally && unblockedTrackers.length) { + // show breakage warning sliders at the top of the list + printable = printableWarningSliders.concat(printable); + + if (POPUP_DATA.settings.learnLocally && unblockedTrackers.length) { printable.push( '
+ +
-

- -

+ + +
diff --git a/src/tests/tests/utils.js b/src/tests/tests/utils.js index 26c1882542..039bc6675e 100644 --- a/src/tests/tests/utils.js +++ b/src/tests/tests/utils.js @@ -571,4 +571,41 @@ QUnit.test("estimateMaxEntropy", assert => { }); +QUnit.test("firstPartyProtectionsEnabled", assert => { + assert.ok( + utils.firstPartyProtectionsEnabled("www.google.com"), + "properly identifies a url pattern from our firstparties list" + ); + + assert.ok( + utils.firstPartyProtectionsEnabled("www.google.co.uk"), + "properly identifies a url pattern from our firstparties list" + ); + + assert.notOk( + utils.firstPartyProtectionsEnabled("foobar.com"), + "determines that a url not in the firstparties list is not protected by a firstparty script" + ); + + assert.ok( + utils.firstPartyProtectionsEnabled("www.messenger.com"), + "accurately IDs a site with firstparty protections covered by a wildcard url match" + ); + + assert.ok( + utils.firstPartyProtectionsEnabled("www.facebook.com"), + "wildcard pattern matching" + ); + + assert.ok( + utils.firstPartyProtectionsEnabled("m.facebook.com"), + "wildcard pattern matching" + ); + + assert.notOk( + utils.firstPartyProtectionsEnabled("acebook.com"), + "wildcard pattern matching" + ); +}); + })(); diff --git a/tests/selenium/popup_test.py b/tests/selenium/popup_test.py index e2f1c56c41..1e13f4af5d 100644 --- a/tests/selenium/popup_test.py +++ b/tests/selenium/popup_test.py @@ -62,7 +62,7 @@ def open_popup(self, show_nag=False, origins=None): " type: 'getPopupData'," " tabId: tabs[0].id" " }, (response) => {" - " response.seenComic = !show_nag;" + " response.settings.seenComic = !show_nag;" " response.origins = origins;" " setPopupData(response);" " refreshPopup();" @@ -137,7 +137,7 @@ def test_trackers_link(self): self.open_popup() - # Get all possible tracker links (none, one, multiple) + # Get all possible tracker links ("no" and "multiple" messages) trackers_links = self.driver.find_elements_by_css_selector("#pbInstructions a") if not trackers_links: self.fail("Unable to find trackers link on popup")