OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008, 2009, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008, 2009, 2011 Apple 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 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 updateCachedAttributeValuesIfNeeded(); | 669 updateCachedAttributeValuesIfNeeded(); |
670 return m_cachedHasInheritedPresentationalRole; | 670 return m_cachedHasInheritedPresentationalRole; |
671 } | 671 } |
672 | 672 |
673 bool AXObject::isPresentationalChild() const | 673 bool AXObject::isPresentationalChild() const |
674 { | 674 { |
675 updateCachedAttributeValuesIfNeeded(); | 675 updateCachedAttributeValuesIfNeeded(); |
676 return m_cachedIsPresentationalChild; | 676 return m_cachedIsPresentationalChild; |
677 } | 677 } |
678 | 678 |
| 679 // Simplify whitespace, but preserve a single leading and trailing whitespace ch
aracter if it's present. |
| 680 // static |
| 681 String AXObject::collapseWhitespace(const String& str) |
| 682 { |
| 683 StringBuilder result; |
| 684 if (!str.isEmpty() && isHTMLSpace<UChar>(str[0])) |
| 685 result.append(' '); |
| 686 result.append(str.simplifyWhiteSpace(isHTMLSpace<UChar>)); |
| 687 if (!str.isEmpty() && isHTMLSpace<UChar>(str[str.length() - 1])) |
| 688 result.append(' '); |
| 689 return result.toString(); |
| 690 } |
| 691 |
679 String AXObject::computedName() const | 692 String AXObject::computedName() const |
680 { | 693 { |
681 AXNameFrom nameFrom; | 694 AXNameFrom nameFrom; |
682 AXObject::AXObjectVector nameObjects; | 695 AXObject::AXObjectVector nameObjects; |
683 return name(nameFrom, &nameObjects); | 696 return name(nameFrom, &nameObjects); |
684 } | 697 } |
685 | 698 |
686 String AXObject::name(AXNameFrom& nameFrom, AXObject::AXObjectVector* nameObject
s) const | 699 String AXObject::name(AXNameFrom& nameFrom, AXObject::AXObjectVector* nameObject
s) const |
687 { | 700 { |
688 HeapHashSet<Member<const AXObject>> visited; | 701 HeapHashSet<Member<const AXObject>> visited; |
689 AXRelatedObjectVector relatedObjects; | 702 AXRelatedObjectVector relatedObjects; |
690 String text = textAlternative(false, false, visited, nameFrom, &relatedObjec
ts, nullptr); | 703 String text = textAlternative(false, false, visited, nameFrom, &relatedObjec
ts, nullptr); |
691 | 704 |
692 if (!node() || !isHTMLBRElement(node())) | 705 AccessibilityRole role = roleValue(); |
693 text = text.simplifyWhiteSpace(isHTMLSpace<UChar>, WTF::DoNotStripWhiteS
pace); | 706 if (!node() || (!isHTMLBRElement(node()) && role != StaticTextRole && role !
= InlineTextBoxRole)) |
| 707 text = collapseWhitespace(text); |
694 | 708 |
695 if (nameObjects) { | 709 if (nameObjects) { |
696 nameObjects->clear(); | 710 nameObjects->clear(); |
697 for (size_t i = 0; i < relatedObjects.size(); i++) | 711 for (size_t i = 0; i < relatedObjects.size(); i++) |
698 nameObjects->append(relatedObjects[i]->object); | 712 nameObjects->append(relatedObjects[i]->object); |
699 } | 713 } |
700 return text; | 714 return text; |
701 } | 715 } |
702 | 716 |
703 String AXObject::name(NameSources* nameSources) const | 717 String AXObject::name(NameSources* nameSources) const |
704 { | 718 { |
705 AXObjectSet visited; | 719 AXObjectSet visited; |
706 AXNameFrom tmpNameFrom; | 720 AXNameFrom tmpNameFrom; |
707 AXRelatedObjectVector tmpRelatedObjects; | 721 AXRelatedObjectVector tmpRelatedObjects; |
708 String text = textAlternative(false, false, visited, tmpNameFrom, &tmpRelate
dObjects, nameSources); | 722 String text = textAlternative(false, false, visited, tmpNameFrom, &tmpRelate
dObjects, nameSources); |
709 text = text.simplifyWhiteSpace(isHTMLSpace<UChar>); | 723 text = text.simplifyWhiteSpace(isHTMLSpace<UChar>); |
710 return text; | 724 return text; |
711 } | 725 } |
712 | 726 |
713 String AXObject::recursiveTextAlternative(const AXObject& axObj, bool inAriaLabe
lledByTraversal, AXObjectSet& visited) | 727 String AXObject::recursiveTextAlternative(const AXObject& axObj, bool inAriaLabe
lledByTraversal, AXObjectSet& visited) |
714 { | 728 { |
715 AXNameFrom tmpNameFrom; | 729 AXNameFrom tmpNameFrom; |
716 return axObj.textAlternative(true, inAriaLabelledByTraversal, visited, tmpNa
meFrom, nullptr, nullptr); | 730 return axObj.textAlternative(true, inAriaLabelledByTraversal, visited, tmpNa
meFrom, nullptr, nullptr); |
717 } | 731 } |
718 | 732 |
| 733 bool AXObject::isHiddenForTextAlternativeCalculation() const |
| 734 { |
| 735 if (equalIgnoringCase(getAttribute(aria_hiddenAttr), "false")) |
| 736 return false; |
| 737 |
| 738 if (layoutObject()) |
| 739 return layoutObject()->style()->visibility() != VISIBLE; |
| 740 |
| 741 // This is an obscure corner case: if a node has no LayoutObject, that means
it's not rendered, |
| 742 // but we still may be exploring it as part of a text alternative calculatio
n, for example if it |
| 743 // was explicitly referenced by aria-labelledby. So we need to explicitly ca
ll the style resolver |
| 744 // to check whether it's invisible or display:none, rather than relying on t
he style cached in the |
| 745 // LayoutObject. |
| 746 Document* doc = document(); |
| 747 if (doc && doc->frame() && node() && node()->isElementNode()) { |
| 748 RefPtr<ComputedStyle> style = doc->ensureStyleResolver().styleForElement
(toElement(node())); |
| 749 return style->display() == NONE || style->visibility() != VISIBLE; |
| 750 } |
| 751 |
| 752 return false; |
| 753 } |
| 754 |
719 String AXObject::ariaTextAlternative(bool recursive, bool inAriaLabelledByTraver
sal, AXObjectSet& visited, AXNameFrom& nameFrom, AXRelatedObjectVector* relatedO
bjects, NameSources* nameSources, bool* foundTextAlternative) const | 755 String AXObject::ariaTextAlternative(bool recursive, bool inAriaLabelledByTraver
sal, AXObjectSet& visited, AXNameFrom& nameFrom, AXRelatedObjectVector* relatedO
bjects, NameSources* nameSources, bool* foundTextAlternative) const |
720 { | 756 { |
721 String textAlternative; | 757 String textAlternative; |
722 bool alreadyVisited = visited.contains(this); | 758 bool alreadyVisited = visited.contains(this); |
723 visited.add(this); | 759 visited.add(this); |
724 | 760 |
725 // Step 2A from: http://www.w3.org/TR/accname-aam-1.1 | 761 // Step 2A from: http://www.w3.org/TR/accname-aam-1.1 |
726 // If you change this logic, update AXNodeObject::nameFromLabelElement, too. | 762 // If you change this logic, update AXNodeObject::nameFromLabelElement, too. |
727 if (!recursive && layoutObject() | 763 if (!inAriaLabelledByTraversal && isHiddenForTextAlternativeCalculation()) { |
728 && layoutObject()->style()->visibility() != VISIBLE | 764 *foundTextAlternative = true; |
729 && !equalIgnoringCase(getAttribute(aria_hiddenAttr), "false")) { | |
730 return String(); | 765 return String(); |
731 } | 766 } |
732 | 767 |
733 // Step 2B from: http://www.w3.org/TR/accname-aam-1.1 | 768 // Step 2B from: http://www.w3.org/TR/accname-aam-1.1 |
734 // If you change this logic, update AXNodeObject::nameFromLabelElement, too. | 769 // If you change this logic, update AXNodeObject::nameFromLabelElement, too. |
735 if (!inAriaLabelledByTraversal && !alreadyVisited) { | 770 if (!inAriaLabelledByTraversal && !alreadyVisited) { |
736 const QualifiedName& attr = hasAttribute(aria_labeledbyAttr) && !hasAttr
ibute(aria_labelledbyAttr) ? aria_labeledbyAttr : aria_labelledbyAttr; | 771 const QualifiedName& attr = hasAttribute(aria_labeledbyAttr) && !hasAttr
ibute(aria_labelledbyAttr) ? aria_labeledbyAttr : aria_labelledbyAttr; |
737 nameFrom = AXNameFromRelatedElement; | 772 nameFrom = AXNameFromRelatedElement; |
738 if (nameSources) { | 773 if (nameSources) { |
739 nameSources->append(NameSource(*foundTextAlternative, attr)); | 774 nameSources->append(NameSource(*foundTextAlternative, attr)); |
(...skipping 941 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1681 | 1716 |
1682 DEFINE_TRACE(AXObject) | 1717 DEFINE_TRACE(AXObject) |
1683 { | 1718 { |
1684 visitor->trace(m_children); | 1719 visitor->trace(m_children); |
1685 visitor->trace(m_parent); | 1720 visitor->trace(m_parent); |
1686 visitor->trace(m_cachedLiveRegionRoot); | 1721 visitor->trace(m_cachedLiveRegionRoot); |
1687 visitor->trace(m_axObjectCache); | 1722 visitor->trace(m_axObjectCache); |
1688 } | 1723 } |
1689 | 1724 |
1690 } // namespace blink | 1725 } // namespace blink |
OLD | NEW |