tor-browser

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

dialog-focus-shadow.html (9866B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <title>dialog focus delegation</title>
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 <body>
      7 
      8 <!--
      9  We focus this one between each test, to ensure that for non-modal dialogs,
     10  if there is no focus delegate, it stays focused (instead of causing focus to reset to the body).
     11 -->
     12 <button id="focus-between-tests">Focus between tests</button>
     13 
     14 <dialog data-description="No autofocus, no delegatesFocus, no siblings">
     15  <template class="turn-into-shadow-tree">
     16    <button disabled>Non-focusable</button>
     17    <button>Focusable</button>
     18    <button disabled>Non-focusable</button>
     19  </template>
     20 </dialog>
     21 
     22 <dialog data-description="No autofocus, no delegatesFocus, sibling before">
     23  <button class="focus-me">Focusable</button>
     24  <template class="turn-into-shadow-tree">
     25    <button disabled>Non-focusable</button>
     26    <button>Focusable</button>
     27    <button disabled>Non-focusable</button>
     28  </template>
     29 </dialog>
     30 
     31 <dialog data-description="No autofocus, no delegatesFocus, sibling after">
     32  <template class="turn-into-shadow-tree">
     33    <button disabled>Non-focusable</button>
     34    <button>Focusable</button>
     35    <button disabled>Non-focusable</button>
     36  </template>
     37  <button class="focus-me">Focusable</button>
     38 </dialog>
     39 
     40 <dialog data-description="No autofocus, yes delegatesFocus, no siblings">
     41  <template class="turn-into-shadow-tree delegates-focus">
     42    <button disabled>Non-focusable</button>
     43    <button class="focus-me">Focusable</button>
     44    <button disabled>Non-focusable</button>
     45  </template>
     46 </dialog>
     47 
     48 <dialog data-description="No autofocus, yes delegatesFocus, sibling before">
     49  <button class="focus-me">Focusable</button>
     50  <template class="turn-into-shadow-tree delegates-focus">
     51    <button disabled>Non-focusable</button>
     52    <button>Focusable</button>
     53    <button disabled>Non-focusable</button>
     54  </template>
     55 </dialog>
     56 
     57 <dialog data-description="No autofocus, yes delegatesFocus, sibling after">
     58  <template class="turn-into-shadow-tree delegates-focus">
     59    <button disabled>Non-focusable</button>
     60    <button class="focus-me">Focusable</button>
     61    <button disabled>Non-focusable</button>
     62  </template>
     63  <button>Focusable</button>
     64 </dialog>
     65 
     66 <dialog data-description="Autofocus before, no delegatesFocus">
     67  <button autofocus class="focus-me">Focusable</button>
     68  <template class="turn-into-shadow-tree">
     69    <button disabled>Non-focusable</button>
     70    <button>Focusable</button>
     71    <button disabled>Non-focusable</button>
     72  </template>
     73 </dialog>
     74 
     75 <dialog data-description="Autofocus before, yes delegatesFocus">
     76  <button autofocus class="focus-me">Focusable</button>
     77  <template class="turn-into-shadow-tree delegates-focus">
     78    <button disabled>Non-focusable</button>
     79    <button>Focusable</button>
     80    <button disabled>Non-focusable</button>
     81  </template>
     82 </dialog>
     83 
     84 <dialog data-description="Autofocus after, no delegatesFocus">
     85  <template class="turn-into-shadow-tree">
     86    <button disabled>Non-focusable</button>
     87    <button>Focusable</button>
     88    <button disabled>Non-focusable</button>
     89  </template>
     90  <button autofocus class="focus-me">Focusable</button>
     91 </dialog>
     92 
     93 <dialog data-description="Autofocus after, yes delegatesFocus">
     94  <template class="turn-into-shadow-tree delegates-focus">
     95    <button disabled>Non-focusable</button>
     96    <button>Focusable</button>
     97    <button disabled>Non-focusable</button>
     98  </template>
     99  <button autofocus class="focus-me">Focusable</button>
    100 </dialog>
    101 
    102 <dialog data-description="Autofocus on shadow host, yes delegatesFocus, no siblings">
    103  <template class="turn-into-shadow-tree delegates-focus autofocus">
    104    <button disabled>Non-focusable</button>
    105    <button class="focus-me">Focusable</button>
    106    <button disabled>Non-focusable</button>
    107  </template>
    108 </dialog>
    109 
    110 <dialog data-description="Autofocus on shadow host, yes delegatesFocus, sibling before">
    111  <button>Focusable</button>
    112  <template class="turn-into-shadow-tree delegates-focus autofocus">
    113    <button disabled>Non-focusable</button>
    114    <button class="focus-me">Focusable</button>
    115    <button disabled>Non-focusable</button>
    116  </template>
    117 </dialog>
    118 
    119 <dialog data-description="Autofocus on shadow host, yes delegatesFocus, sibling after">
    120  <template class="turn-into-shadow-tree delegates-focus autofocus">
    121    <button disabled>Non-focusable</button>
    122    <button class="focus-me">Focusable</button>
    123    <button disabled>Non-focusable</button>
    124  </template>
    125  <button>Focusable</button>
    126 </dialog>
    127 
    128 <dialog data-description="Autofocus on shadow host, no delegatesFocus, no siblings">
    129  <template class="turn-into-shadow-tree autofocus">
    130    <button disabled>Non-focusable</button>
    131    <button>Focusable</button>
    132    <button disabled>Non-focusable</button>
    133  </template>
    134 </dialog>
    135 
    136 <dialog data-description="Autofocus on shadow host, no delegatesFocus, sibling before">
    137  <button class="focus-me">Focusable</button>
    138  <template class="turn-into-shadow-tree autofocus">
    139    <button disabled>Non-focusable</button>
    140    <button>Focusable</button>
    141    <button disabled>Non-focusable</button>
    142  </template>
    143 </dialog>
    144 
    145 <dialog data-description="Autofocus on shadow host, no delegatesFocus, sibling after">
    146  <template class="turn-into-shadow-tree autofocus">
    147    <button disabled>Non-focusable</button>
    148    <button>Focusable</button>
    149    <button disabled>Non-focusable</button>
    150  </template>
    151  <button class="focus-me">Focusable</button>
    152 </dialog>
    153 
    154 <dialog data-description="Autofocus inside shadow tree, yes delegatesFocus, no siblings">
    155  <template class="turn-into-shadow-tree delegates-focus">
    156    <button>Focusable</button>
    157    <button autofocus class="focus-me">Focusable</button>
    158    <button disabled>Non-focusable</button>
    159  </template>
    160 </dialog>
    161 
    162 <dialog data-description="Autofocus inside shadow tree, yes delegatesFocus, sibling before">
    163  <button class="focus-me">Focusable</button>
    164  <template class="turn-into-shadow-tree delegates-focus">
    165    <button>Focusable</button>
    166    <button autofocus>Focusable</button>
    167    <button disabled>Non-focusable</button>
    168  </template>
    169 </dialog>
    170 
    171 <dialog data-description="Autofocus inside shadow tree, yes delegatesFocus, sibling after">
    172  <template class="turn-into-shadow-tree delegates-focus">
    173    <button>Focusable</button>
    174    <button autofocus class="focus-me">Focusable</button>
    175    <button disabled>Non-focusable</button>
    176  </template>
    177  <button>Focusable</button>
    178 </dialog>
    179 
    180 <dialog data-description="Autofocus inside shadow tree, no delegatesFocus, no siblings">
    181  <template class="turn-into-shadow-tree">
    182    <button>Focusable</button>
    183    <button autofocus>Focusable</button>
    184    <button disabled>Non-focusable</button>
    185  </template>
    186 </dialog>
    187 
    188 <dialog data-description="Autofocus inside shadow tree, no delegatesFocus, sibling before">
    189  <button class="focus-me">Focusable</button>
    190  <template class="turn-into-shadow-tree">
    191    <button>Focusable</button>
    192    <button autofocus>Focusable</button>
    193    <button disabled>Non-focusable</button>
    194  </template>
    195 </dialog>
    196 
    197 <dialog data-description="Autofocus inside shadow tree, no delegatesFocus, sibling after">
    198  <template class="turn-into-shadow-tree">
    199    <button>Focusable</button>
    200    <button autofocus>Focusable</button>
    201    <button disabled>Non-focusable</button>
    202  </template>
    203  <button class="focus-me">Focusable</button>
    204 </dialog>
    205 
    206 <dialog data-description="Two shadow trees, both delegatesFocus, first tree doesn't have autofocus element, second does">
    207  <template class="turn-into-shadow-tree delegates-focus">
    208    <button disabled>Non-focusable</button>
    209    <button class="focus-me">Focusable</button>
    210    <button disabled>Non-focusable</button>
    211  </template>
    212  <template class="turn-into-shadow-tree delegates-focus">
    213    <button autofocus>Focusable</button>
    214  </template>
    215 </dialog>
    216 
    217 <dialog data-description="No autofocus, no delegatesFocus, slotted target">
    218  <template class="turn-into-shadow-tree">
    219    <button>Focusable</button>
    220    <slot></slot>
    221    <button>Focusable</button>
    222  </template>
    223  <button class="focus-me">Focusable</button>
    224 </dialog>
    225 
    226 <dialog data-description="Shadowroot on child, no autofocus, no delegatesFocus">
    227  <div>
    228    <template class="turn-into-shadow-tree">
    229      <button>Focusable</button>
    230    </template>
    231  </div>
    232  <button class="focus-me">Focusable</button>
    233 </dialog>
    234 
    235 <script>
    236 for (const template of document.querySelectorAll(".turn-into-shadow-tree")) {
    237  const div = document.createElement("div");
    238  div.attachShadow({ mode: "open", delegatesFocus: template.classList.contains("delegates-focus")  });
    239 
    240  if (template.classList.contains("autofocus")) {
    241    div.setAttribute("autofocus", true);
    242  }
    243  div.shadowRoot.append(template.content);
    244  template.replaceWith(div);
    245 }
    246 
    247 const focusBetweenTests = document.querySelector("#focus-between-tests");
    248 
    249 for (const dialog of document.querySelectorAll("dialog")) {
    250  for (const method of ["show", "showModal"]) {
    251    test(t => {
    252      focusBetweenTests.focus();
    253 
    254      dialog[method]();
    255      t.add_cleanup(() => dialog.close());
    256 
    257      const expectedFocusOutsideShadowTree = dialog.querySelector(".focus-me");
    258      if (expectedFocusOutsideShadowTree) {
    259        assert_equals(document.activeElement, expectedFocusOutsideShadowTree);
    260      } else {
    261        const shadowHost = dialog.querySelector("div");
    262        const expectedFocusInsideShadowTree = shadowHost.shadowRoot.querySelector(".focus-me");
    263        if (expectedFocusInsideShadowTree) {
    264          assert_equals(document.activeElement, shadowHost);
    265          assert_equals(shadowHost.shadowRoot.activeElement, expectedFocusInsideShadowTree);
    266        } else {
    267          // There is no focus delegate. The dialog element should be focused.
    268          assert_equals(document.activeElement, dialog);
    269        }
    270      }
    271    }, `${method}: ${dialog.dataset.description}`);
    272  }
    273 }
    274 </script>