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 799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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")) |
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()) |
aboxhall
2017/03/31 00:23:39
This doesn't seem right. This is a token value; if
dmazzoni
2017/03/31 04:34:58
The spec says: "Any value not recognized in the li
| |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |