summaryrefslogtreecommitdiffstats
path: root/browser/components/protections/test/browser/browser_protections_report_ui.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/protections/test/browser/browser_protections_report_ui.js')
-rw-r--r--browser/components/protections/test/browser/browser_protections_report_ui.js845
1 files changed, 845 insertions, 0 deletions
diff --git a/browser/components/protections/test/browser/browser_protections_report_ui.js b/browser/components/protections/test/browser/browser_protections_report_ui.js
new file mode 100644
index 0000000000..6f8d48d6dd
--- /dev/null
+++ b/browser/components/protections/test/browser/browser_protections_report_ui.js
@@ -0,0 +1,845 @@
+/* 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/. */
+
+// Note: This test may cause intermittents if run at exactly midnight.
+
+const { Sqlite } = ChromeUtils.importESModule(
+ "resource://gre/modules/Sqlite.sys.mjs"
+);
+const { AboutProtectionsParent } = ChromeUtils.importESModule(
+ "resource:///actors/AboutProtectionsParent.sys.mjs"
+);
+
+XPCOMUtils.defineLazyServiceGetter(
+ this,
+ "TrackingDBService",
+ "@mozilla.org/tracking-db-service;1",
+ "nsITrackingDBService"
+);
+
+XPCOMUtils.defineLazyGetter(this, "DB_PATH", function () {
+ return PathUtils.join(PathUtils.profileDir, "protections.sqlite");
+});
+
+const SQL = {
+ insertCustomTimeEvent:
+ "INSERT INTO events (type, count, timestamp)" +
+ "VALUES (:type, :count, date(:timestamp));",
+
+ selectAll: "SELECT * FROM events",
+};
+
+add_setup(async function () {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.contentblocking.database.enabled", true],
+ ["browser.vpn_promo.enabled", false],
+ ],
+ });
+});
+
+add_task(async function test_graph_display() {
+ // This creates the schema.
+ await TrackingDBService.saveEvents(JSON.stringify({}));
+ let db = await Sqlite.openConnection({ path: DB_PATH });
+
+ let date = new Date().toISOString();
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.TRACKERS_ID,
+ count: 1,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.CRYPTOMINERS_ID,
+ count: 2,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.FINGERPRINTERS_ID,
+ count: 2,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.TRACKING_COOKIES_ID,
+ count: 4,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.SOCIAL_ID,
+ count: 1,
+ timestamp: date,
+ });
+
+ date = new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString();
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.TRACKERS_ID,
+ count: 4,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.CRYPTOMINERS_ID,
+ count: 3,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.FINGERPRINTERS_ID,
+ count: 2,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.SOCIAL_ID,
+ count: 1,
+ timestamp: date,
+ });
+
+ date = new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString();
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.TRACKERS_ID,
+ count: 4,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.CRYPTOMINERS_ID,
+ count: 3,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.TRACKING_COOKIES_ID,
+ count: 1,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.SOCIAL_ID,
+ count: 1,
+ timestamp: date,
+ });
+
+ date = new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString();
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.TRACKERS_ID,
+ count: 3,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.FINGERPRINTERS_ID,
+ count: 2,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.TRACKING_COOKIES_ID,
+ count: 1,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.SOCIAL_ID,
+ count: 1,
+ timestamp: date,
+ });
+
+ date = new Date(Date.now() - 4 * 24 * 60 * 60 * 1000).toISOString();
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.CRYPTOMINERS_ID,
+ count: 2,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.FINGERPRINTERS_ID,
+ count: 2,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.TRACKING_COOKIES_ID,
+ count: 1,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.SOCIAL_ID,
+ count: 1,
+ timestamp: date,
+ });
+
+ date = new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString();
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.TRACKERS_ID,
+ count: 3,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.CRYPTOMINERS_ID,
+ count: 3,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.FINGERPRINTERS_ID,
+ count: 2,
+ timestamp: date,
+ });
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.TRACKING_COOKIES_ID,
+ count: 8,
+ timestamp: date,
+ });
+
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ url: "about:protections",
+ gBrowser,
+ });
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ const DATA_TYPES = [
+ "cryptominer",
+ "fingerprinter",
+ "tracker",
+ "cookie",
+ "social",
+ ];
+ let allBars = null;
+ await ContentTaskUtils.waitForCondition(() => {
+ allBars = content.document.querySelectorAll(".graph-bar");
+ return allBars.length;
+ }, "The graph has been built");
+
+ Assert.equal(allBars.length, 7, "7 bars have been found on the graph");
+
+ // For accessibility, test if the graph is a table
+ // and has a correct column count (number of data types + total + day)
+ Assert.equal(
+ content.document.getElementById("graph").getAttribute("role"),
+ "table",
+ "Graph is an accessible table"
+ );
+ Assert.equal(
+ content.document.getElementById("graph").getAttribute("aria-colcount"),
+ DATA_TYPES.length + 2,
+ "Table has the right number of columns"
+ );
+ Assert.equal(
+ content.document.getElementById("graph").getAttribute("aria-labelledby"),
+ "graphLegendDescription",
+ "Table has an accessible label"
+ );
+
+ // today has each type
+ // yesterday will have no tracking cookies
+ // 2 days ago will have no fingerprinters
+ // 3 days ago will have no cryptominers
+ // 4 days ago will have no trackers
+ // 5 days ago will have no social (when we add social)
+ // 6 days ago will be empty
+ Assert.equal(
+ allBars[6].querySelectorAll(".inner-bar").length,
+ DATA_TYPES.length,
+ "today has all of the data types shown"
+ );
+ Assert.equal(
+ allBars[6].getAttribute("role"),
+ "row",
+ "Today has the correct role"
+ );
+ Assert.equal(
+ allBars[6].getAttribute("aria-owns"),
+ "day0 count0 cryptominer0 fingerprinter0 tracker0 cookie0 social0",
+ "Row has the columns in the right order"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".tracker-bar").style.height,
+ "10%",
+ "trackers take 10%"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".tracker-bar").parentNode.getAttribute("role"),
+ "cell",
+ "Trackers have the correct role"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".tracker-bar").getAttribute("role"),
+ "img",
+ "Tracker bar has the correct image role"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".tracker-bar").getAttribute("aria-label"),
+ "1 tracking content (10%)",
+ "Trackers have the correct accessible text"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".cryptominer-bar").style.height,
+ "20%",
+ "cryptominers take 20%"
+ );
+ Assert.equal(
+ allBars[6]
+ .querySelector(".cryptominer-bar")
+ .parentNode.getAttribute("role"),
+ "cell",
+ "Cryptominers have the correct role"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".cryptominer-bar").getAttribute("role"),
+ "img",
+ "Cryptominer bar has the correct image role"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".cryptominer-bar").getAttribute("aria-label"),
+ "2 cryptominers (20%)",
+ "Cryptominers have the correct accessible label"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".fingerprinter-bar").style.height,
+ "20%",
+ "fingerprinters take 20%"
+ );
+ Assert.equal(
+ allBars[6]
+ .querySelector(".fingerprinter-bar")
+ .parentNode.getAttribute("role"),
+ "cell",
+ "Fingerprinters have the correct role"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".fingerprinter-bar").getAttribute("role"),
+ "img",
+ "Fingerprinter bar has the correct image role"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".fingerprinter-bar").getAttribute("aria-label"),
+ "2 fingerprinters (20%)",
+ "Fingerprinters have the correct accessible label"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".cookie-bar").style.height,
+ "40%",
+ "cross site tracking cookies take 40%"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".cookie-bar").parentNode.getAttribute("role"),
+ "cell",
+ "cross site tracking cookies have the correct role"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".cookie-bar").getAttribute("role"),
+ "img",
+ "Cross site tracking cookies bar has the correct image role"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".cookie-bar").getAttribute("aria-label"),
+ "4 cross-site tracking cookies (40%)",
+ "cross site tracking cookies have the correct accessible label"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".social-bar").style.height,
+ "10%",
+ "social trackers take 10%"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".social-bar").parentNode.getAttribute("role"),
+ "cell",
+ "social trackers have the correct role"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".social-bar").getAttribute("role"),
+ "img",
+ "social tracker bar has the correct image role"
+ );
+ Assert.equal(
+ allBars[6].querySelector(".social-bar").getAttribute("aria-label"),
+ "1 social media tracker (10%)",
+ "social trackers have the correct accessible text"
+ );
+
+ Assert.equal(
+ allBars[5].querySelectorAll(".inner-bar").length,
+ DATA_TYPES.length - 1,
+ "1 day ago is missing one type"
+ );
+ Assert.ok(
+ !allBars[5].querySelector(".cookie-bar"),
+ "there is no cross site tracking cookie section 1 day ago."
+ );
+ Assert.equal(
+ allBars[5].getAttribute("aria-owns"),
+ "day1 count1 cryptominer1 fingerprinter1 tracker1 social1",
+ "Row has the columns in the right order"
+ );
+
+ Assert.equal(
+ allBars[4].querySelectorAll(".inner-bar").length,
+ DATA_TYPES.length - 1,
+ "2 days ago is missing one type"
+ );
+ Assert.ok(
+ !allBars[4].querySelector(".fingerprinter-bar"),
+ "there is no fingerprinter section 1 day ago."
+ );
+ Assert.equal(
+ allBars[4].getAttribute("aria-owns"),
+ "day2 count2 cryptominer2 tracker2 cookie2 social2",
+ "Row has the columns in the right order"
+ );
+
+ Assert.equal(
+ allBars[3].querySelectorAll(".inner-bar").length,
+ DATA_TYPES.length - 1,
+ "3 days ago is missing one type"
+ );
+ Assert.ok(
+ !allBars[3].querySelector(".cryptominer-bar"),
+ "there is no cryptominer section 1 day ago."
+ );
+ Assert.equal(
+ allBars[3].getAttribute("aria-owns"),
+ "day3 count3 fingerprinter3 tracker3 cookie3 social3",
+ "Row has the columns in the right order"
+ );
+
+ Assert.equal(
+ allBars[2].querySelectorAll(".inner-bar").length,
+ DATA_TYPES.length - 1,
+ "4 days ago is missing one type"
+ );
+ Assert.ok(
+ !allBars[2].querySelector(".tracker-bar"),
+ "there is no tracker section 1 day ago."
+ );
+ Assert.equal(
+ allBars[2].getAttribute("aria-owns"),
+ "day4 count4 cryptominer4 fingerprinter4 cookie4 social4",
+ "Row has the columns in the right order"
+ );
+
+ Assert.equal(
+ allBars[1].querySelectorAll(".inner-bar").length,
+ DATA_TYPES.length - 1,
+ "5 days ago is missing one type"
+ );
+ Assert.ok(
+ !allBars[1].querySelector(".social-bar"),
+ "there is no social section 1 day ago."
+ );
+ Assert.equal(
+ allBars[1].getAttribute("aria-owns"),
+ "day5 count5 cryptominer5 fingerprinter5 tracker5 cookie5",
+ "Row has the columns in the right order"
+ );
+
+ Assert.equal(
+ allBars[0].querySelectorAll(".inner-bar").length,
+ 0,
+ "6 days ago has no content"
+ );
+ Assert.ok(
+ allBars[0].classList.contains("empty"),
+ "6 days ago is an empty bar"
+ );
+ Assert.equal(
+ allBars[0].getAttribute("aria-owns"),
+ "day6 ",
+ "Row has the columns in the right order"
+ );
+
+ // Check that each tab has the correct aria-labelledby and aria-describedby
+ // values. This helps screen readers know what type of tracker the reported
+ // tab number is referencing.
+ const socialTab = content.document.getElementById("tab-social");
+ Assert.equal(
+ socialTab.getAttribute("aria-labelledby"),
+ "socialLabel socialTitle",
+ "aria-labelledby attribute is socialLabel socialTitle"
+ );
+ Assert.equal(
+ socialTab.getAttribute("aria-describedby"),
+ "socialContent",
+ "aria-describedby attribute is socialContent"
+ );
+
+ const cookieTab = content.document.getElementById("tab-cookie");
+ Assert.equal(
+ cookieTab.getAttribute("aria-labelledby"),
+ "cookieLabel cookieTitle",
+ "aria-labelledby attribute is cookieLabel cookieTitle"
+ );
+ Assert.equal(
+ cookieTab.getAttribute("aria-describedby"),
+ "cookieContent",
+ "aria-describedby attribute is cookieContent"
+ );
+
+ const trackerTab = content.document.getElementById("tab-tracker");
+ Assert.equal(
+ trackerTab.getAttribute("aria-labelledby"),
+ "trackerLabel trackerTitle",
+ "aria-labelledby attribute is trackerLabel trackerTitle"
+ );
+ Assert.equal(
+ trackerTab.getAttribute("aria-describedby"),
+ "trackerContent",
+ "aria-describedby attribute is trackerContent"
+ );
+
+ const fingerprinterTab =
+ content.document.getElementById("tab-fingerprinter");
+ Assert.equal(
+ fingerprinterTab.getAttribute("aria-labelledby"),
+ "fingerprinterLabel fingerprinterTitle",
+ "aria-labelledby attribute is fingerprinterLabel fingerprinterTitle"
+ );
+ Assert.equal(
+ fingerprinterTab.getAttribute("aria-describedby"),
+ "fingerprinterContent",
+ "aria-describedby attribute is fingerprinterContent"
+ );
+
+ const cryptominerTab = content.document.getElementById("tab-cryptominer");
+ Assert.equal(
+ cryptominerTab.getAttribute("aria-labelledby"),
+ "cryptominerLabel cryptominerTitle",
+ "aria-labelledby attribute is cryptominerLabel cryptominerTitle"
+ );
+ Assert.equal(
+ cryptominerTab.getAttribute("aria-describedby"),
+ "cryptominerContent",
+ "aria-describedby attribute is cryptominerContent"
+ );
+ });
+
+ // Use the TrackingDBService API to delete the data.
+ await TrackingDBService.clearAll();
+ // Make sure the data was deleted.
+ let rows = await db.execute(SQL.selectAll);
+ is(rows.length, 0, "length is 0");
+ await db.close();
+ BrowserTestUtils.removeTab(tab);
+});
+
+// Ensure that each type of tracker is hidden from the graph if there are no recorded
+// trackers of that type and the user has chosen to not block that type.
+add_task(async function test_etp_custom_settings() {
+ Services.prefs.setStringPref("browser.contentblocking.category", "strict");
+ Services.prefs.setBoolPref(
+ "privacy.socialtracking.block_cookies.enabled",
+ true
+ );
+ // hide cookies from the graph
+ Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ url: "about:protections",
+ gBrowser,
+ });
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ await ContentTaskUtils.waitForCondition(() => {
+ let legend = content.document.getElementById("legend");
+ return ContentTaskUtils.is_visible(legend);
+ }, "The legend is visible");
+
+ let label = content.document.getElementById("cookieLabel");
+ Assert.ok(ContentTaskUtils.is_hidden(label), "Cookie Label is hidden");
+
+ label = content.document.getElementById("trackerLabel");
+ Assert.ok(ContentTaskUtils.is_visible(label), "Tracker Label is visible");
+ label = content.document.getElementById("socialLabel");
+ Assert.ok(ContentTaskUtils.is_visible(label), "Social Label is visible");
+ label = content.document.getElementById("cryptominerLabel");
+ Assert.ok(
+ ContentTaskUtils.is_visible(label),
+ "Cryptominer Label is visible"
+ );
+ label = content.document.getElementById("fingerprinterLabel");
+ Assert.ok(
+ ContentTaskUtils.is_visible(label),
+ "Fingerprinter Label is visible"
+ );
+ });
+ BrowserTestUtils.removeTab(tab);
+
+ // hide ad trackers from the graph
+ Services.prefs.setBoolPref("privacy.trackingprotection.enabled", false);
+ tab = await BrowserTestUtils.openNewForegroundTab({
+ url: "about:protections",
+ gBrowser,
+ });
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ await ContentTaskUtils.waitForCondition(() => {
+ let legend = content.document.getElementById("legend");
+ return ContentTaskUtils.is_visible(legend);
+ }, "The legend is visible");
+
+ let label = content.document.querySelector("#trackerLabel");
+ Assert.ok(ContentTaskUtils.is_hidden(label), "Tracker Label is hidden");
+
+ label = content.document.querySelector("#socialLabel");
+ Assert.ok(ContentTaskUtils.is_hidden(label), "Social Label is hidden");
+ });
+ BrowserTestUtils.removeTab(tab);
+
+ // hide social from the graph
+ Services.prefs.setBoolPref(
+ "privacy.trackingprotection.socialtracking.enabled",
+ false
+ );
+ Services.prefs.setBoolPref(
+ "privacy.socialtracking.block_cookies.enabled",
+ false
+ );
+ tab = await BrowserTestUtils.openNewForegroundTab({
+ url: "about:protections",
+ gBrowser,
+ });
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ await ContentTaskUtils.waitForCondition(() => {
+ let legend = content.document.getElementById("legend");
+ return ContentTaskUtils.is_visible(legend);
+ }, "The legend is visible");
+
+ let label = content.document.querySelector("#socialLabel");
+ Assert.ok(ContentTaskUtils.is_hidden(label), "Social Label is hidden");
+ });
+ BrowserTestUtils.removeTab(tab);
+
+ // hide fingerprinting from the graph
+ Services.prefs.setBoolPref(
+ "privacy.trackingprotection.fingerprinting.enabled",
+ false
+ );
+ tab = await BrowserTestUtils.openNewForegroundTab({
+ url: "about:protections",
+ gBrowser,
+ });
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ await ContentTaskUtils.waitForCondition(() => {
+ let legend = content.document.getElementById("legend");
+ return ContentTaskUtils.is_visible(legend);
+ }, "The legend is visible");
+
+ let label = content.document.querySelector("#fingerprinterLabel");
+ Assert.ok(
+ ContentTaskUtils.is_hidden(label),
+ "Fingerprinter Label is hidden"
+ );
+ });
+ BrowserTestUtils.removeTab(tab);
+
+ // hide cryptomining from the graph
+ Services.prefs.setBoolPref(
+ "privacy.trackingprotection.cryptomining.enabled",
+ false
+ );
+ // Turn fingerprinting on so that all protectionsare not turned off, otherwise we will get a special card.
+ Services.prefs.setBoolPref(
+ "privacy.trackingprotection.fingerprinting.enabled",
+ true
+ );
+ tab = await BrowserTestUtils.openNewForegroundTab({
+ url: "about:protections",
+ gBrowser,
+ });
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ await ContentTaskUtils.waitForCondition(() => {
+ let legend = content.document.getElementById("legend");
+ return ContentTaskUtils.is_visible(legend);
+ }, "The legend is visible");
+
+ let label = content.document.querySelector("#cryptominerLabel");
+ Assert.ok(ContentTaskUtils.is_hidden(label), "Cryptominer Label is hidden");
+ });
+ Services.prefs.clearUserPref("browser.contentblocking.category");
+ Services.prefs.clearUserPref(
+ "privacy.trackingprotection.fingerprinting.enabled"
+ );
+ Services.prefs.clearUserPref(
+ "privacy.trackingprotection.cryptomining.enabled"
+ );
+ Services.prefs.clearUserPref("privacy.trackingprotection.enabled");
+ Services.prefs.clearUserPref("network.cookie.cookieBehavior");
+ Services.prefs.clearUserPref("privacy.socialtracking.block_cookies.enabled");
+
+ BrowserTestUtils.removeTab(tab);
+});
+
+// Ensure that the Custom manage Protections card is shown if the user has all protections turned off.
+add_task(async function test_etp_custom_protections_off() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.contentblocking.category", "custom"],
+ ["network.cookie.cookieBehavior", 0], // not blocking
+ ["privacy.trackingprotection.cryptomining.enabled", false], // not blocking
+ ["privacy.trackingprotection.fingerprinting.enabled", false],
+ ["privacy.trackingprotection.enabled", false],
+ ["privacy.trackingprotection.socialtracking.enabled", false],
+ ["privacy.socialtracking.block_cookies.enabled", false],
+ ],
+ });
+
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ url: "about:protections",
+ gBrowser,
+ });
+
+ let aboutPreferencesPromise = BrowserTestUtils.waitForNewTab(
+ gBrowser,
+ "about:preferences#privacy"
+ );
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ await ContentTaskUtils.waitForCondition(() => {
+ let etpCard = content.document.querySelector(".etp-card");
+ return etpCard.classList.contains("custom-not-blocking");
+ }, "The custom protections warning card is showing");
+
+ let manageProtectionsButton =
+ content.document.getElementById("manage-protections");
+ Assert.ok(
+ ContentTaskUtils.is_visible(manageProtectionsButton),
+ "Button to manage protections is displayed"
+ );
+ });
+
+ // Custom protection card should show, even if there would otherwise be data on the graph.
+ let db = await Sqlite.openConnection({ path: DB_PATH });
+ let date = new Date().toISOString();
+ await db.execute(SQL.insertCustomTimeEvent, {
+ type: TrackingDBService.TRACKERS_ID,
+ count: 1,
+ timestamp: date,
+ });
+ await BrowserTestUtils.reloadTab(tab);
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ await ContentTaskUtils.waitForCondition(() => {
+ let etpCard = content.document.querySelector(".etp-card");
+ return etpCard.classList.contains("custom-not-blocking");
+ }, "The custom protections warning card is showing");
+
+ let manageProtectionsButton =
+ content.document.getElementById("manage-protections");
+ Assert.ok(
+ ContentTaskUtils.is_visible(manageProtectionsButton),
+ "Button to manage protections is displayed"
+ );
+
+ manageProtectionsButton.click();
+ });
+ let aboutPreferencesTab = await aboutPreferencesPromise;
+ info("about:preferences#privacy was successfully opened in a new tab");
+ gBrowser.removeTab(aboutPreferencesTab);
+
+ Services.prefs.setStringPref("browser.contentblocking.category", "standard");
+ // Use the TrackingDBService API to delete the data.
+ await TrackingDBService.clearAll();
+ // Make sure the data was deleted.
+ let rows = await db.execute(SQL.selectAll);
+ is(rows.length, 0, "length is 0");
+ await db.close();
+ BrowserTestUtils.removeTab(tab);
+});
+
+// Ensure that the ETP mobile promotion card is shown when the pref is on and
+// there are no mobile devices connected.
+add_task(async function test_etp_mobile_promotion_pref_on() {
+ AboutProtectionsParent.setTestOverride(mockGetLoginDataWithSyncedDevices());
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.contentblocking.report.show_mobile_app", true]],
+ });
+
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ url: "about:protections",
+ gBrowser,
+ });
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ let mobilePromotion = content.document.getElementById("mobile-hanger");
+ Assert.ok(
+ ContentTaskUtils.is_visible(mobilePromotion),
+ "Mobile promotions card is displayed when pref is on and there are no synced mobile devices"
+ );
+
+ // Card should hide after the X is clicked.
+ mobilePromotion.querySelector(".exit-icon").click();
+ Assert.ok(
+ ContentTaskUtils.is_hidden(mobilePromotion),
+ "Mobile promotions card is no longer displayed after clicking the X button"
+ );
+ });
+ BrowserTestUtils.removeTab(tab);
+
+ // Add a mock mobile device. The promotion should now be hidden.
+ AboutProtectionsParent.setTestOverride(
+ mockGetLoginDataWithSyncedDevices(true)
+ );
+ tab = await BrowserTestUtils.openNewForegroundTab({
+ url: "about:protections",
+ gBrowser,
+ });
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ let mobilePromotion = content.document.getElementById("mobile-hanger");
+ Assert.ok(
+ ContentTaskUtils.is_hidden(mobilePromotion),
+ "Mobile promotions card is hidden when pref is on if there are synced mobile devices"
+ );
+ });
+
+ BrowserTestUtils.removeTab(tab);
+ AboutProtectionsParent.setTestOverride(null);
+});
+
+// Test that ETP mobile promotion is not shown when the pref is off,
+// even if no mobile devices are synced.
+add_task(async function test_etp_mobile_promotion_pref_on() {
+ AboutProtectionsParent.setTestOverride(mockGetLoginDataWithSyncedDevices());
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.contentblocking.report.show_mobile_app", false]],
+ });
+
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ url: "about:protections",
+ gBrowser,
+ });
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ let mobilePromotion = content.document.getElementById("mobile-hanger");
+ Assert.ok(
+ ContentTaskUtils.is_hidden(mobilePromotion),
+ "Mobile promotions card is not displayed when pref is off and there are no synced mobile devices"
+ );
+ });
+
+ BrowserTestUtils.removeTab(tab);
+
+ AboutProtectionsParent.setTestOverride(
+ mockGetLoginDataWithSyncedDevices(true)
+ );
+ tab = await BrowserTestUtils.openNewForegroundTab({
+ url: "about:protections",
+ gBrowser,
+ });
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ let mobilePromotion = content.document.getElementById("mobile-hanger");
+ Assert.ok(
+ ContentTaskUtils.is_hidden(mobilePromotion),
+ "Mobile promotions card is not displayed when pref is off even if there are synced mobile devices"
+ );
+ });
+ BrowserTestUtils.removeTab(tab);
+ AboutProtectionsParent.setTestOverride(null);
+});
+
+// Test that clicking on the link to settings in the header properly opens the settings page.
+add_task(async function test_settings_links() {
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ url: "about:protections",
+ gBrowser,
+ });
+ let aboutPreferencesPromise = BrowserTestUtils.waitForNewTab(
+ gBrowser,
+ "about:preferences#privacy"
+ );
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ const protectionSettings = await ContentTaskUtils.waitForCondition(() => {
+ return content.document.getElementById("protection-settings");
+ }, "protection-settings link exists");
+
+ protectionSettings.click();
+ });
+ let aboutPreferencesTab = await aboutPreferencesPromise;
+ info("about:preferences#privacy was successfully opened in a new tab");
+ gBrowser.removeTab(aboutPreferencesTab);
+ gBrowser.removeTab(tab);
+});