tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser_protectionsUI_cryptominers.js (8630B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 const TRACKING_PAGE =
      7  // eslint-disable-next-line @microsoft/sdl/no-insecure-url
      8  "http://example.org/browser/browser/base/content/test/protectionsUI/trackingPage.html";
      9 const CM_PROTECTION_PREF = "privacy.trackingprotection.cryptomining.enabled";
     10 let cmHistogram;
     11 
     12 add_setup(async function () {
     13  await SpecialPowers.pushPrefEnv({
     14    set: [
     15      [
     16        "urlclassifier.features.cryptomining.blacklistHosts",
     17        "cryptomining.example.com",
     18      ],
     19      [
     20        "urlclassifier.features.cryptomining.annotate.blacklistHosts",
     21        "cryptomining.example.com",
     22      ],
     23      ["privacy.trackingprotection.enabled", false],
     24      ["privacy.trackingprotection.annotate_channels", false],
     25      ["privacy.trackingprotection.fingerprinting.enabled", false],
     26      ["urlclassifier.features.fingerprinting.annotate.blacklistHosts", ""],
     27    ],
     28  });
     29  cmHistogram = Services.telemetry.getHistogramById(
     30    "CRYPTOMINERS_BLOCKED_COUNT"
     31  );
     32  registerCleanupFunction(() => {
     33    cmHistogram.clear();
     34  });
     35 });
     36 
     37 async function testIdentityState(hasException) {
     38  cmHistogram.clear();
     39  let promise = BrowserTestUtils.openNewForegroundTab({
     40    url: TRACKING_PAGE,
     41    gBrowser,
     42  });
     43  let [tab] = await Promise.all([promise, waitForContentBlockingEvent()]);
     44 
     45  if (hasException) {
     46    let loaded = BrowserTestUtils.browserLoaded(
     47      tab.linkedBrowser,
     48      false,
     49      TRACKING_PAGE
     50    );
     51    gProtectionsHandler.disableForCurrentPage();
     52    await loaded;
     53  }
     54 
     55  await openProtectionsPanel();
     56 
     57  ok(
     58    !gProtectionsHandler._protectionsPopup.hasAttribute("detected"),
     59    "cryptominers are not detected"
     60  );
     61 
     62  ok(
     63    BrowserTestUtils.isVisible(gProtectionsHandler.iconBox),
     64    "icon box is visible regardless the exception"
     65  );
     66 
     67  promise = waitForContentBlockingEvent();
     68 
     69  await SpecialPowers.spawn(tab.linkedBrowser, [], function () {
     70    content.postMessage("cryptomining", "*");
     71  });
     72 
     73  await promise;
     74 
     75  ok(
     76    gProtectionsHandler._protectionsPopup.hasAttribute("detected"),
     77    "trackers are detected"
     78  );
     79  ok(
     80    BrowserTestUtils.isVisible(gProtectionsHandler.iconBox),
     81    "icon box is visible"
     82  );
     83  is(
     84    gProtectionsHandler.iconBox.hasAttribute("hasException"),
     85    hasException,
     86    "Shows an exception when appropriate"
     87  );
     88 
     89  if (hasException) {
     90    let loaded = BrowserTestUtils.browserLoaded(
     91      tab.linkedBrowser,
     92      false,
     93      TRACKING_PAGE
     94    );
     95    gProtectionsHandler.enableForCurrentPage();
     96    await loaded;
     97  }
     98 
     99  let loads = hasException ? 3 : 1;
    100  testTelemetry(loads, 1, hasException);
    101 
    102  BrowserTestUtils.removeTab(tab);
    103 }
    104 
    105 async function testSubview(hasException) {
    106  cmHistogram.clear();
    107  let promise = BrowserTestUtils.openNewForegroundTab({
    108    url: TRACKING_PAGE,
    109    gBrowser,
    110  });
    111  let [tab] = await Promise.all([promise, waitForContentBlockingEvent()]);
    112 
    113  if (hasException) {
    114    let loaded = BrowserTestUtils.browserLoaded(
    115      tab.linkedBrowser,
    116      false,
    117      TRACKING_PAGE
    118    );
    119    gProtectionsHandler.disableForCurrentPage();
    120    await loaded;
    121  }
    122 
    123  promise = waitForContentBlockingEvent();
    124  await SpecialPowers.spawn(tab.linkedBrowser, [], function () {
    125    content.postMessage("cryptomining", "*");
    126  });
    127  await promise;
    128 
    129  await openProtectionsPanel();
    130 
    131  let categoryItem = document.getElementById(
    132    "protections-popup-category-cryptominers"
    133  );
    134 
    135  // Explicitly waiting for the category item becoming visible.
    136  await TestUtils.waitForCondition(() => {
    137    return BrowserTestUtils.isVisible(categoryItem);
    138  });
    139 
    140  ok(BrowserTestUtils.isVisible(categoryItem), "TP category item is visible");
    141 
    142  /* eslint-disable mozilla/no-arbitrary-setTimeout */
    143  // We have to wait until the ContentBlockingLog gets updated in the content.
    144  // Unfortunately, we need to use the setTimeout here since we don't have an
    145  // easy to know whether the log is updated in the content. This should be
    146  // removed after the log been removed in the content (Bug 1599046).
    147  await new Promise(resolve => {
    148    setTimeout(resolve, 500);
    149  });
    150  /* eslint-enable mozilla/no-arbitrary-setTimeout */
    151 
    152  let subview = document.getElementById("protections-popup-cryptominersView");
    153  let viewShown = BrowserTestUtils.waitForEvent(subview, "ViewShown");
    154  categoryItem.click();
    155  await viewShown;
    156 
    157  let trackersViewShimHint = document.getElementById(
    158    "protections-popup-cryptominersView-shim-allow-hint"
    159  );
    160  ok(trackersViewShimHint.hidden, "Shim hint is hidden");
    161 
    162  let listItems = subview.querySelectorAll(".protections-popup-list-item");
    163  is(listItems.length, 1, "We have 1 item in the list");
    164  let listItem = listItems[0];
    165  ok(BrowserTestUtils.isVisible(listItem), "List item is visible");
    166  is(
    167    listItem.querySelector("label").value,
    168    // eslint-disable-next-line @microsoft/sdl/no-insecure-url
    169    "http://cryptomining.example.com",
    170    "Has the correct host"
    171  );
    172  is(
    173    listItem.classList.contains("allowed"),
    174    hasException,
    175    "Indicates the miner was blocked or allowed"
    176  );
    177 
    178  let mainView = document.getElementById("protections-popup-mainView");
    179  viewShown = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
    180  let backButton = subview.querySelector(".subviewbutton-back");
    181  backButton.click();
    182  await viewShown;
    183 
    184  ok(true, "Main view was shown");
    185 
    186  if (hasException) {
    187    let loaded = BrowserTestUtils.browserLoaded(
    188      tab.linkedBrowser,
    189      false,
    190      TRACKING_PAGE
    191    );
    192    gProtectionsHandler.enableForCurrentPage();
    193    await loaded;
    194  }
    195 
    196  let loads = hasException ? 3 : 1;
    197  testTelemetry(loads, 1, hasException);
    198 
    199  BrowserTestUtils.removeTab(tab);
    200 }
    201 
    202 async function testCategoryItem() {
    203  Services.prefs.setBoolPref(CM_PROTECTION_PREF, false);
    204  let promise = BrowserTestUtils.openNewForegroundTab({
    205    url: TRACKING_PAGE,
    206    gBrowser,
    207  });
    208  let [tab] = await Promise.all([promise, waitForContentBlockingEvent()]);
    209 
    210  await openProtectionsPanel();
    211 
    212  let categoryItem = document.getElementById(
    213    "protections-popup-category-cryptominers"
    214  );
    215 
    216  ok(
    217    !categoryItem.classList.contains("blocked"),
    218    "Category not marked as blocked"
    219  );
    220  ok(
    221    categoryItem.classList.contains("notFound"),
    222    "Category marked as not found"
    223  );
    224  Services.prefs.setBoolPref(CM_PROTECTION_PREF, true);
    225  ok(categoryItem.classList.contains("blocked"), "Category marked as blocked");
    226  ok(
    227    categoryItem.classList.contains("notFound"),
    228    "Category marked as not found"
    229  );
    230  Services.prefs.setBoolPref(CM_PROTECTION_PREF, false);
    231  ok(
    232    !categoryItem.classList.contains("blocked"),
    233    "Category not marked as blocked"
    234  );
    235  ok(
    236    categoryItem.classList.contains("notFound"),
    237    "Category marked as not found"
    238  );
    239  await closeProtectionsPanel();
    240 
    241  promise = waitForContentBlockingEvent();
    242 
    243  await SpecialPowers.spawn(tab.linkedBrowser, [], function () {
    244    content.postMessage("cryptomining", "*");
    245  });
    246 
    247  await promise;
    248 
    249  await openProtectionsPanel();
    250  ok(
    251    !categoryItem.classList.contains("blocked"),
    252    "Category not marked as blocked"
    253  );
    254  ok(
    255    !categoryItem.classList.contains("notFound"),
    256    "Category not marked as not found"
    257  );
    258  Services.prefs.setBoolPref(CM_PROTECTION_PREF, true);
    259  ok(categoryItem.classList.contains("blocked"), "Category marked as blocked");
    260  ok(
    261    !categoryItem.classList.contains("notFound"),
    262    "Category not marked as not found"
    263  );
    264  Services.prefs.setBoolPref(CM_PROTECTION_PREF, false);
    265  ok(
    266    !categoryItem.classList.contains("blocked"),
    267    "Category not marked as blocked"
    268  );
    269  ok(
    270    !categoryItem.classList.contains("notFound"),
    271    "Category not marked as not found"
    272  );
    273  await closeProtectionsPanel();
    274 
    275  BrowserTestUtils.removeTab(tab);
    276 }
    277 
    278 function testTelemetry(pagesVisited, pagesWithBlockableContent, hasException) {
    279  let results = cmHistogram.snapshot();
    280  Assert.equal(
    281    results.values[0],
    282    pagesVisited,
    283    "The correct number of page loads have been recorded"
    284  );
    285  let expectedValue = hasException ? 2 : 1;
    286  Assert.equal(
    287    results.values[expectedValue],
    288    pagesWithBlockableContent,
    289    "The correct number of cryptominers have been recorded as blocked or allowed."
    290  );
    291 }
    292 
    293 add_task(async function test() {
    294  Services.prefs.setBoolPref(CM_PROTECTION_PREF, true);
    295 
    296  await testIdentityState(false);
    297  await testIdentityState(true);
    298 
    299  await testSubview(false);
    300  await testSubview(true);
    301 
    302  await testCategoryItem();
    303 
    304  Services.prefs.clearUserPref(CM_PROTECTION_PREF);
    305  Services.prefs.setStringPref("browser.contentblocking.category", "standard");
    306 });