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 12 matching lines...) Expand all Loading... |
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 */ | 27 */ |
28 | 28 |
29 #include "modules/accessibility/AXNodeObject.h" | 29 #include "modules/accessibility/AXNodeObject.h" |
30 | 30 |
31 #include "core/InputTypeNames.h" | 31 #include "core/InputTypeNames.h" |
32 #include "core/dom/AccessibleNode.h" | 32 #include "core/dom/AccessibleNode.h" |
| 33 #include "core/dom/AccessibleNodeList.h" |
33 #include "core/dom/Element.h" | 34 #include "core/dom/Element.h" |
34 #include "core/dom/FlatTreeTraversal.h" | 35 #include "core/dom/FlatTreeTraversal.h" |
35 #include "core/dom/NodeTraversal.h" | 36 #include "core/dom/NodeTraversal.h" |
36 #include "core/dom/QualifiedName.h" | 37 #include "core/dom/QualifiedName.h" |
37 #include "core/dom/Text.h" | 38 #include "core/dom/Text.h" |
38 #include "core/dom/UserGestureIndicator.h" | 39 #include "core/dom/UserGestureIndicator.h" |
39 #include "core/editing/EditingUtilities.h" | 40 #include "core/editing/EditingUtilities.h" |
40 #include "core/editing/markers/DocumentMarkerController.h" | 41 #include "core/editing/markers/DocumentMarkerController.h" |
41 #include "core/frame/LocalFrameView.h" | 42 #include "core/frame/LocalFrameView.h" |
42 #include "core/html/HTMLAnchorElement.h" | 43 #include "core/html/HTMLAnchorElement.h" |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 default: | 262 default: |
262 return; | 263 return; |
263 } | 264 } |
264 | 265 |
265 Element* target_element = value.element(); | 266 Element* target_element = value.element(); |
266 AXObject* target_obj = ax_object_cache_->GetOrCreate(target_element); | 267 AXObject* target_obj = ax_object_cache_->GetOrCreate(target_element); |
267 if (target_element) | 268 if (target_element) |
268 sparse_attribute_client_.AddObjectAttribute(attribute, *target_obj); | 269 sparse_attribute_client_.AddObjectAttribute(attribute, *target_obj); |
269 } | 270 } |
270 | 271 |
| 272 void AddRelationListProperty(AOMRelationListProperty property, |
| 273 const AccessibleNodeList& relations) override { |
| 274 AXObjectVectorAttribute attribute; |
| 275 switch (property) { |
| 276 case AOMRelationListProperty::kControls: |
| 277 attribute = AXObjectVectorAttribute::kAriaControls; |
| 278 break; |
| 279 case AOMRelationListProperty::kFlowTo: |
| 280 attribute = AXObjectVectorAttribute::kAriaFlowTo; |
| 281 break; |
| 282 default: |
| 283 return; |
| 284 } |
| 285 |
| 286 HeapVector<Member<AXObject>> objects; |
| 287 for (size_t i = 0; i < relations.length(); ++i) { |
| 288 AccessibleNode* accessible_node = relations.item(i); |
| 289 if (accessible_node) { |
| 290 Element* element = accessible_node->element(); |
| 291 AXObject* ax_element = ax_object_cache_->GetOrCreate(element); |
| 292 if (ax_element && !ax_element->AccessibilityIsIgnored()) |
| 293 objects.push_back(ax_element); |
| 294 } |
| 295 } |
| 296 |
| 297 sparse_attribute_client_.AddObjectVectorAttribute(attribute, objects); |
| 298 } |
| 299 |
271 private: | 300 private: |
272 Persistent<AXObjectCacheImpl> ax_object_cache_; | 301 Persistent<AXObjectCacheImpl> ax_object_cache_; |
273 AXSparseAttributeClient& sparse_attribute_client_; | 302 AXSparseAttributeClient& sparse_attribute_client_; |
274 }; | 303 }; |
275 | 304 |
276 AXNodeObject::AXNodeObject(Node* node, AXObjectCacheImpl& ax_object_cache) | 305 AXNodeObject::AXNodeObject(Node* node, AXObjectCacheImpl& ax_object_cache) |
277 : AXObject(ax_object_cache), | 306 : AXObject(ax_object_cache), |
278 aria_role_(kUnknownRole), | 307 aria_role_(kUnknownRole), |
279 children_dirty_(false), | 308 children_dirty_(false), |
280 node_(node) {} | 309 node_(node) {} |
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 role = ButtonRoleType(); | 795 role = ButtonRoleType(); |
767 | 796 |
768 role = RemapAriaRoleDueToParent(role); | 797 role = RemapAriaRoleDueToParent(role); |
769 | 798 |
770 if (role) | 799 if (role) |
771 return role; | 800 return role; |
772 | 801 |
773 return kUnknownRole; | 802 return kUnknownRole; |
774 } | 803 } |
775 | 804 |
776 void AXNodeObject::AccessibilityChildrenFromAttribute( | 805 void AXNodeObject::AccessibilityChildrenFromAOMProperty( |
777 QualifiedName attr, | 806 AOMRelationListProperty property, |
778 AXObject::AXObjectVector& children) const { | 807 AXObject::AXObjectVector& children) const { |
779 HeapVector<Member<Element>> elements; | 808 HeapVector<Member<Element>> elements; |
780 ElementsFromAttribute(elements, attr); | 809 if (!HasAOMPropertyOrARIAAttribute(property, elements)) |
| 810 return; |
781 | 811 |
782 AXObjectCacheImpl& cache = AxObjectCache(); | 812 AXObjectCacheImpl& cache = AxObjectCache(); |
783 for (const auto& element : elements) { | 813 for (const auto& element : elements) { |
784 if (AXObject* child = cache.GetOrCreate(element)) { | 814 if (AXObject* child = cache.GetOrCreate(element)) { |
785 // Only aria-labelledby and aria-describedby can target hidden elements. | 815 // Only aria-labelledby and aria-describedby can target hidden elements. |
786 if (child->AccessibilityIsIgnored() && attr != aria_labelledbyAttr && | 816 if (child->AccessibilityIsIgnored() && |
787 attr != aria_labeledbyAttr && attr != aria_describedbyAttr) { | 817 property != AOMRelationListProperty::kLabeledBy && |
| 818 property != AOMRelationListProperty::kDescribedBy) { |
788 continue; | 819 continue; |
789 } | 820 } |
790 children.push_back(child); | 821 children.push_back(child); |
791 } | 822 } |
792 } | 823 } |
793 } | 824 } |
794 | 825 |
795 // This only returns true if this is the element that actually has the | 826 // This only returns true if this is the element that actually has the |
796 // contentEditable attribute set, unlike node->hasEditableStyle() which will | 827 // contentEditable attribute set, unlike node->hasEditableStyle() which will |
797 // also return true if an ancestor is editable. | 828 // also return true if an ancestor is editable. |
(...skipping 1731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2529 bool ignored_status = AccessibilityIsIgnored(); | 2560 bool ignored_status = AccessibilityIsIgnored(); |
2530 | 2561 |
2531 // The AX hierarchy only needs to be updated if the ignored status of an | 2562 // The AX hierarchy only needs to be updated if the ignored status of an |
2532 // element has changed. | 2563 // element has changed. |
2533 if (ignored_status != AccessibilityIsIgnored()) | 2564 if (ignored_status != AccessibilityIsIgnored()) |
2534 ChildrenChanged(); | 2565 ChildrenChanged(); |
2535 } | 2566 } |
2536 | 2567 |
2537 void AXNodeObject::ComputeAriaOwnsChildren( | 2568 void AXNodeObject::ComputeAriaOwnsChildren( |
2538 HeapVector<Member<AXObject>>& owned_children) const { | 2569 HeapVector<Member<AXObject>>& owned_children) const { |
| 2570 Vector<String> id_vector; |
| 2571 if (!CanHaveChildren() || IsNativeTextControl() || |
| 2572 HasContentEditableAttributeSet()) { |
| 2573 AxObjectCache().UpdateAriaOwns(this, id_vector, owned_children); |
| 2574 return; |
| 2575 } |
| 2576 |
| 2577 HeapVector<Member<Element>> elements; |
| 2578 if (HasAOMProperty(AOMRelationListProperty::kOwns, elements)) { |
| 2579 AxObjectCache().UpdateAriaOwns(this, id_vector, owned_children); |
| 2580 |
| 2581 for (const auto& element : elements) { |
| 2582 AXObject* ax_element = ax_object_cache_->GetOrCreate(&*element); |
| 2583 if (ax_element && !ax_element->AccessibilityIsIgnored()) |
| 2584 owned_children.push_back(ax_element); |
| 2585 } |
| 2586 |
| 2587 return; |
| 2588 } |
| 2589 |
2539 if (!HasAttribute(aria_ownsAttr)) | 2590 if (!HasAttribute(aria_ownsAttr)) |
2540 return; | 2591 return; |
2541 | 2592 |
2542 Vector<String> id_vector; | 2593 TokenVectorFromAttribute(id_vector, aria_ownsAttr); |
2543 if (CanHaveChildren() && !IsNativeTextControl() && | |
2544 !HasContentEditableAttributeSet()) | |
2545 TokenVectorFromAttribute(id_vector, aria_ownsAttr); | |
2546 | |
2547 AxObjectCache().UpdateAriaOwns(this, id_vector, owned_children); | 2594 AxObjectCache().UpdateAriaOwns(this, id_vector, owned_children); |
2548 } | 2595 } |
2549 | 2596 |
2550 // Based on | 2597 // Based on |
2551 // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessible-name-and-
description-calculation | 2598 // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessible-name-and-
description-calculation |
2552 String AXNodeObject::NativeTextAlternative( | 2599 String AXNodeObject::NativeTextAlternative( |
2553 AXObjectSet& visited, | 2600 AXObjectSet& visited, |
2554 AXNameFrom& name_from, | 2601 AXNameFrom& name_from, |
2555 AXRelatedObjectVector* related_objects, | 2602 AXRelatedObjectVector* related_objects, |
2556 NameSources* name_sources, | 2603 NameSources* name_sources, |
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3061 | 3108 |
3062 description_from = kAXDescriptionFromRelatedElement; | 3109 description_from = kAXDescriptionFromRelatedElement; |
3063 if (description_sources) { | 3110 if (description_sources) { |
3064 description_sources->push_back( | 3111 description_sources->push_back( |
3065 DescriptionSource(found_description, aria_describedbyAttr)); | 3112 DescriptionSource(found_description, aria_describedbyAttr)); |
3066 description_sources->back().type = description_from; | 3113 description_sources->back().type = description_from; |
3067 } | 3114 } |
3068 | 3115 |
3069 // aria-describedby overrides any other accessible description, from: | 3116 // aria-describedby overrides any other accessible description, from: |
3070 // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html | 3117 // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html |
| 3118 // AOM version. |
| 3119 HeapVector<Member<Element>> elements; |
| 3120 if (HasAOMProperty(AOMRelationListProperty::kDescribedBy, elements)) { |
| 3121 AXObjectSet visited; |
| 3122 description = TextFromElements(true, visited, elements, related_objects); |
| 3123 if (!description.IsNull()) { |
| 3124 if (description_sources) { |
| 3125 DescriptionSource& source = description_sources->back(); |
| 3126 source.type = description_from; |
| 3127 source.related_objects = *related_objects; |
| 3128 source.text = description; |
| 3129 found_description = true; |
| 3130 } else { |
| 3131 return description; |
| 3132 } |
| 3133 } else if (description_sources) { |
| 3134 description_sources->back().invalid = true; |
| 3135 } |
| 3136 } |
| 3137 |
| 3138 // aria-describedby overrides any other accessible description, from: |
| 3139 // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html |
3071 const AtomicString& aria_describedby = GetAttribute(aria_describedbyAttr); | 3140 const AtomicString& aria_describedby = GetAttribute(aria_describedbyAttr); |
3072 if (!aria_describedby.IsNull()) { | 3141 if (!aria_describedby.IsNull()) { |
3073 if (description_sources) | 3142 if (description_sources) |
3074 description_sources->back().attribute_value = aria_describedby; | 3143 description_sources->back().attribute_value = aria_describedby; |
3075 | 3144 |
3076 description = TextFromAriaDescribedby(related_objects); | 3145 description = TextFromAriaDescribedby(related_objects); |
3077 | 3146 |
3078 if (!description.IsNull()) { | 3147 if (!description.IsNull()) { |
3079 if (description_sources) { | 3148 if (description_sources) { |
3080 DescriptionSource& source = description_sources->back(); | 3149 DescriptionSource& source = description_sources->back(); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3258 return String(); | 3327 return String(); |
3259 return ToTextControlElement(node)->StrippedPlaceholder(); | 3328 return ToTextControlElement(node)->StrippedPlaceholder(); |
3260 } | 3329 } |
3261 | 3330 |
3262 DEFINE_TRACE(AXNodeObject) { | 3331 DEFINE_TRACE(AXNodeObject) { |
3263 visitor->Trace(node_); | 3332 visitor->Trace(node_); |
3264 AXObject::Trace(visitor); | 3333 AXObject::Trace(visitor); |
3265 } | 3334 } |
3266 | 3335 |
3267 } // namespace blink | 3336 } // namespace blink |
OLD | NEW |