tor-browser

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

iframe-document-preserve.window.js (5985B)


      1 // META: script=/common/get-host-info.sub.js
      2 
      3 promise_test(async t => {
      4  let iframeLoadCounter = 0;
      5  const div = document.createElement('div');
      6  const iframe = document.createElement('iframe');
      7  t.add_cleanup(() => iframe.remove());
      8 
      9  const loadPromise = new Promise((resolve) => {
     10    iframe.onload = () => {
     11      iframeLoadCounter++;
     12      resolve()
     13    };
     14  });
     15 
     16  div.append(iframe);
     17  document.body.append(div);
     18  await loadPromise;
     19  assert_equals(iframeLoadCounter, 1, "iframe loads");
     20 
     21  const innerDocument = iframe.contentDocument;
     22  assert_true(innerDocument !== null, "about:blank Document is reachable");
     23 
     24  iframe.onload = () => iframeLoadCounter++;
     25  await new Promise(resolve => t.step_timeout(resolve, 50));
     26  document.body.moveBefore(iframe, null);
     27  assert_equals(iframe.contentDocument, innerDocument, "Document is preserved");
     28  assert_equals(iframeLoadCounter, 1, "iframe does not reload");
     29 }, "moveBefore(): about:blank iframe's document is preserved");
     30 
     31 const kRemoveNewParent = 'remove new parent';
     32 const kRemoveSelf = 'remove self';
     33 const kRemoveSelfViaReplaceChildren = 'remove self via replaceChildren()';
     34 const kRemoveSelfViaInnerHTML = 'remove self via innerHTML';
     35 
     36 promise_test(async t => {
     37  const div = document.createElement('div');
     38  const iframe = document.createElement('iframe');
     39  t.add_cleanup(() => iframe.remove());
     40 
     41  const loadPromise = new Promise(resolve => iframe.onload = resolve);
     42  iframe.src = '/resources/blank.html';
     43 
     44  div.append(iframe);
     45  document.body.append(div);
     46  await loadPromise;
     47  const innerDocument = iframe.contentDocument;
     48 
     49  document.body.moveBefore(iframe, null);
     50  assert_equals(iframe.contentDocument, innerDocument, "Document is preserved");
     51 }, "moveBefore(): simple same-origin document is preserved");
     52 
     53 // This function runs the same test with a few variations. The meat of the test
     54 // loads a cross-origin iframe which asserts that it does not get reloaded.
     55 // Second, we remove the iframe from the parent document in a few different ways
     56 // to trigger initially crashy paths in Chromium during the implementation of
     57 // this feature.
     58 function runTest(removalType) {
     59  promise_test(async t => {
     60    let iframeLoadCounter = 0;
     61    const oldParent = document.createElement('div');
     62    const newParent = document.createElement('div');
     63    const iframe = document.createElement('iframe');
     64    iframe.onload = e => iframeLoadCounter++;
     65    switch (removalType) {
     66      case kRemoveNewParent:
     67        t.add_cleanup(() => newParent.remove());
     68        break;
     69      case kRemoveSelf:
     70        t.add_cleanup(() => iframe.remove());
     71        break;
     72      case kRemoveSelfViaReplaceChildren:
     73        t.add_cleanup(() => newParent.replaceChildren());
     74        break;
     75      case kRemoveSelfViaInnerHTML:
     76        t.add_cleanup(() => {newParent.innerHTML = '';});
     77        break;
     78    }
     79 
     80    const loadMessagePromise = new Promise(resolve => window.onmessage = resolve);
     81    const crossOriginIframeURL = new URL('resources/moveBefore-iframe.html',
     82        location.href.replace(self.origin, get_host_info().HTTP_REMOTE_ORIGIN));
     83    iframe.src = crossOriginIframeURL;
     84 
     85    oldParent.append(iframe);
     86    document.body.append(oldParent, newParent);
     87    const loadMessage = await loadMessagePromise;
     88    assert_equals(loadMessage.data, 'loaded');
     89 
     90    const messagePromise = new Promise(resolve => window.onmessage = resolve);
     91    newParent.moveBefore(iframe, null);
     92    iframe.contentWindow.postMessage("after moveBefore", "*");
     93    const message = await messagePromise;
     94    // If `moveBefore()` behaved just like `insertBefore()`, and reloaded the
     95    // document, then `message` would contain `loaded` instead of
     96    // `ack after moveBefore`.
     97    assert_equals(message.data, 'ack after moveBefore', 'Iframe did not load reload after moveBefore()');
     98    assert_equals(iframeLoadCounter, 1, "iframe does not fire a second load event");
     99  }, `moveBefore(): cross-origin iframe is preserved: ${removalType}`);
    100 }
    101 
    102 runTest(kRemoveNewParent);
    103 runTest(kRemoveSelf);
    104 runTest(kRemoveSelfViaReplaceChildren);
    105 runTest(kRemoveSelfViaInnerHTML);
    106 
    107 promise_test(async t => {
    108  const iframe1 = document.createElement('iframe');
    109  iframe1.name = 'iframe1';
    110  const iframe2 = document.createElement('iframe');
    111  iframe2.name = 'iframe2';
    112  const iframe3 = document.createElement('iframe');
    113  iframe3.name = 'iframe3';
    114 
    115  document.body.append(iframe1, iframe2, iframe3);
    116 
    117  // Assert that the order of iframes in the DOM matches the order of iframes in
    118  // `window.frames`.
    119  let iframes = document.querySelectorAll('iframe');
    120  assert_equals(iframes[0].name, "iframe1", "iframe1 comes first in DOM");
    121  assert_equals(iframes[1].name, "iframe2", "iframe2 comes second in DOM");
    122  assert_equals(iframes[2].name, "iframe3", "iframe3 comes last in DOM");
    123  assert_equals(window.frames[0].name, "iframe1", "iframe1 comes first in frames");
    124  assert_equals(window.frames[1].name, "iframe2", "iframe2 comes second in frames");
    125  assert_equals(window.frames[2].name, "iframe3", "iframe3 comes last in frames");
    126 
    127  // Reverse the order of iframes in the DOM.
    128  document.body.moveBefore(iframe2, iframe1);
    129  document.body.moveBefore(iframe3, iframe2);
    130 
    131  // Assert that the order of iframes in the DOM is inverse the order of iframes
    132  // in `window.frames`.
    133  iframes = document.querySelectorAll('iframe');
    134  assert_equals(iframes[0].name, "iframe3", "iframe3 comes first in DOM after moveBefore");
    135  assert_equals(iframes[1].name, "iframe2", "iframe2 comes second in DOM after moveBefore");
    136  assert_equals(iframes[2].name, "iframe1", "iframe1 comes last in DOM after moveBefore");
    137  assert_equals(window.frames[0].name, "iframe1", "iframe1 comes first in frames after moveBefore");
    138  assert_equals(window.frames[1].name, "iframe2", "iframe2 comes second in frames after moveBefore");
    139  assert_equals(window.frames[2].name, "iframe3", "iframe3 comes last in frames afterMoveBefore");
    140 }, "window.frames ordering does not change due to moveBefore()");