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 805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 return 0; | 816 return 0; |
817 } | 817 } |
818 | 818 |
819 static Element* siblingWithAriaRole(String role, Node* node) { | 819 static Element* siblingWithAriaRole(String role, Node* node) { |
820 Node* parent = node->parentNode(); | 820 Node* parent = node->parentNode(); |
821 if (!parent) | 821 if (!parent) |
822 return 0; | 822 return 0; |
823 | 823 |
824 for (Element* sibling = ElementTraversal::firstChild(*parent); sibling; | 824 for (Element* sibling = ElementTraversal::firstChild(*parent); sibling; |
825 sibling = ElementTraversal::nextSibling(*sibling)) { | 825 sibling = ElementTraversal::nextSibling(*sibling)) { |
826 const AtomicString& siblingAriaRole = sibling->getAttribute(roleAttr); | 826 const AtomicString& siblingAriaRole = |
| 827 AccessibleNode::getProperty(sibling, AOMStringProperty::kRole); |
827 if (equalIgnoringCase(siblingAriaRole, role)) | 828 if (equalIgnoringCase(siblingAriaRole, role)) |
828 return sibling; | 829 return sibling; |
829 } | 830 } |
830 | 831 |
831 return 0; | 832 return 0; |
832 } | 833 } |
833 | 834 |
834 Element* AXNodeObject::menuItemElementForMenu() const { | 835 Element* AXNodeObject::menuItemElementForMenu() const { |
835 if (ariaRoleAttribute() != MenuRole) | 836 if (ariaRoleAttribute() != MenuRole) |
836 return 0; | 837 return 0; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
921 return; | 922 return; |
922 | 923 |
923 AXSparseAttributeSetterMap& axSparseAttributeSetterMap = | 924 AXSparseAttributeSetterMap& axSparseAttributeSetterMap = |
924 getSparseAttributeSetterMap(); | 925 getSparseAttributeSetterMap(); |
925 AttributeCollection attributes = toElement(node)->attributesWithoutUpdate(); | 926 AttributeCollection attributes = toElement(node)->attributesWithoutUpdate(); |
926 for (const Attribute& attr : attributes) { | 927 for (const Attribute& attr : attributes) { |
927 SparseAttributeSetter* setter = axSparseAttributeSetterMap.at(attr.name()); | 928 SparseAttributeSetter* setter = axSparseAttributeSetterMap.at(attr.name()); |
928 if (setter) | 929 if (setter) |
929 setter->run(*this, sparseAttributeClient, attr.value()); | 930 setter->run(*this, sparseAttributeClient, attr.value()); |
930 } | 931 } |
| 932 |
| 933 // TODO(dmazzoni): Efficiently iterate over AccessibleNode properties that are |
| 934 // set and merge the two loops somehow. |
| 935 if (toElement(node)->existingAccessibleNode()) { |
| 936 AtomicString keyShortcuts = |
| 937 getAOMPropertyOrARIAAttribute(AOMStringProperty::kKeyShortcuts); |
| 938 if (!keyShortcuts.isNull()) { |
| 939 axSparseAttributeSetterMap.at(aria_keyshortcutsAttr) |
| 940 ->run(*this, sparseAttributeClient, keyShortcuts); |
| 941 } |
| 942 AtomicString roleDescription = |
| 943 getAOMPropertyOrARIAAttribute(AOMStringProperty::kRoleDescription); |
| 944 if (!roleDescription.isNull()) { |
| 945 axSparseAttributeSetterMap.at(aria_roledescriptionAttr) |
| 946 ->run(*this, sparseAttributeClient, roleDescription); |
| 947 } |
| 948 } |
931 } | 949 } |
932 | 950 |
933 bool AXNodeObject::isAnchor() const { | 951 bool AXNodeObject::isAnchor() const { |
934 return !isNativeImage() && isLink(); | 952 return !isNativeImage() && isLink(); |
935 } | 953 } |
936 | 954 |
937 bool AXNodeObject::isControl() const { | 955 bool AXNodeObject::isControl() const { |
938 Node* node = this->getNode(); | 956 Node* node = this->getNode(); |
939 if (!node) | 957 if (!node) |
940 return false; | 958 return false; |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1134 return toHTMLInputElement(*node).shouldAppearChecked(); | 1152 return toHTMLInputElement(*node).shouldAppearChecked(); |
1135 | 1153 |
1136 // Else, if this is an ARIA role checkbox or radio or menuitemcheckbox | 1154 // Else, if this is an ARIA role checkbox or radio or menuitemcheckbox |
1137 // or menuitemradio or switch, respect the aria-checked attribute | 1155 // or menuitemradio or switch, respect the aria-checked attribute |
1138 switch (ariaRoleAttribute()) { | 1156 switch (ariaRoleAttribute()) { |
1139 case CheckBoxRole: | 1157 case CheckBoxRole: |
1140 case MenuItemCheckBoxRole: | 1158 case MenuItemCheckBoxRole: |
1141 case MenuItemRadioRole: | 1159 case MenuItemRadioRole: |
1142 case RadioButtonRole: | 1160 case RadioButtonRole: |
1143 case SwitchRole: | 1161 case SwitchRole: |
1144 if (equalIgnoringCase(getAttribute(aria_checkedAttr), "true")) | 1162 if (equalIgnoringCase( |
| 1163 getAOMPropertyOrARIAAttribute(AOMStringProperty::kChecked), |
| 1164 "true")) |
1145 return true; | 1165 return true; |
1146 return false; | 1166 return false; |
1147 default: | 1167 default: |
1148 break; | 1168 break; |
1149 } | 1169 } |
1150 | 1170 |
1151 // Otherwise it's not checked | 1171 // Otherwise it's not checked |
1152 return false; | 1172 return false; |
1153 } | 1173 } |
1154 | 1174 |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 } | 1416 } |
1397 | 1417 |
1398 return level; | 1418 return level; |
1399 } | 1419 } |
1400 | 1420 |
1401 String AXNodeObject::ariaAutoComplete() const { | 1421 String AXNodeObject::ariaAutoComplete() const { |
1402 if (roleValue() != ComboBoxRole) | 1422 if (roleValue() != ComboBoxRole) |
1403 return String(); | 1423 return String(); |
1404 | 1424 |
1405 const AtomicString& ariaAutoComplete = | 1425 const AtomicString& ariaAutoComplete = |
1406 getAttribute(aria_autocompleteAttr).lower(); | 1426 getAOMPropertyOrARIAAttribute(AOMStringProperty::kAutocomplete).lower(); |
1407 | 1427 |
1408 if (ariaAutoComplete == "inline" || ariaAutoComplete == "list" || | 1428 if (ariaAutoComplete == "inline" || ariaAutoComplete == "list" || |
1409 ariaAutoComplete == "both") | 1429 ariaAutoComplete == "both") |
1410 return ariaAutoComplete; | 1430 return ariaAutoComplete; |
1411 | 1431 |
1412 return String(); | 1432 return String(); |
1413 } | 1433 } |
1414 | 1434 |
1415 void AXNodeObject::markers(Vector<DocumentMarker::MarkerType>& markerTypes, | 1435 void AXNodeObject::markers(Vector<DocumentMarker::MarkerType>& markerTypes, |
1416 Vector<AXRange>& markerRanges) const { | 1436 Vector<AXRange>& markerRanges) const { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1458 TreeScope& treeScope = anchor->treeScope(); | 1478 TreeScope& treeScope = anchor->treeScope(); |
1459 Element* target = treeScope.findAnchor(fragment); | 1479 Element* target = treeScope.findAnchor(fragment); |
1460 if (!target) | 1480 if (!target) |
1461 return AXObject::inPageLinkTarget(); | 1481 return AXObject::inPageLinkTarget(); |
1462 // If the target is not in the accessibility tree, get the first unignored | 1482 // If the target is not in the accessibility tree, get the first unignored |
1463 // sibling. | 1483 // sibling. |
1464 return axObjectCache().firstAccessibleObjectFromNode(target); | 1484 return axObjectCache().firstAccessibleObjectFromNode(target); |
1465 } | 1485 } |
1466 | 1486 |
1467 AccessibilityOrientation AXNodeObject::orientation() const { | 1487 AccessibilityOrientation AXNodeObject::orientation() const { |
1468 const AtomicString& ariaOrientation = getAttribute(aria_orientationAttr); | 1488 const AtomicString& ariaOrientation = |
| 1489 getAOMPropertyOrARIAAttribute(AOMStringProperty::kOrientation); |
1469 AccessibilityOrientation orientation = AccessibilityOrientationUndefined; | 1490 AccessibilityOrientation orientation = AccessibilityOrientationUndefined; |
1470 if (equalIgnoringCase(ariaOrientation, "horizontal")) | 1491 if (equalIgnoringCase(ariaOrientation, "horizontal")) |
1471 orientation = AccessibilityOrientationHorizontal; | 1492 orientation = AccessibilityOrientationHorizontal; |
1472 else if (equalIgnoringCase(ariaOrientation, "vertical")) | 1493 else if (equalIgnoringCase(ariaOrientation, "vertical")) |
1473 orientation = AccessibilityOrientationVertical; | 1494 orientation = AccessibilityOrientationVertical; |
1474 | 1495 |
1475 switch (roleValue()) { | 1496 switch (roleValue()) { |
1476 case ComboBoxRole: | 1497 case ComboBoxRole: |
1477 case ListBoxRole: | 1498 case ListBoxRole: |
1478 case MenuRole: | 1499 case MenuRole: |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1604 return AXObject::colorValue(); | 1625 return AXObject::colorValue(); |
1605 | 1626 |
1606 // HTMLInputElement::value always returns a string parseable by Color. | 1627 // HTMLInputElement::value always returns a string parseable by Color. |
1607 Color color; | 1628 Color color; |
1608 bool success = color.setFromString(input->value()); | 1629 bool success = color.setFromString(input->value()); |
1609 DCHECK(success); | 1630 DCHECK(success); |
1610 return color.rgb(); | 1631 return color.rgb(); |
1611 } | 1632 } |
1612 | 1633 |
1613 AriaCurrentState AXNodeObject::ariaCurrentState() const { | 1634 AriaCurrentState AXNodeObject::ariaCurrentState() const { |
1614 if (!hasAttribute(aria_currentAttr)) | 1635 const AtomicString& attributeValue = |
1615 return AXObject::ariaCurrentState(); | 1636 getAOMPropertyOrARIAAttribute(AOMStringProperty::kCurrent); |
1616 | 1637 if (attributeValue.isNull()) |
1617 const AtomicString& attributeValue = getAttribute(aria_currentAttr); | 1638 return AriaCurrentStateUndefined; |
1618 if (attributeValue.isEmpty() || equalIgnoringCase(attributeValue, "false")) | 1639 if (attributeValue.isEmpty() || equalIgnoringCase(attributeValue, "false")) |
1619 return AriaCurrentStateFalse; | 1640 return AriaCurrentStateFalse; |
1620 if (equalIgnoringCase(attributeValue, "true")) | 1641 if (equalIgnoringCase(attributeValue, "true")) |
1621 return AriaCurrentStateTrue; | 1642 return AriaCurrentStateTrue; |
1622 if (equalIgnoringCase(attributeValue, "page")) | 1643 if (equalIgnoringCase(attributeValue, "page")) |
1623 return AriaCurrentStatePage; | 1644 return AriaCurrentStatePage; |
1624 if (equalIgnoringCase(attributeValue, "step")) | 1645 if (equalIgnoringCase(attributeValue, "step")) |
1625 return AriaCurrentStateStep; | 1646 return AriaCurrentStateStep; |
1626 if (equalIgnoringCase(attributeValue, "location")) | 1647 if (equalIgnoringCase(attributeValue, "location")) |
1627 return AriaCurrentStateLocation; | 1648 return AriaCurrentStateLocation; |
1628 if (equalIgnoringCase(attributeValue, "date")) | 1649 if (equalIgnoringCase(attributeValue, "date")) |
1629 return AriaCurrentStateDate; | 1650 return AriaCurrentStateDate; |
1630 if (equalIgnoringCase(attributeValue, "time")) | 1651 if (equalIgnoringCase(attributeValue, "time")) |
1631 return AriaCurrentStateTime; | 1652 return AriaCurrentStateTime; |
1632 // An unknown value should return true. | 1653 // An unknown value should return true. |
1633 if (!attributeValue.isEmpty()) | 1654 if (!attributeValue.isEmpty()) |
1634 return AriaCurrentStateTrue; | 1655 return AriaCurrentStateTrue; |
1635 | 1656 |
1636 return AXObject::ariaCurrentState(); | 1657 return AXObject::ariaCurrentState(); |
1637 } | 1658 } |
1638 | 1659 |
1639 InvalidState AXNodeObject::getInvalidState() const { | 1660 InvalidState AXNodeObject::getInvalidState() const { |
1640 if (hasAttribute(aria_invalidAttr)) { | 1661 const AtomicString& attributeValue = |
1641 const AtomicString& attributeValue = getAttribute(aria_invalidAttr); | 1662 getAOMPropertyOrARIAAttribute(AOMStringProperty::kInvalid); |
1642 if (equalIgnoringCase(attributeValue, "false")) | 1663 if (equalIgnoringCase(attributeValue, "false")) |
1643 return InvalidStateFalse; | 1664 return InvalidStateFalse; |
1644 if (equalIgnoringCase(attributeValue, "true")) | 1665 if (equalIgnoringCase(attributeValue, "true")) |
1645 return InvalidStateTrue; | 1666 return InvalidStateTrue; |
1646 if (equalIgnoringCase(attributeValue, "spelling")) | 1667 if (equalIgnoringCase(attributeValue, "spelling")) |
1647 return InvalidStateSpelling; | 1668 return InvalidStateSpelling; |
1648 if (equalIgnoringCase(attributeValue, "grammar")) | 1669 if (equalIgnoringCase(attributeValue, "grammar")) |
1649 return InvalidStateGrammar; | 1670 return InvalidStateGrammar; |
1650 // A yet unknown value. | 1671 // A yet unknown value. |
1651 if (!attributeValue.isEmpty()) | 1672 if (!attributeValue.isEmpty()) |
1652 return InvalidStateOther; | 1673 return InvalidStateOther; |
1653 } | |
1654 | 1674 |
1655 if (getNode() && getNode()->isElementNode() && | 1675 if (getNode() && getNode()->isElementNode() && |
1656 toElement(getNode())->isFormControlElement()) { | 1676 toElement(getNode())->isFormControlElement()) { |
1657 HTMLFormControlElement* element = toHTMLFormControlElement(getNode()); | 1677 HTMLFormControlElement* element = toHTMLFormControlElement(getNode()); |
1658 HeapVector<Member<HTMLFormControlElement>> invalidControls; | 1678 HeapVector<Member<HTMLFormControlElement>> invalidControls; |
1659 bool isInvalid = | 1679 bool isInvalid = |
1660 !element->checkValidity(&invalidControls, CheckValidityDispatchNoEvent); | 1680 !element->checkValidity(&invalidControls, CheckValidityDispatchNoEvent); |
1661 return isInvalid ? InvalidStateTrue : InvalidStateFalse; | 1681 return isInvalid ? InvalidStateTrue : InvalidStateFalse; |
1662 } | 1682 } |
1663 | 1683 |
(...skipping 30 matching lines...) Expand all Loading... |
1694 const auto& siblings = parentObject()->children(); | 1714 const auto& siblings = parentObject()->children(); |
1695 return siblings.size(); | 1715 return siblings.size(); |
1696 } | 1716 } |
1697 } | 1717 } |
1698 | 1718 |
1699 return 0; | 1719 return 0; |
1700 } | 1720 } |
1701 | 1721 |
1702 String AXNodeObject::ariaInvalidValue() const { | 1722 String AXNodeObject::ariaInvalidValue() const { |
1703 if (getInvalidState() == InvalidStateOther) | 1723 if (getInvalidState() == InvalidStateOther) |
1704 return getAttribute(aria_invalidAttr); | 1724 return getAOMPropertyOrARIAAttribute(AOMStringProperty::kInvalid); |
1705 | 1725 |
1706 return String(); | 1726 return String(); |
1707 } | 1727 } |
1708 | 1728 |
1709 String AXNodeObject::valueDescription() const { | 1729 String AXNodeObject::valueDescription() const { |
1710 if (!supportsRangeValue()) | 1730 if (!supportsRangeValue()) |
1711 return String(); | 1731 return String(); |
1712 | 1732 |
1713 return getAttribute(aria_valuetextAttr).getString(); | 1733 return getAOMPropertyOrARIAAttribute(AOMStringProperty::kValueText) |
| 1734 .getString(); |
1714 } | 1735 } |
1715 | 1736 |
1716 float AXNodeObject::valueForRange() const { | 1737 float AXNodeObject::valueForRange() const { |
1717 if (hasAttribute(aria_valuenowAttr)) | 1738 if (hasAttribute(aria_valuenowAttr)) |
1718 return getAttribute(aria_valuenowAttr).toFloat(); | 1739 return getAttribute(aria_valuenowAttr).toFloat(); |
1719 | 1740 |
1720 if (isNativeSlider()) | 1741 if (isNativeSlider()) |
1721 return toHTMLInputElement(*getNode()).valueAsNumber(); | 1742 return toHTMLInputElement(*getNode()).valueAsNumber(); |
1722 | 1743 |
1723 if (isHTMLMeterElement(getNode())) | 1744 if (isHTMLMeterElement(getNode())) |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1867 if (foundTextAlternative && !nameSources) | 1888 if (foundTextAlternative && !nameSources) |
1868 return textAlternative; | 1889 return textAlternative; |
1869 | 1890 |
1870 // Step 2E from: http://www.w3.org/TR/accname-aam-1.1 | 1891 // Step 2E from: http://www.w3.org/TR/accname-aam-1.1 |
1871 if (recursive && !inAriaLabelledByTraversal && isControl() && !isButton()) { | 1892 if (recursive && !inAriaLabelledByTraversal && isControl() && !isButton()) { |
1872 // No need to set any name source info in a recursive call. | 1893 // No need to set any name source info in a recursive call. |
1873 if (isTextControl()) | 1894 if (isTextControl()) |
1874 return text(); | 1895 return text(); |
1875 | 1896 |
1876 if (isRange()) { | 1897 if (isRange()) { |
1877 const AtomicString& ariaValuetext = getAttribute(aria_valuetextAttr); | 1898 const AtomicString& ariaValuetext = |
| 1899 getAOMPropertyOrARIAAttribute(AOMStringProperty::kValueText); |
1878 if (!ariaValuetext.isNull()) | 1900 if (!ariaValuetext.isNull()) |
1879 return ariaValuetext.getString(); | 1901 return ariaValuetext.getString(); |
1880 return String::number(valueForRange()); | 1902 return String::number(valueForRange()); |
1881 } | 1903 } |
1882 | 1904 |
1883 return stringValue(); | 1905 return stringValue(); |
1884 } | 1906 } |
1885 | 1907 |
1886 // Step 2D from: http://www.w3.org/TR/accname-aam-1.1 | 1908 // Step 2D from: http://www.w3.org/TR/accname-aam-1.1 |
1887 textAlternative = nativeTextAlternative(visited, nameFrom, relatedObjects, | 1909 textAlternative = nativeTextAlternative(visited, nameFrom, relatedObjects, |
(...skipping 842 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2730 | 2752 |
2731 // Also check for aria-placeholder. | 2753 // Also check for aria-placeholder. |
2732 nameFrom = AXNameFromPlaceholder; | 2754 nameFrom = AXNameFromPlaceholder; |
2733 if (nameSources) { | 2755 if (nameSources) { |
2734 nameSources->push_back( | 2756 nameSources->push_back( |
2735 NameSource(*foundTextAlternative, aria_placeholderAttr)); | 2757 NameSource(*foundTextAlternative, aria_placeholderAttr)); |
2736 NameSource& source = nameSources->back(); | 2758 NameSource& source = nameSources->back(); |
2737 source.type = nameFrom; | 2759 source.type = nameFrom; |
2738 } | 2760 } |
2739 const AtomicString& ariaPlaceholder = | 2761 const AtomicString& ariaPlaceholder = |
2740 htmlElement->fastGetAttribute(aria_placeholderAttr); | 2762 getAOMPropertyOrARIAAttribute(AOMStringProperty::kPlaceholder); |
2741 if (!ariaPlaceholder.isEmpty()) { | 2763 if (!ariaPlaceholder.isEmpty()) { |
2742 textAlternative = ariaPlaceholder; | 2764 textAlternative = ariaPlaceholder; |
2743 if (nameSources) { | 2765 if (nameSources) { |
2744 NameSource& source = nameSources->back(); | 2766 NameSource& source = nameSources->back(); |
2745 source.text = textAlternative; | 2767 source.text = textAlternative; |
2746 source.attributeValue = ariaPlaceholder; | 2768 source.attributeValue = ariaPlaceholder; |
2747 *foundTextAlternative = true; | 2769 *foundTextAlternative = true; |
2748 } else { | 2770 } else { |
2749 return textAlternative; | 2771 return textAlternative; |
2750 } | 2772 } |
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3238 return String(); | 3260 return String(); |
3239 return toTextControlElement(node)->strippedPlaceholder(); | 3261 return toTextControlElement(node)->strippedPlaceholder(); |
3240 } | 3262 } |
3241 | 3263 |
3242 DEFINE_TRACE(AXNodeObject) { | 3264 DEFINE_TRACE(AXNodeObject) { |
3243 visitor->trace(m_node); | 3265 visitor->trace(m_node); |
3244 AXObject::trace(visitor); | 3266 AXObject::trace(visitor); |
3245 } | 3267 } |
3246 | 3268 |
3247 } // namespace blink | 3269 } // namespace blink |
OLD | NEW |