OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | |
David Tseng
2015/05/08 21:58:24
nit: remove (c)?
dmazzoni
2015/05/13 04:22:19
Done.
| |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/browser/accessibility/accessibility_tree_search.h" | |
6 | |
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" | |
12 | |
13 namespace content { | |
14 | |
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)); | |
David Tseng
2015/05/08 21:58:24
What about shortcut and url?
dmazzoni
2015/05/13 04:22:20
I don't think those are text. shortcut is the acce
| |
29 } | |
30 | |
31 AccessibilityTreeSearch::AccessibilityTreeSearch( | |
32 BrowserAccessibilityManager* tree) | |
33 : tree_(tree), | |
David Tseng
2015/05/08 21:58:24
nit: +4 indent
dmazzoni
2015/05/13 04:22:19
I think this is right? It's +4 from the left edge
| |
34 start_node_(nullptr), | |
35 direction_(AccessibilityTreeSearch::FORWARDS), | |
36 result_limit_(-1), | |
David Tseng
2015/05/08 21:58:24
nit: -1 means what? (error/unlimited)?
dmazzoni
2015/05/13 04:22:19
Done.
| |
37 immediate_descendants_only_(false), | |
38 visible_only_(false), | |
39 did_search_(false) { | |
40 } | |
41 | |
42 AccessibilityTreeSearch::~AccessibilityTreeSearch() { | |
43 } | |
44 | |
45 void AccessibilityTreeSearch::SetStartNode(BrowserAccessibility* start_node) { | |
46 DCHECK(!did_search_); | |
47 start_node_ = start_node; | |
48 } | |
49 | |
50 void AccessibilityTreeSearch::SetDirection(Direction direction) { | |
51 DCHECK(!did_search_); | |
52 direction_ = direction; | |
53 } | |
54 | |
55 void AccessibilityTreeSearch::SetResultLimit(int result_limit) { | |
56 DCHECK(!did_search_); | |
57 result_limit_ = result_limit; | |
58 } | |
59 | |
60 void AccessibilityTreeSearch::SetImmediateDescendantsOnly( | |
61 bool immediate_descendants_only) { | |
62 DCHECK(!did_search_); | |
63 immediate_descendants_only_ = immediate_descendants_only; | |
64 } | |
65 | |
66 void AccessibilityTreeSearch::SetVisibleOnly(bool visible_only) { | |
67 DCHECK(!did_search_); | |
68 visible_only_ = visible_only; | |
69 } | |
70 | |
71 void AccessibilityTreeSearch::SetSearchText(const std::string& text) { | |
72 DCHECK(!did_search_); | |
73 search_text_ = text; | |
74 } | |
75 | |
76 void AccessibilityTreeSearch::AddPredicate( | |
77 AccessibilityMatchPredicate predicate) { | |
78 DCHECK(!did_search_); | |
79 predicates_.push_back(predicate); | |
80 } | |
81 | |
82 size_t AccessibilityTreeSearch::CountMatches() { | |
83 if (!did_search_) | |
84 DoSearch(); | |
85 | |
86 return matches_.size(); | |
87 } | |
88 | |
89 BrowserAccessibility* AccessibilityTreeSearch::GetMatchAtIndex(size_t index) { | |
90 if (!did_search_) | |
91 DoSearch(); | |
92 | |
93 DCHECK(index < matches_.size()); | |
David Tseng
2015/05/08 21:58:24
Should this be a DCHECK?
dmazzoni
2015/05/13 04:22:19
Done.
| |
94 return matches_[index]; | |
95 } | |
96 | |
97 void AccessibilityTreeSearch::DoSearch() | |
98 { | |
99 BrowserAccessibility* node = nullptr; | |
100 if (start_node_) { | |
David Tseng
2015/05/08 21:58:24
Is it expected that the search starts from the dir
dmazzoni
2015/05/13 04:22:19
Yes, the search does not include the start node it
| |
101 if (direction_ == FORWARDS) | |
102 node = tree_->NextInTreeOrder(start_node_); | |
103 else | |
104 node = tree_->PreviousInTreeOrder(start_node_); | |
105 } else { | |
106 start_node_ = tree_->GetRoot(); | |
107 node = start_node_; | |
108 } | |
109 | |
110 while (node && (result_limit_ < 0 || | |
111 static_cast<int>(matches_.size()) < result_limit_)) { | |
112 if (immediate_descendants_only_ && start_node_) { | |
David Tseng
2015/05/08 21:58:24
Isn't start_node_ always going to be non-null here
dmazzoni
2015/05/13 04:22:20
Done.
| |
113 if (!node->IsDescendantOf(start_node_)) | |
David Tseng
2015/05/08 21:58:24
This check could be part of your traversal.
dmazzoni
2015/05/13 04:22:20
Done.
| |
114 return; | |
115 } | |
116 | |
117 bool is_match = true; | |
118 for (size_t i = 0; i < predicates_.size() && is_match; ++i) { | |
David Tseng
2015/05/08 21:58:24
Maybe add a CHECK to ensure the caller has actuall
dmazzoni
2015/05/13 04:22:19
Not required - it's okay to use this just to get t
| |
119 if (!predicates_[i](start_node_, node)) | |
120 is_match = false; | |
121 } | |
122 | |
123 if (visible_only_) { | |
124 if (node->HasState(ui::AX_STATE_INVISIBLE) || | |
125 node->HasState(ui::AX_STATE_OFFSCREEN)) { | |
126 is_match = false; | |
127 } | |
128 } | |
129 | |
130 if (!search_text_.empty()) { | |
131 base::string16 search_text_lower = | |
132 base::i18n::ToLower(base::UTF8ToUTF16(search_text_)); | |
133 std::vector<base::string16> node_strings; | |
134 GetNodeStrings(node, &node_strings); | |
135 bool found_text_match = false; | |
136 for (size_t i = 0; i < node_strings.size(); ++i) { | |
137 base::string16 node_string_lower = base::i18n::ToLower(node_strings[i]); | |
138 if (node_string_lower.find(search_text_lower) != base::string16::npos) { | |
David Tseng
2015/05/08 21:58:25
Does Mac expect case insensitive searches?
dmazzoni
2015/05/13 04:22:20
Yes, this matches their implementation. We could m
| |
139 found_text_match = true; | |
140 break; | |
141 } | |
142 } | |
143 if (!found_text_match) | |
144 is_match = false; | |
145 } | |
146 | |
147 if (is_match) | |
148 matches_.push_back(node); | |
149 | |
150 if (direction_ == FORWARDS) | |
151 node = tree_->NextInTreeOrder(node); | |
152 else | |
153 node = tree_->PreviousInTreeOrder(node); | |
154 } | |
155 } | |
156 | |
157 } // namespace content | |
OLD | NEW |