Index: ui/accessibility/platform/ax_platform_node_win.cc |
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc |
index 6dcdc91e23134602f6be614e7d9fd9f4f6b9761c..44af7cdc285ee8207b5e4e822dfa6a5157813ef6 100644 |
--- a/ui/accessibility/platform/ax_platform_node_win.cc |
+++ b/ui/accessibility/platform/ax_platform_node_win.cc |
@@ -499,6 +499,18 @@ STDMETHODIMP AXPlatformNodeWin::get_accRole( |
VARIANT var_id, VARIANT* role) { |
AXPlatformNodeWin* target; |
COM_OBJECT_VALIDATE_VAR_ID_1_ARG_AND_GET_TARGET(var_id, role, target); |
+ |
+ // For historical reasons, we return a string (typically |
+ // containing the HTML tag name) as the MSAA role, rather |
+ // than a int. |
+ std::string role_string = target->StringOverrideForMSAARole(); |
+ if (!role_string.empty()) { |
+ role->vt = VT_BSTR; |
+ std::wstring wsTmp(role_string.begin(), role_string.end()); |
+ role->bstrVal = SysAllocString(wsTmp.c_str()); |
+ return S_OK; |
+ } |
+ |
role->vt = VT_I4; |
role->lVal = target->MSAARole(); |
return S_OK; |
@@ -1029,77 +1041,379 @@ int AXPlatformNodeWin::MSAARole() { |
switch (GetData().role) { |
case ui::AX_ROLE_ALERT: |
return ROLE_SYSTEM_ALERT; |
+ |
+ case ui::AX_ROLE_ALERT_DIALOG: |
+ return ROLE_SYSTEM_DIALOG; |
+ |
+ case ui::AX_ROLE_ANCHOR: |
+ return ROLE_SYSTEM_LINK; |
+ |
case ui::AX_ROLE_APPLICATION: |
return ROLE_SYSTEM_APPLICATION; |
- case ui::AX_ROLE_BUTTON_DROP_DOWN: |
- return ROLE_SYSTEM_BUTTONDROPDOWN; |
- case ui::AX_ROLE_POP_UP_BUTTON: |
- return ROLE_SYSTEM_BUTTONMENU; |
- case ui::AX_ROLE_CARET: |
- return ROLE_SYSTEM_CARET; |
+ |
+ case ui::AX_ROLE_ARTICLE: |
+ return ROLE_SYSTEM_DOCUMENT; |
+ |
+ case ui::AX_ROLE_AUDIO: |
+ return ROLE_SYSTEM_GROUPING; |
+ |
+ case ui::AX_ROLE_BANNER: |
+ return ROLE_SYSTEM_GROUPING; |
+ |
+ case ui::AX_ROLE_BUSY_INDICATOR: |
+ return ROLE_SYSTEM_ANIMATION; |
+ |
+ case ui::AX_ROLE_BUTTON: |
+ return ROLE_SYSTEM_PUSHBUTTON; |
+ |
+ case ui::AX_ROLE_CANVAS: |
+ return ROLE_SYSTEM_GRAPHIC; |
+ |
+ case ui::AX_ROLE_CAPTION: |
+ return ROLE_SYSTEM_TEXT; |
+ |
+ case ui::AX_ROLE_CELL: |
+ return ROLE_SYSTEM_CELL; |
+ |
case ui::AX_ROLE_CHECK_BOX: |
return ROLE_SYSTEM_CHECKBUTTON; |
+ |
+ case ui::AX_ROLE_COLOR_WELL: |
+ return ROLE_SYSTEM_TEXT; |
+ |
+ case ui::AX_ROLE_COLUMN: |
+ return ROLE_SYSTEM_COLUMN; |
+ |
+ case ui::AX_ROLE_COLUMN_HEADER: |
+ return ROLE_SYSTEM_COLUMNHEADER; |
+ |
case ui::AX_ROLE_COMBO_BOX: |
return ROLE_SYSTEM_COMBOBOX; |
+ |
+ case ui::AX_ROLE_COMPLEMENTARY: |
+ return ROLE_SYSTEM_GROUPING; |
+ |
+ case ui::AX_ROLE_CONTENT_INFO: |
+ return ROLE_SYSTEM_TEXT; |
+ |
+ case ui::AX_ROLE_DATE: |
+ case ui::AX_ROLE_DATE_TIME: |
+ return ROLE_SYSTEM_DROPLIST; |
+ |
+ case ui::AX_ROLE_DESCRIPTION_LIST_DETAIL: |
+ return ROLE_SYSTEM_TEXT; |
+ |
+ case ui::AX_ROLE_DESCRIPTION_LIST: |
+ return ROLE_SYSTEM_LIST; |
+ |
+ case ui::AX_ROLE_DESCRIPTION_LIST_TERM: |
+ return ROLE_SYSTEM_LISTITEM; |
+ |
+ case ui::AX_ROLE_DETAILS: |
+ return ROLE_SYSTEM_GROUPING; |
+ |
case ui::AX_ROLE_DIALOG: |
return ROLE_SYSTEM_DIALOG; |
+ |
+ case ui::AX_ROLE_DISCLOSURE_TRIANGLE: |
+ return ROLE_SYSTEM_PUSHBUTTON; |
+ |
+ case ui::AX_ROLE_DOCUMENT: |
+ case ui::AX_ROLE_ROOT_WEB_AREA: |
+ case ui::AX_ROLE_WEB_AREA: |
+ return ROLE_SYSTEM_DOCUMENT; |
+ |
+ case ui::AX_ROLE_EMBEDDED_OBJECT: |
+ if (delegate_->GetChildCount()) { |
+ return ROLE_SYSTEM_GROUPING; |
+ } else { |
+ return ROLE_SYSTEM_CLIENT; |
+ } |
+ |
+ case ui::AX_ROLE_FIGURE: |
+ return ROLE_SYSTEM_GROUPING; |
+ |
+ case ui::AX_ROLE_FEED: |
+ return ROLE_SYSTEM_GROUPING; |
+ |
case ui::AX_ROLE_GENERIC_CONTAINER: |
return ROLE_SYSTEM_GROUPING; |
+ |
+ case ui::AX_ROLE_GRID: |
+ return ROLE_SYSTEM_TABLE; |
+ |
case ui::AX_ROLE_GROUP: |
return ROLE_SYSTEM_GROUPING; |
+ |
+ case ui::AX_ROLE_HEADING: |
+ return ROLE_SYSTEM_GROUPING; |
+ |
+ case ui::AX_ROLE_IFRAME: |
+ return ROLE_SYSTEM_DOCUMENT; |
+ |
+ case ui::AX_ROLE_IFRAME_PRESENTATIONAL: |
+ return ROLE_SYSTEM_GROUPING; |
+ |
case ui::AX_ROLE_IMAGE: |
return ROLE_SYSTEM_GRAPHIC; |
+ |
+ case ui::AX_ROLE_IMAGE_MAP_LINK: |
+ return ROLE_SYSTEM_LINK; |
+ |
+ case ui::AX_ROLE_INPUT_TIME: |
+ return ROLE_SYSTEM_GROUPING; |
+ |
+ case ui::AX_ROLE_LABEL_TEXT: |
+ case ui::AX_ROLE_LEGEND: |
+ return ROLE_SYSTEM_TEXT; |
+ |
case ui::AX_ROLE_LINK: |
return ROLE_SYSTEM_LINK; |
- case ui::AX_ROLE_LOCATION_BAR: |
+ |
+ case ui::AX_ROLE_LIST: |
+ return ROLE_SYSTEM_LIST; |
+ |
+ case ui::AX_ROLE_LIST_BOX: |
+ return ROLE_SYSTEM_LIST; |
+ |
+ case ui::AX_ROLE_LIST_BOX_OPTION: |
+ return ROLE_SYSTEM_LISTITEM; |
+ |
+ case ui::AX_ROLE_LIST_ITEM: |
+ return ROLE_SYSTEM_LISTITEM; |
+ |
+ case ui::AX_ROLE_MAIN: |
return ROLE_SYSTEM_GROUPING; |
+ |
+ case ui::AX_ROLE_MARK: |
+ return ROLE_SYSTEM_TEXT; |
+ |
+ case ui::AX_ROLE_MARQUEE: |
+ return ROLE_SYSTEM_ANIMATION; |
+ |
+ case ui::AX_ROLE_MATH: |
+ return ROLE_SYSTEM_EQUATION; |
+ |
+ case ui::AX_ROLE_MENU: |
+ case ui::AX_ROLE_MENU_BUTTON: |
+ return ROLE_SYSTEM_MENUPOPUP; |
+ |
case ui::AX_ROLE_MENU_BAR: |
return ROLE_SYSTEM_MENUBAR; |
+ |
case ui::AX_ROLE_MENU_ITEM: |
return ROLE_SYSTEM_MENUITEM; |
+ |
+ case ui::AX_ROLE_MENU_ITEM_CHECK_BOX: |
+ return ROLE_SYSTEM_MENUITEM; |
+ |
+ case ui::AX_ROLE_MENU_ITEM_RADIO: |
+ return ROLE_SYSTEM_MENUITEM; |
+ |
case ui::AX_ROLE_MENU_LIST_POPUP: |
- return ROLE_SYSTEM_MENUPOPUP; |
- case ui::AX_ROLE_TREE: |
+ return ROLE_SYSTEM_LIST; |
+ |
+ case ui::AX_ROLE_MENU_LIST_OPTION: |
+ return ROLE_SYSTEM_LISTITEM; |
+ |
+ case ui::AX_ROLE_NAVIGATION: |
+ return ROLE_SYSTEM_GROUPING; |
+ |
+ case ui::AX_ROLE_NOTE: |
+ return ROLE_SYSTEM_GROUPING; |
+ |
+ case ui::AX_ROLE_OUTLINE: |
return ROLE_SYSTEM_OUTLINE; |
- case ui::AX_ROLE_TREE_ITEM: |
- return ROLE_SYSTEM_OUTLINEITEM; |
- case ui::AX_ROLE_TAB: |
- return ROLE_SYSTEM_PAGETAB; |
- case ui::AX_ROLE_TAB_LIST: |
- return ROLE_SYSTEM_PAGETABLIST; |
- case ui::AX_ROLE_PANE: |
- return ROLE_SYSTEM_PANE; |
+ |
+ case ui::AX_ROLE_POP_UP_BUTTON: { |
+ std::string html_tag = GetData().GetStringAttribute(ui::AX_ATTR_HTML_TAG); |
+ if (html_tag == "select") |
+ return ROLE_SYSTEM_COMBOBOX; |
+ return ROLE_SYSTEM_BUTTONMENU; |
+ } |
+ case ui::AX_ROLE_PRE: |
+ return ROLE_SYSTEM_TEXT; |
+ |
case ui::AX_ROLE_PROGRESS_INDICATOR: |
return ROLE_SYSTEM_PROGRESSBAR; |
- case ui::AX_ROLE_BUTTON: |
- return ROLE_SYSTEM_PUSHBUTTON; |
+ |
case ui::AX_ROLE_RADIO_BUTTON: |
return ROLE_SYSTEM_RADIOBUTTON; |
+ |
+ case ui::AX_ROLE_RADIO_GROUP: |
+ return ROLE_SYSTEM_GROUPING; |
+ |
+ case ui::AX_ROLE_REGION: { |
+ std::string html_tag = GetData().GetStringAttribute(ui::AX_ATTR_HTML_TAG); |
+ if (html_tag == "section") |
+ return ROLE_SYSTEM_GROUPING; |
+ return ROLE_SYSTEM_PANE; |
+ } |
+ |
+ case ui::AX_ROLE_ROW: { |
+ // Role changes depending on whether row is inside a treegrid |
+ // https://www.w3.org/TR/core-aam-1.1/#role-map-row |
+ auto* container = FromNativeViewAccessible(GetParent()); |
+ if (container && container->GetData().role == ui::AX_ROLE_GROUP) { |
+ // If parent was a rowgroup, we need to look at the grandparent |
+ container = FromNativeViewAccessible(container->GetParent()); |
+ } |
+ |
+ if (!container) |
+ return ROLE_SYSTEM_ROW; |
+ |
+ return ROLE_SYSTEM_OUTLINEITEM; |
+ } |
+ |
+ case ui::AX_ROLE_ROW_HEADER: |
+ return ROLE_SYSTEM_ROWHEADER; |
+ |
+ case ui::AX_ROLE_RUBY: |
+ return ROLE_SYSTEM_TEXT; |
+ |
+ case ui::AX_ROLE_RULER: |
+ return ROLE_SYSTEM_CLIENT; |
+ |
+ case ui::AX_ROLE_SCROLL_AREA: |
+ return ROLE_SYSTEM_CLIENT; |
+ |
case ui::AX_ROLE_SCROLL_BAR: |
return ROLE_SYSTEM_SCROLLBAR; |
- case ui::AX_ROLE_SPLITTER: |
- return ROLE_SYSTEM_SEPARATOR; |
+ |
+ case ui::AX_ROLE_SEARCH: |
+ return ROLE_SYSTEM_GROUPING; |
+ |
case ui::AX_ROLE_SLIDER: |
return ROLE_SYSTEM_SLIDER; |
+ |
+ case ui::AX_ROLE_SPIN_BUTTON: |
+ return ROLE_SYSTEM_SPINBUTTON; |
+ |
+ case ui::AX_ROLE_SPIN_BUTTON_PART: |
+ return ROLE_SYSTEM_PUSHBUTTON; |
+ |
+ case ui::AX_ROLE_ANNOTATION: |
+ case ui::AX_ROLE_LIST_MARKER: |
case ui::AX_ROLE_STATIC_TEXT: |
return ROLE_SYSTEM_STATICTEXT; |
+ |
+ case ui::AX_ROLE_STATUS: |
+ return ROLE_SYSTEM_STATUSBAR; |
+ |
+ case ui::AX_ROLE_SPLITTER: |
+ return ROLE_SYSTEM_SEPARATOR; |
+ |
+ case ui::AX_ROLE_SVG_ROOT: |
+ return ROLE_SYSTEM_GRAPHIC; |
+ |
+ case ui::AX_ROLE_TAB: |
+ return ROLE_SYSTEM_PAGETAB; |
+ |
+ case ui::AX_ROLE_TABLE: |
+ return ROLE_SYSTEM_TABLE; |
+ |
+ case ui::AX_ROLE_TABLE_HEADER_CONTAINER: |
+ return ROLE_SYSTEM_GROUPING; |
+ |
+ case ui::AX_ROLE_TAB_LIST: |
+ return ROLE_SYSTEM_PAGETABLIST; |
+ |
+ case ui::AX_ROLE_TAB_PANEL: |
+ return ROLE_SYSTEM_PROPERTYPAGE; |
+ |
+ case ui::AX_ROLE_TERM: |
+ return ROLE_SYSTEM_LISTITEM; |
+ |
+ case ui::AX_ROLE_TOGGLE_BUTTON: |
+ return ROLE_SYSTEM_PUSHBUTTON; |
+ |
case ui::AX_ROLE_TEXT_FIELD: |
+ case ui::AX_ROLE_SEARCH_BOX: |
+ return ROLE_SYSTEM_TEXT; |
+ |
+ case ui::AX_ROLE_ABBR: |
+ case ui::AX_ROLE_TIME: |
return ROLE_SYSTEM_TEXT; |
- case ui::AX_ROLE_TITLE_BAR: |
- return ROLE_SYSTEM_TITLEBAR; |
+ |
+ case ui::AX_ROLE_TIMER: |
+ return ROLE_SYSTEM_CLOCK; |
+ |
case ui::AX_ROLE_TOOLBAR: |
return ROLE_SYSTEM_TOOLBAR; |
- case ui::AX_ROLE_WEB_VIEW: |
+ |
+ case ui::AX_ROLE_TOOLTIP: |
+ return ROLE_SYSTEM_TOOLTIP; |
+ |
+ case ui::AX_ROLE_TREE: |
+ return ROLE_SYSTEM_OUTLINE; |
+ |
+ case ui::AX_ROLE_TREE_GRID: |
+ return ROLE_SYSTEM_OUTLINE; |
+ |
+ case ui::AX_ROLE_TREE_ITEM: |
+ return ROLE_SYSTEM_OUTLINEITEM; |
+ |
+ case ui::AX_ROLE_LINE_BREAK: |
+ return ROLE_SYSTEM_WHITESPACE; |
+ |
+ case ui::AX_ROLE_VIDEO: |
return ROLE_SYSTEM_GROUPING; |
+ |
case ui::AX_ROLE_WINDOW: |
return ROLE_SYSTEM_WINDOW; |
- case ui::AX_ROLE_CLIENT: |
+ |
+ // TODO(dmazzoni): figure out the proper MSAA role for roles not called out |
+ // here. |
default: |
- // This is the default role for MSAA. |
return ROLE_SYSTEM_CLIENT; |
} |
} |
+std::string AXPlatformNodeWin::StringOverrideForMSAARole() { |
+ std::string html_tag = GetData().GetStringAttribute(ui::AX_ATTR_HTML_TAG); |
+ |
+ switch (GetData().role) { |
+ case ui::AX_ROLE_BLOCKQUOTE: |
+ case ui::AX_ROLE_DEFINITION: |
+ case ui::AX_ROLE_IMAGE_MAP: |
+ return html_tag; |
+ |
+ case ui::AX_ROLE_CANVAS: |
+ if (GetData().GetBoolAttribute(ui::AX_ATTR_CANVAS_HAS_FALLBACK)) { |
+ // TODO(dougt) why not just use the html_tag? |
+ return "canvas"; |
+ } |
+ break; |
+ |
+ case ui::AX_ROLE_FORM: |
+ // TODO(dougt) why not just use the html_tag? |
+ return "form"; |
+ |
+ case ui::AX_ROLE_HEADING: |
+ if (!html_tag.empty()) |
+ return html_tag; |
+ break; |
+ |
+ case ui::AX_ROLE_PARAGRAPH: |
+ // TODO(dougt) why not just use the html_tag and why upper case? |
+ return "P"; |
+ |
+ case ui::AX_ROLE_GENERIC_CONTAINER: |
+ // TODO(dougt) why can't we always use div in this case? |
+ if (html_tag.empty()) |
+ return "div"; |
+ return html_tag; |
+ |
+ case ui::AX_ROLE_SWITCH: |
+ return "switch"; |
+ |
+ default: |
+ return ""; |
+ } |
+ |
+ return ""; |
+} |
+ |
int AXPlatformNodeWin::MSAAState() { |
const AXNodeData& data = GetData(); |
const uint32_t state = data.state; |