diff --git a/browser/base/content/test/protectionsUI/browser.ini b/browser/base/content/test/protectionsUI/browser.ini index a73ec7b50fc75c487fa0e88176a1f8cb4fcbd4be..cda174e45a37c1df28785f2cbe01073f2eb025cd 100644 --- a/browser/base/content/test/protectionsUI/browser.ini +++ b/browser/base/content/test/protectionsUI/browser.ini @@ -40,3 +40,4 @@ support-files = [browser_protectionsUI_state_reset.js] [browser_protectionsUI_telemetry.js] [browser_protectionsUI_trackers_subview.js] +[browser_protectionsUI_subview_shim.js] diff --git a/browser/base/content/test/protectionsUI/browser_protectionsUI.js b/browser/base/content/test/protectionsUI/browser_protectionsUI.js index 265b1bce7837bc1ddc544e353a3e9298df70014d..7e347ecb1dfe0d93a3e11fd40a4b3eb4400f7a83 100644 --- a/browser/base/content/test/protectionsUI/browser_protectionsUI.js +++ b/browser/base/content/test/protectionsUI/browser_protectionsUI.js @@ -617,7 +617,7 @@ add_task(async function testNumberOfBlockedTrackers() { add_task(async function testSubViewTelemetry() { let items = [ - ["protections-popup-category-tracking-protection", "trackers"], + ["protections-popup-category-trackers", "trackers"], ["protections-popup-category-socialblock", "social"], ["protections-popup-category-cookies", "cookies"], ["protections-popup-category-cryptominers", "cryptominers"], diff --git a/browser/base/content/test/protectionsUI/browser_protectionsUI_3.js b/browser/base/content/test/protectionsUI/browser_protectionsUI_3.js index 7621a0c6bec0796014e58b2916894668df4a5347..1a747e054b38997825cd7a4473de5e39d105e258 100644 --- a/browser/base/content/test/protectionsUI/browser_protectionsUI_3.js +++ b/browser/base/content/test/protectionsUI/browser_protectionsUI_3.js @@ -15,8 +15,13 @@ registerCleanupFunction(function() { }); add_task(async function testNormalBrowsing() { - let TrackingProtection = gBrowser.ownerGlobal.TrackingProtection; - ok(TrackingProtection, "TP is attached to the browser window"); + let { + TrackingProtection, + } = gBrowser.ownerGlobal.gProtectionsHandler.blockers; + ok( + TrackingProtection, + "Normal window gProtectionsHandler should have TrackingProtection blocker." + ); Services.prefs.setBoolPref(PREF, true); Services.prefs.setBoolPref(PB_PREF, false); @@ -35,8 +40,13 @@ add_task(async function testPrivateBrowsing() { let privateWin = await BrowserTestUtils.openNewBrowserWindow({ private: true, }); - let TrackingProtection = privateWin.gBrowser.ownerGlobal.TrackingProtection; - ok(TrackingProtection, "TP is attached to the browser window"); + let { + TrackingProtection, + } = privateWin.gBrowser.ownerGlobal.gProtectionsHandler.blockers; + ok( + TrackingProtection, + "Private window gProtectionsHandler should have TrackingProtection blocker." + ); Services.prefs.setBoolPref(PREF, true); Services.prefs.setBoolPref(PB_PREF, false); diff --git a/browser/base/content/test/protectionsUI/browser_protectionsUI_animation_2.js b/browser/base/content/test/protectionsUI/browser_protectionsUI_animation_2.js index 517655fcc9580266f5656aabba778fbab3a0cef1..876cba897a441d6d946b5f920823c4f53eb338c0 100644 --- a/browser/base/content/test/protectionsUI/browser_protectionsUI_animation_2.js +++ b/browser/base/content/test/protectionsUI/browser_protectionsUI_animation_2.js @@ -212,9 +212,13 @@ add_task(async function testNormalBrowsing() { gProtectionsHandler, "gProtectionsHandler is attached to the browser window" ); - let TrackingProtection = gBrowser.ownerGlobal.TrackingProtection; + + let { + TrackingProtection, + } = gBrowser.ownerGlobal.gProtectionsHandler.blockers; ok(TrackingProtection, "TP is attached to the browser window"); - let ThirdPartyCookies = gBrowser.ownerGlobal.ThirdPartyCookies; + + let { ThirdPartyCookies } = gBrowser.ownerGlobal.gProtectionsHandler.blockers; ok(ThirdPartyCookies, "TPC is attached to the browser window"); Services.prefs.setBoolPref(TP_PREF, true); @@ -242,9 +246,13 @@ add_task(async function testPrivateBrowsing() { gProtectionsHandler, "gProtectionsHandler is attached to the private window" ); - let TrackingProtection = tabbrowser.ownerGlobal.TrackingProtection; + let { + TrackingProtection, + } = tabbrowser.ownerGlobal.gProtectionsHandler.blockers; ok(TrackingProtection, "TP is attached to the private window"); - let ThirdPartyCookies = tabbrowser.ownerGlobal.ThirdPartyCookies; + let { + ThirdPartyCookies, + } = tabbrowser.ownerGlobal.gProtectionsHandler.blockers; ok(ThirdPartyCookies, "TPC is attached to the browser window"); Services.prefs.setBoolPref(TP_PB_PREF, true); diff --git a/browser/base/content/test/protectionsUI/browser_protectionsUI_categories.js b/browser/base/content/test/protectionsUI/browser_protectionsUI_categories.js index a2b7c3716ead178c44c06d3ddb823e10822a886c..f8a327c9e175473f235231ac313761d18b922e44 100644 --- a/browser/base/content/test/protectionsUI/browser_protectionsUI_categories.js +++ b/browser/base/content/test/protectionsUI/browser_protectionsUI_categories.js @@ -182,7 +182,7 @@ add_task(async function testCategorySections() { await closeProtectionsPanel(); let categoryItems = [ - "protections-popup-category-tracking-protection", + "protections-popup-category-trackers", "protections-popup-category-socialblock", "protections-popup-category-cookies", "protections-popup-category-cryptominers", @@ -234,7 +234,7 @@ add_task(async function testCategorySections() { */ add_task(async function testCategorySectionInitial() { let categoryItems = [ - "protections-popup-category-tracking-protection", + "protections-popup-category-trackers", "protections-popup-category-socialblock", "protections-popup-category-cookies", "protections-popup-category-cryptominers", diff --git a/browser/base/content/test/protectionsUI/browser_protectionsUI_cryptominers.js b/browser/base/content/test/protectionsUI/browser_protectionsUI_cryptominers.js index 0ab558a0505d7800ce12fff7bb9921da78b98003..8be2103071aec97db7ab36a65e819443e6083658 100644 --- a/browser/base/content/test/protectionsUI/browser_protectionsUI_cryptominers.js +++ b/browser/base/content/test/protectionsUI/browser_protectionsUI_cryptominers.js @@ -153,6 +153,11 @@ async function testSubview(hasException) { categoryItem.click(); await viewShown; + let trackersViewShimHint = document.getElementById( + "protections-popup-cryptominersView-shim-allow-hint" + ); + ok(trackersViewShimHint.hidden, "Shim hint is hidden"); + let listItems = subview.querySelectorAll(".protections-popup-list-item"); is(listItems.length, 1, "We have 1 item in the list"); let listItem = listItems[0]; diff --git a/browser/base/content/test/protectionsUI/browser_protectionsUI_fingerprinters.js b/browser/base/content/test/protectionsUI/browser_protectionsUI_fingerprinters.js index accf84ccd564d328fea7c084eadaaa14a5cb80a4..441b465853dad4b121956542f5788e353c0ec99f 100644 --- a/browser/base/content/test/protectionsUI/browser_protectionsUI_fingerprinters.js +++ b/browser/base/content/test/protectionsUI/browser_protectionsUI_fingerprinters.js @@ -228,6 +228,11 @@ async function testSubview(hasException) { categoryItem.click(); await viewShown; + let trackersViewShimHint = document.getElementById( + "protections-popup-fingerprintersView-shim-allow-hint" + ); + ok(trackersViewShimHint.hidden, "Shim hint is hidden"); + let listItems = subview.querySelectorAll(".protections-popup-list-item"); is(listItems.length, 1, "We have 1 item in the list"); let listItem = listItems[0]; diff --git a/browser/base/content/test/protectionsUI/browser_protectionsUI_open_preferences.js b/browser/base/content/test/protectionsUI/browser_protectionsUI_open_preferences.js index 992d5538b9ad640b50bd50e9fd840afe6b29bba6..0cad0975690924f42d641603f7291fa26e542c50 100644 --- a/browser/base/content/test/protectionsUI/browser_protectionsUI_open_preferences.js +++ b/browser/base/content/test/protectionsUI/browser_protectionsUI_open_preferences.js @@ -67,7 +67,7 @@ add_task(async function testOpenPreferencesFromTrackersSubview() { await openProtectionsPanel(); let categoryItem = document.getElementById( - "protections-popup-category-tracking-protection" + "protections-popup-category-trackers" ); // Explicitly waiting for the category item becoming visible. diff --git a/browser/base/content/test/protectionsUI/browser_protectionsUI_pbmode_exceptions.js b/browser/base/content/test/protectionsUI/browser_protectionsUI_pbmode_exceptions.js index e3191a0f80656a7a36cbb9906701078d2c8694ec..53db3236bb4d8fae2993fa91b0153622248fea0c 100644 --- a/browser/base/content/test/protectionsUI/browser_protectionsUI_pbmode_exceptions.js +++ b/browser/base/content/test/protectionsUI/browser_protectionsUI_pbmode_exceptions.js @@ -91,7 +91,9 @@ add_task(async function testExceptionAddition() { gProtectionsHandler = browser.ownerGlobal.gProtectionsHandler; ok(gProtectionsHandler, "CB is attached to the private window"); - TrackingProtection = browser.ownerGlobal.TrackingProtection; + + TrackingProtection = + browser.ownerGlobal.gProtectionsHandler.blockers.TrackingProtection; ok(TrackingProtection, "TP is attached to the private window"); Services.prefs.setBoolPref(TP_PB_PREF, true); @@ -135,7 +137,8 @@ add_task(async function testExceptionPersistence() { gProtectionsHandler = browser.ownerGlobal.gProtectionsHandler; ok(gProtectionsHandler, "CB is attached to the private window"); - TrackingProtection = browser.ownerGlobal.TrackingProtection; + TrackingProtection = + browser.ownerGlobal.gProtectionsHandler.blockers.TrackingProtection; ok(TrackingProtection, "TP is attached to the private window"); ok(TrackingProtection.enabled, "TP is still enabled"); diff --git a/browser/base/content/test/protectionsUI/browser_protectionsUI_socialtracking.js b/browser/base/content/test/protectionsUI/browser_protectionsUI_socialtracking.js index 65580ac0cb38ea7915cc31796314599fcef6d2aa..93a4b0dfc0e0a3992a47e5d7b31791f1b8de579b 100644 --- a/browser/base/content/test/protectionsUI/browser_protectionsUI_socialtracking.js +++ b/browser/base/content/test/protectionsUI/browser_protectionsUI_socialtracking.js @@ -159,6 +159,11 @@ async function testSubview(hasException) { categoryItem.click(); await viewShown; + let trackersViewShimHint = document.getElementById( + "protections-popup-socialblockView-shim-allow-hint" + ); + ok(trackersViewShimHint.hidden, "Shim hint is hidden"); + let listItems = subview.querySelectorAll(".protections-popup-list-item"); is(listItems.length, 1, "We have 1 item in the list"); let listItem = listItems[0]; diff --git a/browser/base/content/test/protectionsUI/browser_protectionsUI_state.js b/browser/base/content/test/protectionsUI/browser_protectionsUI_state.js index d6a96e9c9e4bf7dbb6fd123b015ad16d6ef37707..123f61df6dd9f485787188ddd8124451aa804caf 100644 --- a/browser/base/content/test/protectionsUI/browser_protectionsUI_state.js +++ b/browser/base/content/test/protectionsUI/browser_protectionsUI_state.js @@ -88,7 +88,7 @@ async function testBenignPage() { "Cookie restrictions category is not found" ); ok( - notFound("protections-popup-category-tracking-protection"), + notFound("protections-popup-category-trackers"), "Trackers category is not found" ); await closeProtectionsPanel(win); @@ -125,7 +125,7 @@ async function testBenignPageWithException() { "Cookie restrictions category is not found" ); ok( - notFound("protections-popup-category-tracking-protection"), + notFound("protections-popup-category-trackers"), "Trackers category is not found" ); await closeProtectionsPanel(win); @@ -170,7 +170,7 @@ async function testTrackingPage(window) { await openProtectionsPanel(false, window); ok( - !notFound("protections-popup-category-tracking-protection"), + !notFound("protections-popup-category-trackers"), "Trackers category is detected" ); if (gTrackingPageURL == COOKIE_PAGE) { @@ -213,7 +213,7 @@ async function testTrackingPageUnblocked(blockedByTP, window) { await openProtectionsPanel(false, window); ok( - !notFound("protections-popup-category-tracking-protection"), + !notFound("protections-popup-category-trackers"), "Trackers category is detected" ); if (gTrackingPageURL == COOKIE_PAGE) { @@ -284,7 +284,9 @@ add_task(async function testNormalBrowsing() { gProtectionsHandler, "gProtectionsHandler is attached to the browser window" ); - TrackingProtection = gBrowser.ownerGlobal.TrackingProtection; + + TrackingProtection = + gBrowser.ownerGlobal.gProtectionsHandler.blockers.TrackingProtection; ok(TrackingProtection, "TP is attached to the browser window"); is( TrackingProtection.enabled, @@ -323,7 +325,9 @@ add_task(async function testPrivateBrowsing() { gProtectionsHandler, "gProtectionsHandler is attached to the private window" ); - TrackingProtection = tabbrowser.ownerGlobal.TrackingProtection; + + TrackingProtection = + tabbrowser.ownerGlobal.gProtectionsHandler.blockers.TrackingProtection; ok(TrackingProtection, "TP is attached to the private window"); is( TrackingProtection.enabled, @@ -355,7 +359,8 @@ add_task(async function testThirdPartyCookies() { gProtectionsHandler, "gProtectionsHandler is attached to the browser window" ); - ThirdPartyCookies = gBrowser.ownerGlobal.ThirdPartyCookies; + ThirdPartyCookies = + gBrowser.ownerGlobal.gProtectionsHandler.blockers.ThirdPartyCookies; ok(ThirdPartyCookies, "TP is attached to the browser window"); is( ThirdPartyCookies.enabled, diff --git a/browser/base/content/test/protectionsUI/browser_protectionsUI_subview_shim.js b/browser/base/content/test/protectionsUI/browser_protectionsUI_subview_shim.js new file mode 100644 index 0000000000000000000000000000000000000000..736b008253227ded04e632d0589d46bdf9a05c5b --- /dev/null +++ b/browser/base/content/test/protectionsUI/browser_protectionsUI_subview_shim.js @@ -0,0 +1,399 @@ +/* eslint-disable mozilla/no-arbitrary-setTimeout */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests the warning and list indicators that are shown in the protections panel + * subview when a tracking channel is allowed via the + * "urlclassifier-before-block-channel" event. + */ + +// Choose origin so that all tracking origins used are third-parties. +const TRACKING_PAGE = + "http://example.net/browser/browser/base/content/test/protectionsUI/trackingPage.html"; + +add_task(async function setup() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.trackingprotection.enabled", true], + ["privacy.trackingprotection.annotate_channels", true], + ["privacy.trackingprotection.cryptomining.enabled", true], + ["privacy.trackingprotection.socialtracking.enabled", true], + ["privacy.trackingprotection.fingerprinting.enabled", true], + ["privacy.socialtracking.block_cookies.enabled", true], + // Allowlist trackertest.org loaded by default in trackingPage.html + ["urlclassifier.trackingSkipURLs", "trackertest.org"], + ["urlclassifier.trackingAnnotationSkipURLs", "trackertest.org"], + // Additional denylisted hosts. + [ + "urlclassifier.trackingAnnotationTable.testEntries", + "tracking.example.com", + ], + [ + "urlclassifier.features.cryptomining.blacklistHosts", + "cryptomining.example.com", + ], + [ + "urlclassifier.features.cryptomining.annotate.blacklistHosts", + "cryptomining.example.com", + ], + [ + "urlclassifier.features.fingerprinting.blacklistHosts", + "fingerprinting.example.com", + ], + [ + "urlclassifier.features.fingerprinting.annotate.blacklistHosts", + "fingerprinting.example.com", + ], + ], + }); + + await UrlClassifierTestUtils.addTestTrackers(); + registerCleanupFunction(() => { + UrlClassifierTestUtils.cleanupTestTrackers(); + }); +}); + +async function assertSubViewState(category, expectedState) { + await openProtectionsPanel(); + + // Sort the expected state by origin and transform it into an array. + let expectedStateSorted = Object.keys(expectedState) + .sort() + .reduce((stateArr, key) => { + let obj = expectedState[key]; + obj.origin = key; + stateArr.push(obj); + return stateArr; + }, []); + + if (!expectedStateSorted.length) { + ok( + BrowserTestUtils.is_visible( + document.getElementById( + "protections-popup-no-trackers-found-description" + ) + ), + "No Trackers detected should be shown" + ); + return; + } + + let categoryItem = document.getElementById( + `protections-popup-category-${category}` + ); + + // Explicitly waiting for the category item becoming visible. + await TestUtils.waitForCondition(() => { + return BrowserTestUtils.is_visible(categoryItem); + }); + + ok( + BrowserTestUtils.is_visible(categoryItem), + `${category} category item is visible` + ); + + ok(!categoryItem.disabled, `${category} category item is enabled`); + + let subView = document.getElementById(`protections-popup-${category}View`); + let viewShown = BrowserTestUtils.waitForEvent(subView, "ViewShown"); + categoryItem.click(); + await viewShown; + + ok(true, `${category} subView was shown`); + + info("Testing tracker list"); + + // Get the listed trackers in the UI and sort them by origin. + let items = Array.from( + subView.querySelectorAll( + `#protections-popup-${category}View-list .protections-popup-list-item` + ) + ).sort((a, b) => { + let originA = a.querySelector("label").value; + let originB = b.querySelector("label").value; + return originA.localeCompare(originB); + }); + + is( + items.length, + expectedStateSorted.length, + "List has expected amount of entries" + ); + + for (let i = 0; i < expectedStateSorted.length; i += 1) { + let expected = expectedStateSorted[i]; + let item = items[i]; + + let label = item.querySelector(".protections-popup-list-host-label"); + ok(label, "Item has label."); + is(label.tooltipText, expected.origin, "Label has correct tooltip."); + is(label.value, expected.origin, "Label has correct text."); + + is( + item.classList.contains("allowed"), + !expected.block, + "Item has allowed class if tracker is not blocked" + ); + + let shimAllowIndicator = item.querySelector( + ".protections-popup-list-host-shim-allow-indicator" + ); + + if (expected.shimAllow) { + is(item.childNodes.length, 2, "Item has two childNodes."); + ok(shimAllowIndicator, "Item has shim allow indicator icon."); + ok( + shimAllowIndicator.tooltipText, + "Shim allow indicator icon has tooltip text" + ); + } else { + is(item.childNodes.length, 1, "Item has one childNode."); + ok(!shimAllowIndicator, "Item does not have shim allow indicator icon."); + } + } + + let shimAllowSection = document.getElementById( + `protections-popup-${category}View-shim-allow-hint` + ); + ok(shimAllowSection, `Category ${category} has shim-allow hint.`); + + if (Object.values(expectedState).some(entry => entry.shimAllow)) { + BrowserTestUtils.is_visible( + shimAllowSection, + "Shim allow hint is visible." + ); + } else { + BrowserTestUtils.is_hidden(shimAllowSection, "Shim allow hint is hidden."); + } + + await closeProtectionsPanel(); +} + +async function runTestForCategoryAndState(category, action) { + // Maps the protection categories to the test tracking origins defined in + // ./trackingAPI.js and the UI class identifiers to look for in the + // protections UI. + let categoryToTestData = { + tracking: { + apiMessage: "more-tracking", + origin: "https://itisatracker.org", + elementId: "trackers", + }, + socialtracking: { + origin: "https://social-tracking.example.org", + elementId: "socialblock", + }, + cryptomining: { + origin: "http://cryptomining.example.com", + elementId: "cryptominers", + }, + fingerprinting: { + origin: "https://fingerprinting.example.com", + elementId: "fingerprinters", + }, + }; + + let promise = BrowserTestUtils.openNewForegroundTab({ + url: TRACKING_PAGE, + gBrowser, + }); + // Wait for the tab to load and the initial blocking events from the + // classifier. + let [tab] = await Promise.all([promise, waitForContentBlockingEvent()]); + + let { + origin: trackingOrigin, + elementId: categoryElementId, + apiMessage, + } = categoryToTestData[category]; + if (!apiMessage) { + apiMessage = category; + } + + // For allow or replace actions we need to hook into before-block-channel. + // If we don't hook into the event, the tracking channel will be blocked. + let beforeBlockChannelPromise; + if (action != "block") { + beforeBlockChannelPromise = UrlClassifierTestUtils.handleBeforeBlockChannel( + { + filterOrigin: trackingOrigin, + action, + } + ); + } + // Load the test tracker matching the category. + await SpecialPowers.spawn(tab.linkedBrowser, [{ apiMessage }], function( + args + ) { + content.postMessage(args.apiMessage, "*"); + }); + await beforeBlockChannelPromise; + + // Next, test if the UI state is correct for the given category and action. + let expectedState = {}; + expectedState[trackingOrigin] = { + block: action == "block", + shimAllow: action == "allow", + }; + + await assertSubViewState(categoryElementId, expectedState); + + BrowserTestUtils.removeTab(tab); +} + +/** + * Test mixed allow/block/replace states for the tracking protection category. + * @param {Object} options - States to test. + * @param {boolean} options.block - Test tracker block state. + * @param {boolean} options.allow - Test tracker allow state. + * @param {boolean} options.replace - Test tracker replace state. + */ +async function runTestMixed({ block, allow, replace }) { + const ORIGIN_BLOCK = "https://trackertest.org"; + const ORIGIN_ALLOW = "https://itisatracker.org"; + const ORIGIN_REPLACE = "https://tracking.example.com"; + + let promise = BrowserTestUtils.openNewForegroundTab({ + url: TRACKING_PAGE, + gBrowser, + }); + + let [tab] = await Promise.all([promise, waitForContentBlockingEvent()]); + + if (block) { + // Temporarily remove trackertest.org from the allowlist. + await SpecialPowers.pushPrefEnv({ + clear: [ + ["urlclassifier.trackingSkipURLs"], + ["urlclassifier.trackingAnnotationSkipURLs"], + ], + }); + let blockEventPromise = waitForContentBlockingEvent(); + await SpecialPowers.spawn(tab.linkedBrowser, [], function() { + content.postMessage("tracking", "*"); + }); + await blockEventPromise; + await SpecialPowers.popPrefEnv(); + } + + if (allow) { + let promiseEvent = waitForContentBlockingEvent(); + let promiseAllow = UrlClassifierTestUtils.handleBeforeBlockChannel({ + filterOrigin: ORIGIN_ALLOW, + action: "allow", + }); + + await SpecialPowers.spawn(tab.linkedBrowser, [], function() { + content.postMessage("more-tracking", "*"); + }); + + await promiseAllow; + await promiseEvent; + } + + if (replace) { + let promiseReplace = UrlClassifierTestUtils.handleBeforeBlockChannel({ + filterOrigin: ORIGIN_REPLACE, + action: "replace", + }); + + await SpecialPowers.spawn(tab.linkedBrowser, [], function() { + content.postMessage("more-tracking-2", "*"); + }); + + await promiseReplace; + } + + let expectedState = {}; + + if (block) { + expectedState[ORIGIN_BLOCK] = { + shimAllow: false, + block: true, + }; + } + + if (replace) { + expectedState[ORIGIN_REPLACE] = { + shimAllow: false, + block: false, + }; + } + + if (allow) { + expectedState[ORIGIN_ALLOW] = { + shimAllow: true, + block: false, + }; + } + + // Check the protection categories subview with the block list. + await assertSubViewState("trackers", expectedState); + + BrowserTestUtils.removeTab(tab); +} + +add_task(async function testNoShim() { + await runTestMixed({ + allow: false, + replace: false, + block: false, + }); + await runTestMixed({ + allow: false, + replace: false, + block: true, + }); +}); + +add_task(async function testShimAllow() { + await runTestMixed({ + allow: true, + replace: false, + block: false, + }); + await runTestMixed({ + allow: true, + replace: false, + block: true, + }); +}); + +add_task(async function testShimReplace() { + await runTestMixed({ + allow: false, + replace: true, + block: false, + }); + await runTestMixed({ + allow: false, + replace: true, + block: true, + }); +}); + +add_task(async function testShimMixed() { + await runTestMixed({ + allow: true, + replace: true, + block: true, + }); +}); + +add_task(async function testShimCategorySubviews() { + let categories = [ + "tracking", + "socialtracking", + "cryptomining", + "fingerprinting", + ]; + for (let category of categories) { + for (let action of ["block", "allow", "replace"]) { + info(`Test category subview. category: ${category}, action: ${action}`); + await runTestForCategoryAndState(category, action); + } + } +}); diff --git a/browser/base/content/test/protectionsUI/browser_protectionsUI_telemetry.js b/browser/base/content/test/protectionsUI/browser_protectionsUI_telemetry.js index e7e85d1fbf11e3ed61a4de7e0187c420a0260a43..70cc24b7fd16e5d2f4d44fd764eb8683b4576110 100644 --- a/browser/base/content/test/protectionsUI/browser_protectionsUI_telemetry.js +++ b/browser/base/content/test/protectionsUI/browser_protectionsUI_telemetry.js @@ -33,7 +33,8 @@ add_task(async function setup() { await UrlClassifierTestUtils.addTestTrackers(); Services.prefs.setBoolPref(DTSCBN_PREF, true); - let TrackingProtection = gBrowser.ownerGlobal.TrackingProtection; + let TrackingProtection = + gBrowser.ownerGlobal.gProtectionsHandler.blockers.TrackingProtection; ok(TrackingProtection, "TP is attached to the browser window"); ok(!TrackingProtection.enabled, "TP is not enabled"); diff --git a/browser/base/content/test/protectionsUI/browser_protectionsUI_trackers_subview.js b/browser/base/content/test/protectionsUI/browser_protectionsUI_trackers_subview.js index a229b4a1ecafa7a415a803df3e0063164049ffde..3dea57cb75fd3b21779bdf94ed257ca9fdee0296 100644 --- a/browser/base/content/test/protectionsUI/browser_protectionsUI_trackers_subview.js +++ b/browser/base/content/test/protectionsUI/browser_protectionsUI_trackers_subview.js @@ -33,7 +33,7 @@ async function assertSitesListed(blocked) { await openProtectionsPanel(); let categoryItem = document.getElementById( - "protections-popup-category-tracking-protection" + "protections-popup-category-trackers" ); // Explicitly waiting for the category item becoming visible. @@ -49,6 +49,10 @@ async function assertSitesListed(blocked) { ok(true, "Trackers view was shown"); + let trackersViewShimHint = document.getElementById( + "protections-popup-trackersView-shim-allow-hint" + ); + ok(trackersViewShimHint.hidden, "Shim hint is hidden"); let listItems = trackersView.querySelectorAll(".protections-popup-list-item"); is(listItems.length, 1, "We have 1 tracker in the list"); diff --git a/browser/base/content/test/protectionsUI/trackingAPI.js b/browser/base/content/test/protectionsUI/trackingAPI.js index cc15eacf5620ca147053619609ac1d97fdf73533..b515358a3281b27423f633c040ac98f1e8b948d4 100644 --- a/browser/base/content/test/protectionsUI/trackingAPI.js +++ b/browser/base/content/test/protectionsUI/trackingAPI.js @@ -32,6 +32,9 @@ onmessage = event => { case "more-tracking": createIframe("https://itisatracker.org/"); break; + case "more-tracking-2": + createIframe("https://tracking.example.com/"); + break; case "cookie": createIframe( "https://trackertest.org/browser/browser/base/content/test/protectionsUI/cookieServer.sjs" diff --git a/browser/extensions/webcompat/tests/browser/head.js b/browser/extensions/webcompat/tests/browser/head.js index 7bd1dde9504b143904f845c5f40ad1711d968eb2..9935d3747154efa76a4b742a03fdfdef56b391e0 100644 --- a/browser/extensions/webcompat/tests/browser/head.js +++ b/browser/extensions/webcompat/tests/browser/head.js @@ -41,7 +41,8 @@ async function testShimRuns( waitForLoad: true, }); - const TrackingProtection = tab.ownerGlobal.TrackingProtection; + const TrackingProtection = + tab.ownerGlobal.gProtectionsHandler.blockers.TrackingProtection; ok(TrackingProtection, "TP is attached to the tab"); ok(TrackingProtection.enabled, "TP is enabled"); diff --git a/toolkit/components/url-classifier/tests/UrlClassifierTestUtils.jsm b/toolkit/components/url-classifier/tests/UrlClassifierTestUtils.jsm index 400582d1d74f3775eb0b98b93588d351a6cdeca8..e82719927634745af82fed43084cd91249378575 100644 --- a/toolkit/components/url-classifier/tests/UrlClassifierTestUtils.jsm +++ b/toolkit/components/url-classifier/tests/UrlClassifierTestUtils.jsm @@ -233,4 +233,62 @@ var UrlClassifierTestUtils = { } }); }, + + /** + * Handle the next "urlclassifier-before-block-channel" event. + * @param {Object} options + * @param {String} [options.filterOrigin] - Only handle event for channels + * with matching origin. + * @param {function} [options.onBeforeBlockChannel] - Optional callback for + * the event. Called before acting on the channel. + * @param {("allow"|"replace")} [options.action] - Whether to allow or replace + * the channel. + * @returns {Promise} - Resolves once event has been handled. + */ + handleBeforeBlockChannel({ + filterOrigin = null, + onBeforeBlockChannel, + action, + }) { + if (action && action != "allow" && action != "replace") { + throw new Error("Invalid action " + action); + } + let channelClassifierService = Cc[ + "@mozilla.org/url-classifier/channel-classifier-service;1" + ].getService(Ci.nsIChannelClassifierService); + + let resolver; + let promise = new Promise(resolve => { + resolver = resolve; + }); + + let observer = { + observe(subject, topic) { + if (topic != "urlclassifier-before-block-channel") { + return; + } + let channel = subject.QueryInterface(Ci.nsIUrlClassifierBlockedChannel); + + if (filterOrigin) { + let { url } = channel; + let { origin } = new URL(url); + if (filterOrigin != origin) { + return; + } + } + + if (onBeforeBlockChannel) { + onBeforeBlockChannel(channel); + } + if (action) { + channel[action](); + } + + channelClassifierService.removeListener(observer); + resolver(); + }, + }; + channelClassifierService.addListener(observer); + return promise; + }, }; diff --git a/tools/lint/rejected-words.yml b/tools/lint/rejected-words.yml index 51883067254f107043658a8b9ffffe2ddde39db1..ead8389124a3b462f658ae9cb6610b76eadeafc9 100644 --- a/tools/lint/rejected-words.yml +++ b/tools/lint/rejected-words.yml @@ -38,6 +38,7 @@ avoid-blacklist-and-whitelist: - browser/base/content/test/protectionsUI/browser_protectionsUI_report_breakage.js - browser/base/content/test/protectionsUI/browser_protectionsUI_socialtracking.js - browser/base/content/test/protectionsUI/browser_protectionsUI_state.js + - browser/base/content/test/protectionsUI/browser_protectionsUI_subview_shim.js - browser/base/content/test/siteIdentity/browser_no_mcb_for_loopback.js - browser/base/content/test/siteIdentity/browser_no_mcb_for_onions.js - browser/base/content/test/static/browser_all_files_referenced.js