tor-browser

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

browser_toolbarKeyNav.js (27877B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 requestLongerTimeout(2);
      7 
      8 /**
      9 * Test browser toolbar keyboard navigation.
     10 * These tests assume the default browser configuration for toolbars unless
     11 * otherwise specified.
     12 */
     13 
     14 const { CustomizableUITestUtils } = ChromeUtils.importESModule(
     15  "resource://testing-common/CustomizableUITestUtils.sys.mjs"
     16 );
     17 let gCUITestUtils = new CustomizableUITestUtils(window);
     18 
     19 const PERMISSIONS_PAGE =
     20  "https://example.com/browser/browser/base/content/test/permissions/permissions.html";
     21 const afterUrlBarButton = "fxa-toolbar-menu-button";
     22 const sidebarRevampEnabled = Services.prefs.getBoolPref(
     23  "sidebar.revamp",
     24  false
     25 );
     26 // The DevEdition has the DevTools button in the toolbar by default. Remove it
     27 // to prevent branch-specific rules what button should be focused.
     28 function resetToolbarWithoutDevEditionButtons() {
     29  CustomizableUI.reset();
     30  CustomizableUI.removeWidgetFromArea("developer-button");
     31 }
     32 
     33 function AddHomeBesideReload() {
     34  CustomizableUI.addWidgetToArea(
     35    "home-button",
     36    "nav-bar",
     37    CustomizableUI.getPlacementOfWidget("stop-reload-button").position + 1
     38  );
     39 }
     40 
     41 function RemoveHomeButton() {
     42  CustomizableUI.removeWidgetFromArea("home-button");
     43 }
     44 
     45 function AddOldMenuSideButtons() {
     46  // Make the FxA button visible even though we're signed out.
     47  // We'll use oldfxastatus to restore the old state.
     48  document.documentElement.setAttribute(
     49    "oldfxastatus",
     50    document.documentElement.getAttribute("fxastatus")
     51  );
     52  document.documentElement.setAttribute("fxastatus", "signed_in");
     53  // The FxA button is supposed to be last, add these buttons before it.
     54  CustomizableUI.addWidgetToArea(
     55    "library-button",
     56    "nav-bar",
     57    CustomizableUI.getWidgetIdsInArea("nav-bar").length - 3
     58  );
     59  if (!sidebarRevampEnabled) {
     60    CustomizableUI.addWidgetToArea(
     61      "sidebar-button",
     62      "nav-bar",
     63      CustomizableUI.getWidgetIdsInArea("nav-bar").length - 3
     64    );
     65  }
     66  CustomizableUI.addWidgetToArea(
     67    "unified-extensions-button",
     68    "nav-bar",
     69    CustomizableUI.getWidgetIdsInArea("nav-bar").length - 3
     70  );
     71 }
     72 
     73 function RemoveOldMenuSideButtons() {
     74  CustomizableUI.removeWidgetFromArea("library-button");
     75  if (!sidebarRevampEnabled) {
     76    CustomizableUI.removeWidgetFromArea("sidebar-button");
     77  }
     78  document.documentElement.setAttribute(
     79    "fxastatus",
     80    document.documentElement.getAttribute("oldfxastatus")
     81  );
     82  document.documentElement.removeAttribute("oldfxastatus");
     83 }
     84 
     85 function startFromUrlBar(aWindow = window) {
     86  aWindow.gURLBar.focus();
     87  is(
     88    aWindow.document.activeElement,
     89    aWindow.gURLBar.inputField,
     90    "URL bar focused for start of test"
     91  );
     92 }
     93 
     94 // The Reload button is disabled for a short time even after the page finishes
     95 // loading. Wait for it to be enabled.
     96 async function waitUntilReloadEnabled() {
     97  let button = document.getElementById("reload-button");
     98  await TestUtils.waitForCondition(() => !button.disabled);
     99 }
    100 
    101 // Opens a new, blank tab, executes a task and closes the tab.
    102 function withNewBlankTab(taskFn) {
    103  return BrowserTestUtils.withNewTab("about:blank", async function () {
    104    // For a blank tab, the Reload button should be disabled. However, when we
    105    // open about:blank with BrowserTestUtils.withNewTab, this is unreliable.
    106    // Therefore, explicitly disable the reload command.
    107    // We disable the command (rather than disabling the button directly) so the
    108    // button will be updated correctly for future page loads.
    109    document.getElementById("Browser:Reload").setAttribute("disabled", "true");
    110    await taskFn();
    111  });
    112 }
    113 
    114 function removeFirefoxViewButton() {
    115  CustomizableUI.removeWidgetFromArea("firefox-view-button");
    116 }
    117 
    118 const BOOKMARKS_COUNT = 100;
    119 
    120 add_setup(async function () {
    121  await SpecialPowers.pushPrefEnv({
    122    set: [
    123      ["test.wait300msAfterTabSwitch", true],
    124      // TODO: Reenable in https://bugzilla.mozilla.org/show_bug.cgi?id=1923388
    125      ["browser.urlbar.scotchBonnet.enableOverride", false],
    126      ["browser.urlbar.trustPanel.featureGate", false],
    127      ["browser.toolbars.keyboard_navigation", true],
    128      ["accessibility.tabfocus", 7],
    129      // Taskbar Tabs' page action is controlled by a pref that differs across
    130      // platforms and by runtime checks. Patching around it is currently
    131      // onorous and creates issues with existing tests without improving test
    132      // coverage, so disable it herein.
    133      ["browser.taskbarTabs.enabled", false],
    134      ["browser.search.widget.new", false],
    135    ],
    136  });
    137  resetToolbarWithoutDevEditionButtons();
    138 
    139  await PlacesUtils.bookmarks.eraseEverything();
    140  // Add bookmarks.
    141  let bookmarks = new Array(BOOKMARKS_COUNT);
    142  for (let i = 0; i < BOOKMARKS_COUNT; ++i) {
    143    // eslint-disable-next-line @microsoft/sdl/no-insecure-url
    144    bookmarks[i] = { url: `http://test.places.${i}y/` };
    145  }
    146  await PlacesUtils.bookmarks.insertTree({
    147    guid: PlacesUtils.bookmarks.toolbarGuid,
    148    children: bookmarks,
    149  });
    150 
    151  await PlacesUtils.bookmarks.insert({
    152    parentGuid: PlacesUtils.bookmarks.toolbarGuid,
    153    title: "Test",
    154    url: "https://example.com",
    155  });
    156 
    157  // Make sure the sidebar launcher is visible (when sidebar.revamp is true);
    158  // previous tests might have hidden it.
    159  await SidebarController.initializeUIState({ launcherVisible: true });
    160 });
    161 
    162 // Test tab stops with no page loaded.
    163 add_task(async function testTabStopsNoPageWithHomeButton() {
    164  AddHomeBesideReload();
    165  await withNewBlankTab(async function () {
    166    startFromUrlBar();
    167    if (sidebarRevampEnabled) {
    168      await expectFocusAfterKey("Shift+Tab", "sidebar-button");
    169      await expectFocusAfterKey("ArrowRight", "home-button");
    170    } else {
    171      await expectFocusAfterKey("Shift+Tab", "home-button");
    172    }
    173    await expectFocusAfterKey("Shift+Tab", "tabs-newtab-button");
    174    await expectFocusAfterKey("Shift+Tab", gBrowser.selectedTab);
    175    await expectFocusAfterKey("Tab", "tabs-newtab-button");
    176    if (sidebarRevampEnabled) {
    177      await expectFocusAfterKey("Tab", "sidebar-button");
    178      await expectFocusAfterKey("ArrowRight", "home-button");
    179    } else {
    180      await expectFocusAfterKey("Tab", "home-button");
    181    }
    182    await expectFocusAfterKey("Tab", gURLBar.inputField);
    183    await expectFocusAfterKey("Tab", afterUrlBarButton);
    184    if (sidebarRevampEnabled) {
    185      let sidebar = document.querySelector("sidebar-main");
    186      await expectFocusAfterKey("Tab", sidebar.toolButtons[0]);
    187      await expectFocusAfterKey("Tab", sidebar.customizeButton);
    188    }
    189    await expectFocusAfterKey("Tab", gBrowser.selectedBrowser);
    190  });
    191  RemoveHomeButton();
    192 });
    193 
    194 async function doTestTabStopsPageLoaded(aPageActionsVisible) {
    195  info(`doTestTabStopsPageLoaded(${aPageActionsVisible})`);
    196 
    197  BrowserPageActions.mainButtonNode.style.display = aPageActionsVisible
    198    ? "flex"
    199    : "none";
    200  await BrowserTestUtils.withNewTab("https://example.com", async function () {
    201    let sidebar = document.querySelector("sidebar-main");
    202    await waitUntilReloadEnabled();
    203    startFromUrlBar();
    204    await expectFocusAfterKey(
    205      "Shift+Tab",
    206      "tracking-protection-icon-container"
    207    );
    208    if (sidebarRevampEnabled) {
    209      await expectFocusAfterKey("Shift+Tab", "sidebar-button");
    210      await expectFocusAfterKey("ArrowRight", "reload-button");
    211    } else {
    212      await expectFocusAfterKey("Shift+Tab", "reload-button");
    213    }
    214    await expectFocusAfterKey("Shift+Tab", "tabs-newtab-button");
    215    await expectFocusAfterKey("Shift+Tab", gBrowser.selectedTab);
    216    await expectFocusAfterKey("Tab", "tabs-newtab-button");
    217    if (sidebarRevampEnabled) {
    218      await expectFocusAfterKey("Tab", "sidebar-button");
    219      await expectFocusAfterKey("ArrowRight", "reload-button");
    220    } else {
    221      await expectFocusAfterKey("Tab", "reload-button");
    222    }
    223    await expectFocusAfterKey("Tab", "tracking-protection-icon-container");
    224    await expectFocusAfterKey("Tab", gURLBar.inputField);
    225    await expectFocusAfterKey(
    226      "Tab",
    227      aPageActionsVisible ? "pageActionButton" : "star-button-box"
    228    );
    229    await expectFocusAfterKey("Tab", afterUrlBarButton);
    230    if (sidebarRevampEnabled) {
    231      await expectFocusAfterKey("Tab", sidebar.toolButtons[0]);
    232      await expectFocusAfterKey("Tab", sidebar.customizeButton);
    233    }
    234    await expectFocusAfterKey("Tab", gBrowser.selectedBrowser);
    235  });
    236  BrowserPageActions.mainButtonNode.style.removeProperty("display");
    237 }
    238 
    239 // Test tab stops with a page loaded.
    240 add_task(async function testTabStopsPageLoaded() {
    241  await doTestTabStopsPageLoaded(false);
    242  await doTestTabStopsPageLoaded(true);
    243 });
    244 
    245 // Test tab stops with a notification anchor visible.
    246 // The notification anchor should not get its own tab stop.
    247 add_task(async function testTabStopsWithNotification() {
    248  await BrowserTestUtils.withNewTab(
    249    PERMISSIONS_PAGE,
    250    async function (aBrowser) {
    251      let popupShown = BrowserTestUtils.waitForEvent(
    252        PopupNotifications.panel,
    253        "popupshown"
    254      );
    255      // Request a permission.
    256      BrowserTestUtils.synthesizeMouseAtCenter("#geo", {}, aBrowser);
    257      await popupShown;
    258      startFromUrlBar();
    259      // If the notification anchor were in the tab order, the next shift+tab
    260      // would focus it instead of #tracking-protection-icon-container.
    261      await expectFocusAfterKey(
    262        "Shift+Tab",
    263        "tracking-protection-icon-container"
    264      );
    265    }
    266  );
    267 });
    268 
    269 // Test tab stops with the Bookmarks toolbar visible.
    270 add_task(async function testTabStopsWithBookmarksToolbarVisible() {
    271  await BrowserTestUtils.withNewTab("about:blank", async function () {
    272    CustomizableUI.setToolbarVisibility("PersonalToolbar", true);
    273    await TestUtils.waitForCondition(() => {
    274      return !document
    275        .getElementById("PersonalToolbar")
    276        .hasAttribute("collapsed");
    277    });
    278    startFromUrlBar();
    279    await expectFocusAfterKey("Tab", afterUrlBarButton);
    280    await expectFocusAfterKey("Tab", "PersonalToolbar", true);
    281    if (sidebarRevampEnabled) {
    282      let sidebar = document.querySelector("sidebar-main");
    283      await expectFocusAfterKey("Tab", sidebar.toolButtons[0]);
    284      await expectFocusAfterKey("Tab", sidebar.customizeButton);
    285    }
    286    await expectFocusAfterKey("Tab", gBrowser.selectedBrowser);
    287  });
    288 });
    289 
    290 // Test tab stops with the Bookmarks toolbar hidden.
    291 add_task(async function testTabStopsWithBookmarksToolbarHidden() {
    292  await BrowserTestUtils.withNewTab("about:blank", async function () {
    293    // Make sure the Bookmarks toolbar is no longer tabbable once hidden.
    294    CustomizableUI.setToolbarVisibility("PersonalToolbar", false);
    295    const toolbar = document.getElementById("PersonalToolbar");
    296    await TestUtils.waitForCondition(() => toolbar.hasAttribute("collapsed"));
    297    startFromUrlBar();
    298    await expectFocusAfterKey("Tab", afterUrlBarButton);
    299    if (sidebarRevampEnabled) {
    300      let sidebar = document.querySelector("sidebar-main");
    301      await expectFocusAfterKey("Tab", sidebar.toolButtons[0]);
    302      await expectFocusAfterKey("Tab", sidebar.customizeButton);
    303    }
    304    await expectFocusAfterKey("Tab", gBrowser.selectedBrowser);
    305  });
    306 });
    307 
    308 // Test a focusable toolbartabstop which has no navigable buttons.
    309 add_task(async function testTabStopNoButtons() {
    310  await withNewBlankTab(async function () {
    311    // The Back, Forward and Reload buttons are all currently disabled.
    312    if (!sidebarRevampEnabled) {
    313      // The Home button is the only other button at that tab stop.
    314      CustomizableUI.removeWidgetFromArea("home-button");
    315    } else {
    316      // The home and sidebar buttons are the only other button at that tab stop.
    317      CustomizableUI.removeWidgetFromArea("home-button");
    318      CustomizableUI.removeWidgetFromArea("sidebar-button");
    319    }
    320    startFromUrlBar();
    321    await expectFocusAfterKey("Shift+Tab", "tabs-newtab-button");
    322    await expectFocusAfterKey("Tab", gURLBar.inputField);
    323    resetToolbarWithoutDevEditionButtons();
    324    AddHomeBesideReload();
    325    if (!sidebarRevampEnabled) {
    326      CustomizableUI.addWidgetToArea("sidebar-button", "nav-bar", 0);
    327    }
    328    // Make sure the button is reachable now that it has been re-added.
    329    await expectFocusAfterKey("Shift+Tab", "sidebar-button", true);
    330    await expectFocusAfterKey("ArrowRight", "home-button");
    331    RemoveHomeButton();
    332  });
    333 });
    334 
    335 // Test that right/left arrows move through toolbarbuttons.
    336 // This also verifies that:
    337 // 1. Right/left arrows do nothing when at the edges; and
    338 // 2. The overflow menu button can't be reached by right arrow when it isn't
    339 // visible.
    340 add_task(async function testArrowsToolbarbuttons() {
    341  AddOldMenuSideButtons();
    342  await BrowserTestUtils.withNewTab("about:blank", async function () {
    343    startFromUrlBar();
    344    await expectFocusAfterKey("Tab", "library-button");
    345    EventUtils.synthesizeKey("KEY_ArrowLeft");
    346    is(
    347      document.activeElement.id,
    348      "library-button",
    349      "ArrowLeft at end of button group does nothing"
    350    );
    351    if (!sidebarRevampEnabled) {
    352      await expectFocusAfterKey("ArrowRight", "sidebar-button");
    353    }
    354    await expectFocusAfterKey("ArrowRight", "unified-extensions-button");
    355    await expectFocusAfterKey("ArrowRight", "fxa-toolbar-menu-button");
    356    // This next check also confirms that the overflow menu button is skipped,
    357    // since it is currently invisible.
    358    await expectFocusAfterKey("ArrowRight", "PanelUI-menu-button");
    359    EventUtils.synthesizeKey("KEY_ArrowRight");
    360    is(
    361      document.activeElement.id,
    362      "PanelUI-menu-button",
    363      "ArrowRight at end of button group does nothing"
    364    );
    365    await expectFocusAfterKey("ArrowLeft", "fxa-toolbar-menu-button");
    366    await expectFocusAfterKey("ArrowLeft", "unified-extensions-button");
    367    if (!sidebarRevampEnabled) {
    368      await expectFocusAfterKey("ArrowLeft", "sidebar-button");
    369    }
    370    await expectFocusAfterKey("ArrowLeft", "library-button");
    371  });
    372  RemoveOldMenuSideButtons();
    373 });
    374 
    375 // Test that right/left arrows move through buttons which aren't toolbarbuttons
    376 // but have role="button".
    377 add_task(async function testArrowsRoleButton() {
    378  BrowserPageActions.mainButtonNode.style.display = "flex";
    379 
    380  await BrowserTestUtils.withNewTab("https://example.com", async function () {
    381    startFromUrlBar();
    382    await expectFocusAfterKey("Tab", "pageActionButton");
    383    await expectFocusAfterKey("ArrowRight", "star-button-box");
    384    await expectFocusAfterKey("ArrowLeft", "pageActionButton");
    385  });
    386  BrowserPageActions.mainButtonNode.style.removeProperty("display");
    387 });
    388 
    389 // Test that right/left arrows do not land on disabled buttons.
    390 add_task(async function testArrowsDisabledButtons() {
    391  await BrowserTestUtils.withNewTab(
    392    "https://example.com",
    393    async function (aBrowser) {
    394      await waitUntilReloadEnabled();
    395      startFromUrlBar();
    396      await expectFocusAfterKey(
    397        "Shift+Tab",
    398        "tracking-protection-icon-container"
    399      );
    400      // Back and Forward buttons are disabled.
    401      if (sidebarRevampEnabled) {
    402        await expectFocusAfterKey("Shift+Tab", "sidebar-button");
    403        await expectFocusAfterKey("ArrowRight", "reload-button");
    404      } else {
    405        await expectFocusAfterKey("Shift+Tab", "reload-button");
    406      }
    407      EventUtils.synthesizeKey("KEY_ArrowLeft");
    408      if (sidebarRevampEnabled) {
    409        is(
    410          document.activeElement.id,
    411          "sidebar-button",
    412          "ArrowLeft on Reload button when prior buttons disabled navigates to sidebar-button"
    413        );
    414      } else {
    415        is(
    416          document.activeElement.id,
    417          "reload-button",
    418          "ArrowLeft on Reload button when prior buttons disabled does nothing"
    419        );
    420      }
    421 
    422      BrowserTestUtils.startLoadingURIString(aBrowser, "https://example.com/2");
    423      await BrowserTestUtils.browserLoaded(aBrowser);
    424      await waitUntilReloadEnabled();
    425      startFromUrlBar();
    426      await expectFocusAfterKey(
    427        "Shift+Tab",
    428        "tracking-protection-icon-container"
    429      );
    430      if (sidebarRevampEnabled) {
    431        await expectFocusAfterKey("Shift+Tab", "sidebar-button");
    432        await expectFocusAfterKey("ArrowRight", "back-button");
    433      } else {
    434        await expectFocusAfterKey("Shift+Tab", "back-button");
    435      }
    436      // Forward button is still disabled.
    437      await expectFocusAfterKey("ArrowRight", "reload-button");
    438    }
    439  );
    440 });
    441 
    442 // Test that right arrow reaches the overflow menu button when it is visible.
    443 add_task(async function testArrowsOverflowButton() {
    444  AddOldMenuSideButtons();
    445  await BrowserTestUtils.withNewTab("about:blank", async function () {
    446    // Move something to the overflow menu to make the button appear.
    447    CustomizableUI.addWidgetToArea(
    448      "home-button",
    449      CustomizableUI.AREA_FIXED_OVERFLOW_PANEL
    450    );
    451    startFromUrlBar();
    452    await expectFocusAfterKey("Tab", "library-button");
    453    if (!sidebarRevampEnabled) {
    454      await expectFocusAfterKey("ArrowRight", "sidebar-button");
    455    }
    456    await expectFocusAfterKey("ArrowRight", "unified-extensions-button");
    457    await expectFocusAfterKey("ArrowRight", "fxa-toolbar-menu-button");
    458    await expectFocusAfterKey("ArrowRight", "nav-bar-overflow-button");
    459    // Make sure the button is not reachable once it is invisible again.
    460    await expectFocusAfterKey("ArrowRight", "PanelUI-menu-button");
    461    resetToolbarWithoutDevEditionButtons();
    462    // Flush layout so its invisibility can be detected.
    463    document.getElementById("nav-bar-overflow-button").clientWidth;
    464    // We reset the toolbar above so the unified extensions button is now the
    465    // "last" button.
    466    await expectFocusAfterKey("ArrowLeft", "unified-extensions-button");
    467    await expectFocusAfterKey("ArrowLeft", "fxa-toolbar-menu-button");
    468  });
    469  RemoveOldMenuSideButtons();
    470 });
    471 
    472 // Test that toolbar keyboard navigation doesn't interfere with PanelMultiView
    473 // keyboard navigation.
    474 // We do this by opening the Library menu and ensuring that pressing left arrow
    475 // does nothing.
    476 add_task(async function testArrowsInPanelMultiView() {
    477  AddOldMenuSideButtons();
    478  let button = document.getElementById("library-button");
    479  await focusAndActivateElement(button, () => EventUtils.synthesizeKey(" "));
    480  let view = document.getElementById("appMenu-libraryView");
    481  let focused = BrowserTestUtils.waitForEvent(view, "focus", true);
    482  let focusEvt = await focused;
    483  ok(true, "Focus inside Library menu after toolbar button pressed");
    484  EventUtils.synthesizeKey("KEY_ArrowLeft");
    485  is(
    486    document.activeElement,
    487    focusEvt.target,
    488    "ArrowLeft inside panel does nothing"
    489  );
    490  let hidden = BrowserTestUtils.waitForEvent(document, "popuphidden", true);
    491  view.closest("panel").hidePopup();
    492  await hidden;
    493  RemoveOldMenuSideButtons();
    494 });
    495 
    496 // Test that right/left arrows move in the expected direction for RTL locales.
    497 add_task(async function testArrowsRtl() {
    498  AddOldMenuSideButtons();
    499  await BrowserTestUtils.enableRtlLocale();
    500  startFromUrlBar(window);
    501  await expectFocusAfterKey("Tab", "library-button");
    502  EventUtils.synthesizeKey("KEY_ArrowRight", {});
    503  if (!sidebarRevampEnabled) {
    504    await expectFocusAfterKey("ArrowLeft", "sidebar-button");
    505  }
    506  await expectFocusAfterKey("ArrowLeft", "unified-extensions-button");
    507  await BrowserTestUtils.disableRtlLocale();
    508  RemoveOldMenuSideButtons();
    509 });
    510 
    511 // Test that right arrow reaches the overflow menu button on the Bookmarks
    512 // toolbar when it is visible.
    513 add_task(async function testArrowsBookmarksOverflowButton() {
    514  let toolbar = gNavToolbox.querySelector("#PersonalToolbar");
    515  // Third parameter is 'persist' and true is the default.
    516  // Fourth parameter is 'animated' and we want no animation.
    517  setToolbarVisibility(toolbar, true, true, false);
    518  Assert.ok(!toolbar.collapsed, "toolbar should be visible");
    519 
    520  await BrowserTestUtils.waitForEvent(
    521    toolbar,
    522    "BookmarksToolbarVisibilityUpdated"
    523  );
    524  let items = document.getElementById("PlacesToolbarItems").children;
    525  let lastVisible;
    526  for (let item of items) {
    527    if (item.style.visibility == "hidden") {
    528      break;
    529    }
    530    lastVisible = item;
    531  }
    532  await focusAndActivateElement(lastVisible, () =>
    533    expectFocusAfterKey("ArrowRight", "PlacesChevron")
    534  );
    535  setToolbarVisibility(toolbar, false, true, false);
    536 });
    537 
    538 registerCleanupFunction(async function () {
    539  CustomizableUI.reset();
    540  await PlacesUtils.bookmarks.eraseEverything();
    541 });
    542 
    543 // Test that when a toolbar button opens a panel, closing the panel restores
    544 // focus to the button which opened it.
    545 add_task(async function testPanelCloseRestoresFocus() {
    546  AddOldMenuSideButtons();
    547  await withNewBlankTab(async function () {
    548    // We can't use forceFocus because that removes focusability immediately.
    549    // Instead, we must let ToolbarKeyboardNavigator handle this properly.
    550    startFromUrlBar();
    551    await expectFocusAfterKey("Tab", "library-button");
    552    let view = document.getElementById("appMenu-libraryView");
    553    let shown = BrowserTestUtils.waitForEvent(view, "ViewShown");
    554    EventUtils.synthesizeKey(" ");
    555    await shown;
    556    let hidden = BrowserTestUtils.waitForEvent(document, "popuphidden", true);
    557    view.closest("panel").hidePopup();
    558    await hidden;
    559    is(
    560      document.activeElement.id,
    561      "library-button",
    562      "Focus restored to Library button after panel closed"
    563    );
    564  });
    565  RemoveOldMenuSideButtons();
    566 });
    567 
    568 // Test that the arrow key works in the group of the
    569 // 'tracking-protection-icon-container' and the 'identity-box'.
    570 add_task(async function testArrowKeyForTPIconContainerandIdentityBox() {
    571  await BrowserTestUtils.withNewTab(
    572    "https://example.com",
    573    async function (browser) {
    574      // Simulate geo sharing so the permission box shows
    575      gBrowser.updateBrowserSharing(browser, { geo: true });
    576      await waitUntilReloadEnabled();
    577      startFromUrlBar();
    578      await expectFocusAfterKey(
    579        "Shift+Tab",
    580        "tracking-protection-icon-container"
    581      );
    582      await expectFocusAfterKey("ArrowRight", "identity-icon-box");
    583      await expectFocusAfterKey("ArrowRight", "identity-permission-box");
    584      await expectFocusAfterKey("ArrowLeft", "identity-icon-box");
    585      await expectFocusAfterKey(
    586        "ArrowLeft",
    587        "tracking-protection-icon-container"
    588      );
    589      gBrowser.updateBrowserSharing(browser, { geo: false });
    590    }
    591  );
    592 });
    593 
    594 // Test navigation by typed characters.
    595 add_task(async function testCharacterNavigation() {
    596  AddHomeBesideReload();
    597  AddOldMenuSideButtons();
    598  await BrowserTestUtils.withNewTab("https://example.com", async function () {
    599    await waitUntilReloadEnabled();
    600    startFromUrlBar();
    601    await expectFocusAfterKey("Tab", "star-button-box");
    602    await expectFocusAfterKey("h", "home-button");
    603    // There's no button starting with "hs", so pressing s should do nothing.
    604    EventUtils.synthesizeKey("s");
    605    is(
    606      document.activeElement.id,
    607      "home-button",
    608      "home-button still focused after s pressed"
    609    );
    610    // Escape should reset the search.
    611    EventUtils.synthesizeKey("KEY_Escape");
    612    if (!sidebarRevampEnabled) {
    613      // Pressing s should find the button starting with s: Sidebars.
    614      await expectFocusAfterKey("s", "sidebar-button");
    615    }
    616  });
    617  RemoveHomeButton();
    618  RemoveOldMenuSideButtons();
    619 });
    620 
    621 // Test that toolbar character navigation doesn't trigger in PanelMultiView for
    622 // a panel anchored to the toolbar.
    623 // We do this by opening the Library menu and ensuring that pressing s
    624 // does nothing.
    625 // This test should be removed if PanelMultiView implements character
    626 // navigation.
    627 add_task(async function testCharacterInPanelMultiView() {
    628  AddOldMenuSideButtons();
    629  let button = document.getElementById("library-button");
    630  let view = document.getElementById("appMenu-libraryView");
    631  let focused = BrowserTestUtils.waitForEvent(view, "focus", true);
    632  await focusAndActivateElement(button, () => EventUtils.synthesizeKey(" "));
    633  let focusEvt = await focused;
    634  ok(true, "Focus inside Library menu after toolbar button pressed");
    635  EventUtils.synthesizeKey("s");
    636  is(document.activeElement, focusEvt.target, "s inside panel does nothing");
    637  let hidden = BrowserTestUtils.waitForEvent(document, "popuphidden", true);
    638  view.closest("panel").hidePopup();
    639  await hidden;
    640  RemoveOldMenuSideButtons();
    641 });
    642 
    643 // Test tab stops after the search bar is added.
    644 add_task(async function testTabStopsAfterSearchBarAdded() {
    645  AddOldMenuSideButtons();
    646  await gCUITestUtils.addSearchBar();
    647  await withNewBlankTab(async function () {
    648    startFromUrlBar();
    649    await expectFocusAfterKey("Tab", "searchbar", true);
    650    await expectFocusAfterKey("Tab", "library-button");
    651    await expectFocusAfterKey("Shift+Tab", "searchbar", true);
    652    await expectFocusAfterKey("Shift+Tab", gURLBar.inputField);
    653  });
    654  gCUITestUtils.removeSearchBar();
    655  RemoveOldMenuSideButtons();
    656 });
    657 
    658 // Test tab navigation when the Firefox View button is present
    659 // and when the button is not present.
    660 add_task(async function testFirefoxViewButtonNavigation() {
    661  // Add enough tabs so that the new-tab-button appears in the toolbar
    662  // and the tabs-newtab-button is hidden.
    663  await BrowserTestUtils.overflowTabs(registerCleanupFunction, window);
    664 
    665  // Assert that Firefox View button receives focus when tab navigating
    666  // forward from the end of web content.
    667  // Additionally, ensure that focus is not trapped between the
    668  // selected tab and the new-tab button.
    669  // Finally, assert that focus is restored to web content when
    670  // navigating backwards from the Firefox View button.
    671  await BrowserTestUtils.withNewTab(
    672    PERMISSIONS_PAGE,
    673    async function (aBrowser) {
    674      await SpecialPowers.spawn(aBrowser, [], async () => {
    675        content.document.querySelector("#camera").focus();
    676      });
    677 
    678      await expectFocusAfterKey("Tab", "firefox-view-button");
    679      let selectedTab = document.querySelector("tab[selected]");
    680      await expectFocusAfterKey("Tab", selectedTab);
    681      await expectFocusAfterKey("Tab", "new-tab-button");
    682      await expectFocusAfterKey("Shift+Tab", selectedTab);
    683      await expectFocusAfterKey("Shift+Tab", "firefox-view-button");
    684 
    685      // Moving from toolbar back into content
    686      EventUtils.synthesizeKey("KEY_Tab", { shiftKey: true });
    687      await SpecialPowers.spawn(aBrowser, [], async () => {
    688        let activeElement = content.document.activeElement;
    689        let expectedElement = content.document.querySelector("#camera");
    690        is(
    691          activeElement,
    692          expectedElement,
    693          "Focus should be returned to the 'camera' button"
    694        );
    695      });
    696    }
    697  );
    698 
    699  // Assert that the selected tab receives focus before the new-tab button
    700  // if there is no Firefox View button.
    701  // Additionally, assert that navigating backwards from the selected tab
    702  // restores focus to the last element in the web content.
    703  await BrowserTestUtils.withNewTab(
    704    PERMISSIONS_PAGE,
    705    async function (aBrowser) {
    706      removeFirefoxViewButton();
    707 
    708      await SpecialPowers.spawn(aBrowser, [], async () => {
    709        content.document.querySelector("#camera").focus();
    710      });
    711 
    712      let selectedTab = document.querySelector("tab[selected]");
    713      await expectFocusAfterKey("Tab", selectedTab);
    714      await expectFocusAfterKey("Tab", "new-tab-button");
    715      await expectFocusAfterKey("Shift+Tab", selectedTab);
    716 
    717      // Moving from toolbar back into content
    718      EventUtils.synthesizeKey("KEY_Tab", { shiftKey: true });
    719      await SpecialPowers.spawn(aBrowser, [], async () => {
    720        let activeElement = content.document.activeElement;
    721        let expectedElement = content.document.querySelector("#camera");
    722        is(
    723          activeElement,
    724          expectedElement,
    725          "Focus should be returned to the 'camera' button"
    726        );
    727      });
    728    }
    729  );
    730 
    731  // Clean up extra tabs
    732  while (gBrowser.tabs.length > 1) {
    733    BrowserTestUtils.removeTab(gBrowser.tabs[0]);
    734  }
    735  CustomizableUI.reset();
    736 });