| 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 |