tor-browser

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

test_find.html (8838B)


      1 <!doctype html>
      2 <meta charset="utf-8">
      3 <script src="/resources/testharness.js"></script>
      4 <script src="/resources/testharnessreport.js"></script>
      5 <body>
      6 <script>
      7 const t = async_test("Test window.find / nsFind");
      8 
      9 function testFindable(findCount, textToFind, buildDoc, description) {
     10  if (typeof findCount == "boolean")
     11    findCount = findCount ? 1 : 0;
     12  try {
     13    const iframe = document.querySelector("iframe")
     14    iframe.contentDocument.documentElement.innerHTML =
     15      (typeof buildDoc == "string") ? buildDoc : "";
     16 
     17    if (typeof buildDoc == "function")
     18      buildDoc(iframe.contentDocument);
     19 
     20    iframe.contentWindow.getSelection().removeAllRanges();
     21    for (let i = findCount; i >= 0; --i) {
     22      const expectFindable = i != 0;
     23      assert_equals(
     24        iframe.contentWindow.find(textToFind),
     25        expectFindable,
     26        "Should be " + (expectFindable ? "" : "not ") + "findable: " + description + ", text: " + textToFind + ", iter: " + (findCount - i + 1)
     27      );
     28    }
     29 
     30  } catch (ex) {
     31    assert_unreached(ex);
     32  }
     33 }
     34 
     35 const INLINE_LIKE_DISPLAY_VALUES = [
     36  "inline",
     37  "inline-grid",
     38  "inline-block",
     39  "inline-flex",
     40 ];
     41 
     42 const BLOCK_LIKE_DISPLAY_VALUES = [
     43  "block",
     44  "flex",
     45  "grid",
     46  "list-item",
     47  "table-column-group",
     48  "table-column",
     49  "table-footer-group",
     50  "table-header-group",
     51  "table-row-group",
     52  "table-row",
     53  "table",
     54 ];
     55 
     56 let runTests = t.step_func_done(function() {
     57  testFindable(true, "me and me", `
     58    me <div style="display: contents">and</div> me
     59  `, "display: contents");
     60 
     61  testFindable(true, "me me", `
     62    me <div style="display: none">and</div> me
     63  `, "display: none");
     64 
     65  testFindable(false, "me and me", `
     66    me <div style="display: none">and</div> me
     67  `, "display: none");
     68 
     69  for (const display of INLINE_LIKE_DISPLAY_VALUES) {
     70    testFindable(true, "me and me", `
     71      me <div style="display: ${display}">and</div> me
     72    `, "div display: " + display);
     73    testFindable(true, "me and me", `
     74      me <span style="display: ${display}">and</span> me
     75    `, "span display: " + display);
     76  }
     77 
     78  for (const display of BLOCK_LIKE_DISPLAY_VALUES) {
     79    testFindable(false, "me and me", `
     80      me <div style="display: ${display}">and</div> me
     81    `, "div display: " + display);
     82    testFindable(false, "me and me", `
     83      me <span style="display: ${display}">and</span> me
     84    `, "span display: " + display);
     85  }
     86 
     87  testFindable(false, "me and me", `
     88    me <fieldset>and</fieldset> me
     89  `);
     90 
     91  testFindable(true, "This text should be visible", `
     92    <div style="visibility: hidden">
     93      <div style="visibility: visible">
     94        This text should be visible
     95      </div>
     96    </div>
     97  `);
     98 
     99  testFindable(true, "This text should be visible", `
    100    <style>:root { overflow: hidden }</style>
    101    <div style="overflow: auto;">
    102      <div style="height: 300vh"></div>
    103      This text should be visible
    104    </div>
    105  `);
    106 
    107  testFindable(true, "foobar", `
    108    <body><script style="display: block;">foobar</` + `script></body>
    109  `);
    110 
    111 
    112  testFindable(true, "Shadow text", function(document) {
    113    let div = document.createElement("div");
    114    div.attachShadow({ mode: "open" }).innerHTML = `
    115      Wohoo, this is Shadow text, yay!
    116    `;
    117    document.documentElement.appendChild(div);
    118  }, "In Shadow DOM");
    119 
    120  testFindable(true, "Shadow text", function(document) {
    121    let div = document.createElement("div");
    122    div.appendChild(document.createTextNode(
    123      "Wohoo, this is Shadow text, yay!"
    124    ));
    125    div.attachShadow({ mode: "open" }).innerHTML = `<slot></slot>`;
    126    document.documentElement.appendChild(div);
    127  }, "Slotted content in Shadow DOM");
    128 
    129  // TODO(emilio): This should work in an ideal world.
    130  testFindable(false, "Shadow text", function(document) {
    131    let div = document.createElement("div");
    132    div.appendChild(document.createTextNode("text, yay!"));
    133    div.attachShadow({ mode: "open" }).innerHTML = `This is Shadow <slot></slot>`;
    134    document.documentElement.appendChild(div);
    135  }, "Mixed shadow and non-shadow text");
    136 
    137  testFindable(true, "Shadow", function(document) {
    138    document.documentElement.innerHTML = `
    139      Sources<span id="host"></span>
    140      <div>whatever</div>
    141    `;
    142    document.getElementById("host").attachShadow({ mode: "open" }).innerHTML = "Shadow text";
    143  }, "Test inside a shadow-root mid-match");
    144 
    145  testFindable(false, "Outside shadow", function(document) {
    146    document.documentElement.innerHTML = `
    147      Outside <div id="host"></div> shadow
    148    `;
    149    document.getElementById("host").attachShadow({ mode: "open" }).innerHTML = "inside shadow";
    150  }, "Block in different subtree");
    151 
    152  // NOTE(emilio): It is probably doable / worth changing this to return true,
    153  // maybe, by relaxing the security checks in the ranges nsFind returns or
    154  // such.
    155  //
    156  // See bug 1442466 / bug 1510485 / bug 1505887.
    157  testFindable(false, "foo", function(document) {
    158    let input = document.createElement("input");
    159    input.value = "foo";
    160    document.documentElement.appendChild(input);
    161  }, "Native anonymous content isn't exposed in window.find");
    162 
    163  // Same as above, but in this case the check is warranted, we shouldn't
    164  // expose this range.
    165  testFindable(false, "find me", `
    166    <style>div::before { content: "Do find me" }</style>
    167    <div></div>
    168  `, "Pseudo-element");
    169 
    170  // Same as above.
    171  testFindable(false, "find me", `
    172    <img alt="Do find me">
    173  `, "Image alt content");
    174 
    175  // Same as above.
    176  testFindable(false, "find me", `
    177    <input type="submit" value="Do find me">
    178  `, "Submit input value");
    179 
    180  testFindable(false, "\0", `
    181    &#0;
    182  `);
    183 
    184  testFindable(true, "\0", function(document) {
    185    document.documentElement.appendChild(document.createTextNode("\0"));
    186  }, "Inserted null characters are findable");
    187 
    188  testFindable(false, "ab", `a<br>b`, "<br> forces a break even if there's no whitespace in between");
    189 
    190  testFindable(true, "history.kafka", `
    191    <code>database.history&#8203;.kafka.bootstrap.servers</code>
    192  `, "ZWSP should be ignored");
    193 
    194  testFindable(2, " ", "a    b    c", "Collapsed whitespace");
    195 
    196  // TODO(emilio): This might be worth discussing in the spec. For now
    197  // hard-coding our implementation.
    198  testFindable(false, "find me", `
    199    Do you find <span inert>not findable</span> me?
    200  `, "boundary-crossing inert");
    201 
    202  testFindable(true, "hidden content", `
    203    <div hidden="until-found">This is hidden content</div>
    204  `, "hidden=until-found should be findable");
    205 
    206  testFindable(true, "details content", `
    207    <details>
    208      <summary>Click to expand</summary>
    209      <div>This is details content</div>
    210    </details>
    211  `, "closed details should be findable");
    212 
    213  promise_test(async function() {
    214    const iframe = document.querySelector("iframe");
    215    iframe.contentDocument.documentElement.innerHTML = `
    216      <div id="hidden" hidden="until-found">findable text</div>
    217    `;
    218 
    219    const beforematchPromise = new Promise(resolve => {
    220      iframe.contentDocument.getElementById("hidden").addEventListener("beforematch", () => {
    221        resolve();
    222      }, { once: true });
    223    });
    224 
    225    iframe.contentWindow.getSelection().removeAllRanges();
    226    const found = iframe.contentWindow.find("findable");
    227 
    228    assert_true(found, "Should find text in hidden=until-found");
    229 
    230    await beforematchPromise;
    231 
    232    await new Promise(resolve => iframe.contentWindow.requestAnimationFrame(resolve));
    233 
    234    const hiddenElement = iframe.contentDocument.getElementById("hidden");
    235    assert_equals(hiddenElement.hidden, false, "hidden attribute should be removed");
    236  }, "beforematch event fires and element is revealed for hidden=until-found");
    237 
    238  testFindable(false, "should not be found", `
    239    <style>#outer { content-visibility: hidden; }</style>
    240    <div id="outer">
    241      <div hidden="until-found">This should not be found</div>
    242    </div>
    243  `, "hidden=until-found inside content-visibility:hidden should not be findable");
    244 
    245  promise_test(async function() {
    246    const iframe = document.querySelector("iframe");
    247    iframe.contentDocument.documentElement.innerHTML = `
    248      <details id="details">
    249        <summary>Summary</summary>
    250        <div>Details text</div>
    251      </details>
    252    `;
    253 
    254    iframe.contentWindow.getSelection().removeAllRanges();
    255    const found = iframe.contentWindow.find("Details text");
    256 
    257    assert_true(found, "Should find text in closed details");
    258 
    259    await new Promise(resolve => iframe.contentWindow.requestAnimationFrame(resolve));
    260 
    261    const detailsElement = iframe.contentDocument.getElementById("details");
    262    assert_true(detailsElement.open, "details element should be opened after find");
    263  }, "details element is opened after find");
    264 });
    265 
    266 window.onload = function() {
    267  let iframe = document.createElement("iframe");
    268  iframe.onload = runTests;
    269  iframe.srcdoc = "<!doctype html><html></html>";
    270  document.body.appendChild(iframe);
    271 };
    272 </script>
    273 </body>