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

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

Issue 2788523002: Finish all string attributes for Accessibility Object Model Phase 1. (Closed)
Patch Set: Test that checked works with true/false, not only 'true' and 'false' Created 3 years, 8 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 /* 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 799 matching lines...) Expand 10 before | Expand all | Expand 10 after
810 return 0; 810 return 0;
811 } 811 }
812 812
813 static Element* siblingWithAriaRole(String role, Node* node) { 813 static Element* siblingWithAriaRole(String role, Node* node) {
814 Node* parent = node->parentNode(); 814 Node* parent = node->parentNode();
815 if (!parent) 815 if (!parent)
816 return 0; 816 return 0;
817 817
818 for (Element* sibling = ElementTraversal::firstChild(*parent); sibling; 818 for (Element* sibling = ElementTraversal::firstChild(*parent); sibling;
819 sibling = ElementTraversal::nextSibling(*sibling)) { 819 sibling = ElementTraversal::nextSibling(*sibling)) {
820 const AtomicString& siblingAriaRole = sibling->getAttribute(roleAttr); 820 const AtomicString& siblingAriaRole =
821 AccessibleNode::getProperty(sibling, AOMStringProperty::kRole);
821 if (equalIgnoringCase(siblingAriaRole, role)) 822 if (equalIgnoringCase(siblingAriaRole, role))
822 return sibling; 823 return sibling;
823 } 824 }
824 825
825 return 0; 826 return 0;
826 } 827 }
827 828
828 Element* AXNodeObject::menuItemElementForMenu() const { 829 Element* AXNodeObject::menuItemElementForMenu() const {
829 if (ariaRoleAttribute() != MenuRole) 830 if (ariaRoleAttribute() != MenuRole)
830 return 0; 831 return 0;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
915 return; 916 return;
916 917
917 AXSparseAttributeSetterMap& axSparseAttributeSetterMap = 918 AXSparseAttributeSetterMap& axSparseAttributeSetterMap =
918 getSparseAttributeSetterMap(); 919 getSparseAttributeSetterMap();
919 AttributeCollection attributes = toElement(node)->attributesWithoutUpdate(); 920 AttributeCollection attributes = toElement(node)->attributesWithoutUpdate();
920 for (const Attribute& attr : attributes) { 921 for (const Attribute& attr : attributes) {
921 SparseAttributeSetter* setter = axSparseAttributeSetterMap.at(attr.name()); 922 SparseAttributeSetter* setter = axSparseAttributeSetterMap.at(attr.name());
922 if (setter) 923 if (setter)
923 setter->run(*this, sparseAttributeClient, attr.value()); 924 setter->run(*this, sparseAttributeClient, attr.value());
924 } 925 }
926
927 // TODO(dmazzoni): Efficiently iterate over AccessibleNode properties that are
928 // set and merge the two loops somehow.
929 if (toElement(node)->existingAccessibleNode()) {
930 AtomicString keyShortcuts =
931 getAOMPropertyOrARIAAttribute(AOMStringProperty::kKeyShortcuts);
932 if (!keyShortcuts.isNull()) {
933 axSparseAttributeSetterMap.at(aria_keyshortcutsAttr)
934 ->run(*this, sparseAttributeClient, keyShortcuts);
935 }
936 AtomicString roleDescription =
937 getAOMPropertyOrARIAAttribute(AOMStringProperty::kRoleDescription);
938 if (!roleDescription.isNull()) {
939 axSparseAttributeSetterMap.at(aria_roledescriptionAttr)
940 ->run(*this, sparseAttributeClient, roleDescription);
941 }
942 }
925 } 943 }
926 944
927 bool AXNodeObject::isAnchor() const { 945 bool AXNodeObject::isAnchor() const {
928 return !isNativeImage() && isLink(); 946 return !isNativeImage() && isLink();
929 } 947 }
930 948
931 bool AXNodeObject::isControl() const { 949 bool AXNodeObject::isControl() const {
932 Node* node = this->getNode(); 950 Node* node = this->getNode();
933 if (!node) 951 if (!node)
934 return false; 952 return false;
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1106 return toHTMLInputElement(*node).shouldAppearChecked(); 1124 return toHTMLInputElement(*node).shouldAppearChecked();
1107 1125
1108 // Else, if this is an ARIA role checkbox or radio or menuitemcheckbox 1126 // Else, if this is an ARIA role checkbox or radio or menuitemcheckbox
1109 // or menuitemradio or switch, respect the aria-checked attribute 1127 // or menuitemradio or switch, respect the aria-checked attribute
1110 switch (ariaRoleAttribute()) { 1128 switch (ariaRoleAttribute()) {
1111 case CheckBoxRole: 1129 case CheckBoxRole:
1112 case MenuItemCheckBoxRole: 1130 case MenuItemCheckBoxRole:
1113 case MenuItemRadioRole: 1131 case MenuItemRadioRole:
1114 case RadioButtonRole: 1132 case RadioButtonRole:
1115 case SwitchRole: 1133 case SwitchRole:
1116 if (equalIgnoringCase(getAttribute(aria_checkedAttr), "true")) 1134 if (equalIgnoringCase(
1135 getAOMPropertyOrARIAAttribute(AOMStringProperty::kChecked),
1136 "true"))
1117 return true; 1137 return true;
1118 return false; 1138 return false;
1119 default: 1139 default:
1120 break; 1140 break;
1121 } 1141 }
1122 1142
1123 // Otherwise it's not checked 1143 // Otherwise it's not checked
1124 return false; 1144 return false;
1125 } 1145 }
1126 1146
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
1368 } 1388 }
1369 1389
1370 return level; 1390 return level;
1371 } 1391 }
1372 1392
1373 String AXNodeObject::ariaAutoComplete() const { 1393 String AXNodeObject::ariaAutoComplete() const {
1374 if (roleValue() != ComboBoxRole) 1394 if (roleValue() != ComboBoxRole)
1375 return String(); 1395 return String();
1376 1396
1377 const AtomicString& ariaAutoComplete = 1397 const AtomicString& ariaAutoComplete =
1378 getAttribute(aria_autocompleteAttr).lower(); 1398 getAOMPropertyOrARIAAttribute(AOMStringProperty::kAutocomplete).lower();
1379 1399
1380 if (ariaAutoComplete == "inline" || ariaAutoComplete == "list" || 1400 if (ariaAutoComplete == "inline" || ariaAutoComplete == "list" ||
1381 ariaAutoComplete == "both") 1401 ariaAutoComplete == "both")
1382 return ariaAutoComplete; 1402 return ariaAutoComplete;
1383 1403
1384 return String(); 1404 return String();
1385 } 1405 }
1386 1406
1387 void AXNodeObject::markers(Vector<DocumentMarker::MarkerType>& markerTypes, 1407 void AXNodeObject::markers(Vector<DocumentMarker::MarkerType>& markerTypes,
1388 Vector<AXRange>& markerRanges) const { 1408 Vector<AXRange>& markerRanges) const {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1430 TreeScope& treeScope = anchor->treeScope(); 1450 TreeScope& treeScope = anchor->treeScope();
1431 Element* target = treeScope.findAnchor(fragment); 1451 Element* target = treeScope.findAnchor(fragment);
1432 if (!target) 1452 if (!target)
1433 return AXObject::inPageLinkTarget(); 1453 return AXObject::inPageLinkTarget();
1434 // If the target is not in the accessibility tree, get the first unignored 1454 // If the target is not in the accessibility tree, get the first unignored
1435 // sibling. 1455 // sibling.
1436 return axObjectCache().firstAccessibleObjectFromNode(target); 1456 return axObjectCache().firstAccessibleObjectFromNode(target);
1437 } 1457 }
1438 1458
1439 AccessibilityOrientation AXNodeObject::orientation() const { 1459 AccessibilityOrientation AXNodeObject::orientation() const {
1440 const AtomicString& ariaOrientation = getAttribute(aria_orientationAttr); 1460 const AtomicString& ariaOrientation =
1461 getAOMPropertyOrARIAAttribute(AOMStringProperty::kOrientation);
1441 AccessibilityOrientation orientation = AccessibilityOrientationUndefined; 1462 AccessibilityOrientation orientation = AccessibilityOrientationUndefined;
1442 if (equalIgnoringCase(ariaOrientation, "horizontal")) 1463 if (equalIgnoringCase(ariaOrientation, "horizontal"))
1443 orientation = AccessibilityOrientationHorizontal; 1464 orientation = AccessibilityOrientationHorizontal;
1444 else if (equalIgnoringCase(ariaOrientation, "vertical")) 1465 else if (equalIgnoringCase(ariaOrientation, "vertical"))
1445 orientation = AccessibilityOrientationVertical; 1466 orientation = AccessibilityOrientationVertical;
1446 1467
1447 switch (roleValue()) { 1468 switch (roleValue()) {
1448 case ComboBoxRole: 1469 case ComboBoxRole:
1449 case ListBoxRole: 1470 case ListBoxRole:
1450 case MenuRole: 1471 case MenuRole:
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1576 return AXObject::colorValue(); 1597 return AXObject::colorValue();
1577 1598
1578 // HTMLInputElement::value always returns a string parseable by Color. 1599 // HTMLInputElement::value always returns a string parseable by Color.
1579 Color color; 1600 Color color;
1580 bool success = color.setFromString(input->value()); 1601 bool success = color.setFromString(input->value());
1581 DCHECK(success); 1602 DCHECK(success);
1582 return color.rgb(); 1603 return color.rgb();
1583 } 1604 }
1584 1605
1585 AriaCurrentState AXNodeObject::ariaCurrentState() const { 1606 AriaCurrentState AXNodeObject::ariaCurrentState() const {
1586 if (!hasAttribute(aria_currentAttr)) 1607 const AtomicString& attributeValue =
1587 return AXObject::ariaCurrentState(); 1608 getAOMPropertyOrARIAAttribute(AOMStringProperty::kCurrent);
1588 1609 if (attributeValue.isNull())
1589 const AtomicString& attributeValue = getAttribute(aria_currentAttr); 1610 return AriaCurrentStateUndefined;
1590 if (attributeValue.isEmpty() || equalIgnoringCase(attributeValue, "false")) 1611 if (attributeValue.isEmpty() || equalIgnoringCase(attributeValue, "false"))
1591 return AriaCurrentStateFalse; 1612 return AriaCurrentStateFalse;
1592 if (equalIgnoringCase(attributeValue, "true")) 1613 if (equalIgnoringCase(attributeValue, "true"))
1593 return AriaCurrentStateTrue; 1614 return AriaCurrentStateTrue;
1594 if (equalIgnoringCase(attributeValue, "page")) 1615 if (equalIgnoringCase(attributeValue, "page"))
1595 return AriaCurrentStatePage; 1616 return AriaCurrentStatePage;
1596 if (equalIgnoringCase(attributeValue, "step")) 1617 if (equalIgnoringCase(attributeValue, "step"))
1597 return AriaCurrentStateStep; 1618 return AriaCurrentStateStep;
1598 if (equalIgnoringCase(attributeValue, "location")) 1619 if (equalIgnoringCase(attributeValue, "location"))
1599 return AriaCurrentStateLocation; 1620 return AriaCurrentStateLocation;
1600 if (equalIgnoringCase(attributeValue, "date")) 1621 if (equalIgnoringCase(attributeValue, "date"))
1601 return AriaCurrentStateDate; 1622 return AriaCurrentStateDate;
1602 if (equalIgnoringCase(attributeValue, "time")) 1623 if (equalIgnoringCase(attributeValue, "time"))
1603 return AriaCurrentStateTime; 1624 return AriaCurrentStateTime;
1604 // An unknown value should return true. 1625 // An unknown value should return true.
1605 if (!attributeValue.isEmpty()) 1626 if (!attributeValue.isEmpty())
1606 return AriaCurrentStateTrue; 1627 return AriaCurrentStateTrue;
1607 1628
1608 return AXObject::ariaCurrentState(); 1629 return AXObject::ariaCurrentState();
1609 } 1630 }
1610 1631
1611 InvalidState AXNodeObject::getInvalidState() const { 1632 InvalidState AXNodeObject::getInvalidState() const {
1612 if (hasAttribute(aria_invalidAttr)) { 1633 const AtomicString& attributeValue =
1613 const AtomicString& attributeValue = getAttribute(aria_invalidAttr); 1634 getAOMPropertyOrARIAAttribute(AOMStringProperty::kInvalid);
1614 if (equalIgnoringCase(attributeValue, "false")) 1635 if (equalIgnoringCase(attributeValue, "false"))
esprehn 2017/04/04 06:22:30 fwiw I think all of these should use ASCII case in
dmazzoni 2017/04/04 18:59:17 I can change this throughout modules/accessibility
1615 return InvalidStateFalse; 1636 return InvalidStateFalse;
1616 if (equalIgnoringCase(attributeValue, "true")) 1637 if (equalIgnoringCase(attributeValue, "true"))
1617 return InvalidStateTrue; 1638 return InvalidStateTrue;
1618 if (equalIgnoringCase(attributeValue, "spelling")) 1639 if (equalIgnoringCase(attributeValue, "spelling"))
1619 return InvalidStateSpelling; 1640 return InvalidStateSpelling;
1620 if (equalIgnoringCase(attributeValue, "grammar")) 1641 if (equalIgnoringCase(attributeValue, "grammar"))
1621 return InvalidStateGrammar; 1642 return InvalidStateGrammar;
1622 // A yet unknown value. 1643 // A yet unknown value.
1623 if (!attributeValue.isEmpty()) 1644 if (!attributeValue.isEmpty())
1624 return InvalidStateOther; 1645 return InvalidStateOther;
1625 }
1626 1646
1627 if (getNode() && getNode()->isElementNode() && 1647 if (getNode() && getNode()->isElementNode() &&
1628 toElement(getNode())->isFormControlElement()) { 1648 toElement(getNode())->isFormControlElement()) {
1629 HTMLFormControlElement* element = toHTMLFormControlElement(getNode()); 1649 HTMLFormControlElement* element = toHTMLFormControlElement(getNode());
1630 HeapVector<Member<HTMLFormControlElement>> invalidControls; 1650 HeapVector<Member<HTMLFormControlElement>> invalidControls;
1631 bool isInvalid = 1651 bool isInvalid =
1632 !element->checkValidity(&invalidControls, CheckValidityDispatchNoEvent); 1652 !element->checkValidity(&invalidControls, CheckValidityDispatchNoEvent);
1633 return isInvalid ? InvalidStateTrue : InvalidStateFalse; 1653 return isInvalid ? InvalidStateTrue : InvalidStateFalse;
1634 } 1654 }
1635 1655
(...skipping 30 matching lines...) Expand all
1666 const auto& siblings = parentObject()->children(); 1686 const auto& siblings = parentObject()->children();
1667 return siblings.size(); 1687 return siblings.size();
1668 } 1688 }
1669 } 1689 }
1670 1690
1671 return 0; 1691 return 0;
1672 } 1692 }
1673 1693
1674 String AXNodeObject::ariaInvalidValue() const { 1694 String AXNodeObject::ariaInvalidValue() const {
1675 if (getInvalidState() == InvalidStateOther) 1695 if (getInvalidState() == InvalidStateOther)
1676 return getAttribute(aria_invalidAttr); 1696 return getAOMPropertyOrARIAAttribute(AOMStringProperty::kInvalid);
1677 1697
1678 return String(); 1698 return String();
1679 } 1699 }
1680 1700
1681 String AXNodeObject::valueDescription() const { 1701 String AXNodeObject::valueDescription() const {
1682 if (!supportsRangeValue()) 1702 if (!supportsRangeValue())
1683 return String(); 1703 return String();
1684 1704
1685 return getAttribute(aria_valuetextAttr).getString(); 1705 return getAOMPropertyOrARIAAttribute(AOMStringProperty::kValueText)
1706 .getString();
1686 } 1707 }
1687 1708
1688 float AXNodeObject::valueForRange() const { 1709 float AXNodeObject::valueForRange() const {
1689 if (hasAttribute(aria_valuenowAttr)) 1710 if (hasAttribute(aria_valuenowAttr))
1690 return getAttribute(aria_valuenowAttr).toFloat(); 1711 return getAttribute(aria_valuenowAttr).toFloat();
1691 1712
1692 if (isNativeSlider()) 1713 if (isNativeSlider())
1693 return toHTMLInputElement(*getNode()).valueAsNumber(); 1714 return toHTMLInputElement(*getNode()).valueAsNumber();
1694 1715
1695 if (isHTMLMeterElement(getNode())) 1716 if (isHTMLMeterElement(getNode()))
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
1839 if (foundTextAlternative && !nameSources) 1860 if (foundTextAlternative && !nameSources)
1840 return textAlternative; 1861 return textAlternative;
1841 1862
1842 // Step 2E from: http://www.w3.org/TR/accname-aam-1.1 1863 // Step 2E from: http://www.w3.org/TR/accname-aam-1.1
1843 if (recursive && !inAriaLabelledByTraversal && isControl() && !isButton()) { 1864 if (recursive && !inAriaLabelledByTraversal && isControl() && !isButton()) {
1844 // No need to set any name source info in a recursive call. 1865 // No need to set any name source info in a recursive call.
1845 if (isTextControl()) 1866 if (isTextControl())
1846 return text(); 1867 return text();
1847 1868
1848 if (isRange()) { 1869 if (isRange()) {
1849 const AtomicString& ariaValuetext = getAttribute(aria_valuetextAttr); 1870 const AtomicString& ariaValuetext =
1871 getAOMPropertyOrARIAAttribute(AOMStringProperty::kValueText);
1850 if (!ariaValuetext.isNull()) 1872 if (!ariaValuetext.isNull())
1851 return ariaValuetext.getString(); 1873 return ariaValuetext.getString();
1852 return String::number(valueForRange()); 1874 return String::number(valueForRange());
1853 } 1875 }
1854 1876
1855 return stringValue(); 1877 return stringValue();
1856 } 1878 }
1857 1879
1858 // Step 2D from: http://www.w3.org/TR/accname-aam-1.1 1880 // Step 2D from: http://www.w3.org/TR/accname-aam-1.1
1859 textAlternative = nativeTextAlternative(visited, nameFrom, relatedObjects, 1881 textAlternative = nativeTextAlternative(visited, nameFrom, relatedObjects,
(...skipping 842 matching lines...) Expand 10 before | Expand all | Expand 10 after
2702 2724
2703 // Also check for aria-placeholder. 2725 // Also check for aria-placeholder.
2704 nameFrom = AXNameFromPlaceholder; 2726 nameFrom = AXNameFromPlaceholder;
2705 if (nameSources) { 2727 if (nameSources) {
2706 nameSources->push_back( 2728 nameSources->push_back(
2707 NameSource(*foundTextAlternative, aria_placeholderAttr)); 2729 NameSource(*foundTextAlternative, aria_placeholderAttr));
2708 NameSource& source = nameSources->back(); 2730 NameSource& source = nameSources->back();
2709 source.type = nameFrom; 2731 source.type = nameFrom;
2710 } 2732 }
2711 const AtomicString& ariaPlaceholder = 2733 const AtomicString& ariaPlaceholder =
2712 htmlElement->fastGetAttribute(aria_placeholderAttr); 2734 getAOMPropertyOrARIAAttribute(AOMStringProperty::kPlaceholder);
2713 if (!ariaPlaceholder.isEmpty()) { 2735 if (!ariaPlaceholder.isEmpty()) {
2714 textAlternative = ariaPlaceholder; 2736 textAlternative = ariaPlaceholder;
2715 if (nameSources) { 2737 if (nameSources) {
2716 NameSource& source = nameSources->back(); 2738 NameSource& source = nameSources->back();
2717 source.text = textAlternative; 2739 source.text = textAlternative;
2718 source.attributeValue = ariaPlaceholder; 2740 source.attributeValue = ariaPlaceholder;
2719 *foundTextAlternative = true; 2741 *foundTextAlternative = true;
2720 } else { 2742 } else {
2721 return textAlternative; 2743 return textAlternative;
2722 } 2744 }
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after
3213 return String(); 3235 return String();
3214 return toTextControlElement(node)->strippedPlaceholder(); 3236 return toTextControlElement(node)->strippedPlaceholder();
3215 } 3237 }
3216 3238
3217 DEFINE_TRACE(AXNodeObject) { 3239 DEFINE_TRACE(AXNodeObject) {
3218 visitor->trace(m_node); 3240 visitor->trace(m_node);
3219 AXObject::trace(visitor); 3241 AXObject::trace(visitor);
3220 } 3242 }
3221 3243
3222 } // namespace blink 3244 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698