tor-browser

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

script-focus.https.html (6823B)


      1 <!DOCTYPE html>
      2 <title>Test Script-Based Focus for Fenced Frames</title>
      3 <script src="/resources/testharness.js"></script>
      4 <script src="/resources/testharnessreport.js"></script>
      5 <script src="/resources/testdriver.js"></script>
      6 <script src="/resources/testdriver-actions.js"></script>
      7 <script src="/resources/testdriver-vendor.js"></script>
      8 <script src="/common/utils.js"></script>
      9 <script src="resources/utils.js"></script>
     10 <script src="/common/dispatcher/dispatcher.js"></script>
     11 
     12 <script src="/common/get-host-info.sub.js"></script>
     13 
     14 <body>
     15 <script>
     16 async function AttemptButtonFocus(frame, expecting_focus) {
     17  await frame.execute(async (expecting_focus) => {
     18    const button = document.createElement("button");
     19    document.body.append(button);
     20    button.focus();
     21    assert_equals(document.activeElement == button, expecting_focus,
     22        "Button's focus should match expected focus");
     23  }, [expecting_focus]);
     24 }
     25 
     26 async function ClickOn(element, actions) {
     27  // Wait until the window size is initialized.
     28  while (window.innerWidth == 0) {
     29    await new Promise(resolve => requestAnimationFrame(resolve));
     30  }
     31  await actions.pointerMove(0, 0, {origin: element})
     32               .pointerDown()
     33               .pointerUp()
     34               .send();
     35 }
     36 
     37 async function SetupTest(click=true) {
     38  // Clean up any leftover frames from prior tests.
     39  document.querySelectorAll("fencedframe").forEach(e => {
     40    e.remove();
     41  })
     42 
     43  const actions = new test_driver.Actions();
     44 
     45  const frame = attachFencedFrameContext();
     46  const fencedframe_element = frame.element;
     47 
     48  if (click)
     49    await ClickOn(document.body, actions);
     50 
     51  return [actions, frame, fencedframe_element];
     52 }
     53 
     54 promise_test(async () => {
     55  const [actions, ff1, ff1_element] = await SetupTest(false);
     56 
     57  await ClickOn(ff1_element, actions);
     58  await AttemptButtonFocus(ff1, true);
     59 
     60  const button = document.createElement("button");
     61  document.body.append(button);
     62  button.focus();
     63  assert_true(document.activeElement == button,
     64      "The button should have focus");
     65  assert_false(navigator.userActivation.isActive,
     66      "Window should not have user activation");
     67 }, "An embedder can focus out of a fenced frame");
     68 
     69 promise_test(async () => {
     70  const [actions, frame, fencedframe_element] = await SetupTest();
     71 
     72  await AttemptButtonFocus(frame, false);
     73  await ClickOn(fencedframe_element, actions);
     74  await AttemptButtonFocus(frame, true);
     75 }, "Fenced frames can't pull script focus until getting user activation");
     76 
     77 promise_test(async t => {
     78  const [actions, frame, fencedframe_element] = await SetupTest();
     79 
     80  await ClickOn(fencedframe_element, actions);
     81  await ClickOn(document.body, actions);
     82 
     83  await AttemptButtonFocus(frame, true);
     84 
     85  // Give the browser time to receive the focus event before attempting
     86  // another focus.
     87  await t.step_timeout(async () => {await AttemptButtonFocus(frame, true);},
     88      500);
     89 }, "Focused fenced frames can move programmatic focus within frame");
     90 
     91 promise_test(async () => {
     92  const [actions, frame, fencedframe_element] = await SetupTest();
     93 
     94  await ClickOn(fencedframe_element, actions);
     95  await ClickOn(document.body, actions);
     96 
     97  // This will pull focus across a frame boundary and consume user activation.
     98  await AttemptButtonFocus(frame, true);
     99 
    100  await ClickOn(document.body, actions);
    101  await AttemptButtonFocus(frame, false);
    102 }, "Script focus into a fenced frame consumes user activation");
    103 
    104 promise_test(async () => {
    105  const [actions, ff1, ff1_element] = await SetupTest();
    106 
    107  const ff2 = attachFencedFrameContext();
    108  const ff2_element = ff2.element;
    109 
    110  await ClickOn(ff1_element, actions);
    111 
    112  await AttemptButtonFocus(ff1, true);
    113  await AttemptButtonFocus(ff2, false);
    114 }, "Another fenced frame cannot pull focus out of a focused fenced frame");
    115 
    116 promise_test(async () => {
    117  const [actions, ff1, ff1_element] = await SetupTest();
    118 
    119  await ClickOn(ff1_element, actions);
    120  await AttemptButtonFocus(ff1, true);
    121 
    122  await ff1.execute(async () => {
    123    const ff2 = attachFencedFrameContext();
    124 
    125    await ff2.execute(async () => {
    126      const button = document.createElement("button");
    127      document.body.append(button);
    128      button.focus();
    129      assert_false(document.activeElement == button,
    130          "The button should not have focus");
    131      assert_false(navigator.userActivation.isActive,
    132          "The fenced frame should not have user activation");
    133    });
    134  });
    135 }, "A fenced frame nested in another fenced frame cannot pull focus");
    136 
    137 promise_test(async () => {
    138  const [actions, ff1, ff1_element] = await SetupTest();
    139 
    140  await ClickOn(document.body, actions);
    141 
    142  const button = document.createElement("button");
    143  document.body.append(button);
    144  button.focus();
    145  assert_equals(document.activeElement, button,
    146      "The button in the main page should have focus.");
    147 
    148  await ff1.execute(async () => {
    149    assert_false(navigator.userActivation.isActive,
    150        "The fenced frame should not have user activation.");
    151    window.focus();
    152  });
    153 
    154  assert_equals(document.activeElement, button,
    155      "The button in the main page should still have focus.");
    156 }, "A fenced frame cannot pull window.focus() without user activation");
    157 
    158 promise_test(async () => {
    159  const [actions, ff1, ff1_element] = await SetupTest();
    160 
    161  await ClickOn(ff1_element, actions);
    162  await ClickOn(document.body, actions);
    163 
    164  const button = document.createElement("button");
    165  document.body.append(button);
    166  button.focus();
    167  assert_equals(document.activeElement, button,
    168      "The button should have focus.");
    169 
    170  await ff1.execute(async () => {
    171    assert_true(navigator.userActivation.isActive,
    172        "The fenced frame should have user activation.");
    173    window.focus();
    174    assert_false(navigator.userActivation.isActive,
    175        "The fenced frame's user activation should be consumed by the focus");
    176  });
    177 
    178  assert_equals(document.activeElement, document.body,
    179      "The main page's focus should be pulled away from the button.");
    180 }, "A fenced frame can pull window.focus() after user activation");
    181 
    182 promise_test(async () => {
    183  var actions = new test_driver.Actions();
    184 
    185  const frame = attachIFrameContext(
    186      {origin: get_host_info().HTTPS_REMOTE_ORIGIN});
    187  const iframe_element =
    188      document.body.getElementsByTagName('iframe')[0];
    189 
    190  await frame.execute(async () => {
    191    const button = document.createElement("button");
    192    document.body.append(button);
    193    button.focus();
    194    assert_equals(document.activeElement, button,
    195        "The button in the iframe should have focus.");
    196  }, [true]);
    197 
    198  const button = document.createElement("button");
    199  document.body.append(button);
    200  button.focus();
    201  assert_equals(document.activeElement, button,
    202      "The button in the main page should have focus.");
    203 }, "An cross-origin iframe can pull focus back and forth without activation");
    204 
    205 </script>
    206 </body>