Skip to content

Commit

Permalink
Introduce internal accessibility role for the <math> tag
Browse files Browse the repository at this point in the history
Typical use case for ARIA role="math" [1] is to provide HTML markup with
math content in a textual representation. Chrome currently treats nodes
with such a role as a leaf, with presentational children and supporting
name from contents. This is however the contrary to what is desired for
MathML's <math> element (at least on ATK and AX API), for which the
MathML descendants are expected to be exposed in the accessibility tree
and for which spoken text is determined by the AT from these
descendants.

The MathML AAM spec currently does not specify how to map the <math>
tag [2] but the HTML AAM spec says it should use role="math"
with WAI-ARIA mapping [3]. This CL introduces an internal mathMLMath
role that is used for the default role of the <math> tag and is
following the same mapping. It enables the exposure difference
mentioned above while still preserving backward compatibility for
content using role="math". While MathMLCore is disabled, the <math>
tag remains mapped to role="math" by default.

AX-Relnotes: n/a.

[1] https://w3c.github.io/aria/#math
[2] w3c/mathml-aam#9
[3] https://w3c.github.io/html-aam/#html-element-role-mappings

Bug: 6606, 1038895, 1051115
Change-Id: I47dedcb53e8496e40142dc5d2d53c1f2ebe6b918
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3222742
Commit-Queue: Frédéric Wang <[email protected]>
Reviewed-by: Tom Sepez <[email protected]>
Reviewed-by: Nektarios Paisios <[email protected]>
Cr-Commit-Position: refs/heads/main@{#933395}
  • Loading branch information
fred-wang authored and Chromium LUCI CQ committed Oct 20, 2021
1 parent 485ef27 commit 6ee9585
Show file tree
Hide file tree
Showing 25 changed files with 85 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1461,6 +1461,7 @@ std::u16string BrowserAccessibilityAndroid::GetRoleDescription() const {
message_id = IDS_AX_ROLE_MARQUEE;
break;
case ax::mojom::Role::kMath:
case ax::mojom::Role::kMathMLMath:
message_id = IDS_AX_ROLE_MATH;
break;
case ax::mojom::Role::kMenu:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2081,6 +2081,7 @@ - (NSString*)roleDescription {
return base::SysUTF16ToNSString(
content_client->GetLocalizedString(IDS_AX_ROLE_MARK));
case ax::mojom::Role::kMath:
case ax::mojom::Role::kMathMLMath:
return base::SysUTF16ToNSString(
content_client->GetLocalizedString(IDS_AX_ROLE_MATH));
case ax::mojom::Role::kNavigation:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1200,7 +1200,8 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_innerHTML(BSTR* innerHTML) {
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!owner())
return E_FAIL;
if (owner()->GetRole() != ax::mojom::Role::kMath)
if (owner()->GetRole() != ax::mojom::Role::kMath &&
owner()->GetRole() != ax::mojom::Role::kMathMLMath)
return E_NOTIMPL;

std::u16string inner_html =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
android.webkit.WebView focusable focused scrollable
++android.view.View
++++android.view.View role_description='math' name='%F0%9D%90%B4 2 + %F0%9D%90%B5 2'
++++android.view.View role_description='math'
++++++android.widget.TextView name='%F0%9D%90%B4'
++++++android.widget.TextView name='2'
++++++android.widget.TextView name='+'
++++++android.widget.TextView name='%F0%9D%90%B5'
++++++android.widget.TextView name='2'
++++++android.widget.TextView name='2'
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[document web]
++[section]
++++[math] name='%F0%9D%90%B4 2 + %F0%9D%90%B5 2'
++++[math]
++++++[section]
++++++++[static] name='%F0%9D%90%B4'
++++++[section]
Expand All @@ -10,4 +10,4 @@
++++++[section]
++++++++[static] name='%F0%9D%90%B5'
++++++[section]
++++++++[static] name='2'
++++++++[static] name='2'
4 changes: 2 additions & 2 deletions content/test/data/accessibility/html/math-expected-mac.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
AXWebArea AXRoleDescription='HTML content'
++AXGroup AXRoleDescription='group'
++++AXGroup AXSubrole=AXDocumentMath AXRoleDescription='math' AXTitle='%F0%9D%90%B4 2 + %F0%9D%90%B5 2'
++++AXGroup AXSubrole=AXDocumentMath AXRoleDescription='math'
++++++AXGroup AXRoleDescription='group'
++++++++AXStaticText AXRoleDescription='text' AXValue='%F0%9D%90%B4'
++++++AXGroup AXRoleDescription='group'
Expand All @@ -10,4 +10,4 @@ AXWebArea AXRoleDescription='HTML content'
++++++AXGroup AXRoleDescription='group'
++++++++AXStaticText AXRoleDescription='text' AXValue='%F0%9D%90%B5'
++++++AXGroup AXRoleDescription='group'
++++++++AXStaticText AXRoleDescription='text' AXValue='2'
++++++++AXStaticText AXRoleDescription='text' AXValue='2'
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Document
++Group IsControlElement=false
++++Group Name='%F0%9D%90%B4 2 + %F0%9D%90%B5 2'
++++Group IsControlElement=false
++++++Group IsControlElement=false
++++++++Text Name='%F0%9D%90%B4'
++++++Group IsControlElement=false
Expand All @@ -10,4 +10,4 @@ Document
++++++Group IsControlElement=false
++++++++Text Name='%F0%9D%90%B5'
++++++Group IsControlElement=false
++++++++Text Name='2'
++++++++Text Name='2'
4 changes: 2 additions & 2 deletions content/test/data/accessibility/html/math-expected-win.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
++IA2_ROLE_SECTION
++++ROLE_SYSTEM_EQUATION name='%F0%9D%90%B4 2 + %F0%9D%90%B5 2' inner_html='<newline> <mrow><newline> <msup><mi>%F0%9D%90%B4</mi><mn>2</mn></msup><newline> <mo>+</mo><newline> <msup><mi>%F0%9D%90%B5</mi><mn>2</mn></msup><newline> </mrow><newline> '
++++ROLE_SYSTEM_EQUATION inner_html='<newline> <mrow><newline> <msup><mi>%F0%9D%90%B4</mi><mn>2</mn></msup><newline> <mo>+</mo><newline> <msup><mi>%F0%9D%90%B5</mi><mn>2</mn></msup><newline> </mrow><newline> '
++++++IA2_ROLE_SECTION
++++++++ROLE_SYSTEM_STATICTEXT name='%F0%9D%90%B4'
++++++IA2_ROLE_SECTION
Expand All @@ -10,4 +10,4 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
++++++IA2_ROLE_SECTION
++++++++ROLE_SYSTEM_STATICTEXT name='%F0%9D%90%B5'
++++++IA2_ROLE_SECTION
++++++++ROLE_SYSTEM_STATICTEXT name='2'
++++++++ROLE_SYSTEM_STATICTEXT name='2'
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
rootWebArea
++genericContainer ignored
++++genericContainer ignored
++++++radioButton name='Both%C2%A01 + 4%C2%A0and%C2%A02 + 3' checkedState=false
++++++radioButton name='Both%C2%A01 + 4%C2%A0and%C2%A0' checkedState=false
++++++++staticText name='Both%C2%A0'
++++++++++inlineTextBox name='Both%C2%A0'
++++++++math name='1 + 4'
Expand All @@ -16,7 +16,7 @@ rootWebArea
++++++++++++++inlineTextBox name='4'
++++++++staticText name='%C2%A0and%C2%A0'
++++++++++inlineTextBox name='%C2%A0and%C2%A0'
++++++++math name='2 + 3'
++++++++mathMLMath
++++++++++genericContainer
++++++++++++staticText name='2'
++++++++++++++inlineTextBox name='2'
Expand All @@ -25,4 +25,4 @@ rootWebArea
++++++++++++++inlineTextBox name='+'
++++++++++genericContainer
++++++++++++staticText name='3'
++++++++++++++inlineTextBox name='3'
++++++++++++++inlineTextBox name='3'
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<div role="radio" tabindex=0>
<span>Both&nbsp;</span>
<math><mn>1</mn><mo>+</mo><mn>4</mn></math>
<math role="math"><mn>1</mn><mo>+</mo><mn>4</mn></math>
<span>&nbsp;and&nbsp;</span>
<math><mn>2</mn><mo>+</mo><mn>3</mn></math>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ rootWebArea htmlTag='#document'
++++++++genericContainer className='html-namespace' htmlTag='svg' name='created'
++++++++genericContainer className='custom-namespace' htmlTag='svg' name='created'
++++++genericContainer className='math-container' htmlTag='div'
++++++++math htmlTag='math' name='original'
++++++++mathMLMath htmlTag='math' name='original'
++++++++genericContainer className='html-namespace' htmlTag='math' name='created'
++++++++genericContainer className='custom-namespace' htmlTag='math' name='created'
++++++staticText name='Done'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ rootWebArea
++++++paragraph
++++++++staticText name='This test passes if the 'math' node in the accessibility tree is empty:'
++++++++++inlineTextBox name='This test passes if the 'math' node in the accessibility tree is empty:'
++++++math
++++++mathMLMath
1 change: 1 addition & 0 deletions extensions/common/api/automation.idl
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@
mark,
marquee,
math,
mathMLMath,
menu,
menuBar,
menuItem,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
#include "third_party/blink/renderer/modules/accessibility/ax_relation_cache.h"
#include "third_party/blink/renderer/platform/graphics/image_data_buffer.h"
#include "third_party/blink/renderer/platform/keyboard_codes.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
#include "third_party/blink/renderer/platform/text/text_direction.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
Expand Down Expand Up @@ -557,6 +558,7 @@ AXObjectInclusion AXNodeObject::ShouldIncludeBasedOnSemantics(
ax::mojom::blink::Role::kMain,
ax::mojom::blink::Role::kMark,
ax::mojom::blink::Role::kMath,
ax::mojom::blink::Role::kMathMLMath,
ax::mojom::blink::Role::kMeter,
ax::mojom::blink::Role::kNavigation,
ax::mojom::blink::Role::kPluginObject,
Expand Down Expand Up @@ -1066,8 +1068,11 @@ ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const {

// Mapping of MathML elements. See https://w3c.github.io/mathml-aam/
if (auto* element = DynamicTo<MathMLElement>(GetNode())) {
if (element->HasTagName(mathml_names::kMathTag))
return ax::mojom::blink::Role::kMath;
if (element->HasTagName(mathml_names::kMathTag)) {
return RuntimeEnabledFeatures::MathMLCoreEnabled()
? ax::mojom::blink::Role::kMathMLMath
: ax::mojom::blink::Role::kMath;
}
// TODO(crbug.com/6606): Map more MathML elements.
if (element->HasTagName(mathml_names::kMspaceTag))
return ax::mojom::blink::Role::kNone;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1527,7 +1527,8 @@ void AXObject::SerializeHTMLAttributes(ui::AXNodeData* node_data) {
// TODO(nektar): Turn off kHTMLAccessibilityMode for automation and Mac
// and remove ifdef.
#if defined(OS_WIN) || defined(OS_CHROMEOS)
if (node_data->role == ax::mojom::blink::Role::kMath &&
if ((node_data->role == ax::mojom::blink::Role::kMath ||
node_data->role == ax::mojom::blink::Role::kMathMLMath) &&
element->innerHTML().length()) {
TruncateAndAddStringAttribute(node_data,
ax::mojom::blink::StringAttribute::kInnerHtml,
Expand Down Expand Up @@ -5639,6 +5640,7 @@ bool AXObject::SupportsNameFromContents(bool recursive) const {
case ax::mojom::blink::Role::kLog:
case ax::mojom::blink::Role::kMain:
case ax::mojom::blink::Role::kMarquee:
case ax::mojom::blink::Role::kMathMLMath:
case ax::mojom::blink::Role::kMenuListPopup:
case ax::mojom::blink::Role::kMenu:
case ax::mojom::blink::Role::kMenuBar:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ x
a
/
b

𝑥
+
𝑎
/
𝑏
Most important heading here
Google Chrome

Expand Down Expand Up @@ -99,6 +105,24 @@ AXRole: AXGenericContainer
AXRole: AXGenericContainer
AXRole: AXStaticText "b"
AXRole: AXInlineTextBox "b"
AXRole: AXMathMLMath
AXRole: AXGenericContainer
AXRole: AXGenericContainer
AXRole: AXStaticText "𝑥"
AXRole: AXInlineTextBox "𝑥"
AXRole: AXGenericContainer
AXRole: AXStaticText "+"
AXRole: AXInlineTextBox "+"
AXRole: AXGenericContainer
AXRole: AXGenericContainer
AXRole: AXStaticText "𝑎"
AXRole: AXInlineTextBox "𝑎"
AXRole: AXGenericContainer
AXRole: AXStaticText "/"
AXRole: AXInlineTextBox "/"
AXRole: AXGenericContainer
AXRole: AXStaticText "𝑏"
AXRole: AXInlineTextBox "𝑏"
AXRole: AXMain
AXRole: AXArticle
AXRole: AXHeaderAsNonLandmark
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ <h1>Heading</h1>
<dt>Milk</dt>
<dd>- white cold drink</dd>
</dl>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<math role="math" xmlns="http://www.w3.org/1998/Math/MathML">
<mrow>
<mi> x </mi>
<mo> + </mo>
Expand All @@ -28,6 +28,17 @@ <h1>Heading</h1>
</mrow>
</mrow>
</math>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mrow>
<mi>x</mi>
<mo>+</mo>
<mrow>
<mi>a</mi>
<mo>/</mo>
<mi>b</mi>
</mrow>
</mrow>
</math>
<main>
<article>
<header>
Expand Down
1 change: 1 addition & 0 deletions third_party/closure_compiler/externs/automation.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ chrome.automation.RoleType = {
MARK: 'mark',
MARQUEE: 'marquee',
MATH: 'math',
MATH_MLMATH: 'mathMLMath',
MENU: 'menu',
MENU_BAR: 'menuBar',
MENU_ITEM: 'menuItem',
Expand Down
2 changes: 2 additions & 0 deletions ui/accessibility/ax_enum_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,8 @@ const char* ToString(ax::mojom::Role role) {
return "marquee";
case ax::mojom::Role::kMath:
return "math";
case ax::mojom::Role::kMathMLMath:
return "mathMLMath";
case ax::mojom::Role::kMenu:
return "menu";
case ax::mojom::Role::kMenuBar:
Expand Down
5 changes: 3 additions & 2 deletions ui/accessibility/ax_enums.mojom
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ enum Event {
// Web: this attribute is only used in web content.
//
// Native: this attribute is only used in native UI.
// Next version: 2
// Next value: 187
// Next version: 3
// Next value: 188
[Extensible, Stable, Uuid="d258eb73-e0cc-490c-b881-80ee11d3fec2"]
enum Role {
// Used for role="none"/"presentation" -- ignored in platform tree.
Expand Down Expand Up @@ -246,6 +246,7 @@ enum Role {
kMark = 119,
kMarquee = 120,
kMath = 121,
[MinVersion=2] kMathMLMath = 187,
kMenu = 122,
kMenuBar = 123,
kMenuItem = 124,
Expand Down
4 changes: 3 additions & 1 deletion ui/accessibility/ax_node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1707,7 +1707,9 @@ bool AXNode::IsLeaf() const {
return true;
case ax::mojom::Role::kCheckBox:
case ax::mojom::Role::kListBoxOption:
case ax::mojom::Role::kMath: // role="math" is flat, unlike <math>.
// role="math" is flat. But always return false for kMathMLMath since the
// children of a <math> tag should be exposed to make MathML accessible.
case ax::mojom::Role::kMath:
case ax::mojom::Role::kMenuListOption:
case ax::mojom::Role::kMenuItem:
case ax::mojom::Role::kMenuItemCheckBox:
Expand Down
3 changes: 3 additions & 0 deletions ui/accessibility/ax_role_properties.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ bool HasPresentationalChildren(const ax::mojom::Role role) {
case ax::mojom::Role::kButton:
case ax::mojom::Role::kCheckBox:
case ax::mojom::Role::kMath:
// Return false for kMathMLMath, since the children of a <math> tag should
// be exposed to make MathML accessible.
case ax::mojom::Role::kMenuItemCheckBox:
case ax::mojom::Role::kMenuItemRadio:
case ax::mojom::Role::kMenuListOption:
Expand Down Expand Up @@ -570,6 +572,7 @@ bool IsSection(const ax::mojom::Role role) {
case ax::mojom::Role::kLog:
case ax::mojom::Role::kMarquee:
case ax::mojom::Role::kMath:
case ax::mojom::Role::kMathMLMath:
case ax::mojom::Role::kNote:
case ax::mojom::Role::kProgressIndicator: // Subclass of kStatus.
case ax::mojom::Role::kRow: // Subclass of kGroup.
Expand Down
1 change: 1 addition & 0 deletions ui/accessibility/platform/ax_platform_node_auralinux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2851,6 +2851,7 @@ AtkRole AXPlatformNodeAuraLinux::GetAtkRole() const {
case ax::mojom::Role::kMark:
return kStaticRole;
case ax::mojom::Role::kMath:
case ax::mojom::Role::kMathMLMath:
return ATK_ROLE_MATH;
case ax::mojom::Role::kMarquee:
return ATK_ROLE_MARQUEE;
Expand Down
2 changes: 2 additions & 0 deletions ui/accessibility/platform/ax_platform_node_cocoa.mm
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ RoleMap BuildRoleMap() {
{ax::mojom::Role::kMark, NSAccessibilityGroupRole},
{ax::mojom::Role::kMarquee, NSAccessibilityGroupRole},
{ax::mojom::Role::kMath, NSAccessibilityGroupRole},
{ax::mojom::Role::kMathMLMath, NSAccessibilityGroupRole},
{ax::mojom::Role::kMenu, NSAccessibilityMenuRole},
{ax::mojom::Role::kMenuBar, NSAccessibilityMenuBarRole},
{ax::mojom::Role::kMenuItem, NSAccessibilityMenuItemRole},
Expand Down Expand Up @@ -266,6 +267,7 @@ RoleMap BuildSubroleMap() {
{ax::mojom::Role::kMain, @"AXLandmarkMain"},
{ax::mojom::Role::kMarquee, @"AXApplicationMarquee"},
{ax::mojom::Role::kMath, @"AXDocumentMath"},
{ax::mojom::Role::kMathMLMath, @"AXDocumentMath"},
{ax::mojom::Role::kNavigation, @"AXLandmarkNavigation"},
{ax::mojom::Role::kNote, @"AXDocumentNote"},
{ax::mojom::Role::kRegion, @"AXLandmarkRegion"},
Expand Down
3 changes: 3 additions & 0 deletions ui/accessibility/platform/ax_platform_node_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5537,6 +5537,7 @@ int AXPlatformNodeWin::MSAARole() {
return ROLE_SYSTEM_ANIMATION;

case ax::mojom::Role::kMath:
case ax::mojom::Role::kMathMLMath:
return ROLE_SYSTEM_EQUATION;

case ax::mojom::Role::kMenu:
Expand Down Expand Up @@ -6367,6 +6368,7 @@ std::wstring AXPlatformNodeWin::UIAAriaRole() {
return L"marquee";

case ax::mojom::Role::kMath:
case ax::mojom::Role::kMathMLMath:
return L"group";

case ax::mojom::Role::kMenu:
Expand Down Expand Up @@ -7030,6 +7032,7 @@ LONG AXPlatformNodeWin::ComputeUIAControlType() { // NOLINT(runtime/int)
return UIA_TextControlTypeId;

case ax::mojom::Role::kMath:
case ax::mojom::Role::kMathMLMath:
return UIA_GroupControlTypeId;

case ax::mojom::Role::kMenu:
Expand Down

0 comments on commit 6ee9585

Please sign in to comment.