Skip to content

Commit

Permalink
Implement MSAA/IA2 HelpText property
Browse files Browse the repository at this point in the history
This change implements HelpText property for views by exposing
one of the following:
1. If Placeholder is available, set its value as the HelpText.
2. If the element has NameFrom::kTitle or NameFrom::kPlaceholder,
expose StringAttribute::kName as the HelpText.
3. If Tooltip is available, set its value as the HelpText.
4. Return S_FALSE if there is no help information available.

This change also adds an AXPlatformNodeWinTest to test
the new implementation of HelpText property.

Change-Id: I8a3d0d38273da75d7969a60f70a4627c96e8ffde
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1661003
Reviewed-by: Kevin Babbitt <kbabbitt@microsoft.com>
Commit-Queue: Maria Villarreal <mavill@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#670267}
  • Loading branch information
Marialicia Villarreal Garcia authored and Commit Bot committed Jun 18, 2019
1 parent ad7d498 commit 5e983af
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 16 deletions.
36 changes: 20 additions & 16 deletions ui/accessibility/platform/ax_platform_node_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1064,8 +1064,9 @@ IFACEMETHODIMP AXPlatformNodeWin::get_accState(VARIANT var_id, VARIANT* state) {

IFACEMETHODIMP AXPlatformNodeWin::get_accHelp(VARIANT var_id, BSTR* help) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ACC_HELP);
COM_OBJECT_VALIDATE_1_ARG(help);
return S_FALSE;
AXPlatformNodeWin* target;
COM_OBJECT_VALIDATE_VAR_ID_1_ARG_AND_GET_TARGET(var_id, help, target);
return target->GetHelpText(help);
}

IFACEMETHODIMP AXPlatformNodeWin::get_accValue(VARIANT var_id, BSTR* value) {
Expand Down Expand Up @@ -3766,20 +3767,8 @@ IFACEMETHODIMP AXPlatformNodeWin::GetPropertyValue(PROPERTYID property_id,
break;

case UIA_HelpTextPropertyId:
if (HasStringAttribute(ax::mojom::StringAttribute::kPlaceholder)) {
V_VT(result) = VT_BSTR;
GetStringAttributeAsBstr(ax::mojom::StringAttribute::kPlaceholder,
&V_BSTR(result));
} else if (data.GetNameFrom() == ax::mojom::NameFrom::kPlaceholder ||
data.GetNameFrom() == ax::mojom::NameFrom::kTitle) {
V_VT(result) = VT_BSTR;
GetStringAttributeAsBstr(ax::mojom::StringAttribute::kName,
&V_BSTR(result));
} else if (HasStringAttribute(ax::mojom::StringAttribute::kTooltip)) {
V_VT(result) = VT_BSTR;
GetStringAttributeAsBstr(ax::mojom::StringAttribute::kTooltip,
&V_BSTR(result));
}
V_VT(result) = VT_BSTR;
GetHelpText(&V_BSTR(result));
break;

case UIA_IsContentElementPropertyId:
Expand Down Expand Up @@ -6815,6 +6804,21 @@ HRESULT AXPlatformNodeWin::AllocateComArrayFromVector(
return S_OK;
}

HRESULT AXPlatformNodeWin::GetHelpText(BSTR* helpText) {
if (HasStringAttribute(ax::mojom::StringAttribute::kPlaceholder)) {
return GetStringAttributeAsBstr(ax::mojom::StringAttribute::kPlaceholder,
helpText);
} else if (GetData().GetNameFrom() == ax::mojom::NameFrom::kPlaceholder ||
GetData().GetNameFrom() == ax::mojom::NameFrom::kTitle) {
return GetStringAttributeAsBstr(ax::mojom::StringAttribute::kName,
helpText);
} else if (HasStringAttribute(ax::mojom::StringAttribute::kTooltip)) {
return GetStringAttributeAsBstr(ax::mojom::StringAttribute::kTooltip,
helpText);
}
return S_FALSE;
}

// TODO(dmazzoni): Remove this function once combo box refactoring is
// complete.
bool AXPlatformNodeWin::IsAncestorComboBox() {
Expand Down
3 changes: 3 additions & 0 deletions ui/accessibility/platform/ax_platform_node_win.h
Original file line number Diff line number Diff line change
Expand Up @@ -1201,6 +1201,9 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
// Helper method for mutating the ISelectionItemProvider selected state
HRESULT ISelectionItemProviderSetSelected(bool selected);

// Helper method for getting the help text property.
HRESULT GetHelpText(BSTR* helpText);

//
// Getters for UIA GetTextAttributeValue
//
Expand Down
95 changes: 95 additions & 0 deletions ui/accessibility/platform/ax_platform_node_win_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,101 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleShortcut) {
root_obj->get_accKeyboardShortcut(bad_id, k2.Receive()));
}

TEST_F(AXPlatformNodeWinTest, TestIAccessibleHelpText) {
AXNodeData root;
root.id = 0;

// Test Placeholder StringAttribute is exposed.
AXNodeData node1;
node1.id = 1;
node1.SetName("name-from-title");
node1.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
static_cast<int>(ax::mojom::NameFrom::kTitle));
node1.AddStringAttribute(ax::mojom::StringAttribute::kPlaceholder,
"placeholder");
root.child_ids.push_back(node1.id);

// Test NameFrom Title is exposed.
AXNodeData node2;
node2.id = 2;
node2.SetName("name-from-title");
node2.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
static_cast<int>(ax::mojom::NameFrom::kTitle));
root.child_ids.push_back(node2.id);

