tor-browser

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

browser_browsingContext-01.js (5432B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 const URL = "about:blank";
      7 
      8 async function getBrowsingContextId(browser, id) {
      9  return SpecialPowers.spawn(browser, [id], async function (id) {
     10    let contextId = content.window.docShell.browsingContext.id;
     11 
     12    let frames = [content.window];
     13    while (frames.length) {
     14      let frame = frames.pop();
     15      let target = frame.document.getElementById(id);
     16      if (target) {
     17        contextId = target.docShell.browsingContext.id;
     18        break;
     19      }
     20 
     21      frames = frames.concat(Array.from(frame.frames));
     22    }
     23 
     24    return contextId;
     25  });
     26 }
     27 
     28 async function addFrame(browser, id, parentId) {
     29  return SpecialPowers.spawn(
     30    browser,
     31    [{ parentId, id }],
     32    async function ({ parentId, id }) {
     33      let parent = null;
     34      if (parentId) {
     35        let frames = [content.window];
     36        while (frames.length) {
     37          let frame = frames.pop();
     38          let target = frame.document.getElementById(parentId);
     39          if (target) {
     40            parent = target.contentWindow.document.body;
     41            break;
     42          }
     43          frames = frames.concat(Array.from(frame.frames));
     44        }
     45      } else {
     46        parent = content.document.body;
     47      }
     48 
     49      let frame = await new Promise(resolve => {
     50        let frame = content.document.createElement("iframe");
     51        frame.id = id || "";
     52        frame.url = "about:blank";
     53        frame.onload = () => resolve(frame);
     54        parent.appendChild(frame);
     55      });
     56 
     57      return frame.contentWindow.docShell.browsingContext.id;
     58    }
     59  );
     60 }
     61 
     62 async function removeFrame(browser, id) {
     63  return SpecialPowers.spawn(browser, [id], async function (id) {
     64    let frames = [content.window];
     65    while (frames.length) {
     66      let frame = frames.pop();
     67      let target = frame.document.getElementById(id);
     68      if (target) {
     69        target.remove();
     70        break;
     71      }
     72 
     73      frames = frames.concat(Array.from(frame.frames));
     74    }
     75  });
     76 }
     77 
     78 function getBrowsingContextById(id) {
     79  return BrowsingContext.get(id);
     80 }
     81 
     82 add_task(async function () {
     83  await BrowserTestUtils.withNewTab(
     84    { gBrowser, url: URL },
     85    async function (browser) {
     86      let topId = await getBrowsingContextId(browser, "");
     87      let topContext = getBrowsingContextById(topId);
     88      isnot(topContext, null);
     89      is(topContext.parent, null);
     90      is(
     91        topId,
     92        browser.browsingContext.id,
     93        "<browser> has the correct browsingContext"
     94      );
     95      is(
     96        browser.browserId,
     97        topContext.browserId,
     98        "browsing context should have a correct <browser> id"
     99      );
    100 
    101      let id0 = await addFrame(browser, "frame0");
    102      let browsingContext0 = getBrowsingContextById(id0);
    103      isnot(browsingContext0, null);
    104      is(browsingContext0.parent, topContext);
    105 
    106      await removeFrame(browser, "frame0");
    107 
    108      is(topContext.children.indexOf(browsingContext0), -1);
    109 
    110      // TODO(farre): Handle browsingContext removal [see Bug 1486719].
    111      todo_isnot(browsingContext0.parent, topContext);
    112    }
    113  );
    114 });
    115 
    116 add_task(async function () {
    117  // If Fission is disabled, the pref is no-op.
    118  await SpecialPowers.pushPrefEnv({ set: [["fission.bfcacheInParent", true]] });
    119 
    120  await BrowserTestUtils.withNewTab(
    121    {
    122      gBrowser,
    123      url:
    124        getRootDirectory(gTestPath).replace(
    125          "chrome://mochitests/content",
    126          // eslint-disable-next-line @microsoft/sdl/no-insecure-url
    127          "http://example.com"
    128        ) + "dummy_page.html",
    129    },
    130    async function (browser) {
    131      let path = getRootDirectory(gTestPath).replace(
    132        "chrome://mochitests/content",
    133        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
    134        "http://example.com"
    135      );
    136      await SpecialPowers.spawn(browser, [path], async function (path) {
    137        var bc = new content.BroadcastChannel("browser_browsingContext");
    138        function waitForMessage(command) {
    139          let p = new Promise(resolve => {
    140            bc.addEventListener("message", e => resolve(e), { once: true });
    141          });
    142          command();
    143          return p;
    144        }
    145 
    146        // Open a new window and wait for the message.
    147        let e1 = await waitForMessage(_ =>
    148          content.window.open(path + "onpageshow_message.html", "", "noopener")
    149        );
    150 
    151        is(e1.data, "pageshow", "Got page show");
    152 
    153        let e2 = await waitForMessage(_ => bc.postMessage("createiframe"));
    154        is(e2.data.framesLength, 1, "Here we should have an iframe");
    155 
    156        let e3 = await waitForMessage(_ => bc.postMessage("nextpage"));
    157 
    158        is(e3.data.event, "load");
    159        is(e3.data.framesLength, 0, "Here there shouldn't be an iframe");
    160 
    161        // Return to the previous document. N.B. we expect to trigger
    162        // BFCache here, hence we wait for pageshow.
    163        let e4 = await waitForMessage(_ => bc.postMessage("back"));
    164 
    165        is(e4.data, "pageshow");
    166 
    167        let e5 = await waitForMessage(_ => bc.postMessage("queryframes"));
    168        is(e5.data.framesLength, 1, "And again there should be an iframe");
    169 
    170        is(e5.outerWindowId, e2.outerWindowId, "BF cache cached outer window");
    171        is(e5.browsingContextId, e2.browsingContextId, "BF cache cached BC");
    172 
    173        let e6 = await waitForMessage(_ => bc.postMessage("close"));
    174        is(e6.data, "closed");
    175 
    176        bc.close();
    177      });
    178    }
    179  );
    180 });