Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Side by Side Diff: third_party/WebKit/Source/modules/accessibility/InspectorAccessibilityAgent.cpp

Issue 2390783006: [DevTools] Accessibility: Show siblings and children of selected node (Closed)
Patch Set: Ready for a first look Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "modules/accessibility/InspectorAccessibilityAgent.h" 5 #include "modules/accessibility/InspectorAccessibilityAgent.h"
6 6
7 #include "core/HTMLNames.h" 7 #include "core/HTMLNames.h"
8 #include "core/dom/AXObjectCache.h" 8 #include "core/dom/AXObjectCache.h"
9 #include "core/dom/DOMNodeIds.h" 9 #include "core/dom/DOMNodeIds.h"
10 #include "core/dom/Element.h" 10 #include "core/dom/Element.h"
11 #include "core/dom/Node.h"
12 #include "core/dom/NodeList.h"
11 #include "core/inspector/IdentifiersFactory.h" 13 #include "core/inspector/IdentifiersFactory.h"
12 #include "core/inspector/InspectorDOMAgent.h" 14 #include "core/inspector/InspectorDOMAgent.h"
13 #include "core/inspector/InspectorStyleSheet.h" 15 #include "core/inspector/InspectorStyleSheet.h"
14 #include "core/page/Page.h" 16 #include "core/page/Page.h"
15 #include "modules/accessibility/AXObject.h" 17 #include "modules/accessibility/AXObject.h"
16 #include "modules/accessibility/AXObjectCacheImpl.h" 18 #include "modules/accessibility/AXObjectCacheImpl.h"
17 #include "modules/accessibility/InspectorTypeBuilderHelper.h" 19 #include "modules/accessibility/InspectorTypeBuilderHelper.h"
18 #include <memory> 20 #include <memory>
19 21
20 namespace blink { 22 namespace blink {
21 23
22 using protocol::Accessibility::AXGlobalStates; 24 using protocol::Accessibility::AXGlobalStates;
23 using protocol::Accessibility::AXLiveRegionAttributes; 25 using protocol::Accessibility::AXLiveRegionAttributes;
24 using protocol::Accessibility::AXNode; 26 using protocol::Accessibility::AXNode;
25 using protocol::Accessibility::AXNodeId; 27 using protocol::Accessibility::AXNodeId;
26 using protocol::Accessibility::AXProperty; 28 using protocol::Accessibility::AXProperty;
27 using protocol::Accessibility::AXValueSource; 29 using protocol::Accessibility::AXValueSource;
28 using protocol::Accessibility::AXValueType; 30 using protocol::Accessibility::AXValueType;
29 using protocol::Accessibility::AXRelatedNode; 31 using protocol::Accessibility::AXRelatedNode;
30 using protocol::Accessibility::AXRelationshipAttributes; 32 using protocol::Accessibility::AXRelationshipAttributes;
31 using protocol::Accessibility::AXValue; 33 using protocol::Accessibility::AXValue;
32 using protocol::Accessibility::AXWidgetAttributes; 34 using protocol::Accessibility::AXWidgetAttributes;
33 using protocol::Accessibility::AXWidgetStates; 35 using protocol::Accessibility::AXWidgetStates;
34 36
35 using namespace HTMLNames; 37 using namespace HTMLNames;
36 38
37 namespace { 39 namespace {
38 40
39 void fillCoreProperties(AXObject* axObject, AXNode* nodeObject) { 41 void fillLiveRegionProperties(AXObject& axObject,
40 // Description (secondary to the accessible name). 42 protocol::Array<AXProperty>& properties) {
41 AXNameFrom nameFrom; 43 if (!axObject.liveRegionRoot())
42 AXObject::AXObjectVector nameObjects; 44 return;
43 axObject->name(nameFrom, &nameObjects);
44 AXDescriptionFrom descriptionFrom;
45 AXObject::AXObjectVector descriptionObjects;
46 String description =
47 axObject->description(nameFrom, descriptionFrom, &descriptionObjects);
48 if (!description.isEmpty())
49 nodeObject->setDescription(
50 createValue(description, AXValueTypeEnum::ComputedString));
51 45
52 // Value. 46 properties.addItem(
53 if (axObject->supportsRangeValue()) { 47 createProperty(AXLiveRegionAttributesEnum::Live,
54 nodeObject->setValue(createValue(axObject->valueForRange())); 48 createValue(axObject.containerLiveRegionStatus(),
55 } else { 49 AXValueTypeEnum::Token)));
56 String stringValue = axObject->stringValue(); 50 properties.addItem(
57 if (!stringValue.isEmpty()) 51 createProperty(AXLiveRegionAttributesEnum::Atomic,
58 nodeObject->setValue(createValue(stringValue)); 52 createBooleanValue(axObject.containerLiveRegionAtomic())));
53 properties.addItem(
54 createProperty(AXLiveRegionAttributesEnum::Relevant,
55 createValue(axObject.containerLiveRegionRelevant(),
56 AXValueTypeEnum::TokenList)));
57 properties.addItem(
58 createProperty(AXLiveRegionAttributesEnum::Busy,
59 createBooleanValue(axObject.containerLiveRegionBusy())));
60
61 if (!axObject.isLiveRegion()) {
62 properties.addItem(createProperty(
63 AXLiveRegionAttributesEnum::Root,
64 createRelatedNodeListValue(*(axObject.liveRegionRoot()))));
59 } 65 }
60 } 66 }
61 67
62 void fillLiveRegionProperties(AXObject* axObject, 68 void fillGlobalStates(AXObject& axObject,
63 protocol::Array<AXProperty>* properties) { 69 protocol::Array<AXProperty>& properties) {
64 if (!axObject->liveRegionRoot()) 70 if (!axObject.isEnabled())
65 return; 71 properties.addItem(
66
67 properties->addItem(
68 createProperty(AXLiveRegionAttributesEnum::Live,
69 createValue(axObject->containerLiveRegionStatus(),
70 AXValueTypeEnum::Token)));
71 properties->addItem(createProperty(
72 AXLiveRegionAttributesEnum::Atomic,
73 createBooleanValue(axObject->containerLiveRegionAtomic())));
74 properties->addItem(
75 createProperty(AXLiveRegionAttributesEnum::Relevant,
76 createValue(axObject->containerLiveRegionRelevant(),
77 AXValueTypeEnum::TokenList)));
78 properties->addItem(
79 createProperty(AXLiveRegionAttributesEnum::Busy,
80 createBooleanValue(axObject->containerLiveRegionBusy())));
81
82 if (!axObject->isLiveRegion())
83 properties->addItem(
84 createProperty(AXLiveRegionAttributesEnum::Root,
85 createRelatedNodeListValue(axObject->liveRegionRoot())));
86 }
87
88 void fillGlobalStates(AXObject* axObject,
89 protocol::Array<AXProperty>* properties) {
90 if (!axObject->isEnabled())
91 properties->addItem(
92 createProperty(AXGlobalStatesEnum::Disabled, createBooleanValue(true))); 72 createProperty(AXGlobalStatesEnum::Disabled, createBooleanValue(true)));
93 73
94 if (const AXObject* hiddenRoot = axObject->ariaHiddenRoot()) { 74 if (const AXObject* hiddenRoot = axObject.ariaHiddenRoot()) {
95 properties->addItem( 75 properties.addItem(
96 createProperty(AXGlobalStatesEnum::Hidden, createBooleanValue(true))); 76 createProperty(AXGlobalStatesEnum::Hidden, createBooleanValue(true)));
97 properties->addItem(createProperty(AXGlobalStatesEnum::HiddenRoot, 77 properties.addItem(createProperty(AXGlobalStatesEnum::HiddenRoot,
98 createRelatedNodeListValue(hiddenRoot))); 78 createRelatedNodeListValue(*hiddenRoot)));
99 } 79 }
100 80
101 InvalidState invalidState = axObject->getInvalidState(); 81 InvalidState invalidState = axObject.getInvalidState();
102 switch (invalidState) { 82 switch (invalidState) {
103 case InvalidStateUndefined: 83 case InvalidStateUndefined:
104 break; 84 break;
105 case InvalidStateFalse: 85 case InvalidStateFalse:
106 properties->addItem( 86 properties.addItem(
107 createProperty(AXGlobalStatesEnum::Invalid, 87 createProperty(AXGlobalStatesEnum::Invalid,
108 createValue("false", AXValueTypeEnum::Token))); 88 createValue("false", AXValueTypeEnum::Token)));
109 break; 89 break;
110 case InvalidStateTrue: 90 case InvalidStateTrue:
111 properties->addItem( 91 properties.addItem(
112 createProperty(AXGlobalStatesEnum::Invalid, 92 createProperty(AXGlobalStatesEnum::Invalid,
113 createValue("true", AXValueTypeEnum::Token))); 93 createValue("true", AXValueTypeEnum::Token)));
114 break; 94 break;
115 case InvalidStateSpelling: 95 case InvalidStateSpelling:
116 properties->addItem( 96 properties.addItem(
117 createProperty(AXGlobalStatesEnum::Invalid, 97 createProperty(AXGlobalStatesEnum::Invalid,
118 createValue("spelling", AXValueTypeEnum::Token))); 98 createValue("spelling", AXValueTypeEnum::Token)));
119 break; 99 break;
120 case InvalidStateGrammar: 100 case InvalidStateGrammar:
121 properties->addItem( 101 properties.addItem(
122 createProperty(AXGlobalStatesEnum::Invalid, 102 createProperty(AXGlobalStatesEnum::Invalid,
123 createValue("grammar", AXValueTypeEnum::Token))); 103 createValue("grammar", AXValueTypeEnum::Token)));
124 break; 104 break;
125 default: 105 default:
126 // TODO(aboxhall): expose invalid: <nothing> and source: aria-invalid as 106 // TODO(aboxhall): expose invalid: <nothing> and source: aria-invalid as
127 // invalid value 107 // invalid value
128 properties->addItem(createProperty( 108 properties.addItem(createProperty(
129 AXGlobalStatesEnum::Invalid, 109 AXGlobalStatesEnum::Invalid,
130 createValue(axObject->ariaInvalidValue(), AXValueTypeEnum::String))); 110 createValue(axObject.ariaInvalidValue(), AXValueTypeEnum::String)));
131 break; 111 break;
132 } 112 }
133 } 113 }
134 114
135 bool roleAllowsMultiselectable(AccessibilityRole role) { 115 bool roleAllowsMultiselectable(AccessibilityRole role) {
136 return role == GridRole || role == ListBoxRole || role == TabListRole || 116 return role == GridRole || role == ListBoxRole || role == TabListRole ||
137 role == TreeGridRole || role == TreeRole; 117 role == TreeGridRole || role == TreeRole;
138 } 118 }
139 119
140 bool roleAllowsOrientation(AccessibilityRole role) { 120 bool roleAllowsOrientation(AccessibilityRole role) {
(...skipping 25 matching lines...) Expand all
166 role == SwitchRole; 146 role == SwitchRole;
167 } 147 }
168 148
169 bool roleAllowsSelected(AccessibilityRole role) { 149 bool roleAllowsSelected(AccessibilityRole role) {
170 return role == CellRole || role == ListBoxOptionRole || role == RowRole || 150 return role == CellRole || role == ListBoxOptionRole || role == RowRole ||
171 role == TabRole || role == ColumnHeaderRole || 151 role == TabRole || role == ColumnHeaderRole ||
172 role == MenuItemRadioRole || role == RadioButtonRole || 152 role == MenuItemRadioRole || role == RadioButtonRole ||
173 role == RowHeaderRole || role == TreeItemRole; 153 role == RowHeaderRole || role == TreeItemRole;
174 } 154 }
175 155
176 void fillWidgetProperties(AXObject* axObject, 156 void fillWidgetProperties(AXObject& axObject,
dmazzoni 2016/10/19 16:33:49 You could land a quick change to replace pointers
aboxhall 2016/10/19 23:49:05 Done.
177 protocol::Array<AXProperty>* properties) { 157 protocol::Array<AXProperty>& properties) {
178 AccessibilityRole role = axObject->roleValue(); 158 AccessibilityRole role = axObject.roleValue();
179 String autocomplete = axObject->ariaAutoComplete(); 159 String autocomplete = axObject.ariaAutoComplete();
180 if (!autocomplete.isEmpty()) 160 if (!autocomplete.isEmpty())
181 properties->addItem( 161 properties.addItem(
182 createProperty(AXWidgetAttributesEnum::Autocomplete, 162 createProperty(AXWidgetAttributesEnum::Autocomplete,
183 createValue(autocomplete, AXValueTypeEnum::Token))); 163 createValue(autocomplete, AXValueTypeEnum::Token)));
184 164
185 if (axObject->hasAttribute(HTMLNames::aria_haspopupAttr)) { 165 if (axObject.hasAttribute(HTMLNames::aria_haspopupAttr)) {
186 bool hasPopup = axObject->ariaHasPopup(); 166 bool hasPopup = axObject.ariaHasPopup();
187 properties->addItem(createProperty(AXWidgetAttributesEnum::Haspopup, 167 properties.addItem(createProperty(AXWidgetAttributesEnum::Haspopup,
188 createBooleanValue(hasPopup))); 168 createBooleanValue(hasPopup)));
189 } 169 }
190 170
191 int headingLevel = axObject->headingLevel(); 171 int headingLevel = axObject.headingLevel();
192 if (headingLevel > 0) 172 if (headingLevel > 0) {
dmazzoni 2016/10/19 16:33:49 Did this come from "git cl format" or some other a
aboxhall 2016/10/19 23:49:05 Done.
193 properties->addItem(createProperty(AXWidgetAttributesEnum::Level, 173 properties.addItem(createProperty(AXWidgetAttributesEnum::Level,
194 createValue(headingLevel))); 174 createValue(headingLevel)));
195 int hierarchicalLevel = axObject->hierarchicalLevel(); 175 }
176 int hierarchicalLevel = axObject.hierarchicalLevel();
196 if (hierarchicalLevel > 0 || 177 if (hierarchicalLevel > 0 ||
197 axObject->hasAttribute(HTMLNames::aria_levelAttr)) 178 axObject.hasAttribute(HTMLNames::aria_levelAttr)) {
198 properties->addItem(createProperty(AXWidgetAttributesEnum::Level, 179 properties.addItem(createProperty(AXWidgetAttributesEnum::Level,
199 createValue(hierarchicalLevel))); 180 createValue(hierarchicalLevel)));
181 }
200 182
201 if (roleAllowsMultiselectable(role)) { 183 if (roleAllowsMultiselectable(role)) {
202 bool multiselectable = axObject->isMultiSelectable(); 184 bool multiselectable = axObject.isMultiSelectable();
203 properties->addItem(createProperty(AXWidgetAttributesEnum::Multiselectable, 185 properties.addItem(createProperty(AXWidgetAttributesEnum::Multiselectable,
204 createBooleanValue(multiselectable))); 186 createBooleanValue(multiselectable)));
205 } 187 }
206 188
207 if (roleAllowsOrientation(role)) { 189 if (roleAllowsOrientation(role)) {
208 AccessibilityOrientation orientation = axObject->orientation(); 190 AccessibilityOrientation orientation = axObject.orientation();
209 switch (orientation) { 191 switch (orientation) {
210 case AccessibilityOrientationVertical: 192 case AccessibilityOrientationVertical:
211 properties->addItem( 193 properties.addItem(
212 createProperty(AXWidgetAttributesEnum::Orientation, 194 createProperty(AXWidgetAttributesEnum::Orientation,
213 createValue("vertical", AXValueTypeEnum::Token))); 195 createValue("vertical", AXValueTypeEnum::Token)));
214 break; 196 break;
215 case AccessibilityOrientationHorizontal: 197 case AccessibilityOrientationHorizontal:
216 properties->addItem( 198 properties.addItem(
217 createProperty(AXWidgetAttributesEnum::Orientation, 199 createProperty(AXWidgetAttributesEnum::Orientation,
218 createValue("horizontal", AXValueTypeEnum::Token))); 200 createValue("horizontal", AXValueTypeEnum::Token)));
219 break; 201 break;
220 case AccessibilityOrientationUndefined: 202 case AccessibilityOrientationUndefined:
221 break; 203 break;
222 } 204 }
223 } 205 }
224 206
225 if (role == TextFieldRole) 207 if (role == TextFieldRole) {
226 properties->addItem( 208 properties.addItem(
227 createProperty(AXWidgetAttributesEnum::Multiline, 209 createProperty(AXWidgetAttributesEnum::Multiline,
228 createBooleanValue(axObject->isMultiline()))); 210 createBooleanValue(axObject.isMultiline())));
211 }
229 212
230 if (roleAllowsReadonly(role)) { 213 if (roleAllowsReadonly(role)) {
231 properties->addItem( 214 properties.addItem(
232 createProperty(AXWidgetAttributesEnum::Readonly, 215 createProperty(AXWidgetAttributesEnum::Readonly,
233 createBooleanValue(axObject->isReadOnly()))); 216 createBooleanValue(axObject.isReadOnly())));
234 } 217 }
235 218
236 if (roleAllowsRequired(role)) { 219 if (roleAllowsRequired(role)) {
237 properties->addItem( 220 properties.addItem(
238 createProperty(AXWidgetAttributesEnum::Required, 221 createProperty(AXWidgetAttributesEnum::Required,
239 createBooleanValue(axObject->isRequired()))); 222 createBooleanValue(axObject.isRequired())));
240 } 223 }
241 224
242 if (roleAllowsSort(role)) { 225 if (roleAllowsSort(role)) {
243 // TODO(aboxhall): sort 226 // TODO(aboxhall): sort
244 } 227 }
245 228
246 if (axObject->isRange()) { 229 if (axObject.isRange()) {
247 properties->addItem( 230 properties.addItem(
248 createProperty(AXWidgetAttributesEnum::Valuemin, 231 createProperty(AXWidgetAttributesEnum::Valuemin,
249 createValue(axObject->minValueForRange()))); 232 createValue(axObject.minValueForRange())));
250 properties->addItem( 233 properties.addItem(
251 createProperty(AXWidgetAttributesEnum::Valuemax, 234 createProperty(AXWidgetAttributesEnum::Valuemax,
252 createValue(axObject->maxValueForRange()))); 235 createValue(axObject.maxValueForRange())));
253 properties->addItem( 236 properties.addItem(
254 createProperty(AXWidgetAttributesEnum::Valuetext, 237 createProperty(AXWidgetAttributesEnum::Valuetext,
255 createValue(axObject->valueDescription()))); 238 createValue(axObject.valueDescription())));
256 } 239 }
257 } 240 }
258 241
259 void fillWidgetStates(AXObject* axObject, 242 void fillWidgetStates(AXObject& axObject,
260 protocol::Array<AXProperty>* properties) { 243 protocol::Array<AXProperty>& properties) {
261 AccessibilityRole role = axObject->roleValue(); 244 AccessibilityRole role = axObject.roleValue();
262 if (roleAllowsChecked(role)) { 245 if (roleAllowsChecked(role)) {
263 AccessibilityButtonState checked = axObject->checkboxOrRadioValue(); 246 AccessibilityButtonState checked = axObject.checkboxOrRadioValue();
264 switch (checked) { 247 switch (checked) {
265 case ButtonStateOff: 248 case ButtonStateOff:
266 properties->addItem( 249 properties.addItem(
267 createProperty(AXWidgetStatesEnum::Checked, 250 createProperty(AXWidgetStatesEnum::Checked,
268 createValue("false", AXValueTypeEnum::Tristate))); 251 createValue("false", AXValueTypeEnum::Tristate)));
269 break; 252 break;
270 case ButtonStateOn: 253 case ButtonStateOn:
271 properties->addItem( 254 properties.addItem(
272 createProperty(AXWidgetStatesEnum::Checked, 255 createProperty(AXWidgetStatesEnum::Checked,
273 createValue("true", AXValueTypeEnum::Tristate))); 256 createValue("true", AXValueTypeEnum::Tristate)));
274 break; 257 break;
275 case ButtonStateMixed: 258 case ButtonStateMixed:
276 properties->addItem( 259 properties.addItem(
277 createProperty(AXWidgetStatesEnum::Checked, 260 createProperty(AXWidgetStatesEnum::Checked,
278 createValue("mixed", AXValueTypeEnum::Tristate))); 261 createValue("mixed", AXValueTypeEnum::Tristate)));
279 break; 262 break;
280 } 263 }
281 } 264 }
282 265
283 AccessibilityExpanded expanded = axObject->isExpanded(); 266 AccessibilityExpanded expanded = axObject.isExpanded();
284 switch (expanded) { 267 switch (expanded) {
285 case ExpandedUndefined: 268 case ExpandedUndefined:
286 break; 269 break;
287 case ExpandedCollapsed: 270 case ExpandedCollapsed:
288 properties->addItem(createProperty( 271 properties.addItem(createProperty(
289 AXWidgetStatesEnum::Expanded, 272 AXWidgetStatesEnum::Expanded,
290 createBooleanValue(false, AXValueTypeEnum::BooleanOrUndefined))); 273 createBooleanValue(false, AXValueTypeEnum::BooleanOrUndefined)));
291 break; 274 break;
292 case ExpandedExpanded: 275 case ExpandedExpanded:
293 properties->addItem(createProperty( 276 properties.addItem(createProperty(
294 AXWidgetStatesEnum::Expanded, 277 AXWidgetStatesEnum::Expanded,
295 createBooleanValue(true, AXValueTypeEnum::BooleanOrUndefined))); 278 createBooleanValue(true, AXValueTypeEnum::BooleanOrUndefined)));
296 break; 279 break;
297 } 280 }
298 281
299 if (role == ToggleButtonRole) { 282 if (role == ToggleButtonRole) {
300 if (!axObject->isPressed()) { 283 if (!axObject.isPressed()) {
301 properties->addItem( 284 properties.addItem(
302 createProperty(AXWidgetStatesEnum::Pressed, 285 createProperty(AXWidgetStatesEnum::Pressed,
303 createValue("false", AXValueTypeEnum::Tristate))); 286 createValue("false", AXValueTypeEnum::Tristate)));
304 } else { 287 } else {
305 const AtomicString& pressedAttr = 288 const AtomicString& pressedAttr =
306 axObject->getAttribute(HTMLNames::aria_pressedAttr); 289 axObject.getAttribute(HTMLNames::aria_pressedAttr);
307 if (equalIgnoringCase(pressedAttr, "mixed")) 290 if (equalIgnoringCase(pressedAttr, "mixed"))
308 properties->addItem( 291 properties.addItem(
309 createProperty(AXWidgetStatesEnum::Pressed, 292 createProperty(AXWidgetStatesEnum::Pressed,
310 createValue("mixed", AXValueTypeEnum::Tristate))); 293 createValue("mixed", AXValueTypeEnum::Tristate)));
311 else 294 else
312 properties->addItem( 295 properties.addItem(
313 createProperty(AXWidgetStatesEnum::Pressed, 296 createProperty(AXWidgetStatesEnum::Pressed,
314 createValue("true", AXValueTypeEnum::Tristate))); 297 createValue("true", AXValueTypeEnum::Tristate)));
315 } 298 }
316 } 299 }
317 300
318 if (roleAllowsSelected(role)) { 301 if (roleAllowsSelected(role)) {
319 properties->addItem( 302 properties.addItem(
320 createProperty(AXWidgetStatesEnum::Selected, 303 createProperty(AXWidgetStatesEnum::Selected,
321 createBooleanValue(axObject->isSelected()))); 304 createBooleanValue(axObject.isSelected())));
322 } 305 }
323 } 306 }
324 307
325 std::unique_ptr<AXProperty> createRelatedNodeListProperty( 308 std::unique_ptr<AXProperty> createRelatedNodeListProperty(
326 const String& key, 309 const String& key,
327 AXRelatedObjectVector& nodes) { 310 AXRelatedObjectVector& nodes) {
328 std::unique_ptr<AXValue> nodeListValue = 311 std::unique_ptr<AXValue> nodeListValue =
329 createRelatedNodeListValue(nodes, AXValueTypeEnum::NodeList); 312 createRelatedNodeListValue(nodes, AXValueTypeEnum::NodeList);
330 return createProperty(key, std::move(nodeListValue)); 313 return createProperty(key, std::move(nodeListValue));
331 } 314 }
332 315
333 std::unique_ptr<AXProperty> createRelatedNodeListProperty( 316 std::unique_ptr<AXProperty> createRelatedNodeListProperty(
334 const String& key, 317 const String& key,
335 AXObject::AXObjectVector& nodes, 318 AXObject::AXObjectVector& nodes,
336 const QualifiedName& attr, 319 const QualifiedName& attr,
337 AXObject* axObject) { 320 AXObject& axObject) {
338 std::unique_ptr<AXValue> nodeListValue = createRelatedNodeListValue(nodes); 321 std::unique_ptr<AXValue> nodeListValue = createRelatedNodeListValue(nodes);
339 const AtomicString& attrValue = axObject->getAttribute(attr); 322 const AtomicString& attrValue = axObject.getAttribute(attr);
340 nodeListValue->setValue(protocol::StringValue::create(attrValue)); 323 nodeListValue->setValue(protocol::StringValue::create(attrValue));
341 return createProperty(key, std::move(nodeListValue)); 324 return createProperty(key, std::move(nodeListValue));
342 } 325 }
343 326
344 void fillRelationships(AXObject* axObject, 327 void fillRelationships(AXObject& axObject,
345 protocol::Array<AXProperty>* properties) { 328 protocol::Array<AXProperty>& properties) {
346 if (AXObject* activeDescendant = axObject->activeDescendant()) { 329 if (AXObject* activeDescendant = axObject.activeDescendant()) {
347 properties->addItem( 330 properties.addItem(
348 createProperty(AXRelationshipAttributesEnum::Activedescendant, 331 createProperty(AXRelationshipAttributesEnum::Activedescendant,
349 createRelatedNodeListValue(activeDescendant))); 332 createRelatedNodeListValue(*activeDescendant)));
350 } 333 }
351 334
352 AXObject::AXObjectVector results; 335 AXObject::AXObjectVector results;
353 axObject->ariaFlowToElements(results); 336 axObject.ariaFlowToElements(results);
354 if (!results.isEmpty()) 337 if (!results.isEmpty())
355 properties->addItem( 338 properties.addItem(
356 createRelatedNodeListProperty(AXRelationshipAttributesEnum::Flowto, 339 createRelatedNodeListProperty(AXRelationshipAttributesEnum::Flowto,
357 results, aria_flowtoAttr, axObject)); 340 results, aria_flowtoAttr, axObject));
358 results.clear(); 341 results.clear();
359 342
360 axObject->ariaControlsElements(results); 343 axObject.ariaControlsElements(results);
361 if (!results.isEmpty()) 344 if (!results.isEmpty())
362 properties->addItem( 345 properties.addItem(
363 createRelatedNodeListProperty(AXRelationshipAttributesEnum::Controls, 346 createRelatedNodeListProperty(AXRelationshipAttributesEnum::Controls,
364 results, aria_controlsAttr, axObject)); 347 results, aria_controlsAttr, axObject));
365 results.clear(); 348 results.clear();
366 349
367 axObject->ariaDescribedbyElements(results); 350 axObject.ariaDescribedbyElements(results);
368 if (!results.isEmpty()) 351 if (!results.isEmpty())
369 properties->addItem( 352 properties.addItem(
370 createRelatedNodeListProperty(AXRelationshipAttributesEnum::Describedby, 353 createRelatedNodeListProperty(AXRelationshipAttributesEnum::Describedby,
371 results, aria_describedbyAttr, axObject)); 354 results, aria_describedbyAttr, axObject));
372 results.clear(); 355 results.clear();
373 356
374 axObject->ariaOwnsElements(results); 357 axObject.ariaOwnsElements(results);
375 if (!results.isEmpty()) 358 if (!results.isEmpty())
376 properties->addItem(createRelatedNodeListProperty( 359 properties.addItem(createRelatedNodeListProperty(
377 AXRelationshipAttributesEnum::Owns, results, aria_ownsAttr, axObject)); 360 AXRelationshipAttributesEnum::Owns, results, aria_ownsAttr, axObject));
378 results.clear(); 361 results.clear();
379 } 362 }
380 363
381 std::unique_ptr<AXValue> createRoleNameValue(AccessibilityRole role) { 364 std::unique_ptr<AXValue> createRoleNameValue(AccessibilityRole role) {
382 AtomicString roleName = AXObject::roleName(role); 365 AtomicString roleName = AXObject::roleName(role);
383 std::unique_ptr<AXValue> roleNameValue; 366 std::unique_ptr<AXValue> roleNameValue;
384 if (!roleName.isNull()) { 367 if (!roleName.isNull()) {
385 roleNameValue = createValue(roleName, AXValueTypeEnum::Role); 368 roleNameValue = createValue(roleName, AXValueTypeEnum::Role);
386 } else { 369 } else {
387 roleNameValue = createValue(AXObject::internalRoleName(role), 370 roleNameValue = createValue(AXObject::internalRoleName(role),
388 AXValueTypeEnum::InternalRole); 371 AXValueTypeEnum::InternalRole);
389 } 372 }
390 return roleNameValue; 373 return roleNameValue;
391 } 374 }
392 375
393 std::unique_ptr<AXNode> buildObjectForIgnoredNode(Node* node, 376 bool isAncestorOf(AXObject* possibleAncestor, AXObject* descendant) {
394 const AXObject* axObject) { 377 if (!possibleAncestor || !descendant)
378 return false;
379
380 AXObject* ancestor = descendant;
381 while (ancestor) {
382 if (ancestor == possibleAncestor)
383 return true;
384 ancestor = ancestor->parentObject();
385 }
386 return false;
387 }
388
389 } // namespace
390
391 InspectorAccessibilityAgent::InspectorAccessibilityAgent(
392 Page* page,
393 InspectorDOMAgent* domAgent)
394 : m_page(page), m_domAgent(domAgent) {}
395
396 void InspectorAccessibilityAgent::getPartialAXTree(
397 ErrorString* errorString,
398 int domNodeId,
399 std::unique_ptr<protocol::Array<AXNode>>* nodes) {
400 if (!m_domAgent->enabled()) {
401 *errorString = "DOM agent must be enabled";
402 return;
403 }
404 Node* domNode = m_domAgent->assertNode(errorString, domNodeId);
405 if (!domNode)
406 return;
407
408 Document& document = domNode->document();
409 document.updateStyleAndLayoutIgnorePendingStylesheets();
410 DocumentLifecycle::DisallowTransitionScope disallowTransition(
411 document.lifecycle());
412 LocalFrame* localFrame = document.frame();
413 if (!localFrame) {
414 *errorString = "Frame is detached.";
415 return;
416 }
417 std::unique_ptr<ScopedAXObjectCache> scopedCache =
418 ScopedAXObjectCache::create(document);
419 AXObjectCacheImpl* cache = toAXObjectCacheImpl(scopedCache->get());
420
421 AXObject* inspectedAXObject = cache->getOrCreate(domNode);
422 *nodes = protocol::Array<protocol::Accessibility::AXNode>::create();
423 if (!inspectedAXObject || inspectedAXObject->accessibilityIsIgnored()) {
424 (*nodes)->addItem(
425 buildObjectForIgnoredNode(domNode, inspectedAXObject, *nodes, *cache));
426 } else {
427 (*nodes)->addItem(buildProtocolAXObject(*inspectedAXObject,
428 inspectedAXObject, *nodes, *cache));
429 }
430
431 if (!inspectedAXObject)
432 return;
433
434 AXObject* parent = inspectedAXObject->parentObjectUnignored();
dmazzoni 2016/10/19 16:33:48 Will it be confusing if you can click on a node an
aboxhall 2016/10/19 23:49:05 Yeah, I think it's either that (i.e. show ignored
435 if (!parent)
436 return;
437
438 std::unique_ptr<AXNode> parentNodeObject =
439 buildProtocolAXObject(*parent, inspectedAXObject, *nodes, *cache);
440
441 (*nodes)->addItem(std::move(parentNodeObject));
dmazzoni 2016/10/19 16:33:48 Are you using parentNodeObject? If not, maybe just
aboxhall 2016/10/19 23:49:05 Done.
442 AXObject* ancestor = parent->parentObjectUnignored();
443 while (ancestor) {
444 (*nodes)->addItem(
445 buildProtocolAXObject(*ancestor, inspectedAXObject, *nodes, *cache));
dmazzoni 2016/10/19 16:33:48 I think you can eliminate a few lines of code here
aboxhall 2016/10/19 23:49:05 Done (yeah, it was originally special-casing the p
446 ancestor = ancestor->parentObjectUnignored();
447 }
448 }
449
450 std::unique_ptr<AXNode> InspectorAccessibilityAgent::buildObjectForIgnoredNode(
451 Node* domNode,
452 AXObject* axObject,
453 std::unique_ptr<protocol::Array<AXNode>>& nodes,
454 AXObjectCacheImpl& cache) const {
395 AXObject::IgnoredReasons ignoredReasons; 455 AXObject::IgnoredReasons ignoredReasons;
396 456
397 AXID axID = 0; 457 AXID axID = 0;
458 if (axObject)
459 axID = axObject->axObjectID();
398 std::unique_ptr<AXNode> ignoredNodeObject = 460 std::unique_ptr<AXNode> ignoredNodeObject =
399 AXNode::create().setNodeId(String::number(axID)).setIgnored(true).build(); 461 AXNode::create().setNodeId(String::number(axID)).setIgnored(true).build();
400 if (axObject) { 462 if (axObject) {
401 axObject->computeAccessibilityIsIgnored(&ignoredReasons); 463 axObject->computeAccessibilityIsIgnored(&ignoredReasons);
402 axID = axObject->axObjectID(); 464 axID = axObject->axObjectID();
dmazzoni 2016/10/19 16:33:49 Duplicate, you just computed it above
aboxhall 2016/10/19 23:49:05 Done.
403 AccessibilityRole role = axObject->roleValue(); 465 AccessibilityRole role = AccessibilityRole::IgnoredRole;
404 ignoredNodeObject->setRole(createRoleNameValue(role)); 466 ignoredNodeObject->setRole(createRoleNameValue(role));
405 } else if (node && !node->layoutObject()) { 467
468 populateRelatives(*axObject, axObject, *(ignoredNodeObject.get()), nodes,
469 cache);
470 } else if (domNode && !domNode->layoutObject()) {
471 populateDOMNodeRelatives(*domNode, *(ignoredNodeObject.get()), nodes,
472 cache);
406 ignoredReasons.append(IgnoredReason(AXNotRendered)); 473 ignoredReasons.append(IgnoredReason(AXNotRendered));
407 } 474 }
408 475
476 if (domNode)
477 ignoredNodeObject->setDomNodeId(DOMNodeIds::idForNode(domNode));
478
409 std::unique_ptr<protocol::Array<AXProperty>> ignoredReasonProperties = 479 std::unique_ptr<protocol::Array<AXProperty>> ignoredReasonProperties =
410 protocol::Array<AXProperty>::create(); 480 protocol::Array<AXProperty>::create();
411 for (size_t i = 0; i < ignoredReasons.size(); i++) 481 for (size_t i = 0; i < ignoredReasons.size(); i++)
412 ignoredReasonProperties->addItem(createProperty(ignoredReasons[i])); 482 ignoredReasonProperties->addItem(createProperty(ignoredReasons[i]));
413 ignoredNodeObject->setIgnoredReasons(std::move(ignoredReasonProperties)); 483 ignoredNodeObject->setIgnoredReasons(std::move(ignoredReasonProperties));
414 484
415 return ignoredNodeObject; 485 return ignoredNodeObject;
416 } 486 }
417 487
418 std::unique_ptr<AXNode> buildProtocolAXObject(AXObject* axObject) { 488 void InspectorAccessibilityAgent::populateDOMNodeRelatives(
419 AccessibilityRole role = axObject->roleValue(); 489 Node& inspectedDOMNode,
490 AXNode& nodeObject,
491 std::unique_ptr<protocol::Array<AXNode>>& nodes,
492 AXObjectCacheImpl& cache) const {
493 // Walk up parents until an AXObject can be found.
494 Node* parentNode = inspectedDOMNode.parentNode();
dmazzoni 2016/10/19 16:33:48 I'm not an expert at all, but I suspect you may wa
aboxhall 2016/10/19 23:49:05 That makes sense, thanks for catching.
495 AXObject* parentAXObject = cache.getOrCreate(parentNode);
496 while (!parentAXObject) {
497 parentNode = parentNode->parentNode();
498 parentAXObject = cache.getOrCreate(parentNode);
499 };
500 if (parentAXObject) {
501 // Populate parent and siblings.
502 nodeObject.setParentId(String::number(parentAXObject->axObjectID()));
503 std::unique_ptr<AXNode> parentNodeObject =
504 buildProtocolAXObject(*parentAXObject, nullptr, nodes, cache);
505 std::unique_ptr<protocol::Array<AXNodeId>> siblingIds =
506 protocol::Array<AXNodeId>::create();
507 findDOMNodeChildren(siblingIds, *parentNode, inspectedDOMNode, nodes,
508 cache);
509 parentNodeObject->setChildIds(std::move(siblingIds));
510 nodes->addItem(std::move(parentNodeObject));
511 }
512 // Then populate children.
513 std::unique_ptr<protocol::Array<AXNodeId>> childIds =
514 protocol::Array<AXNodeId>::create();
515 findDOMNodeChildren(childIds, inspectedDOMNode, inspectedDOMNode, nodes,
516 cache);
517 }
518
519 void InspectorAccessibilityAgent::findDOMNodeChildren(
520 std::unique_ptr<protocol::Array<AXNodeId>>& childIds,
521 Node& parentNode,
522 Node& inspectedDOMNode,
523 std::unique_ptr<protocol::Array<AXNode>>& nodes,
524 AXObjectCacheImpl& cache) const {
525 NodeList* childNodes = parentNode.childNodes();
526 for (size_t i = 0; i < childNodes->length(); ++i) {
527 Node* childNode = childNodes->item(i);
528 if (childNode == &inspectedDOMNode) {
529 childIds->addItem(String::number(0));
dmazzoni 2016/10/19 16:33:48 Can you document this magic number? Why is the ins
aboxhall 2016/10/19 23:49:05 It doesn't have an actual id - there is no AXNode
530 continue;
531 }
532 AXObject* childAXObject = cache.getOrCreate(childNode);
533 if (childAXObject && !childAXObject->accessibilityIsIgnored()) {
534 addChild(childIds, *childAXObject, nullptr, nodes, cache);
535 continue;
536 }
537
538 if (!childAXObject ||
539 childNode->isShadowIncludingInclusiveAncestorOf(&inspectedDOMNode)) {
540 // If the inspected node may be a descendant of this node, keep walking
541 // recursively until we find its actual siblings.
542 findDOMNodeChildren(childIds, *childNode, inspectedDOMNode, nodes, cache);
543 continue;
544 }
545
546 // Otherwise, just add the un-ignored children.
dmazzoni 2016/10/19 16:33:48 Reading through all of the special cases for build
aboxhall 2016/10/19 23:49:05 Not quite accurate - this is only called if there
aboxhall 2016/10/21 17:28:23 Ok, I tried that out and it actually doesn't buy u
547 const AXObject::AXObjectVector& indirectChildren =
548 childAXObject->children();
549 for (unsigned i = 0; i < indirectChildren.size(); ++i)
550 addChild(childIds, *(indirectChildren[i]), nullptr, nodes, cache);
551 }
552 }
553
554 std::unique_ptr<AXNode> InspectorAccessibilityAgent::buildProtocolAXObject(
555 AXObject& axObject,
556 AXObject* inspectedAXObject,
557 std::unique_ptr<protocol::Array<AXNode>>& nodes,
558 AXObjectCacheImpl& cache) const {
559 AccessibilityRole role = axObject.roleValue();
420 std::unique_ptr<AXNode> nodeObject = 560 std::unique_ptr<AXNode> nodeObject =
421 AXNode::create() 561 AXNode::create()
422 .setNodeId(String::number(axObject->axObjectID())) 562 .setNodeId(String::number(axObject.axObjectID()))
423 .setIgnored(false) 563 .setIgnored(false)
424 .build(); 564 .build();
425 nodeObject->setRole(createRoleNameValue(role)); 565 nodeObject->setRole(createRoleNameValue(role));
426 566
427 std::unique_ptr<protocol::Array<AXProperty>> properties = 567 std::unique_ptr<protocol::Array<AXProperty>> properties =
428 protocol::Array<AXProperty>::create(); 568 protocol::Array<AXProperty>::create();
429 fillLiveRegionProperties(axObject, properties.get()); 569 fillLiveRegionProperties(axObject, *(properties.get()));
430 fillGlobalStates(axObject, properties.get()); 570 fillGlobalStates(axObject, *(properties.get()));
431 fillWidgetProperties(axObject, properties.get()); 571 fillWidgetProperties(axObject, *(properties.get()));
432 fillWidgetStates(axObject, properties.get()); 572 fillWidgetStates(axObject, *(properties.get()));
433 fillRelationships(axObject, properties.get()); 573 fillRelationships(axObject, *(properties.get()));
434 574
435 AXObject::NameSources nameSources; 575 AXObject::NameSources nameSources;
436 String computedName = axObject->name(&nameSources); 576 String computedName = axObject.name(&nameSources);
437 if (!nameSources.isEmpty()) { 577 if (!nameSources.isEmpty()) {
438 std::unique_ptr<AXValue> name = 578 std::unique_ptr<AXValue> name =
439 createValue(computedName, AXValueTypeEnum::ComputedString); 579 createValue(computedName, AXValueTypeEnum::ComputedString);
440 if (!nameSources.isEmpty()) { 580 if (!nameSources.isEmpty()) {
441 std::unique_ptr<protocol::Array<AXValueSource>> nameSourceProperties = 581 std::unique_ptr<protocol::Array<AXValueSource>> nameSourceProperties =
442 protocol::Array<AXValueSource>::create(); 582 protocol::Array<AXValueSource>::create();
443 for (size_t i = 0; i < nameSources.size(); ++i) { 583 for (size_t i = 0; i < nameSources.size(); ++i) {
444 NameSource& nameSource = nameSources[i]; 584 NameSource& nameSource = nameSources[i];
445 nameSourceProperties->addItem(createValueSource(nameSource)); 585 nameSourceProperties->addItem(createValueSource(nameSource));
446 if (nameSource.text.isNull() || nameSource.superseded) 586 if (nameSource.text.isNull() || nameSource.superseded)
447 continue; 587 continue;
448 if (!nameSource.relatedObjects.isEmpty()) { 588 if (!nameSource.relatedObjects.isEmpty()) {
449 properties->addItem(createRelatedNodeListProperty( 589 properties->addItem(createRelatedNodeListProperty(
450 AXRelationshipAttributesEnum::Labelledby, 590 AXRelationshipAttributesEnum::Labelledby,
451 nameSource.relatedObjects)); 591 nameSource.relatedObjects));
452 } 592 }
453 } 593 }
454 name->setSources(std::move(nameSourceProperties)); 594 name->setSources(std::move(nameSourceProperties));
455 } 595 }
456 nodeObject->setProperties(std::move(properties)); 596 nodeObject->setProperties(std::move(properties));
457 nodeObject->setName(std::move(name)); 597 nodeObject->setName(std::move(name));
458 } else { 598 } else {
459 nodeObject->setProperties(std::move(properties)); 599 nodeObject->setProperties(std::move(properties));
460 } 600 }
461 601
462 fillCoreProperties(axObject, nodeObject.get()); 602 fillCoreProperties(axObject, inspectedAXObject, *(nodeObject.get()), nodes,
603 cache);
463 return nodeObject; 604 return nodeObject;
464 } 605 }
465 606
466 } // namespace 607 void InspectorAccessibilityAgent::fillCoreProperties(
608 AXObject& axObject,
609 AXObject* inspectedAXObject,
610 AXNode& nodeObject,
611 std::unique_ptr<protocol::Array<AXNode>>& nodes,
612 AXObjectCacheImpl& cache) const {
613 AXNameFrom nameFrom;
614 AXObject::AXObjectVector nameObjects;
615 axObject.name(nameFrom, &nameObjects);
467 616
468 InspectorAccessibilityAgent::InspectorAccessibilityAgent( 617 AXDescriptionFrom descriptionFrom;
469 Page* page, 618 AXObject::AXObjectVector descriptionObjects;
470 InspectorDOMAgent* domAgent) 619 String description =
471 : m_page(page), m_domAgent(domAgent) {} 620 axObject.description(nameFrom, descriptionFrom, &descriptionObjects);
621 if (!description.isEmpty()) {
622 nodeObject.setDescription(
623 createValue(description, AXValueTypeEnum::ComputedString));
624 }
625 // Value.
626 if (axObject.supportsRangeValue()) {
627 nodeObject.setValue(createValue(axObject.valueForRange()));
628 } else {
629 String stringValue = axObject.stringValue();
630 if (!stringValue.isEmpty())
631 nodeObject.setValue(createValue(stringValue));
632 }
472 633
473 void InspectorAccessibilityAgent::getAXNodeChain( 634 populateRelatives(axObject, inspectedAXObject, nodeObject, nodes, cache);
474 ErrorString* errorString, 635
475 int domNodeId, 636 Node* node = axObject.getNode();
476 bool fetchAncestors, 637 if (node)
477 std::unique_ptr<protocol::Array<protocol::Accessibility::AXNode>>* nodes) { 638 nodeObject.setDomNodeId(DOMNodeIds::idForNode(node));
478 if (!m_domAgent->enabled()) { 639 }
479 *errorString = "DOM agent must be enabled"; 640
641 void InspectorAccessibilityAgent::populateRelatives(
642 AXObject& axObject,
643 AXObject* inspectedAXObject,
644 AXNode& nodeObject,
645 std::unique_ptr<protocol::Array<AXNode>>& nodes,
646 AXObjectCacheImpl& cache) const {
647 AXObject* parentObject = axObject.parentObject();
648 if (parentObject && parentObject != inspectedAXObject) {
649 // Use unignored parent unless parent is inspected ignored object.
650 parentObject = axObject.parentObjectUnignored();
651 }
652 if (parentObject)
653 nodeObject.setParentId(String::number(parentObject->axObjectID()));
654
655 std::unique_ptr<protocol::Array<AXNodeId>> childIds =
656 protocol::Array<AXNodeId>::create();
657 if (!inspectedAXObject) {
658 // If there is no AXObject for the inspected node, the caller will populate
659 // its relatives.
480 return; 660 return;
481 } 661 }
482 Node* node = m_domAgent->assertNode(errorString, domNodeId); 662
483 if (!node) 663 if (&axObject == inspectedAXObject->parentObjectUnignored() &&
664 inspectedAXObject->accessibilityIsIgnored()) {
665 // This is the parent of an ignored object, so search for its siblings.
666 addSiblingsOfIgnored(childIds, axObject, inspectedAXObject, nodes, cache);
667 } else {
668 addChildren(axObject, *inspectedAXObject, childIds, nodes, cache);
669 }
670 nodeObject.setChildIds(std::move(childIds));
671 }
672
673 void InspectorAccessibilityAgent::addSiblingsOfIgnored(
674 std::unique_ptr<protocol::Array<AXNodeId>>& childIds,
675 AXObject& parentAXObject,
676 AXObject* inspectedAXObject,
677 std::unique_ptr<protocol::Array<AXNode>>& nodes,
678 AXObjectCacheImpl& cache) const {
679 for (AXObject* childAXObject = parentAXObject.rawFirstChild(); childAXObject;
680 childAXObject = childAXObject->rawNextSibling()) {
681 if (childAXObject != inspectedAXObject &&
682 childAXObject->accessibilityIsIgnored()) {
683 if (isAncestorOf(childAXObject, inspectedAXObject)) {
684 addSiblingsOfIgnored(childIds, *childAXObject, inspectedAXObject, nodes,
685 cache);
686 continue;
687 }
688 const AXObject::AXObjectVector& indirectChildren =
689 childAXObject->children();
690 for (unsigned i = 0; i < indirectChildren.size(); ++i) {
691 addChild(childIds, *(indirectChildren[i]), inspectedAXObject, nodes,
692 cache);
693 }
694 continue;
695 }
696 addChild(childIds, *childAXObject, inspectedAXObject, nodes, cache);
697 }
698 }
699
700 void InspectorAccessibilityAgent::addChild(
701 std::unique_ptr<protocol::Array<AXNodeId>>& childIds,
702 AXObject& childAXObject,
703 AXObject* inspectedAXObject,
704 std::unique_ptr<protocol::Array<AXNode>>& nodes,
705 AXObjectCacheImpl& cache) const {
706 childIds->addItem(String::number(childAXObject.axObjectID()));
707 if (&childAXObject == inspectedAXObject)
484 return; 708 return;
709 nodes->addItem(
710 buildProtocolAXObject(childAXObject, inspectedAXObject, nodes, cache));
711 }
485 712
486 Document& document = node->document(); 713 void InspectorAccessibilityAgent::addChildren(
487 document.updateStyleAndLayoutIgnorePendingStylesheets(); 714 AXObject& axObject,
488 DocumentLifecycle::DisallowTransitionScope disallowTransition( 715 AXObject& inspectedAXObject,
489 document.lifecycle()); 716 std::unique_ptr<protocol::Array<AXNodeId>>& childIds,
490 LocalFrame* localFrame = document.frame(); 717 std::unique_ptr<protocol::Array<AXNode>>& nodes,
491 if (!localFrame) { 718 AXObjectCacheImpl& cache) const {
492 *errorString = "Frame is detached."; 719 const AXObject::AXObjectVector& children = axObject.children();
493 return; 720 for (unsigned i = 0; i < children.size(); i++) {
494 } 721 AXObject& childAXObject = *children[i].get();
495 std::unique_ptr<ScopedAXObjectCache> scopedCache = 722 childIds->addItem(String::number(childAXObject.axObjectID()));
496 ScopedAXObjectCache::create(document); 723 if (&axObject == &inspectedAXObject ||
497 AXObjectCacheImpl* cache = toAXObjectCacheImpl(scopedCache->get()); 724 &axObject == inspectedAXObject.parentObjectUnignored()) {
498 AXObject* axObject = cache->getOrCreate(node); 725 // Only add children/siblings of inspected node to returned nodes.
499 *nodes = protocol::Array<protocol::Accessibility::AXNode>::create(); 726 nodes->addItem(buildProtocolAXObject(childAXObject, &inspectedAXObject,
500 if (!axObject || axObject->accessibilityIsIgnored()) { 727 nodes, cache));
501 (*nodes)->addItem(buildObjectForIgnoredNode(node, axObject));
502 } else {
503 (*nodes)->addItem(buildProtocolAXObject(axObject));
504 }
505
506 if (fetchAncestors && axObject) {
507 AXObject* parent = axObject->parentObjectUnignored();
508 while (parent) {
509 (*nodes)->addItem(buildProtocolAXObject(parent));
510 parent = parent->parentObjectUnignored();
511 } 728 }
512 } 729 }
513 } 730 }
514 731
515 DEFINE_TRACE(InspectorAccessibilityAgent) { 732 DEFINE_TRACE(InspectorAccessibilityAgent) {
516 visitor->trace(m_page); 733 visitor->trace(m_page);
517 visitor->trace(m_domAgent); 734 visitor->trace(m_domAgent);
518 InspectorBaseAgent::trace(visitor); 735 InspectorBaseAgent::trace(visitor);
519 } 736 }
520 737
521 } // namespace blink 738 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698