tor-browser

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

head.js (23269B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 // This directory contains tests that check tips and interventions, and in
      5 // particular the update-related interventions.
      6 // We mock updates by using the test helpers in
      7 // toolkit/mozapps/update/tests/browser.
      8 
      9 "use strict";
     10 
     11 Services.scriptloader.loadSubScript(
     12  "chrome://mochitests/content/browser/toolkit/mozapps/update/tests/browser/head.js",
     13  this
     14 );
     15 
     16 ChromeUtils.defineESModuleGetters(this, {
     17  HttpServer: "resource://testing-common/httpd.sys.mjs",
     18  ResetProfile: "resource://gre/modules/ResetProfile.sys.mjs",
     19  TelemetryTestUtils: "resource://testing-common/TelemetryTestUtils.sys.mjs",
     20  UrlbarProviderInterventions:
     21    "moz-src:///browser/components/urlbar/UrlbarProviderInterventions.sys.mjs",
     22  UrlbarProvidersManager:
     23    "moz-src:///browser/components/urlbar/UrlbarProvidersManager.sys.mjs",
     24  UrlbarResult: "moz-src:///browser/components/urlbar/UrlbarResult.sys.mjs",
     25 });
     26 
     27 ChromeUtils.defineLazyGetter(this, "UrlbarTestUtils", () => {
     28  const { UrlbarTestUtils: module } = ChromeUtils.importESModule(
     29    "resource://testing-common/UrlbarTestUtils.sys.mjs"
     30  );
     31  module.init(this);
     32  return module;
     33 });
     34 
     35 ChromeUtils.defineLazyGetter(this, "SearchTestUtils", () => {
     36  const { SearchTestUtils: module } = ChromeUtils.importESModule(
     37    "resource://testing-common/SearchTestUtils.sys.mjs"
     38  );
     39  module.init(this);
     40  return module;
     41 });
     42 
     43 // For each intervention type, a search string that trigger the intervention.
     44 const SEARCH_STRINGS = {
     45  CLEAR: "firefox history",
     46  REFRESH: "firefox slow",
     47  UPDATE: "firefox update",
     48 };
     49 
     50 registerCleanupFunction(() => {
     51  // We need to reset the provider's appUpdater.status between tests so that
     52  // each test doesn't interfere with the next.
     53  UrlbarProviderInterventions.resetAppUpdater();
     54 });
     55 
     56 /**
     57 * Override our binary path so that the update lock doesn't think more than one
     58 * instance of this test is running.
     59 * This is a heavily pared down copy of the function in xpcshellUtilsAUS.js.
     60 */
     61 function adjustGeneralPaths() {
     62  let dirProvider = {
     63    getFile(aProp, aPersistent) {
     64      // Set the value of persistent to false so when this directory provider is
     65      // unregistered it will revert back to the original provider.
     66      aPersistent.value = false;
     67      // The sync manager only uses XRE_EXECUTABLE_FILE, so that's all we need
     68      // to override, we won't bother handling anything else.
     69      if (aProp == XRE_EXECUTABLE_FILE) {
     70        // The temp directory that the mochitest runner creates is unique per
     71        // test, so its path can serve to provide the unique key that the update
     72        // sync manager requires (it doesn't need for this to be the actual
     73        // path to any real file, it's only used as an opaque string).
     74        let tempPath = Services.env.get("MOZ_PROCESS_LOG");
     75        let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
     76        file.initWithPath(tempPath);
     77        return file;
     78      }
     79      return null;
     80    },
     81    QueryInterface: ChromeUtils.generateQI(["nsIDirectoryServiceProvider"]),
     82  };
     83 
     84  let ds = Services.dirsvc.QueryInterface(Ci.nsIDirectoryService);
     85  try {
     86    ds.QueryInterface(Ci.nsIProperties).undefine(XRE_EXECUTABLE_FILE);
     87  } catch (_ex) {
     88    // We only override one property, so we have nothing to do if that fails.
     89    return;
     90  }
     91  ds.registerProvider(dirProvider);
     92  registerCleanupFunction(() => {
     93    ds.unregisterProvider(dirProvider);
     94    // Reset the update lock once again so that we know the lock we're
     95    // interested in here will be closed properly (normally that happens during
     96    // XPCOM shutdown, but that isn't consistent during tests).
     97    let syncManager = Cc[
     98      "@mozilla.org/updates/update-sync-manager;1"
     99    ].getService(Ci.nsIUpdateSyncManager);
    100    syncManager.resetLock();
    101  });
    102 
    103  // Now that we've overridden the directory provider, the name of the update
    104  // lock needs to be changed to match the overridden path.
    105  let syncManager = Cc["@mozilla.org/updates/update-sync-manager;1"].getService(
    106    Ci.nsIUpdateSyncManager
    107  );
    108  syncManager.resetLock();
    109 }
    110 
    111 /**
    112 * Initializes a mock app update.  Adapted from runAboutDialogUpdateTest:
    113 * https://searchfox.org/mozilla-central/source/toolkit/mozapps/update/tests/browser/head.js
    114 *
    115 * @param {object} params
    116 *   See the files in toolkit/mozapps/update/tests/browser.
    117 */
    118 async function initUpdate(params) {
    119  Services.env.set("MOZ_TEST_SLOW_SKIP_UPDATE_STAGE", "1");
    120  await SpecialPowers.pushPrefEnv({
    121    set: [
    122      [PREF_APP_UPDATE_DISABLEDFORTESTING, false],
    123      [PREF_APP_UPDATE_URL_MANUAL, gDetailsURL],
    124    ],
    125  });
    126 
    127  adjustGeneralPaths();
    128  await setupTestUpdater();
    129 
    130  let queryString = params.queryString ? params.queryString : "";
    131  let updateURL =
    132    URL_HTTP_UPDATE_SJS +
    133    "?detailsURL=" +
    134    gDetailsURL +
    135    queryString +
    136    getVersionParams();
    137  if (params.backgroundUpdate) {
    138    setUpdateURL(updateURL);
    139    await gAUS.checkForBackgroundUpdates();
    140    if (params.continueFile) {
    141      await continueFileHandler(params.continueFile);
    142    }
    143    if (params.waitForUpdateState) {
    144      let whichUpdateFn =
    145        params.waitForUpdateState == STATE_DOWNLOADING
    146          ? "getDownloadingUpdate"
    147          : "getReadyUpdate";
    148      let update;
    149      await TestUtils.waitForCondition(
    150        async () => {
    151          update = await gUpdateManager[whichUpdateFn]();
    152          return update && update.state == params.waitForUpdateState;
    153        },
    154        "Waiting for update state: " + params.waitForUpdateState,
    155        undefined,
    156        200
    157      ).catch(e => {
    158        // Instead of throwing let the check below fail the test so the panel
    159        // ID and the expected panel ID is printed in the log.
    160        logTestInfo(e);
    161      });
    162      // Display the UI after the update state equals the expected value.
    163      Assert.equal(
    164        update.state,
    165        params.waitForUpdateState,
    166        "The update state value should equal " + params.waitForUpdateState
    167      );
    168    }
    169  } else {
    170    updateURL += "&slowUpdateCheck=1&useSlowDownloadMar=1";
    171    setUpdateURL(updateURL);
    172  }
    173 }
    174 
    175 /**
    176 * Performs steps in a mock update.  Adapted from runAboutDialogUpdateTest:
    177 * https://searchfox.org/mozilla-central/source/toolkit/mozapps/update/tests/browser/head.js
    178 *
    179 * @param {Array} steps
    180 *   See the files in toolkit/mozapps/update/tests/browser.
    181 */
    182 async function processUpdateSteps(steps) {
    183  for (let step of steps) {
    184    await processUpdateStep(step);
    185  }
    186 }
    187 
    188 /**
    189 * Performs a step in a mock update.  Adapted from runAboutDialogUpdateTest:
    190 * https://searchfox.org/mozilla-central/source/toolkit/mozapps/update/tests/browser/head.js
    191 *
    192 * @param {object} step
    193 *   See the files in toolkit/mozapps/update/tests/browser.
    194 */
    195 async function processUpdateStep(step) {
    196  if (typeof step == "function") {
    197    step();
    198    return;
    199  }
    200 
    201  const { panelId, checkActiveUpdate, continueFile, downloadInfo } = step;
    202 
    203  if (
    204    panelId == "downloading" &&
    205    gAUS.currentState == Ci.nsIApplicationUpdateService.STATE_IDLE
    206  ) {
    207    // Now that `AUS.downloadUpdate` is async, we start showing the
    208    // downloading panel while `AUS.downloadUpdate` is still resolving.
    209    // But the below checks assume that this resolution has already
    210    // happened. So we need to wait for things to actually resolve.
    211    await gAUS.stateTransition;
    212  }
    213 
    214  if (checkActiveUpdate) {
    215    let whichUpdateFn =
    216      checkActiveUpdate.state == STATE_DOWNLOADING
    217        ? "getDownloadingUpdate"
    218        : "getReadyUpdate";
    219    let update;
    220    await TestUtils.waitForCondition(async () => {
    221      update = await gUpdateManager[whichUpdateFn]();
    222      return update;
    223    }, "Waiting for active update");
    224    Assert.ok(!!update, "There should be an active update");
    225    Assert.equal(
    226      update.state,
    227      checkActiveUpdate.state,
    228      "The active update state should equal " + checkActiveUpdate.state
    229    );
    230  } else {
    231    Assert.ok(
    232      !(await gUpdateManager.getReadyUpdate()),
    233      "There should not be a ready update"
    234    );
    235    Assert.ok(
    236      !(await gUpdateManager.getDownloadingUpdate()),
    237      "There should not be a downloadingUpdate update"
    238    );
    239  }
    240 
    241  if (panelId == "downloading") {
    242    for (let i = 0; i < downloadInfo.length; ++i) {
    243      let data = downloadInfo[i];
    244      // The About Dialog tests always specify a continue file.
    245      await continueFileHandler(continueFile);
    246      let patch = getPatchOfType(
    247        data.patchType,
    248        await gUpdateManager.getDownloadingUpdate()
    249      );
    250      // The update is removed early when the last download fails so check
    251      // that there is a patch before proceeding.
    252      let isLastPatch = i == downloadInfo.length - 1;
    253      if (!isLastPatch || patch) {
    254        let resultName = data.bitsResult ? "bitsResult" : "internalResult";
    255        patch.QueryInterface(Ci.nsIWritablePropertyBag);
    256        await TestUtils.waitForCondition(
    257          () => patch.getProperty(resultName) == data[resultName],
    258          "Waiting for expected patch property " +
    259            resultName +
    260            " value: " +
    261            data[resultName],
    262          undefined,
    263          200
    264        ).catch(e => {
    265          // Instead of throwing let the check below fail the test so the
    266          // property value and the expected property value is printed in
    267          // the log.
    268          logTestInfo(e);
    269        });
    270        Assert.equal(
    271          patch.getProperty(resultName),
    272          data[resultName],
    273          "The patch property " +
    274            resultName +
    275            " value should equal " +
    276            data[resultName]
    277        );
    278      }
    279    }
    280  } else if (continueFile) {
    281    await continueFileHandler(continueFile);
    282  }
    283 }
    284 
    285 /**
    286 * Checks an intervention tip.  This works by starting a search that should
    287 * trigger a tip, picks the tip, and waits for the tip's action to happen.
    288 *
    289 * @param {object} options
    290 *   Options for the test
    291 * @param {string} options.searchString
    292 *   The search string.
    293 * @param {string} options.tip
    294 *   The expected tip type.
    295 * @param {string | RegExp} options.title
    296 *   The expected tip title.
    297 * @param {string | RegExp} options.button
    298 *   The expected button title.
    299 * @param {Function} options.awaitCallback
    300 *   A function that checks the tip's action.  Should return a promise (or be
    301 *   async).
    302 * @returns {object}
    303 *   The value returned from `awaitCallback`.
    304 */
    305 async function doUpdateTest({
    306  searchString,
    307  tip,
    308  title,
    309  button,
    310  awaitCallback,
    311 } = {}) {
    312  // Do a search that triggers the tip.
    313  let [result, element] = await awaitTip(searchString);
    314  Assert.strictEqual(result.payload.type, tip, "Tip type");
    315  await element.ownerDocument.l10n.translateFragment(element);
    316 
    317  let actualTitle = element._elements.get("title").textContent;
    318  if (typeof title == "string") {
    319    Assert.equal(actualTitle, title, "Title string");
    320  } else {
    321    // regexp
    322    Assert.ok(title.test(actualTitle), "Title regexp");
    323  }
    324 
    325  let actualButton = element._buttons.get("0").textContent;
    326  if (typeof button == "string") {
    327    Assert.equal(actualButton, button, "Button string");
    328  } else {
    329    // regexp
    330    Assert.ok(button.test(actualButton), "Button regexp");
    331  }
    332 
    333  Assert.ok(element._buttons.has("result-menu"), "Tip has a menu button");
    334 
    335  // Pick the tip and wait for the action.
    336  let values = await Promise.all([awaitCallback(), pickTip()]);
    337 
    338  return values[0] || null;
    339 }
    340 
    341 /**
    342 * Starts a search and asserts that the second result is a tip.
    343 *
    344 * @param {string} searchString
    345 *   The search string.
    346 * @param {window} win
    347 *   The window.
    348 * @returns {(result| element)[]}
    349 *   The result and its element in the DOM.
    350 */
    351 async function awaitTip(searchString, win = window) {
    352  let context = await UrlbarTestUtils.promiseAutocompleteResultPopup({
    353    window: win,
    354    value: searchString,
    355    waitForFocus,
    356    fireInputEvent: true,
    357  });
    358  Assert.greaterOrEqual(
    359    context.results.length,
    360    2,
    361    "Number of results is greater than or equal to 2"
    362  );
    363  let result = context.results[1];
    364  Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.TIP, "Result type");
    365  let element = await UrlbarTestUtils.waitForAutocompleteResultAt(win, 1);
    366  return [result, element];
    367 }
    368 
    369 /**
    370 * Picks the current tip's button.  The view should be open and the second
    371 * result should be a tip.
    372 */
    373 async function pickTip() {
    374  let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
    375  let button = result.element.row._buttons.get("0");
    376  await UrlbarTestUtils.promisePopupClose(window, () => {
    377    EventUtils.synthesizeMouseAtCenter(button, {});
    378  });
    379 }
    380 
    381 /**
    382 * Waits for the quit-application-requested notification and cancels it (so that
    383 * the app isn't actually restarted).
    384 */
    385 async function awaitAppRestartRequest() {
    386  await TestUtils.topicObserved(
    387    "quit-application-requested",
    388    (cancelQuit, data) => {
    389      if (data == "restart") {
    390        cancelQuit.QueryInterface(Ci.nsISupportsPRBool).data = true;
    391        return true;
    392      }
    393      return false;
    394    }
    395  );
    396 }
    397 
    398 /**
    399 * Sets up the profile so that it can be reset.
    400 */
    401 function makeProfileResettable() {
    402  // Make reset possible.
    403  let profileService = Cc["@mozilla.org/toolkit/profile-service;1"].getService(
    404    Ci.nsIToolkitProfileService
    405  );
    406  let currentProfileDir = Services.dirsvc.get("ProfD", Ci.nsIFile);
    407  let profileName = "mochitest-test-profile-temp-" + Date.now();
    408  let tempProfile = profileService.createProfile(
    409    currentProfileDir,
    410    profileName
    411  );
    412  Assert.ok(
    413    ResetProfile.resetSupported(),
    414    "Should be able to reset from mochitest's temporary profile once it's in the profile manager."
    415  );
    416 
    417  registerCleanupFunction(() => {
    418    tempProfile.remove(false);
    419    Assert.ok(
    420      !ResetProfile.resetSupported(),
    421      "Shouldn't be able to reset from mochitest's temporary profile once removed from the profile manager."
    422    );
    423  });
    424 }
    425 
    426 /**
    427 * Starts a search that should trigger a tip, picks the tip, and waits for the
    428 * tip's action to happen.
    429 *
    430 * @param {object} options
    431 *   Options for the test
    432 * @param {string} options.searchString
    433 *   The search string.
    434 * @param {TIPS} options.tip
    435 *   The expected tip type.
    436 * @param {string} options.title
    437 *   The expected tip title.
    438 * @param {string} options.button
    439 *   The expected button title.
    440 * @param {Function} options.awaitCallback
    441 *   A function that checks the tip's action.  Should return a promise (or be
    442 *   async).
    443 * @returns {*}
    444 *   The value returned from `awaitCallback`.
    445 */
    446 function checkIntervention({
    447  searchString,
    448  tip,
    449  title,
    450  button,
    451  awaitCallback,
    452 } = {}) {
    453  // Opening modal dialogs confuses focus on Linux just after them, thus run
    454  // these checks in separate tabs to better isolate them.
    455  return BrowserTestUtils.withNewTab("about:blank", async () => {
    456    // Do a search that triggers the tip.
    457    let [result, element] = await awaitTip(searchString);
    458    Assert.strictEqual(result.payload.type, tip);
    459    await element.ownerDocument.l10n.translateFragment(element);
    460 
    461    let actualTitle = element._elements.get("title").textContent;
    462    if (typeof title == "string") {
    463      Assert.equal(actualTitle, title, "Title string");
    464    } else {
    465      // regexp
    466      Assert.ok(title.test(actualTitle), "Title regexp");
    467    }
    468 
    469    let actualButton = element._buttons.get("0").textContent;
    470    if (typeof button == "string") {
    471      Assert.equal(actualButton, button, "Button string");
    472    } else {
    473      // regexp
    474      Assert.ok(button.test(actualButton), "Button regexp");
    475    }
    476 
    477    let menuButton = element._buttons.get("result-menu");
    478    Assert.ok(menuButton, "Menu button exists");
    479    Assert.ok(BrowserTestUtils.isVisible(menuButton), "Menu button is visible");
    480 
    481    let values = await Promise.all([awaitCallback(), pickTip()]);
    482    Assert.ok(true, "Refresh dialog opened");
    483 
    484    // Ensure the urlbar is closed so that the engagement is ended.
    485    await UrlbarTestUtils.promisePopupClose(window, () => gURLBar.blur());
    486 
    487    return values[0] || null;
    488  });
    489 }
    490 
    491 /**
    492 * Starts a search and asserts that there are no tips.
    493 *
    494 * @param {string} searchString
    495 *   The search string.
    496 * @param {Window} win
    497 *   The host window.
    498 */
    499 async function awaitNoTip(searchString, win = window) {
    500  let context = await UrlbarTestUtils.promiseAutocompleteResultPopup({
    501    window: win,
    502    value: searchString,
    503    waitForFocus,
    504    fireInputEvent: true,
    505  });
    506  for (let result of context.results) {
    507    Assert.notEqual(result.type, UrlbarUtils.RESULT_TYPE.TIP);
    508  }
    509 }
    510 
    511 /**
    512 * Search tips helper.  Asserts that a particular search tip is shown or that no
    513 * search tip is shown.
    514 *
    515 * @param {window} win
    516 *   A browser window.
    517 * @param {UrlbarProviderSearchTips.TIP_TYPE} expectedTip
    518 *   The expected search tip.  Pass a falsey value (like zero) for none.
    519 * @param {boolean} closeView
    520 *   If true, this function closes the urlbar view before returning.
    521 */
    522 async function checkTip(win, expectedTip, closeView = true) {
    523  if (!expectedTip) {
    524    // Wait a bit for the tip to not show up.
    525    // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
    526    await new Promise(resolve => setTimeout(resolve, 100));
    527    Assert.ok(!win.gURLBar.view.isOpen, "View is not open");
    528    return;
    529  }
    530 
    531  // Wait for the view to open, and then check the tip result.
    532  await UrlbarTestUtils.promisePopupOpen(win, () => {});
    533  Assert.ok(true, "View opened");
    534  Assert.equal(UrlbarTestUtils.getResultCount(win), 1, "Number of results");
    535  let result = await UrlbarTestUtils.getDetailsOfResultAt(win, 0);
    536  Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.TIP, "Result type");
    537  let heuristic;
    538  let title;
    539  let name = Services.search.defaultEngine.name;
    540  switch (expectedTip) {
    541    case UrlbarProviderSearchTips.TIP_TYPE.ONBOARD:
    542      heuristic = true;
    543      title =
    544        `Type less, find more: Search ${name} right from your ` +
    545        `address bar.`;
    546      break;
    547    case UrlbarProviderSearchTips.TIP_TYPE.REDIRECT:
    548      heuristic = false;
    549      title =
    550        `Start your search in the address bar to see suggestions from ` +
    551        `${name} and your browsing history.`;
    552      break;
    553  }
    554  Assert.equal(result.heuristic, heuristic, "Result is heuristic");
    555  Assert.equal(result.displayed.title, title, "Title");
    556  Assert.equal(
    557    result.element.row._buttons.get("0").textContent,
    558    "Okay, Got It",
    559    "Button text"
    560  );
    561  Assert.ok(
    562    !result.element.row._buttons.has("help"),
    563    "Buttons in row does not include help"
    564  );
    565 
    566  Assert.ok(
    567    !UrlbarTestUtils.getOneOffSearchButtonsVisible(window),
    568    "One-offs should be hidden when showing a search tip"
    569  );
    570 
    571  if (closeView) {
    572    await UrlbarTestUtils.promisePopupClose(win);
    573  }
    574 }
    575 
    576 function makeTipResult({
    577  buttonUrl,
    578  helpUrl = undefined,
    579  descriptionL10n = undefined,
    580  descriptionLearnMoreTopic = undefined,
    581 }) {
    582  return new UrlbarResult({
    583    type: UrlbarUtils.RESULT_TYPE.TIP,
    584    source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    585    payload: {
    586      helpUrl,
    587      descriptionL10n,
    588      descriptionLearnMoreTopic,
    589      type: "test",
    590      titleL10n: { id: "urlbar-search-tips-confirm" },
    591      buttons: [
    592        {
    593          url: buttonUrl,
    594          l10n: { id: "urlbar-search-tips-confirm" },
    595        },
    596      ],
    597    },
    598  });
    599 }
    600 
    601 /**
    602 * Search tips helper.  Opens a foreground tab and asserts that a particular
    603 * search tip is shown or that no search tip is shown.
    604 *
    605 * @param {window} win
    606 *   A browser window.
    607 * @param {string} url
    608 *   The URL to load in a new foreground tab.
    609 * @param {UrlbarProviderSearchTips.TIP_TYPE} expectedTip
    610 *   The expected search tip.  Pass a falsey value (like zero) for none.
    611 * @param {boolean} reset
    612 *   If true, the search tips provider will be reset before this function
    613 *   returns.  See resetSearchTipsProvider.
    614 */
    615 async function checkTab(win, url, expectedTip, reset = true) {
    616  // BrowserTestUtils.withNewTab always waits for tab load, which hangs on
    617  // about:newtab for some reason, so don't use it.
    618  let shownCount;
    619  if (expectedTip) {
    620    shownCount = UrlbarPrefs.get(`tipShownCount.${expectedTip}`);
    621  }
    622 
    623  let tab = await BrowserTestUtils.openNewForegroundTab({
    624    gBrowser: win.gBrowser,
    625    url,
    626    waitForLoad: url != "about:newtab",
    627  });
    628 
    629  await checkTip(win, expectedTip, true);
    630  if (expectedTip) {
    631    Assert.equal(
    632      UrlbarPrefs.get(`tipShownCount.${expectedTip}`),
    633      shownCount + 1,
    634      "The shownCount pref should have been incremented by one."
    635    );
    636  }
    637 
    638  if (reset) {
    639    resetSearchTipsProvider();
    640  }
    641 
    642  BrowserTestUtils.removeTab(tab);
    643 }
    644 
    645 /**
    646 * This lets us visit www.google.com (for example) and have it redirect to
    647 * our test HTTP server instead of visiting the actual site.
    648 *
    649 * @param {string} domain
    650 *   The domain to which we are redirecting.
    651 * @param {string} path
    652 *   The pathname on the domain.
    653 * @param {Function} callback
    654 *   Executed when the test suite thinks `domain` is loaded.
    655 */
    656 async function withDNSRedirect(domain, path, callback) {
    657  // Some domains have special security requirements, like www.bing.com.  We
    658  // need to override them to successfully load them.  This part is adapted from
    659  // testing/marionette/cert.js.
    660  const certOverrideService = Cc[
    661    "@mozilla.org/security/certoverride;1"
    662  ].getService(Ci.nsICertOverrideService);
    663  Services.prefs.setBoolPref(
    664    "network.stricttransportsecurity.preloadlist",
    665    false
    666  );
    667  Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 0);
    668  certOverrideService.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(
    669    true
    670  );
    671 
    672  // Now set network.dns.localDomains to redirect the domain to localhost and
    673  // set up an HTTP server.
    674  Services.prefs.setCharPref("network.dns.localDomains", domain);
    675 
    676  let server = new HttpServer();
    677  server.registerPathHandler(path, (req, resp) => {
    678    resp.write(`Test! http://${domain}${path}`);
    679  });
    680  server.start(-1);
    681  server.identity.setPrimary("http", domain, server.identity.primaryPort);
    682  let url = `http://${domain}:${server.identity.primaryPort}${path}`;
    683 
    684  await callback(url);
    685 
    686  // Reset network.dns.localDomains and stop the server.
    687  Services.prefs.clearUserPref("network.dns.localDomains");
    688  await new Promise(resolve => server.stop(resolve));
    689 
    690  // Reset the security stuff.
    691  certOverrideService.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(
    692    false
    693  );
    694  Services.prefs.clearUserPref("network.stricttransportsecurity.preloadlist");
    695  Services.prefs.clearUserPref("security.cert_pinning.enforcement_level");
    696  const sss = Cc["@mozilla.org/ssservice;1"].getService(
    697    Ci.nsISiteSecurityService
    698  );
    699  sss.clearAll();
    700 }
    701 
    702 function resetSearchTipsProvider() {
    703  Services.prefs.clearUserPref(
    704    `browser.urlbar.tipShownCount.${UrlbarProviderSearchTips.TIP_TYPE.ONBOARD}`
    705  );
    706  Services.prefs.clearUserPref(
    707    `browser.urlbar.tipShownCount.${UrlbarProviderSearchTips.TIP_TYPE.REDIRECT}`
    708  );
    709  UrlbarProvidersManager.getProvider(
    710    "UrlbarProviderSearchTips"
    711  ).disableTipsForCurrentSession = false;
    712 }
    713 
    714 async function setDefaultEngine(name) {
    715  let engine = (await Services.search.getEngines()).find(e => e.name == name);
    716  Assert.ok(engine);
    717  await Services.search.setDefault(
    718    engine,
    719    Ci.nsISearchService.CHANGE_REASON_UNKNOWN
    720  );
    721 }