Commit 38af4da2 authored by Dominic Mazzoni's avatar Dominic Mazzoni Committed by Commit Bot

Fix accessibility issues with sliders on Android

First, re-lands the fix to bug 836554, which ensures TalkBack
announces when a slider changes. This time, adds a check to only fire
the TYPE_VIEW_SELECTED event if the slider has accessibility focus,
hoping that will address the problems with fullscreen video by suppressing
announcements when an unfocused slider changes.

Also, doesn't expose the "can scroll forwards / backwards" actions on a slider
that isn't an HTML INPUT control, because a pure ARIA slider won't respond
to those. That addresses bug 917845.

Finally, added code to ensure that a slider updates the accessibility tree
when its value changes - I found this was necessary in order to get
announcements after changing a slider with the volume keys.

Bug: 836554, 917845, 953652
Change-Id: I3f1f88321a4644bc5729c16c14e0bd9037a641ef
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1853857Reviewed-by: default avatarAkihiro Ota <akihiroota@chromium.org>
Commit-Queue: Dominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#705199}
parent 4b057e2a
...@@ -1164,6 +1164,13 @@ int BrowserAccessibilityAndroid::GetItemCount() const { ...@@ -1164,6 +1164,13 @@ int BrowserAccessibilityAndroid::GetItemCount() const {
bool BrowserAccessibilityAndroid::CanScrollForward() const { bool BrowserAccessibilityAndroid::CanScrollForward() const {
if (IsSlider()) { if (IsSlider()) {
// If it's not a native INPUT element, then increment and decrement
// won't work.
std::string html_tag =
GetStringAttribute(ax::mojom::StringAttribute::kHtmlTag);
if (html_tag != "input")
return false;
float value = GetFloatAttribute(ax::mojom::FloatAttribute::kValueForRange); float value = GetFloatAttribute(ax::mojom::FloatAttribute::kValueForRange);
float max = GetFloatAttribute(ax::mojom::FloatAttribute::kMaxValueForRange); float max = GetFloatAttribute(ax::mojom::FloatAttribute::kMaxValueForRange);
return value < max; return value < max;
...@@ -1174,6 +1181,13 @@ bool BrowserAccessibilityAndroid::CanScrollForward() const { ...@@ -1174,6 +1181,13 @@ bool BrowserAccessibilityAndroid::CanScrollForward() const {
bool BrowserAccessibilityAndroid::CanScrollBackward() const { bool BrowserAccessibilityAndroid::CanScrollBackward() const {
if (IsSlider()) { if (IsSlider()) {
// If it's not a native INPUT element, then increment and decrement
// won't work.
std::string html_tag =
GetStringAttribute(ax::mojom::StringAttribute::kHtmlTag);
if (html_tag != "input")
return false;
float value = GetFloatAttribute(ax::mojom::FloatAttribute::kValueForRange); float value = GetFloatAttribute(ax::mojom::FloatAttribute::kValueForRange);
float min = GetFloatAttribute(ax::mojom::FloatAttribute::kMinValueForRange); float min = GetFloatAttribute(ax::mojom::FloatAttribute::kMinValueForRange);
return value > min; return value > min;
......
...@@ -466,8 +466,9 @@ public class WebContentsAccessibilityImpl extends AccessibilityNodeProvider ...@@ -466,8 +466,9 @@ public class WebContentsAccessibilityImpl extends AccessibilityNodeProvider
} }
case ACTION_SET_TEXT: { case ACTION_SET_TEXT: {
if (!WebContentsAccessibilityImplJni.get().isEditableText( if (!WebContentsAccessibilityImplJni.get().isEditableText(
mNativeObj, WebContentsAccessibilityImpl.this, virtualViewId)) mNativeObj, WebContentsAccessibilityImpl.this, virtualViewId)) {
return false; return false;
}
if (arguments == null) return false; if (arguments == null) return false;
String newText = arguments.getString(ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE); String newText = arguments.getString(ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE);
if (newText == null) return false; if (newText == null) return false;
...@@ -481,8 +482,9 @@ public class WebContentsAccessibilityImpl extends AccessibilityNodeProvider ...@@ -481,8 +482,9 @@ public class WebContentsAccessibilityImpl extends AccessibilityNodeProvider
} }
case AccessibilityNodeInfo.ACTION_SET_SELECTION: { case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
if (!WebContentsAccessibilityImplJni.get().isEditableText( if (!WebContentsAccessibilityImplJni.get().isEditableText(
mNativeObj, WebContentsAccessibilityImpl.this, virtualViewId)) mNativeObj, WebContentsAccessibilityImpl.this, virtualViewId)) {
return false; return false;
}
int selectionStart = 0; int selectionStart = 0;
int selectionEnd = 0; int selectionEnd = 0;
if (arguments != null) { if (arguments != null) {
...@@ -808,8 +810,9 @@ public class WebContentsAccessibilityImpl extends AccessibilityNodeProvider ...@@ -808,8 +810,9 @@ public class WebContentsAccessibilityImpl extends AccessibilityNodeProvider
mNativeObj, WebContentsAccessibilityImpl.this, newAccessibilityFocusId); mNativeObj, WebContentsAccessibilityImpl.this, newAccessibilityFocusId);
if (WebContentsAccessibilityImplJni.get().isAutofillPopupNode( if (WebContentsAccessibilityImplJni.get().isAutofillPopupNode(
mNativeObj, WebContentsAccessibilityImpl.this, mAccessibilityFocusId)) mNativeObj, WebContentsAccessibilityImpl.this, mAccessibilityFocusId)) {
mAutofillPopupView.requestFocus(); mAutofillPopupView.requestFocus();
}
sendAccessibilityEvent( sendAccessibilityEvent(
mAccessibilityFocusId, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); mAccessibilityFocusId, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
...@@ -1004,7 +1007,14 @@ public class WebContentsAccessibilityImpl extends AccessibilityNodeProvider ...@@ -1004,7 +1007,14 @@ public class WebContentsAccessibilityImpl extends AccessibilityNodeProvider
@CalledByNative @CalledByNative
private void handleSliderChanged(int id) { private void handleSliderChanged(int id) {
sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_SCROLLED); // If the node has accessibility focus, fire TYPE_VIEW_SELECTED, which triggers
// TalkBack to announce the change. If not, fire TYPE_VIEW_SCROLLED, which
// does not trigger an immediate announcement but still ensures some event is fired.
if (mAccessibilityFocusId == id) {
sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_SELECTED);
} else {
sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_SCROLLED);
}
} }
@CalledByNative @CalledByNative
......
...@@ -113,6 +113,10 @@ bool AXSlider::OnNativeSetValueAction(const String& value) { ...@@ -113,6 +113,10 @@ bool AXSlider::OnNativeSetValueAction(const String& value) {
// Fire change event manually, as LayoutSlider::setValueForPosition does. // Fire change event manually, as LayoutSlider::setValueForPosition does.
input->DispatchFormControlChangeEvent(); input->DispatchFormControlChangeEvent();
// Ensure the AX node is updated.
AXObjectCache().MarkAXObjectDirty(this, false);
return true; return true;
} }
......
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