tor-browser

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

browser_reservedkey.js (10252B)


      1 add_task(async function test_reserved_shortcuts() {
      2  let keyset = document.createXULElement("keyset");
      3  let key1 = document.createXULElement("key");
      4  key1.setAttribute("id", "kt_reserved");
      5  key1.setAttribute("modifiers", "shift");
      6  key1.setAttribute("key", "O");
      7  key1.setAttribute("reserved", "true");
      8  key1.setAttribute("count", "0");
      9  key1.addEventListener("command", () => {
     10    let attribute = key1.getAttribute("count");
     11    key1.setAttribute("count", Number(attribute) + 1);
     12  });
     13 
     14  let key2 = document.createXULElement("key");
     15  key2.setAttribute("id", "kt_notreserved");
     16  key2.setAttribute("modifiers", "shift");
     17  key2.setAttribute("key", "P");
     18  key2.setAttribute("reserved", "false");
     19  key2.setAttribute("count", "0");
     20  key2.addEventListener("command", () => {
     21    let attribute = key2.getAttribute("count");
     22    key2.setAttribute("count", Number(attribute) + 1);
     23  });
     24 
     25  let key3 = document.createXULElement("key");
     26  key3.setAttribute("id", "kt_reserveddefault");
     27  key3.setAttribute("modifiers", "shift");
     28  key3.setAttribute("key", "Q");
     29  key3.setAttribute("count", "0");
     30  key3.addEventListener("command", () => {
     31    let attribute = key3.getAttribute("count");
     32    key3.setAttribute("count", Number(attribute) + 1);
     33  });
     34 
     35  keyset.appendChild(key1);
     36  keyset.appendChild(key2);
     37  keyset.appendChild(key3);
     38  let container = document.createXULElement("box");
     39  container.appendChild(keyset);
     40  document.documentElement.appendChild(container);
     41 
     42  const pageUrl =
     43    "data:text/html,<body onload='document.body.firstElementChild.focus();'><div onkeydown='event.preventDefault();' tabindex=0>Test</div></body>";
     44  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
     45 
     46  EventUtils.sendString("OPQ");
     47 
     48  is(
     49    document.getElementById("kt_reserved").getAttribute("count"),
     50    "1",
     51    "reserved='true' with preference off"
     52  );
     53  is(
     54    document.getElementById("kt_notreserved").getAttribute("count"),
     55    "0",
     56    "reserved='false' with preference off"
     57  );
     58  is(
     59    document.getElementById("kt_reserveddefault").getAttribute("count"),
     60    "0",
     61    "default reserved with preference off"
     62  );
     63 
     64  // Now try with reserved shortcut key handling enabled.
     65  await new Promise(resolve => {
     66    SpecialPowers.pushPrefEnv(
     67      { set: [["permissions.default.shortcuts", 2]] },
     68      resolve
     69    );
     70  });
     71 
     72  EventUtils.sendString("OPQ");
     73 
     74  is(
     75    document.getElementById("kt_reserved").getAttribute("count"),
     76    "2",
     77    "reserved='true' with preference on"
     78  );
     79  is(
     80    document.getElementById("kt_notreserved").getAttribute("count"),
     81    "0",
     82    "reserved='false' with preference on"
     83  );
     84  is(
     85    document.getElementById("kt_reserveddefault").getAttribute("count"),
     86    "1",
     87    "default reserved with preference on"
     88  );
     89 
     90  document.documentElement.removeChild(container);
     91 
     92  BrowserTestUtils.removeTab(tab);
     93 });
     94 
     95 // This test checks that Alt+<key> and F10 cannot be blocked when the preference is set.
     96 if (!navigator.platform.includes("Mac")) {
     97  add_task(async function test_accesskeys_menus() {
     98    await new Promise(resolve => {
     99      SpecialPowers.pushPrefEnv(
    100        { set: [["permissions.default.shortcuts", 2]] },
    101        resolve
    102      );
    103    });
    104 
    105    const uri =
    106      'data:text/html,<body onkeydown=\'if (event.key == "H" || event.key == "F10") event.preventDefault();\'>';
    107    let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, uri);
    108 
    109    // Pressing Alt+H should open the Help menu.
    110    let helpPopup = document.getElementById("menu_HelpPopup");
    111    let popupShown = BrowserTestUtils.waitForEvent(helpPopup, "popupshown");
    112    EventUtils.synthesizeKey("KEY_Alt", { type: "keydown" });
    113    EventUtils.synthesizeKey("h", { altKey: true });
    114    EventUtils.synthesizeKey("KEY_Alt", { type: "keyup" });
    115    await popupShown;
    116 
    117    ok(true, "Help menu opened");
    118 
    119    let popupHidden = BrowserTestUtils.waitForEvent(helpPopup, "popuphidden");
    120    helpPopup.hidePopup();
    121    await popupHidden;
    122 
    123    // Pressing F10 should focus the menubar. On Linux, the file menu should open, but on Windows,
    124    // pressing Down will open the file menu.
    125    let menubar = document.getElementById("main-menubar");
    126    let menubarActive = BrowserTestUtils.waitForEvent(
    127      menubar,
    128      "DOMMenuBarActive"
    129    );
    130    EventUtils.synthesizeKey("KEY_F10");
    131    await menubarActive;
    132 
    133    let filePopup = document.getElementById("menu_FilePopup");
    134    popupShown = BrowserTestUtils.waitForEvent(filePopup, "popupshown");
    135    if (navigator.platform.includes("Win")) {
    136      EventUtils.synthesizeKey("KEY_ArrowDown");
    137    }
    138    await popupShown;
    139 
    140    ok(true, "File menu opened");
    141 
    142    popupHidden = BrowserTestUtils.waitForEvent(filePopup, "popuphidden");
    143    filePopup.hidePopup();
    144    await popupHidden;
    145 
    146    BrowserTestUtils.removeTab(tab1);
    147  });
    148 }
    149 
    150 // There is a <key> element for Backspace and delete with reserved="false",
    151 // so make sure that it is not treated as a blocked shortcut key.
    152 add_task(async function test_backspace_delete() {
    153  await new Promise(resolve => {
    154    SpecialPowers.pushPrefEnv(
    155      { set: [["permissions.default.shortcuts", 2]] },
    156      resolve
    157    );
    158  });
    159 
    160  // The input field is autofocused. If this test fails, backspace can go back
    161  // in history so cancel the beforeunload event and adjust the field to make the test fail.
    162  const uri =
    163    'data:text/html,<body onbeforeunload=\'document.getElementById("field").value = "failed";\'>' +
    164    "<input id='field' value='something'></body>";
    165  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, uri);
    166 
    167  await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
    168    content.document.getElementById("field").focus();
    169 
    170    // Add a promise that resolves when the backspace key gets received
    171    // so we can ensure the key gets received before checking the result.
    172    content.keysPromise = new Promise(resolve => {
    173      content.addEventListener("keyup", event => {
    174        if (event.code == "Backspace") {
    175          resolve(content.document.getElementById("field").value);
    176        }
    177      });
    178    });
    179  });
    180 
    181  // Move the caret so backspace will delete the first character.
    182  EventUtils.synthesizeKey("KEY_ArrowRight", {});
    183  EventUtils.synthesizeKey("KEY_Backspace", {});
    184 
    185  let fieldValue = await SpecialPowers.spawn(
    186    tab.linkedBrowser,
    187    [],
    188    async function () {
    189      return content.keysPromise;
    190    }
    191  );
    192  is(fieldValue, "omething", "backspace not prevented");
    193 
    194  // now do the same thing for the delete key:
    195  await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
    196    content.document.getElementById("field").focus();
    197 
    198    // Add a promise that resolves when the backspace key gets received
    199    // so we can ensure the key gets received before checking the result.
    200    content.keysPromise = new Promise(resolve => {
    201      content.addEventListener("keyup", event => {
    202        if (event.code == "Delete") {
    203          resolve(content.document.getElementById("field").value);
    204        }
    205      });
    206    });
    207  });
    208 
    209  // Move the caret so backspace will delete the first character.
    210  EventUtils.synthesizeKey("KEY_Delete", {});
    211 
    212  fieldValue = await SpecialPowers.spawn(
    213    tab.linkedBrowser,
    214    [],
    215    async function () {
    216      return content.keysPromise;
    217    }
    218  );
    219  is(fieldValue, "mething", "delete not prevented");
    220 
    221  BrowserTestUtils.removeTab(tab);
    222 });
    223 
    224 // TODO: Make this to run on Windows too to have automated tests also there.
    225 if (
    226  navigator.platform.includes("Mac") ||
    227  navigator.platform.includes("Linux")
    228 ) {
    229  add_task(
    230    async function test_reserved_shortcuts_conflict_with_user_settings() {
    231      await new Promise(resolve => {
    232        SpecialPowers.pushPrefEnv(
    233          { set: [["test.events.async.enabled", true]] },
    234          resolve
    235        );
    236      });
    237 
    238      const keyset = document.createXULElement("keyset");
    239      const key = document.createXULElement("key");
    240      key.setAttribute("id", "conflict_with_known_native_key_binding");
    241      if (navigator.platform.includes("Mac")) {
    242        // Select to end of the paragraph
    243        key.setAttribute("modifiers", "ctrl,shift");
    244        key.setAttribute("key", "E");
    245      } else {
    246        // Select All
    247        key.setAttribute("modifiers", "ctrl");
    248        key.setAttribute("key", "a");
    249      }
    250      key.setAttribute("reserved", "true");
    251      key.setAttribute("count", "0");
    252      key.addEventListener("command", () => {
    253        const attribute = key.getAttribute("count");
    254        key.setAttribute("count", Number(attribute) + 1);
    255      });
    256 
    257      keyset.appendChild(key);
    258      const container = document.createXULElement("box");
    259      container.appendChild(keyset);
    260      document.documentElement.appendChild(container);
    261 
    262      const pageUrl =
    263        "data:text/html,<body onload='document.body.firstChild.focus(); getSelection().collapse(document.body.firstChild, 0)'><div contenteditable>Test</div></body>";
    264      const tab = await BrowserTestUtils.openNewForegroundTab(
    265        gBrowser,
    266        pageUrl
    267      );
    268 
    269      await SpecialPowers.spawn(
    270        tab.linkedBrowser,
    271        [key.getAttribute("key")],
    272        async function (aExpectedKeyValue) {
    273          content.promiseTestResult = new Promise(resolve => {
    274            content.addEventListener("keyup", event => {
    275              if (event.key.toLowerCase() == aExpectedKeyValue.toLowerCase()) {
    276                resolve(content.getSelection().getRangeAt(0).toString());
    277              }
    278            });
    279          });
    280        }
    281      );
    282 
    283      EventUtils.synthesizeKey(key.getAttribute("key"), {
    284        ctrlKey: key.getAttribute("modifiers").includes("ctrl"),
    285        shiftKey: key.getAttribute("modifiers").includes("shift"),
    286      });
    287 
    288      const selectedText = await SpecialPowers.spawn(
    289        tab.linkedBrowser,
    290        [],
    291        async function () {
    292          return content.promiseTestResult;
    293        }
    294      );
    295      is(
    296        selectedText,
    297        "Test",
    298        "The shortcut key should select all text in the editor"
    299      );
    300 
    301      is(
    302        key.getAttribute("count"),
    303        "0",
    304        "The reserved shortcut key should be consumed by the focused editor instead"
    305      );
    306 
    307      document.documentElement.removeChild(container);
    308 
    309      BrowserTestUtils.removeTab(tab);
    310    }
    311  );
    312 }