Commit 89b0e82d authored by Colin Blundell's avatar Colin Blundell Committed by Commit Bot

[WebLayer] Handle accessibility in infobars

This CL augments WebLayer's infobars implementation by handling
accessibility as Chrome's does: while accessibility is enabled the
infobar container view does not scroll out of view. The implementation
is a port of that of //chrome's InfoBarContainer.java extended to
handle the wrinkle that WebLayerAccessibilityUtil drops its observers
when there are no more Browsers and doesn't re-add them on addition of
a new Browser.

Bug: 1093846
Change-Id: Ic58d17823068d60c9d0d25a80f7ddcf420f9a2fa
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2254020
Commit-Queue: Colin Blundell <blundell@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#781801}
parent e9b0f4a0
......@@ -17,6 +17,7 @@ import org.junit.runner.RunWith;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.content_public.browser.test.util.Criteria;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.weblayer.Browser;
......@@ -65,6 +66,26 @@ public class InfoBarTest {
helper.waitForFirst();
}
private void setAccessibilityEnabled(boolean value) {
TestThreadUtils.runOnUiThreadBlocking(() -> {
try {
getTestWebLayer().setAccessibilityEnabled(value);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
});
}
private boolean canInfoBarContainerScroll() throws Exception {
return TestThreadUtils.runOnUiThreadBlocking(() -> {
try {
return getTestWebLayer().canInfoBarContainerScroll(getActiveTab());
} catch (RemoteException e) {
throw new RuntimeException(e);
}
});
}
@Before
public void setUp() throws Throwable {
final String url = mActivityTestRule.getTestDataURL("tall_page.html");
......@@ -155,4 +176,22 @@ public class InfoBarTest {
mActivityTestRule.navigateAndWait("about:blank");
Assert.assertEquals(infoBarContainerView.getVisibility(), View.VISIBLE);
}
// Tests that infobar container is blocked from scrolling when accessibility is enabled.
@Test
@SmallTest
public void testAccessibility() throws Exception {
InstrumentationActivity activity = mActivityTestRule.getActivity();
// Turn on accessibility, which should disable the infobar container from scrolling. This
// polls as setAccessibilityEnabled() is async.
setAccessibilityEnabled(true);
CriteriaHelper.pollInstrumentationThread(
Criteria.equals(false, () -> canInfoBarContainerScroll()));
// Turn accessibility off and verify that the infobar container can scroll.
setAccessibilityEnabled(false);
CriteriaHelper.pollInstrumentationThread(
Criteria.equals(true, () -> canInfoBarContainerScroll()));
}
}
......@@ -20,6 +20,7 @@ import org.chromium.content_public.browser.NavigationHandle;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.WebContentsObserver;
import org.chromium.ui.KeyboardVisibilityDelegate.KeyboardVisibilityListener;
import org.chromium.ui.util.AccessibilityUtil;
import java.util.ArrayList;
......@@ -33,7 +34,19 @@ import java.util.ArrayList;
public class InfoBarContainer implements KeyboardVisibilityListener, InfoBar.Container {
private static final String TAG = "InfoBarContainer";
// TODO(crbug.com/1025620): Port over //chrome's listening to AccessibilityUtil if/as needed.
// Number of instances that have not been destroyed.
private static int sInstanceCount;
// InfoBarContainer's handling of accessibility is a global toggle, and thus a static observer
// suffices. However, observing accessibility events has the wrinkle that all accessibility
// observers are removed when there are no more Browsers and are not re-added if a new Browser
// is subsequently created. To handle this wrinkle, |sAccessibilityObserver| is added as an
// observer whenever the number of non-destroyed InfoBarContainers becomes non-zero and removed
// whenever that number flips to zero.
private static final AccessibilityUtil.Observer sAccessibilityObserver;
static {
sAccessibilityObserver = (enabled) -> setIsAllowedToAutoHide(!enabled);
}
/**
* A listener for the InfoBar animations.
......@@ -166,6 +179,10 @@ public class InfoBarContainer implements KeyboardVisibilityListener, InfoBar.Con
private @Nullable InfoBarContainerView mInfoBarContainerView;
InfoBarContainer(TabImpl tab) {
if (++sInstanceCount == 1) {
WebLayerAccessibilityUtil.get().addObserver(sAccessibilityObserver);
}
mTab = tab;
mTab.getWebContents().addObserver(mWebContentsObserver);
......@@ -304,6 +321,11 @@ public class InfoBarContainer implements KeyboardVisibilityListener, InfoBar.Con
public void destroy() {
mTab.getWebContents().removeObserver(mWebContentsObserver);
if (--sInstanceCount == 0) {
WebLayerAccessibilityUtil.get().removeObserver(sAccessibilityObserver);
}
if (mInfoBarContainerView != null) destroyContainerView();
if (mNativeInfoBarContainer != 0) {
InfoBarContainerJni.get().destroy(mNativeInfoBarContainer, InfoBarContainer.this);
......
......@@ -106,7 +106,8 @@ public class InfoBarContainerView extends SwipableOverlayView {
// SwipableOverlayView implementation.
@Override
protected boolean isAllowedToAutoHide() {
@VisibleForTesting
public boolean isAllowedToAutoHide() {
return sIsAllowedToAutoHide;
}
......
......@@ -887,6 +887,11 @@ public final class TabImpl extends ITab.Stub implements LoginPrompt.Observer {
return (mBrowser.getActiveTab() == this) ? mBrowser.getViewController() : null;
}
@VisibleForTesting
public boolean canInfoBarContainerScrollForTesting() {
return mInfoBarContainer.getContainerViewForTesting().isAllowedToAutoHide();
}
@NativeMethods
interface Natives {
TabImpl fromWebContents(WebContents webContents);
......
......@@ -157,4 +157,9 @@ public final class TestWebLayerImpl extends ITestWebLayer.Stub {
long tabImpl, int top, int bottom, Runnable runnable);
void setIgnoreMissingKeyForTranslateManager(boolean ignore);
}
@Override
public boolean canInfoBarContainerScroll(ITab tab) {
return ((TabImpl) tab).canInfoBarContainerScrollForTesting();
}
}
......@@ -42,4 +42,6 @@ interface ITestWebLayer {
void setIgnoreMissingKeyForTranslateManager(in boolean ignore) = 12;
void forceNetworkConnectivityState(in boolean networkAvailable) = 13;
boolean canInfoBarContainerScroll(in ITab tab) = 14;
}
......@@ -110,4 +110,8 @@ public final class TestWebLayer {
public void forceNetworkConnectivityState(boolean networkAvailable) throws RemoteException {
mITestWebLayer.forceNetworkConnectivityState(networkAvailable);
}
public boolean canInfoBarContainerScroll(Tab tab) throws RemoteException {
return mITestWebLayer.canInfoBarContainerScroll(tab.getITab());
}
}
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