diff --git a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java index 5b8978ed893a2..fd0b6fc3d494c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java @@ -698,14 +698,14 @@ public class KeyboardShortcuts { /** * This should be called from the Activity's onKeyDown() to handle keyboard shortcuts. * - * Note: onKeyDown() is called after the active view or web page has had a chance to handle + * <p>Note: onKeyDown() is called after the active view or web page has had a chance to handle * the key event. So the keys handled here *can* be overridden by any view or web page. * * @param event The KeyEvent to handle. * @param isCurrentTabVisible Whether page-related actions are valid, e.g. reload, zoom in. This - * should be false when in the tab switcher. + * should be false when in the tab switcher. * @param tabSwitchingEnabled Whether shortcuts that switch between tabs are enabled (e.g. - * Ctrl+Tab, Ctrl+3). + * Ctrl+Tab, Ctrl+3). * @param tabModelSelector The current tab modelSelector. * @param menuOrKeyboardActionController Controls keyboard actions. * @param toolbarManager Manages the toolbar. @@ -726,6 +726,7 @@ public class KeyboardShortcuts { && !event.isAltPressed() && keyCode != KeyEvent.KEYCODE_F3 && keyCode != KeyEvent.KEYCODE_F5 + && keyCode != KeyEvent.KEYCODE_F6 && keyCode != KeyEvent.KEYCODE_F10 && keyCode != KeyEvent.KEYCODE_FORWARD && keyCode != KeyEvent.KEYCODE_REFRESH) { @@ -894,6 +895,29 @@ public class KeyboardShortcuts { case KeyboardShortcutsSemanticMeaning.OPEN_HELP: menuOrKeyboardActionController.onMenuOrKeyboardAction(R.id.help_id, false); return true; + case KeyboardShortcutsSemanticMeaning + .NOT_IMPLEMENTED_KEYBOARD_FOCUS_SWITCH_ROW_OF_TOP_ELEMENTS: + if (ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_KEYBOARD_A11Y)) { + // TODO(crbug.com/360423850): Don't allow F6 to be overridden by websites. + return menuOrKeyboardActionController.onMenuOrKeyboardAction( + R.id.switch_keyboard_focus_row, /* fromMenu= */ false); + } else { + return false; + } + case KeyboardShortcutsSemanticMeaning.NOT_IMPLEMENTED_KEYBOARD_FOCUS_TOOLBAR: + if (ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_KEYBOARD_A11Y)) { + toolbarManager.requestFocus(); + return true; + } else { + return false; + } + case KeyboardShortcutsSemanticMeaning.NOT_IMPLEMENTED_KEYBOARD_FOCUS_BOOKMARKS: + if (ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_KEYBOARD_A11Y)) { + return menuOrKeyboardActionController.onMenuOrKeyboardAction( + R.id.focus_bookmarks, /* fromMenu= */ false); + } else { + return false; + } } } diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/KeyboardShortcutsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/KeyboardShortcutsTest.java index 7d7b57ad2e3f4..2e4490334a406 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/KeyboardShortcutsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/KeyboardShortcutsTest.java @@ -31,7 +31,9 @@ import org.mockito.junit.MockitoRule; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.chrome.R; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tab.TabSelectionType; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModelSelector; @@ -109,30 +111,6 @@ public class KeyboardShortcutsTest { /* expectHandled= */ false, /* isCurrentTabVisible= */ true, /* metaState= */ 0); } - private void testOpenBookmarks( - boolean expectHandled, boolean isCurrentTabVisible, int metaState) { - assertEquals( - expectHandled, - KeyboardShortcuts.onKeyDown( - new KeyEvent( - /* downTime= */ SystemClock.uptimeMillis(), - /* eventTime= */ SystemClock.uptimeMillis(), - KeyEvent.ACTION_DOWN, - KeyEvent.KEYCODE_O, - /* repeat= */ 0, - metaState), - isCurrentTabVisible, - /* tabSwitchingEnabled= */ true, - mTabModelSelector, - mMenuOrKeyboardActionController, - mToolbarManager)); - - verify(mMenuOrKeyboardActionController, expectHandled ? times(1) : never()) - .onMenuOrKeyboardAction( - /* id= */ eq(R.id.all_bookmarks_menu_id), - /* fromMenu= */ expectHandled ? eq(false) : anyBoolean()); - } - @Test @SmallTest public void testToggleBookmarkBar() { @@ -245,21 +223,7 @@ public class KeyboardShortcutsTest { "expected handling of key event with keycode %s and metaState %s to" + " be %s", keyCode, metaState, expectHandled); - assertTrue( - message, - KeyboardShortcuts.onKeyDown( - new KeyEvent( - /* downTime= */ SystemClock.uptimeMillis(), - /* eventTime= */ SystemClock.uptimeMillis(), - KeyEvent.ACTION_DOWN, - keyCode, - /* repeat= */ 0, - metaState), - /* isCurrentTabVisible= */ true, - /* tabSwitchingEnabled= */ true, - mTabModelSelector, - mMenuOrKeyboardActionController, - mToolbarManager)); + assertTrue(message, keyDown(keyCode, metaState, true)); verify(mTabModel, times(1)) .setIndex(SMALL_NUMBER_OF_TABS - 1, TabSelectionType.FROM_USER); clearInvocations(mTabModel); @@ -278,21 +242,7 @@ public class KeyboardShortcutsTest { String.format( "expected key event with keycode %s and metaState %s to be handled", keyCode, metaState); - assertTrue( - message, - KeyboardShortcuts.onKeyDown( - new KeyEvent( - /* downTime= */ SystemClock.uptimeMillis(), - /* eventTime= */ SystemClock.uptimeMillis(), - KeyEvent.ACTION_DOWN, - keyCode, - /* repeat= */ 0, - metaState), - /* isCurrentTabVisible= */ true, - /* tabSwitchingEnabled= */ true, - mTabModelSelector, - mMenuOrKeyboardActionController, - mToolbarManager)); + assertTrue(message, keyDown(keyCode, metaState, true)); verify(mTabModel, times(1)) .setIndex(LARGE_NUMBER_OF_TABS - 1, TabSelectionType.FROM_USER); clearInvocations(mTabModel); @@ -300,6 +250,47 @@ public class KeyboardShortcutsTest { } } + // Tests for focus placement on top Clank. + + @Test + @SmallTest + @EnableFeatures(ChromeFeatureList.ANDROID_KEYBOARD_A11Y) + public void testGoToToolbar() { + assertTrue( + keyDown(KeyEvent.KEYCODE_T, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON, true)); + verify(mToolbarManager, times(1)).requestFocus(); + } + + @Test + @SmallTest + @EnableFeatures(ChromeFeatureList.ANDROID_KEYBOARD_A11Y) + public void testGoToBookmarksBar() { + keyDown(KeyEvent.KEYCODE_B, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON, true); + verify(mMenuOrKeyboardActionController, times(1)) + .onMenuOrKeyboardAction( + /* id= */ eq(R.id.focus_bookmarks), /* fromMenu= */ eq(false)); + } + + @Test + @SmallTest + @EnableFeatures(ChromeFeatureList.ANDROID_KEYBOARD_A11Y) + public void testFocusSwitch() { + keyDown(KeyEvent.KEYCODE_F6, 0, true); + verify(mMenuOrKeyboardActionController, times(1)) + .onMenuOrKeyboardAction( + /* id= */ eq(R.id.switch_keyboard_focus_row), /* fromMenu= */ eq(false)); + } + + private void testOpenBookmarks( + boolean expectHandled, boolean isCurrentTabVisible, int metaState) { + assertEquals(expectHandled, keyDown(KeyEvent.KEYCODE_O, metaState, isCurrentTabVisible)); + + verify(mMenuOrKeyboardActionController, expectHandled ? times(1) : never()) + .onMenuOrKeyboardAction( + /* id= */ eq(R.id.all_bookmarks_menu_id), + /* fromMenu= */ expectHandled ? eq(false) : anyBoolean()); + } + private void assertGoToTab(boolean expectHandled, int keyCode, int metaState) { String message = String.format( @@ -308,21 +299,7 @@ public class KeyboardShortcutsTest { // Note: we always expect (CTRL or ALT) + [1-9] to be a "go to tab" shortcut; we expect // onKeyDown to always be true. However, setting the index of the tab model won't happen if // the number is out of range. - assertTrue( - message, - KeyboardShortcuts.onKeyDown( - new KeyEvent( - /* downTime= */ SystemClock.uptimeMillis(), - /* eventTime= */ SystemClock.uptimeMillis(), - KeyEvent.ACTION_DOWN, - keyCode, - /* repeat= */ 0, - metaState), - /* isCurrentTabVisible= */ true, - /* tabSwitchingEnabled= */ true, - mTabModelSelector, - mMenuOrKeyboardActionController, - mToolbarManager)); + assertTrue(message, keyDown(keyCode, metaState, true)); int numCode = (KeyEvent.KEYCODE_1 <= keyCode && keyCode <= KeyEvent.KEYCODE_8) ? keyCode - KeyEvent.KEYCODE_0 @@ -330,4 +307,20 @@ public class KeyboardShortcutsTest { verify(mTabModel, expectHandled ? times(1) : never()) .setIndex(numCode - 1, TabSelectionType.FROM_USER); } + + private boolean keyDown(int keyCode, int metaState, boolean isCurrentTabVisible) { + return KeyboardShortcuts.onKeyDown( + new KeyEvent( + /* downTime= */ SystemClock.uptimeMillis(), + /* eventTime= */ SystemClock.uptimeMillis(), + KeyEvent.ACTION_DOWN, + keyCode, + /* repeat= */ 0, + metaState), + isCurrentTabVisible, + /* tabSwitchingEnabled= */ true, + mTabModelSelector, + mMenuOrKeyboardActionController, + mToolbarManager); + } }