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

Side by Side Diff: third_party/WebKit/Source/core/dom/AccessibleNode.cpp

Issue 2967193003: Relation list properties for Accessibility Object Model phase 1 (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/dom/AccessibleNode.h" 5 #include "core/dom/AccessibleNode.h"
6 6
7 #include "core/dom/AXObjectCache.h" 7 #include "core/dom/AXObjectCache.h"
8 #include "core/dom/AccessibleNodeList.h"
8 #include "core/dom/Element.h" 9 #include "core/dom/Element.h"
9 #include "core/dom/QualifiedName.h" 10 #include "core/dom/QualifiedName.h"
10 #include "core/frame/Settings.h" 11 #include "core/frame/Settings.h"
11 12
12 namespace blink { 13 namespace blink {
13 14
14 using namespace HTMLNames; 15 using namespace HTMLNames;
15 16
16 namespace { 17 namespace {
17 18
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 break; 64 break;
64 case AOMRelationProperty::kErrorMessage: 65 case AOMRelationProperty::kErrorMessage:
65 return aria_errormessageAttr; 66 return aria_errormessageAttr;
66 break; 67 break;
67 } 68 }
68 69
69 NOTREACHED(); 70 NOTREACHED();
70 return g_null_name; 71 return g_null_name;
71 } 72 }
72 73
74 QualifiedName GetCorrespondingARIAAttribute(AOMRelationListProperty property) {
75 switch (property) {
76 case AOMRelationListProperty::kDescribedBy:
77 return aria_describedbyAttr;
78 break;
79 case AOMRelationListProperty::kControls:
80 return aria_controlsAttr;
81 break;
82 case AOMRelationListProperty::kFlowTo:
83 return aria_flowtoAttr;
84 break;
85 case AOMRelationListProperty::kLabeledBy:
86 // Note that there are two valid spellings of this attribute.
aboxhall 2017/07/06 05:37:14 Perhaps "allowed" instead of "valid"?
dmazzoni 2017/07/06 06:34:25 Done.
87 // Callers should check both.
88 return aria_labeledbyAttr;
aboxhall 2017/07/06 05:37:14 I think we should prefer the English spelling here
dmazzoni 2017/07/06 06:34:25 Done, I flipped a couple other places in this file
89 break;
90 case AOMRelationListProperty::kOwns:
91 return aria_ownsAttr;
92 break;
93 }
94
95 NOTREACHED();
96 return g_null_name;
97 }
98
73 QualifiedName GetCorrespondingARIAAttribute(AOMBooleanProperty property) { 99 QualifiedName GetCorrespondingARIAAttribute(AOMBooleanProperty property) {
74 switch (property) { 100 switch (property) {
75 case AOMBooleanProperty::kAtomic: 101 case AOMBooleanProperty::kAtomic:
76 return aria_atomicAttr; 102 return aria_atomicAttr;
77 break; 103 break;
78 case AOMBooleanProperty::kBusy: 104 case AOMBooleanProperty::kBusy:
79 return aria_busyAttr; 105 return aria_busyAttr;
80 break; 106 break;
81 case AOMBooleanProperty::kDisabled: 107 case AOMBooleanProperty::kDisabled:
82 return aria_disabledAttr; 108 return aria_disabledAttr;
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 if (AccessibleNode* accessible_node = element->ExistingAccessibleNode()) { 231 if (AccessibleNode* accessible_node = element->ExistingAccessibleNode()) {
206 for (const auto& item : accessible_node->relation_properties_) { 232 for (const auto& item : accessible_node->relation_properties_) {
207 if (item.first == property && item.second) 233 if (item.first == property && item.second)
208 return item.second; 234 return item.second;
209 } 235 }
210 } 236 }
211 237
212 return nullptr; 238 return nullptr;
213 } 239 }
214 240
241 // static
242 AccessibleNodeList* AccessibleNode::GetProperty(
243 Element* element,
244 AOMRelationListProperty property) {
245 if (!element)
246 return nullptr;
247
248 if (AccessibleNode* accessible_node = element->ExistingAccessibleNode()) {
249 for (const auto& item : accessible_node->relation_list_properties_) {
250 if (item.first == property && item.second)
251 return item.second;
252 }
253 }
254
255 return nullptr;
256 }
257
258 // static
259 bool AccessibleNode::GetProperty(Element* element,
260 AOMRelationListProperty property,
261 HeapVector<Member<Element>>& targets) {
262 AccessibleNodeList* node_list = GetProperty(element, property);
263 if (!node_list)
264 return false;
265
266 for (size_t i = 0; i < node_list->length(); ++i) {
267 AccessibleNode* accessible_node = node_list->item(i);
268 if (accessible_node) {
269 Element* element = accessible_node->element();
270 if (element)
271 targets.push_back(element);
272 }
273 }
274
275 return true;
276 }
277
215 template <typename P, typename T> 278 template <typename P, typename T>
216 static T FindPropertyValue(P property, 279 static T FindPropertyValue(P property,
217 bool& is_null, 280 bool& is_null,
218 Vector<std::pair<P, T>>& properties, 281 Vector<std::pair<P, T>>& properties,
219 T default_value) { 282 T default_value) {
220 for (const auto& item : properties) { 283 for (const auto& item : properties) {
221 if (item.first == property) { 284 if (item.first == property) {
222 is_null = false; 285 is_null = false;
223 return item.second; 286 return item.second;
224 } 287 }
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 QualifiedName attribute = GetCorrespondingARIAAttribute(property); 380 QualifiedName attribute = GetCorrespondingARIAAttribute(property);
318 AtomicString value = element->FastGetAttribute(attribute); 381 AtomicString value = element->FastGetAttribute(attribute);
319 Element* target = element->GetTreeScope().getElementById(value); 382 Element* target = element->GetTreeScope().getElementById(value);
320 if (!target) 383 if (!target)
321 return nullptr; 384 return nullptr;
322 385
323 return target->accessibleNode(); 386 return target->accessibleNode();
324 } 387 }
325 388
326 // static 389 // static
390 bool AccessibleNode::GetPropertyOrARIAAttribute(
391 Element* element,
392 AOMRelationListProperty property,
393 HeapVector<Member<Element>>& targets) {
394 if (!element)
395 return false;
396
397 if (GetProperty(element, property, targets))
398 return true;
399
400 // Fall back on the equivalent ARIA attribute.
401 QualifiedName attribute = GetCorrespondingARIAAttribute(property);
402 String value = element->FastGetAttribute(attribute).GetString();
403 if (value.IsEmpty() && property == AOMRelationListProperty::kLabeledBy)
404 value = element->FastGetAttribute(aria_labelledbyAttr).GetString();
405 if (value.IsEmpty())
406 return false;
407
408 value.SimplifyWhiteSpace();
409 Vector<String> ids;
410 value.Split(' ', ids);
411 if (ids.IsEmpty())
412 return false;
413
414 TreeScope& scope = element->GetTreeScope();
415 for (const auto& id : ids) {
416 if (Element* id_element = scope.getElementById(AtomicString(id)))
417 targets.push_back(id_element);
418 }
419 return true;
420 }
421
422 // static
327 bool AccessibleNode::GetPropertyOrARIAAttribute(Element* element, 423 bool AccessibleNode::GetPropertyOrARIAAttribute(Element* element,
328 AOMBooleanProperty property, 424 AOMBooleanProperty property,
329 bool& is_null) { 425 bool& is_null) {
330 is_null = true; 426 is_null = true;
331 if (!element) 427 if (!element)
332 return false; 428 return false;
333 429
334 bool result = GetProperty(element, property, is_null); 430 bool result = GetProperty(element, property, is_null);
335 if (!is_null) 431 if (!is_null)
336 return result; 432 return result;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 } 518 }
423 for (auto& item : accessible_node->int_properties_) { 519 for (auto& item : accessible_node->int_properties_) {
424 client->AddIntProperty(item.first, item.second); 520 client->AddIntProperty(item.first, item.second);
425 shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first)); 521 shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
426 } 522 }
427 for (auto& item : accessible_node->uint_properties_) { 523 for (auto& item : accessible_node->uint_properties_) {
428 client->AddUIntProperty(item.first, item.second); 524 client->AddUIntProperty(item.first, item.second);
429 shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first)); 525 shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
430 } 526 }
431 for (auto& item : accessible_node->relation_properties_) { 527 for (auto& item : accessible_node->relation_properties_) {
528 if (!item.second)
529 continue;
432 client->AddRelationProperty(item.first, *item.second); 530 client->AddRelationProperty(item.first, *item.second);
433 shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first)); 531 shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
434 } 532 }
533 for (auto& item : accessible_node->relation_list_properties_) {
534 if (!item.second)
535 continue;
536 client->AddRelationListProperty(item.first, *item.second);
537 shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
538 }
435 } 539 }
436 540
437 AccessibleNode* AccessibleNode::activeDescendant() const { 541 AccessibleNode* AccessibleNode::activeDescendant() const {
438 return GetProperty(element_, AOMRelationProperty::kActiveDescendant); 542 return GetProperty(element_, AOMRelationProperty::kActiveDescendant);
439 } 543 }
440 544
441 void AccessibleNode::setActiveDescendant(AccessibleNode* active_descendant) { 545 void AccessibleNode::setActiveDescendant(AccessibleNode* active_descendant) {
442 SetRelationProperty(AOMRelationProperty::kActiveDescendant, 546 SetRelationProperty(AOMRelationProperty::kActiveDescendant,
443 active_descendant); 547 active_descendant);
444 NotifyAttributeChanged(aria_activedescendantAttr); 548 NotifyAttributeChanged(aria_activedescendantAttr);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 604
501 uint32_t AccessibleNode::colSpan(bool& is_null) const { 605 uint32_t AccessibleNode::colSpan(bool& is_null) const {
502 return GetProperty(element_, AOMUIntProperty::kColSpan, is_null); 606 return GetProperty(element_, AOMUIntProperty::kColSpan, is_null);
503 } 607 }
504 608
505 void AccessibleNode::setColSpan(uint32_t col_span, bool is_null) { 609 void AccessibleNode::setColSpan(uint32_t col_span, bool is_null) {
506 SetUIntProperty(AOMUIntProperty::kColSpan, col_span, is_null); 610 SetUIntProperty(AOMUIntProperty::kColSpan, col_span, is_null);
507 NotifyAttributeChanged(aria_colspanAttr); 611 NotifyAttributeChanged(aria_colspanAttr);
508 } 612 }
509 613
614 AccessibleNodeList* AccessibleNode::controls() const {
615 return GetProperty(element_, AOMRelationListProperty::kControls);
616 }
617
618 void AccessibleNode::setControls(AccessibleNodeList* controls) {
619 SetRelationListProperty(AOMRelationListProperty::kControls, controls);
620 NotifyAttributeChanged(aria_controlsAttr);
621 }
622
510 AtomicString AccessibleNode::current() const { 623 AtomicString AccessibleNode::current() const {
511 return GetProperty(element_, AOMStringProperty::kCurrent); 624 return GetProperty(element_, AOMStringProperty::kCurrent);
512 } 625 }
513 626
514 void AccessibleNode::setCurrent(const AtomicString& current) { 627 void AccessibleNode::setCurrent(const AtomicString& current) {
515 SetStringProperty(AOMStringProperty::kCurrent, current); 628 SetStringProperty(AOMStringProperty::kCurrent, current);
516 629
517 if (AXObjectCache* cache = element_->GetDocument().ExistingAXObjectCache()) 630 if (AXObjectCache* cache = element_->GetDocument().ExistingAXObjectCache())
518 cache->HandleAttributeChanged(aria_currentAttr, element_); 631 cache->HandleAttributeChanged(aria_currentAttr, element_);
519 } 632 }
520 633
634 AccessibleNodeList* AccessibleNode::describedBy() {
635 return GetProperty(element_, AOMRelationListProperty::kDescribedBy);
636 }
637
638 void AccessibleNode::setDescribedBy(AccessibleNodeList* described_by) {
639 SetRelationListProperty(AOMRelationListProperty::kDescribedBy, described_by);
640 NotifyAttributeChanged(aria_describedbyAttr);
641 }
642
521 AccessibleNode* AccessibleNode::details() const { 643 AccessibleNode* AccessibleNode::details() const {
522 return GetProperty(element_, AOMRelationProperty::kDetails); 644 return GetProperty(element_, AOMRelationProperty::kDetails);
523 } 645 }
524 646
525 void AccessibleNode::setDetails(AccessibleNode* details) { 647 void AccessibleNode::setDetails(AccessibleNode* details) {
526 SetRelationProperty(AOMRelationProperty::kDetails, details); 648 SetRelationProperty(AOMRelationProperty::kDetails, details);
527 NotifyAttributeChanged(aria_detailsAttr); 649 NotifyAttributeChanged(aria_detailsAttr);
528 } 650 }
529 651
530 bool AccessibleNode::disabled(bool& is_null) const { 652 bool AccessibleNode::disabled(bool& is_null) const {
(...skipping 16 matching lines...) Expand all
547 669
548 bool AccessibleNode::expanded(bool& is_null) const { 670 bool AccessibleNode::expanded(bool& is_null) const {
549 return GetProperty(element_, AOMBooleanProperty::kExpanded, is_null); 671 return GetProperty(element_, AOMBooleanProperty::kExpanded, is_null);
550 } 672 }
551 673
552 void AccessibleNode::setExpanded(bool expanded, bool is_null) { 674 void AccessibleNode::setExpanded(bool expanded, bool is_null) {
553 SetBooleanProperty(AOMBooleanProperty::kExpanded, expanded, is_null); 675 SetBooleanProperty(AOMBooleanProperty::kExpanded, expanded, is_null);
554 NotifyAttributeChanged(aria_expandedAttr); 676 NotifyAttributeChanged(aria_expandedAttr);
555 } 677 }
556 678
679 AccessibleNodeList* AccessibleNode::flowTo() const {
680 return GetProperty(element_, AOMRelationListProperty::kFlowTo);
681 }
682
683 void AccessibleNode::setFlowTo(AccessibleNodeList* flow_to) {
684 SetRelationListProperty(AOMRelationListProperty::kFlowTo, flow_to);
685 NotifyAttributeChanged(aria_flowtoAttr);
686 }
687
557 bool AccessibleNode::hidden(bool& is_null) const { 688 bool AccessibleNode::hidden(bool& is_null) const {
558 return GetProperty(element_, AOMBooleanProperty::kHidden, is_null); 689 return GetProperty(element_, AOMBooleanProperty::kHidden, is_null);
559 } 690 }
560 691
561 void AccessibleNode::setHidden(bool hidden, bool is_null) { 692 void AccessibleNode::setHidden(bool hidden, bool is_null) {
562 SetBooleanProperty(AOMBooleanProperty::kHidden, hidden, is_null); 693 SetBooleanProperty(AOMBooleanProperty::kHidden, hidden, is_null);
563 NotifyAttributeChanged(aria_hiddenAttr); 694 NotifyAttributeChanged(aria_hiddenAttr);
564 } 695 }
565 696
566 AtomicString AccessibleNode::invalid() const { 697 AtomicString AccessibleNode::invalid() const {
(...skipping 16 matching lines...) Expand all
583 714
584 AtomicString AccessibleNode::label() const { 715 AtomicString AccessibleNode::label() const {
585 return GetProperty(element_, AOMStringProperty::kLabel); 716 return GetProperty(element_, AOMStringProperty::kLabel);
586 } 717 }
587 718
588 void AccessibleNode::setLabel(const AtomicString& label) { 719 void AccessibleNode::setLabel(const AtomicString& label) {
589 SetStringProperty(AOMStringProperty::kLabel, label); 720 SetStringProperty(AOMStringProperty::kLabel, label);
590 NotifyAttributeChanged(aria_labelAttr); 721 NotifyAttributeChanged(aria_labelAttr);
591 } 722 }
592 723
724 AccessibleNodeList* AccessibleNode::labeledBy() {
725 return GetProperty(element_, AOMRelationListProperty::kLabeledBy);
726 }
727
728 void AccessibleNode::setLabeledBy(AccessibleNodeList* labeled_by) {
729 SetRelationListProperty(AOMRelationListProperty::kLabeledBy, labeled_by);
730 NotifyAttributeChanged(aria_labeledbyAttr);
731 }
732
593 uint32_t AccessibleNode::level(bool& is_null) const { 733 uint32_t AccessibleNode::level(bool& is_null) const {
594 return GetProperty(element_, AOMUIntProperty::kLevel, is_null); 734 return GetProperty(element_, AOMUIntProperty::kLevel, is_null);
595 } 735 }
596 736
597 void AccessibleNode::setLevel(uint32_t level, bool is_null) { 737 void AccessibleNode::setLevel(uint32_t level, bool is_null) {
598 SetUIntProperty(AOMUIntProperty::kLevel, level, is_null); 738 SetUIntProperty(AOMUIntProperty::kLevel, level, is_null);
599 NotifyAttributeChanged(aria_levelAttr); 739 NotifyAttributeChanged(aria_levelAttr);
600 } 740 }
601 741
602 AtomicString AccessibleNode::live() const { 742 AtomicString AccessibleNode::live() const {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 778
639 AtomicString AccessibleNode::orientation() const { 779 AtomicString AccessibleNode::orientation() const {
640 return GetProperty(element_, AOMStringProperty::kOrientation); 780 return GetProperty(element_, AOMStringProperty::kOrientation);
641 } 781 }
642 782
643 void AccessibleNode::setOrientation(const AtomicString& orientation) { 783 void AccessibleNode::setOrientation(const AtomicString& orientation) {
644 SetStringProperty(AOMStringProperty::kOrientation, orientation); 784 SetStringProperty(AOMStringProperty::kOrientation, orientation);
645 NotifyAttributeChanged(aria_orientationAttr); 785 NotifyAttributeChanged(aria_orientationAttr);
646 } 786 }
647 787
788 AccessibleNodeList* AccessibleNode::owns() const {
789 return GetProperty(element_, AOMRelationListProperty::kOwns);
790 }
791
792 void AccessibleNode::setOwns(AccessibleNodeList* owns) {
793 SetRelationListProperty(AOMRelationListProperty::kOwns, owns);
794 NotifyAttributeChanged(aria_ownsAttr);
795 }
796
648 AtomicString AccessibleNode::placeholder() const { 797 AtomicString AccessibleNode::placeholder() const {
649 return GetProperty(element_, AOMStringProperty::kPlaceholder); 798 return GetProperty(element_, AOMStringProperty::kPlaceholder);
650 } 799 }
651 800
652 void AccessibleNode::setPlaceholder(const AtomicString& placeholder) { 801 void AccessibleNode::setPlaceholder(const AtomicString& placeholder) {
653 SetStringProperty(AOMStringProperty::kPlaceholder, placeholder); 802 SetStringProperty(AOMStringProperty::kPlaceholder, placeholder);
654 NotifyAttributeChanged(aria_placeholderAttr); 803 NotifyAttributeChanged(aria_placeholderAttr);
655 } 804 }
656 805
657 uint32_t AccessibleNode::posInSet(bool& is_null) const { 806 uint32_t AccessibleNode::posInSet(bool& is_null) const {
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 for (auto& item : relation_properties_) { 973 for (auto& item : relation_properties_) {
825 if (item.first == property) { 974 if (item.first == property) {
826 item.second = value; 975 item.second = value;
827 return; 976 return;
828 } 977 }
829 } 978 }
830 979
831 relation_properties_.push_back(std::make_pair(property, value)); 980 relation_properties_.push_back(std::make_pair(property, value));
832 } 981 }
833 982
983 void AccessibleNode::SetRelationListProperty(AOMRelationListProperty property,
984 AccessibleNodeList* value) {
985 for (auto& item : relation_list_properties_) {
986 if (item.first == property) {
987 if (item.second)
988 item.second->RemoveOwner(property, this);
989 if (value)
990 value->AddOwner(property, this);
991 item.second = value;
992 return;
993 }
994 }
995
996 relation_list_properties_.push_back(std::make_pair(property, value));
997 }
998
834 template <typename P, typename T> 999 template <typename P, typename T>
835 static void SetProperty(P property, 1000 static void SetProperty(P property,
836 T value, 1001 T value,
837 bool is_null, 1002 bool is_null,
838 Vector<std::pair<P, T>>& properties) { 1003 Vector<std::pair<P, T>>& properties) {
839 for (size_t i = 0; i < properties.size(); i++) { 1004 for (size_t i = 0; i < properties.size(); i++) {
840 auto& item = properties[i]; 1005 auto& item = properties[i];
841 if (item.first == property) { 1006 if (item.first == property) {
842 if (is_null) 1007 if (is_null)
843 properties.erase(i); 1008 properties.erase(i);
(...skipping 23 matching lines...) Expand all
867 bool is_null) { 1032 bool is_null) {
868 SetProperty(property, value, is_null, uint_properties_); 1033 SetProperty(property, value, is_null, uint_properties_);
869 } 1034 }
870 1035
871 void AccessibleNode::SetFloatProperty(AOMFloatProperty property, 1036 void AccessibleNode::SetFloatProperty(AOMFloatProperty property,
872 float value, 1037 float value,
873 bool is_null) { 1038 bool is_null) {
874 SetProperty(property, value, is_null, float_properties_); 1039 SetProperty(property, value, is_null, float_properties_);
875 } 1040 }
876 1041
1042 void AccessibleNode::OnRelationListChanged(AOMRelationListProperty property) {
1043 NotifyAttributeChanged(GetCorrespondingARIAAttribute(property));
1044 }
1045
877 void AccessibleNode::NotifyAttributeChanged( 1046 void AccessibleNode::NotifyAttributeChanged(
878 const blink::QualifiedName& attribute) { 1047 const blink::QualifiedName& attribute) {
879 // TODO(dmazzoni): Make a cleaner API for this rather than pretending 1048 // TODO(dmazzoni): Make a cleaner API for this rather than pretending
880 // the DOM attribute changed. 1049 // the DOM attribute changed.
881 if (AXObjectCache* cache = GetAXObjectCache()) 1050 if (AXObjectCache* cache = GetAXObjectCache())
882 cache->HandleAttributeChanged(attribute, element_); 1051 cache->HandleAttributeChanged(attribute, element_);
883 } 1052 }
884 1053
885 AXObjectCache* AccessibleNode::GetAXObjectCache() { 1054 AXObjectCache* AccessibleNode::GetAXObjectCache() {
886 return element_->GetDocument().ExistingAXObjectCache(); 1055 return element_->GetDocument().ExistingAXObjectCache();
887 } 1056 }
888 1057
889 DEFINE_TRACE(AccessibleNode) { 1058 DEFINE_TRACE(AccessibleNode) {
890 visitor->Trace(element_); 1059 visitor->Trace(element_);
891 visitor->Trace(relation_properties_); 1060 visitor->Trace(relation_properties_);
1061 visitor->Trace(relation_list_properties_);
892 } 1062 }
893 1063
894 } // namespace blink 1064 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698