Move IA2 State handling to AXPlatformNodeWin.
This CL moves all ia2_state handling from BrowserAccessibilityComWin to
AXPlatformNodeWin. In addition, we now forward get_states() to
AXPlatformNodeWin as well.
BUG=703369
Review-Url: https://codereview.chromium.org/2968833002
Cr-Commit-Position: refs/heads/master@{#485862}
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index a6736aa..68f9068 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -914,7 +914,7 @@
return html_tag == "textarea";
}
-// In general we should use IsEditField() instead if we want to check for
+// In general we should use ui::IsEditField() instead if we want to check for
// something that has a caret and the user can edit.
// TODO(aleventhal) this name is confusing because it returns true for combobox,
// and we should take a look at why a combobox is considered a text control. The
@@ -936,11 +936,6 @@
}
}
-bool BrowserAccessibility::IsEditField() const {
- return GetRole() == ui::AX_ROLE_TEXT_FIELD ||
- GetRole() == ui::AX_ROLE_SEARCH_BOX;
-}
-
// Indicates if this object is at the root of a rich edit text control.
bool BrowserAccessibility::IsRichTextControl() const {
return HasState(ui::AX_STATE_RICHLY_EDITABLE) &&
diff --git a/content/browser/accessibility/browser_accessibility_com_win.cc b/content/browser/accessibility/browser_accessibility_com_win.cc
index 6bee579..7bad359c 100644
--- a/content/browser/accessibility/browser_accessibility_com_win.cc
+++ b/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -720,12 +720,7 @@
return E_FAIL;
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- if (!states)
- return E_INVALIDARG;
-
- *states = ia2_state();
-
- return S_OK;
+ return AXPlatformNodeWin::get_states(states);
}
STDMETHODIMP BrowserAccessibilityComWin::get_uniqueID(LONG* unique_id) {
@@ -3739,6 +3734,8 @@
// If this is a web area for a presentational iframe, give it a role of
// something other than DOCUMENT so that the fact that it's a separate doc
// is not exposed to AT.
+ // TODO(dougt): When we move IA2 Role handling to AXPlatformNodeWin, we can
+ // remove this ia2_role special case.
if (owner()->IsWebAreaForPresentationalIframe()) {
win_attributes_->ia2_role = ROLE_SYSTEM_GROUPING;
}
@@ -4920,46 +4917,6 @@
void BrowserAccessibilityComWin::InitRoleAndState() {
int32_t ia2_role = 0;
- int32_t ia2_state = IA2_STATE_OPAQUE;
-
- const auto checked_state = static_cast<ui::AXCheckedState>(
- owner()->GetIntAttribute(ui::AX_ATTR_CHECKED_STATE));
- if (checked_state) {
- ia2_state |= IA2_STATE_CHECKABLE;
- }
-
- if (owner()->HasIntAttribute(ui::AX_ATTR_INVALID_STATE) &&
- owner()->GetIntAttribute(ui::AX_ATTR_INVALID_STATE) !=
- ui::AX_INVALID_STATE_FALSE)
- ia2_state |= IA2_STATE_INVALID_ENTRY;
- if (owner()->HasState(ui::AX_STATE_REQUIRED))
- ia2_state |= IA2_STATE_REQUIRED;
- if (owner()->HasState(ui::AX_STATE_VERTICAL))
- ia2_state |= IA2_STATE_VERTICAL;
- if (owner()->HasState(ui::AX_STATE_HORIZONTAL))
- ia2_state |= IA2_STATE_HORIZONTAL;
-
- const bool is_editable = owner()->HasState(ui::AX_STATE_EDITABLE);
- if (is_editable)
- ia2_state |= IA2_STATE_EDITABLE;
-
- if (owner()->IsRichTextControl() || owner()->IsEditField()) {
- // Support multi/single line states if root editable or appropriate role.
- // We support the edit box roles even if the area is not actually editable,
- // because it is technically feasible for JS to implement the edit box
- // by controlling selection.
- if (owner()->HasState(ui::AX_STATE_MULTILINE)) {
- ia2_state |= IA2_STATE_MULTI_LINE;
- } else {
- ia2_state |= IA2_STATE_SINGLE_LINE;
- }
- }
-
- if (!owner()->GetStringAttribute(ui::AX_ATTR_AUTO_COMPLETE).empty())
- ia2_state |= IA2_STATE_SUPPORTS_AUTOCOMPLETION;
-
- if (owner()->GetBoolAttribute(ui::AX_ATTR_MODAL))
- ia2_state |= IA2_STATE_MODAL;
base::string16 html_tag = owner()->GetString16Attribute(ui::AX_ATTR_HTML_TAG);
switch (owner()->GetRole()) {
@@ -5038,12 +4995,6 @@
case ui::AX_ROLE_MENU_ITEM_RADIO:
ia2_role = IA2_ROLE_RADIO_MENU_ITEM;
break;
- case ui::AX_ROLE_MENU_LIST_POPUP:
- ia2_state &= ~(IA2_STATE_EDITABLE);
- break;
- case ui::AX_ROLE_MENU_LIST_OPTION:
- ia2_state &= ~(IA2_STATE_EDITABLE);
- break;
case ui::AX_ROLE_NAVIGATION:
ia2_role = IA2_ROLE_SECTION;
break;
@@ -5069,7 +5020,6 @@
break;
case ui::AX_ROLE_SCROLL_AREA:
ia2_role = IA2_ROLE_SCROLL_PANE;
- ia2_state &= ~(IA2_STATE_EDITABLE);
break;
case ui::AX_ROLE_SEARCH:
ia2_role = IA2_ROLE_SECTION;
@@ -5083,10 +5033,6 @@
case ui::AX_ROLE_TOGGLE_BUTTON:
ia2_role = IA2_ROLE_TOGGLE_BUTTON;
break;
- case ui::AX_ROLE_TEXT_FIELD:
- case ui::AX_ROLE_SEARCH_BOX:
- ia2_state |= IA2_STATE_SELECTABLE_TEXT;
- break;
case ui::AX_ROLE_ABBR:
case ui::AX_ROLE_TIME:
ia2_role = IA2_ROLE_TEXT_FRAME;
@@ -5105,7 +5051,7 @@
ia2_role = win_attributes_->ia_role;
win_attributes_->ia2_role = ia2_role;
- win_attributes_->ia2_state = ia2_state;
+ win_attributes_->ia2_state = IA2State();
}
BrowserAccessibilityComWin* ToBrowserAccessibilityComWin(
diff --git a/content/browser/accessibility/browser_accessibility_com_win.h b/content/browser/accessibility/browser_accessibility_com_win.h
index 9114591..511ba1f 100644
--- a/content/browser/accessibility/browser_accessibility_com_win.h
+++ b/content/browser/accessibility/browser_accessibility_com_win.h
@@ -728,7 +728,7 @@
private:
// Private accessors.
int32_t ia2_role() const { return win_attributes_->ia2_role; }
- int32_t ia2_state() const { return win_attributes_->ia2_state; }
+
const std::vector<base::string16>& ia2_attributes() const {
return win_attributes_->ia2_attributes;
}
diff --git a/ui/accessibility/ax_role_properties.cc b/ui/accessibility/ax_role_properties.cc
index bf66431..34355fe 100644
--- a/ui/accessibility/ax_role_properties.cc
+++ b/ui/accessibility/ax_role_properties.cc
@@ -133,4 +133,8 @@
}
}
+bool IsEditField(ui::AXRole role) {
+ return role == ui::AX_ROLE_TEXT_FIELD || role == ui::AX_ROLE_SEARCH_BOX;
+}
+
} // namespace ui
diff --git a/ui/accessibility/ax_role_properties.h b/ui/accessibility/ax_role_properties.h
index 22c7c2b..ef6838f 100644
--- a/ui/accessibility/ax_role_properties.h
+++ b/ui/accessibility/ax_role_properties.h
@@ -32,6 +32,9 @@
// Returns true if this node is a menu or related role.
AX_EXPORT bool IsMenuRelated(ui::AXRole role);
+// Returns true if this node is a edit field.
+AX_EXPORT bool IsEditField(ui::AXRole role);
+
} // namespace ui
#endif // UI_ACCESSIBILITY_AX_ROLE_PROPERTIES_H_
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index cb51a4f..a5907b3b 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -20,6 +20,7 @@
#include "third_party/skia/include/core/SkColor.h"
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/accessibility/ax_role_properties.h"
#include "ui/accessibility/ax_text_utils.h"
#include "ui/accessibility/ax_tree_data.h"
#include "ui/accessibility/platform/ax_platform_node_delegate.h"
@@ -747,15 +748,7 @@
STDMETHODIMP AXPlatformNodeWin::get_states(AccessibleStates* states) {
COM_OBJECT_VALIDATE_1_ARG(states);
- // There are only a couple of states we need to support
- // in IAccessible2. If any more are added, we may want to
- // add a helper function like MSAAState.
- *states = IA2_STATE_OPAQUE;
- if (GetData().state & (1 << ui::AX_STATE_EDITABLE))
- *states |= IA2_STATE_EDITABLE;
- if (GetData().state & (1 << ui::AX_STATE_VERTICAL))
- *states |= IA2_STATE_VERTICAL;
-
+ *states = IA2State();
return S_OK;
}
@@ -1605,6 +1598,74 @@
return parent->GetData().role == ui::AX_ROLE_IFRAME_PRESENTATIONAL;
}
+int32_t AXPlatformNodeWin::IA2State() {
+ const AXNodeData& data = GetData();
+
+ int32_t ia2_state = IA2_STATE_OPAQUE;
+
+ const auto checked_state = static_cast<ui::AXCheckedState>(
+ GetIntAttribute(ui::AX_ATTR_CHECKED_STATE));
+ if (checked_state) {
+ ia2_state |= IA2_STATE_CHECKABLE;
+ }
+
+ if (HasIntAttribute(ui::AX_ATTR_INVALID_STATE) &&
+ GetIntAttribute(ui::AX_ATTR_INVALID_STATE) != ui::AX_INVALID_STATE_FALSE)
+ ia2_state |= IA2_STATE_INVALID_ENTRY;
+ if (data.HasState(ui::AX_STATE_REQUIRED))
+ ia2_state |= IA2_STATE_REQUIRED;
+ if (data.HasState(ui::AX_STATE_VERTICAL))
+ ia2_state |= IA2_STATE_VERTICAL;
+ if (data.HasState(ui::AX_STATE_HORIZONTAL))
+ ia2_state |= IA2_STATE_HORIZONTAL;
+
+ const bool is_editable = data.HasState(ui::AX_STATE_EDITABLE);
+ if (is_editable)
+ ia2_state |= IA2_STATE_EDITABLE;
+
+ if (IsRichTextControl() || ui::IsEditField(data.role)) {
+ // Support multi/single line states if root editable or appropriate role.
+ // We support the edit box roles even if the area is not actually editable,
+ // because it is technically feasible for JS to implement the edit box
+ // by controlling selection.
+ if (data.HasState(ui::AX_STATE_MULTILINE)) {
+ ia2_state |= IA2_STATE_MULTI_LINE;
+ } else {
+ ia2_state |= IA2_STATE_SINGLE_LINE;
+ }
+ }
+
+ if (!GetStringAttribute(ui::AX_ATTR_AUTO_COMPLETE).empty())
+ ia2_state |= IA2_STATE_SUPPORTS_AUTOCOMPLETION;
+
+ if (GetBoolAttribute(ui::AX_ATTR_MODAL))
+ ia2_state |= IA2_STATE_MODAL;
+
+ switch (data.role) {
+ case ui::AX_ROLE_MENU_LIST_POPUP:
+ ia2_state &= ~(IA2_STATE_EDITABLE);
+ break;
+ case ui::AX_ROLE_MENU_LIST_OPTION:
+ ia2_state &= ~(IA2_STATE_EDITABLE);
+ break;
+ case ui::AX_ROLE_SCROLL_AREA:
+ ia2_state &= ~(IA2_STATE_EDITABLE);
+ break;
+ case ui::AX_ROLE_TEXT_FIELD:
+ case ui::AX_ROLE_SEARCH_BOX:
+ if (data.HasState(ui::AX_STATE_MULTILINE)) {
+ ia2_state |= IA2_STATE_MULTI_LINE;
+ } else {
+ ia2_state |= IA2_STATE_SINGLE_LINE;
+ }
+ ia2_state |= IA2_STATE_SELECTABLE_TEXT;
+ break;
+ default:
+ break;
+ }
+ return ia2_state;
+}
+
bool AXPlatformNodeWin::ShouldNodeHaveReadonlyState(
const AXNodeData& data) const {
if (data.GetBoolAttribute(ui::AX_ATTR_ARIA_READONLY))
diff --git a/ui/accessibility/platform/ax_platform_node_win.h b/ui/accessibility/platform/ax_platform_node_win.h
index 38ffb05..172bc33 100644
--- a/ui/accessibility/platform/ax_platform_node_win.h
+++ b/ui/accessibility/platform/ax_platform_node_win.h
@@ -274,6 +274,8 @@
int MSAARole();
std::string StringOverrideForMSAARole();
+ int32_t IA2State();
+
// AXPlatformNodeBase overrides.
void Dispose() override;