1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/accessibility/one_shot_accessibility_tree_search.h"
7 #include "base/i18n/case_conversion.h"
8 #include "base/strings/string16.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "content/browser/accessibility/browser_accessibility.h"
11 #include "content/browser/accessibility/browser_accessibility_manager.h"
15 // Given a node, populate a vector with all of the strings from that node's
16 // attributes that might be relevant for a text search.
17 void GetNodeStrings(BrowserAccessibility
* node
,
18 std::vector
<base::string16
>* strings
) {
19 if (node
->HasStringAttribute(ui::AX_ATTR_NAME
))
20 strings
->push_back(node
->GetString16Attribute(ui::AX_ATTR_NAME
));
21 if (node
->HasStringAttribute(ui::AX_ATTR_DESCRIPTION
))
22 strings
->push_back(node
->GetString16Attribute(ui::AX_ATTR_DESCRIPTION
));
23 if (node
->HasStringAttribute(ui::AX_ATTR_HELP
))
24 strings
->push_back(node
->GetString16Attribute(ui::AX_ATTR_HELP
));
25 if (node
->HasStringAttribute(ui::AX_ATTR_VALUE
))
26 strings
->push_back(node
->GetString16Attribute(ui::AX_ATTR_VALUE
));
27 if (node
->HasStringAttribute(ui::AX_ATTR_PLACEHOLDER
))
28 strings
->push_back(node
->GetString16Attribute(ui::AX_ATTR_PLACEHOLDER
));
31 OneShotAccessibilityTreeSearch::OneShotAccessibilityTreeSearch(
32 BrowserAccessibilityManager
* tree
)
35 direction_(OneShotAccessibilityTreeSearch::FORWARDS
),
36 result_limit_(UNLIMITED_RESULTS
),
37 immediate_descendants_only_(false),
42 OneShotAccessibilityTreeSearch::~OneShotAccessibilityTreeSearch() {
45 void OneShotAccessibilityTreeSearch::SetStartNode(
46 BrowserAccessibility
* start_node
) {
48 start_node_
= start_node
;
51 void OneShotAccessibilityTreeSearch::SetDirection(Direction direction
) {
53 direction_
= direction
;
56 void OneShotAccessibilityTreeSearch::SetResultLimit(int result_limit
) {
58 result_limit_
= result_limit
;
61 void OneShotAccessibilityTreeSearch::SetImmediateDescendantsOnly(
62 bool immediate_descendants_only
) {
64 immediate_descendants_only_
= immediate_descendants_only
;
67 void OneShotAccessibilityTreeSearch::SetVisibleOnly(bool visible_only
) {
69 visible_only_
= visible_only
;
72 void OneShotAccessibilityTreeSearch::SetSearchText(const std::string
& text
) {
77 void OneShotAccessibilityTreeSearch::AddPredicate(
78 AccessibilityMatchPredicate predicate
) {
80 predicates_
.push_back(predicate
);
83 size_t OneShotAccessibilityTreeSearch::CountMatches() {
87 return matches_
.size();
90 BrowserAccessibility
* OneShotAccessibilityTreeSearch::GetMatchAtIndex(
95 CHECK(index
< matches_
.size());
96 return matches_
[index
];
99 void OneShotAccessibilityTreeSearch::Search()
101 if (immediate_descendants_only_
) {
102 SearchByIteratingOverChildren();
104 SearchByWalkingTree();
108 void OneShotAccessibilityTreeSearch::SearchByIteratingOverChildren() {
113 i
< start_node_
->PlatformChildCount() &&
114 (result_limit_
== UNLIMITED_RESULTS
||
115 static_cast<int>(matches_
.size()) < result_limit_
);
117 BrowserAccessibility
* child
= start_node_
->PlatformGetChild(i
);
119 matches_
.push_back(child
);
123 void OneShotAccessibilityTreeSearch::SearchByWalkingTree() {
124 BrowserAccessibility
* node
= nullptr;
126 if (direction_
== FORWARDS
)
127 node
= tree_
->NextInTreeOrder(start_node_
);
129 node
= tree_
->PreviousInTreeOrder(start_node_
);
131 start_node_
= tree_
->GetRoot();
135 while (node
&& (result_limit_
== UNLIMITED_RESULTS
||
136 static_cast<int>(matches_
.size()) < result_limit_
)) {
138 matches_
.push_back(node
);
140 if (direction_
== FORWARDS
)
141 node
= tree_
->NextInTreeOrder(node
);
143 node
= tree_
->PreviousInTreeOrder(node
);
147 bool OneShotAccessibilityTreeSearch::Matches(BrowserAccessibility
* node
) {
148 for (size_t i
= 0; i
< predicates_
.size(); ++i
) {
149 if (!predicates_
[i
](start_node_
, node
))
154 if (node
->HasState(ui::AX_STATE_INVISIBLE
) ||
155 node
->HasState(ui::AX_STATE_OFFSCREEN
)) {
160 if (!search_text_
.empty()) {
161 base::string16 search_text_lower
=
162 base::i18n::ToLower(base::UTF8ToUTF16(search_text_
));
163 std::vector
<base::string16
> node_strings
;
164 GetNodeStrings(node
, &node_strings
);
165 bool found_text_match
= false;
166 for (size_t i
= 0; i
< node_strings
.size(); ++i
) {
167 base::string16 node_string_lower
=
168 base::i18n::ToLower(node_strings
[i
]);
169 if (node_string_lower
.find(search_text_lower
) !=
170 base::string16::npos
) {
171 found_text_match
= true;
175 if (!found_text_match
)
182 } // namespace content