summaryrefslogtreecommitdiffstats
path: root/toolkit/components/antitracking/test/browser/browser_urlQueryStringStripping_telemetry_2.js
blob: 9f7c6146f1440b2dd31c681f6569628ae253d9be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
"use strict";

const TEST_URI = TEST_DOMAIN + TEST_PATH + "file_stripping.html";

const QUERY_STRIPPING_COUNT = "QUERY_STRIPPING_COUNT";
const QUERY_STRIPPING_PARAM_COUNT = "QUERY_STRIPPING_PARAM_COUNT";
const QUERY_STRIPPING_COUNT_BY_PARAM = "QUERY_STRIPPING_COUNT_BY_PARAM";

const histogramLabels =
  Services.telemetry.getCategoricalLabels().QUERY_STRIPPING_COUNT_BY_PARAM;

async function clearTelemetry() {
  // There's an arbitrary interval of 2 seconds in which the content
  // processes sync their data with the parent process, we wait
  // this out to ensure that we clear everything.
  // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
  await new Promise(resolve => setTimeout(resolve, 2000));

  Services.telemetry.getSnapshotForHistograms("main", true /* clear */);
  Services.telemetry.getHistogramById(QUERY_STRIPPING_COUNT).clear();
  Services.telemetry.getHistogramById(QUERY_STRIPPING_PARAM_COUNT).clear();
  Services.telemetry.getHistogramById(QUERY_STRIPPING_COUNT_BY_PARAM).clear();

  let isCleared = () => {
    let histograms = Services.telemetry.getSnapshotForHistograms(
      "main",
      false /* clear */
    ).content;

    return (
      !histograms ||
      (!histograms[QUERY_STRIPPING_COUNT] &&
        !histograms[QUERY_STRIPPING_PARAM_COUNT] &&
        !histograms.QUERY_STRIPPING_COUNT_BY_PARAM)
    );
  };

  // Check that the telemetry probes have been cleared properly. Do this check
  // sync first to avoid any race conditions where telemetry arrives after
  // clearing.
  if (!isCleared()) {
    await TestUtils.waitForCondition(isCleared);
  }

  ok(true, "Telemetry has been cleared.");
}

async function verifyQueryString(browser, expected) {
  await SpecialPowers.spawn(browser, [expected], expected => {
    // Strip the first question mark.
    let search = content.location.search.slice(1);

    is(search, expected, "The query string is correct.");
  });
}

function testTelemetry(queryParamToCount) {
  const histogram = Services.telemetry.getHistogramById(
    QUERY_STRIPPING_COUNT_BY_PARAM
  );

  let snapshot = histogram.snapshot();

  let indexToCount = {};
  Object.entries(queryParamToCount).forEach(([key, value]) => {
    let index = histogramLabels.indexOf(`param_${key}`);

    // In debug builds we perform additional stripping for testing, which
    // results in telemetry being recorded twice. This does not impact
    // production builds.
    if (SpecialPowers.isDebugBuild) {
      indexToCount[index] = value * 2;
    } else {
      indexToCount[index] = value;
    }
  });

  for (let [i, val] of Object.entries(snapshot.values)) {
    let expectedCount = indexToCount[i] || 0;

    is(
      val,
      expectedCount,
      `Histogram ${QUERY_STRIPPING_COUNT_BY_PARAM} should have expected value for label ${histogramLabels[i]}.`
    );
  }
}

add_setup(async function () {
  await SpecialPowers.pushPrefEnv({
    set: [
      ["privacy.query_stripping.enabled", true],
      [
        "privacy.query_stripping.strip_list",
        "foo mc_eid oly_anon_id oly_enc_id __s vero_id _hsenc mkt_tok fbclid ysclid",
      ],
    ],
  });

  // Clear Telemetry probes before testing.
  await clearTelemetry();
});

/**
 * Tests the QUERY_STRIPPING_COUNT_BY_PARAM histogram telemetry which counts how
 * often query params from a predefined lists are stripped.
 */
add_task(async function test_queryParamCountTelemetry() {
  info("Test with a query params to be stripped and recoded in telemetry.");
  let url = new URL(TEST_URI);
  url.searchParams.set("mc_eid", "myValue");

  // Open a new tab and trigger the query stripping.
  await BrowserTestUtils.withNewTab(url.href, async browser => {
    // Verify that the tracking query param has been stripped.
    await verifyQueryString(browser, "");
  });

  testTelemetry({ mc_eid: 1 });

  // Repeat this with the same query parameter, the respective histogram bucket
  // should be incremented.
  await BrowserTestUtils.withNewTab(url.href, async browser => {
    await verifyQueryString(browser, "");
  });

  testTelemetry({ mc_eid: 2 });

  url = new URL(TEST_URI);
  url.searchParams.set("fbclid", "myValue2");
  url.searchParams.set("mkt_tok", "myValue3");
  url.searchParams.set("bar", "foo");

  info("Test with multiple query params to be stripped.");
  await BrowserTestUtils.withNewTab(url.href, async browser => {
    await verifyQueryString(browser, "bar=foo");
  });
  testTelemetry({ mc_eid: 2, fbclid: 1, mkt_tok: 1 });

  info(
    "Test with query param on the strip-list, which should not be recoded in telemetry."
  );
  url = new URL(TEST_URI);
  url.searchParams.set("foo", "bar");
  url.searchParams.set("__s", "myValue4");
  url.searchParams.set("ysclid", "myValue5");
  await BrowserTestUtils.withNewTab(url.href, async browser => {
    await verifyQueryString(browser, "");
  });
  testTelemetry({ mc_eid: 2, fbclid: 1, mkt_tok: 1, __s: 1, ysclid: 1 });

  url = new URL(TEST_URI);
  url.searchParams.set("foo", "bar");
  await BrowserTestUtils.withNewTab(url.href, async browser => {
    await verifyQueryString(browser, "");
  });
  testTelemetry({ mc_eid: 2, fbclid: 1, mkt_tok: 1, __s: 1, ysclid: 1 });

  await clearTelemetry();
});