Commit 6bee55cd authored by Aaron Leventhal's avatar Aaron Leventhal Committed by Commit Bot

Don't expose native mixed radios as ax mixed

Do not expose native radio mixed state as accessibility mixed state, because
this confuses the JAWS screen reader, which reports a mixed radio as
both checked and partially checked. A native mixed native radio
button sinply means no radio buttons have been checked in the group yet.

Bug: 739752
Change-Id: Icdfc404b6d50d1ecb25b5b3221c79ba0da2f7400
Reviewed-on: https://chromium-review.googlesource.com/561817
Commit-Queue: Aaron Leventhal <aleventhal@chromium.org>
Commit-Queue: Nektarios Paisios <nektar@chromium.org>
Reviewed-by: default avatarNektarios Paisios <nektar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#484990}
parent efbc4622
...@@ -6,20 +6,20 @@ rootWebArea ...@@ -6,20 +6,20 @@ rootWebArea
++++listBoxOption selectable name='Item 1' setSize=2 posInSet=1 ++++listBoxOption selectable name='Item 1' setSize=2 posInSet=1
++++listBoxOption selectable name='Item 2' setSize=2 posInSet=2 ++++listBoxOption selectable name='Item 2' setSize=2 posInSet=2
++form ++form
++++radioButton setSize=4 posInSet=3 checkedState=3 ++++radioButton setSize=4 posInSet=3 checkedState=1
++++staticText name='1' ++++staticText name='1'
++++++inlineTextBox name='1' ++++++inlineTextBox name='1'
++++lineBreak name='<newline>' ++++lineBreak name='<newline>'
++++++inlineTextBox name='<newline>' ++++++inlineTextBox name='<newline>'
++++radioButton setSize=4 posInSet=4 checkedState=3 ++++radioButton setSize=4 posInSet=4 checkedState=1
++++staticText name='2' ++++staticText name='2'
++++++inlineTextBox name='2' ++++++inlineTextBox name='2'
++radioButton setSize=2 posInSet=1 checkedState=3 ++radioButton setSize=2 posInSet=1 checkedState=1
++staticText name='Apple' ++staticText name='Apple'
++++inlineTextBox name='Apple' ++++inlineTextBox name='Apple'
++lineBreak name='<newline>' ++lineBreak name='<newline>'
++++inlineTextBox name='<newline>' ++++inlineTextBox name='<newline>'
++radioButton setSize=2 posInSet=2 checkedState=3 ++radioButton setSize=2 posInSet=2 checkedState=1
++staticText name='Banana' ++staticText name='Banana'
++++inlineTextBox name='Banana' ++++inlineTextBox name='Banana'
++group name='Cake' ++group name='Cake'
...@@ -38,6 +38,6 @@ rootWebArea ...@@ -38,6 +38,6 @@ rootWebArea
++++++++++inlineTextBox name='red' ++++++++++inlineTextBox name='red'
++++++lineBreak name='<newline>' ++++++lineBreak name='<newline>'
++++++++inlineTextBox name='<newline>' ++++++++inlineTextBox name='<newline>'
++++++radioButton name='blue' setSize=1 posInSet=1 checkedState=3 ++++++radioButton name='blue' setSize=1 posInSet=1 checkedState=1
++staticText name='Done' ++staticText name='Done'
++++inlineTextBox name='Done' ++++inlineTextBox name='Done'
...@@ -6,15 +6,15 @@ AXWebArea AXRoleDescription='HTML content' ...@@ -6,15 +6,15 @@ AXWebArea AXRoleDescription='HTML content'
++++AXStaticText AXRoleDescription='text' AXValue='Item 1' AXARIASetSize='2' AXARIAPosInSet='1' ++++AXStaticText AXRoleDescription='text' AXValue='Item 1' AXARIASetSize='2' AXARIAPosInSet='1'
++++AXStaticText AXRoleDescription='text' AXValue='Item 2' AXARIASetSize='2' AXARIAPosInSet='2' ++++AXStaticText AXRoleDescription='text' AXValue='Item 2' AXARIASetSize='2' AXARIAPosInSet='2'
++AXGroup AXRoleDescription='form' ++AXGroup AXRoleDescription='form'
++++AXRadioButton AXRoleDescription='radio button' AXValue='2' AXARIASetSize='4' AXARIAPosInSet='3' ++++AXRadioButton AXRoleDescription='radio button' AXValue='0' AXARIASetSize='4' AXARIAPosInSet='3'
++++AXStaticText AXRoleDescription='text' AXValue='1' ++++AXStaticText AXRoleDescription='text' AXValue='1'
++++AXUnknown AXRoleDescription='unknown' AXTitle='<newline>' ++++AXUnknown AXRoleDescription='unknown' AXTitle='<newline>'
++++AXRadioButton AXRoleDescription='radio button' AXValue='2' AXARIASetSize='4' AXARIAPosInSet='4' ++++AXRadioButton AXRoleDescription='radio button' AXValue='0' AXARIASetSize='4' AXARIAPosInSet='4'
++++AXStaticText AXRoleDescription='text' AXValue='2' ++++AXStaticText AXRoleDescription='text' AXValue='2'
++AXRadioButton AXRoleDescription='radio button' AXValue='2' AXARIASetSize='2' AXARIAPosInSet='1' ++AXRadioButton AXRoleDescription='radio button' AXValue='0' AXARIASetSize='2' AXARIAPosInSet='1'
++AXStaticText AXRoleDescription='text' AXValue='Apple' ++AXStaticText AXRoleDescription='text' AXValue='Apple'
++AXUnknown AXRoleDescription='unknown' AXTitle='<newline>' ++AXUnknown AXRoleDescription='unknown' AXTitle='<newline>'
++AXRadioButton AXRoleDescription='radio button' AXValue='2' AXARIASetSize='2' AXARIAPosInSet='2' ++AXRadioButton AXRoleDescription='radio button' AXValue='0' AXARIASetSize='2' AXARIAPosInSet='2'
++AXStaticText AXRoleDescription='text' AXValue='Banana' ++AXStaticText AXRoleDescription='text' AXValue='Banana'
++AXGroup AXRoleDescription='group' AXTitle='Cake' ++AXGroup AXRoleDescription='group' AXTitle='Cake'
++++AXGroup AXRoleDescription='group' ++++AXGroup AXRoleDescription='group'
...@@ -28,5 +28,5 @@ AXWebArea AXRoleDescription='HTML content' ...@@ -28,5 +28,5 @@ AXWebArea AXRoleDescription='HTML content'
++++++AXGroup AXRoleDescription='group' ++++++AXGroup AXRoleDescription='group'
++++++++AXStaticText AXRoleDescription='text' AXValue='red' ++++++++AXStaticText AXRoleDescription='text' AXValue='red'
++++++AXUnknown AXRoleDescription='unknown' AXTitle='<newline>' ++++++AXUnknown AXRoleDescription='unknown' AXTitle='<newline>'
++++++AXRadioButton AXRoleDescription='radio button' AXTitle='blue' AXValue='2' AXARIASetSize='1' AXARIAPosInSet='1' ++++++AXRadioButton AXRoleDescription='radio button' AXTitle='blue' AXValue='0' AXARIASetSize='1' AXARIAPosInSet='1'
++AXStaticText AXRoleDescription='text' AXValue='Done' ++AXStaticText AXRoleDescription='text' AXValue='Done'
...@@ -6,15 +6,15 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ...@@ -6,15 +6,15 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
++++ROLE_SYSTEM_LISTITEM name='Item 1' FOCUSABLE setsize:2 posinset:1 ++++ROLE_SYSTEM_LISTITEM name='Item 1' FOCUSABLE setsize:2 posinset:1
++++ROLE_SYSTEM_LISTITEM name='Item 2' FOCUSABLE setsize:2 posinset:2 ++++ROLE_SYSTEM_LISTITEM name='Item 2' FOCUSABLE setsize:2 posinset:2
++IA2_ROLE_FORM ++IA2_ROLE_FORM
++++ROLE_SYSTEM_RADIOBUTTON MIXED FOCUSABLE IA2_STATE_CHECKABLE setsize:4 posinset:3 checkable:true ++++ROLE_SYSTEM_RADIOBUTTON FOCUSABLE IA2_STATE_CHECKABLE setsize:4 posinset:3 checkable:true
++++ROLE_SYSTEM_STATICTEXT name='1' ++++ROLE_SYSTEM_STATICTEXT name='1'
++++ROLE_SYSTEM_WHITESPACE name='<newline>' ++++ROLE_SYSTEM_WHITESPACE name='<newline>'
++++ROLE_SYSTEM_RADIOBUTTON MIXED FOCUSABLE IA2_STATE_CHECKABLE setsize:4 posinset:4 checkable:true ++++ROLE_SYSTEM_RADIOBUTTON FOCUSABLE IA2_STATE_CHECKABLE setsize:4 posinset:4 checkable:true
++++ROLE_SYSTEM_STATICTEXT name='2' ++++ROLE_SYSTEM_STATICTEXT name='2'
++ROLE_SYSTEM_RADIOBUTTON MIXED FOCUSABLE IA2_STATE_CHECKABLE setsize:2 posinset:1 checkable:true ++ROLE_SYSTEM_RADIOBUTTON FOCUSABLE IA2_STATE_CHECKABLE setsize:2 posinset:1 checkable:true
++ROLE_SYSTEM_STATICTEXT name='Apple' ++ROLE_SYSTEM_STATICTEXT name='Apple'
++ROLE_SYSTEM_WHITESPACE name='<newline>' ++ROLE_SYSTEM_WHITESPACE name='<newline>'
++ROLE_SYSTEM_RADIOBUTTON MIXED FOCUSABLE IA2_STATE_CHECKABLE setsize:2 posinset:2 checkable:true ++ROLE_SYSTEM_RADIOBUTTON FOCUSABLE IA2_STATE_CHECKABLE setsize:2 posinset:2 checkable:true
++ROLE_SYSTEM_STATICTEXT name='Banana' ++ROLE_SYSTEM_STATICTEXT name='Banana'
++ROLE_SYSTEM_GROUPING name='Cake' ++ROLE_SYSTEM_GROUPING name='Cake'
++++IA2_ROLE_LABEL ++++IA2_ROLE_LABEL
...@@ -28,5 +28,5 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ...@@ -28,5 +28,5 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
++++++IA2_ROLE_LABEL ++++++IA2_ROLE_LABEL
++++++++ROLE_SYSTEM_STATICTEXT name='red' ++++++++ROLE_SYSTEM_STATICTEXT name='red'
++++++ROLE_SYSTEM_WHITESPACE name='<newline>' ++++++ROLE_SYSTEM_WHITESPACE name='<newline>'
++++++ROLE_SYSTEM_RADIOBUTTON name='blue' MIXED FOCUSABLE IA2_STATE_CHECKABLE setsize:1 posinset:1 checkable:true ++++++ROLE_SYSTEM_RADIOBUTTON name='blue' FOCUSABLE IA2_STATE_CHECKABLE setsize:1 posinset:1 checkable:true
++ROLE_SYSTEM_STATICTEXT name='Done' ++ROLE_SYSTEM_STATICTEXT name='Done'
\ No newline at end of file
...@@ -12,7 +12,7 @@ rootWebArea name='Action verbs' ...@@ -12,7 +12,7 @@ rootWebArea name='Action verbs'
++textField ++textField
++checkBox defaultActionVerb=2 checkedState=1 ++checkBox defaultActionVerb=2 checkedState=1
++checkBox defaultActionVerb=8 checkedState=2 ++checkBox defaultActionVerb=8 checkedState=2
++radioButton defaultActionVerb=7 checkedState=3 ++radioButton defaultActionVerb=7 checkedState=1
++switch name='ARIA Switch' defaultActionVerb=2 checkedState=1 ++switch name='ARIA Switch' defaultActionVerb=2 checkedState=1
++popUpButton collapsed haspopup defaultActionVerb=5 ++popUpButton collapsed haspopup defaultActionVerb=5
++++menuListPopup invisible activedescendantId=menuListOption ++++menuListPopup invisible activedescendantId=menuListOption
......
rootWebArea rootWebArea
++form ++form
++++radioButton checkedState=3 radioGroupIds=radioButton ++++radioButton checkedState=1 radioGroupIds=radioButton
++++staticText name='Radio1' ++++staticText name='Radio1'
++++++inlineTextBox name='Radio1' ++++++inlineTextBox name='Radio1'
++++lineBreak name='<newline>' ++++lineBreak name='<newline>'
++++++inlineTextBox name='<newline>' ++++++inlineTextBox name='<newline>'
++++radioButton checkedState=3 radioGroupIds=radioButton ++++radioButton checkedState=1 radioGroupIds=radioButton
++++staticText name='Radio2' ++++staticText name='Radio2'
++++++inlineTextBox name='Radio2' ++++++inlineTextBox name='Radio2'
++form ++form
++++radioButton name='Radio3' checkedState=1 radioGroupIds=radioButton,radioButton ++++radioButton name='Radio3' checkedState=1 radioGroupIds=radioButton,radioButton
++++radioButton name='Radio4' checkedState=2 radioGroupIds=radioButton,radioButton ++++radioButton name='Radio4' checkedState=2 radioGroupIds=radioButton,radioButton
++form ++form
++++radioButton name='Radio5' checkedState=3 radioGroupIds=radioButton ++++radioButton name='Radio5' checkedState=1 radioGroupIds=radioButton
++++radioButton name='Radio6' checkedState=2 radioGroupIds=radioButton ++++radioButton name='Radio6' checkedState=2 radioGroupIds=radioButton
\ No newline at end of file
AXWebArea AXWebArea
++AXGroup ++AXGroup
++++AXRadioButton AXValue='2' AXLinkedUIElements=["AXRadioButton 2"] ++++AXRadioButton AXValue='0' AXLinkedUIElements=["AXRadioButton 0"]
++++AXStaticText AXValue='Radio1' ++++AXStaticText AXValue='Radio1'
++++AXUnknown AXTitle='<newline>' ++++AXUnknown AXTitle='<newline>'
++++AXRadioButton AXValue='2' AXLinkedUIElements=["AXRadioButton 2"] ++++AXRadioButton AXValue='0' AXLinkedUIElements=["AXRadioButton 0"]
++++AXStaticText AXValue='Radio2' ++++AXStaticText AXValue='Radio2'
++AXGroup ++AXGroup
++++AXRadioButton AXTitle='Radio3' AXValue='0' AXLinkedUIElements=["AXRadioButton Radio3","AXRadioButton Radio4"] ++++AXRadioButton AXTitle='Radio3' AXValue='0' AXLinkedUIElements=["AXRadioButton Radio3","AXRadioButton Radio4"]
++++AXRadioButton AXTitle='Radio4' AXValue='1' AXLinkedUIElements=["AXRadioButton Radio3","AXRadioButton Radio4"] ++++AXRadioButton AXTitle='Radio4' AXValue='1' AXLinkedUIElements=["AXRadioButton Radio3","AXRadioButton Radio4"]
++AXGroup ++AXGroup
++++AXRadioButton AXTitle='Radio5' AXValue='2' AXLinkedUIElements=["AXRadioButton Radio5"] ++++AXRadioButton AXTitle='Radio5' AXValue='0' AXLinkedUIElements=["AXRadioButton Radio5"]
++++AXRadioButton AXTitle='Radio6' AXValue='1' AXLinkedUIElements=["AXRadioButton Radio6"] ++++AXRadioButton AXTitle='Radio6' AXValue='1' AXLinkedUIElements=["AXRadioButton Radio6"]
\ No newline at end of file
ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0><obj1><obj2>' ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0><obj1><obj2>'
++IA2_ROLE_FORM ia2_hypertext='<obj0>Radio1<newline><obj3>Radio2' ++IA2_ROLE_FORM ia2_hypertext='<obj0>Radio1<newline><obj3>Radio2'
++++ROLE_SYSTEM_RADIOBUTTON MIXED FOCUSABLE IA2_STATE_CHECKABLE checkable:true ++++ROLE_SYSTEM_RADIOBUTTON FOCUSABLE IA2_STATE_CHECKABLE checkable:true
++++ROLE_SYSTEM_STATICTEXT name='Radio1' ia2_hypertext='Radio1' ++++ROLE_SYSTEM_STATICTEXT name='Radio1' ia2_hypertext='Radio1'
++++ROLE_SYSTEM_WHITESPACE name='<newline>' ia2_hypertext='<newline>' ++++ROLE_SYSTEM_WHITESPACE name='<newline>' ia2_hypertext='<newline>'
++++ROLE_SYSTEM_RADIOBUTTON MIXED FOCUSABLE IA2_STATE_CHECKABLE checkable:true ++++ROLE_SYSTEM_RADIOBUTTON FOCUSABLE IA2_STATE_CHECKABLE checkable:true
++++ROLE_SYSTEM_STATICTEXT name='Radio2' ia2_hypertext='Radio2' ++++ROLE_SYSTEM_STATICTEXT name='Radio2' ia2_hypertext='Radio2'
++IA2_ROLE_FORM ia2_hypertext='<obj0><obj1>' ++IA2_ROLE_FORM ia2_hypertext='<obj0><obj1>'
++++ROLE_SYSTEM_RADIOBUTTON name='Radio3' FOCUSABLE IA2_STATE_CHECKABLE checkable:true ia2_hypertext='Radio3' ++++ROLE_SYSTEM_RADIOBUTTON name='Radio3' FOCUSABLE IA2_STATE_CHECKABLE checkable:true ia2_hypertext='Radio3'
++++ROLE_SYSTEM_RADIOBUTTON name='Radio4' CHECKED FOCUSABLE IA2_STATE_CHECKABLE checkable:true ia2_hypertext='Radio4' ++++ROLE_SYSTEM_RADIOBUTTON name='Radio4' CHECKED FOCUSABLE IA2_STATE_CHECKABLE checkable:true ia2_hypertext='Radio4'
++IA2_ROLE_FORM ia2_hypertext='<obj0><obj1>' ++IA2_ROLE_FORM ia2_hypertext='<obj0><obj1>'
++++ROLE_SYSTEM_RADIOBUTTON name='Radio5' MIXED FOCUSABLE IA2_STATE_CHECKABLE checkable:true ia2_hypertext='Radio5' ++++ROLE_SYSTEM_RADIOBUTTON name='Radio5' FOCUSABLE IA2_STATE_CHECKABLE checkable:true ia2_hypertext='Radio5'
++++ROLE_SYSTEM_RADIOBUTTON name='Radio6' CHECKED FOCUSABLE IA2_STATE_CHECKABLE checkable:true ia2_hypertext='Radio6' ++++ROLE_SYSTEM_RADIOBUTTON name='Radio6' CHECKED FOCUSABLE IA2_STATE_CHECKABLE checkable:true ia2_hypertext='Radio6'
...@@ -54,9 +54,9 @@ ...@@ -54,9 +54,9 @@
test(function(t) { test(function(t) {
var ax = axElementById("element3"); var ax = axElementById("element3");
assert_equals(ax.checked, "mixed"); assert_equals(ax.checked, "false");
}, "A native radio that in a group with nothing checked" + }, "A native radio that in a group with nothing checked" +
" must have the mixed state"); " must appear unchecked, not mixed");
test(function(t) { test(function(t) {
var ax = axElementById("element4"); var ax = axElementById("element4");
......
...@@ -539,7 +539,12 @@ AccessibilityCheckedState AXObject::CheckedState() const { ...@@ -539,7 +539,12 @@ AccessibilityCheckedState AXObject::CheckedState() const {
if (!node) if (!node)
return kCheckedStateUndefined; return kCheckedStateUndefined;
if (IsNativeInputInMixedState(node)) // Expose native checkbox mixed state as accessibility mixed state. However,
// do not expose native radio mixed state as accessibility mixed state.
// This would confuse the JAWS screen reader, which reports a mixed radio as
// both checked and partially checked, but a native mixed native radio
// button sinply means no radio buttons have been checked in the group yet.
if (IsNativeCheckboxInMixedState(node))
return kCheckedStateMixed; return kCheckedStateMixed;
if (isHTMLInputElement(*node) && if (isHTMLInputElement(*node) &&
...@@ -551,14 +556,13 @@ AccessibilityCheckedState AXObject::CheckedState() const { ...@@ -551,14 +556,13 @@ AccessibilityCheckedState AXObject::CheckedState() const {
return kCheckedStateFalse; return kCheckedStateFalse;
} }
bool AXObject::IsNativeInputInMixedState(const Node* node) { bool AXObject::IsNativeCheckboxInMixedState(const Node* node) {
if (!isHTMLInputElement(node)) if (!isHTMLInputElement(node))
return false; return false;
const HTMLInputElement* input = toHTMLInputElement(node); const HTMLInputElement* input = toHTMLInputElement(node);
const auto inputType = input->type(); const auto inputType = input->type();
if (inputType != InputTypeNames::checkbox && if (inputType != InputTypeNames::checkbox)
inputType != InputTypeNames::radio)
return false; return false;
return input->ShouldAppearIndeterminate(); return input->ShouldAppearIndeterminate();
} }
......
...@@ -887,7 +887,7 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> { ...@@ -887,7 +887,7 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
private: private:
bool IsCheckable() const; bool IsCheckable() const;
static bool IsNativeInputInMixedState(const Node*); static bool IsNativeCheckboxInMixedState(const Node*);
static bool IncludesARIAWidgetRole(const String&); static bool IncludesARIAWidgetRole(const String&);
static bool HasInteractiveARIAAttribute(const Element&); static bool HasInteractiveARIAAttribute(const Element&);
......
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