add_task(async function test_reserved_shortcuts() {
  /* eslint-disable no-unsanitized/property */
  let keyset = `<keyset>
                  <key id='kt_reserved' modifiers='shift' key='O' reserved='true' count='0'
                       oncommand='this.setAttribute("count", Number(this.getAttribute("count")) + 1)'/>
                  <key id='kt_notreserved' modifiers='shift' key='P' reserved='false' count='0'
                       oncommand='this.setAttribute("count", Number(this.getAttribute("count")) + 1)'/>
                  <key id='kt_reserveddefault' modifiers='shift' key='Q' count='0'
                       oncommand='this.setAttribute("count", Number(this.getAttribute("count")) + 1)'/>
                </keyset>`;

  let container = document.createElement("box");
  container.innerHTML = keyset;
  document.documentElement.appendChild(container);
  /* eslint-enable no-unsanitized/property */

  const pageUrl = "data:text/html,<body onload='document.body.firstChild.focus();'><div onkeydown='event.preventDefault();' tabindex=0>Test</div></body>";
  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);

  EventUtils.synthesizeKey("O", { shiftKey: true });
  EventUtils.synthesizeKey("P", { shiftKey: true });
  EventUtils.synthesizeKey("Q", { shiftKey: true });

  is(document.getElementById("kt_reserved").getAttribute("count"), "1", "reserved='true' with preference off");
  is(document.getElementById("kt_notreserved").getAttribute("count"), "0", "reserved='false' with preference off");
  is(document.getElementById("kt_reserveddefault").getAttribute("count"), "0", "default reserved with preference off");

  // Now try with reserved shortcut key handling enabled.
  await new Promise(resolve => {
    SpecialPowers.pushPrefEnv({"set": [["permissions.default.shortcuts", 2]]}, resolve);
  });

  EventUtils.synthesizeKey("O", { shiftKey: true });
  EventUtils.synthesizeKey("P", { shiftKey: true });
  EventUtils.synthesizeKey("Q", { shiftKey: true });

  is(document.getElementById("kt_reserved").getAttribute("count"), "2", "reserved='true' with preference on");
  is(document.getElementById("kt_notreserved").getAttribute("count"), "0", "reserved='false' with preference on");
  is(document.getElementById("kt_reserveddefault").getAttribute("count"), "1", "default reserved with preference on");

  document.documentElement.removeChild(container);

  await BrowserTestUtils.removeTab(tab);
});

// This test checks that Alt+<key> and F10 cannot be blocked when the preference is set.
if (navigator.platform.indexOf("Mac") == -1) {
  add_task(async function test_accesskeys_menus() {
    await new Promise(resolve => {
      SpecialPowers.pushPrefEnv({"set": [["permissions.default.shortcuts", 2]]}, resolve);
    });

    const uri = "data:text/html,<body onkeydown='if (event.key == \"H\" || event.key == \"F10\") event.preventDefault();'>";
    let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, uri);

    // Pressing Alt+H should open the Help menu.
    let helpPopup = document.getElementById("menu_HelpPopup");
    let popupShown = BrowserTestUtils.waitForEvent(helpPopup, "popupshown");
    EventUtils.synthesizeKey("VK_ALT", { type: "keydown" });
    EventUtils.synthesizeKey("H", { altKey: true });
    EventUtils.synthesizeKey("VK_ALT", { type: "keyup" });
    await popupShown;

    ok(true, "Help menu opened");

    let popupHidden = BrowserTestUtils.waitForEvent(helpPopup, "popuphidden");
    helpPopup.hidePopup();
    await popupHidden;

    // Pressing F10 should focus the menubar. On Linux, the file menu should open, but on Windows,
    // pressing Down will open the file menu.
    let menubar = document.getElementById("main-menubar");
    let menubarActive = BrowserTestUtils.waitForEvent(menubar, "DOMMenuBarActive");
    EventUtils.sendKey("F10");
    await menubarActive;

    let filePopup = document.getElementById("menu_FilePopup");
    popupShown = BrowserTestUtils.waitForEvent(filePopup, "popupshown");
    if (navigator.platform.indexOf("Win") >= 0) {
      EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" });
    }
    await popupShown;

    ok(true, "File menu opened");

    popupHidden = BrowserTestUtils.waitForEvent(filePopup, "popuphidden");
    filePopup.hidePopup();
    await popupHidden;

    await BrowserTestUtils.removeTab(tab1);
  });
}

// There is a <key> element for Backspace with reserved="false", so make sure that it is not
// treated as a blocked shortcut key.
add_task(async function test_backspace() {
  await new Promise(resolve => {
    SpecialPowers.pushPrefEnv({"set": [["permissions.default.shortcuts", 2]]}, resolve);
  });

  // The input field is autofocused. If this test fails, backspace can go back
  // in history so cancel the beforeunload event and adjust the field to make the test fail.
  const uri = "data:text/html,<body onbeforeunload='document.getElementById(\"field\").value = \"failed\";'>" +
                 "<input id='field' value='something'></body>";
  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, uri);

  await ContentTask.spawn(tab.linkedBrowser, { }, async function() {
    content.document.getElementById("field").focus();

    // Add a promise that resolves when the backspace key gets received
    // so we can ensure the key gets received before checking the result.
    content.keysPromise = new Promise(resolve => {
      content.addEventListener("keyup", event => {
        if (event.code == "Backspace") {
          resolve(content.document.getElementById("field").value);
        }
      });
    });
  });

  // Move the caret so backspace will delete the first character.
  EventUtils.synthesizeKey("KEY_ArrowRight", {});
  EventUtils.synthesizeKey("KEY_Backspace", {});

  let fieldValue = await ContentTask.spawn(tab.linkedBrowser, { }, async function() {
    return content.keysPromise;
  });
  is(fieldValue, "omething", "backspace not prevented");

  BrowserTestUtils.removeTab(tab);
});
