diff options
Diffstat (limited to '')
-rw-r--r-- | toolkit/components/url-classifier/tests/browser/browser_emailtracking_telemetry.js | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/toolkit/components/url-classifier/tests/browser/browser_emailtracking_telemetry.js b/toolkit/components/url-classifier/tests/browser/browser_emailtracking_telemetry.js new file mode 100644 index 0000000000..086ca49afe --- /dev/null +++ b/toolkit/components/url-classifier/tests/browser/browser_emailtracking_telemetry.js @@ -0,0 +1,423 @@ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +"use strict"; + +let { UrlClassifierTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/UrlClassifierTestUtils.sys.mjs" +); + +const TEST_DOMAIN = "https://example.com/"; +const TEST_EMAIL_WEBAPP_DOMAIN = "https://test1.example.com/"; +const EMAIL_TRACKER_DOMAIN = "https://email-tracking.example.org/"; +const TEST_PATH = "browser/toolkit/components/url-classifier/tests/browser/"; + +const TEST_PAGE = TEST_DOMAIN + TEST_PATH + "page.html"; +const TEST_EMAIL_WEBAPP_PAGE = + TEST_EMAIL_WEBAPP_DOMAIN + TEST_PATH + "page.html"; + +const EMAIL_TRACKER_PAGE = EMAIL_TRACKER_DOMAIN + TEST_PATH + "page.html"; +const EMAIL_TRACKER_IMAGE = EMAIL_TRACKER_DOMAIN + TEST_PATH + "raptor.jpg"; + +const TELEMETRY_EMAIL_TRACKER_COUNT = "EMAIL_TRACKER_COUNT"; +const TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB = + "EMAIL_TRACKER_EMBEDDED_PER_TAB"; + +const LABEL_BASE_NORMAL = 0; +const LABEL_CONTENT_NORMAL = 1; +const LABEL_BASE_EMAIL_WEBAPP = 2; +const LABEL_CONTENT_EMAIL_WEBAPP = 3; + +const KEY_BASE_NORMAL = "base_normal"; +const KEY_CONTENT_NORMAL = "content_normal"; +const KEY_ALL_NORMAL = "all_normal"; +const KEY_BASE_EMAILAPP = "base_emailapp"; +const KEY_CONTENT_EMAILAPP = "content_emailapp"; +const KEY_ALL_EMAILAPP = "all_emailapp"; + +async function clearTelemetry() { + Services.telemetry.getSnapshotForHistograms("main", true /* clear */); + Services.telemetry.getHistogramById(TELEMETRY_EMAIL_TRACKER_COUNT).clear(); + Services.telemetry + .getKeyedHistogramById(TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB) + .clear(); +} + +async function loadImage(browser, url) { + return SpecialPowers.spawn(browser, [url], page => { + return new Promise(resolve => { + let image = new content.Image(); + image.src = page + "?" + Math.random(); + image.onload = _ => resolve(true); + image.onerror = _ => resolve(false); + }); + }); +} + +async function getTelemetryProbe(key, label, checkCntFn) { + let histogram; + + // Wait until the telemetry probe appears. + await TestUtils.waitForCondition(() => { + let histograms = Services.telemetry.getSnapshotForHistograms( + "main", + false /* clear */ + ).parent; + + histogram = histograms[key]; + + let checkRes = false; + + if (histogram) { + checkRes = checkCntFn ? checkCntFn(histogram.values[label]) : true; + } + + return checkRes; + }); + + return histogram.values[label] || 0; +} + +async function getKeyedHistogram(histogram_id, key, bucket, checkCntFn) { + let histogram; + + // Wait until the telemetry probe appears. + await TestUtils.waitForCondition(() => { + let histograms = Services.telemetry.getSnapshotForKeyedHistograms( + "main", + false /* clear */ + ).parent; + + histogram = histograms[histogram_id]; + + let checkRes = false; + + if (histogram && histogram[key]) { + checkRes = checkCntFn ? checkCntFn(histogram[key].values[bucket]) : true; + } + + return checkRes; + }); + + return histogram[key].values[bucket] || 0; +} + +async function checkTelemetryProbe(key, label, expectedCnt) { + let cnt = await getTelemetryProbe(key, label, cnt => { + if (cnt === undefined) { + cnt = 0; + } + + return cnt == expectedCnt; + }); + + is(cnt, expectedCnt, "There should be expected count in telemetry."); +} + +async function checkKeyedHistogram(histogram_id, key, bucket, expectedCnt) { + let cnt = await getKeyedHistogram(histogram_id, key, bucket, cnt => { + if (cnt === undefined) { + cnt = 0; + } + + return cnt == expectedCnt; + }); + + is(cnt, expectedCnt, "There should be expected count in keyed telemetry."); +} + +function checkNoTelemetryProbe(key) { + let histograms = Services.telemetry.getSnapshotForHistograms( + "main", + false /* clear */ + ).parent; + + let histogram = histograms[key]; + + ok(!histogram, `No Telemetry has been recorded for ${key}`); +} + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "urlclassifier.features.emailtracking.datacollection.blocklistTables", + "mochitest5-track-simple", + ], + [ + "urlclassifier.features.emailtracking.datacollection.allowlistTables", + "", + ], + [ + "urlclassifier.features.emailtracking.blocklistTables", + "mochitest5-track-simple", + ], + ["urlclassifier.features.emailtracking.allowlistTables", ""], + ["privacy.trackingprotection.enabled", false], + ["privacy.trackingprotection.annotate_channels", false], + ["privacy.trackingprotection.cryptomining.enabled", false], + ["privacy.trackingprotection.emailtracking.enabled", true], + [ + "privacy.trackingprotection.emailtracking.data_collection.enabled", + true, + ], + ["privacy.trackingprotection.fingerprinting.enabled", false], + ["privacy.trackingprotection.socialtracking.enabled", false], + [ + "privacy.trackingprotection.emailtracking.webapp.domains", + "test1.example.com", + ], + ], + }); + + await UrlClassifierTestUtils.addTestTrackers(); + + registerCleanupFunction(function () { + UrlClassifierTestUtils.cleanupTestTrackers(); + }); + + await clearTelemetry(); +}); + +add_task(async function test_email_tracking_telemetry() { + // Open a non email webapp tab. + await BrowserTestUtils.withNewTab(TEST_PAGE, async browser => { + // Load a image from the email tracker + let res = await loadImage(browser, EMAIL_TRACKER_IMAGE); + + is(res, false, "The image is blocked."); + + // Verify the telemetry of the email tracker count. + await checkTelemetryProbe( + TELEMETRY_EMAIL_TRACKER_COUNT, + LABEL_BASE_NORMAL, + 1 + ); + await checkTelemetryProbe( + TELEMETRY_EMAIL_TRACKER_COUNT, + LABEL_CONTENT_NORMAL, + 0 + ); + await checkTelemetryProbe( + TELEMETRY_EMAIL_TRACKER_COUNT, + LABEL_BASE_EMAIL_WEBAPP, + 0 + ); + await checkTelemetryProbe( + TELEMETRY_EMAIL_TRACKER_COUNT, + LABEL_CONTENT_EMAIL_WEBAPP, + 0 + ); + }); + + // Open an email webapp tab. + await BrowserTestUtils.withNewTab(TEST_EMAIL_WEBAPP_PAGE, async browser => { + // Load a image from the email tracker + let res = await loadImage(browser, EMAIL_TRACKER_IMAGE); + + is(res, false, "The image is blocked."); + + // Verify the telemetry of the email tracker count. + await checkTelemetryProbe( + TELEMETRY_EMAIL_TRACKER_COUNT, + LABEL_BASE_NORMAL, + 1 + ); + await checkTelemetryProbe( + TELEMETRY_EMAIL_TRACKER_COUNT, + LABEL_CONTENT_NORMAL, + 0 + ); + await checkTelemetryProbe( + TELEMETRY_EMAIL_TRACKER_COUNT, + LABEL_BASE_EMAIL_WEBAPP, + 1 + ); + await checkTelemetryProbe( + TELEMETRY_EMAIL_TRACKER_COUNT, + LABEL_CONTENT_EMAIL_WEBAPP, + 0 + ); + }); + // Make sure the tab was closed properly before clearing Telemetry. + await BrowserUtils.promiseObserved("window-global-destroyed"); + + await clearTelemetry(); +}); + +add_task(async function test_no_telemetry_for_first_party_email_tracker() { + // Open a email tracker tab. + await BrowserTestUtils.withNewTab(EMAIL_TRACKER_PAGE, async browser => { + // Load a image from the first-party email tracker + let res = await loadImage(browser, EMAIL_TRACKER_IMAGE); + + is(res, true, "The image is loaded."); + + // Verify that there was no telemetry recorded. + checkNoTelemetryProbe(TELEMETRY_EMAIL_TRACKER_COUNT); + }); + // Make sure the tab was closed properly before clearing Telemetry. + await BrowserUtils.promiseObserved("window-global-destroyed"); + + await clearTelemetry(); +}); + +add_task(async function test_disable_email_data_collection() { + // Disable Email Tracking Data Collection. + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "privacy.trackingprotection.emailtracking.data_collection.enabled", + false, + ], + ], + }); + + // Open an email webapp tab. + await BrowserTestUtils.withNewTab(TEST_EMAIL_WEBAPP_PAGE, async browser => { + // Load a image from the email tracker + let res = await loadImage(browser, EMAIL_TRACKER_IMAGE); + + is(res, false, "The image is blocked."); + + // Verify that there was no telemetry recorded. + checkNoTelemetryProbe(TELEMETRY_EMAIL_TRACKER_COUNT); + }); + // Make sure the tab was closed properly before clearing Telemetry. + await BrowserUtils.promiseObserved("window-global-destroyed"); + + await SpecialPowers.popPrefEnv(); + await clearTelemetry(); +}); + +add_task(async function test_email_tracker_embedded_telemetry() { + // First, we open a page without loading any email trackers. + await BrowserTestUtils.withNewTab(TEST_PAGE, async _ => {}); + // Make sure the tab was closed properly before checking Telemetry. + await BrowserUtils.promiseObserved("window-global-destroyed"); + + // Check that the telemetry has been record properly for normal page. The + // telemetry should show there was no email tracker loaded. + await checkKeyedHistogram( + TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB, + KEY_BASE_NORMAL, + 0, + 1 + ); + await checkKeyedHistogram( + TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB, + KEY_CONTENT_NORMAL, + 0, + 1 + ); + await checkKeyedHistogram( + TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB, + KEY_ALL_NORMAL, + 0, + 1 + ); + + // Second, Open a email webapp tab that doesn't a load email tracker. + await BrowserTestUtils.withNewTab(TEST_EMAIL_WEBAPP_PAGE, async _ => {}); + // Make sure the tab was closed properly before checking Telemetry. + await BrowserUtils.promiseObserved("window-global-destroyed"); + + // Check that the telemetry has been record properly for the email webapp. The + // telemetry should show there was no email tracker loaded. + await checkKeyedHistogram( + TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB, + KEY_BASE_EMAILAPP, + 0, + 1 + ); + await checkKeyedHistogram( + TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB, + KEY_CONTENT_EMAILAPP, + 0, + 1 + ); + await checkKeyedHistogram( + TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB, + KEY_ALL_EMAILAPP, + 0, + 1 + ); + + // Third, open a page with one email tracker loaded. + await BrowserTestUtils.withNewTab(TEST_PAGE, async browser => { + // Load a image from the email tracker + let res = await loadImage(browser, EMAIL_TRACKER_IMAGE); + + is(res, false, "The image is blocked."); + }); + // Make sure the tab was closed properly before checking Telemetry. + await BrowserUtils.promiseObserved("window-global-destroyed"); + + // Verify that the telemetry has been record properly, The telemetry should + // show there was one base email tracker loaded. + await checkKeyedHistogram( + TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB, + KEY_BASE_NORMAL, + 1, + 1 + ); + await checkKeyedHistogram( + TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB, + KEY_CONTENT_NORMAL, + 0, + 2 + ); + await checkKeyedHistogram( + TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB, + KEY_ALL_NORMAL, + 0, + 1 + ); + await checkKeyedHistogram( + TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB, + KEY_ALL_NORMAL, + 1, + 1 + ); + + // Open a page and load the same email tracker multiple times. There + // should be only one count for the same tracker. + await BrowserTestUtils.withNewTab(TEST_PAGE, async browser => { + // Load a image from the email tracker two times. + await loadImage(browser, EMAIL_TRACKER_IMAGE); + await loadImage(browser, EMAIL_TRACKER_IMAGE); + }); + // Make sure the tab was closed properly before checking Telemetry. + await BrowserUtils.promiseObserved("window-global-destroyed"); + + // Verify that there is still only one count when loading the same tracker + // multiple times. + await checkKeyedHistogram( + TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB, + KEY_BASE_NORMAL, + 1, + 2 + ); + await checkKeyedHistogram( + TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB, + KEY_CONTENT_NORMAL, + 0, + 3 + ); + await checkKeyedHistogram( + TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB, + KEY_ALL_NORMAL, + 0, + 1 + ); + await checkKeyedHistogram( + TELEMETRY_EMAIL_TRACKER_EMBEDDED_PER_TAB, + KEY_ALL_NORMAL, + 1, + 2 + ); + + await clearTelemetry(); +}); |