OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/accessibility/accessibility_node_serializer.h" | 5 #include "content/renderer/accessibility/accessibility_node_serializer.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 12 #include "content/renderer/accessibility/blink_ax_enum_conversion.h" |
12 #include "third_party/WebKit/public/platform/WebRect.h" | 13 #include "third_party/WebKit/public/platform/WebRect.h" |
13 #include "third_party/WebKit/public/platform/WebSize.h" | 14 #include "third_party/WebKit/public/platform/WebSize.h" |
14 #include "third_party/WebKit/public/platform/WebString.h" | 15 #include "third_party/WebKit/public/platform/WebString.h" |
15 #include "third_party/WebKit/public/platform/WebVector.h" | 16 #include "third_party/WebKit/public/platform/WebVector.h" |
16 #include "third_party/WebKit/public/web/WebAXEnums.h" | 17 #include "third_party/WebKit/public/web/WebAXEnums.h" |
17 #include "third_party/WebKit/public/web/WebAXObject.h" | 18 #include "third_party/WebKit/public/web/WebAXObject.h" |
18 #include "third_party/WebKit/public/web/WebDocument.h" | 19 #include "third_party/WebKit/public/web/WebDocument.h" |
19 #include "third_party/WebKit/public/web/WebDocumentType.h" | 20 #include "third_party/WebKit/public/web/WebDocumentType.h" |
20 #include "third_party/WebKit/public/web/WebElement.h" | 21 #include "third_party/WebKit/public/web/WebElement.h" |
21 #include "third_party/WebKit/public/web/WebFormControlElement.h" | 22 #include "third_party/WebKit/public/web/WebFormControlElement.h" |
22 #include "third_party/WebKit/public/web/WebFrame.h" | 23 #include "third_party/WebKit/public/web/WebFrame.h" |
23 #include "third_party/WebKit/public/web/WebInputElement.h" | 24 #include "third_party/WebKit/public/web/WebInputElement.h" |
24 #include "third_party/WebKit/public/web/WebNode.h" | 25 #include "third_party/WebKit/public/web/WebNode.h" |
25 | 26 |
| 27 using base::UTF16ToUTF8; |
26 using blink::WebAXObject; | 28 using blink::WebAXObject; |
27 using blink::WebDocument; | 29 using blink::WebDocument; |
28 using blink::WebDocumentType; | 30 using blink::WebDocumentType; |
29 using blink::WebElement; | 31 using blink::WebElement; |
30 using blink::WebNode; | 32 using blink::WebNode; |
31 using blink::WebVector; | 33 using blink::WebVector; |
32 | 34 |
33 namespace content { | 35 namespace content { |
34 namespace { | 36 namespace { |
35 | 37 |
36 // Returns true if |ancestor| is the first unignored parent of |child|, | 38 // Returns true if |ancestor| is the first unignored parent of |child|, |
37 // which means that when walking up the parent chain from |child|, | 39 // which means that when walking up the parent chain from |child|, |
38 // |ancestor| is the *first* ancestor that isn't marked as | 40 // |ancestor| is the *first* ancestor that isn't marked as |
39 // accessibilityIsIgnored(). | 41 // accessibilityIsIgnored(). |
40 bool IsParentUnignoredOf(const WebAXObject& ancestor, | 42 bool IsParentUnignoredOf(const WebAXObject& ancestor, |
41 const WebAXObject& child) { | 43 const WebAXObject& child) { |
42 WebAXObject parent = child.parentObject(); | 44 WebAXObject parent = child.parentObject(); |
43 while (!parent.isDetached() && parent.accessibilityIsIgnored()) | 45 while (!parent.isDetached() && parent.accessibilityIsIgnored()) |
44 parent = parent.parentObject(); | 46 parent = parent.parentObject(); |
45 return parent.equals(ancestor); | 47 return parent.equals(ancestor); |
46 } | 48 } |
47 | 49 |
48 bool IsTrue(std::string html_value) { | 50 bool IsTrue(std::string html_value) { |
49 return LowerCaseEqualsASCII(html_value, "true"); | 51 return LowerCaseEqualsASCII(html_value, "true"); |
50 } | 52 } |
51 | 53 |
52 // Provides a conversion between the WebAXObject state | |
53 // accessors and a state bitmask that can be serialized and sent to the | |
54 // Browser process. Rare state are sent as boolean attributes instead. | |
55 uint32 ConvertState(const WebAXObject& o) { | |
56 uint32 state = 0; | |
57 if (o.isChecked()) | |
58 state |= (1 << blink::WebAXStateChecked); | |
59 | |
60 if (o.isCollapsed()) | |
61 state |= (1 << blink::WebAXStateCollapsed); | |
62 | |
63 if (o.canSetFocusAttribute()) | |
64 state |= (1 << blink::WebAXStateFocusable); | |
65 | |
66 if (o.isFocused()) | |
67 state |= (1 << blink::WebAXStateFocused); | |
68 | |
69 if (o.role() == blink::WebAXRolePopUpButton || | |
70 o.ariaHasPopup()) { | |
71 state |= (1 << blink::WebAXStateHaspopup); | |
72 if (!o.isCollapsed()) | |
73 state |= (1 << blink::WebAXStateExpanded); | |
74 } | |
75 | |
76 if (o.isHovered()) | |
77 state |= (1 << blink::WebAXStateHovered); | |
78 | |
79 if (o.isIndeterminate()) | |
80 state |= (1 << blink::WebAXStateIndeterminate); | |
81 | |
82 if (!o.isVisible()) | |
83 state |= (1 << blink::WebAXStateInvisible); | |
84 | |
85 if (o.isLinked()) | |
86 state |= (1 << blink::WebAXStateLinked); | |
87 | |
88 if (o.isMultiSelectable()) | |
89 state |= (1 << blink::WebAXStateMultiselectable); | |
90 | |
91 if (o.isOffScreen()) | |
92 state |= (1 << blink::WebAXStateOffscreen); | |
93 | |
94 if (o.isPressed()) | |
95 state |= (1 << blink::WebAXStatePressed); | |
96 | |
97 if (o.isPasswordField()) | |
98 state |= (1 << blink::WebAXStateProtected); | |
99 | |
100 if (o.isReadOnly()) | |
101 state |= (1 << blink::WebAXStateReadonly); | |
102 | |
103 if (o.isRequired()) | |
104 state |= (1 << blink::WebAXStateRequired); | |
105 | |
106 if (o.canSetSelectedAttribute()) | |
107 state |= (1 << blink::WebAXStateSelectable); | |
108 | |
109 if (o.isSelected()) | |
110 state |= (1 << blink::WebAXStateSelected); | |
111 | |
112 if (o.isVisited()) | |
113 state |= (1 << blink::WebAXStateVisited); | |
114 | |
115 if (o.isEnabled()) | |
116 state |= (1 << blink::WebAXStateEnabled); | |
117 | |
118 if (o.isVertical()) | |
119 state |= (1 << blink::WebAXStateVertical); | |
120 | |
121 if (o.isVisited()) | |
122 state |= (1 << blink::WebAXStateVisited); | |
123 | |
124 return state; | |
125 } | |
126 | |
127 } // Anonymous namespace | 54 } // Anonymous namespace |
128 | 55 |
129 void SerializeAccessibilityNode( | 56 void SerializeAccessibilityNode( |
130 const WebAXObject& src, | 57 const WebAXObject& src, |
131 AccessibilityNodeData* dst) { | 58 ui::AXNodeData* dst) { |
132 dst->role = src.role(); | 59 dst->role = AXRoleFromBlink(src.role()); |
133 dst->state = ConvertState(src); | 60 dst->state = AXStateFromBlink(src); |
134 dst->location = src.boundingBoxRect(); | 61 dst->location = src.boundingBoxRect(); |
135 dst->id = src.axID(); | 62 dst->id = src.axID(); |
136 std::string name = base::UTF16ToUTF8(src.title()); | 63 std::string name = base::UTF16ToUTF8(src.title()); |
137 | 64 |
138 std::string value; | 65 std::string value; |
139 if (src.valueDescription().length()) { | 66 if (src.valueDescription().length()) { |
140 dst->AddStringAttribute(dst->ATTR_VALUE, | 67 dst->AddStringAttribute(ui::AX_ATTR_VALUE, |
141 base::UTF16ToUTF8(src.valueDescription())); | 68 UTF16ToUTF8(src.valueDescription())); |
142 } else { | 69 } else { |
143 dst->AddStringAttribute(dst->ATTR_VALUE, | 70 dst->AddStringAttribute(ui::AX_ATTR_VALUE, UTF16ToUTF8(src.stringValue())); |
144 base::UTF16ToUTF8(src.stringValue())); | |
145 } | 71 } |
146 | 72 |
147 if (dst->role == blink::WebAXRoleColorWell) { | 73 if (dst->role == ui::AX_ROLE_COLOR_WELL) { |
148 int r, g, b; | 74 int r, g, b; |
149 src.colorValue(r, g, b); | 75 src.colorValue(r, g, b); |
150 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_RED, r); | 76 dst->AddIntAttribute(ui::AX_ATTR_COLOR_VALUE_RED, r); |
151 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_GREEN, g); | 77 dst->AddIntAttribute(ui::AX_ATTR_COLOR_VALUE_GREEN, g); |
152 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_BLUE, b); | 78 dst->AddIntAttribute(ui::AX_ATTR_COLOR_VALUE_BLUE, b); |
153 } | 79 } |
154 | 80 |
155 if (dst->role == blink::WebAXRoleInlineTextBox) { | 81 if (dst->role == ui::AX_ROLE_INLINE_TEXT_BOX) { |
156 dst->AddIntAttribute(dst->ATTR_TEXT_DIRECTION, src.textDirection()); | 82 dst->AddIntAttribute(ui::AX_ATTR_TEXT_DIRECTION, src.textDirection()); |
157 | 83 |
158 WebVector<int> src_character_offsets; | 84 WebVector<int> src_character_offsets; |
159 src.characterOffsets(src_character_offsets); | 85 src.characterOffsets(src_character_offsets); |
160 std::vector<int32> character_offsets; | 86 std::vector<int32> character_offsets; |
161 character_offsets.reserve(src_character_offsets.size()); | 87 character_offsets.reserve(src_character_offsets.size()); |
162 for (size_t i = 0; i < src_character_offsets.size(); ++i) | 88 for (size_t i = 0; i < src_character_offsets.size(); ++i) |
163 character_offsets.push_back(src_character_offsets[i]); | 89 character_offsets.push_back(src_character_offsets[i]); |
164 dst->AddIntListAttribute(dst->ATTR_CHARACTER_OFFSETS, character_offsets); | 90 dst->AddIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS, character_offsets); |
165 | 91 |
166 WebVector<int> src_word_starts; | 92 WebVector<int> src_word_starts; |
167 WebVector<int> src_word_ends; | 93 WebVector<int> src_word_ends; |
168 src.wordBoundaries(src_word_starts, src_word_ends); | 94 src.wordBoundaries(src_word_starts, src_word_ends); |
169 std::vector<int32> word_starts; | 95 std::vector<int32> word_starts; |
170 std::vector<int32> word_ends; | 96 std::vector<int32> word_ends; |
171 word_starts.reserve(src_word_starts.size()); | 97 word_starts.reserve(src_word_starts.size()); |
172 word_ends.reserve(src_word_starts.size()); | 98 word_ends.reserve(src_word_starts.size()); |
173 for (size_t i = 0; i < src_word_starts.size(); ++i) { | 99 for (size_t i = 0; i < src_word_starts.size(); ++i) { |
174 word_starts.push_back(src_word_starts[i]); | 100 word_starts.push_back(src_word_starts[i]); |
175 word_ends.push_back(src_word_ends[i]); | 101 word_ends.push_back(src_word_ends[i]); |
176 } | 102 } |
177 dst->AddIntListAttribute(dst->ATTR_WORD_STARTS, word_starts); | 103 dst->AddIntListAttribute(ui::AX_ATTR_WORD_STARTS, word_starts); |
178 dst->AddIntListAttribute(dst->ATTR_WORD_ENDS, word_ends); | 104 dst->AddIntListAttribute(ui::AX_ATTR_WORD_ENDS, word_ends); |
179 } | 105 } |
180 | 106 |
181 if (src.accessKey().length()) { | 107 if (src.accessKey().length()) |
182 dst->AddStringAttribute(dst->ATTR_ACCESS_KEY, | 108 dst->AddStringAttribute(ui::AX_ATTR_ACCESS_KEY, |
183 base::UTF16ToUTF8(src.accessKey())); | 109 UTF16ToUTF8(src.accessKey())); |
184 } | 110 if (src.actionVerb().length()) |
185 if (src.actionVerb().length()) { | 111 dst->AddStringAttribute(ui::AX_ATTR_ACTION, UTF16ToUTF8(src.actionVerb())); |
186 dst->AddStringAttribute(dst->ATTR_ACTION, | |
187 base::UTF16ToUTF8(src.actionVerb())); | |
188 } | |
189 if (src.isAriaReadOnly()) | 112 if (src.isAriaReadOnly()) |
190 dst->AddBoolAttribute(dst->ATTR_ARIA_READONLY, true); | 113 dst->AddBoolAttribute(ui::AX_ATTR_ARIA_READONLY, true); |
191 if (src.isButtonStateMixed()) | 114 if (src.isButtonStateMixed()) |
192 dst->AddBoolAttribute(dst->ATTR_BUTTON_MIXED, true); | 115 dst->AddBoolAttribute(ui::AX_ATTR_BUTTON_MIXED, true); |
193 if (src.canSetValueAttribute()) | 116 if (src.canSetValueAttribute()) |
194 dst->AddBoolAttribute(dst->ATTR_CAN_SET_VALUE, true); | 117 dst->AddBoolAttribute(ui::AX_ATTR_CAN_SET_VALUE, true); |
195 if (src.accessibilityDescription().length()) { | 118 if (src.accessibilityDescription().length()) { |
196 dst->AddStringAttribute(dst->ATTR_DESCRIPTION, | 119 dst->AddStringAttribute(ui::AX_ATTR_DESCRIPTION, |
197 base::UTF16ToUTF8(src.accessibilityDescription())); | 120 UTF16ToUTF8(src.accessibilityDescription())); |
198 } | 121 } |
199 if (src.hasComputedStyle()) { | 122 if (src.hasComputedStyle()) { |
200 dst->AddStringAttribute(dst->ATTR_DISPLAY, | 123 dst->AddStringAttribute(ui::AX_ATTR_DISPLAY, |
201 base::UTF16ToUTF8(src.computedStyleDisplay())); | 124 UTF16ToUTF8(src.computedStyleDisplay())); |
202 } | 125 } |
203 if (src.helpText().length()) | 126 if (src.helpText().length()) |
204 dst->AddStringAttribute(dst->ATTR_HELP, base::UTF16ToUTF8(src.helpText())); | 127 dst->AddStringAttribute(ui::AX_ATTR_HELP, UTF16ToUTF8(src.helpText())); |
205 if (src.keyboardShortcut().length()) { | 128 if (src.keyboardShortcut().length()) { |
206 dst->AddStringAttribute(dst->ATTR_SHORTCUT, | 129 dst->AddStringAttribute(ui::AX_ATTR_SHORTCUT, |
207 base::UTF16ToUTF8(src.keyboardShortcut())); | 130 UTF16ToUTF8(src.keyboardShortcut())); |
208 } | 131 } |
209 if (!src.titleUIElement().isDetached()) { | 132 if (!src.titleUIElement().isDetached()) { |
210 dst->AddIntAttribute(dst->ATTR_TITLE_UI_ELEMENT, | 133 dst->AddIntAttribute(ui::AX_ATTR_TITLE_UI_ELEMENT, |
211 src.titleUIElement().axID()); | 134 src.titleUIElement().axID()); |
212 } | 135 } |
213 if (!src.url().isEmpty()) | 136 if (!src.url().isEmpty()) |
214 dst->AddStringAttribute(dst->ATTR_URL, src.url().spec()); | 137 dst->AddStringAttribute(ui::AX_ATTR_URL, src.url().spec()); |
215 | 138 |
216 if (dst->role == blink::WebAXRoleHeading) | 139 if (dst->role == ui::AX_ROLE_HEADING) |
217 dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.headingLevel()); | 140 dst->AddIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL, src.headingLevel()); |
218 else if ((dst->role == blink::WebAXRoleTreeItem || | 141 else if ((dst->role == ui::AX_ROLE_TREE_ITEM || |
219 dst->role == blink::WebAXRoleRow) && | 142 dst->role == ui::AX_ROLE_ROW) && |
220 src.hierarchicalLevel() > 0) { | 143 src.hierarchicalLevel() > 0) { |
221 dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.hierarchicalLevel()); | 144 dst->AddIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL, |
| 145 src.hierarchicalLevel()); |
222 } | 146 } |
223 | 147 |
224 // Treat the active list box item as focused. | 148 // Treat the active list box item as focused. |
225 if (dst->role == blink::WebAXRoleListBoxOption && | 149 if (dst->role == ui::AX_ROLE_LIST_BOX_OPTION && |
226 src.isSelectedOptionActive()) { | 150 src.isSelectedOptionActive()) { |
227 dst->state |= (1 << blink::WebAXStateFocused); | 151 dst->state |= (1 << ui::AX_STATE_FOCUSED); |
228 } | 152 } |
229 | 153 |
230 if (src.canvasHasFallbackContent()) | 154 if (src.canvasHasFallbackContent()) |
231 dst->AddBoolAttribute(dst->ATTR_CANVAS_HAS_FALLBACK, true); | 155 dst->AddBoolAttribute(ui::AX_ATTR_CANVAS_HAS_FALLBACK, true); |
232 | 156 |
233 WebNode node = src.node(); | 157 WebNode node = src.node(); |
234 bool is_iframe = false; | 158 bool is_iframe = false; |
235 std::string live_atomic; | 159 std::string live_atomic; |
236 std::string live_busy; | 160 std::string live_busy; |
237 std::string live_status; | 161 std::string live_status; |
238 std::string live_relevant; | 162 std::string live_relevant; |
239 | 163 |
240 if (!node.isNull() && node.isElementNode()) { | 164 if (!node.isNull() && node.isElementNode()) { |
241 WebElement element = node.to<WebElement>(); | 165 WebElement element = node.to<WebElement>(); |
242 is_iframe = (element.tagName() == base::ASCIIToUTF16("IFRAME")); | 166 is_iframe = (element.tagName() == base::ASCIIToUTF16("IFRAME")); |
243 | 167 |
244 if (LowerCaseEqualsASCII(element.getAttribute("aria-expanded"), "true")) | 168 if (LowerCaseEqualsASCII(element.getAttribute("aria-expanded"), "true")) |
245 dst->state |= (1 << blink::WebAXStateExpanded); | 169 dst->state |= (1 << ui::AX_STATE_EXPANDED); |
246 | 170 |
247 // TODO(ctguil): The tagName in WebKit is lower cased but | 171 // TODO(ctguil): The tagName in WebKit is lower cased but |
248 // HTMLElement::nodeName calls localNameUpper. Consider adding | 172 // HTMLElement::nodeName calls localNameUpper. Consider adding |
249 // a WebElement method that returns the original lower cased tagName. | 173 // a WebElement method that returns the original lower cased tagName. |
250 dst->AddStringAttribute( | 174 dst->AddStringAttribute( |
251 dst->ATTR_HTML_TAG, | 175 ui::AX_ATTR_HTML_TAG, |
252 StringToLowerASCII(base::UTF16ToUTF8(element.tagName()))); | 176 StringToLowerASCII(UTF16ToUTF8(element.tagName()))); |
253 for (unsigned i = 0; i < element.attributeCount(); ++i) { | 177 for (unsigned i = 0; i < element.attributeCount(); ++i) { |
254 std::string name = StringToLowerASCII(base::UTF16ToUTF8( | 178 std::string name = StringToLowerASCII(base::UTF16ToUTF8( |
255 element.attributeLocalName(i))); | 179 element.attributeLocalName(i))); |
256 std::string value = base::UTF16ToUTF8(element.attributeValue(i)); | 180 std::string value = base::UTF16ToUTF8(element.attributeValue(i)); |
257 dst->html_attributes.push_back(std::make_pair(name, value)); | 181 dst->html_attributes.push_back(std::make_pair(name, value)); |
258 } | 182 } |
259 | 183 |
260 if (dst->role == blink::WebAXRoleEditableText || | 184 if (dst->role == ui::AX_ROLE_EDITABLE_TEXT || |
261 dst->role == blink::WebAXRoleTextArea || | 185 dst->role == ui::AX_ROLE_TEXT_AREA || |
262 dst->role == blink::WebAXRoleTextField) { | 186 dst->role == ui::AX_ROLE_TEXT_FIELD) { |
263 dst->AddIntAttribute(dst->ATTR_TEXT_SEL_START, src.selectionStart()); | 187 dst->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START, src.selectionStart()); |
264 dst->AddIntAttribute(dst->ATTR_TEXT_SEL_END, src.selectionEnd()); | 188 dst->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_END, src.selectionEnd()); |
265 | 189 |
266 WebVector<int> src_line_breaks; | 190 WebVector<int> src_line_breaks; |
267 src.lineBreaks(src_line_breaks); | 191 src.lineBreaks(src_line_breaks); |
268 if (src_line_breaks.size() > 0) { | 192 if (src_line_breaks.size() > 0) { |
269 std::vector<int32> line_breaks; | 193 std::vector<int32> line_breaks; |
270 line_breaks.reserve(src_line_breaks.size()); | 194 line_breaks.reserve(src_line_breaks.size()); |
271 for (size_t i = 0; i < src_line_breaks.size(); ++i) | 195 for (size_t i = 0; i < src_line_breaks.size(); ++i) |
272 line_breaks.push_back(src_line_breaks[i]); | 196 line_breaks.push_back(src_line_breaks[i]); |
273 dst->AddIntListAttribute(dst->ATTR_LINE_BREAKS, line_breaks); | 197 dst->AddIntListAttribute(ui::AX_ATTR_LINE_BREAKS, line_breaks); |
274 } | 198 } |
275 } | 199 } |
276 | 200 |
277 // ARIA role. | 201 // ARIA role. |
278 if (element.hasAttribute("role")) { | 202 if (element.hasAttribute("role")) { |
279 dst->AddStringAttribute(dst->ATTR_ROLE, | 203 dst->AddStringAttribute(ui::AX_ATTR_ROLE, |
280 base::UTF16ToUTF8(element.getAttribute("role"))); | 204 UTF16ToUTF8(element.getAttribute("role"))); |
281 } | 205 } |
282 | 206 |
283 // Live region attributes | 207 // Live region attributes |
284 live_atomic = base::UTF16ToUTF8(element.getAttribute("aria-atomic")); | 208 live_atomic = base::UTF16ToUTF8(element.getAttribute("aria-atomic")); |
285 live_busy = base::UTF16ToUTF8(element.getAttribute("aria-busy")); | 209 live_busy = base::UTF16ToUTF8(element.getAttribute("aria-busy")); |
286 live_status = base::UTF16ToUTF8(element.getAttribute("aria-live")); | 210 live_status = base::UTF16ToUTF8(element.getAttribute("aria-live")); |
287 live_relevant = base::UTF16ToUTF8(element.getAttribute("aria-relevant")); | 211 live_relevant = base::UTF16ToUTF8(element.getAttribute("aria-relevant")); |
288 } | 212 } |
289 | 213 |
290 // Walk up the parent chain to set live region attributes of containers | 214 // Walk up the parent chain to set live region attributes of containers |
(...skipping 24 matching lines...) Expand all Loading... |
315 if (container_elem.hasAttribute("aria-relevant") && | 239 if (container_elem.hasAttribute("aria-relevant") && |
316 container_live_relevant.empty()) { | 240 container_live_relevant.empty()) { |
317 container_live_relevant = | 241 container_live_relevant = |
318 base::UTF16ToUTF8(container_elem.getAttribute("aria-relevant")); | 242 base::UTF16ToUTF8(container_elem.getAttribute("aria-relevant")); |
319 } | 243 } |
320 } | 244 } |
321 container_accessible = container_accessible.parentObject(); | 245 container_accessible = container_accessible.parentObject(); |
322 } | 246 } |
323 | 247 |
324 if (!live_atomic.empty()) | 248 if (!live_atomic.empty()) |
325 dst->AddBoolAttribute(dst->ATTR_LIVE_ATOMIC, IsTrue(live_atomic)); | 249 dst->AddBoolAttribute(ui::AX_ATTR_LIVE_ATOMIC, IsTrue(live_atomic)); |
326 if (!live_busy.empty()) | 250 if (!live_busy.empty()) |
327 dst->AddBoolAttribute(dst->ATTR_LIVE_BUSY, IsTrue(live_busy)); | 251 dst->AddBoolAttribute(ui::AX_ATTR_LIVE_BUSY, IsTrue(live_busy)); |
328 if (!live_status.empty()) | 252 if (!live_status.empty()) |
329 dst->AddStringAttribute(dst->ATTR_LIVE_STATUS, live_status); | 253 dst->AddStringAttribute(ui::AX_ATTR_LIVE_STATUS, live_status); |
330 if (!live_relevant.empty()) | 254 if (!live_relevant.empty()) |
331 dst->AddStringAttribute(dst->ATTR_LIVE_RELEVANT, live_relevant); | 255 dst->AddStringAttribute(ui::AX_ATTR_LIVE_RELEVANT, live_relevant); |
332 | 256 |
333 if (!container_live_atomic.empty()) { | 257 if (!container_live_atomic.empty()) { |
334 dst->AddBoolAttribute(dst->ATTR_CONTAINER_LIVE_ATOMIC, | 258 dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_ATOMIC, |
335 IsTrue(container_live_atomic)); | 259 IsTrue(container_live_atomic)); |
336 } | 260 } |
337 if (!container_live_busy.empty()) { | 261 if (!container_live_busy.empty()) { |
338 dst->AddBoolAttribute(dst->ATTR_CONTAINER_LIVE_BUSY, | 262 dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_BUSY, |
339 IsTrue(container_live_busy)); | 263 IsTrue(container_live_busy)); |
340 } | 264 } |
341 if (!container_live_status.empty()) { | 265 if (!container_live_status.empty()) { |
342 dst->AddStringAttribute(dst->ATTR_CONTAINER_LIVE_STATUS, | 266 dst->AddStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_STATUS, |
343 container_live_status); | 267 container_live_status); |
344 } | 268 } |
345 if (!container_live_relevant.empty()) { | 269 if (!container_live_relevant.empty()) { |
346 dst->AddStringAttribute(dst->ATTR_CONTAINER_LIVE_RELEVANT, | 270 dst->AddStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_RELEVANT, |
347 container_live_relevant); | 271 container_live_relevant); |
348 } | 272 } |
349 | 273 |
350 if (dst->role == blink::WebAXRoleProgressIndicator || | 274 if (dst->role == ui::AX_ROLE_PROGRESS_INDICATOR || |
351 dst->role == blink::WebAXRoleScrollBar || | 275 dst->role == ui::AX_ROLE_SCROLL_BAR || |
352 dst->role == blink::WebAXRoleSlider || | 276 dst->role == ui::AX_ROLE_SLIDER || |
353 dst->role == blink::WebAXRoleSpinButton) { | 277 dst->role == ui::AX_ROLE_SPIN_BUTTON) { |
354 dst->AddFloatAttribute(dst->ATTR_VALUE_FOR_RANGE, src.valueForRange()); | 278 dst->AddFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, src.valueForRange()); |
355 dst->AddFloatAttribute(dst->ATTR_MAX_VALUE_FOR_RANGE, | 279 dst->AddFloatAttribute(ui::AX_ATTR_MAX_VALUE_FOR_RANGE, |
356 src.maxValueForRange()); | 280 src.maxValueForRange()); |
357 dst->AddFloatAttribute(dst->ATTR_MIN_VALUE_FOR_RANGE, | 281 dst->AddFloatAttribute(ui::AX_ATTR_MIN_VALUE_FOR_RANGE, |
358 src.minValueForRange()); | 282 src.minValueForRange()); |
359 } | 283 } |
360 | 284 |
361 if (dst->role == blink::WebAXRoleDocument || | 285 if (dst->role == ui::AX_ROLE_DOCUMENT || |
362 dst->role == blink::WebAXRoleWebArea) { | 286 dst->role == ui::AX_ROLE_WEB_AREA) { |
363 dst->AddStringAttribute(dst->ATTR_HTML_TAG, "#document"); | 287 dst->AddStringAttribute(ui::AX_ATTR_HTML_TAG, "#document"); |
364 const WebDocument& document = src.document(); | 288 const WebDocument& document = src.document(); |
365 if (name.empty()) | 289 if (name.empty()) |
366 name = base::UTF16ToUTF8(document.title()); | 290 name = UTF16ToUTF8(document.title()); |
367 dst->AddStringAttribute(dst->ATTR_DOC_TITLE, | 291 dst->AddStringAttribute(ui::AX_ATTR_DOC_TITLE, |
368 base::UTF16ToUTF8(document.title())); | 292 UTF16ToUTF8(document.title())); |
369 dst->AddStringAttribute(dst->ATTR_DOC_URL, document.url().spec()); | 293 dst->AddStringAttribute(ui::AX_ATTR_DOC_URL, document.url().spec()); |
370 dst->AddStringAttribute( | 294 dst->AddStringAttribute( |
371 dst->ATTR_DOC_MIMETYPE, | 295 ui::AX_ATTR_DOC_MIMETYPE, |
372 document.isXHTMLDocument() ? "text/xhtml" : "text/html"); | 296 document.isXHTMLDocument() ? "text/xhtml" : "text/html"); |
373 dst->AddBoolAttribute(dst->ATTR_DOC_LOADED, src.isLoaded()); | 297 dst->AddBoolAttribute(ui::AX_ATTR_DOC_LOADED, src.isLoaded()); |
374 dst->AddFloatAttribute(dst->ATTR_DOC_LOADING_PROGRESS, | 298 dst->AddFloatAttribute(ui::AX_ATTR_DOC_LOADING_PROGRESS, |
375 src.estimatedLoadingProgress()); | 299 src.estimatedLoadingProgress()); |
376 | 300 |
377 const WebDocumentType& doctype = document.doctype(); | 301 const WebDocumentType& doctype = document.doctype(); |
378 if (!doctype.isNull()) { | 302 if (!doctype.isNull()) { |
379 dst->AddStringAttribute(dst->ATTR_DOC_DOCTYPE, | 303 dst->AddStringAttribute(ui::AX_ATTR_DOC_DOCTYPE, |
380 base::UTF16ToUTF8(doctype.name())); | 304 UTF16ToUTF8(doctype.name())); |
381 } | 305 } |
382 | 306 |
383 const gfx::Size& scroll_offset = document.frame()->scrollOffset(); | 307 const gfx::Size& scroll_offset = document.frame()->scrollOffset(); |
384 dst->AddIntAttribute(dst->ATTR_SCROLL_X, scroll_offset.width()); | 308 dst->AddIntAttribute(ui::AX_ATTR_SCROLL_X, scroll_offset.width()); |
385 dst->AddIntAttribute(dst->ATTR_SCROLL_Y, scroll_offset.height()); | 309 dst->AddIntAttribute(ui::AX_ATTR_SCROLL_Y, scroll_offset.height()); |
386 | 310 |
387 const gfx::Size& min_offset = document.frame()->minimumScrollOffset(); | 311 const gfx::Size& min_offset = document.frame()->minimumScrollOffset(); |
388 dst->AddIntAttribute(dst->ATTR_SCROLL_X_MIN, min_offset.width()); | 312 dst->AddIntAttribute(ui::AX_ATTR_SCROLL_X_MIN, min_offset.width()); |
389 dst->AddIntAttribute(dst->ATTR_SCROLL_Y_MIN, min_offset.height()); | 313 dst->AddIntAttribute(ui::AX_ATTR_SCROLL_Y_MIN, min_offset.height()); |
390 | 314 |
391 const gfx::Size& max_offset = document.frame()->maximumScrollOffset(); | 315 const gfx::Size& max_offset = document.frame()->maximumScrollOffset(); |
392 dst->AddIntAttribute(dst->ATTR_SCROLL_X_MAX, max_offset.width()); | 316 dst->AddIntAttribute(ui::AX_ATTR_SCROLL_X_MAX, max_offset.width()); |
393 dst->AddIntAttribute(dst->ATTR_SCROLL_Y_MAX, max_offset.height()); | 317 dst->AddIntAttribute(ui::AX_ATTR_SCROLL_Y_MAX, max_offset.height()); |
394 } | 318 } |
395 | 319 |
396 if (dst->role == blink::WebAXRoleTable) { | 320 if (dst->role == ui::AX_ROLE_TABLE) { |
397 int column_count = src.columnCount(); | 321 int column_count = src.columnCount(); |
398 int row_count = src.rowCount(); | 322 int row_count = src.rowCount(); |
399 if (column_count > 0 && row_count > 0) { | 323 if (column_count > 0 && row_count > 0) { |
400 std::set<int32> unique_cell_id_set; | 324 std::set<int32> unique_cell_id_set; |
401 std::vector<int32> cell_ids; | 325 std::vector<int32> cell_ids; |
402 std::vector<int32> unique_cell_ids; | 326 std::vector<int32> unique_cell_ids; |
403 dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_COUNT, column_count); | 327 dst->AddIntAttribute(ui::AX_ATTR_TABLE_COLUMN_COUNT, column_count); |
404 dst->AddIntAttribute(dst->ATTR_TABLE_ROW_COUNT, row_count); | 328 dst->AddIntAttribute(ui::AX_ATTR_TABLE_ROW_COUNT, row_count); |
405 WebAXObject header = src.headerContainerObject(); | 329 WebAXObject header = src.headerContainerObject(); |
406 if (!header.isDetached()) | 330 if (!header.isDetached()) |
407 dst->AddIntAttribute(dst->ATTR_TABLE_HEADER_ID, header.axID()); | 331 dst->AddIntAttribute(ui::AX_ATTR_TABLE_HEADER_ID, header.axID()); |
408 for (int i = 0; i < column_count * row_count; ++i) { | 332 for (int i = 0; i < column_count * row_count; ++i) { |
409 WebAXObject cell = src.cellForColumnAndRow( | 333 WebAXObject cell = src.cellForColumnAndRow( |
410 i % column_count, i / column_count); | 334 i % column_count, i / column_count); |
411 int cell_id = -1; | 335 int cell_id = -1; |
412 if (!cell.isDetached()) { | 336 if (!cell.isDetached()) { |
413 cell_id = cell.axID(); | 337 cell_id = cell.axID(); |
414 if (unique_cell_id_set.find(cell_id) == unique_cell_id_set.end()) { | 338 if (unique_cell_id_set.find(cell_id) == unique_cell_id_set.end()) { |
415 unique_cell_id_set.insert(cell_id); | 339 unique_cell_id_set.insert(cell_id); |
416 unique_cell_ids.push_back(cell_id); | 340 unique_cell_ids.push_back(cell_id); |
417 } | 341 } |
418 } | 342 } |
419 cell_ids.push_back(cell_id); | 343 cell_ids.push_back(cell_id); |
420 } | 344 } |
421 dst->AddIntListAttribute(dst->ATTR_CELL_IDS, cell_ids); | 345 dst->AddIntListAttribute(ui::AX_ATTR_CELL_IDS, cell_ids); |
422 dst->AddIntListAttribute(dst->ATTR_UNIQUE_CELL_IDS, unique_cell_ids); | 346 dst->AddIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS, unique_cell_ids); |
423 } | 347 } |
424 } | 348 } |
425 | 349 |
426 if (dst->role == blink::WebAXRoleRow) { | 350 if (dst->role == ui::AX_ROLE_ROW) { |
427 dst->AddIntAttribute(dst->ATTR_TABLE_ROW_INDEX, src.rowIndex()); | 351 dst->AddIntAttribute(ui::AX_ATTR_TABLE_ROW_INDEX, src.rowIndex()); |
428 WebAXObject header = src.rowHeader(); | 352 WebAXObject header = src.rowHeader(); |
429 if (!header.isDetached()) | 353 if (!header.isDetached()) |
430 dst->AddIntAttribute(dst->ATTR_TABLE_ROW_HEADER_ID, header.axID()); | 354 dst->AddIntAttribute(ui::AX_ATTR_TABLE_ROW_HEADER_ID, header.axID()); |
431 } | 355 } |
432 | 356 |
433 if (dst->role == blink::WebAXRoleColumn) { | 357 if (dst->role == ui::AX_ROLE_COLUMN) { |
434 dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_INDEX, src.columnIndex()); | 358 dst->AddIntAttribute(ui::AX_ATTR_TABLE_COLUMN_INDEX, src.columnIndex()); |
435 WebAXObject header = src.columnHeader(); | 359 WebAXObject header = src.columnHeader(); |
436 if (!header.isDetached()) | 360 if (!header.isDetached()) |
437 dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_HEADER_ID, header.axID()); | 361 dst->AddIntAttribute(ui::AX_ATTR_TABLE_COLUMN_HEADER_ID, header.axID()); |
438 } | 362 } |
439 | 363 |
440 if (dst->role == blink::WebAXRoleCell || | 364 if (dst->role == ui::AX_ROLE_CELL || |
441 dst->role == blink::WebAXRoleRowHeader || | 365 dst->role == ui::AX_ROLE_ROW_HEADER || |
442 dst->role == blink::WebAXRoleColumnHeader) { | 366 dst->role == ui::AX_ROLE_COLUMN_HEADER) { |
443 dst->AddIntAttribute(dst->ATTR_TABLE_CELL_COLUMN_INDEX, | 367 dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_COLUMN_INDEX, |
444 src.cellColumnIndex()); | 368 src.cellColumnIndex()); |
445 dst->AddIntAttribute(dst->ATTR_TABLE_CELL_COLUMN_SPAN, | 369 dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_COLUMN_SPAN, |
446 src.cellColumnSpan()); | 370 src.cellColumnSpan()); |
447 dst->AddIntAttribute(dst->ATTR_TABLE_CELL_ROW_INDEX, src.cellRowIndex()); | 371 dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_ROW_INDEX, src.cellRowIndex()); |
448 dst->AddIntAttribute(dst->ATTR_TABLE_CELL_ROW_SPAN, src.cellRowSpan()); | 372 dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_ROW_SPAN, src.cellRowSpan()); |
449 } | 373 } |
450 | 374 |
451 dst->AddStringAttribute(dst->ATTR_NAME, name); | 375 dst->AddStringAttribute(ui::AX_ATTR_NAME, name); |
452 | 376 |
453 // Add the ids of *indirect* children - those who are children of this node, | 377 // Add the ids of *indirect* children - those who are children of this node, |
454 // but whose parent is *not* this node. One example is a table | 378 // but whose parent is *not* this node. One example is a table |
455 // cell, which is a child of both a row and a column. Because the cell's | 379 // cell, which is a child of both a row and a column. Because the cell's |
456 // parent is the row, the row adds it as a child, and the column adds it | 380 // parent is the row, the row adds it as a child, and the column adds it |
457 // as an indirect child. | 381 // as an indirect child. |
458 int child_count = src.childCount(); | 382 int child_count = src.childCount(); |
459 for (int i = 0; i < child_count; ++i) { | 383 for (int i = 0; i < child_count; ++i) { |
460 WebAXObject child = src.childAt(i); | 384 WebAXObject child = src.childAt(i); |
461 std::vector<int32> indirect_child_ids; | 385 std::vector<int32> indirect_child_ids; |
462 if (!is_iframe && !child.isDetached() && !IsParentUnignoredOf(src, child)) | 386 if (!is_iframe && !child.isDetached() && !IsParentUnignoredOf(src, child)) |
463 indirect_child_ids.push_back(child.axID()); | 387 indirect_child_ids.push_back(child.axID()); |
464 if (indirect_child_ids.size() > 0) { | 388 if (indirect_child_ids.size() > 0) { |
465 dst->AddIntListAttribute( | 389 dst->AddIntListAttribute( |
466 dst->ATTR_INDIRECT_CHILD_IDS, indirect_child_ids); | 390 ui::AX_ATTR_INDIRECT_CHILD_IDS, indirect_child_ids); |
467 } | 391 } |
468 } | 392 } |
469 } | 393 } |
470 | 394 |
471 bool ShouldIncludeChildNode( | 395 bool ShouldIncludeChildNode( |
472 const WebAXObject& parent, | 396 const WebAXObject& parent, |
473 const WebAXObject& child) { | 397 const WebAXObject& child) { |
474 // The child may be invalid due to issues in webkit accessibility code. | 398 // The child may be invalid due to issues in webkit accessibility code. |
475 // Don't add children that are invalid thus preventing a crash. | 399 // Don't add children that are invalid thus preventing a crash. |
476 // https://bugs.webkit.org/show_bug.cgi?id=44149 | 400 // https://bugs.webkit.org/show_bug.cgi?id=44149 |
477 // TODO(ctguil): We may want to remove this check as webkit stabilizes. | 401 // TODO(ctguil): We may want to remove this check as webkit stabilizes. |
478 if (child.isDetached()) | 402 if (child.isDetached()) |
479 return false; | 403 return false; |
480 | 404 |
481 // Skip children whose parent isn't this - see indirect_child_ids, above. | 405 // Skip children whose parent isn't this - see indirect_child_ids, above. |
482 // As an exception, include children of an iframe element. | 406 // As an exception, include children of an iframe element. |
483 bool is_iframe = false; | 407 bool is_iframe = false; |
484 WebNode node = parent.node(); | 408 WebNode node = parent.node(); |
485 if (!node.isNull() && node.isElementNode()) { | 409 if (!node.isNull() && node.isElementNode()) { |
486 WebElement element = node.to<WebElement>(); | 410 WebElement element = node.to<WebElement>(); |
487 is_iframe = (element.tagName() == base::ASCIIToUTF16("IFRAME")); | 411 is_iframe = (element.tagName() == base::ASCIIToUTF16("IFRAME")); |
488 } | 412 } |
489 | 413 |
490 return (is_iframe || IsParentUnignoredOf(parent, child)); | 414 return (is_iframe || IsParentUnignoredOf(parent, child)); |
491 } | 415 } |
492 | 416 |
493 } // namespace content | 417 } // namespace content |
OLD | NEW |