Chromium Code Reviews| 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 43 #include "core/html/HTMLMediaElement.h" | 43 #include "core/html/HTMLMediaElement.h" |
| 44 #include "core/html/HTMLMeterElement.h" | 44 #include "core/html/HTMLMeterElement.h" |
| 45 #include "core/html/HTMLPlugInElement.h" | 45 #include "core/html/HTMLPlugInElement.h" |
| 46 #include "core/html/HTMLSelectElement.h" | 46 #include "core/html/HTMLSelectElement.h" |
| 47 #include "core/html/HTMLTableCaptionElement.h" | 47 #include "core/html/HTMLTableCaptionElement.h" |
| 48 #include "core/html/HTMLTableCellElement.h" | 48 #include "core/html/HTMLTableCellElement.h" |
| 49 #include "core/html/HTMLTableElement.h" | 49 #include "core/html/HTMLTableElement.h" |
| 50 #include "core/html/HTMLTableRowElement.h" | 50 #include "core/html/HTMLTableRowElement.h" |
| 51 #include "core/html/HTMLTableSectionElement.h" | 51 #include "core/html/HTMLTableSectionElement.h" |
| 52 #include "core/html/HTMLTextAreaElement.h" | 52 #include "core/html/HTMLTextAreaElement.h" |
| 53 #include "core/html/LabelsNodeList.h" | |
| 53 #include "core/html/parser/HTMLParserIdioms.h" | 54 #include "core/html/parser/HTMLParserIdioms.h" |
| 54 #include "core/html/shadow/MediaControlElements.h" | 55 #include "core/html/shadow/MediaControlElements.h" |
| 55 #include "core/layout/LayoutBlockFlow.h" | 56 #include "core/layout/LayoutBlockFlow.h" |
| 56 #include "core/layout/LayoutObject.h" | 57 #include "core/layout/LayoutObject.h" |
| 57 #include "core/svg/SVGElement.h" | 58 #include "core/svg/SVGElement.h" |
| 58 #include "modules/accessibility/AXObjectCacheImpl.h" | 59 #include "modules/accessibility/AXObjectCacheImpl.h" |
| 59 #include "platform/UserGestureIndicator.h" | 60 #include "platform/UserGestureIndicator.h" |
| 60 #include "platform/text/PlatformLocale.h" | 61 #include "platform/text/PlatformLocale.h" |
| 61 #include "wtf/text/StringBuilder.h" | 62 #include "wtf/text/StringBuilder.h" |
| 62 | 63 |
| (...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 636 return false; | 637 return false; |
| 637 | 638 |
| 638 // An SVG root is focusable by default, but it's probably not interactive, s o don't | 639 // An SVG root is focusable by default, but it's probably not interactive, s o don't |
| 639 // include it. It can still be made accessible by giving it an ARIA role. | 640 // include it. It can still be made accessible by giving it an ARIA role. |
| 640 if (roleValue() == SVGRootRole) | 641 if (roleValue() == SVGRootRole) |
| 641 return false; | 642 return false; |
| 642 | 643 |
| 643 return true; | 644 return true; |
| 644 } | 645 } |
| 645 | 646 |
| 646 HTMLLabelElement* AXNodeObject::labelForElement(const Element* element) const | |
| 647 { | |
| 648 if (!element->isHTMLElement() || !toHTMLElement(element)->isLabelable()) | |
| 649 return 0; | |
| 650 | |
| 651 const AtomicString& id = element->getIdAttribute(); | |
| 652 if (!id.isEmpty()) { | |
| 653 if (HTMLLabelElement* labelFor = element->treeScope().labelElementForId( id)) | |
| 654 return labelFor; | |
| 655 } | |
| 656 | |
| 657 HTMLLabelElement* labelWrappedElement = Traversal<HTMLLabelElement>::firstAn cestor(*element); | |
| 658 if (labelWrappedElement && labelWrappedElement->control() == toLabelableElem ent(element)) | |
| 659 return labelWrappedElement; | |
| 660 | |
| 661 return 0; | |
| 662 } | |
| 663 | |
| 664 AXObject* AXNodeObject::menuButtonForMenu() const | 647 AXObject* AXNodeObject::menuButtonForMenu() const |
| 665 { | 648 { |
| 666 Element* menuItem = menuItemElementForMenu(); | 649 Element* menuItem = menuItemElementForMenu(); |
| 667 | 650 |
| 668 if (menuItem) { | 651 if (menuItem) { |
| 669 // ARIA just has generic menu items. AppKit needs to know if this is a t op level items like MenuBarButton or MenuBarItem | 652 // ARIA just has generic menu items. AppKit needs to know if this is a t op level items like MenuBarButton or MenuBarItem |
| 670 AXObject* menuItemAX = axObjectCache().getOrCreate(menuItem); | 653 AXObject* menuItemAX = axObjectCache().getOrCreate(menuItem); |
| 671 if (menuItemAX && menuItemAX->isMenuButton()) | 654 if (menuItemAX && menuItemAX->isMenuButton()) |
| 672 return menuItemAX; | 655 return menuItemAX; |
| 673 } | 656 } |
| (...skipping 933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1607 if (nameSources) { | 1590 if (nameSources) { |
| 1608 foundTextAlternative = true; | 1591 foundTextAlternative = true; |
| 1609 nameSources->last().text = textAlternative; | 1592 nameSources->last().text = textAlternative; |
| 1610 } else { | 1593 } else { |
| 1611 return textAlternative; | 1594 return textAlternative; |
| 1612 } | 1595 } |
| 1613 } | 1596 } |
| 1614 | 1597 |
| 1615 nameFrom = AXNameFromUninitialized; | 1598 nameFrom = AXNameFromUninitialized; |
| 1616 | 1599 |
| 1617 if (foundTextAlternative) { | 1600 if (nameSources && foundTextAlternative) { |
| 1618 for (size_t i = 0; i < nameSources->size(); ++i) { | 1601 for (size_t i = 0; i < nameSources->size(); ++i) { |
| 1619 if (!(*nameSources)[i].text.isNull() && !(*nameSources)[i].supersede d) { | 1602 if (!(*nameSources)[i].text.isNull() && !(*nameSources)[i].supersede d) { |
| 1620 NameSource& nameSource = (*nameSources)[i]; | 1603 NameSource& nameSource = (*nameSources)[i]; |
| 1621 nameFrom = nameSource.type; | 1604 nameFrom = nameSource.type; |
| 1622 if (!nameSource.relatedObjects.isEmpty()) | 1605 if (!nameSource.relatedObjects.isEmpty()) |
| 1623 *relatedObjects = nameSource.relatedObjects; | 1606 *relatedObjects = nameSource.relatedObjects; |
| 1624 return nameSource.text; | 1607 return nameSource.text; |
| 1625 } | 1608 } |
| 1626 } | 1609 } |
| 1627 } | 1610 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1701 // Step 2C from: http://www.w3.org/TR/accname-aam-1.1 | 1684 // Step 2C from: http://www.w3.org/TR/accname-aam-1.1 |
| 1702 const AtomicString& ariaLabel = getAttribute(aria_labelAttr); | 1685 const AtomicString& ariaLabel = getAttribute(aria_labelAttr); |
| 1703 if (!ariaLabel.isEmpty()) | 1686 if (!ariaLabel.isEmpty()) |
| 1704 return false; | 1687 return false; |
| 1705 | 1688 |
| 1706 // Based on http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessi ble-name-and-description-calculation | 1689 // Based on http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessi ble-name-and-description-calculation |
| 1707 // 5.1/5.5 Text inputs, Other labelable Elements | 1690 // 5.1/5.5 Text inputs, Other labelable Elements |
| 1708 HTMLElement* htmlElement = nullptr; | 1691 HTMLElement* htmlElement = nullptr; |
| 1709 if (getNode()->isHTMLElement()) | 1692 if (getNode()->isHTMLElement()) |
| 1710 htmlElement = toHTMLElement(getNode()); | 1693 htmlElement = toHTMLElement(getNode()); |
| 1711 if (htmlElement && htmlElement->isLabelable()) { | 1694 if (htmlElement && isLabelableElement(htmlElement)) { |
| 1712 HTMLLabelElement* label = labelForElement(htmlElement); | 1695 if (toLabelableElement(htmlElement)->labels() && toLabelableElement(html Element)->labels()->length() > 0) |
| 1713 if (label) | |
| 1714 return true; | 1696 return true; |
| 1715 } | 1697 } |
| 1716 | 1698 |
| 1717 return false; | 1699 return false; |
| 1718 } | 1700 } |
| 1719 | 1701 |
| 1720 LayoutRect AXNodeObject::elementRect() const | 1702 LayoutRect AXNodeObject::elementRect() const |
| 1721 { | 1703 { |
| 1722 // First check if it has a custom rect, for example if this element is tied to a canvas path. | 1704 // First check if it has a custom rect, for example if this element is tied to a canvas path. |
| 1723 if (!m_explicitElementRect.isEmpty()) | 1705 if (!m_explicitElementRect.isEmpty()) |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2170 | 2152 |
| 2171 const HTMLInputElement* inputElement = nullptr; | 2153 const HTMLInputElement* inputElement = nullptr; |
| 2172 if (isHTMLInputElement(getNode())) | 2154 if (isHTMLInputElement(getNode())) |
| 2173 inputElement = toHTMLInputElement(getNode()); | 2155 inputElement = toHTMLInputElement(getNode()); |
| 2174 | 2156 |
| 2175 // 5.1/5.5 Text inputs, Other labelable Elements | 2157 // 5.1/5.5 Text inputs, Other labelable Elements |
| 2176 // If you change this logic, update AXNodeObject::nameFromLabelElement, too. | 2158 // If you change this logic, update AXNodeObject::nameFromLabelElement, too. |
| 2177 HTMLElement* htmlElement = nullptr; | 2159 HTMLElement* htmlElement = nullptr; |
| 2178 if (getNode()->isHTMLElement()) | 2160 if (getNode()->isHTMLElement()) |
| 2179 htmlElement = toHTMLElement(getNode()); | 2161 htmlElement = toHTMLElement(getNode()); |
| 2162 | |
| 2180 if (htmlElement && htmlElement->isLabelable()) { | 2163 if (htmlElement && htmlElement->isLabelable()) { |
| 2181 // label | 2164 LabelsNodeList* labels = toLabelableElement(htmlElement)->labels(); |
| 2182 nameFrom = AXNameFromRelatedElement; | 2165 if (labels && labels->length() > 0) { |
| 2183 if (nameSources) { | 2166 nameFrom = AXNameFromRelatedElement; |
|
aboxhall
2016/05/13 20:19:16
This needs to be set outside this if block, as bef
dmazzoni
2016/05/13 22:22:42
OK, done. I was thinking it was okay to skip it if
| |
| 2184 nameSources->append(NameSource(*foundTextAlternative)); | 2167 StringBuilder accumulatedText; |
| 2185 nameSources->last().type = nameFrom; | 2168 for (unsigned labelIndex = 0; labelIndex < labels->length(); ++label Index) { |
| 2186 nameSources->last().nativeSource = AXTextFromNativeHTMLLabel; | 2169 Element* label = labels->item(labelIndex); |
| 2187 } | 2170 AXObject* labelAXObject = axObjectCache().getOrCreate(label); |
| 2188 HTMLLabelElement* label = labelForElement(htmlElement); | 2171 // Avoid an infinite loop for label wrapped |
| 2189 if (label) { | 2172 if (labelAXObject && !visited.contains(labelAXObject)) { |
| 2190 AXObject* labelAXObject = axObjectCache().getOrCreate(label); | 2173 String result = recursiveTextAlternative(*labelAXObject, fal se, visited); |
| 2191 // Avoid an infinite loop for label wrapped | 2174 if (!result.isEmpty()) { |
| 2192 if (labelAXObject && !visited.contains(labelAXObject)) { | 2175 if (!accumulatedText.isEmpty()) |
| 2193 textAlternative = recursiveTextAlternative(*labelAXObject, false , visited); | 2176 accumulatedText.append(" "); |
| 2177 accumulatedText.append(result); | |
| 2178 } | |
| 2194 | 2179 |
| 2195 if (relatedObjects) { | 2180 if (relatedObjects) { |
| 2196 localRelatedObjects.append(new NameSourceRelatedObject(label AXObject, textAlternative)); | 2181 localRelatedObjects.append(new NameSourceRelatedObject(l abelAXObject, result)); |
| 2197 *relatedObjects = localRelatedObjects; | 2182 *relatedObjects = localRelatedObjects; |
| 2198 localRelatedObjects.clear(); | 2183 } |
| 2199 } | |
| 2200 | 2184 |
| 2201 if (nameSources) { | 2185 if (nameSources) { |
| 2202 NameSource& source = nameSources->last(); | 2186 nameSources->append(NameSource(*foundTextAlternative)); |
| 2203 source.relatedObjects = *relatedObjects; | 2187 NameSource& source = nameSources->last(); |
| 2204 source.text = textAlternative; | 2188 source.type = nameFrom; |
| 2205 if (label->getAttribute(forAttr) == htmlElement->getIdAttrib ute()) | 2189 source.nativeSource = AXTextFromNativeHTMLLabel; |
| 2206 source.nativeSource = AXTextFromNativeHTMLLabelFor; | 2190 source.relatedObjects = *relatedObjects; |
| 2207 else | 2191 source.text = textAlternative; |
| 2208 source.nativeSource = AXTextFromNativeHTMLLabelWrapped; | 2192 if (label->getAttribute(forAttr) == htmlElement->getIdAt tribute()) |
| 2209 *foundTextAlternative = true; | 2193 source.nativeSource = AXTextFromNativeHTMLLabelFor; |
| 2210 } else { | 2194 else |
| 2211 return textAlternative; | 2195 source.nativeSource = AXTextFromNativeHTMLLabelWrapp ed; |
| 2196 } | |
| 2212 } | 2197 } |
| 2213 } | 2198 } |
| 2199 | |
| 2200 if (relatedObjects) | |
| 2201 localRelatedObjects.clear(); | |
| 2202 | |
| 2203 textAlternative = accumulatedText.toString(); | |
| 2204 *foundTextAlternative = true; | |
| 2205 | |
| 2206 if (!nameSources) | |
| 2207 return textAlternative; | |
| 2214 } | 2208 } |
| 2215 } | 2209 } |
| 2216 | 2210 |
| 2217 // 5.2 input type="button", input type="submit" and input type="reset" | 2211 // 5.2 input type="button", input type="submit" and input type="reset" |
| 2218 if (inputElement && inputElement->isTextButton()) { | 2212 if (inputElement && inputElement->isTextButton()) { |
| 2219 // value attribue | 2213 // value attribue |
| 2220 nameFrom = AXNameFromValue; | 2214 nameFrom = AXNameFromValue; |
| 2221 if (nameSources) { | 2215 if (nameSources) { |
| 2222 nameSources->append(NameSource(*foundTextAlternative, valueAttr)); | 2216 nameSources->append(NameSource(*foundTextAlternative, valueAttr)); |
| 2223 nameSources->last().type = nameFrom; | 2217 nameSources->last().type = nameFrom; |
| (...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2792 return placeholder; | 2786 return placeholder; |
| 2793 } | 2787 } |
| 2794 | 2788 |
| 2795 DEFINE_TRACE(AXNodeObject) | 2789 DEFINE_TRACE(AXNodeObject) |
| 2796 { | 2790 { |
| 2797 visitor->trace(m_node); | 2791 visitor->trace(m_node); |
| 2798 AXObject::trace(visitor); | 2792 AXObject::trace(visitor); |
| 2799 } | 2793 } |
| 2800 | 2794 |
| 2801 } // namespace blink | 2795 } // namespace blink |
| OLD | NEW |