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

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

Issue 1417213006: Switch all LayoutTests to use new AX name calculation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month 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 12 matching lines...) Expand all
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include "config.h" 29 #include "config.h"
30 #include "modules/accessibility/AXNodeObject.h" 30 #include "modules/accessibility/AXNodeObject.h"
31 31
32 #include "core/InputTypeNames.h" 32 #include "core/InputTypeNames.h"
33 #include "core/dom/Element.h"
33 #include "core/dom/NodeTraversal.h" 34 #include "core/dom/NodeTraversal.h"
34 #include "core/dom/Text.h" 35 #include "core/dom/Text.h"
35 #include "core/dom/shadow/ComposedTreeTraversal.h" 36 #include "core/dom/shadow/ComposedTreeTraversal.h"
36 #include "core/html/HTMLDListElement.h" 37 #include "core/html/HTMLDListElement.h"
37 #include "core/html/HTMLFieldSetElement.h" 38 #include "core/html/HTMLFieldSetElement.h"
38 #include "core/html/HTMLFrameElementBase.h" 39 #include "core/html/HTMLFrameElementBase.h"
39 #include "core/html/HTMLImageElement.h" 40 #include "core/html/HTMLImageElement.h"
40 #include "core/html/HTMLInputElement.h" 41 #include "core/html/HTMLInputElement.h"
41 #include "core/html/HTMLLabelElement.h" 42 #include "core/html/HTMLLabelElement.h"
42 #include "core/html/HTMLLegendElement.h" 43 #include "core/html/HTMLLegendElement.h"
(...skipping 1447 matching lines...) Expand 10 before | Expand all | Expand 10 after
1490 return String(); 1491 return String();
1491 1492
1492 if (ariaRoleAttribute() == StaticTextRole) { 1493 if (ariaRoleAttribute() == StaticTextRole) {
1493 String staticText = text(); 1494 String staticText = text();
1494 if (!staticText.length()) 1495 if (!staticText.length())
1495 staticText = deprecatedTextUnderElement(TextUnderElementAll); 1496 staticText = deprecatedTextUnderElement(TextUnderElementAll);
1496 return staticText; 1497 return staticText;
1497 } 1498 }
1498 1499
1499 if (node->isTextNode()) 1500 if (node->isTextNode())
1500 return deprecatedTextUnderElement(TextUnderElementAll); 1501 return deprecatedTextUnderElement(TextUnderElementAll);
aboxhall 2015/11/05 17:49:21 Should this be addressed in this change?
dmazzoni 2015/11/06 00:21:17 Not yet. Changing this could affect existing Chrom
1501 1502
1502 if (isHTMLSelectElement(*node)) { 1503 if (isHTMLSelectElement(*node)) {
1503 HTMLSelectElement& selectElement = toHTMLSelectElement(*node); 1504 HTMLSelectElement& selectElement = toHTMLSelectElement(*node);
1504 int selectedIndex = selectElement.selectedIndex(); 1505 int selectedIndex = selectElement.selectedIndex();
1505 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = sel ectElement.listItems(); 1506 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = sel ectElement.listItems();
1506 if (selectedIndex >= 0 && static_cast<size_t>(selectedIndex) < listItems .size()) { 1507 if (selectedIndex >= 0 && static_cast<size_t>(selectedIndex) < listItems .size()) {
1507 const AtomicString& overriddenDescription = listItems[selectedIndex] ->fastGetAttribute(aria_labelAttr); 1508 const AtomicString& overriddenDescription = listItems[selectedIndex] ->fastGetAttribute(aria_labelAttr);
1508 if (!overriddenDescription.isNull()) 1509 if (!overriddenDescription.isNull())
1509 return overriddenDescription; 1510 return overriddenDescription;
1510 } 1511 }
1511 if (!selectElement.multiple()) 1512 if (!selectElement.multiple())
1512 return selectElement.value(); 1513 return selectElement.value();
1513 return String(); 1514 return String();
1514 } 1515 }
1515 1516
1516 if (isNativeTextControl()) 1517 if (isNativeTextControl())
1517 return text(); 1518 return text();
1518 1519
1520 // Handle other HTML input elements that aren't text controls, like date and time
1521 // controls, by returning the string value, with the exception of checkboxes
1522 // and radio buttons (which would return "on").
1523 if (isHTMLInputElement(node)) {
1524 HTMLInputElement* input = toHTMLInputElement(node);
1525 if (input->type() != InputTypeNames::checkbox && input->type() != InputT ypeNames::radio)
1526 return input->value();
1527 }
1528
1519 // FIXME: We might need to implement a value here for more types 1529 // FIXME: We might need to implement a value here for more types
1520 // FIXME: It would be better not to advertise a value at all for the types f or which we don't implement one; 1530 // FIXME: It would be better not to advertise a value at all for the types f or which we don't implement one;
1521 // this would require subclassing or making accessibilityAttributeNames do s omething other than return a 1531 // this would require subclassing or making accessibilityAttributeNames do s omething other than return a
1522 // single static array. 1532 // single static array.
1523 return String(); 1533 return String();
1524 } 1534 }
1525 1535
1526 String AXNodeObject::ariaDescribedByAttribute() const 1536 String AXNodeObject::ariaDescribedByAttribute() const
1527 { 1537 {
1528 WillBeHeapVector<RawPtrWillBeMember<Element>> elements; 1538 WillBeHeapVector<RawPtrWillBeMember<Element>> elements;
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
1918 } 1928 }
1919 1929
1920 // Step 2D from: http://www.w3.org/TR/accname-aam-1.1 1930 // Step 2D from: http://www.w3.org/TR/accname-aam-1.1
1921 textAlternative = nativeTextAlternative(visited, nameFrom, relatedObjects, n ameSources, &foundTextAlternative); 1931 textAlternative = nativeTextAlternative(visited, nameFrom, relatedObjects, n ameSources, &foundTextAlternative);
1922 if (!textAlternative.isNull() && !nameSources) 1932 if (!textAlternative.isNull() && !nameSources)
1923 return textAlternative; 1933 return textAlternative;
1924 1934
1925 // Step 2E from: http://www.w3.org/TR/accname-aam-1.1 1935 // Step 2E from: http://www.w3.org/TR/accname-aam-1.1
1926 if (recursive && !inAriaLabelledByTraversal && isControl()) { 1936 if (recursive && !inAriaLabelledByTraversal && isControl()) {
1927 // No need to set any name source info in a recursive call. 1937 // No need to set any name source info in a recursive call.
1928 if (roleValue() == TextFieldRole || roleValue() == ComboBoxRole)
1929 return text();
1930 if (isRange()) { 1938 if (isRange()) {
1931 const AtomicString& ariaValuetext = getAttribute(aria_valuetextAttr) ; 1939 const AtomicString& ariaValuetext = getAttribute(aria_valuetextAttr) ;
1932 if (!ariaValuetext.isNull()) 1940 if (!ariaValuetext.isNull())
1933 return ariaValuetext.string(); 1941 return ariaValuetext.string();
1934 return String::number(valueForRange()); 1942 return String::number(valueForRange());
1935 } 1943 }
1944
1945 return stringValue();
aboxhall 2015/11/05 17:49:21 I'm not sure how I feel about this. It's calling i
dmazzoni 2015/11/06 00:21:17 The current code only handles the string value of
aboxhall 2015/11/06 01:11:23 Could we possibly pull out the control-related log
dmazzoni 2015/11/06 04:54:06 Good idea! Done.
1936 } 1946 }
1937 1947
1938 // Step 2F / 2G from: http://www.w3.org/TR/accname-aam-1.1 1948 // Step 2F / 2G from: http://www.w3.org/TR/accname-aam-1.1
1939 if (recursive || nameFromContents()) { 1949 if (recursive || nameFromContents()) {
1940 nameFrom = AXNameFromContents; 1950 nameFrom = AXNameFromContents;
1941 if (nameSources) { 1951 if (nameSources) {
1942 nameSources->append(NameSource(foundTextAlternative)); 1952 nameSources->append(NameSource(foundTextAlternative));
1943 nameSources->last().type = nameFrom; 1953 nameSources->last().type = nameFrom;
1944 } 1954 }
1945 1955
1946 Node* node = this->node(); 1956 Node* node = this->node();
1947 if (node && node->isTextNode()) 1957 if (node && node->isTextNode())
1948 textAlternative = toText(node)->wholeText(); 1958 textAlternative = toText(node)->wholeText();
1959 else if (isHTMLBRElement(node))
1960 textAlternative = String("\n");
1949 else 1961 else
1950 textAlternative = textFromDescendants(visited); 1962 textAlternative = textFromDescendants(visited);
1951 1963
1952 if (!textAlternative.isEmpty()) { 1964 if (!textAlternative.isEmpty()) {
1953 if (nameSources) { 1965 if (nameSources) {
1954 foundTextAlternative = true; 1966 foundTextAlternative = true;
1955 nameSources->last().text = textAlternative; 1967 nameSources->last().text = textAlternative;
1956 } else { 1968 } else {
1957 return textAlternative; 1969 return textAlternative;
1958 } 1970 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1991 } 2003 }
1992 2004
1993 return String(); 2005 return String();
1994 } 2006 }
1995 2007
1996 String AXNodeObject::textFromDescendants(AXObjectSet& visited) const 2008 String AXNodeObject::textFromDescendants(AXObjectSet& visited) const
1997 { 2009 {
1998 StringBuilder accumulatedText; 2010 StringBuilder accumulatedText;
1999 AXObject* previous = nullptr; 2011 AXObject* previous = nullptr;
2000 for (AXObject* child = firstChild(); child; child = child->nextSibling()) { 2012 for (AXObject* child = firstChild(); child; child = child->nextSibling()) {
2013 // Skip hidden children
2014 if (child->isInertOrAriaHidden())
2015 continue;
2016
2001 // If we're going between two layoutObjects that are in separate LayoutB oxes, add 2017 // If we're going between two layoutObjects that are in separate LayoutB oxes, add
2002 // whitespace if it wasn't there already. Intuitively if you have 2018 // whitespace if it wasn't there already. Intuitively if you have
2003 // <span>Hello</span><span>World</span>, those are part of the same Layo utBox 2019 // <span>Hello</span><span>World</span>, those are part of the same Layo utBox
2004 // so we should return "HelloWorld", but given <div>Hello</div><div>Worl d</div> the 2020 // so we should return "HelloWorld", but given <div>Hello</div><div>Worl d</div> the
2005 // strings are in separate boxes so we should return "Hello World". 2021 // strings are in separate boxes so we should return "Hello World".
2006 if (previous && accumulatedText.length() && !isHTMLSpace(accumulatedText [accumulatedText.length() - 1])) { 2022 if (previous && accumulatedText.length() && !isHTMLSpace(accumulatedText [accumulatedText.length() - 1])) {
2007 if (!isInSameNonInlineBlockFlow(child->layoutObject(), previous->lay outObject())) 2023 if (!isInSameNonInlineBlockFlow(child->layoutObject(), previous->lay outObject()))
2008 accumulatedText.append(' '); 2024 accumulatedText.append(' ');
2009 } 2025 }
2010 2026
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
2218 } 2234 }
2219 2235
2220 bool AXNodeObject::canHaveChildren() const 2236 bool AXNodeObject::canHaveChildren() const
2221 { 2237 {
2222 // If this is an AXLayoutObject, then it's okay if this object 2238 // If this is an AXLayoutObject, then it's okay if this object
2223 // doesn't have a node - there are some layoutObjects that don't have associ ated 2239 // doesn't have a node - there are some layoutObjects that don't have associ ated
2224 // nodes, like scroll areas and css-generated text. 2240 // nodes, like scroll areas and css-generated text.
2225 if (!node() && !isAXLayoutObject()) 2241 if (!node() && !isAXLayoutObject())
2226 return false; 2242 return false;
2227 2243
2244 if (node() && isHTMLMapElement(node()))
2245 return false;
2246
2228 // Elements that should not have children 2247 // Elements that should not have children
2229 switch (roleValue()) { 2248 switch (roleValue()) {
2230 case ImageRole: 2249 case ImageRole:
2231 case ButtonRole: 2250 case ButtonRole:
2232 case PopUpButtonRole: 2251 case PopUpButtonRole:
2233 case CheckBoxRole: 2252 case CheckBoxRole:
2234 case RadioButtonRole: 2253 case RadioButtonRole:
2235 case SwitchRole: 2254 case SwitchRole:
2236 case TabRole: 2255 case TabRole:
2237 case ToggleButtonRole: 2256 case ToggleButtonRole:
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after
2755 source.text = textAlternative; 2774 source.text = textAlternative;
2756 *foundTextAlternative = true; 2775 *foundTextAlternative = true;
2757 } else { 2776 } else {
2758 return textAlternative; 2777 return textAlternative;
2759 } 2778 }
2760 } 2779 }
2761 } 2780 }
2762 return textAlternative; 2781 return textAlternative;
2763 } 2782 }
2764 2783
2765 // 5.8 img Element 2784 // 5.8 img or area Element
2766 if (isHTMLImageElement(node())) { 2785 if (isHTMLImageElement(node()) || isHTMLAreaElement(node()) || (layoutObject () && layoutObject()->isSVGImage())) {
2767 // alt 2786 // alt
2768 nameFrom = AXNameFromAttribute; 2787 nameFrom = AXNameFromAttribute;
2769 if (nameSources) { 2788 if (nameSources) {
2770 nameSources->append(NameSource(*foundTextAlternative, altAttr)); 2789 nameSources->append(NameSource(*foundTextAlternative, altAttr));
2771 nameSources->last().type = nameFrom; 2790 nameSources->last().type = nameFrom;
2772 } 2791 }
2773 const AtomicString& alt = getAttribute(altAttr); 2792 const AtomicString& alt = getAttribute(altAttr);
2774 if (!alt.isNull()) { 2793 if (!alt.isNull()) {
2775 textAlternative = alt; 2794 textAlternative = alt;
2776 if (nameSources) { 2795 if (nameSources) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2833 source.text = textAlternative; 2852 source.text = textAlternative;
2834 *foundTextAlternative = true; 2853 *foundTextAlternative = true;
2835 } else { 2854 } else {
2836 return textAlternative; 2855 return textAlternative;
2837 } 2856 }
2838 } 2857 }
2839 2858
2840 return textAlternative; 2859 return textAlternative;
2841 } 2860 }
2842 2861
2862 // Fieldset / legend.
aboxhall 2015/11/05 17:49:21 Wohoo! You can add http://crbug.com/550663 to the
dmazzoni 2015/11/06 00:21:17 Done.
2863 if (isHTMLFieldSetElement(node())) {
2864 nameFrom = AXNameFromRelatedElement;
2865 if (nameSources) {
2866 nameSources->append(NameSource(*foundTextAlternative));
2867 nameSources->last().type = nameFrom;
2868 nameSources->last().nativeSource = AXTextFromNativeHTMLLegend;
2869 }
2870 HTMLElement* legend = toHTMLFieldSetElement(node())->legend();
2871 if (legend) {
2872 AXObject* legendAXObject = axObjectCache().getOrCreate(legend);
2873 // Avoid an infinite loop
2874 if (legendAXObject && !visited.contains(legendAXObject)) {
2875 textAlternative = recursiveTextAlternative(*legendAXObject, fals e, visited);
2876
2877 if (relatedObjects) {
2878 localRelatedObjects.append(new NameSourceRelatedObject(legen dAXObject, textAlternative));
2879 *relatedObjects = localRelatedObjects;
2880 localRelatedObjects.clear();
2881 }
2882
2883 if (nameSources) {
2884 NameSource& source = nameSources->last();
2885 source.relatedObjects = *relatedObjects;
2886 source.text = textAlternative;
2887 source.nativeSource = AXTextFromNativeHTMLLegend;
aboxhall 2015/11/05 17:49:21 No need to re-set this.
dmazzoni 2015/11/06 00:21:17 Done.
2888 *foundTextAlternative = true;
2889 } else {
2890 return textAlternative;
2891 }
2892 }
2893 }
2894 }
2895
2843 return textAlternative; 2896 return textAlternative;
2844 } 2897 }
2845 2898
2846 String AXNodeObject::description(AXNameFrom nameFrom, AXDescriptionFrom& descrip tionFrom, AXObjectVector* descriptionObjects) const 2899 String AXNodeObject::description(AXNameFrom nameFrom, AXDescriptionFrom& descrip tionFrom, AXObjectVector* descriptionObjects) const
2847 { 2900 {
2848 AXRelatedObjectVector relatedObjects; 2901 AXRelatedObjectVector relatedObjects;
2849 String result = description(nameFrom, descriptionFrom, nullptr, &relatedObje cts); 2902 String result = description(nameFrom, descriptionFrom, nullptr, &relatedObje cts);
2850 if (descriptionObjects) { 2903 if (descriptionObjects) {
2851 descriptionObjects->clear(); 2904 descriptionObjects->clear();
2852 for (size_t i = 0; i < relatedObjects.size(); i++) 2905 for (size_t i = 0; i < relatedObjects.size(); i++)
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
3012 description = title; 3065 description = title;
3013 if (descriptionSources) { 3066 if (descriptionSources) {
3014 foundDescription = true; 3067 foundDescription = true;
3015 descriptionSources->last().text = description; 3068 descriptionSources->last().text = description;
3016 } else { 3069 } else {
3017 return description; 3070 return description;
3018 } 3071 }
3019 } 3072 }
3020 } 3073 }
3021 3074
3075 // aria-help.
3076 // FIXME: this is not part of the official standard, but it's needed because the built-in date/time controls use it.
3077 descriptionFrom = AXDescriptionFromAttribute;
3078 if (descriptionSources) {
3079 descriptionSources->append(DescriptionSource(foundDescription, aria_help Attr));
3080 descriptionSources->last().type = descriptionFrom;
3081 }
3082 const AtomicString& help = getAttribute(aria_helpAttr);
3083 if (!help.isEmpty()) {
3084 description = help;
3085 if (descriptionSources) {
3086 foundDescription = true;
3087 descriptionSources->last().text = description;
3088 } else {
3089 return description;
3090 }
3091 }
3092
3022 descriptionFrom = AXDescriptionFromUninitialized; 3093 descriptionFrom = AXDescriptionFromUninitialized;
3023 3094
3024 if (foundDescription) { 3095 if (foundDescription) {
3025 for (size_t i = 0; i < descriptionSources->size(); ++i) { 3096 for (size_t i = 0; i < descriptionSources->size(); ++i) {
3026 if (!(*descriptionSources)[i].text.isNull() && !(*descriptionSources )[i].superseded) { 3097 if (!(*descriptionSources)[i].text.isNull() && !(*descriptionSources )[i].superseded) {
3027 DescriptionSource& descriptionSource = (*descriptionSources)[i]; 3098 DescriptionSource& descriptionSource = (*descriptionSources)[i];
3028 descriptionFrom = descriptionSource.type; 3099 descriptionFrom = descriptionSource.type;
3029 if (!descriptionSource.relatedObjects.isEmpty()) 3100 if (!descriptionSource.relatedObjects.isEmpty())
3030 *relatedObjects = descriptionSource.relatedObjects; 3101 *relatedObjects = descriptionSource.relatedObjects;
3031 return descriptionSource.text; 3102 return descriptionSource.text;
3032 } 3103 }
3033 } 3104 }
3034 } 3105 }
3035 3106
3036 return String(); 3107 return String();
3037 } 3108 }
3038 3109
3039 DEFINE_TRACE(AXNodeObject) 3110 DEFINE_TRACE(AXNodeObject)
3040 { 3111 {
3041 visitor->trace(m_node); 3112 visitor->trace(m_node);
3042 AXObject::trace(visitor); 3113 AXObject::trace(visitor);
3043 } 3114 }
3044 3115
3045 } // namespace blink 3116 } // namespace blin
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698