// Test NameFrom Placeholder is exposed.
AXNodeData node3;
node3.id = 3;
node3.SetName("name-from-placeholder");
node3.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
static_cast<int>(ax::mojom::NameFrom::kPlaceholder));
root.child_ids.push_back(node3.id);

// Test Tooltip StringAttribute is exposed.
AXNodeData node4;
node4.id = 4;
node4.SetName("name-from-attribute");
node4.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
static_cast<int>(ax::mojom::NameFrom::kAttribute));
node4.AddStringAttribute(ax::mojom::StringAttribute::kTooltip, "tooltip");
root.child_ids.push_back(node4.id);

// Test StringAttribute is not exposed without explicit
// Placeholder / Title / Tooltip.
AXNodeData node5;
node5.id = 5;
node5.SetName("name-from-attribute");
node5.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
static_cast<int>(ax::mojom::NameFrom::kAttribute));
root.child_ids.push_back(node5.id);

Init(root, node1, node2, node3, node4, node5);

auto* root_node = GetRootNode();

ScopedBstr helpText1;
ComPtr<IAccessible> child_node1(
IAccessibleFromNode(root_node->children()[0]));
EXPECT_EQ(S_OK, child_node1->get_accHelp(SELF, helpText1.Receive()));
EXPECT_STREQ(L"placeholder", helpText1);

ScopedBstr helpText2;
ComPtr<IAccessible> child_node2(
IAccessibleFromNode(root_node->children()[1]));
EXPECT_EQ(S_OK, child_node2->get_accHelp(SELF, helpText2.Receive()));
EXPECT_STREQ(L"name-from-title", helpText2);

ScopedBstr helpText3;
ComPtr<IAccessible> child_node3(
IAccessibleFromNode(root_node->children()[2]));
EXPECT_EQ(S_OK, child_node3->get_accHelp(SELF, helpText3.Receive()));
EXPECT_STREQ(L"name-from-placeholder", helpText3);

ScopedBstr helpText4;
ComPtr<IAccessible> child_node4(
IAccessibleFromNode(root_node->children()[3]));
EXPECT_EQ(S_OK, child_node4->get_accHelp(SELF, helpText4.Receive()));
EXPECT_STREQ(L"tooltip", helpText4);

ScopedBstr helpText5;
ComPtr<IAccessible> child_node5(
IAccessibleFromNode(root_node->children()[4]));
EXPECT_EQ(S_FALSE, child_node5->get_accHelp(SELF, helpText5.Receive()));

ScopedBstr helpText6;
ScopedVariant root_id(0);
EXPECT_EQ(S_OK, child_node4->get_accHelp(root_id, helpText6.Receive()));
EXPECT_STREQ(L"tooltip", helpText6);

EXPECT_EQ(E_INVALIDARG, child_node5->get_accHelp(SELF, nullptr));
ScopedVariant var_id(5);
EXPECT_EQ(E_INVALIDARG,
child_node5->get_accHelp(var_id, helpText5.Receive()));
ScopedVariant bad_id(999);
EXPECT_EQ(E_INVALIDARG,
child_node5->get_accHelp(bad_id, helpText5.Receive()));
}

TEST_F(AXPlatformNodeWinTest,
TestIAccessibleSelectionListBoxOptionNothingSelected) {
AXNodeData list;
Expand Down

0 comments on commit 5e983af

Please sign in to comment.