OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012, Google Inc. All rights reserved. | 2 * Copyright (C) 2012, Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 #include "platform/wtf/text/StringBuilder.h" | 73 #include "platform/wtf/text/StringBuilder.h" |
74 | 74 |
75 namespace blink { | 75 namespace blink { |
76 | 76 |
77 using namespace HTMLNames; | 77 using namespace HTMLNames; |
78 | 78 |
79 class SparseAttributeSetter { | 79 class SparseAttributeSetter { |
80 USING_FAST_MALLOC(SparseAttributeSetter); | 80 USING_FAST_MALLOC(SparseAttributeSetter); |
81 | 81 |
82 public: | 82 public: |
83 virtual void Run(const AXObjectImpl&, | 83 virtual void Run(const AXObject&, |
84 AXSparseAttributeClient&, | 84 AXSparseAttributeClient&, |
85 const AtomicString& value) = 0; | 85 const AtomicString& value) = 0; |
86 }; | 86 }; |
87 | 87 |
88 class BoolAttributeSetter : public SparseAttributeSetter { | 88 class BoolAttributeSetter : public SparseAttributeSetter { |
89 public: | 89 public: |
90 BoolAttributeSetter(AXBoolAttribute attribute) : attribute_(attribute) {} | 90 BoolAttributeSetter(AXBoolAttribute attribute) : attribute_(attribute) {} |
91 | 91 |
92 private: | 92 private: |
93 AXBoolAttribute attribute_; | 93 AXBoolAttribute attribute_; |
94 | 94 |
95 void Run(const AXObjectImpl& obj, | 95 void Run(const AXObject& obj, |
96 AXSparseAttributeClient& attribute_map, | 96 AXSparseAttributeClient& attribute_map, |
97 const AtomicString& value) override { | 97 const AtomicString& value) override { |
98 attribute_map.AddBoolAttribute(attribute_, | 98 attribute_map.AddBoolAttribute(attribute_, |
99 EqualIgnoringASCIICase(value, "true")); | 99 EqualIgnoringASCIICase(value, "true")); |
100 } | 100 } |
101 }; | 101 }; |
102 | 102 |
103 class StringAttributeSetter : public SparseAttributeSetter { | 103 class StringAttributeSetter : public SparseAttributeSetter { |
104 public: | 104 public: |
105 StringAttributeSetter(AXStringAttribute attribute) : attribute_(attribute) {} | 105 StringAttributeSetter(AXStringAttribute attribute) : attribute_(attribute) {} |
106 | 106 |
107 private: | 107 private: |
108 AXStringAttribute attribute_; | 108 AXStringAttribute attribute_; |
109 | 109 |
110 void Run(const AXObjectImpl& obj, | 110 void Run(const AXObject& obj, |
111 AXSparseAttributeClient& attribute_map, | 111 AXSparseAttributeClient& attribute_map, |
112 const AtomicString& value) override { | 112 const AtomicString& value) override { |
113 attribute_map.AddStringAttribute(attribute_, value); | 113 attribute_map.AddStringAttribute(attribute_, value); |
114 } | 114 } |
115 }; | 115 }; |
116 | 116 |
117 class ObjectAttributeSetter : public SparseAttributeSetter { | 117 class ObjectAttributeSetter : public SparseAttributeSetter { |
118 public: | 118 public: |
119 ObjectAttributeSetter(AXObjectAttribute attribute) : attribute_(attribute) {} | 119 ObjectAttributeSetter(AXObjectAttribute attribute) : attribute_(attribute) {} |
120 | 120 |
121 private: | 121 private: |
122 AXObjectAttribute attribute_; | 122 AXObjectAttribute attribute_; |
123 | 123 |
124 void Run(const AXObjectImpl& obj, | 124 void Run(const AXObject& obj, |
125 AXSparseAttributeClient& attribute_map, | 125 AXSparseAttributeClient& attribute_map, |
126 const AtomicString& value) override { | 126 const AtomicString& value) override { |
127 if (value.IsNull() || value.IsEmpty()) | 127 if (value.IsNull() || value.IsEmpty()) |
128 return; | 128 return; |
129 | 129 |
130 Node* node = obj.GetNode(); | 130 Node* node = obj.GetNode(); |
131 if (!node || !node->IsElementNode()) | 131 if (!node || !node->IsElementNode()) |
132 return; | 132 return; |
133 Element* target = ToElement(node)->GetTreeScope().getElementById(value); | 133 Element* target = ToElement(node)->GetTreeScope().getElementById(value); |
134 if (!target) | 134 if (!target) |
135 return; | 135 return; |
136 AXObjectImpl* ax_target = obj.AxObjectCache().GetOrCreate(target); | 136 AXObject* ax_target = obj.AxObjectCache().GetOrCreate(target); |
137 if (ax_target) | 137 if (ax_target) |
138 attribute_map.AddObjectAttribute(attribute_, *ax_target); | 138 attribute_map.AddObjectAttribute(attribute_, *ax_target); |
139 } | 139 } |
140 }; | 140 }; |
141 | 141 |
142 class ObjectVectorAttributeSetter : public SparseAttributeSetter { | 142 class ObjectVectorAttributeSetter : public SparseAttributeSetter { |
143 public: | 143 public: |
144 ObjectVectorAttributeSetter(AXObjectVectorAttribute attribute) | 144 ObjectVectorAttributeSetter(AXObjectVectorAttribute attribute) |
145 : attribute_(attribute) {} | 145 : attribute_(attribute) {} |
146 | 146 |
147 private: | 147 private: |
148 AXObjectVectorAttribute attribute_; | 148 AXObjectVectorAttribute attribute_; |
149 | 149 |
150 void Run(const AXObjectImpl& obj, | 150 void Run(const AXObject& obj, |
151 AXSparseAttributeClient& attribute_map, | 151 AXSparseAttributeClient& attribute_map, |
152 const AtomicString& value) override { | 152 const AtomicString& value) override { |
153 Node* node = obj.GetNode(); | 153 Node* node = obj.GetNode(); |
154 if (!node || !node->IsElementNode()) | 154 if (!node || !node->IsElementNode()) |
155 return; | 155 return; |
156 | 156 |
157 String attribute_value = value.GetString(); | 157 String attribute_value = value.GetString(); |
158 if (attribute_value.IsEmpty()) | 158 if (attribute_value.IsEmpty()) |
159 return; | 159 return; |
160 | 160 |
161 attribute_value.SimplifyWhiteSpace(); | 161 attribute_value.SimplifyWhiteSpace(); |
162 Vector<String> ids; | 162 Vector<String> ids; |
163 attribute_value.Split(' ', ids); | 163 attribute_value.Split(' ', ids); |
164 if (ids.IsEmpty()) | 164 if (ids.IsEmpty()) |
165 return; | 165 return; |
166 | 166 |
167 HeapVector<Member<AXObjectImpl>> objects; | 167 HeapVector<Member<AXObject>> objects; |
168 TreeScope& scope = node->GetTreeScope(); | 168 TreeScope& scope = node->GetTreeScope(); |
169 for (const auto& id : ids) { | 169 for (const auto& id : ids) { |
170 if (Element* id_element = scope.getElementById(AtomicString(id))) { | 170 if (Element* id_element = scope.getElementById(AtomicString(id))) { |
171 AXObjectImpl* ax_id_element = | 171 AXObject* ax_id_element = obj.AxObjectCache().GetOrCreate(id_element); |
172 obj.AxObjectCache().GetOrCreate(id_element); | |
173 if (ax_id_element && !ax_id_element->AccessibilityIsIgnored()) | 172 if (ax_id_element && !ax_id_element->AccessibilityIsIgnored()) |
174 objects.push_back(ax_id_element); | 173 objects.push_back(ax_id_element); |
175 } | 174 } |
176 } | 175 } |
177 | 176 |
178 attribute_map.AddObjectVectorAttribute(attribute_, objects); | 177 attribute_map.AddObjectVectorAttribute(attribute_, objects); |
179 } | 178 } |
180 }; | 179 }; |
181 | 180 |
182 using AXSparseAttributeSetterMap = | 181 using AXSparseAttributeSetterMap = |
(...skipping 26 matching lines...) Expand all Loading... |
209 aria_keyshortcutsAttr, | 208 aria_keyshortcutsAttr, |
210 new StringAttributeSetter(AXStringAttribute::kAriaKeyShortcuts)); | 209 new StringAttributeSetter(AXStringAttribute::kAriaKeyShortcuts)); |
211 ax_sparse_attribute_setter_map.Set( | 210 ax_sparse_attribute_setter_map.Set( |
212 aria_roledescriptionAttr, | 211 aria_roledescriptionAttr, |
213 new StringAttributeSetter(AXStringAttribute::kAriaRoleDescription)); | 212 new StringAttributeSetter(AXStringAttribute::kAriaRoleDescription)); |
214 } | 213 } |
215 return ax_sparse_attribute_setter_map; | 214 return ax_sparse_attribute_setter_map; |
216 } | 215 } |
217 | 216 |
218 AXNodeObject::AXNodeObject(Node* node, AXObjectCacheImpl& ax_object_cache) | 217 AXNodeObject::AXNodeObject(Node* node, AXObjectCacheImpl& ax_object_cache) |
219 : AXObjectImpl(ax_object_cache), | 218 : AXObject(ax_object_cache), |
220 aria_role_(kUnknownRole), | 219 aria_role_(kUnknownRole), |
221 children_dirty_(false), | 220 children_dirty_(false), |
222 node_(node) {} | 221 node_(node) {} |
223 | 222 |
224 AXNodeObject* AXNodeObject::Create(Node* node, | 223 AXNodeObject* AXNodeObject::Create(Node* node, |
225 AXObjectCacheImpl& ax_object_cache) { | 224 AXObjectCacheImpl& ax_object_cache) { |
226 return new AXNodeObject(node, ax_object_cache); | 225 return new AXNodeObject(node, ax_object_cache); |
227 } | 226 } |
228 | 227 |
229 AXNodeObject::~AXNodeObject() { | 228 AXNodeObject::~AXNodeObject() { |
230 DCHECK(!node_); | 229 DCHECK(!node_); |
231 } | 230 } |
232 | 231 |
233 void AXNodeObject::AlterSliderValue(bool increase) { | 232 void AXNodeObject::AlterSliderValue(bool increase) { |
234 if (RoleValue() != kSliderRole) | 233 if (RoleValue() != kSliderRole) |
235 return; | 234 return; |
236 | 235 |
237 float value = ValueForRange(); | 236 float value = ValueForRange(); |
238 float step = StepValueForRange(); | 237 float step = StepValueForRange(); |
239 | 238 |
240 value += increase ? step : -step; | 239 value += increase ? step : -step; |
241 | 240 |
242 SetValue(String::Number(value)); | 241 SetValue(String::Number(value)); |
243 AxObjectCache().PostNotification(GetNode(), | 242 AxObjectCache().PostNotification(GetNode(), |
244 AXObjectCacheImpl::kAXValueChanged); | 243 AXObjectCacheImpl::kAXValueChanged); |
245 } | 244 } |
246 | 245 |
247 AXObjectImpl* AXNodeObject::ActiveDescendant() { | 246 AXObject* AXNodeObject::ActiveDescendant() { |
248 if (!node_ || !node_->IsElementNode()) | 247 if (!node_ || !node_->IsElementNode()) |
249 return nullptr; | 248 return nullptr; |
250 | 249 |
251 const AtomicString& active_descendant_attr = | 250 const AtomicString& active_descendant_attr = |
252 GetAttribute(aria_activedescendantAttr); | 251 GetAttribute(aria_activedescendantAttr); |
253 if (active_descendant_attr.IsNull() || active_descendant_attr.IsEmpty()) | 252 if (active_descendant_attr.IsNull() || active_descendant_attr.IsEmpty()) |
254 return nullptr; | 253 return nullptr; |
255 | 254 |
256 Element* element = ToElement(GetNode()); | 255 Element* element = ToElement(GetNode()); |
257 Element* descendant = | 256 Element* descendant = |
258 element->GetTreeScope().getElementById(active_descendant_attr); | 257 element->GetTreeScope().getElementById(active_descendant_attr); |
259 if (!descendant) | 258 if (!descendant) |
260 return nullptr; | 259 return nullptr; |
261 | 260 |
262 AXObjectImpl* ax_descendant = AxObjectCache().GetOrCreate(descendant); | 261 AXObject* ax_descendant = AxObjectCache().GetOrCreate(descendant); |
263 return ax_descendant; | 262 return ax_descendant; |
264 } | 263 } |
265 | 264 |
266 bool AXNodeObject::ComputeAccessibilityIsIgnored( | 265 bool AXNodeObject::ComputeAccessibilityIsIgnored( |
267 IgnoredReasons* ignored_reasons) const { | 266 IgnoredReasons* ignored_reasons) const { |
268 #if DCHECK_IS_ON() | 267 #if DCHECK_IS_ON() |
269 // Double-check that an AXObjectImpl is never accessed before | 268 // Double-check that an AXObject is never accessed before |
270 // it's been initialized. | 269 // it's been initialized. |
271 DCHECK(initialized_); | 270 DCHECK(initialized_); |
272 #endif | 271 #endif |
273 | 272 |
274 // If this element is within a parent that cannot have children, it should not | 273 // If this element is within a parent that cannot have children, it should not |
275 // be exposed. | 274 // be exposed. |
276 if (IsDescendantOfLeafNode()) { | 275 if (IsDescendantOfLeafNode()) { |
277 if (ignored_reasons) | 276 if (ignored_reasons) |
278 ignored_reasons->push_back( | 277 ignored_reasons->push_back( |
279 IgnoredReason(kAXAncestorIsLeafNode, LeafNodeAncestor())); | 278 IgnoredReason(kAXAncestorIsLeafNode, LeafNodeAncestor())); |
280 return true; | 279 return true; |
281 } | 280 } |
282 | 281 |
283 // Ignore labels that are already referenced by a control. | 282 // Ignore labels that are already referenced by a control. |
284 AXObjectImpl* control_object = CorrespondingControlForLabelElement(); | 283 AXObject* control_object = CorrespondingControlForLabelElement(); |
285 if (control_object && control_object->IsCheckboxOrRadio() && | 284 if (control_object && control_object->IsCheckboxOrRadio() && |
286 control_object->NameFromLabelElement()) { | 285 control_object->NameFromLabelElement()) { |
287 if (ignored_reasons) { | 286 if (ignored_reasons) { |
288 HTMLLabelElement* label = LabelElementContainer(); | 287 HTMLLabelElement* label = LabelElementContainer(); |
289 if (label && label != GetNode()) { | 288 if (label && label != GetNode()) { |
290 AXObjectImpl* label_ax_object = AxObjectCache().GetOrCreate(label); | 289 AXObject* label_ax_object = AxObjectCache().GetOrCreate(label); |
291 ignored_reasons->push_back( | 290 ignored_reasons->push_back( |
292 IgnoredReason(kAXLabelContainer, label_ax_object)); | 291 IgnoredReason(kAXLabelContainer, label_ax_object)); |
293 } | 292 } |
294 | 293 |
295 ignored_reasons->push_back(IgnoredReason(kAXLabelFor, control_object)); | 294 ignored_reasons->push_back(IgnoredReason(kAXLabelFor, control_object)); |
296 } | 295 } |
297 return true; | 296 return true; |
298 } | 297 } |
299 | 298 |
300 Element* element = GetNode()->IsElementNode() ? ToElement(GetNode()) | 299 Element* element = GetNode()->IsElementNode() ? ToElement(GetNode()) |
(...skipping 11 matching lines...) Expand all Loading... |
312 return true; | 311 return true; |
313 } | 312 } |
314 return false; | 313 return false; |
315 } | 314 } |
316 | 315 |
317 static bool IsListElement(Node* node) { | 316 static bool IsListElement(Node* node) { |
318 return isHTMLUListElement(*node) || isHTMLOListElement(*node) || | 317 return isHTMLUListElement(*node) || isHTMLOListElement(*node) || |
319 isHTMLDListElement(*node); | 318 isHTMLDListElement(*node); |
320 } | 319 } |
321 | 320 |
322 static bool IsPresentationalInTable(AXObjectImpl* parent, | 321 static bool IsPresentationalInTable(AXObject* parent, |
323 HTMLElement* current_element) { | 322 HTMLElement* current_element) { |
324 if (!current_element) | 323 if (!current_element) |
325 return false; | 324 return false; |
326 | 325 |
327 Node* parent_node = parent->GetNode(); | 326 Node* parent_node = parent->GetNode(); |
328 if (!parent_node || !parent_node->IsHTMLElement()) | 327 if (!parent_node || !parent_node->IsHTMLElement()) |
329 return false; | 328 return false; |
330 | 329 |
331 // AXTable determines the role as checking isTableXXX. | 330 // AXTable determines the role as checking isTableXXX. |
332 // If Table has explicit role including presentation, AXTable doesn't assign | 331 // If Table has explicit role including presentation, AXTable doesn't assign |
333 // implicit Role to a whole Table. That's why we should check it based on | 332 // implicit Role to a whole Table. That's why we should check it based on |
334 // node. | 333 // node. |
335 // Normal Table Tree is that | 334 // Normal Table Tree is that |
336 // cell(its role)-> tr(tr role)-> tfoot, tbody, thead(ignored role) -> | 335 // cell(its role)-> tr(tr role)-> tfoot, tbody, thead(ignored role) -> |
337 // table(table role). | 336 // table(table role). |
338 // If table has presentation role, it will be like | 337 // If table has presentation role, it will be like |
339 // cell(group)-> tr(unknown) -> tfoot, tbody, thead(ignored) -> | 338 // cell(group)-> tr(unknown) -> tfoot, tbody, thead(ignored) -> |
340 // table(presentation). | 339 // table(presentation). |
341 if (IsHTMLTableCellElement(*current_element) && | 340 if (IsHTMLTableCellElement(*current_element) && |
342 isHTMLTableRowElement(*parent_node)) | 341 isHTMLTableRowElement(*parent_node)) |
343 return parent->HasInheritedPresentationalRole(); | 342 return parent->HasInheritedPresentationalRole(); |
344 | 343 |
345 if (isHTMLTableRowElement(*current_element) && | 344 if (isHTMLTableRowElement(*current_element) && |
346 IsHTMLTableSectionElement(ToHTMLElement(*parent_node))) { | 345 IsHTMLTableSectionElement(ToHTMLElement(*parent_node))) { |
347 // Because TableSections have ignored role, presentation should be checked | 346 // Because TableSections have ignored role, presentation should be checked |
348 // with its parent node. | 347 // with its parent node. |
349 AXObjectImpl* table_object = parent->ParentObject(); | 348 AXObject* table_object = parent->ParentObject(); |
350 Node* table_node = table_object ? table_object->GetNode() : 0; | 349 Node* table_node = table_object ? table_object->GetNode() : 0; |
351 return isHTMLTableElement(table_node) && | 350 return isHTMLTableElement(table_node) && |
352 table_object->HasInheritedPresentationalRole(); | 351 table_object->HasInheritedPresentationalRole(); |
353 } | 352 } |
354 return false; | 353 return false; |
355 } | 354 } |
356 | 355 |
357 static bool IsRequiredOwnedElement(AXObjectImpl* parent, | 356 static bool IsRequiredOwnedElement(AXObject* parent, |
358 AccessibilityRole current_role, | 357 AccessibilityRole current_role, |
359 HTMLElement* current_element) { | 358 HTMLElement* current_element) { |
360 Node* parent_node = parent->GetNode(); | 359 Node* parent_node = parent->GetNode(); |
361 if (!parent_node || !parent_node->IsHTMLElement()) | 360 if (!parent_node || !parent_node->IsHTMLElement()) |
362 return false; | 361 return false; |
363 | 362 |
364 if (current_role == kListItemRole) | 363 if (current_role == kListItemRole) |
365 return IsListElement(parent_node); | 364 return IsListElement(parent_node); |
366 if (current_role == kListMarkerRole) | 365 if (current_role == kListMarkerRole) |
367 return isHTMLLIElement(*parent_node); | 366 return isHTMLLIElement(*parent_node); |
368 if (current_role == kMenuItemCheckBoxRole || current_role == kMenuItemRole || | 367 if (current_role == kMenuItemCheckBoxRole || current_role == kMenuItemRole || |
369 current_role == kMenuItemRadioRole) | 368 current_role == kMenuItemRadioRole) |
370 return isHTMLMenuElement(*parent_node); | 369 return isHTMLMenuElement(*parent_node); |
371 | 370 |
372 if (!current_element) | 371 if (!current_element) |
373 return false; | 372 return false; |
374 if (IsHTMLTableCellElement(*current_element)) | 373 if (IsHTMLTableCellElement(*current_element)) |
375 return isHTMLTableRowElement(*parent_node); | 374 return isHTMLTableRowElement(*parent_node); |
376 if (isHTMLTableRowElement(*current_element)) | 375 if (isHTMLTableRowElement(*current_element)) |
377 return IsHTMLTableSectionElement(ToHTMLElement(*parent_node)); | 376 return IsHTMLTableSectionElement(ToHTMLElement(*parent_node)); |
378 | 377 |
379 // In case of ListboxRole and its child, ListBoxOptionRole, inheritance of | 378 // In case of ListboxRole and its child, ListBoxOptionRole, inheritance of |
380 // presentation role is handled in AXListBoxOption because ListBoxOption Role | 379 // presentation role is handled in AXListBoxOption because ListBoxOption Role |
381 // doesn't have any child. | 380 // doesn't have any child. |
382 // If it's just ignored because of presentation, we can't see any AX tree | 381 // If it's just ignored because of presentation, we can't see any AX tree |
383 // related to ListBoxOption. | 382 // related to ListBoxOption. |
384 return false; | 383 return false; |
385 } | 384 } |
386 | 385 |
387 const AXObjectImpl* AXNodeObject::InheritsPresentationalRoleFrom() const { | 386 const AXObject* AXNodeObject::InheritsPresentationalRoleFrom() const { |
388 // ARIA states if an item can get focus, it should not be presentational. | 387 // ARIA states if an item can get focus, it should not be presentational. |
389 if (CanSetFocusAttribute()) | 388 if (CanSetFocusAttribute()) |
390 return 0; | 389 return 0; |
391 | 390 |
392 if (IsPresentational()) | 391 if (IsPresentational()) |
393 return this; | 392 return this; |
394 | 393 |
395 // http://www.w3.org/TR/wai-aria/complete#presentation | 394 // http://www.w3.org/TR/wai-aria/complete#presentation |
396 // ARIA spec says that the user agent MUST apply an inherited role of | 395 // ARIA spec says that the user agent MUST apply an inherited role of |
397 // presentation | 396 // presentation |
398 // to any owned elements that do not have an explicit role defined. | 397 // to any owned elements that do not have an explicit role defined. |
399 if (AriaRoleAttribute() != kUnknownRole) | 398 if (AriaRoleAttribute() != kUnknownRole) |
400 return 0; | 399 return 0; |
401 | 400 |
402 AXObjectImpl* parent = ParentObject(); | 401 AXObject* parent = ParentObject(); |
403 if (!parent) | 402 if (!parent) |
404 return 0; | 403 return 0; |
405 | 404 |
406 HTMLElement* element = nullptr; | 405 HTMLElement* element = nullptr; |
407 if (GetNode() && GetNode()->IsHTMLElement()) | 406 if (GetNode() && GetNode()->IsHTMLElement()) |
408 element = ToHTMLElement(GetNode()); | 407 element = ToHTMLElement(GetNode()); |
409 if (!parent->HasInheritedPresentationalRole()) { | 408 if (!parent->HasInheritedPresentationalRole()) { |
410 if (!GetLayoutObject() || !GetLayoutObject()->IsBoxModelObject()) | 409 if (!GetLayoutObject() || !GetLayoutObject()->IsBoxModelObject()) |
411 return 0; | 410 return 0; |
412 | 411 |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 role = RemapAriaRoleDueToParent(role); | 716 role = RemapAriaRoleDueToParent(role); |
718 | 717 |
719 if (role) | 718 if (role) |
720 return role; | 719 return role; |
721 | 720 |
722 return kUnknownRole; | 721 return kUnknownRole; |
723 } | 722 } |
724 | 723 |
725 void AXNodeObject::AccessibilityChildrenFromAttribute( | 724 void AXNodeObject::AccessibilityChildrenFromAttribute( |
726 QualifiedName attr, | 725 QualifiedName attr, |
727 AXObjectImpl::AXObjectVector& children) const { | 726 AXObject::AXObjectVector& children) const { |
728 HeapVector<Member<Element>> elements; | 727 HeapVector<Member<Element>> elements; |
729 ElementsFromAttribute(elements, attr); | 728 ElementsFromAttribute(elements, attr); |
730 | 729 |
731 AXObjectCacheImpl& cache = AxObjectCache(); | 730 AXObjectCacheImpl& cache = AxObjectCache(); |
732 for (const auto& element : elements) { | 731 for (const auto& element : elements) { |
733 if (AXObjectImpl* child = cache.GetOrCreate(element)) { | 732 if (AXObject* child = cache.GetOrCreate(element)) { |
734 // Only aria-labelledby and aria-describedby can target hidden elements. | 733 // Only aria-labelledby and aria-describedby can target hidden elements. |
735 if (child->AccessibilityIsIgnored() && attr != aria_labelledbyAttr && | 734 if (child->AccessibilityIsIgnored() && attr != aria_labelledbyAttr && |
736 attr != aria_labeledbyAttr && attr != aria_describedbyAttr) { | 735 attr != aria_labeledbyAttr && attr != aria_describedbyAttr) { |
737 continue; | 736 continue; |
738 } | 737 } |
739 children.push_back(child); | 738 children.push_back(child); |
740 } | 739 } |
741 } | 740 } |
742 } | 741 } |
743 | 742 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 | 796 |
798 // An SVG root is focusable by default, but it's probably not interactive, so | 797 // An SVG root is focusable by default, but it's probably not interactive, so |
799 // don't include it. It can still be made accessible by giving it an ARIA | 798 // don't include it. It can still be made accessible by giving it an ARIA |
800 // role. | 799 // role. |
801 if (RoleValue() == kSVGRootRole) | 800 if (RoleValue() == kSVGRootRole) |
802 return false; | 801 return false; |
803 | 802 |
804 return true; | 803 return true; |
805 } | 804 } |
806 | 805 |
807 AXObjectImpl* AXNodeObject::MenuButtonForMenu() const { | 806 AXObject* AXNodeObject::MenuButtonForMenu() const { |
808 Element* menu_item = MenuItemElementForMenu(); | 807 Element* menu_item = MenuItemElementForMenu(); |
809 | 808 |
810 if (menu_item) { | 809 if (menu_item) { |
811 // ARIA just has generic menu items. AppKit needs to know if this is a top | 810 // ARIA just has generic menu items. AppKit needs to know if this is a top |
812 // level items like MenuBarButton or MenuBarItem | 811 // level items like MenuBarButton or MenuBarItem |
813 AXObjectImpl* menu_item_ax = AxObjectCache().GetOrCreate(menu_item); | 812 AXObject* menu_item_ax = AxObjectCache().GetOrCreate(menu_item); |
814 if (menu_item_ax && menu_item_ax->IsMenuButton()) | 813 if (menu_item_ax && menu_item_ax->IsMenuButton()) |
815 return menu_item_ax; | 814 return menu_item_ax; |
816 } | 815 } |
817 return 0; | 816 return 0; |
818 } | 817 } |
819 | 818 |
820 static Element* SiblingWithAriaRole(String role, Node* node) { | 819 static Element* SiblingWithAriaRole(String role, Node* node) { |
821 Node* parent = node->parentNode(); | 820 Node* parent = node->parentNode(); |
822 if (!parent) | 821 if (!parent) |
823 return 0; | 822 return 0; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
873 AccessibilityRole role) const { | 872 AccessibilityRole role) const { |
874 // Some objects change their role based on their parent. | 873 // Some objects change their role based on their parent. |
875 // However, asking for the unignoredParent calls accessibilityIsIgnored(), | 874 // However, asking for the unignoredParent calls accessibilityIsIgnored(), |
876 // which can trigger a loop. While inside the call stack of creating an | 875 // which can trigger a loop. While inside the call stack of creating an |
877 // element, we need to avoid accessibilityIsIgnored(). | 876 // element, we need to avoid accessibilityIsIgnored(). |
878 // https://bugs.webkit.org/show_bug.cgi?id=65174 | 877 // https://bugs.webkit.org/show_bug.cgi?id=65174 |
879 | 878 |
880 if (role != kListBoxOptionRole && role != kMenuItemRole) | 879 if (role != kListBoxOptionRole && role != kMenuItemRole) |
881 return role; | 880 return role; |
882 | 881 |
883 for (AXObjectImpl* parent = ParentObject(); | 882 for (AXObject* parent = ParentObject(); |
884 parent && !parent->AccessibilityIsIgnored(); | 883 parent && !parent->AccessibilityIsIgnored(); |
885 parent = parent->ParentObject()) { | 884 parent = parent->ParentObject()) { |
886 AccessibilityRole parent_aria_role = parent->AriaRoleAttribute(); | 885 AccessibilityRole parent_aria_role = parent->AriaRoleAttribute(); |
887 | 886 |
888 // Selects and listboxes both have options as child roles, but they map to | 887 // Selects and listboxes both have options as child roles, but they map to |
889 // different roles within WebCore. | 888 // different roles within WebCore. |
890 if (role == kListBoxOptionRole && parent_aria_role == kMenuRole) | 889 if (role == kListBoxOptionRole && parent_aria_role == kMenuRole) |
891 return kMenuItemRole; | 890 return kMenuItemRole; |
892 // An aria "menuitem" may map to MenuButton or MenuItem depending on its | 891 // An aria "menuitem" may map to MenuButton or MenuItem depending on its |
893 // parent. | 892 // parent. |
(...skipping 11 matching lines...) Expand all Loading... |
905 | 904 |
906 void AXNodeObject::Init() { | 905 void AXNodeObject::Init() { |
907 #if DCHECK_IS_ON() | 906 #if DCHECK_IS_ON() |
908 DCHECK(!initialized_); | 907 DCHECK(!initialized_); |
909 initialized_ = true; | 908 initialized_ = true; |
910 #endif | 909 #endif |
911 role_ = DetermineAccessibilityRole(); | 910 role_ = DetermineAccessibilityRole(); |
912 } | 911 } |
913 | 912 |
914 void AXNodeObject::Detach() { | 913 void AXNodeObject::Detach() { |
915 AXObjectImpl::Detach(); | 914 AXObject::Detach(); |
916 node_ = nullptr; | 915 node_ = nullptr; |
917 } | 916 } |
918 | 917 |
919 void AXNodeObject::GetSparseAXAttributes( | 918 void AXNodeObject::GetSparseAXAttributes( |
920 AXSparseAttributeClient& sparse_attribute_client) const { | 919 AXSparseAttributeClient& sparse_attribute_client) const { |
921 Node* node = this->GetNode(); | 920 Node* node = this->GetNode(); |
922 if (!node || !node->IsElementNode()) | 921 if (!node || !node->IsElementNode()) |
923 return; | 922 return; |
924 | 923 |
925 AXSparseAttributeSetterMap& ax_sparse_attribute_setter_map = | 924 AXSparseAttributeSetterMap& ax_sparse_attribute_setter_map = |
(...skipping 27 matching lines...) Expand all Loading... |
953 bool AXNodeObject::IsAnchor() const { | 952 bool AXNodeObject::IsAnchor() const { |
954 return !IsNativeImage() && IsLink(); | 953 return !IsNativeImage() && IsLink(); |
955 } | 954 } |
956 | 955 |
957 bool AXNodeObject::IsControl() const { | 956 bool AXNodeObject::IsControl() const { |
958 Node* node = this->GetNode(); | 957 Node* node = this->GetNode(); |
959 if (!node) | 958 if (!node) |
960 return false; | 959 return false; |
961 | 960 |
962 return ((node->IsElementNode() && ToElement(node)->IsFormControlElement()) || | 961 return ((node->IsElementNode() && ToElement(node)->IsFormControlElement()) || |
963 AXObjectImpl::IsARIAControl(AriaRoleAttribute())); | 962 AXObject::IsARIAControl(AriaRoleAttribute())); |
964 } | 963 } |
965 | 964 |
966 bool AXNodeObject::IsControllingVideoElement() const { | 965 bool AXNodeObject::IsControllingVideoElement() const { |
967 Node* node = this->GetNode(); | 966 Node* node = this->GetNode(); |
968 if (!node) | 967 if (!node) |
969 return true; | 968 return true; |
970 | 969 |
971 return isHTMLVideoElement(ToParentMediaElement(node)); | 970 return isHTMLVideoElement(ToParentMediaElement(node)); |
972 } | 971 } |
973 | 972 |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1154 | 1153 |
1155 // Note: we can't call getNode()->willRespondToMouseClickEvents() because | 1154 // Note: we can't call getNode()->willRespondToMouseClickEvents() because |
1156 // that triggers a style recalc and can delete this. | 1155 // that triggers a style recalc and can delete this. |
1157 if (GetNode()->HasEventListeners(EventTypeNames::mouseup) || | 1156 if (GetNode()->HasEventListeners(EventTypeNames::mouseup) || |
1158 GetNode()->HasEventListeners(EventTypeNames::mousedown) || | 1157 GetNode()->HasEventListeners(EventTypeNames::mousedown) || |
1159 GetNode()->HasEventListeners(EventTypeNames::click) || | 1158 GetNode()->HasEventListeners(EventTypeNames::click) || |
1160 GetNode()->HasEventListeners(EventTypeNames::DOMActivate)) | 1159 GetNode()->HasEventListeners(EventTypeNames::DOMActivate)) |
1161 return true; | 1160 return true; |
1162 } | 1161 } |
1163 | 1162 |
1164 return AXObjectImpl::IsClickable(); | 1163 return AXObject::IsClickable(); |
1165 } | 1164 } |
1166 | 1165 |
1167 bool AXNodeObject::IsEnabled() const { | 1166 bool AXNodeObject::IsEnabled() const { |
1168 if (IsDescendantOfDisabledNode()) | 1167 if (IsDescendantOfDisabledNode()) |
1169 return false; | 1168 return false; |
1170 | 1169 |
1171 Node* node = this->GetNode(); | 1170 Node* node = this->GetNode(); |
1172 if (!node || !node->IsElementNode()) | 1171 if (!node || !node->IsElementNode()) |
1173 return true; | 1172 return true; |
1174 | 1173 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1297 // for this information for all elements. | 1296 // for this information for all elements. |
1298 return !IsReadOnly(); | 1297 return !IsReadOnly(); |
1299 } | 1298 } |
1300 | 1299 |
1301 bool AXNodeObject::CanSetSelectedAttribute() const { | 1300 bool AXNodeObject::CanSetSelectedAttribute() const { |
1302 // ARIA list box options can be selected if they are children of an element | 1301 // ARIA list box options can be selected if they are children of an element |
1303 // with an aria-activedescendant attribute. | 1302 // with an aria-activedescendant attribute. |
1304 if (AriaRoleAttribute() == kListBoxOptionRole && | 1303 if (AriaRoleAttribute() == kListBoxOptionRole && |
1305 AncestorExposesActiveDescendant()) | 1304 AncestorExposesActiveDescendant()) |
1306 return true; | 1305 return true; |
1307 return AXObjectImpl::CanSetSelectedAttribute(); | 1306 return AXObject::CanSetSelectedAttribute(); |
1308 } | 1307 } |
1309 | 1308 |
1310 bool AXNodeObject::CanvasHasFallbackContent() const { | 1309 bool AXNodeObject::CanvasHasFallbackContent() const { |
1311 Node* node = this->GetNode(); | 1310 Node* node = this->GetNode(); |
1312 if (!isHTMLCanvasElement(node)) | 1311 if (!isHTMLCanvasElement(node)) |
1313 return false; | 1312 return false; |
1314 | 1313 |
1315 // If it has any children that are elements, we'll assume it might be fallback | 1314 // If it has any children that are elements, we'll assume it might be fallback |
1316 // content. If it has no children or its only children are not elements | 1315 // content. If it has no children or its only children are not elements |
1317 // (e.g. just text nodes), it doesn't have fallback content. | 1316 // (e.g. just text nodes), it doesn't have fallback content. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1373 return 1; | 1372 return 1; |
1374 } | 1373 } |
1375 | 1374 |
1376 // Only tree item will calculate its level through the DOM currently. | 1375 // Only tree item will calculate its level through the DOM currently. |
1377 if (RoleValue() != kTreeItemRole) | 1376 if (RoleValue() != kTreeItemRole) |
1378 return 0; | 1377 return 0; |
1379 | 1378 |
1380 // Hierarchy leveling starts at 1, to match the aria-level spec. | 1379 // Hierarchy leveling starts at 1, to match the aria-level spec. |
1381 // We measure tree hierarchy by the number of groups that the item is within. | 1380 // We measure tree hierarchy by the number of groups that the item is within. |
1382 unsigned level = 1; | 1381 unsigned level = 1; |
1383 for (AXObjectImpl* parent = ParentObject(); parent; | 1382 for (AXObject* parent = ParentObject(); parent; |
1384 parent = parent->ParentObject()) { | 1383 parent = parent->ParentObject()) { |
1385 AccessibilityRole parent_role = parent->RoleValue(); | 1384 AccessibilityRole parent_role = parent->RoleValue(); |
1386 if (parent_role == kGroupRole) | 1385 if (parent_role == kGroupRole) |
1387 level++; | 1386 level++; |
1388 else if (parent_role == kTreeRole) | 1387 else if (parent_role == kTreeRole) |
1389 break; | 1388 break; |
1390 } | 1389 } |
1391 | 1390 |
1392 return level; | 1391 return level; |
1393 } | 1392 } |
(...skipping 30 matching lines...) Expand all Loading... |
1424 marker_ranges.push_back( | 1423 marker_ranges.push_back( |
1425 AXRange(marker->StartOffset(), marker->EndOffset())); | 1424 AXRange(marker->StartOffset(), marker->EndOffset())); |
1426 break; | 1425 break; |
1427 case DocumentMarker::kComposition: | 1426 case DocumentMarker::kComposition: |
1428 // No need for accessibility to know about these marker types. | 1427 // No need for accessibility to know about these marker types. |
1429 break; | 1428 break; |
1430 } | 1429 } |
1431 } | 1430 } |
1432 } | 1431 } |
1433 | 1432 |
1434 AXObjectImpl* AXNodeObject::InPageLinkTarget() const { | 1433 AXObject* AXNodeObject::InPageLinkTarget() const { |
1435 if (!node_ || !isHTMLAnchorElement(node_) || !GetDocument()) | 1434 if (!node_ || !isHTMLAnchorElement(node_) || !GetDocument()) |
1436 return AXObjectImpl::InPageLinkTarget(); | 1435 return AXObject::InPageLinkTarget(); |
1437 | 1436 |
1438 HTMLAnchorElement* anchor = toHTMLAnchorElement(node_); | 1437 HTMLAnchorElement* anchor = toHTMLAnchorElement(node_); |
1439 DCHECK(anchor); | 1438 DCHECK(anchor); |
1440 KURL link_url = anchor->Href(); | 1439 KURL link_url = anchor->Href(); |
1441 if (!link_url.IsValid()) | 1440 if (!link_url.IsValid()) |
1442 return AXObjectImpl::InPageLinkTarget(); | 1441 return AXObject::InPageLinkTarget(); |
1443 String fragment = link_url.FragmentIdentifier(); | 1442 String fragment = link_url.FragmentIdentifier(); |
1444 if (fragment.IsEmpty()) | 1443 if (fragment.IsEmpty()) |
1445 return AXObjectImpl::InPageLinkTarget(); | 1444 return AXObject::InPageLinkTarget(); |
1446 | 1445 |
1447 KURL document_url = GetDocument()->Url(); | 1446 KURL document_url = GetDocument()->Url(); |
1448 if (!document_url.IsValid() || | 1447 if (!document_url.IsValid() || |
1449 !EqualIgnoringFragmentIdentifier(document_url, link_url)) { | 1448 !EqualIgnoringFragmentIdentifier(document_url, link_url)) { |
1450 return AXObjectImpl::InPageLinkTarget(); | 1449 return AXObject::InPageLinkTarget(); |
1451 } | 1450 } |
1452 | 1451 |
1453 TreeScope& tree_scope = anchor->GetTreeScope(); | 1452 TreeScope& tree_scope = anchor->GetTreeScope(); |
1454 Element* target = tree_scope.FindAnchor(fragment); | 1453 Element* target = tree_scope.FindAnchor(fragment); |
1455 if (!target) | 1454 if (!target) |
1456 return AXObjectImpl::InPageLinkTarget(); | 1455 return AXObject::InPageLinkTarget(); |
1457 // If the target is not in the accessibility tree, get the first unignored | 1456 // If the target is not in the accessibility tree, get the first unignored |
1458 // sibling. | 1457 // sibling. |
1459 return AxObjectCache().FirstAccessibleObjectFromNode(target); | 1458 return AxObjectCache().FirstAccessibleObjectFromNode(target); |
1460 } | 1459 } |
1461 | 1460 |
1462 AccessibilityOrientation AXNodeObject::Orientation() const { | 1461 AccessibilityOrientation AXNodeObject::Orientation() const { |
1463 const AtomicString& aria_orientation = | 1462 const AtomicString& aria_orientation = |
1464 GetAOMPropertyOrARIAAttribute(AOMStringProperty::kOrientation); | 1463 GetAOMPropertyOrARIAAttribute(AOMStringProperty::kOrientation); |
1465 AccessibilityOrientation orientation = kAccessibilityOrientationUndefined; | 1464 AccessibilityOrientation orientation = kAccessibilityOrientationUndefined; |
1466 if (EqualIgnoringASCIICase(aria_orientation, "horizontal")) | 1465 if (EqualIgnoringASCIICase(aria_orientation, "horizontal")) |
(...skipping 17 matching lines...) Expand all Loading... |
1484 case kTabListRole: | 1483 case kTabListRole: |
1485 case kToolbarRole: | 1484 case kToolbarRole: |
1486 if (orientation == kAccessibilityOrientationUndefined) | 1485 if (orientation == kAccessibilityOrientationUndefined) |
1487 orientation = kAccessibilityOrientationHorizontal; | 1486 orientation = kAccessibilityOrientationHorizontal; |
1488 | 1487 |
1489 return orientation; | 1488 return orientation; |
1490 case kRadioGroupRole: | 1489 case kRadioGroupRole: |
1491 case kTreeGridRole: | 1490 case kTreeGridRole: |
1492 return orientation; | 1491 return orientation; |
1493 default: | 1492 default: |
1494 return AXObjectImpl::Orientation(); | 1493 return AXObject::Orientation(); |
1495 } | 1494 } |
1496 } | 1495 } |
1497 | 1496 |
1498 AXObjectImpl::AXObjectVector AXNodeObject::RadioButtonsInGroup() const { | 1497 AXObject::AXObjectVector AXNodeObject::RadioButtonsInGroup() const { |
1499 AXObjectVector radio_buttons; | 1498 AXObjectVector radio_buttons; |
1500 if (!node_ || RoleValue() != kRadioButtonRole) | 1499 if (!node_ || RoleValue() != kRadioButtonRole) |
1501 return radio_buttons; | 1500 return radio_buttons; |
1502 | 1501 |
1503 if (isHTMLInputElement(node_)) { | 1502 if (isHTMLInputElement(node_)) { |
1504 HTMLInputElement* radio_button = toHTMLInputElement(node_); | 1503 HTMLInputElement* radio_button = toHTMLInputElement(node_); |
1505 HeapVector<Member<HTMLInputElement>> html_radio_buttons = | 1504 HeapVector<Member<HTMLInputElement>> html_radio_buttons = |
1506 FindAllRadioButtonsWithSameName(radio_button); | 1505 FindAllRadioButtonsWithSameName(radio_button); |
1507 for (size_t i = 0; i < html_radio_buttons.size(); ++i) { | 1506 for (size_t i = 0; i < html_radio_buttons.size(); ++i) { |
1508 AXObjectImpl* ax_radio_button = | 1507 AXObject* ax_radio_button = |
1509 AxObjectCache().GetOrCreate(html_radio_buttons[i]); | 1508 AxObjectCache().GetOrCreate(html_radio_buttons[i]); |
1510 if (ax_radio_button) | 1509 if (ax_radio_button) |
1511 radio_buttons.push_back(ax_radio_button); | 1510 radio_buttons.push_back(ax_radio_button); |
1512 } | 1511 } |
1513 return radio_buttons; | 1512 return radio_buttons; |
1514 } | 1513 } |
1515 | 1514 |
1516 // If the immediate parent is a radio group, return all its children that are | 1515 // If the immediate parent is a radio group, return all its children that are |
1517 // radio buttons. | 1516 // radio buttons. |
1518 AXObjectImpl* parent = ParentObject(); | 1517 AXObject* parent = ParentObject(); |
1519 if (parent && parent->RoleValue() == kRadioGroupRole) { | 1518 if (parent && parent->RoleValue() == kRadioGroupRole) { |
1520 for (size_t i = 0; i < parent->Children().size(); ++i) { | 1519 for (size_t i = 0; i < parent->Children().size(); ++i) { |
1521 AXObjectImpl* child = parent->Children()[i]; | 1520 AXObject* child = parent->Children()[i]; |
1522 DCHECK(child); | 1521 DCHECK(child); |
1523 if (child->RoleValue() == kRadioButtonRole && | 1522 if (child->RoleValue() == kRadioButtonRole && |
1524 !child->AccessibilityIsIgnored()) { | 1523 !child->AccessibilityIsIgnored()) { |
1525 radio_buttons.push_back(child); | 1524 radio_buttons.push_back(child); |
1526 } | 1525 } |
1527 } | 1526 } |
1528 } | 1527 } |
1529 | 1528 |
1530 return radio_buttons; | 1529 return radio_buttons; |
1531 } | 1530 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1573 return ToTextControlElement(*node).value(); | 1572 return ToTextControlElement(*node).value(); |
1574 | 1573 |
1575 if (!node->IsElementNode()) | 1574 if (!node->IsElementNode()) |
1576 return String(); | 1575 return String(); |
1577 | 1576 |
1578 return ToElement(node)->innerText(); | 1577 return ToElement(node)->innerText(); |
1579 } | 1578 } |
1580 | 1579 |
1581 RGBA32 AXNodeObject::ColorValue() const { | 1580 RGBA32 AXNodeObject::ColorValue() const { |
1582 if (!isHTMLInputElement(GetNode()) || !IsColorWell()) | 1581 if (!isHTMLInputElement(GetNode()) || !IsColorWell()) |
1583 return AXObjectImpl::ColorValue(); | 1582 return AXObject::ColorValue(); |
1584 | 1583 |
1585 HTMLInputElement* input = toHTMLInputElement(GetNode()); | 1584 HTMLInputElement* input = toHTMLInputElement(GetNode()); |
1586 const AtomicString& type = input->getAttribute(typeAttr); | 1585 const AtomicString& type = input->getAttribute(typeAttr); |
1587 if (!EqualIgnoringASCIICase(type, "color")) | 1586 if (!EqualIgnoringASCIICase(type, "color")) |
1588 return AXObjectImpl::ColorValue(); | 1587 return AXObject::ColorValue(); |
1589 | 1588 |
1590 // HTMLInputElement::value always returns a string parseable by Color. | 1589 // HTMLInputElement::value always returns a string parseable by Color. |
1591 Color color; | 1590 Color color; |
1592 bool success = color.SetFromString(input->value()); | 1591 bool success = color.SetFromString(input->value()); |
1593 DCHECK(success); | 1592 DCHECK(success); |
1594 return color.Rgb(); | 1593 return color.Rgb(); |
1595 } | 1594 } |
1596 | 1595 |
1597 AriaCurrentState AXNodeObject::GetAriaCurrentState() const { | 1596 AriaCurrentState AXNodeObject::GetAriaCurrentState() const { |
1598 const AtomicString& attribute_value = | 1597 const AtomicString& attribute_value = |
(...skipping 12 matching lines...) Expand all Loading... |
1611 if (EqualIgnoringASCIICase(attribute_value, "location")) | 1610 if (EqualIgnoringASCIICase(attribute_value, "location")) |
1612 return kAriaCurrentStateLocation; | 1611 return kAriaCurrentStateLocation; |
1613 if (EqualIgnoringASCIICase(attribute_value, "date")) | 1612 if (EqualIgnoringASCIICase(attribute_value, "date")) |
1614 return kAriaCurrentStateDate; | 1613 return kAriaCurrentStateDate; |
1615 if (EqualIgnoringASCIICase(attribute_value, "time")) | 1614 if (EqualIgnoringASCIICase(attribute_value, "time")) |
1616 return kAriaCurrentStateTime; | 1615 return kAriaCurrentStateTime; |
1617 // An unknown value should return true. | 1616 // An unknown value should return true. |
1618 if (!attribute_value.IsEmpty()) | 1617 if (!attribute_value.IsEmpty()) |
1619 return kAriaCurrentStateTrue; | 1618 return kAriaCurrentStateTrue; |
1620 | 1619 |
1621 return AXObjectImpl::GetAriaCurrentState(); | 1620 return AXObject::GetAriaCurrentState(); |
1622 } | 1621 } |
1623 | 1622 |
1624 InvalidState AXNodeObject::GetInvalidState() const { | 1623 InvalidState AXNodeObject::GetInvalidState() const { |
1625 const AtomicString& attribute_value = | 1624 const AtomicString& attribute_value = |
1626 GetAOMPropertyOrARIAAttribute(AOMStringProperty::kInvalid); | 1625 GetAOMPropertyOrARIAAttribute(AOMStringProperty::kInvalid); |
1627 if (EqualIgnoringASCIICase(attribute_value, "false")) | 1626 if (EqualIgnoringASCIICase(attribute_value, "false")) |
1628 return kInvalidStateFalse; | 1627 return kInvalidStateFalse; |
1629 if (EqualIgnoringASCIICase(attribute_value, "true")) | 1628 if (EqualIgnoringASCIICase(attribute_value, "true")) |
1630 return kInvalidStateTrue; | 1629 return kInvalidStateTrue; |
1631 if (EqualIgnoringASCIICase(attribute_value, "spelling")) | 1630 if (EqualIgnoringASCIICase(attribute_value, "spelling")) |
1632 return kInvalidStateSpelling; | 1631 return kInvalidStateSpelling; |
1633 if (EqualIgnoringASCIICase(attribute_value, "grammar")) | 1632 if (EqualIgnoringASCIICase(attribute_value, "grammar")) |
1634 return kInvalidStateGrammar; | 1633 return kInvalidStateGrammar; |
1635 // A yet unknown value. | 1634 // A yet unknown value. |
1636 if (!attribute_value.IsEmpty()) | 1635 if (!attribute_value.IsEmpty()) |
1637 return kInvalidStateOther; | 1636 return kInvalidStateOther; |
1638 | 1637 |
1639 if (GetNode() && GetNode()->IsElementNode() && | 1638 if (GetNode() && GetNode()->IsElementNode() && |
1640 ToElement(GetNode())->IsFormControlElement()) { | 1639 ToElement(GetNode())->IsFormControlElement()) { |
1641 HTMLFormControlElement* element = ToHTMLFormControlElement(GetNode()); | 1640 HTMLFormControlElement* element = ToHTMLFormControlElement(GetNode()); |
1642 HeapVector<Member<HTMLFormControlElement>> invalid_controls; | 1641 HeapVector<Member<HTMLFormControlElement>> invalid_controls; |
1643 bool is_invalid = !element->checkValidity(&invalid_controls, | 1642 bool is_invalid = !element->checkValidity(&invalid_controls, |
1644 kCheckValidityDispatchNoEvent); | 1643 kCheckValidityDispatchNoEvent); |
1645 return is_invalid ? kInvalidStateTrue : kInvalidStateFalse; | 1644 return is_invalid ? kInvalidStateTrue : kInvalidStateFalse; |
1646 } | 1645 } |
1647 | 1646 |
1648 return AXObjectImpl::GetInvalidState(); | 1647 return AXObject::GetInvalidState(); |
1649 } | 1648 } |
1650 | 1649 |
1651 int AXNodeObject::PosInSet() const { | 1650 int AXNodeObject::PosInSet() const { |
1652 if (SupportsSetSizeAndPosInSet()) { | 1651 if (SupportsSetSizeAndPosInSet()) { |
1653 String pos_in_set_str = GetAttribute(aria_posinsetAttr); | 1652 String pos_in_set_str = GetAttribute(aria_posinsetAttr); |
1654 if (!pos_in_set_str.IsEmpty()) { | 1653 if (!pos_in_set_str.IsEmpty()) { |
1655 int pos_in_set = pos_in_set_str.ToInt(); | 1654 int pos_in_set = pos_in_set_str.ToInt(); |
1656 if (pos_in_set > 0) | 1655 if (pos_in_set > 0) |
1657 return pos_in_set; | 1656 return pos_in_set; |
1658 return 1; | 1657 return 1; |
1659 } | 1658 } |
1660 | 1659 |
1661 return AXObjectImpl::IndexInParent() + 1; | 1660 return AXObject::IndexInParent() + 1; |
1662 } | 1661 } |
1663 | 1662 |
1664 return 0; | 1663 return 0; |
1665 } | 1664 } |
1666 | 1665 |
1667 int AXNodeObject::SetSize() const { | 1666 int AXNodeObject::SetSize() const { |
1668 if (SupportsSetSizeAndPosInSet()) { | 1667 if (SupportsSetSizeAndPosInSet()) { |
1669 String set_size_str = GetAttribute(aria_setsizeAttr); | 1668 String set_size_str = GetAttribute(aria_setsizeAttr); |
1670 if (!set_size_str.IsEmpty()) { | 1669 if (!set_size_str.IsEmpty()) { |
1671 int set_size = set_size_str.ToInt(); | 1670 int set_size = set_size_str.ToInt(); |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1930 | 1929 |
1931 return String(); | 1930 return String(); |
1932 } | 1931 } |
1933 | 1932 |
1934 String AXNodeObject::TextFromDescendants(AXObjectSet& visited, | 1933 String AXNodeObject::TextFromDescendants(AXObjectSet& visited, |
1935 bool recursive) const { | 1934 bool recursive) const { |
1936 if (!CanHaveChildren() && recursive) | 1935 if (!CanHaveChildren() && recursive) |
1937 return String(); | 1936 return String(); |
1938 | 1937 |
1939 StringBuilder accumulated_text; | 1938 StringBuilder accumulated_text; |
1940 AXObjectImpl* previous = nullptr; | 1939 AXObject* previous = nullptr; |
1941 | 1940 |
1942 AXObjectVector children; | 1941 AXObjectVector children; |
1943 | 1942 |
1944 HeapVector<Member<AXObjectImpl>> owned_children; | 1943 HeapVector<Member<AXObject>> owned_children; |
1945 ComputeAriaOwnsChildren(owned_children); | 1944 ComputeAriaOwnsChildren(owned_children); |
1946 for (AXObjectImpl* obj = RawFirstChild(); obj; obj = obj->RawNextSibling()) { | 1945 for (AXObject* obj = RawFirstChild(); obj; obj = obj->RawNextSibling()) { |
1947 if (!AxObjectCache().IsAriaOwned(obj)) | 1946 if (!AxObjectCache().IsAriaOwned(obj)) |
1948 children.push_back(obj); | 1947 children.push_back(obj); |
1949 } | 1948 } |
1950 for (const auto& owned_child : owned_children) | 1949 for (const auto& owned_child : owned_children) |
1951 children.push_back(owned_child); | 1950 children.push_back(owned_child); |
1952 | 1951 |
1953 for (AXObjectImpl* child : children) { | 1952 for (AXObject* child : children) { |
1954 // Don't recurse into children that are explicitly marked as aria-hidden. | 1953 // Don't recurse into children that are explicitly marked as aria-hidden. |
1955 // Note that we don't call isInertOrAriaHidden because that would return | 1954 // Note that we don't call isInertOrAriaHidden because that would return |
1956 // true if any ancestor is hidden, but we need to be able to compute the | 1955 // true if any ancestor is hidden, but we need to be able to compute the |
1957 // accessible name of object inside hidden subtrees (for example, if | 1956 // accessible name of object inside hidden subtrees (for example, if |
1958 // aria-labelledby points to an object that's hidden). | 1957 // aria-labelledby points to an object that's hidden). |
1959 if (EqualIgnoringASCIICase(child->GetAttribute(aria_hiddenAttr), "true")) | 1958 if (EqualIgnoringASCIICase(child->GetAttribute(aria_hiddenAttr), "true")) |
1960 continue; | 1959 continue; |
1961 | 1960 |
1962 // If we're going between two layoutObjects that are in separate | 1961 // If we're going between two layoutObjects that are in separate |
1963 // LayoutBoxes, add whitespace if it wasn't there already. Intuitively if | 1962 // LayoutBoxes, add whitespace if it wasn't there already. Intuitively if |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2020 ToLabelableElement(html_element)->labels()->length() > 0) | 2019 ToLabelableElement(html_element)->labels()->length() > 0) |
2021 return true; | 2020 return true; |
2022 } | 2021 } |
2023 | 2022 |
2024 return false; | 2023 return false; |
2025 } | 2024 } |
2026 | 2025 |
2027 bool AXNodeObject::NameFromContents() const { | 2026 bool AXNodeObject::NameFromContents() const { |
2028 Node* node = GetNode(); | 2027 Node* node = GetNode(); |
2029 if (!node || !node->IsElementNode()) | 2028 if (!node || !node->IsElementNode()) |
2030 return AXObjectImpl::NameFromContents(); | 2029 return AXObject::NameFromContents(); |
2031 // AXObjectImpl::nameFromContents determines whether an element should take | 2030 // AXObject::nameFromContents determines whether an element should take its |
2032 // its name from its descendant contents based on role. However, <select> is a | 2031 // name from its descendant contents based on role. However, <select> is a |
2033 // special case, as unlike a typical pop-up button it contains its own pop-up | 2032 // special case, as unlike a typical pop-up button it contains its own pop-up |
2034 // menu's contents, which should not be used as the name. | 2033 // menu's contents, which should not be used as the name. |
2035 if (isHTMLSelectElement(node)) | 2034 if (isHTMLSelectElement(node)) |
2036 return false; | 2035 return false; |
2037 return AXObjectImpl::NameFromContents(); | 2036 return AXObject::NameFromContents(); |
2038 } | 2037 } |
2039 | 2038 |
2040 void AXNodeObject::GetRelativeBounds( | 2039 void AXNodeObject::GetRelativeBounds( |
2041 AXObjectImpl** out_container, | 2040 AXObject** out_container, |
2042 FloatRect& out_bounds_in_container, | 2041 FloatRect& out_bounds_in_container, |
2043 SkMatrix44& out_container_transform) const { | 2042 SkMatrix44& out_container_transform) const { |
2044 if (LayoutObjectForRelativeBounds()) { | 2043 if (LayoutObjectForRelativeBounds()) { |
2045 AXObjectImpl::GetRelativeBounds(out_container, out_bounds_in_container, | 2044 AXObject::GetRelativeBounds(out_container, out_bounds_in_container, |
2046 out_container_transform); | 2045 out_container_transform); |
2047 return; | 2046 return; |
2048 } | 2047 } |
2049 | 2048 |
2050 *out_container = nullptr; | 2049 *out_container = nullptr; |
2051 out_bounds_in_container = FloatRect(); | 2050 out_bounds_in_container = FloatRect(); |
2052 out_container_transform.setIdentity(); | 2051 out_container_transform.setIdentity(); |
2053 | 2052 |
2054 // First check if it has explicit bounds, for example if this element is tied | 2053 // First check if it has explicit bounds, for example if this element is tied |
2055 // to a canvas path. When explicit coordinates are provided, the ID of the | 2054 // to a canvas path. When explicit coordinates are provided, the ID of the |
2056 // explicit container element that the coordinates are relative to must be | 2055 // explicit container element that the coordinates are relative to must be |
2057 // provided too. | 2056 // provided too. |
2058 if (!explicit_element_rect_.IsEmpty()) { | 2057 if (!explicit_element_rect_.IsEmpty()) { |
2059 *out_container = AxObjectCache().ObjectFromAXID(explicit_container_id_); | 2058 *out_container = AxObjectCache().ObjectFromAXID(explicit_container_id_); |
2060 if (*out_container) { | 2059 if (*out_container) { |
2061 out_bounds_in_container = FloatRect(explicit_element_rect_); | 2060 out_bounds_in_container = FloatRect(explicit_element_rect_); |
2062 return; | 2061 return; |
2063 } | 2062 } |
2064 } | 2063 } |
2065 | 2064 |
2066 // If it's in a canvas but doesn't have an explicit rect, get the bounding | 2065 // If it's in a canvas but doesn't have an explicit rect, get the bounding |
2067 // rect of its children. | 2066 // rect of its children. |
2068 if (GetNode()->parentElement()->IsInCanvasSubtree()) { | 2067 if (GetNode()->parentElement()->IsInCanvasSubtree()) { |
2069 Vector<FloatRect> rects; | 2068 Vector<FloatRect> rects; |
2070 for (Node& child : NodeTraversal::ChildrenOf(*GetNode())) { | 2069 for (Node& child : NodeTraversal::ChildrenOf(*GetNode())) { |
2071 if (child.IsHTMLElement()) { | 2070 if (child.IsHTMLElement()) { |
2072 if (AXObjectImpl* obj = AxObjectCache().Get(&child)) { | 2071 if (AXObject* obj = AxObjectCache().Get(&child)) { |
2073 AXObjectImpl* container; | 2072 AXObject* container; |
2074 FloatRect bounds; | 2073 FloatRect bounds; |
2075 obj->GetRelativeBounds(&container, bounds, out_container_transform); | 2074 obj->GetRelativeBounds(&container, bounds, out_container_transform); |
2076 if (container) { | 2075 if (container) { |
2077 *out_container = container; | 2076 *out_container = container; |
2078 rects.push_back(bounds); | 2077 rects.push_back(bounds); |
2079 } | 2078 } |
2080 } | 2079 } |
2081 } | 2080 } |
2082 } | 2081 } |
2083 | 2082 |
2084 if (*out_container) { | 2083 if (*out_container) { |
2085 out_bounds_in_container = UnionRect(rects); | 2084 out_bounds_in_container = UnionRect(rects); |
2086 return; | 2085 return; |
2087 } | 2086 } |
2088 } | 2087 } |
2089 | 2088 |
2090 // If this object doesn't have an explicit element rect or computable from its | 2089 // If this object doesn't have an explicit element rect or computable from its |
2091 // children, for now, let's return the position of the ancestor that does have | 2090 // children, for now, let's return the position of the ancestor that does have |
2092 // a position, and make it the width of that parent, and about the height of a | 2091 // a position, and make it the width of that parent, and about the height of a |
2093 // line of text, so that it's clear the object is a child of the parent. | 2092 // line of text, so that it's clear the object is a child of the parent. |
2094 for (AXObjectImpl* position_provider = ParentObject(); position_provider; | 2093 for (AXObject* position_provider = ParentObject(); position_provider; |
2095 position_provider = position_provider->ParentObject()) { | 2094 position_provider = position_provider->ParentObject()) { |
2096 if (position_provider->IsAXLayoutObject()) { | 2095 if (position_provider->IsAXLayoutObject()) { |
2097 position_provider->GetRelativeBounds( | 2096 position_provider->GetRelativeBounds( |
2098 out_container, out_bounds_in_container, out_container_transform); | 2097 out_container, out_bounds_in_container, out_container_transform); |
2099 if (*out_container) | 2098 if (*out_container) |
2100 out_bounds_in_container.SetSize( | 2099 out_bounds_in_container.SetSize( |
2101 FloatSize(out_bounds_in_container.Width(), | 2100 FloatSize(out_bounds_in_container.Width(), |
2102 std::min(10.0f, out_bounds_in_container.Height()))); | 2101 std::min(10.0f, out_bounds_in_container.Height()))); |
2103 break; | 2102 break; |
2104 } | 2103 } |
(...skipping 10 matching lines...) Expand all Loading... |
2115 // <option>. | 2114 // <option>. |
2116 if (isHTMLOptionElement(node)) | 2115 if (isHTMLOptionElement(node)) |
2117 parent_node = toHTMLOptionElement(node)->OwnerSelectElement(); | 2116 parent_node = toHTMLOptionElement(node)->OwnerSelectElement(); |
2118 | 2117 |
2119 if (!parent_node) | 2118 if (!parent_node) |
2120 parent_node = node->parentNode(); | 2119 parent_node = node->parentNode(); |
2121 | 2120 |
2122 return parent_node; | 2121 return parent_node; |
2123 } | 2122 } |
2124 | 2123 |
2125 AXObjectImpl* AXNodeObject::ComputeParent() const { | 2124 AXObject* AXNodeObject::ComputeParent() const { |
2126 DCHECK(!IsDetached()); | 2125 DCHECK(!IsDetached()); |
2127 if (Node* parent_node = GetParentNodeForComputeParent(GetNode())) | 2126 if (Node* parent_node = GetParentNodeForComputeParent(GetNode())) |
2128 return AxObjectCache().GetOrCreate(parent_node); | 2127 return AxObjectCache().GetOrCreate(parent_node); |
2129 | 2128 |
2130 return nullptr; | 2129 return nullptr; |
2131 } | 2130 } |
2132 | 2131 |
2133 AXObjectImpl* AXNodeObject::ComputeParentIfExists() const { | 2132 AXObject* AXNodeObject::ComputeParentIfExists() const { |
2134 if (Node* parent_node = GetParentNodeForComputeParent(GetNode())) | 2133 if (Node* parent_node = GetParentNodeForComputeParent(GetNode())) |
2135 return AxObjectCache().Get(parent_node); | 2134 return AxObjectCache().Get(parent_node); |
2136 | 2135 |
2137 return nullptr; | 2136 return nullptr; |
2138 } | 2137 } |
2139 | 2138 |
2140 AXObjectImpl* AXNodeObject::RawFirstChild() const { | 2139 AXObject* AXNodeObject::RawFirstChild() const { |
2141 if (!GetNode()) | 2140 if (!GetNode()) |
2142 return 0; | 2141 return 0; |
2143 | 2142 |
2144 Node* first_child = GetNode()->firstChild(); | 2143 Node* first_child = GetNode()->firstChild(); |
2145 | 2144 |
2146 if (!first_child) | 2145 if (!first_child) |
2147 return 0; | 2146 return 0; |
2148 | 2147 |
2149 return AxObjectCache().GetOrCreate(first_child); | 2148 return AxObjectCache().GetOrCreate(first_child); |
2150 } | 2149 } |
2151 | 2150 |
2152 AXObjectImpl* AXNodeObject::RawNextSibling() const { | 2151 AXObject* AXNodeObject::RawNextSibling() const { |
2153 if (!GetNode()) | 2152 if (!GetNode()) |
2154 return 0; | 2153 return 0; |
2155 | 2154 |
2156 Node* next_sibling = GetNode()->nextSibling(); | 2155 Node* next_sibling = GetNode()->nextSibling(); |
2157 if (!next_sibling) | 2156 if (!next_sibling) |
2158 return 0; | 2157 return 0; |
2159 | 2158 |
2160 return AxObjectCache().GetOrCreate(next_sibling); | 2159 return AxObjectCache().GetOrCreate(next_sibling); |
2161 } | 2160 } |
2162 | 2161 |
2163 void AXNodeObject::AddChildren() { | 2162 void AXNodeObject::AddChildren() { |
2164 DCHECK(!IsDetached()); | 2163 DCHECK(!IsDetached()); |
2165 // If the need to add more children in addition to existing children arises, | 2164 // If the need to add more children in addition to existing children arises, |
2166 // childrenChanged should have been called, leaving the object with no | 2165 // childrenChanged should have been called, leaving the object with no |
2167 // children. | 2166 // children. |
2168 DCHECK(!have_children_); | 2167 DCHECK(!have_children_); |
2169 | 2168 |
2170 if (!node_) | 2169 if (!node_) |
2171 return; | 2170 return; |
2172 | 2171 |
2173 have_children_ = true; | 2172 have_children_ = true; |
2174 | 2173 |
2175 // The only time we add children from the DOM tree to a node with a | 2174 // The only time we add children from the DOM tree to a node with a |
2176 // layoutObject is when it's a canvas. | 2175 // layoutObject is when it's a canvas. |
2177 if (GetLayoutObject() && !isHTMLCanvasElement(*node_)) | 2176 if (GetLayoutObject() && !isHTMLCanvasElement(*node_)) |
2178 return; | 2177 return; |
2179 | 2178 |
2180 HeapVector<Member<AXObjectImpl>> owned_children; | 2179 HeapVector<Member<AXObject>> owned_children; |
2181 ComputeAriaOwnsChildren(owned_children); | 2180 ComputeAriaOwnsChildren(owned_children); |
2182 | 2181 |
2183 for (Node& child : NodeTraversal::ChildrenOf(*node_)) { | 2182 for (Node& child : NodeTraversal::ChildrenOf(*node_)) { |
2184 AXObjectImpl* child_obj = AxObjectCache().GetOrCreate(&child); | 2183 AXObject* child_obj = AxObjectCache().GetOrCreate(&child); |
2185 if (child_obj && !AxObjectCache().IsAriaOwned(child_obj)) | 2184 if (child_obj && !AxObjectCache().IsAriaOwned(child_obj)) |
2186 AddChild(child_obj); | 2185 AddChild(child_obj); |
2187 } | 2186 } |
2188 | 2187 |
2189 for (const auto& owned_child : owned_children) | 2188 for (const auto& owned_child : owned_children) |
2190 AddChild(owned_child); | 2189 AddChild(owned_child); |
2191 | 2190 |
2192 for (const auto& child : children_) | 2191 for (const auto& child : children_) |
2193 child->SetParent(this); | 2192 child->SetParent(this); |
2194 } | 2193 } |
2195 | 2194 |
2196 void AXNodeObject::AddChild(AXObjectImpl* child) { | 2195 void AXNodeObject::AddChild(AXObject* child) { |
2197 InsertChild(child, children_.size()); | 2196 InsertChild(child, children_.size()); |
2198 } | 2197 } |
2199 | 2198 |
2200 void AXNodeObject::InsertChild(AXObjectImpl* child, unsigned index) { | 2199 void AXNodeObject::InsertChild(AXObject* child, unsigned index) { |
2201 if (!child) | 2200 if (!child) |
2202 return; | 2201 return; |
2203 | 2202 |
2204 // If the parent is asking for this child's children, then either it's the | 2203 // If the parent is asking for this child's children, then either it's the |
2205 // first time (and clearing is a no-op), or its visibility has changed. In the | 2204 // first time (and clearing is a no-op), or its visibility has changed. In the |
2206 // latter case, this child may have a stale child cached. This can prevent | 2205 // latter case, this child may have a stale child cached. This can prevent |
2207 // aria-hidden changes from working correctly. Hence, whenever a parent is | 2206 // aria-hidden changes from working correctly. Hence, whenever a parent is |
2208 // getting children, ensure data is not stale. | 2207 // getting children, ensure data is not stale. |
2209 child->ClearChildren(); | 2208 child->ClearChildren(); |
2210 | 2209 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2266 if (isHTMLInputElement(*node)) { | 2265 if (isHTMLInputElement(*node)) { |
2267 HTMLInputElement& input = toHTMLInputElement(*node); | 2266 HTMLInputElement& input = toHTMLInputElement(*node); |
2268 if (!input.IsDisabledFormControl() && | 2267 if (!input.IsDisabledFormControl() && |
2269 (IsCheckboxOrRadio() || input.IsTextButton() || | 2268 (IsCheckboxOrRadio() || input.IsTextButton() || |
2270 input.type() == InputTypeNames::file)) | 2269 input.type() == InputTypeNames::file)) |
2271 return &input; | 2270 return &input; |
2272 } else if (isHTMLButtonElement(*node)) { | 2271 } else if (isHTMLButtonElement(*node)) { |
2273 return ToElement(node); | 2272 return ToElement(node); |
2274 } | 2273 } |
2275 | 2274 |
2276 if (AXObjectImpl::IsARIAInput(AriaRoleAttribute())) | 2275 if (AXObject::IsARIAInput(AriaRoleAttribute())) |
2277 return ToElement(node); | 2276 return ToElement(node); |
2278 | 2277 |
2279 if (IsImageButton()) | 2278 if (IsImageButton()) |
2280 return ToElement(node); | 2279 return ToElement(node); |
2281 | 2280 |
2282 if (isHTMLSelectElement(*node)) | 2281 if (isHTMLSelectElement(*node)) |
2283 return ToElement(node); | 2282 return ToElement(node); |
2284 | 2283 |
2285 switch (RoleValue()) { | 2284 switch (RoleValue()) { |
2286 case kButtonRole: | 2285 case kButtonRole: |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2325 Document* AXNodeObject::GetDocument() const { | 2324 Document* AXNodeObject::GetDocument() const { |
2326 if (!GetNode()) | 2325 if (!GetNode()) |
2327 return 0; | 2326 return 0; |
2328 return &GetNode()->GetDocument(); | 2327 return &GetNode()->GetDocument(); |
2329 } | 2328 } |
2330 | 2329 |
2331 void AXNodeObject::SetNode(Node* node) { | 2330 void AXNodeObject::SetNode(Node* node) { |
2332 node_ = node; | 2331 node_ = node; |
2333 } | 2332 } |
2334 | 2333 |
2335 AXObjectImpl* AXNodeObject::CorrespondingControlForLabelElement() const { | 2334 AXObject* AXNodeObject::CorrespondingControlForLabelElement() const { |
2336 HTMLLabelElement* label_element = LabelElementContainer(); | 2335 HTMLLabelElement* label_element = LabelElementContainer(); |
2337 if (!label_element) | 2336 if (!label_element) |
2338 return 0; | 2337 return 0; |
2339 | 2338 |
2340 HTMLElement* corresponding_control = label_element->control(); | 2339 HTMLElement* corresponding_control = label_element->control(); |
2341 if (!corresponding_control) | 2340 if (!corresponding_control) |
2342 return 0; | 2341 return 0; |
2343 | 2342 |
2344 // Make sure the corresponding control isn't a descendant of this label | 2343 // Make sure the corresponding control isn't a descendant of this label |
2345 // that's in the middle of being destroyed. | 2344 // that's in the middle of being destroyed. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2424 return; | 2423 return; |
2425 } | 2424 } |
2426 | 2425 |
2427 AxObjectCache().PostNotification(this, AXObjectCacheImpl::kAXChildrenChanged); | 2426 AxObjectCache().PostNotification(this, AXObjectCacheImpl::kAXChildrenChanged); |
2428 | 2427 |
2429 // Go up the accessibility parent chain, but only if the element already | 2428 // Go up the accessibility parent chain, but only if the element already |
2430 // exists. This method is called during layout, minimal work should be done. | 2429 // exists. This method is called during layout, minimal work should be done. |
2431 // If AX elements are created now, they could interrogate the layout tree | 2430 // If AX elements are created now, they could interrogate the layout tree |
2432 // while it's in a funky state. At the same time, process ARIA live region | 2431 // while it's in a funky state. At the same time, process ARIA live region |
2433 // changes. | 2432 // changes. |
2434 for (AXObjectImpl* parent = this; parent; | 2433 for (AXObject* parent = this; parent; |
2435 parent = parent->ParentObjectIfExists()) { | 2434 parent = parent->ParentObjectIfExists()) { |
2436 parent->SetNeedsToUpdateChildren(); | 2435 parent->SetNeedsToUpdateChildren(); |
2437 | 2436 |
2438 // These notifications always need to be sent because screenreaders are | 2437 // These notifications always need to be sent because screenreaders are |
2439 // reliant on them to perform. In other words, they need to be sent even | 2438 // reliant on them to perform. In other words, they need to be sent even |
2440 // when the screen reader has not accessed this live region since the last | 2439 // when the screen reader has not accessed this live region since the last |
2441 // update. | 2440 // update. |
2442 | 2441 |
2443 // If this element supports ARIA live regions, then notify the AT of | 2442 // If this element supports ARIA live regions, then notify the AT of |
2444 // changes. | 2443 // changes. |
(...skipping 11 matching lines...) Expand all Loading... |
2456 } | 2455 } |
2457 | 2456 |
2458 void AXNodeObject::SelectionChanged() { | 2457 void AXNodeObject::SelectionChanged() { |
2459 // Post the selected text changed event on the first ancestor that's | 2458 // Post the selected text changed event on the first ancestor that's |
2460 // focused (to handle form controls, ARIA text boxes and contentEditable), | 2459 // focused (to handle form controls, ARIA text boxes and contentEditable), |
2461 // or the web area if the selection is just in the document somewhere. | 2460 // or the web area if the selection is just in the document somewhere. |
2462 if (IsFocused() || IsWebArea()) { | 2461 if (IsFocused() || IsWebArea()) { |
2463 AxObjectCache().PostNotification(this, | 2462 AxObjectCache().PostNotification(this, |
2464 AXObjectCacheImpl::kAXSelectedTextChanged); | 2463 AXObjectCacheImpl::kAXSelectedTextChanged); |
2465 if (GetDocument()) { | 2464 if (GetDocument()) { |
2466 AXObjectImpl* document_object = | 2465 AXObject* document_object = AxObjectCache().GetOrCreate(GetDocument()); |
2467 AxObjectCache().GetOrCreate(GetDocument()); | |
2468 AxObjectCache().PostNotification( | 2466 AxObjectCache().PostNotification( |
2469 document_object, AXObjectCacheImpl::kAXDocumentSelectionChanged); | 2467 document_object, AXObjectCacheImpl::kAXDocumentSelectionChanged); |
2470 } | 2468 } |
2471 } else { | 2469 } else { |
2472 AXObjectImpl::SelectionChanged(); // Calls selectionChanged on parent. | 2470 AXObject::SelectionChanged(); // Calls selectionChanged on parent. |
2473 } | 2471 } |
2474 } | 2472 } |
2475 | 2473 |
2476 void AXNodeObject::TextChanged() { | 2474 void AXNodeObject::TextChanged() { |
2477 // If this element supports ARIA live regions, or is part of a region with an | 2475 // If this element supports ARIA live regions, or is part of a region with an |
2478 // ARIA editable role, then notify the AT of changes. | 2476 // ARIA editable role, then notify the AT of changes. |
2479 AXObjectCacheImpl& cache = AxObjectCache(); | 2477 AXObjectCacheImpl& cache = AxObjectCache(); |
2480 for (Node* parent_node = GetNode(); parent_node; | 2478 for (Node* parent_node = GetNode(); parent_node; |
2481 parent_node = parent_node->parentNode()) { | 2479 parent_node = parent_node->parentNode()) { |
2482 AXObjectImpl* parent = cache.Get(parent_node); | 2480 AXObject* parent = cache.Get(parent_node); |
2483 if (!parent) | 2481 if (!parent) |
2484 continue; | 2482 continue; |
2485 | 2483 |
2486 if (parent->IsLiveRegion()) | 2484 if (parent->IsLiveRegion()) |
2487 cache.PostNotification(parent_node, | 2485 cache.PostNotification(parent_node, |
2488 AXObjectCacheImpl::kAXLiveRegionChanged); | 2486 AXObjectCacheImpl::kAXLiveRegionChanged); |
2489 | 2487 |
2490 // If this element is an ARIA text box or content editable, post a "value | 2488 // If this element is an ARIA text box or content editable, post a "value |
2491 // changed" notification on it so that it behaves just like a native input | 2489 // changed" notification on it so that it behaves just like a native input |
2492 // element or textarea. | 2490 // element or textarea. |
2493 if (parent->IsNonNativeTextControl()) | 2491 if (parent->IsNonNativeTextControl()) |
2494 cache.PostNotification(parent_node, AXObjectCacheImpl::kAXValueChanged); | 2492 cache.PostNotification(parent_node, AXObjectCacheImpl::kAXValueChanged); |
2495 } | 2493 } |
2496 } | 2494 } |
2497 | 2495 |
2498 void AXNodeObject::UpdateAccessibilityRole() { | 2496 void AXNodeObject::UpdateAccessibilityRole() { |
2499 role_ = DetermineAccessibilityRole(); | 2497 role_ = DetermineAccessibilityRole(); |
2500 bool ignored_status = AccessibilityIsIgnored(); | 2498 bool ignored_status = AccessibilityIsIgnored(); |
2501 | 2499 |
2502 // The AX hierarchy only needs to be updated if the ignored status of an | 2500 // The AX hierarchy only needs to be updated if the ignored status of an |
2503 // element has changed. | 2501 // element has changed. |
2504 if (ignored_status != AccessibilityIsIgnored()) | 2502 if (ignored_status != AccessibilityIsIgnored()) |
2505 ChildrenChanged(); | 2503 ChildrenChanged(); |
2506 } | 2504 } |
2507 | 2505 |
2508 void AXNodeObject::ComputeAriaOwnsChildren( | 2506 void AXNodeObject::ComputeAriaOwnsChildren( |
2509 HeapVector<Member<AXObjectImpl>>& owned_children) const { | 2507 HeapVector<Member<AXObject>>& owned_children) const { |
2510 if (!HasAttribute(aria_ownsAttr)) | 2508 if (!HasAttribute(aria_ownsAttr)) |
2511 return; | 2509 return; |
2512 | 2510 |
2513 Vector<String> id_vector; | 2511 Vector<String> id_vector; |
2514 if (CanHaveChildren() && !IsNativeTextControl() && | 2512 if (CanHaveChildren() && !IsNativeTextControl() && |
2515 !HasContentEditableAttributeSet()) | 2513 !HasContentEditableAttributeSet()) |
2516 TokenVectorFromAttribute(id_vector, aria_ownsAttr); | 2514 TokenVectorFromAttribute(id_vector, aria_ownsAttr); |
2517 | 2515 |
2518 AxObjectCache().UpdateAriaOwns(this, id_vector, owned_children); | 2516 AxObjectCache().UpdateAriaOwns(this, id_vector, owned_children); |
2519 } | 2517 } |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2751 name_sources->back().native_source = kAXTextFromNativeHTMLFigcaption; | 2749 name_sources->back().native_source = kAXTextFromNativeHTMLFigcaption; |
2752 } | 2750 } |
2753 Element* figcaption = nullptr; | 2751 Element* figcaption = nullptr; |
2754 for (Element& element : ElementTraversal::DescendantsOf(*(GetNode()))) { | 2752 for (Element& element : ElementTraversal::DescendantsOf(*(GetNode()))) { |
2755 if (element.HasTagName(figcaptionTag)) { | 2753 if (element.HasTagName(figcaptionTag)) { |
2756 figcaption = &element; | 2754 figcaption = &element; |
2757 break; | 2755 break; |
2758 } | 2756 } |
2759 } | 2757 } |
2760 if (figcaption) { | 2758 if (figcaption) { |
2761 AXObjectImpl* figcaption_ax_object = | 2759 AXObject* figcaption_ax_object = AxObjectCache().GetOrCreate(figcaption); |
2762 AxObjectCache().GetOrCreate(figcaption); | |
2763 if (figcaption_ax_object) { | 2760 if (figcaption_ax_object) { |
2764 text_alternative = | 2761 text_alternative = |
2765 RecursiveTextAlternative(*figcaption_ax_object, false, visited); | 2762 RecursiveTextAlternative(*figcaption_ax_object, false, visited); |
2766 | 2763 |
2767 if (related_objects) { | 2764 if (related_objects) { |
2768 local_related_objects.push_back(new NameSourceRelatedObject( | 2765 local_related_objects.push_back(new NameSourceRelatedObject( |
2769 figcaption_ax_object, text_alternative)); | 2766 figcaption_ax_object, text_alternative)); |
2770 *related_objects = local_related_objects; | 2767 *related_objects = local_related_objects; |
2771 local_related_objects.clear(); | 2768 local_related_objects.clear(); |
2772 } | 2769 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2816 | 2813 |
2817 // caption | 2814 // caption |
2818 name_from = kAXNameFromCaption; | 2815 name_from = kAXNameFromCaption; |
2819 if (name_sources) { | 2816 if (name_sources) { |
2820 name_sources->push_back(NameSource(*found_text_alternative)); | 2817 name_sources->push_back(NameSource(*found_text_alternative)); |
2821 name_sources->back().type = name_from; | 2818 name_sources->back().type = name_from; |
2822 name_sources->back().native_source = kAXTextFromNativeHTMLTableCaption; | 2819 name_sources->back().native_source = kAXTextFromNativeHTMLTableCaption; |
2823 } | 2820 } |
2824 HTMLTableCaptionElement* caption = table_element->caption(); | 2821 HTMLTableCaptionElement* caption = table_element->caption(); |
2825 if (caption) { | 2822 if (caption) { |
2826 AXObjectImpl* caption_ax_object = AxObjectCache().GetOrCreate(caption); | 2823 AXObject* caption_ax_object = AxObjectCache().GetOrCreate(caption); |
2827 if (caption_ax_object) { | 2824 if (caption_ax_object) { |
2828 text_alternative = | 2825 text_alternative = |
2829 RecursiveTextAlternative(*caption_ax_object, false, visited); | 2826 RecursiveTextAlternative(*caption_ax_object, false, visited); |
2830 if (related_objects) { | 2827 if (related_objects) { |
2831 local_related_objects.push_back( | 2828 local_related_objects.push_back( |
2832 new NameSourceRelatedObject(caption_ax_object, text_alternative)); | 2829 new NameSourceRelatedObject(caption_ax_object, text_alternative)); |
2833 *related_objects = local_related_objects; | 2830 *related_objects = local_related_objects; |
2834 local_related_objects.clear(); | 2831 local_related_objects.clear(); |
2835 } | 2832 } |
2836 | 2833 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2873 if (name_sources) { | 2870 if (name_sources) { |
2874 name_sources->push_back(NameSource(*found_text_alternative)); | 2871 name_sources->push_back(NameSource(*found_text_alternative)); |
2875 name_sources->back().type = name_from; | 2872 name_sources->back().type = name_from; |
2876 name_sources->back().native_source = kAXTextFromNativeHTMLTitleElement; | 2873 name_sources->back().native_source = kAXTextFromNativeHTMLTitleElement; |
2877 } | 2874 } |
2878 DCHECK(GetNode()->IsContainerNode()); | 2875 DCHECK(GetNode()->IsContainerNode()); |
2879 Element* title = ElementTraversal::FirstChild( | 2876 Element* title = ElementTraversal::FirstChild( |
2880 ToContainerNode(*(GetNode())), HasTagName(SVGNames::titleTag)); | 2877 ToContainerNode(*(GetNode())), HasTagName(SVGNames::titleTag)); |
2881 | 2878 |
2882 if (title) { | 2879 if (title) { |
2883 AXObjectImpl* title_ax_object = AxObjectCache().GetOrCreate(title); | 2880 AXObject* title_ax_object = AxObjectCache().GetOrCreate(title); |
2884 if (title_ax_object && !visited.Contains(title_ax_object)) { | 2881 if (title_ax_object && !visited.Contains(title_ax_object)) { |
2885 text_alternative = | 2882 text_alternative = |
2886 RecursiveTextAlternative(*title_ax_object, false, visited); | 2883 RecursiveTextAlternative(*title_ax_object, false, visited); |
2887 if (related_objects) { | 2884 if (related_objects) { |
2888 local_related_objects.push_back( | 2885 local_related_objects.push_back( |
2889 new NameSourceRelatedObject(title_ax_object, text_alternative)); | 2886 new NameSourceRelatedObject(title_ax_object, text_alternative)); |
2890 *related_objects = local_related_objects; | 2887 *related_objects = local_related_objects; |
2891 local_related_objects.clear(); | 2888 local_related_objects.clear(); |
2892 } | 2889 } |
2893 } | 2890 } |
(...skipping 11 matching lines...) Expand all Loading... |
2905 // Fieldset / legend. | 2902 // Fieldset / legend. |
2906 if (isHTMLFieldSetElement(GetNode())) { | 2903 if (isHTMLFieldSetElement(GetNode())) { |
2907 name_from = kAXNameFromRelatedElement; | 2904 name_from = kAXNameFromRelatedElement; |
2908 if (name_sources) { | 2905 if (name_sources) { |
2909 name_sources->push_back(NameSource(*found_text_alternative)); | 2906 name_sources->push_back(NameSource(*found_text_alternative)); |
2910 name_sources->back().type = name_from; | 2907 name_sources->back().type = name_from; |
2911 name_sources->back().native_source = kAXTextFromNativeHTMLLegend; | 2908 name_sources->back().native_source = kAXTextFromNativeHTMLLegend; |
2912 } | 2909 } |
2913 HTMLElement* legend = toHTMLFieldSetElement(GetNode())->Legend(); | 2910 HTMLElement* legend = toHTMLFieldSetElement(GetNode())->Legend(); |
2914 if (legend) { | 2911 if (legend) { |
2915 AXObjectImpl* legend_ax_object = AxObjectCache().GetOrCreate(legend); | 2912 AXObject* legend_ax_object = AxObjectCache().GetOrCreate(legend); |
2916 // Avoid an infinite loop | 2913 // Avoid an infinite loop |
2917 if (legend_ax_object && !visited.Contains(legend_ax_object)) { | 2914 if (legend_ax_object && !visited.Contains(legend_ax_object)) { |
2918 text_alternative = | 2915 text_alternative = |
2919 RecursiveTextAlternative(*legend_ax_object, false, visited); | 2916 RecursiveTextAlternative(*legend_ax_object, false, visited); |
2920 | 2917 |
2921 if (related_objects) { | 2918 if (related_objects) { |
2922 local_related_objects.push_back( | 2919 local_related_objects.push_back( |
2923 new NameSourceRelatedObject(legend_ax_object, text_alternative)); | 2920 new NameSourceRelatedObject(legend_ax_object, text_alternative)); |
2924 *related_objects = local_related_objects; | 2921 *related_objects = local_related_objects; |
2925 local_related_objects.clear(); | 2922 local_related_objects.clear(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2967 name_from = kAXNameFromRelatedElement; | 2964 name_from = kAXNameFromRelatedElement; |
2968 if (name_sources) { | 2965 if (name_sources) { |
2969 name_sources->push_back(NameSource(*found_text_alternative)); | 2966 name_sources->push_back(NameSource(*found_text_alternative)); |
2970 name_sources->back().type = name_from; | 2967 name_sources->back().type = name_from; |
2971 name_sources->back().native_source = kAXTextFromNativeHTMLTitleElement; | 2968 name_sources->back().native_source = kAXTextFromNativeHTMLTitleElement; |
2972 } | 2969 } |
2973 | 2970 |
2974 text_alternative = document->title(); | 2971 text_alternative = document->title(); |
2975 | 2972 |
2976 Element* title_element = document->TitleElement(); | 2973 Element* title_element = document->TitleElement(); |
2977 AXObjectImpl* title_ax_object = | 2974 AXObject* title_ax_object = AxObjectCache().GetOrCreate(title_element); |
2978 AxObjectCache().GetOrCreate(title_element); | |
2979 if (title_ax_object) { | 2975 if (title_ax_object) { |
2980 if (related_objects) { | 2976 if (related_objects) { |
2981 local_related_objects.push_back( | 2977 local_related_objects.push_back( |
2982 new NameSourceRelatedObject(title_ax_object, text_alternative)); | 2978 new NameSourceRelatedObject(title_ax_object, text_alternative)); |
2983 *related_objects = local_related_objects; | 2979 *related_objects = local_related_objects; |
2984 local_related_objects.clear(); | 2980 local_related_objects.clear(); |
2985 } | 2981 } |
2986 | 2982 |
2987 if (name_sources) { | 2983 if (name_sources) { |
2988 NameSource& source = name_sources->back(); | 2984 NameSource& source = name_sources->back(); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3095 | 3091 |
3096 description_from = kAXDescriptionFromRelatedElement; | 3092 description_from = kAXDescriptionFromRelatedElement; |
3097 if (description_sources) { | 3093 if (description_sources) { |
3098 description_sources->push_back(DescriptionSource(found_description)); | 3094 description_sources->push_back(DescriptionSource(found_description)); |
3099 description_sources->back().type = description_from; | 3095 description_sources->back().type = description_from; |
3100 description_sources->back().native_source = | 3096 description_sources->back().native_source = |
3101 kAXTextFromNativeHTMLTableCaption; | 3097 kAXTextFromNativeHTMLTableCaption; |
3102 } | 3098 } |
3103 HTMLTableCaptionElement* caption = table_element->caption(); | 3099 HTMLTableCaptionElement* caption = table_element->caption(); |
3104 if (caption) { | 3100 if (caption) { |
3105 AXObjectImpl* caption_ax_object = AxObjectCache().GetOrCreate(caption); | 3101 AXObject* caption_ax_object = AxObjectCache().GetOrCreate(caption); |
3106 if (caption_ax_object) { | 3102 if (caption_ax_object) { |
3107 AXObjectSet visited; | 3103 AXObjectSet visited; |
3108 description = | 3104 description = |
3109 RecursiveTextAlternative(*caption_ax_object, false, visited); | 3105 RecursiveTextAlternative(*caption_ax_object, false, visited); |
3110 if (related_objects) | 3106 if (related_objects) |
3111 related_objects->push_back( | 3107 related_objects->push_back( |
3112 new NameSourceRelatedObject(caption_ax_object, description)); | 3108 new NameSourceRelatedObject(caption_ax_object, description)); |
3113 | 3109 |
3114 if (description_sources) { | 3110 if (description_sources) { |
3115 DescriptionSource& source = description_sources->back(); | 3111 DescriptionSource& source = description_sources->back(); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3226 | 3222 |
3227 String AXNodeObject::PlaceholderFromNativeAttribute() const { | 3223 String AXNodeObject::PlaceholderFromNativeAttribute() const { |
3228 Node* node = GetNode(); | 3224 Node* node = GetNode(); |
3229 if (!node || !IsTextControlElement(node)) | 3225 if (!node || !IsTextControlElement(node)) |
3230 return String(); | 3226 return String(); |
3231 return ToTextControlElement(node)->StrippedPlaceholder(); | 3227 return ToTextControlElement(node)->StrippedPlaceholder(); |
3232 } | 3228 } |
3233 | 3229 |
3234 DEFINE_TRACE(AXNodeObject) { | 3230 DEFINE_TRACE(AXNodeObject) { |
3235 visitor->Trace(node_); | 3231 visitor->Trace(node_); |
3236 AXObjectImpl::Trace(visitor); | 3232 AXObject::Trace(visitor); |
3237 } | 3233 } |
3238 | 3234 |
3239 } // namespace blink | 3235 } // namespace blink |
OLD | NEW |