tor-browser

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

browser_interventions.js (7784B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 ChromeUtils.defineESModuleGetters(this, {
      7  UrlbarProviderInterventions:
      8    "moz-src:///browser/components/urlbar/UrlbarProviderInterventions.sys.mjs",
      9 });
     10 
     11 add_setup(async function () {
     12  Services.telemetry.clearEvents();
     13  makeProfileResettable();
     14 
     15  await SpecialPowers.pushPrefEnv({
     16    set: [["browser.urlbar.scotchBonnet.enableOverride", false]],
     17  });
     18 });
     19 
     20 // Tests the refresh tip.
     21 add_task(async function refresh() {
     22  // Pick the tip, which should open the refresh dialog.  Click its cancel
     23  // button.
     24  await checkIntervention({
     25    searchString: SEARCH_STRINGS.REFRESH,
     26    tip: UrlbarProviderInterventions.TIP_TYPE.REFRESH,
     27    title:
     28      "Restore default settings and remove old add-ons for optimal performance.",
     29    button: /^Refresh .+…$/,
     30    awaitCallback() {
     31      return BrowserTestUtils.promiseAlertDialog(
     32        "cancel",
     33        "chrome://global/content/resetProfile.xhtml",
     34        { isSubDialog: true }
     35      );
     36    },
     37  });
     38 });
     39 
     40 // Tests the clear tip.
     41 add_task(async function clear() {
     42  // Pick the tip, which should open the refresh dialog.  Click its cancel
     43  // button.
     44  let useOldClearHistoryDialog = Services.prefs.getBoolPref(
     45    "privacy.sanitize.useOldClearHistoryDialog"
     46  );
     47  let dialogURL = useOldClearHistoryDialog
     48    ? "chrome://browser/content/sanitize.xhtml"
     49    : "chrome://browser/content/sanitize_v2.xhtml";
     50  await checkIntervention({
     51    searchString: SEARCH_STRINGS.CLEAR,
     52    tip: UrlbarProviderInterventions.TIP_TYPE.CLEAR,
     53    title: "Clear your cache, cookies, history and more.",
     54    button: "Choose What to Clear…",
     55    awaitCallback() {
     56      return BrowserTestUtils.promiseAlertDialog("cancel", dialogURL, {
     57        isSubDialog: true,
     58      });
     59    },
     60  });
     61 });
     62 
     63 // Tests the clear tip in a private window. The clear tip shouldn't appear in
     64 // private windows.
     65 add_task(async function clear_private() {
     66  let win = await BrowserTestUtils.openNewBrowserWindow({ private: true });
     67  // First, make sure the extension works in PBM by triggering a non-clear
     68  // tip.
     69  let result = (await awaitTip(SEARCH_STRINGS.REFRESH, win))[0];
     70  Assert.strictEqual(
     71    result.payload.type,
     72    UrlbarProviderInterventions.TIP_TYPE.REFRESH
     73  );
     74 
     75  // Blur the urlbar so that the engagement is ended.
     76  await UrlbarTestUtils.promisePopupClose(win, () => win.gURLBar.blur());
     77 
     78  // Now do a search that would trigger the clear tip.
     79  await awaitNoTip(SEARCH_STRINGS.CLEAR, win);
     80 
     81  // Blur the urlbar so that the engagement is ended.
     82  await UrlbarTestUtils.promisePopupClose(win, () => win.gURLBar.blur());
     83 
     84  await BrowserTestUtils.closeWindow(win);
     85 });
     86 
     87 // Test the result of UrlbarProviderInterventions.isActive()
     88 // and whether or not the function calucates the score.
     89 add_task(async function testIsActive() {
     90  const testData = [
     91    {
     92      description: "Test for search string that activates the intervention",
     93      searchString: "firefox slow",
     94      expectedActive: true,
     95      expectedScoreCalculated: true,
     96    },
     97    {
     98      description:
     99        "Test for search string that does not activate the intervention",
    100      searchString: "example slow",
    101      expectedActive: false,
    102      expectedScoreCalculated: true,
    103    },
    104    {
    105      description: "Test for empty search string",
    106      searchString: "",
    107      expectedActive: false,
    108      expectedScoreCalculated: false,
    109    },
    110    {
    111      description: "Test for an URL",
    112      searchString: "https://firefox/slow",
    113      expectedActive: false,
    114      expectedScoreCalculated: false,
    115    },
    116    {
    117      description: "Test for a data URL",
    118      searchString: "data:text/html,<div>firefox slow</div>",
    119      expectedActive: false,
    120      expectedScoreCalculated: false,
    121    },
    122    {
    123      description: "Test for string like URL",
    124      searchString: "firefox://slow",
    125      expectedActive: false,
    126      expectedScoreCalculated: false,
    127    },
    128  ];
    129 
    130  let interventionsProviderInstance = UrlbarProvidersManager.getProvider(
    131    "UrlbarProviderInterventions"
    132  );
    133  // Mock the relevent method of Query so we don't have to start a real one.
    134  interventionsProviderInstance.queryInstance = {
    135    getProvider: name => UrlbarProvidersManager.getProvider(name),
    136  };
    137  for (const {
    138    description,
    139    searchString,
    140    expectedActive,
    141    expectedScoreCalculated,
    142  } of testData) {
    143    info(description);
    144 
    145    // Set null to currentTip to know whether or not UrlbarProviderInterventions
    146    // calculated the score.
    147    interventionsProviderInstance.currentTip = null;
    148 
    149    const isActive = await interventionsProviderInstance.isActive({
    150      searchString,
    151    });
    152    Assert.equal(isActive, expectedActive, "Result of isActive is correct");
    153    const isScoreCalculated = interventionsProviderInstance.currentTip !== null;
    154    Assert.equal(
    155      isScoreCalculated,
    156      expectedScoreCalculated,
    157      "The score is calculated correctly"
    158    );
    159  }
    160  interventionsProviderInstance.queryInstance = null;
    161 });
    162 
    163 add_task(async function tipsAreEnglishOnly() {
    164  // Test that Interventions are working in en-US.
    165  let result = (await awaitTip(SEARCH_STRINGS.REFRESH, window))[0];
    166  Assert.strictEqual(
    167    result.payload.type,
    168    UrlbarProviderInterventions.TIP_TYPE.REFRESH
    169  );
    170  await UrlbarTestUtils.promisePopupClose(window, () => gURLBar.blur());
    171 
    172  // We will need to fetch new engines when we switch locales.
    173  let enginesReloaded =
    174    SearchTestUtils.promiseSearchNotification("engines-reloaded");
    175 
    176  const originalAvailable = Services.locale.availableLocales;
    177  const originalRequested = Services.locale.requestedLocales;
    178  Services.locale.availableLocales = ["en-US", "de"];
    179  Services.locale.requestedLocales = ["de"];
    180 
    181  let cleanup = async () => {
    182    let reloadPromise =
    183      SearchTestUtils.promiseSearchNotification("engines-reloaded");
    184    Services.locale.requestedLocales = originalRequested;
    185    Services.locale.availableLocales = originalAvailable;
    186    await reloadPromise;
    187    cleanup = null;
    188  };
    189  registerCleanupFunction(() => cleanup?.());
    190 
    191  let appLocales = Services.locale.appLocalesAsBCP47;
    192  Assert.equal(appLocales[0], "de");
    193 
    194  await enginesReloaded;
    195 
    196  // Interventions should no longer work in the new locale.
    197  await awaitNoTip(SEARCH_STRINGS.CLEAR, window);
    198  await UrlbarTestUtils.promisePopupClose(window, () => gURLBar.blur());
    199 
    200  await cleanup();
    201 });
    202 
    203 // Tests the help command (using the clear intervention). It should open the
    204 // help page and it should not trigger the primary intervention behavior.
    205 add_task(async function pickHelp() {
    206  await BrowserTestUtils.withNewTab("about:blank", async () => {
    207    // Do a search that triggers the clear tip.
    208    let [result] = await awaitTip(SEARCH_STRINGS.CLEAR);
    209    Assert.strictEqual(
    210      result.payload.type,
    211      UrlbarProviderInterventions.TIP_TYPE.CLEAR
    212    );
    213 
    214    // Click the help command and wait for the help page to load.
    215    Assert.ok(
    216      !!result.payload.helpUrl,
    217      "The result's helpUrl should be defined and non-empty: " +
    218        JSON.stringify(result.payload.helpUrl)
    219    );
    220    let newTabOpened = BrowserTestUtils.waitForNewTab(
    221      gBrowser,
    222      result.payload.helpUrl
    223    );
    224    await UrlbarTestUtils.openResultMenuAndPressAccesskey(window, "h", {
    225      openByMouse: true,
    226      resultIndex: 1,
    227    });
    228    info("Waiting for help URL to load in the current tab");
    229    let newTab = await newTabOpened;
    230    await BrowserTestUtils.removeTab(newTab);
    231 
    232    // Wait a bit and make sure the clear recent history dialog did not open.
    233    // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
    234    await new Promise(r => setTimeout(r, 2000));
    235    Assert.strictEqual(gDialogBox.isOpen, false, "No dialog should be open");
    236  });
    237 });