tor-browser

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

browser_save_as.js (5660B)


      1 "use strict";
      2 
      3 Services.scriptloader.loadSubScript(
      4  "chrome://mochitests/content/browser/toolkit/content/tests/browser/common/mockTransfer.js",
      5  this
      6 );
      7 
      8 // Using insecure HTTP URL for a test cases around HTTP/HTTPS download interaction
      9 // eslint-disable-next-line @microsoft/sdl/no-insecure-url
     10 const HTTP_LINK = `http://example.org/`;
     11 const HTTPS_LINK = `https://example.org/`;
     12 const TEST_PATH =
     13  // eslint-disable-next-line @microsoft/sdl/no-insecure-url
     14  "http://example.com/browser/dom/security/test/https-only/file_save_as.html";
     15 
     16 let MockFilePicker = SpecialPowers.MockFilePicker;
     17 MockFilePicker.init(window.browsingContext);
     18 const tempDir = createTemporarySaveDirectory();
     19 MockFilePicker.displayDirectory = tempDir;
     20 
     21 add_setup(async function () {
     22  await SpecialPowers.pushPrefEnv({
     23    set: [["test.wait300msAfterTabSwitch", true]],
     24  });
     25 
     26  info("Setting MockFilePicker.");
     27  mockTransferRegisterer.register();
     28 
     29  registerCleanupFunction(function () {
     30    mockTransferRegisterer.unregister();
     31    MockFilePicker.cleanup();
     32    tempDir.remove(true);
     33  });
     34 });
     35 
     36 function createTemporarySaveDirectory() {
     37  let saveDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
     38  saveDir.append("testsavedir");
     39  saveDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
     40  return saveDir;
     41 }
     42 
     43 function createPromiseForObservingChannel(expectedUrl) {
     44  return new Promise(resolve => {
     45    let observer = (aSubject, aTopic) => {
     46      if (aTopic === "http-on-modify-request") {
     47        let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
     48 
     49        if (httpChannel.URI.spec != expectedUrl) {
     50          return;
     51        }
     52 
     53        Services.obs.removeObserver(observer, "http-on-modify-request");
     54        resolve();
     55      }
     56    };
     57 
     58    Services.obs.addObserver(observer, "http-on-modify-request");
     59  });
     60 }
     61 
     62 function createPromiseForTransferComplete() {
     63  return new Promise(resolve => {
     64    MockFilePicker.showCallback = fp => {
     65      info("MockFilePicker showCallback");
     66 
     67      let fileName = fp.defaultString;
     68      let destFile = tempDir.clone();
     69      destFile.append(fileName);
     70 
     71      MockFilePicker.setFiles([destFile]);
     72      MockFilePicker.filterIndex = 0; // kSaveAsType_Complete
     73 
     74      MockFilePicker.showCallback = null;
     75      mockTransferCallback = function (downloadSuccess) {
     76        ok(downloadSuccess, "File should have been downloaded successfully");
     77        mockTransferCallback = () => {};
     78        resolve();
     79      };
     80    };
     81  });
     82 }
     83 
     84 function createPromiseForConsoleError(message) {
     85  return new Promise(resolve => {
     86    function listener(msgObj) {
     87      let text = msgObj.message;
     88      if (text.includes(message)) {
     89        info(`Found occurence of '${message}'`);
     90        Services.console.unregisterListener(listener);
     91        resolve();
     92      }
     93    }
     94    Services.console.registerListener(listener);
     95  });
     96 }
     97 
     98 async function runTest(selector, expectedUrl, expectedError) {
     99  info(`Open a new tab for testing "Save link as" in context menu.`);
    100  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PATH);
    101 
    102  let popupShownPromise = BrowserTestUtils.waitForEvent(document, "popupshown");
    103 
    104  let browser = gBrowser.selectedBrowser;
    105 
    106  info("Open the context menu.");
    107  await BrowserTestUtils.synthesizeMouseAtCenter(
    108    selector,
    109    {
    110      type: "contextmenu",
    111      button: 2,
    112    },
    113    browser
    114  );
    115 
    116  await popupShownPromise;
    117 
    118  let downloadEndPromise = expectedError
    119    ? createPromiseForConsoleError(expectedError)
    120    : createPromiseForTransferComplete();
    121  let observerPromise = createPromiseForObservingChannel(expectedUrl);
    122 
    123  let contextMenu = document.getElementById("contentAreaContextMenu");
    124  let popupHiddenPromise = BrowserTestUtils.waitForEvent(
    125    contextMenu,
    126    "popuphidden"
    127  );
    128 
    129  // Select "Save As" option from context menu.
    130  let saveElement = document.getElementById(`context-savelink`);
    131  info("Triggering the save process.");
    132  contextMenu.activateItem(saveElement);
    133 
    134  info("Waiting for the channel.");
    135  await observerPromise;
    136 
    137  info(
    138    expectedError
    139      ? "Waiting for error in console."
    140      : "Wait until the save is finished."
    141  );
    142  await downloadEndPromise;
    143 
    144  info("Wait until the menu is closed.");
    145  await popupHiddenPromise;
    146 
    147  BrowserTestUtils.removeTab(tab);
    148 }
    149 
    150 async function setHttpsFirstAndOnlyPrefs(httpsFirst, httpsOnly) {
    151  await SpecialPowers.pushPrefEnv({
    152    set: [
    153      ["dom.security.https_first", httpsFirst],
    154      ["dom.security.https_only_mode", httpsOnly],
    155    ],
    156  });
    157 }
    158 
    159 add_task(async function testBaseline() {
    160  // Run with HTTPS-First and HTTPS-Only disabled
    161  await setHttpsFirstAndOnlyPrefs(false, false);
    162  await runTest("#insecure-link", HTTP_LINK, undefined);
    163  await runTest("#secure-link", HTTPS_LINK, undefined);
    164 });
    165 
    166 add_task(async function testHttpsFirst() {
    167  // Run with HTTPS-First enabled
    168  // The the user will get a warning about really wanting to download
    169  // from a insecure site, because we upgraded the top level document,
    170  // but the download is still insecure. In the future we also want to
    171  // upgrade these Save-As downloads.
    172  await setHttpsFirstAndOnlyPrefs(true, false);
    173  await runTest(
    174    "#insecure-link",
    175    HTTP_LINK,
    176    "Blocked downloading insecure content “http://example.org/”."
    177  );
    178  await runTest("#secure-link", HTTPS_LINK, undefined);
    179 });
    180 
    181 add_task(async function testHttpsOnly() {
    182  // Run with HTTPS-Only enabled
    183  // Should have same behaviour as HTTPS-First
    184  await setHttpsFirstAndOnlyPrefs(false, true);
    185  await runTest(
    186    "#insecure-link",
    187    HTTP_LINK,
    188    "Blocked downloading insecure content “http://example.org/”."
    189  );
    190  await runTest("#secure-link", HTTPS_LINK, undefined);
    191 });