tor-browser

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

browser_inspector_fission_frame_navigation.js (5516B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 "use strict";
      4 
      5 const EXAMPLE_COM_URI =
      6  "https://example.com/document-builder.sjs?html=<div id=com>com";
      7 const EXAMPLE_NET_URI =
      8  "https://example.net/document-builder.sjs?html=<div id=net>net";
      9 
     10 const ORG_URL_ROOT = URL_ROOT.replace("example.com", "example.org");
     11 const TEST_ORG_URI =
     12  ORG_URL_ROOT + "doc_inspector_fission_frame_navigation.html";
     13 
     14 add_task(async function () {
     15  const { inspector } = await openInspectorForURL(TEST_ORG_URI);
     16  const tree = `
     17    id="root"
     18      iframe
     19        #document
     20          html
     21            head
     22            body
     23              id="org"`;
     24  // Note: the assertMarkupViewAsTree uses very high level APIs and is similar
     25  // to what should happen when a user interacts with the markup view.
     26  // It is important to avoid explicitly fetching walkers or node fronts during
     27  // the test, as it might cause reparenting of remote frames and make the test
     28  // succeed without actually testing that the feature works correctly.
     29  await assertMarkupViewAsTree(tree, "#root", inspector);
     30 
     31  await navigateIframeTo(inspector, EXAMPLE_COM_URI);
     32  const treeAfterLoadingCom = `
     33    id="root"
     34      iframe
     35        #document
     36          html
     37            head
     38            body
     39              id="com"`;
     40  await assertMarkupViewAsTree(treeAfterLoadingCom, "#root", inspector);
     41 
     42  await navigateIframeTo(inspector, EXAMPLE_NET_URI);
     43  const treeAfterLoadingNet = `
     44    id="root"
     45      iframe
     46        #document
     47          html
     48            head
     49            body
     50              id="net"`;
     51  await assertMarkupViewAsTree(treeAfterLoadingNet, "#root", inspector);
     52 });
     53 
     54 /**
     55 * This test will check the behavior when navigating a frame which is not
     56 * visible in the markup view, because its parentNode has not been expanded yet.
     57 *
     58 * We expect a root-node resource to be emitted, but ideally we should not
     59 * initialize the walker and inspector actors for the target of this root-node
     60 * resource.
     61 */
     62 add_task(async function navigateFrameNotExpandedInMarkupView() {
     63  const { inspector } = await openInspectorForURL(TEST_ORG_URI);
     64  const { resourceCommand } = inspector.commands;
     65 
     66  // At this stage the expected layout of the markup view is
     67  // v html     (expanded)
     68  //   v body   (expanded)
     69  //     > p    (collapsed)
     70  //     > div  (collapsed)
     71  //
     72  // The iframe we are about to navigate is therefore hidden and we are not
     73  // watching it - ie, it is not in the list of known NodeFronts/Actors.
     74  const resource = await navigateIframeTo(inspector, EXAMPLE_COM_URI);
     75 
     76  is(
     77    resource.resourceType,
     78    resourceCommand.TYPES.ROOT_NODE,
     79    "A resource with resourceType ROOT_NODE was received when navigating"
     80  );
     81 
     82  // This highlights what doesn't work with the current approach.
     83  // Since the root-node resource is a NodeFront watched via the WalkerFront,
     84  // watching it for a new remote frame target implies initializing the
     85  // inspector & walker fronts.
     86  //
     87  // If the resource was not a front (eg ContentDOMreference?) and was emitted
     88  // by the target actor instead of the walker actor, the client can decide if
     89  // the inspector and walker fronts should be initialized or not.
     90  //
     91  // In this test scenario, the children of the iframe were not known by the
     92  // inspector before this navigation. Per the explanation above, the new target
     93  // should not have an already instantiated inspector front.
     94  //
     95  // This should be fixed when implementing the RootNode resource on the server
     96  // in https://bugzilla.mozilla.org/show_bug.cgi?id=1644190
     97  todo(
     98    !resource.targetFront.getCachedFront("inspector"),
     99    "The inspector front for the new target should not be initialized"
    100  );
    101 });
    102 
    103 async function navigateIframeTo(inspector, url) {
    104  info("Navigate the test iframe to " + url);
    105 
    106  const { commands } = inspector;
    107  const { resourceCommand } = inspector.commands;
    108  const onTargetProcessed = waitForTargetProcessed(commands, url);
    109 
    110  const { onResource: onNewRoot } = await resourceCommand.waitForNextResource(
    111    resourceCommand.TYPES.ROOT_NODE,
    112    {
    113      ignoreExistingResources: true,
    114      predicate: resource => resource.targetFront.url === encodeURI(url),
    115    }
    116  );
    117 
    118  info("Update the src attribute of the iframe tag");
    119  await SpecialPowers.spawn(gBrowser.selectedBrowser, [url], function (_url) {
    120    content.document.querySelector("iframe").setAttribute("src", _url);
    121  });
    122 
    123  info("Wait for frameLoad/newRoot to resolve");
    124  const newRootResult = await onNewRoot;
    125 
    126  info("Wait for pending children updates");
    127  await inspector.markup._waitForChildren();
    128 
    129  info("Wait until the new target has been processed by TargetCommand");
    130  await onTargetProcessed;
    131 
    132  // Note: the newRootResult changes when the test runs with or without fission.
    133  return newRootResult;
    134 }
    135 
    136 /**
    137 * Returns a promise that waits until the provided commands's TargetCommand has fully
    138 * processed a target with the provided URL.
    139 * This will avoid navigating again before the new resource command  have fully
    140 * attached to the new target.
    141 */
    142 function waitForTargetProcessed(commands, url) {
    143  return new Promise(resolve => {
    144    const onTargetProcessed = targetFront => {
    145      if (targetFront.url !== encodeURI(url)) {
    146        return;
    147      }
    148      commands.targetCommand.off(
    149        "processed-available-target",
    150        onTargetProcessed
    151      );
    152      resolve();
    153    };
    154    commands.targetCommand.on("processed-available-target", onTargetProcessed);
    155  });
    156 }