tor-browser

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

browser_mixed_content_auth_download.js (5276B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * https://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 ChromeUtils.defineESModuleGetters(this, {
      7  Downloads: "resource://gre/modules/Downloads.sys.mjs",
      8  DownloadsCommon:
      9    "moz-src:///browser/components/downloads/DownloadsCommon.sys.mjs",
     10 });
     11 
     12 const { PromptTestUtils } = ChromeUtils.importESModule(
     13  "resource://testing-common/PromptTestUtils.sys.mjs"
     14 );
     15 
     16 const downloadMonitoringView = {
     17  _listeners: [],
     18  onDownloadAdded(download) {
     19    for (let listener of this._listeners) {
     20      listener(download);
     21    }
     22    this._listeners = [];
     23  },
     24  waitForDownload(listener) {
     25    this._listeners.push(listener);
     26  },
     27 };
     28 
     29 let SECURE_BASE_URL =
     30  getRootDirectory(gTestPath).replace(
     31    "chrome://mochitests/content/",
     32    "https://example.com/"
     33  ) + "file_auth_download_page.html";
     34 
     35 /**
     36 * Waits until a download is triggered.
     37 * It waits until a prompt is shown,
     38 * saves and then accepts the dialog.
     39 *
     40 * @returns {Promise} Resolved once done.
     41 */
     42 
     43 function shouldTriggerDownload() {
     44  return new Promise(res => {
     45    downloadMonitoringView.waitForDownload(res);
     46  });
     47 }
     48 function shouldNotifyDownloadUI() {
     49  return new Promise(res => {
     50    downloadMonitoringView.waitForDownload(async aDownload => {
     51      let { error } = aDownload;
     52      if (
     53        error.becauseBlockedByReputationCheck &&
     54        error.reputationCheckVerdict == Downloads.Error.BLOCK_VERDICT_INSECURE
     55      ) {
     56        // It's an insecure Download, now Check that it has been cleaned up properly
     57        if ((await IOUtils.stat(aDownload.target.path)).size != 0) {
     58          throw new Error(`Download target is not empty!`);
     59        }
     60        if ((await IOUtils.stat(aDownload.target.path)).size != 0) {
     61          throw new Error(`Download partFile was not cleaned up properly`);
     62        }
     63        // Assert that the Referrer is present
     64        if (!aDownload.source.referrerInfo) {
     65          throw new Error("The Blocked download is missing the ReferrerInfo");
     66        }
     67 
     68        res(aDownload);
     69      } else {
     70        ok(false, "No error for download that was expected to error!");
     71      }
     72    });
     73  });
     74 }
     75 
     76 async function resetDownloads() {
     77  // Removes all downloads from the download List
     78  const types = new Set();
     79  let publicList = await Downloads.getList(Downloads.ALL);
     80  let downloads = await publicList.getAll();
     81  for (let download of downloads) {
     82    if (download.contentType) {
     83      types.add(download.contentType);
     84    }
     85    publicList.remove(download);
     86    await download.finalize(true);
     87  }
     88 }
     89 
     90 async function runTest(url, link, checkFunction, description) {
     91  await resetDownloads();
     92  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
     93  is(
     94    gBrowser.currentURI.schemeIs("https"),
     95    true,
     96    "Scheme of opened tab should be https"
     97  );
     98  info("Checking: " + description);
     99 
    100  let checkPromise = checkFunction();
    101  // Click the Link to trigger the download
    102  SpecialPowers.spawn(gBrowser.selectedBrowser, [link], contentLink => {
    103    content.document.getElementById(contentLink).click();
    104  });
    105  // Wait for the auth prompt, enter the login details and close the prompt
    106  await PromptTestUtils.handleNextPrompt(
    107    gBrowser.selectedBrowser,
    108    { modalType: Ci.nsIPrompt.MODAL_TYPE_TAB, promptType: "promptUserAndPass" },
    109    { buttonNumClick: 0, loginInput: "user", passwordInput: "pass" }
    110  );
    111  await checkPromise;
    112  ok(true, description);
    113  // Close download panel
    114  DownloadsPanel.hidePanel();
    115  is(DownloadsPanel.panel.state, "closed", "Panel should be closed");
    116  await BrowserTestUtils.removeTab(tab);
    117 }
    118 
    119 add_setup(async function () {
    120  let list = await Downloads.getList(Downloads.ALL);
    121  list.addView(downloadMonitoringView);
    122  registerCleanupFunction(() => list.removeView(downloadMonitoringView));
    123  // Ensure to delete all cached credentials before running test
    124  await new Promise(resolve => {
    125    Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, resolve);
    126  });
    127  await SpecialPowers.pushPrefEnv({
    128    set: [["dom.block_download_insecure", true]],
    129  });
    130 });
    131 //Test description:
    132 // 1. Open "https://example.com".
    133 // 2. From "https://example.com" download something, but that download is only available via http
    134 //    and with authentication.
    135 // 3. Login and start download.
    136 // 4. Mixed-content blocker blocks download.
    137 // 5. Unblock download and verify the downloaded file.
    138 add_task(async function test_auth_download() {
    139  await runTest(
    140    SECURE_BASE_URL,
    141    "insecure",
    142    async () => {
    143      let [, download] = await Promise.all([
    144        shouldTriggerDownload(),
    145        shouldNotifyDownloadUI(),
    146      ]);
    147      await download.unblock();
    148      Assert.equal(
    149        download.error,
    150        null,
    151        "There should be no error after unblocking"
    152      );
    153      info(
    154        "Start download to be able to validate the size and the success of the download"
    155      );
    156      await download.start();
    157      is(
    158        download.contentType,
    159        "text/html",
    160        "File contentType should be correct."
    161      );
    162      ok(download.succeeded, "Download succeeded!");
    163      is(download.target.size, 27, "Download has correct size");
    164    },
    165    "A locked Download from an auth server should succeeded to Download after a Manual unblock"
    166  );
    167 });