Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008 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 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 218 return m_cachedElementRect; | 218 return m_cachedElementRect; |
| 219 } | 219 } |
| 220 | 220 |
| 221 LayoutBoxModelObject* AXLayoutObject::getLayoutBoxModelObject() const | 221 LayoutBoxModelObject* AXLayoutObject::getLayoutBoxModelObject() const |
| 222 { | 222 { |
| 223 if (!m_layoutObject || !m_layoutObject->isBoxModelObject()) | 223 if (!m_layoutObject || !m_layoutObject->isBoxModelObject()) |
| 224 return 0; | 224 return 0; |
| 225 return toLayoutBoxModelObject(m_layoutObject); | 225 return toLayoutBoxModelObject(m_layoutObject); |
| 226 } | 226 } |
| 227 | 227 |
| 228 bool AXLayoutObject::shouldNotifyActiveDescendant() const | |
| 229 { | |
| 230 // We want to notify that the combo box has changed its active descendant, | |
| 231 // but we do not want to change the focus, because focus should remain with the combo box. | |
| 232 if (isComboBox()) | |
| 233 return true; | |
| 234 | |
| 235 return shouldFocusActiveDescendant(); | |
| 236 } | |
| 237 | |
| 238 ScrollableArea* AXLayoutObject::getScrollableAreaIfScrollable() const | 228 ScrollableArea* AXLayoutObject::getScrollableAreaIfScrollable() const |
| 239 { | 229 { |
| 240 if (isWebArea()) | 230 if (isWebArea()) |
| 241 return documentFrameView(); | 231 return documentFrameView(); |
| 242 | 232 |
| 243 if (!m_layoutObject || !m_layoutObject->isBox()) | 233 if (!m_layoutObject || !m_layoutObject->isBox()) |
| 244 return 0; | 234 return 0; |
| 245 | 235 |
| 246 LayoutBox* box = toLayoutBox(m_layoutObject); | 236 LayoutBox* box = toLayoutBox(m_layoutObject); |
| 247 if (!box->canBeScrolledAndHasScrollableArea()) | 237 if (!box->canBeScrolledAndHasScrollableArea()) |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 449 bool AXLayoutObject::isVisited() const | 439 bool AXLayoutObject::isVisited() const |
| 450 { | 440 { |
| 451 // FIXME: Is it a privacy violation to expose visited information to accessi bility APIs? | 441 // FIXME: Is it a privacy violation to expose visited information to accessi bility APIs? |
| 452 return m_layoutObject->style()->isLink() && m_layoutObject->style()->insideL ink() == InsideVisitedLink; | 442 return m_layoutObject->style()->isLink() && m_layoutObject->style()->insideL ink() == InsideVisitedLink; |
| 453 } | 443 } |
| 454 | 444 |
| 455 // | 445 // |
| 456 // Check object state. | 446 // Check object state. |
| 457 // | 447 // |
| 458 | 448 |
| 459 bool AXLayoutObject::isFocused() const | 449 bool AXLayoutObject::isFocused() const |
|
dmazzoni
2016/03/31 05:48:30
We don't actually call isFocused from outside of B
| |
| 460 { | 450 { |
| 461 if (!m_layoutObject) | 451 if (!getDocument()) |
| 462 return false; | 452 return false; |
| 463 | 453 |
| 464 Document& document = m_layoutObject->document(); | 454 Element* focusedElement = getDocument()->focusedElement(); |
| 465 Element* focusedElement = document.focusedElement(); | |
| 466 if (!focusedElement) | 455 if (!focusedElement) |
| 467 return false; | 456 return false; |
| 457 AXObject* focusedObject = axObjectCache().getOrCreate(focusedElement); | |
| 458 if (!focusedObject || !focusedObject->isAXLayoutObject()) | |
| 459 return false; | |
| 468 | 460 |
| 469 // A web area is represented by the Document node in the DOM tree, which isn 't focusable. | 461 // A web area is represented by the Document node in the DOM tree, which isn 't focusable. |
| 470 // Check instead if the frame's selection controller is focused | 462 // Check instead if the frame's selection controller is focused |
| 471 if (focusedElement == m_layoutObject->node() | 463 if (focusedObject == this || focusedObject->activeDescendant() == this |
| 472 || (roleValue() == WebAreaRole && document.frame()->selection().isFocuse dAndActive())) | 464 || (roleValue() == WebAreaRole && getDocument()->frame()->selection().is FocusedAndActive())) |
| 473 return true; | 465 return true; |
| 474 | 466 |
| 475 return false; | 467 return false; |
| 476 } | 468 } |
| 477 | 469 |
| 478 bool AXLayoutObject::isSelected() const | 470 bool AXLayoutObject::isSelected() const |
| 479 { | 471 { |
| 480 if (!m_layoutObject) | 472 if (!getLayoutObject() || !getNode()) |
| 481 return false; | |
| 482 | |
| 483 Node* node = m_layoutObject->node(); | |
| 484 if (!node) | |
| 485 return false; | 473 return false; |
| 486 | 474 |
| 487 const AtomicString& ariaSelected = getAttribute(aria_selectedAttr); | 475 const AtomicString& ariaSelected = getAttribute(aria_selectedAttr); |
| 488 if (equalIgnoringCase(ariaSelected, "true")) | 476 if (equalIgnoringCase(ariaSelected, "true")) |
| 489 return true; | 477 return true; |
| 490 | 478 |
| 479 if (ariaRoleAttribute() == ListBoxOptionRole && isFocused()) | |
| 480 return true; | |
| 481 | |
| 491 if (isTabItem() && isTabItemSelected()) | 482 if (isTabItem() && isTabItemSelected()) |
| 492 return true; | 483 return true; |
| 493 | 484 |
| 494 return false; | 485 return false; |
| 495 } | 486 } |
| 496 | 487 |
| 497 // | 488 // |
| 498 // Whether objects are ignored, i.e. not included in the tree. | 489 // Whether objects are ignored, i.e. not included in the tree. |
| 499 // | 490 // |
| 500 | 491 |
| (...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1155 | 1146 |
| 1156 return AXNodeObject::textAlternative(recursive, inAriaLabelledByTraversal, v isited, nameFrom, relatedObjects, nameSources); | 1147 return AXNodeObject::textAlternative(recursive, inAriaLabelledByTraversal, v isited, nameFrom, relatedObjects, nameSources); |
| 1157 } | 1148 } |
| 1158 | 1149 |
| 1159 // | 1150 // |
| 1160 // ARIA attributes. | 1151 // ARIA attributes. |
| 1161 // | 1152 // |
| 1162 | 1153 |
| 1163 AXObject* AXLayoutObject::activeDescendant() const | 1154 AXObject* AXLayoutObject::activeDescendant() const |
| 1164 { | 1155 { |
| 1165 if (!m_layoutObject) | 1156 if (!getLayoutObject() || !getNode()) |
|
dmazzoni
2016/03/31 05:48:30
Hmmm, is there a reason we need a layoutObject? Ma
| |
| 1166 return 0; | 1157 return nullptr; |
| 1167 | 1158 |
| 1168 if (m_layoutObject->node() && !m_layoutObject->node()->isElementNode()) | 1159 if (!getNode()->isElementNode()) |
| 1169 return 0; | 1160 return nullptr; |
| 1170 | 1161 |
| 1171 Element* element = toElement(m_layoutObject->node()); | 1162 Element* element = toElement(getNode()); |
| 1172 if (!element) | 1163 if (!element) |
| 1173 return 0; | 1164 return nullptr; |
| 1174 | 1165 |
| 1175 const AtomicString& activeDescendantAttrStr = element->getAttribute(aria_act ivedescendantAttr); | 1166 const AtomicString& activeDescendantAttr = getAttribute(aria_activedescendan tAttr); |
| 1176 if (activeDescendantAttrStr.isNull() || activeDescendantAttrStr.isEmpty()) | 1167 if (activeDescendantAttr.isNull() || activeDescendantAttr.isEmpty()) |
| 1177 return 0; | 1168 return nullptr; |
| 1178 | 1169 |
| 1179 Element* target = element->treeScope().getElementById(activeDescendantAttrSt r); | 1170 Element* target = element->treeScope().getElementById(activeDescendantAttr); |
| 1180 if (!target) | 1171 if (!target) |
| 1181 return 0; | 1172 return nullptr; |
| 1182 | 1173 |
| 1183 AXObject* obj = axObjectCache().getOrCreate(target); | 1174 AXObject* obj = axObjectCache().getOrCreate(target); |
| 1184 | |
| 1185 // An activedescendant is only useful if it has a layoutObject, because that 's what's needed to post the notification. | 1175 // An activedescendant is only useful if it has a layoutObject, because that 's what's needed to post the notification. |
| 1186 if (obj && obj->isAXLayoutObject()) | 1176 if (obj && obj->isAXLayoutObject()) |
| 1187 return obj; | 1177 return obj; |
| 1188 | 1178 |
| 1189 return 0; | 1179 return nullptr; |
| 1190 } | 1180 } |
| 1191 | 1181 |
| 1192 void AXLayoutObject::ariaFlowToElements(AXObjectVector& flowTo) const | 1182 void AXLayoutObject::ariaFlowToElements(AXObjectVector& flowTo) const |
| 1193 { | 1183 { |
| 1194 accessibilityChildrenFromAttribute(aria_flowtoAttr, flowTo); | 1184 accessibilityChildrenFromAttribute(aria_flowtoAttr, flowTo); |
| 1195 } | 1185 } |
| 1196 | 1186 |
| 1197 void AXLayoutObject::ariaControlsElements(AXObjectVector& controls) const | 1187 void AXLayoutObject::ariaControlsElements(AXObjectVector& controls) const |
| 1198 { | 1188 { |
| 1199 accessibilityChildrenFromAttribute(aria_controlsAttr, controls); | 1189 accessibilityChildrenFromAttribute(aria_controlsAttr, controls); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1247 // AXMenuListOptions, which are not AXLayoutObjects.) | 1237 // AXMenuListOptions, which are not AXLayoutObjects.) |
| 1248 if (parent->isMenuList()) | 1238 if (parent->isMenuList()) |
| 1249 break; | 1239 break; |
| 1250 | 1240 |
| 1251 parent = parent->parentObjectIfExists(); | 1241 parent = parent->parentObjectIfExists(); |
| 1252 } | 1242 } |
| 1253 | 1243 |
| 1254 return parent; | 1244 return parent; |
| 1255 } | 1245 } |
| 1256 | 1246 |
| 1257 bool AXLayoutObject::shouldFocusActiveDescendant() const | |
| 1258 { | |
| 1259 switch (ariaRoleAttribute()) { | |
| 1260 case ComboBoxRole: | |
| 1261 case GridRole: | |
| 1262 case GroupRole: | |
| 1263 case ListBoxRole: | |
| 1264 case MenuRole: | |
| 1265 case MenuBarRole: | |
| 1266 case OutlineRole: | |
| 1267 case PopUpButtonRole: | |
| 1268 case ProgressIndicatorRole: | |
| 1269 case RadioGroupRole: | |
| 1270 case RowRole: | |
| 1271 case TabListRole: | |
| 1272 case ToolbarRole: | |
| 1273 case TreeRole: | |
| 1274 case TreeGridRole: | |
| 1275 return true; | |
| 1276 default: | |
| 1277 return false; | |
| 1278 } | |
| 1279 } | |
| 1280 | |
| 1281 bool AXLayoutObject::supportsARIADragging() const | 1247 bool AXLayoutObject::supportsARIADragging() const |
| 1282 { | 1248 { |
| 1283 const AtomicString& grabbed = getAttribute(aria_grabbedAttr); | 1249 const AtomicString& grabbed = getAttribute(aria_grabbedAttr); |
| 1284 return equalIgnoringCase(grabbed, "true") || equalIgnoringCase(grabbed, "fal se"); | 1250 return equalIgnoringCase(grabbed, "true") || equalIgnoringCase(grabbed, "fal se"); |
| 1285 } | 1251 } |
| 1286 | 1252 |
| 1287 bool AXLayoutObject::supportsARIADropping() const | 1253 bool AXLayoutObject::supportsARIADropping() const |
| 1288 { | 1254 { |
| 1289 const AtomicString& dropEffect = getAttribute(aria_dropeffectAttr); | 1255 const AtomicString& dropEffect = getAttribute(aria_dropeffectAttr); |
| 1290 return !dropEffect.isEmpty(); | 1256 return !dropEffect.isEmpty(); |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1698 return frame->loader().progress().estimatedProgress(); | 1664 return frame->loader().progress().estimatedProgress(); |
| 1699 return 0; | 1665 return 0; |
| 1700 } | 1666 } |
| 1701 | 1667 |
| 1702 // | 1668 // |
| 1703 // DOM and layout tree access. | 1669 // DOM and layout tree access. |
| 1704 // | 1670 // |
| 1705 | 1671 |
| 1706 Node* AXLayoutObject::getNode() const | 1672 Node* AXLayoutObject::getNode() const |
| 1707 { | 1673 { |
| 1708 return m_layoutObject ? m_layoutObject->node() : 0; | 1674 return getLayoutObject() ? getLayoutObject()->node() : nullptr; |
| 1709 } | 1675 } |
| 1710 | 1676 |
| 1711 Document* AXLayoutObject::getDocument() const | 1677 Document* AXLayoutObject::getDocument() const |
| 1712 { | 1678 { |
| 1713 if (!m_layoutObject) | 1679 if (!getLayoutObject()) |
| 1714 return 0; | 1680 return nullptr; |
| 1715 return &m_layoutObject->document(); | 1681 return &getLayoutObject()->document(); |
| 1716 } | 1682 } |
| 1717 | 1683 |
| 1718 FrameView* AXLayoutObject::documentFrameView() const | 1684 FrameView* AXLayoutObject::documentFrameView() const |
| 1719 { | 1685 { |
| 1720 if (!m_layoutObject) | 1686 if (!m_layoutObject) |
| 1721 return 0; | 1687 return 0; |
| 1722 | 1688 |
| 1723 // this is the LayoutObject's Document's LocalFrame's FrameView | 1689 // this is the LayoutObject's Document's LocalFrame's FrameView |
| 1724 return m_layoutObject->document().view(); | 1690 return m_layoutObject->document().view(); |
| 1725 } | 1691 } |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2003 else if (layoutObject->isTextArea() && isHTMLTextAreaElement(*getNode())) | 1969 else if (layoutObject->isTextArea() && isHTMLTextAreaElement(*getNode())) |
| 2004 toHTMLTextAreaElement(*getNode()).setValue(string, DispatchInputAndChang eEvent); | 1970 toHTMLTextAreaElement(*getNode()).setValue(string, DispatchInputAndChang eEvent); |
| 2005 } | 1971 } |
| 2006 | 1972 |
| 2007 // | 1973 // |
| 2008 // Notifications that this object may have changed. | 1974 // Notifications that this object may have changed. |
| 2009 // | 1975 // |
| 2010 | 1976 |
| 2011 void AXLayoutObject::handleActiveDescendantChanged() | 1977 void AXLayoutObject::handleActiveDescendantChanged() |
| 2012 { | 1978 { |
| 2013 Element* element = toElement(getLayoutObject()->node()); | 1979 Element* element = toElement(getNode()); |
| 2014 if (!element) | 1980 if (!element) |
| 2015 return; | 1981 return; |
| 2016 Document& doc = getLayoutObject()->document(); | 1982 Document& doc = getLayoutObject()->document(); |
| 2017 if (!doc.frame()->selection().isFocusedAndActive() || doc.focusedElement() ! = element) | 1983 if (!doc.frame()->selection().isFocusedAndActive() || doc.focusedElement() ! = element) |
| 2018 return; | 1984 return; |
| 2019 AXLayoutObject* activedescendant = toAXLayoutObject(activeDescendant()); | |
| 2020 | 1985 |
| 2021 if (activedescendant && shouldNotifyActiveDescendant()) | 1986 if (supportsActiveDescendant()) |
| 2022 toAXObjectCacheImpl(doc.axObjectCache())->postNotification(m_layoutObjec t, AXObjectCacheImpl::AXActiveDescendantChanged); | 1987 toAXObjectCacheImpl(doc.axObjectCache())->postNotification(getLayoutObje ct(), AXObjectCacheImpl::AXActiveDescendantChanged); |
| 2023 } | 1988 } |
| 2024 | 1989 |
| 2025 void AXLayoutObject::handleAriaExpandedChanged() | 1990 void AXLayoutObject::handleAriaExpandedChanged() |
| 2026 { | 1991 { |
| 2027 // Find if a parent of this object should handle aria-expanded changes. | 1992 // Find if a parent of this object should handle aria-expanded changes. |
| 2028 AXObject* containerParent = this->parentObject(); | 1993 AXObject* containerParent = this->parentObject(); |
| 2029 while (containerParent) { | 1994 while (containerParent) { |
| 2030 bool foundParent = false; | 1995 bool foundParent = false; |
| 2031 | 1996 |
| 2032 switch (containerParent->roleValue()) { | 1997 switch (containerParent->roleValue()) { |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2185 if (treeAncestor) { | 2150 if (treeAncestor) { |
| 2186 AccessibilityRole role = roleValue(); | 2151 AccessibilityRole role = roleValue(); |
| 2187 if (role != TreeItemRole && role != StaticTextRole) | 2152 if (role != TreeItemRole && role != StaticTextRole) |
| 2188 return treeAncestor; | 2153 return treeAncestor; |
| 2189 } | 2154 } |
| 2190 return 0; | 2155 return 0; |
| 2191 } | 2156 } |
| 2192 | 2157 |
| 2193 bool AXLayoutObject::isTabItemSelected() const | 2158 bool AXLayoutObject::isTabItemSelected() const |
| 2194 { | 2159 { |
| 2195 if (!isTabItem() || !m_layoutObject) | 2160 if (!isTabItem() || !getLayoutObject()) |
| 2196 return false; | 2161 return false; |
| 2197 | 2162 |
| 2198 Node* node = m_layoutObject->node(); | 2163 Node* node = getNode(); |
| 2199 if (!node || !node->isElementNode()) | 2164 if (!node || !node->isElementNode()) |
| 2200 return false; | 2165 return false; |
| 2201 | 2166 |
| 2202 // The ARIA spec says a tab item can also be selected if it is aria-labeled by a tabpanel | 2167 // The ARIA spec says a tab item can also be selected if it is aria-labeled by a tabpanel |
| 2203 // that has keyboard focus inside of it, or if a tabpanel in its aria-contro ls list has KB | 2168 // that has keyboard focus inside of it, or if a tabpanel in its aria-contro ls list has KB |
| 2204 // focus inside of it. | 2169 // focus inside of it. |
| 2205 AXObject* focusedElement = axObjectCache().focusedObject(); | 2170 AXObject* focusedElement = axObjectCache().focusedObject(); |
| 2206 if (!focusedElement) | 2171 if (!focusedElement) |
| 2207 return false; | 2172 return false; |
| 2208 | 2173 |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2508 if (label && label->layoutObject()) { | 2473 if (label && label->layoutObject()) { |
| 2509 LayoutRect labelRect = axObjectCache().getOrCreate(label)->elementRe ct(); | 2474 LayoutRect labelRect = axObjectCache().getOrCreate(label)->elementRe ct(); |
| 2510 result.unite(labelRect); | 2475 result.unite(labelRect); |
| 2511 } | 2476 } |
| 2512 } | 2477 } |
| 2513 | 2478 |
| 2514 return result; | 2479 return result; |
| 2515 } | 2480 } |
| 2516 | 2481 |
| 2517 } // namespace blink | 2482 } // namespace blink |
| OLD | NEW |