Commit 43d8be7d authored by Yue Zhang's avatar Yue Zhang Committed by Commit Bot

Block the view bebind the dialog scrim in a11y mode

This CL makes the views behind dialog scrim unselectable through
View#setImportantForAccessibility. Since the parent view of the dialog
view is CoordinatorLayout which is the same as those of
CompositorViewHolder, toolbar, etc, this CL makes all other views
in the same hierachy unselectable when dialog is open, and restores
the importance when dialog is closed.

Bug: 1101561
Change-Id: Iba726c3118d959e730108f44fc3e97b137a660b5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2364795
Commit-Queue: Yue Zhang <yuezhanggg@chromium.org>
Reviewed-by: default avatarWei-Yin Chen (陳威尹) <wychen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#800372}
parent 03f87519
...@@ -45,6 +45,8 @@ import org.chromium.ui.modelutil.PropertyModel; ...@@ -45,6 +45,8 @@ import org.chromium.ui.modelutil.PropertyModel;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.Map;
/** /**
* Parent for TabGridDialog component. * Parent for TabGridDialog component.
...@@ -89,6 +91,7 @@ public class TabGridDialogView extends FrameLayout ...@@ -89,6 +91,7 @@ public class TabGridDialogView extends FrameLayout
private AnimatorSet mHideDialogAnimation; private AnimatorSet mHideDialogAnimation;
private AnimatorListenerAdapter mShowDialogAnimationListener; private AnimatorListenerAdapter mShowDialogAnimationListener;
private AnimatorListenerAdapter mHideDialogAnimationListener; private AnimatorListenerAdapter mHideDialogAnimationListener;
private Map<View, Integer> mAccessibilityImportanceMap = new HashMap<>();
private int mSideMargin; private int mSideMargin;
private int mTopMargin; private int mTopMargin;
private int mOrientation; private int mOrientation;
...@@ -190,6 +193,9 @@ public class TabGridDialogView extends FrameLayout ...@@ -190,6 +193,9 @@ public class TabGridDialogView extends FrameLayout
mCurrentDialogAnimator = null; mCurrentDialogAnimator = null;
mDialogContainerView.requestFocus(); mDialogContainerView.requestFocus();
mDialogContainerView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); mDialogContainerView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
// TODO(crbug.com/1101561): Move clear/restore accessibility importance logic to
// ScrimView so that it can be shared by all components using ScrimView.
clearBackgroundViewAccessibilityImportance();
} }
}; };
mHideDialogAnimationListener = new AnimatorListenerAdapter() { mHideDialogAnimationListener = new AnimatorListenerAdapter() {
...@@ -198,6 +204,7 @@ public class TabGridDialogView extends FrameLayout ...@@ -198,6 +204,7 @@ public class TabGridDialogView extends FrameLayout
setVisibility(View.GONE); setVisibility(View.GONE);
mCurrentDialogAnimator = null; mCurrentDialogAnimator = null;
mDialogContainerView.clearFocus(); mDialogContainerView.clearFocus();
restoreBackgroundViewAccessibilityImportance();
} }
}; };
...@@ -242,6 +249,35 @@ public class TabGridDialogView extends FrameLayout ...@@ -242,6 +249,35 @@ public class TabGridDialogView extends FrameLayout
}); });
} }
private void clearBackgroundViewAccessibilityImportance() {
assert mAccessibilityImportanceMap.size() == 0;
ViewGroup parent = (ViewGroup) getParent();
for (int i = 0; i < parent.getChildCount(); i++) {
View view = parent.getChildAt(i);
if (view == TabGridDialogView.this) {
continue;
}
mAccessibilityImportanceMap.put(view, view.getImportantForAccessibility());
view.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
}
private void restoreBackgroundViewAccessibilityImportance() {
ViewGroup parent = (ViewGroup) getParent();
for (int i = 0; i < parent.getChildCount(); i++) {
View view = parent.getChildAt(i);
if (view == TabGridDialogView.this) {
continue;
}
assert mAccessibilityImportanceMap.containsKey(view);
Integer importance = mAccessibilityImportanceMap.get(view);
view.setImportantForAccessibility(
importance == null ? IMPORTANT_FOR_ACCESSIBILITY_AUTO : importance);
}
mAccessibilityImportanceMap.clear();
}
void setupDialogAnimation(View sourceView) { void setupDialogAnimation(View sourceView) {
// In case where user jumps to a new page from dialog, clean existing animations in // In case where user jumps to a new page from dialog, clean existing animations in
// mHideDialogAnimation and play basic fade out instead of zooming back to corresponding tab // mHideDialogAnimation and play basic fade out instead of zooming back to corresponding tab
......
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
package org.chromium.chrome.browser.tasks.tab_management; package org.chromium.chrome.browser.tasks.tab_management;
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.replaceText; import static androidx.test.espresso.action.ViewActions.replaceText;
...@@ -746,6 +749,34 @@ public class TabGridDialogTest { ...@@ -746,6 +749,34 @@ public class TabGridDialogTest {
verifyShowingDialog(cta, 1, null); verifyShowingDialog(cta, 1, null);
} }
@Test
@MediumTest
public void testAdjustBackGroundViewAccessibilityImportance() {
final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
createTabs(cta, false, 2);
enterTabSwitcher(cta);
verifyTabSwitcherCardCount(cta, 2);
mergeAllNormalTabsToAGroup(cta);
verifyTabSwitcherCardCount(cta, 1);
// Verify accessibility importance adjustment when opening dialog from tab switcher.
openDialogFromTabSwitcherAndVerify(cta, 2, null);
verifyBackgroundViewAccessibilityImportance(cta, true);
Espresso.pressBack();
waitForDialogHidingAnimationInTabSwitcher(cta);
verifyBackgroundViewAccessibilityImportance(cta, false);
// Verify accessibility importance adjustment when opening dialog from tab strip.
openDialogFromTabSwitcherAndVerify(cta, 2, null);
clickFirstTabInDialog(cta);
waitForDialogHidingAnimation(cta);
openDialogFromStripAndVerify(cta, 2, null);
verifyBackgroundViewAccessibilityImportance(cta, true);
Espresso.pressBack();
waitForDialogHidingAnimation(cta);
verifyBackgroundViewAccessibilityImportance(cta, false);
}
private void openDialogFromTabSwitcherAndVerify( private void openDialogFromTabSwitcherAndVerify(
ChromeTabbedActivity cta, int tabCount, String customizedTitle) { ChromeTabbedActivity cta, int tabCount, String customizedTitle) {
clickFirstCardFromTabSwitcher(cta); clickFirstCardFromTabSwitcher(cta);
...@@ -955,4 +986,24 @@ public class TabGridDialogTest { ...@@ -955,4 +986,24 @@ public class TabGridDialogTest {
scrimView.performClick(); scrimView.performClick();
}); });
} }
private void verifyBackgroundViewAccessibilityImportance(
ChromeTabbedActivity cta, boolean isDialogShowing) {
View controlContainer = cta.findViewById(R.id.control_container);
assertEquals(isDialogShowing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
: IMPORTANT_FOR_ACCESSIBILITY_AUTO,
controlContainer.getImportantForAccessibility());
View bottomControls = cta.findViewById(R.id.bottom_controls);
assertEquals(isDialogShowing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
: IMPORTANT_FOR_ACCESSIBILITY_AUTO,
bottomControls.getImportantForAccessibility());
View compositorViewHolder = cta.getCompositorViewHolder();
assertEquals(isDialogShowing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
: IMPORTANT_FOR_ACCESSIBILITY_AUTO,
compositorViewHolder.getImportantForAccessibility());
View bottomContainer = cta.findViewById(R.id.bottom_container);
assertEquals(isDialogShowing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
: IMPORTANT_FOR_ACCESSIBILITY_AUTO,
bottomContainer.getImportantForAccessibility());
}
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment