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; ...@@ -17,6 +17,7 @@ import org.junit.runner.RunWith;
import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.CommandLineFlags; 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.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.weblayer.Browser; import org.chromium.weblayer.Browser;
...@@ -65,6 +66,26 @@ public class InfoBarTest { ...@@ -65,6 +66,26 @@ public class InfoBarTest {
helper.waitForFirst(); 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 @Before
public void setUp() throws Throwable { public void setUp() throws Throwable {
final String url = mActivityTestRule.getTestDataURL("tall_page.html"); final String url = mActivityTestRule.getTestDataURL("tall_page.html");
...@@ -155,4 +176,22 @@ public class InfoBarTest { ...@@ -155,4 +176,22 @@ public class InfoBarTest {
mActivityTestRule.navigateAndWait("about:blank"); mActivityTestRule.navigateAndWait("about:blank");
Assert.assertEquals(infoBarContainerView.getVisibility(), View.VISIBLE); 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; ...@@ -20,6 +20,7 @@ import org.chromium.content_public.browser.NavigationHandle;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.WebContentsObserver; import org.chromium.content_public.browser.WebContentsObserver;
import org.chromium.ui.KeyboardVisibilityDelegate.KeyboardVisibilityListener; import org.chromium.ui.KeyboardVisibilityDelegate.KeyboardVisibilityListener;
import org.chromium.ui.util.AccessibilityUtil;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -33,7 +34,19 @@ import java.util.ArrayList; ...@@ -33,7 +34,19 @@ import java.util.ArrayList;
public class InfoBarContainer implements KeyboardVisibilityListener, InfoBar.Container { public class InfoBarContainer implements KeyboardVisibilityListener, InfoBar.Container {
private static final String TAG = "InfoBarContainer"; 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. * A listener for the InfoBar animations.
...@@ -166,6 +179,10 @@ public class InfoBarContainer implements KeyboardVisibilityListener, InfoBar.Con ...@@ -166,6 +179,10 @@ public class InfoBarContainer implements KeyboardVisibilityListener, InfoBar.Con
private @Nullable InfoBarContainerView mInfoBarContainerView; private @Nullable InfoBarContainerView mInfoBarContainerView;
InfoBarContainer(TabImpl tab) { InfoBarContainer(TabImpl tab) {
if (++sInstanceCount == 1) {
WebLayerAccessibilityUtil.get().addObserver(sAccessibilityObserver);
}
mTab = tab; mTab = tab;
mTab.getWebContents().addObserver(mWebContentsObserver); mTab.getWebContents().addObserver(mWebContentsObserver);
...@@ -304,6 +321,11 @@ public class InfoBarContainer implements KeyboardVisibilityListener, InfoBar.Con ...@@ -304,6 +321,11 @@ public class InfoBarContainer implements KeyboardVisibilityListener, InfoBar.Con
public void destroy() { public void destroy() {
mTab.getWebContents().removeObserver(mWebContentsObserver); mTab.getWebContents().removeObserver(mWebContentsObserver);
if (--sInstanceCount == 0) {
WebLayerAccessibilityUtil.get().removeObserver(sAccessibilityObserver);
}
if (mInfoBarContainerView != null) destroyContainerView(); if (mInfoBarContainerView != null) destroyContainerView();
if (mNativeInfoBarContainer != 0) { if (mNativeInfoBarContainer != 0) {
InfoBarContainerJni.get().destroy(mNativeInfoBarContainer, InfoBarContainer.this); InfoBarContainerJni.get().destroy(mNativeInfoBarContainer, InfoBarContainer.this);
......
...@@ -106,7 +106,8 @@ public class InfoBarContainerView extends SwipableOverlayView { ...@@ -106,7 +106,8 @@ public class InfoBarContainerView extends SwipableOverlayView {
// SwipableOverlayView implementation. // SwipableOverlayView implementation.
@Override @Override
protected boolean isAllowedToAutoHide() { @VisibleForTesting
public boolean isAllowedToAutoHide() {
return sIsAllowedToAutoHide; return sIsAllowedToAutoHide;
} }
......
...@@ -887,6 +887,11 @@ public final class TabImpl extends ITab.Stub implements LoginPrompt.Observer { ...@@ -887,6 +887,11 @@ public final class TabImpl extends ITab.Stub implements LoginPrompt.Observer {
return (mBrowser.getActiveTab() == this) ? mBrowser.getViewController() : null; return (mBrowser.getActiveTab() == this) ? mBrowser.getViewController() : null;
} }
@VisibleForTesting
public boolean canInfoBarContainerScrollForTesting() {
return mInfoBarContainer.getContainerViewForTesting().isAllowedToAutoHide();
}
@NativeMethods @NativeMethods
interface Natives { interface Natives {
TabImpl fromWebContents(WebContents webContents); TabImpl fromWebContents(WebContents webContents);
......
...@@ -157,4 +157,9 @@ public final class TestWebLayerImpl extends ITestWebLayer.Stub { ...@@ -157,4 +157,9 @@ public final class TestWebLayerImpl extends ITestWebLayer.Stub {
long tabImpl, int top, int bottom, Runnable runnable); long tabImpl, int top, int bottom, Runnable runnable);
void setIgnoreMissingKeyForTranslateManager(boolean ignore); void setIgnoreMissingKeyForTranslateManager(boolean ignore);
} }
@Override
public boolean canInfoBarContainerScroll(ITab tab) {
return ((TabImpl) tab).canInfoBarContainerScrollForTesting();
}
} }
...@@ -42,4 +42,6 @@ interface ITestWebLayer { ...@@ -42,4 +42,6 @@ interface ITestWebLayer {
void setIgnoreMissingKeyForTranslateManager(in boolean ignore) = 12; void setIgnoreMissingKeyForTranslateManager(in boolean ignore) = 12;
void forceNetworkConnectivityState(in boolean networkAvailable) = 13; void forceNetworkConnectivityState(in boolean networkAvailable) = 13;
boolean canInfoBarContainerScroll(in ITab tab) = 14;
} }
...@@ -110,4 +110,8 @@ public final class TestWebLayer { ...@@ -110,4 +110,8 @@ public final class TestWebLayer {
public void forceNetworkConnectivityState(boolean networkAvailable) throws RemoteException { public void forceNetworkConnectivityState(boolean networkAvailable) throws RemoteException {
mITestWebLayer.forceNetworkConnectivityState(networkAvailable); 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