[Keyboard A11y] Add shortcuts for focus on top Chrome
Bug: 360423850, 399498687 Change-Id: Ia7bae30507b10f1fff178de40cb641287904a2a8 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6408452 Commit-Queue: Jenna Himawan <jhimawan@google.com> Reviewed-by: Theresa Sullivan <twellington@chromium.org> Cr-Commit-Position: refs/heads/main@{#1439672}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
7675c99656
commit
dc1efa1af1
chrome/android
java
src
org
chromium
chrome
browser
javatests
src
org
chromium
chrome
browser
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user