tor-browser

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

browser_persist_cross_origin_iframe.js (6001B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 const TEST_PATH = getRootDirectory(gTestPath).replace(
      7  "chrome://mochitests/content",
      8  "https://example.org"
      9 );
     10 const TEST_PATH2 = getRootDirectory(gTestPath).replace(
     11  "chrome://mochitests/content",
     12  "https://example.com"
     13 );
     14 
     15 var MockFilePicker = SpecialPowers.MockFilePicker;
     16 MockFilePicker.init(window.browsingContext);
     17 
     18 registerCleanupFunction(async function () {
     19  info("Running the cleanup code");
     20  MockFilePicker.cleanup();
     21  if (gTestDir && gTestDir.exists()) {
     22    // On Windows, sometimes nsIFile.remove() throws, probably because we're
     23    // still writing to the directory we're trying to remove, despite
     24    // waiting for the download to complete. Just retry a bit later...
     25    let succeeded = false;
     26    while (!succeeded) {
     27      try {
     28        gTestDir.remove(true);
     29        succeeded = true;
     30      } catch (ex) {
     31        await new Promise(requestAnimationFrame);
     32      }
     33    }
     34  }
     35 });
     36 
     37 let gTestDir = null;
     38 
     39 function createTemporarySaveDirectory() {
     40  var saveDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
     41  saveDir.append("testsavedir");
     42  if (!saveDir.exists()) {
     43    saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
     44  }
     45  return saveDir;
     46 }
     47 
     48 function canonicalizeExtension(str) {
     49  return str.replace(/\.htm$/, ".html");
     50 }
     51 
     52 function checkContents(dir, expected, str) {
     53  let stack = [dir];
     54  let files = [];
     55  while (stack.length) {
     56    for (let file of stack.pop().directoryEntries) {
     57      if (file.isDirectory()) {
     58        stack.push(file);
     59      }
     60 
     61      let path = canonicalizeExtension(file.getRelativePath(dir));
     62      files.push(path);
     63    }
     64  }
     65 
     66  SimpleTest.isDeeply(
     67    files.sort(),
     68    expected.sort(),
     69    str + "Should contain downloaded files in correct place."
     70  );
     71 }
     72 
     73 async function addFrame(browser, path, selector) {
     74  await SpecialPowers.spawn(
     75    browser,
     76    [path, selector],
     77    async function (path, selector) {
     78      let document = content.document;
     79      let target = document.querySelector(selector);
     80      if (content.HTMLIFrameElement.isInstance(target)) {
     81        document = target.contentDocument;
     82        target = document.body;
     83      }
     84      let element = document.createElement("iframe");
     85      element.src = path;
     86      await new Promise(resolve => {
     87        element.onload = resolve;
     88        target.appendChild(element);
     89      });
     90    }
     91  );
     92 }
     93 
     94 async function handleResult(expected, str) {
     95  let dls = await Downloads.getList(Downloads.PUBLIC);
     96  return new Promise((resolve, reject) => {
     97    dls.addView({
     98      onDownloadChanged(download) {
     99        if (download.succeeded) {
    100          checkContents(gTestDir, expected, str);
    101 
    102          dls.removeView(this);
    103          dls.removeFinished();
    104          resolve();
    105        } else if (download.error) {
    106          reject("Download failed");
    107        }
    108      },
    109    });
    110  });
    111 }
    112 
    113 add_task(async function () {
    114  await BrowserTestUtils.withNewTab(
    115    TEST_PATH + "image.html",
    116    async function (browser) {
    117      await addFrame(browser, TEST_PATH + "image.html", "body");
    118      await addFrame(browser, TEST_PATH2 + "image.html", "body>iframe");
    119 
    120      gTestDir = createTemporarySaveDirectory();
    121 
    122      MockFilePicker.displayDirectory = gTestDir;
    123      MockFilePicker.showCallback = function () {
    124        let destFile = gTestDir.clone();
    125        destFile.append("first.html");
    126        MockFilePicker.setFiles([destFile]);
    127        MockFilePicker.filterIndex = 0; // kSaveAsType_Complete
    128      };
    129 
    130      let expected = [
    131        "first.html",
    132        "first_files",
    133        "first_files/image.html",
    134        "first_files/dummy.png",
    135        "first_files/image_data",
    136        "first_files/image_data/image.html",
    137        "first_files/image_data/image_data",
    138        "first_files/image_data/image_data/dummy.png",
    139      ];
    140 
    141      // This saves the top-level document contained in `browser`
    142      saveBrowser(browser);
    143      await handleResult(expected, "Check toplevel: ");
    144 
    145      // Instead of deleting previously saved files, we update our list
    146      // of expected files for the next part of the test. To not clash
    147      // we make sure to save to a different file name.
    148      expected = expected.concat([
    149        "second.html",
    150        "second_files",
    151        "second_files/dummy.png",
    152        "second_files/image.html",
    153        "second_files/image_data",
    154        "second_files/image_data/dummy.png",
    155      ]);
    156 
    157      MockFilePicker.showCallback = function () {
    158        let destFile = gTestDir.clone();
    159        destFile.append("second.html");
    160        MockFilePicker.setFiles([destFile]);
    161        MockFilePicker.filterIndex = 0; // kSaveAsType_Complete
    162      };
    163 
    164      // This saves the sub-document of the iframe contained in the
    165      // top-level document, as indicated by passing a child browsing
    166      // context as target for the save.
    167      saveBrowser(browser, false, browser.browsingContext.children[0]);
    168      await handleResult(expected, "Check subframe: ");
    169 
    170      // Instead of deleting previously saved files, we update our list
    171      // of expected files for the next part of the test. To not clash
    172      // we make sure to save to a different file name.
    173      expected = expected.concat([
    174        "third.html",
    175        "third_files",
    176        "third_files/dummy.png",
    177      ]);
    178 
    179      MockFilePicker.showCallback = function () {
    180        let destFile = gTestDir.clone();
    181        destFile.append("third.html");
    182        MockFilePicker.setFiles([destFile]);
    183        MockFilePicker.filterIndex = 0; // kSaveAsType_Complete
    184      };
    185 
    186      // This saves the sub-document of the iframe contained in the
    187      // first sub-document, as indicated by passing a child browsing
    188      // context as target for the save. That frame is special, because
    189      // it's cross-process.
    190      saveBrowser(
    191        browser,
    192        false,
    193        browser.browsingContext.children[0].children[0]
    194      );
    195      await handleResult(expected, "Check subframe: ");
    196    }
    197  );
    198 });