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

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

Issue 2393003002: reflow comments in modules/accessiblity (Closed)
Patch Set: Created 4 years, 2 months 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 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 } 177 }
178 178
179 bool AXNodeObject::computeAccessibilityIsIgnored( 179 bool AXNodeObject::computeAccessibilityIsIgnored(
180 IgnoredReasons* ignoredReasons) const { 180 IgnoredReasons* ignoredReasons) const {
181 #if ENABLE(ASSERT) 181 #if ENABLE(ASSERT)
182 // Double-check that an AXObject is never accessed before 182 // Double-check that an AXObject is never accessed before
183 // it's been initialized. 183 // it's been initialized.
184 ASSERT(m_initialized); 184 ASSERT(m_initialized);
185 #endif 185 #endif
186 186
187 // If this element is within a parent that cannot have children, it should not be exposed. 187 // If this element is within a parent that cannot have children, it should not
188 // be exposed.
188 if (isDescendantOfLeafNode()) { 189 if (isDescendantOfLeafNode()) {
189 if (ignoredReasons) 190 if (ignoredReasons)
190 ignoredReasons->append( 191 ignoredReasons->append(
191 IgnoredReason(AXAncestorIsLeafNode, leafNodeAncestor())); 192 IgnoredReason(AXAncestorIsLeafNode, leafNodeAncestor()));
192 return true; 193 return true;
193 } 194 }
194 195
195 // Ignore labels that are already referenced by a control. 196 // Ignore labels that are already referenced by a control.
196 AXObject* controlObject = correspondingControlForLabelElement(); 197 AXObject* controlObject = correspondingControlForLabelElement();
197 if (controlObject && controlObject->isCheckboxOrRadio() && 198 if (controlObject && controlObject->isCheckboxOrRadio() &&
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 static bool isPresentationalInTable(AXObject* parent, 234 static bool isPresentationalInTable(AXObject* parent,
234 HTMLElement* currentElement) { 235 HTMLElement* currentElement) {
235 if (!currentElement) 236 if (!currentElement)
236 return false; 237 return false;
237 238
238 Node* parentNode = parent->getNode(); 239 Node* parentNode = parent->getNode();
239 if (!parentNode || !parentNode->isHTMLElement()) 240 if (!parentNode || !parentNode->isHTMLElement())
240 return false; 241 return false;
241 242
242 // AXTable determines the role as checking isTableXXX. 243 // AXTable determines the role as checking isTableXXX.
243 // If Table has explicit role including presentation, AXTable doesn't assign i mplicit Role 244 // If Table has explicit role including presentation, AXTable doesn't assign
244 // to a whole Table. That's why we should check it based on node. 245 // implicit Role to a whole Table. That's why we should check it based on
246 // node.
245 // Normal Table Tree is that 247 // Normal Table Tree is that
246 // cell(its role)-> tr(tr role)-> tfoot, tbody, thead(ignored role) -> table(t able role). 248 // cell(its role)-> tr(tr role)-> tfoot, tbody, thead(ignored role) ->
249 // table(table role).
247 // If table has presentation role, it will be like 250 // If table has presentation role, it will be like
248 // cell(group)-> tr(unknown) -> tfoot, tbody, thead(ignored) -> table(presenta tion). 251 // cell(group)-> tr(unknown) -> tfoot, tbody, thead(ignored) ->
252 // table(presentation).
249 if (isHTMLTableCellElement(*currentElement) && 253 if (isHTMLTableCellElement(*currentElement) &&
250 isHTMLTableRowElement(*parentNode)) 254 isHTMLTableRowElement(*parentNode))
251 return parent->hasInheritedPresentationalRole(); 255 return parent->hasInheritedPresentationalRole();
252 256
253 if (isHTMLTableRowElement(*currentElement) && 257 if (isHTMLTableRowElement(*currentElement) &&
254 isHTMLTableSectionElement(toHTMLElement(*parentNode))) { 258 isHTMLTableSectionElement(toHTMLElement(*parentNode))) {
255 // Because TableSections have ignored role, presentation should be checked w ith its parent node 259 // Because TableSections have ignored role, presentation should be checked
260 // with its parent node.
256 AXObject* tableObject = parent->parentObject(); 261 AXObject* tableObject = parent->parentObject();
257 Node* tableNode = tableObject ? tableObject->getNode() : 0; 262 Node* tableNode = tableObject ? tableObject->getNode() : 0;
258 return isHTMLTableElement(tableNode) && 263 return isHTMLTableElement(tableNode) &&
259 tableObject->hasInheritedPresentationalRole(); 264 tableObject->hasInheritedPresentationalRole();
260 } 265 }
261 return false; 266 return false;
262 } 267 }
263 268
264 static bool isRequiredOwnedElement(AXObject* parent, 269 static bool isRequiredOwnedElement(AXObject* parent,
265 AccessibilityRole currentRole, 270 AccessibilityRole currentRole,
(...skipping 10 matching lines...) Expand all
276 currentRole == MenuItemRadioRole) 281 currentRole == MenuItemRadioRole)
277 return isHTMLMenuElement(*parentNode); 282 return isHTMLMenuElement(*parentNode);
278 283
279 if (!currentElement) 284 if (!currentElement)
280 return false; 285 return false;
281 if (isHTMLTableCellElement(*currentElement)) 286 if (isHTMLTableCellElement(*currentElement))
282 return isHTMLTableRowElement(*parentNode); 287 return isHTMLTableRowElement(*parentNode);
283 if (isHTMLTableRowElement(*currentElement)) 288 if (isHTMLTableRowElement(*currentElement))
284 return isHTMLTableSectionElement(toHTMLElement(*parentNode)); 289 return isHTMLTableSectionElement(toHTMLElement(*parentNode));
285 290
286 // In case of ListboxRole and it's child, ListBoxOptionRole, 291 // In case of ListboxRole and its child, ListBoxOptionRole, inheritance of
287 // Inheritance of presentation role is handled in AXListBoxOption 292 // presentation role is handled in AXListBoxOption because ListBoxOption Role
288 // Because ListBoxOption Role doesn't have any child. 293 // doesn't have any child.
289 // If it's just ignored because of presentation, we can't see any AX tree rela ted to ListBoxOption. 294 // If it's just ignored because of presentation, we can't see any AX tree
295 // related to ListBoxOption.
290 return false; 296 return false;
291 } 297 }
292 298
293 const AXObject* AXNodeObject::inheritsPresentationalRoleFrom() const { 299 const AXObject* AXNodeObject::inheritsPresentationalRoleFrom() const {
294 // ARIA states if an item can get focus, it should not be presentational. 300 // ARIA states if an item can get focus, it should not be presentational.
295 if (canSetFocusAttribute()) 301 if (canSetFocusAttribute())
296 return 0; 302 return 0;
297 303
298 if (isPresentational()) 304 if (isPresentational())
299 return this; 305 return this;
300 306
301 // http://www.w3.org/TR/wai-aria/complete#presentation 307 // http://www.w3.org/TR/wai-aria/complete#presentation
302 // ARIA spec says that the user agent MUST apply an inherited role of presenta tion 308 // ARIA spec says that the user agent MUST apply an inherited role of
309 // presentation
303 // to any owned elements that do not have an explicit role defined. 310 // to any owned elements that do not have an explicit role defined.
304 if (ariaRoleAttribute() != UnknownRole) 311 if (ariaRoleAttribute() != UnknownRole)
305 return 0; 312 return 0;
306 313
307 AXObject* parent = parentObject(); 314 AXObject* parent = parentObject();
308 if (!parent) 315 if (!parent)
309 return 0; 316 return 0;
310 317
311 HTMLElement* element = nullptr; 318 HTMLElement* element = nullptr;
312 if (getNode() && getNode()->isHTMLElement()) 319 if (getNode() && getNode()->isHTMLElement())
313 element = toHTMLElement(getNode()); 320 element = toHTMLElement(getNode());
314 if (!parent->hasInheritedPresentationalRole()) { 321 if (!parent->hasInheritedPresentationalRole()) {
315 if (!getLayoutObject() || !getLayoutObject()->isBoxModelObject()) 322 if (!getLayoutObject() || !getLayoutObject()->isBoxModelObject())
316 return 0; 323 return 0;
317 324
318 LayoutBoxModelObject* cssBox = toLayoutBoxModelObject(getLayoutObject()); 325 LayoutBoxModelObject* cssBox = toLayoutBoxModelObject(getLayoutObject());
319 if (!cssBox->isTableCell() && !cssBox->isTableRow()) 326 if (!cssBox->isTableCell() && !cssBox->isTableRow())
320 return 0; 327 return 0;
321 328
322 if (!isPresentationalInTable(parent, element)) 329 if (!isPresentationalInTable(parent, element))
323 return 0; 330 return 0;
324 } 331 }
325 // ARIA spec says that when a parent object is presentational and this object 332 // ARIA spec says that when a parent object is presentational and this object
326 // is a required owned element of that parent, then this object is also presen tational. 333 // is a required owned element of that parent, then this object is also
334 // presentational.
327 if (isRequiredOwnedElement(parent, roleValue(), element)) 335 if (isRequiredOwnedElement(parent, roleValue(), element))
328 return parent; 336 return parent;
329 return 0; 337 return 0;
330 } 338 }
331 339
332 bool AXNodeObject::isDescendantOfElementType( 340 bool AXNodeObject::isDescendantOfElementType(
333 const HTMLQualifiedName& tagName) const { 341 const HTMLQualifiedName& tagName) const {
334 if (!getNode()) 342 if (!getNode())
335 return false; 343 return false;
336 344
337 for (Element* parent = getNode()->parentElement(); parent; 345 for (Element* parent = getNode()->parentElement(); parent;
338 parent = parent->parentElement()) { 346 parent = parent->parentElement()) {
339 if (parent->hasTagName(tagName)) 347 if (parent->hasTagName(tagName))
340 return true; 348 return true;
341 } 349 }
342 return false; 350 return false;
343 } 351 }
344 352
345 AccessibilityRole AXNodeObject::nativeAccessibilityRoleIgnoringAria() const { 353 AccessibilityRole AXNodeObject::nativeAccessibilityRoleIgnoringAria() const {
346 if (!getNode()) 354 if (!getNode())
347 return UnknownRole; 355 return UnknownRole;
348 356
349 // HTMLAnchorElement sets isLink only when it has hrefAttr. 357 // HTMLAnchorElement sets isLink only when it has hrefAttr.
350 // We assume that it is also LinkRole if it has event listners even though it doesn't have hrefAttr. 358 // We assume that it is also LinkRole if it has event listners even though it
359 // doesn't have hrefAttr.
351 if (getNode()->isLink() || (isHTMLAnchorElement(*getNode()) && isClickable())) 360 if (getNode()->isLink() || (isHTMLAnchorElement(*getNode()) && isClickable()))
352 return LinkRole; 361 return LinkRole;
353 362
354 if (isHTMLButtonElement(*getNode())) 363 if (isHTMLButtonElement(*getNode()))
355 return buttonRoleType(); 364 return buttonRoleType();
356 365
357 if (isHTMLDetailsElement(*getNode())) 366 if (isHTMLDetailsElement(*getNode()))
358 return DetailsRole; 367 return DetailsRole;
359 368
360 if (isHTMLSummaryElement(*getNode())) { 369 if (isHTMLSummaryElement(*getNode())) {
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 498
490 if (getNode()->hasTagName(sectionTag)) 499 if (getNode()->hasTagName(sectionTag))
491 return RegionRole; 500 return RegionRole;
492 501
493 if (getNode()->hasTagName(addressTag)) 502 if (getNode()->hasTagName(addressTag))
494 return ContentInfoRole; 503 return ContentInfoRole;
495 504
496 if (isHTMLDialogElement(*getNode())) 505 if (isHTMLDialogElement(*getNode()))
497 return DialogRole; 506 return DialogRole;
498 507
499 // The HTML element should not be exposed as an element. That's what the Layou tView element does. 508 // The HTML element should not be exposed as an element. That's what the
509 // LayoutView element does.
500 if (isHTMLHtmlElement(*getNode())) 510 if (isHTMLHtmlElement(*getNode()))
501 return IgnoredRole; 511 return IgnoredRole;
502 512
503 if (isHTMLIFrameElement(*getNode())) { 513 if (isHTMLIFrameElement(*getNode())) {
504 const AtomicString& ariaRole = getAttribute(roleAttr); 514 const AtomicString& ariaRole = getAttribute(roleAttr);
505 if (ariaRole == "none" || ariaRole == "presentation") 515 if (ariaRole == "none" || ariaRole == "presentation")
506 return IframePresentationalRole; 516 return IframePresentationalRole;
507 return IframeRole; 517 return IframeRole;
508 } 518 }
509 519
510 // There should only be one banner/contentInfo per page. If header/footer are being used within an article or section 520 // There should only be one banner/contentInfo per page. If header/footer are
511 // then it should not be exposed as whole page's banner/contentInfo but as a g roup role. 521 // being used within an article or section then it should not be exposed as
522 // whole page's banner/contentInfo but as a group role.
512 if (getNode()->hasTagName(headerTag)) { 523 if (getNode()->hasTagName(headerTag)) {
513 if (isDescendantOfElementType(articleTag) || 524 if (isDescendantOfElementType(articleTag) ||
514 isDescendantOfElementType(sectionTag) || 525 isDescendantOfElementType(sectionTag) ||
515 (getNode()->parentElement() && 526 (getNode()->parentElement() &&
516 getNode()->parentElement()->hasTagName(mainTag))) { 527 getNode()->parentElement()->hasTagName(mainTag))) {
517 return GroupRole; 528 return GroupRole;
518 } 529 }
519 return BannerRole; 530 return BannerRole;
520 } 531 }
521 532
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 666
656 // If it's a control, it's not generic. 667 // If it's a control, it's not generic.
657 if (isControl()) 668 if (isControl())
658 return false; 669 return false;
659 670
660 // If it has an aria role, it's not generic. 671 // If it has an aria role, it's not generic.
661 if (m_ariaRole != UnknownRole) 672 if (m_ariaRole != UnknownRole)
662 return false; 673 return false;
663 674
664 // If the content editable attribute is set on this element, that's the reason 675 // If the content editable attribute is set on this element, that's the reason
665 // it's focusable, and existing logic should handle this case already - so it' s not a 676 // it's focusable, and existing logic should handle this case already - so
666 // generic focusable element. 677 // it's not a generic focusable element.
667 678
668 if (hasContentEditableAttributeSet()) 679 if (hasContentEditableAttributeSet())
669 return false; 680 return false;
670 681
671 // The web area and body element are both focusable, but existing logic handle s these 682 // The web area and body element are both focusable, but existing logic
672 // cases already, so we don't need to include them here. 683 // handles these cases already, so we don't need to include them here.
673 if (roleValue() == WebAreaRole) 684 if (roleValue() == WebAreaRole)
674 return false; 685 return false;
675 if (isHTMLBodyElement(getNode())) 686 if (isHTMLBodyElement(getNode()))
676 return false; 687 return false;
677 688
678 // An SVG root is focusable by default, but it's probably not interactive, so don't 689 // An SVG root is focusable by default, but it's probably not interactive, so
679 // include it. It can still be made accessible by giving it an ARIA role. 690 // don't include it. It can still be made accessible by giving it an ARIA
691 // role.
680 if (roleValue() == SVGRootRole) 692 if (roleValue() == SVGRootRole)
681 return false; 693 return false;
682 694
683 return true; 695 return true;
684 } 696 }
685 697
686 AXObject* AXNodeObject::menuButtonForMenu() const { 698 AXObject* AXNodeObject::menuButtonForMenu() const {
687 Element* menuItem = menuItemElementForMenu(); 699 Element* menuItem = menuItemElementForMenu();
688 700
689 if (menuItem) { 701 if (menuItem) {
690 // ARIA just has generic menu items. AppKit needs to know if this is a top l evel items like MenuBarButton or MenuBarItem 702 // ARIA just has generic menu items. AppKit needs to know if this is a top
703 // level items like MenuBarButton or MenuBarItem
691 AXObject* menuItemAX = axObjectCache().getOrCreate(menuItem); 704 AXObject* menuItemAX = axObjectCache().getOrCreate(menuItem);
692 if (menuItemAX && menuItemAX->isMenuButton()) 705 if (menuItemAX && menuItemAX->isMenuButton())
693 return menuItemAX; 706 return menuItemAX;
694 } 707 }
695 return 0; 708 return 0;
696 } 709 }
697 710
698 static Element* siblingWithAriaRole(String role, Node* node) { 711 static Element* siblingWithAriaRole(String role, Node* node) {
699 Node* parent = node->parentNode(); 712 Node* parent = node->parentNode();
700 if (!parent) 713 if (!parent)
(...skipping 22 matching lines...) Expand all
723 return 0; 736 return 0;
724 737
725 if (!node->isElementNode()) 738 if (!node->isElementNode())
726 node = node->parentElement(); 739 node = node->parentElement();
727 740
728 if (!node) 741 if (!node)
729 return 0; 742 return 0;
730 743
731 for (Element* element = toElement(node); element; 744 for (Element* element = toElement(node); element;
732 element = element->parentElement()) { 745 element = element->parentElement()) {
733 // It's a pretty common practice to put click listeners on the body or docum ent, but that's 746 // It's a pretty common practice to put click listeners on the body or
734 // almost never what the user wants when clicking on an accessible element. 747 // document, but that's almost never what the user wants when clicking on an
748 // accessible element.
735 if (isHTMLBodyElement(element)) 749 if (isHTMLBodyElement(element))
736 break; 750 break;
737 751
738 if (element->hasEventListeners(EventTypeNames::click) || 752 if (element->hasEventListeners(EventTypeNames::click) ||
739 element->hasEventListeners(EventTypeNames::mousedown) || 753 element->hasEventListeners(EventTypeNames::mousedown) ||
740 element->hasEventListeners(EventTypeNames::mouseup) || 754 element->hasEventListeners(EventTypeNames::mouseup) ||
741 element->hasEventListeners(EventTypeNames::DOMActivate)) 755 element->hasEventListeners(EventTypeNames::DOMActivate))
742 return element; 756 return element;
743 } 757 }
744 758
745 return 0; 759 return 0;
746 } 760 }
747 761
748 AccessibilityRole AXNodeObject::remapAriaRoleDueToParent( 762 AccessibilityRole AXNodeObject::remapAriaRoleDueToParent(
749 AccessibilityRole role) const { 763 AccessibilityRole role) const {
750 // Some objects change their role based on their parent. 764 // Some objects change their role based on their parent.
751 // However, asking for the unignoredParent calls accessibilityIsIgnored(), whi ch can trigger a loop. 765 // However, asking for the unignoredParent calls accessibilityIsIgnored(),
752 // While inside the call stack of creating an element, we need to avoid access ibilityIsIgnored(). 766 // which can trigger a loop. While inside the call stack of creating an
767 // element, we need to avoid accessibilityIsIgnored().
753 // https://bugs.webkit.org/show_bug.cgi?id=65174 768 // https://bugs.webkit.org/show_bug.cgi?id=65174
754 769
755 if (role != ListBoxOptionRole && role != MenuItemRole) 770 if (role != ListBoxOptionRole && role != MenuItemRole)
756 return role; 771 return role;
757 772
758 for (AXObject* parent = parentObject(); 773 for (AXObject* parent = parentObject();
759 parent && !parent->accessibilityIsIgnored(); 774 parent && !parent->accessibilityIsIgnored();
760 parent = parent->parentObject()) { 775 parent = parent->parentObject()) {
761 AccessibilityRole parentAriaRole = parent->ariaRoleAttribute(); 776 AccessibilityRole parentAriaRole = parent->ariaRoleAttribute();
762 777
763 // Selects and listboxes both have options as child roles, but they map to d ifferent roles within WebCore. 778 // Selects and listboxes both have options as child roles, but they map to
779 // different roles within WebCore.
764 if (role == ListBoxOptionRole && parentAriaRole == MenuRole) 780 if (role == ListBoxOptionRole && parentAriaRole == MenuRole)
765 return MenuItemRole; 781 return MenuItemRole;
766 // An aria "menuitem" may map to MenuButton or MenuItem depending on its par ent. 782 // An aria "menuitem" may map to MenuButton or MenuItem depending on its
783 // parent.
767 if (role == MenuItemRole && parentAriaRole == GroupRole) 784 if (role == MenuItemRole && parentAriaRole == GroupRole)
768 return MenuButtonRole; 785 return MenuButtonRole;
769 786
770 // If the parent had a different role, then we don't need to continue search ing up the chain. 787 // If the parent had a different role, then we don't need to continue
788 // searching up the chain.
771 if (parentAriaRole) 789 if (parentAriaRole)
772 break; 790 break;
773 } 791 }
774 792
775 return role; 793 return role;
776 } 794 }
777 795
778 void AXNodeObject::init() { 796 void AXNodeObject::init() {
779 #if ENABLE(ASSERT) 797 #if ENABLE(ASSERT)
780 ASSERT(!m_initialized); 798 ASSERT(!m_initialized);
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
989 // Otherwise it's not checked 1007 // Otherwise it's not checked
990 return false; 1008 return false;
991 } 1009 }
992 1010
993 bool AXNodeObject::isClickable() const { 1011 bool AXNodeObject::isClickable() const {
994 if (getNode()) { 1012 if (getNode()) {
995 if (getNode()->isElementNode() && 1013 if (getNode()->isElementNode() &&
996 toElement(getNode())->isDisabledFormControl()) 1014 toElement(getNode())->isDisabledFormControl())
997 return false; 1015 return false;
998 1016
999 // Note: we can't call getNode()->willRespondToMouseClickEvents() because th at triggers a style recalc and can delete this. 1017 // Note: we can't call getNode()->willRespondToMouseClickEvents() because
1018 // that triggers a style recalc and can delete this.
1000 if (getNode()->hasEventListeners(EventTypeNames::mouseup) || 1019 if (getNode()->hasEventListeners(EventTypeNames::mouseup) ||
1001 getNode()->hasEventListeners(EventTypeNames::mousedown) || 1020 getNode()->hasEventListeners(EventTypeNames::mousedown) ||
1002 getNode()->hasEventListeners(EventTypeNames::click) || 1021 getNode()->hasEventListeners(EventTypeNames::click) ||
1003 getNode()->hasEventListeners(EventTypeNames::DOMActivate)) 1022 getNode()->hasEventListeners(EventTypeNames::DOMActivate))
1004 return true; 1023 return true;
1005 } 1024 }
1006 1025
1007 return AXObject::isClickable(); 1026 return AXObject::isClickable();
1008 } 1027 }
1009 1028
(...skipping 27 matching lines...) Expand all
1037 } 1056 }
1038 1057
1039 bool AXNodeObject::isPressed() const { 1058 bool AXNodeObject::isPressed() const {
1040 if (!isButton()) 1059 if (!isButton())
1041 return false; 1060 return false;
1042 1061
1043 Node* node = this->getNode(); 1062 Node* node = this->getNode();
1044 if (!node) 1063 if (!node)
1045 return false; 1064 return false;
1046 1065
1047 // ARIA button with aria-pressed not undefined, then check for aria-pressed at tribute rather than getNode()->active() 1066 // ARIA button with aria-pressed not undefined, then check for aria-pressed
1067 // attribute rather than getNode()->active()
1048 if (ariaRoleAttribute() == ToggleButtonRole) { 1068 if (ariaRoleAttribute() == ToggleButtonRole) {
1049 if (equalIgnoringCase(getAttribute(aria_pressedAttr), "true") || 1069 if (equalIgnoringCase(getAttribute(aria_pressedAttr), "true") ||
1050 equalIgnoringCase(getAttribute(aria_pressedAttr), "mixed")) 1070 equalIgnoringCase(getAttribute(aria_pressedAttr), "mixed"))
1051 return true; 1071 return true;
1052 return false; 1072 return false;
1053 } 1073 }
1054 1074
1055 return node->active(); 1075 return node->active();
1056 } 1076 }
1057 1077
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1091 1111
1092 if (isWebArea()) 1112 if (isWebArea())
1093 return true; 1113 return true;
1094 1114
1095 // Children of elements with an aria-activedescendant attribute should be 1115 // Children of elements with an aria-activedescendant attribute should be
1096 // focusable if they have a (non-presentational) ARIA role. 1116 // focusable if they have a (non-presentational) ARIA role.
1097 if (!isPresentational() && ariaRoleAttribute() != UnknownRole && 1117 if (!isPresentational() && ariaRoleAttribute() != UnknownRole &&
1098 ancestorExposesActiveDescendant()) 1118 ancestorExposesActiveDescendant())
1099 return true; 1119 return true;
1100 1120
1101 // NOTE: It would be more accurate to ask the document whether setFocusedNode( ) would 1121 // NOTE: It would be more accurate to ask the document whether
1102 // do anything. For example, setFocusedNode() will do nothing if the current f ocused 1122 // setFocusedNode() would do anything. For example, setFocusedNode() will do
1103 // node will not relinquish the focus. 1123 // nothing if the current focused node will not relinquish the focus.
1104 if (isDisabledFormControl(node)) 1124 if (isDisabledFormControl(node))
1105 return false; 1125 return false;
1106 1126
1107 return node->isElementNode() && toElement(node)->supportsFocus(); 1127 return node->isElementNode() && toElement(node)->supportsFocus();
1108 } 1128 }
1109 1129
1110 bool AXNodeObject::canSetValueAttribute() const { 1130 bool AXNodeObject::canSetValueAttribute() const {
1111 if (equalIgnoringCase(getAttribute(aria_readonlyAttr), "true")) 1131 if (equalIgnoringCase(getAttribute(aria_readonlyAttr), "true"))
1112 return false; 1132 return false;
1113 1133
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
1509 return overriddenDescription; 1529 return overriddenDescription;
1510 } 1530 }
1511 if (!selectElement.multiple()) 1531 if (!selectElement.multiple())
1512 return selectElement.value(); 1532 return selectElement.value();
1513 return String(); 1533 return String();
1514 } 1534 }
1515 1535
1516 if (isNativeTextControl()) 1536 if (isNativeTextControl())
1517 return text(); 1537 return text();
1518 1538
1519 // Handle other HTML input elements that aren't text controls, like date and t ime 1539 // Handle other HTML input elements that aren't text controls, like date and
1520 // controls, by returning the string value, with the exception of checkboxes 1540 // time controls, by returning the string value, with the exception of
1521 // and radio buttons (which would return "on"). 1541 // checkboxes and radio buttons (which would return "on").
1522 if (isHTMLInputElement(node)) { 1542 if (isHTMLInputElement(node)) {
1523 HTMLInputElement* input = toHTMLInputElement(node); 1543 HTMLInputElement* input = toHTMLInputElement(node);
1524 if (input->type() != InputTypeNames::checkbox && 1544 if (input->type() != InputTypeNames::checkbox &&
1525 input->type() != InputTypeNames::radio) 1545 input->type() != InputTypeNames::radio)
1526 return input->value(); 1546 return input->value();
1527 } 1547 }
1528 1548
1529 return String(); 1549 return String();
1530 } 1550 }
1531 1551
(...skipping 25 matching lines...) Expand all
1557 if (!blockFlow->inlineBoxWrapper()) 1577 if (!blockFlow->inlineBoxWrapper())
1558 return blockFlow; 1578 return blockFlow;
1559 } 1579 }
1560 current = current->parent(); 1580 current = current->parent();
1561 } 1581 }
1562 1582
1563 ASSERT_NOT_REACHED(); 1583 ASSERT_NOT_REACHED();
1564 return nullptr; 1584 return nullptr;
1565 } 1585 }
1566 1586
1567 // Returns true if |r1| and |r2| are both non-null, both inline, and are contain ed 1587 // Returns true if |r1| and |r2| are both non-null, both inline, and are
1568 // within the same non-inline LayoutBlockFlow. 1588 // contained within the same non-inline LayoutBlockFlow.
1569 static bool isInSameNonInlineBlockFlow(LayoutObject* r1, LayoutObject* r2) { 1589 static bool isInSameNonInlineBlockFlow(LayoutObject* r1, LayoutObject* r2) {
1570 if (!r1 || !r2) 1590 if (!r1 || !r2)
1571 return false; 1591 return false;
1572 if (!r1->isInline() || !r2->isInline()) 1592 if (!r1->isInline() || !r2->isInline())
1573 return false; 1593 return false;
1574 LayoutBlockFlow* b1 = nonInlineBlockFlow(r1); 1594 LayoutBlockFlow* b1 = nonInlineBlockFlow(r1);
1575 LayoutBlockFlow* b2 = nonInlineBlockFlow(r2); 1595 LayoutBlockFlow* b2 = nonInlineBlockFlow(r2);
1576 return b1 && b2 && b1 == b2; 1596 return b1 && b2 && b1 == b2;
1577 } 1597 }
1578 1598
1579 bool AXNodeObject::isNativeCheckboxInMixedState() const { 1599 bool AXNodeObject::isNativeCheckboxInMixedState() const {
1580 if (!isHTMLInputElement(m_node)) 1600 if (!isHTMLInputElement(m_node))
1581 return false; 1601 return false;
1582 1602
1583 HTMLInputElement* input = toHTMLInputElement(m_node); 1603 HTMLInputElement* input = toHTMLInputElement(m_node);
1584 return input->type() == InputTypeNames::checkbox && 1604 return input->type() == InputTypeNames::checkbox &&
1585 input->shouldAppearIndeterminate(); 1605 input->shouldAppearIndeterminate();
1586 } 1606 }
1587 1607
1588 // 1608 //
1589 // New AX name calculation. 1609 // New AX name calculation.
1590 // 1610 //
1591 1611
1592 String AXNodeObject::textAlternative(bool recursive, 1612 String AXNodeObject::textAlternative(bool recursive,
1593 bool inAriaLabelledByTraversal, 1613 bool inAriaLabelledByTraversal,
1594 AXObjectSet& visited, 1614 AXObjectSet& visited,
1595 AXNameFrom& nameFrom, 1615 AXNameFrom& nameFrom,
1596 AXRelatedObjectVector* relatedObjects, 1616 AXRelatedObjectVector* relatedObjects,
1597 NameSources* nameSources) const { 1617 NameSources* nameSources) const {
1598 // If nameSources is non-null, relatedObjects is used in filling it in, so it must be non-null as well. 1618 // If nameSources is non-null, relatedObjects is used in filling it in, so it
1619 // must be non-null as well.
1599 if (nameSources) 1620 if (nameSources)
1600 ASSERT(relatedObjects); 1621 ASSERT(relatedObjects);
1601 1622
1602 bool foundTextAlternative = false; 1623 bool foundTextAlternative = false;
1603 1624
1604 if (!getNode() && !getLayoutObject()) 1625 if (!getNode() && !getLayoutObject())
1605 return String(); 1626 return String();
1606 1627
1607 String textAlternative = ariaTextAlternative( 1628 String textAlternative = ariaTextAlternative(
1608 recursive, inAriaLabelledByTraversal, visited, nameFrom, relatedObjects, 1629 recursive, inAriaLabelledByTraversal, visited, nameFrom, relatedObjects,
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1706 computeAriaOwnsChildren(ownedChildren); 1727 computeAriaOwnsChildren(ownedChildren);
1707 for (AXObject* obj = rawFirstChild(); obj; obj = obj->rawNextSibling()) { 1728 for (AXObject* obj = rawFirstChild(); obj; obj = obj->rawNextSibling()) {
1708 if (!axObjectCache().isAriaOwned(obj)) 1729 if (!axObjectCache().isAriaOwned(obj))
1709 children.append(obj); 1730 children.append(obj);
1710 } 1731 }
1711 for (const auto& ownedChild : ownedChildren) 1732 for (const auto& ownedChild : ownedChildren)
1712 children.append(ownedChild); 1733 children.append(ownedChild);
1713 1734
1714 for (AXObject* child : children) { 1735 for (AXObject* child : children) {
1715 // Don't recurse into children that are explicitly marked as aria-hidden. 1736 // Don't recurse into children that are explicitly marked as aria-hidden.
1716 // Note that we don't call isInertOrAriaHidden because that would return tru e 1737 // Note that we don't call isInertOrAriaHidden because that would return
1717 // if any ancestor is hidden, but we need to be able to compute the accessib le 1738 // true if any ancestor is hidden, but we need to be able to compute the
1718 // name of object inside hidden subtrees (for example, if aria-labelledby po ints 1739 // accessible name of object inside hidden subtrees (for example, if
1719 // to an object that's hidden). 1740 // aria-labelledby points to an object that's hidden).
1720 if (equalIgnoringCase(child->getAttribute(aria_hiddenAttr), "true")) 1741 if (equalIgnoringCase(child->getAttribute(aria_hiddenAttr), "true"))
1721 continue; 1742 continue;
1722 1743
1723 // If we're going between two layoutObjects that are in separate LayoutBoxes , add 1744 // If we're going between two layoutObjects that are in separate
1724 // whitespace if it wasn't there already. Intuitively if you have 1745 // LayoutBoxes, add whitespace if it wasn't there already. Intuitively if
1725 // <span>Hello</span><span>World</span>, those are part of the same LayoutBo x 1746 // you have <span>Hello</span><span>World</span>, those are part of the same
1726 // so we should return "HelloWorld", but given <div>Hello</div><div>World</d iv> the 1747 // LayoutBox so we should return "HelloWorld", but given
1727 // strings are in separate boxes so we should return "Hello World". 1748 // <div>Hello</div><div>World</div> the strings are in separate boxes so we
1749 // should return "Hello World".
1728 if (previous && accumulatedText.length() && 1750 if (previous && accumulatedText.length() &&
1729 !isHTMLSpace(accumulatedText[accumulatedText.length() - 1])) { 1751 !isHTMLSpace(accumulatedText[accumulatedText.length() - 1])) {
1730 if (!isInSameNonInlineBlockFlow(child->getLayoutObject(), 1752 if (!isInSameNonInlineBlockFlow(child->getLayoutObject(),
1731 previous->getLayoutObject())) 1753 previous->getLayoutObject()))
1732 accumulatedText.append(' '); 1754 accumulatedText.append(' ');
1733 } 1755 }
1734 1756
1735 String result; 1757 String result;
1736 if (child->isPresentational()) 1758 if (child->isPresentational())
1737 result = child->textFromDescendants(visited, true); 1759 result = child->textFromDescendants(visited, true);
1738 else 1760 else
1739 result = recursiveTextAlternative(*child, false, visited); 1761 result = recursiveTextAlternative(*child, false, visited);
1740 accumulatedText.append(result); 1762 accumulatedText.append(result);
1741 previous = child; 1763 previous = child;
1742 } 1764 }
1743 1765
1744 return accumulatedText.toString(); 1766 return accumulatedText.toString();
1745 } 1767 }
1746 1768
1747 bool AXNodeObject::nameFromLabelElement() const { 1769 bool AXNodeObject::nameFromLabelElement() const {
1748 // This unfortunately duplicates a bit of logic from textAlternative and nativ eTextAlternative, 1770 // This unfortunately duplicates a bit of logic from textAlternative and
1749 // but it's necessary because nameFromLabelElement needs to be called from 1771 // nativeTextAlternative, but it's necessary because nameFromLabelElement
1750 // computeAccessibilityIsIgnored, which isn't allowed to call axObjectCache->g etOrCreate. 1772 // needs to be called from computeAccessibilityIsIgnored, which isn't allowed
1773 // to call axObjectCache->getOrCreate.
1751 1774
1752 if (!getNode() && !getLayoutObject()) 1775 if (!getNode() && !getLayoutObject())
1753 return false; 1776 return false;
1754 1777
1755 // Step 2A from: http://www.w3.org/TR/accname-aam-1.1 1778 // Step 2A from: http://www.w3.org/TR/accname-aam-1.1
1756 if (isHiddenForTextAlternativeCalculation()) 1779 if (isHiddenForTextAlternativeCalculation())
1757 return false; 1780 return false;
1758 1781
1759 // Step 2B from: http://www.w3.org/TR/accname-aam-1.1 1782 // Step 2B from: http://www.w3.org/TR/accname-aam-1.1
1760 HeapVector<Member<Element>> elements; 1783 HeapVector<Member<Element>> elements;
1761 ariaLabelledbyElementVector(elements); 1784 ariaLabelledbyElementVector(elements);
1762 if (elements.size() > 0) 1785 if (elements.size() > 0)
1763 return false; 1786 return false;
1764 1787
1765 // Step 2C from: http://www.w3.org/TR/accname-aam-1.1 1788 // Step 2C from: http://www.w3.org/TR/accname-aam-1.1
1766 const AtomicString& ariaLabel = getAttribute(aria_labelAttr); 1789 const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
1767 if (!ariaLabel.isEmpty()) 1790 if (!ariaLabel.isEmpty())
1768 return false; 1791 return false;
1769 1792
1770 // Based on http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessibl e-name-and-description-calculation 1793 // Based on
1794 // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessible-name-an d-description-calculation
1771 // 5.1/5.5 Text inputs, Other labelable Elements 1795 // 5.1/5.5 Text inputs, Other labelable Elements
1772 HTMLElement* htmlElement = nullptr; 1796 HTMLElement* htmlElement = nullptr;
1773 if (getNode()->isHTMLElement()) 1797 if (getNode()->isHTMLElement())
1774 htmlElement = toHTMLElement(getNode()); 1798 htmlElement = toHTMLElement(getNode());
1775 if (htmlElement && isLabelableElement(htmlElement)) { 1799 if (htmlElement && isLabelableElement(htmlElement)) {
1776 if (toLabelableElement(htmlElement)->labels() && 1800 if (toLabelableElement(htmlElement)->labels() &&
1777 toLabelableElement(htmlElement)->labels()->length() > 0) 1801 toLabelableElement(htmlElement)->labels()->length() > 0)
1778 return true; 1802 return true;
1779 } 1803 }
1780 1804
1781 return false; 1805 return false;
1782 } 1806 }
1783 1807
1784 void AXNodeObject::getRelativeBounds(AXObject** outContainer, 1808 void AXNodeObject::getRelativeBounds(AXObject** outContainer,
1785 FloatRect& outBoundsInContainer, 1809 FloatRect& outBoundsInContainer,
1786 SkMatrix44& outContainerTransform) const { 1810 SkMatrix44& outContainerTransform) const {
1787 if (layoutObjectForRelativeBounds()) { 1811 if (layoutObjectForRelativeBounds()) {
1788 AXObject::getRelativeBounds(outContainer, outBoundsInContainer, 1812 AXObject::getRelativeBounds(outContainer, outBoundsInContainer,
1789 outContainerTransform); 1813 outContainerTransform);
1790 return; 1814 return;
1791 } 1815 }
1792 1816
1793 *outContainer = nullptr; 1817 *outContainer = nullptr;
1794 outBoundsInContainer = FloatRect(); 1818 outBoundsInContainer = FloatRect();
1795 outContainerTransform.setIdentity(); 1819 outContainerTransform.setIdentity();
1796 1820
1797 // First check if it has explicit bounds, for example if this element is tied to a 1821 // First check if it has explicit bounds, for example if this element is tied
1798 // canvas path. When explicit coordinates are provided, the ID of the explicit container 1822 // to a canvas path. When explicit coordinates are provided, the ID of the
1799 // element that the coordinates are relative to must be provided too. 1823 // explicit container element that the coordinates are relative to must be
1824 // provided too.
1800 if (!m_explicitElementRect.isEmpty()) { 1825 if (!m_explicitElementRect.isEmpty()) {
1801 *outContainer = axObjectCache().objectFromAXID(m_explicitContainerID); 1826 *outContainer = axObjectCache().objectFromAXID(m_explicitContainerID);
1802 if (*outContainer) { 1827 if (*outContainer) {
1803 outBoundsInContainer = FloatRect(m_explicitElementRect); 1828 outBoundsInContainer = FloatRect(m_explicitElementRect);
1804 return; 1829 return;
1805 } 1830 }
1806 } 1831 }
1807 1832
1808 // If it's in a canvas but doesn't have an explicit rect, get the bounding rec t of its children. 1833 // If it's in a canvas but doesn't have an explicit rect, get the bounding
1834 // rect of its children.
1809 if (getNode()->parentElement()->isInCanvasSubtree()) { 1835 if (getNode()->parentElement()->isInCanvasSubtree()) {
1810 Vector<FloatRect> rects; 1836 Vector<FloatRect> rects;
1811 for (Node& child : NodeTraversal::childrenOf(*getNode())) { 1837 for (Node& child : NodeTraversal::childrenOf(*getNode())) {
1812 if (child.isHTMLElement()) { 1838 if (child.isHTMLElement()) {
1813 if (AXObject* obj = axObjectCache().get(&child)) { 1839 if (AXObject* obj = axObjectCache().get(&child)) {
1814 AXObject* container; 1840 AXObject* container;
1815 FloatRect bounds; 1841 FloatRect bounds;
1816 obj->getRelativeBounds(&container, bounds, outContainerTransform); 1842 obj->getRelativeBounds(&container, bounds, outContainerTransform);
1817 if (container) { 1843 if (container) {
1818 *outContainer = container; 1844 *outContainer = container;
1819 rects.append(bounds); 1845 rects.append(bounds);
1820 } 1846 }
1821 } 1847 }
1822 } 1848 }
1823 } 1849 }
1824 1850
1825 if (*outContainer) { 1851 if (*outContainer) {
1826 outBoundsInContainer = unionRect(rects); 1852 outBoundsInContainer = unionRect(rects);
1827 return; 1853 return;
1828 } 1854 }
1829 } 1855 }
1830 1856
1831 // If this object doesn't have an explicit element rect or computable from its children, 1857 // If this object doesn't have an explicit element rect or computable from its
1832 // for now, let's return the position of the ancestor that does have a positio n, 1858 // children, for now, let's return the position of the ancestor that does have
1833 // and make it the width of that parent, and about the height of a line of tex t, so that 1859 // a position, and make it the width of that parent, and about the height of a
1834 // it's clear the object is a child of the parent. 1860 // line of text, so that it's clear the object is a child of the parent.
1835 for (AXObject* positionProvider = parentObject(); positionProvider; 1861 for (AXObject* positionProvider = parentObject(); positionProvider;
1836 positionProvider = positionProvider->parentObject()) { 1862 positionProvider = positionProvider->parentObject()) {
1837 if (positionProvider->isAXLayoutObject()) { 1863 if (positionProvider->isAXLayoutObject()) {
1838 positionProvider->getRelativeBounds(outContainer, outBoundsInContainer, 1864 positionProvider->getRelativeBounds(outContainer, outBoundsInContainer,
1839 outContainerTransform); 1865 outContainerTransform);
1840 if (*outContainer) 1866 if (*outContainer)
1841 outBoundsInContainer.setSize( 1867 outBoundsInContainer.setSize(
1842 FloatSize(outBoundsInContainer.width(), 1868 FloatSize(outBoundsInContainer.width(),
1843 std::min(10.0f, outBoundsInContainer.height()))); 1869 std::min(10.0f, outBoundsInContainer.height())));
1844 break; 1870 break;
1845 } 1871 }
1846 } 1872 }
1847 } 1873 }
1848 1874
1849 static Node* getParentNodeForComputeParent(Node* node) { 1875 static Node* getParentNodeForComputeParent(Node* node) {
1850 if (!node) 1876 if (!node)
1851 return nullptr; 1877 return nullptr;
1852 1878
1853 Node* parentNode = nullptr; 1879 Node* parentNode = nullptr;
1854 1880
1855 // Skip over <optgroup> and consider the <select> the immediate parent of an < option>. 1881 // Skip over <optgroup> and consider the <select> the immediate parent of an
1882 // <option>.
1856 if (isHTMLOptionElement(node)) 1883 if (isHTMLOptionElement(node))
1857 parentNode = toHTMLOptionElement(node)->ownerSelectElement(); 1884 parentNode = toHTMLOptionElement(node)->ownerSelectElement();
1858 1885
1859 if (!parentNode) 1886 if (!parentNode)
1860 parentNode = node->parentNode(); 1887 parentNode = node->parentNode();
1861 1888
1862 return parentNode; 1889 return parentNode;
1863 } 1890 }
1864 1891
1865 AXObject* AXNodeObject::computeParent() const { 1892 AXObject* AXNodeObject::computeParent() const {
(...skipping 30 matching lines...) Expand all
1896 Node* nextSibling = getNode()->nextSibling(); 1923 Node* nextSibling = getNode()->nextSibling();
1897 if (!nextSibling) 1924 if (!nextSibling)
1898 return 0; 1925 return 0;
1899 1926
1900 return axObjectCache().getOrCreate(nextSibling); 1927 return axObjectCache().getOrCreate(nextSibling);
1901 } 1928 }
1902 1929
1903 void AXNodeObject::addChildren() { 1930 void AXNodeObject::addChildren() {
1904 ASSERT(!isDetached()); 1931 ASSERT(!isDetached());
1905 // If the need to add more children in addition to existing children arises, 1932 // If the need to add more children in addition to existing children arises,
1906 // childrenChanged should have been called, leaving the object with no childre n. 1933 // childrenChanged should have been called, leaving the object with no
1934 // children.
1907 ASSERT(!m_haveChildren); 1935 ASSERT(!m_haveChildren);
1908 1936
1909 if (!m_node) 1937 if (!m_node)
1910 return; 1938 return;
1911 1939
1912 m_haveChildren = true; 1940 m_haveChildren = true;
1913 1941
1914 // The only time we add children from the DOM tree to a node with a layoutObje ct is when it's a canvas. 1942 // The only time we add children from the DOM tree to a node with a
1943 // layoutObject is when it's a canvas.
1915 if (getLayoutObject() && !isHTMLCanvasElement(*m_node)) 1944 if (getLayoutObject() && !isHTMLCanvasElement(*m_node))
1916 return; 1945 return;
1917 1946
1918 HeapVector<Member<AXObject>> ownedChildren; 1947 HeapVector<Member<AXObject>> ownedChildren;
1919 computeAriaOwnsChildren(ownedChildren); 1948 computeAriaOwnsChildren(ownedChildren);
1920 1949
1921 for (Node& child : NodeTraversal::childrenOf(*m_node)) { 1950 for (Node& child : NodeTraversal::childrenOf(*m_node)) {
1922 AXObject* childObj = axObjectCache().getOrCreate(&child); 1951 AXObject* childObj = axObjectCache().getOrCreate(&child);
1923 if (childObj && !axObjectCache().isAriaOwned(childObj)) 1952 if (childObj && !axObjectCache().isAriaOwned(childObj))
1924 addChild(childObj); 1953 addChild(childObj);
1925 } 1954 }
1926 1955
1927 for (const auto& ownedChild : ownedChildren) 1956 for (const auto& ownedChild : ownedChildren)
1928 addChild(ownedChild); 1957 addChild(ownedChild);
1929 1958
1930 for (const auto& child : m_children) 1959 for (const auto& child : m_children)
1931 child->setParent(this); 1960 child->setParent(this);
1932 } 1961 }
1933 1962
1934 void AXNodeObject::addChild(AXObject* child) { 1963 void AXNodeObject::addChild(AXObject* child) {
1935 insertChild(child, m_children.size()); 1964 insertChild(child, m_children.size());
1936 } 1965 }
1937 1966
1938 void AXNodeObject::insertChild(AXObject* child, unsigned index) { 1967 void AXNodeObject::insertChild(AXObject* child, unsigned index) {
1939 if (!child) 1968 if (!child)
1940 return; 1969 return;
1941 1970
1942 // If the parent is asking for this child's children, then either it's the fir st time (and clearing is a no-op), 1971 // If the parent is asking for this child's children, then either it's the
1943 // or its visibility has changed. In the latter case, this child may have a st ale child cached. 1972 // first time (and clearing is a no-op), or its visibility has changed. In the
1944 // This can prevent aria-hidden changes from working correctly. Hence, wheneve r a parent is getting children, ensure data is not stale. 1973 // latter case, this child may have a stale child cached. This can prevent
1974 // aria-hidden changes from working correctly. Hence, whenever a parent is
1975 // getting children, ensure data is not stale.
1945 child->clearChildren(); 1976 child->clearChildren();
1946 1977
1947 if (child->accessibilityIsIgnored()) { 1978 if (child->accessibilityIsIgnored()) {
1948 const auto& children = child->children(); 1979 const auto& children = child->children();
1949 size_t length = children.size(); 1980 size_t length = children.size();
1950 for (size_t i = 0; i < length; ++i) 1981 for (size_t i = 0; i < length; ++i)
1951 m_children.insert(index + i, children[i]); 1982 m_children.insert(index + i, children[i]);
1952 } else { 1983 } else {
1953 ASSERT(child->parentObject() == this); 1984 ASSERT(child->parentObject() == this);
1954 m_children.insert(index, child); 1985 m_children.insert(index, child);
1955 } 1986 }
1956 } 1987 }
1957 1988
1958 bool AXNodeObject::canHaveChildren() const { 1989 bool AXNodeObject::canHaveChildren() const {
1959 // If this is an AXLayoutObject, then it's okay if this object 1990 // If this is an AXLayoutObject, then it's okay if this object
1960 // doesn't have a node - there are some layoutObjects that don't have associat ed 1991 // doesn't have a node - there are some layoutObjects that don't have
1961 // nodes, like scroll areas and css-generated text. 1992 // associated nodes, like scroll areas and css-generated text.
1962 if (!getNode() && !isAXLayoutObject()) 1993 if (!getNode() && !isAXLayoutObject())
1963 return false; 1994 return false;
1964 1995
1965 if (getNode() && isHTMLMapElement(getNode())) 1996 if (getNode() && isHTMLMapElement(getNode()))
1966 return false; 1997 return false;
1967 1998
1968 AccessibilityRole role = roleValue(); 1999 AccessibilityRole role = roleValue();
1969 2000
1970 // If an element has an ARIA role of presentation, we need to consider the nat ive 2001 // If an element has an ARIA role of presentation, we need to consider the
1971 // role when deciding whether it can have children or not - otherwise giving s omething 2002 // native role when deciding whether it can have children or not - otherwise
1972 // a role of presentation could expose inner implementation details. 2003 // giving something a role of presentation could expose inner implementation
2004 // details.
1973 if (isPresentational()) 2005 if (isPresentational())
1974 role = nativeAccessibilityRoleIgnoringAria(); 2006 role = nativeAccessibilityRoleIgnoringAria();
1975 2007
1976 switch (role) { 2008 switch (role) {
1977 case ImageRole: 2009 case ImageRole:
1978 case ButtonRole: 2010 case ButtonRole:
1979 case PopUpButtonRole: 2011 case PopUpButtonRole:
1980 case CheckBoxRole: 2012 case CheckBoxRole:
1981 case RadioButtonRole: 2013 case RadioButtonRole:
1982 case SwitchRole: 2014 case SwitchRole:
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2038 } 2070 }
2039 2071
2040 Element* AXNodeObject::anchorElement() const { 2072 Element* AXNodeObject::anchorElement() const {
2041 Node* node = this->getNode(); 2073 Node* node = this->getNode();
2042 if (!node) 2074 if (!node)
2043 return 0; 2075 return 0;
2044 2076
2045 AXObjectCacheImpl& cache = axObjectCache(); 2077 AXObjectCacheImpl& cache = axObjectCache();
2046 2078
2047 // search up the DOM tree for an anchor element 2079 // search up the DOM tree for an anchor element
2048 // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElemen t 2080 // NOTE: this assumes that any non-image with an anchor is an
2081 // HTMLAnchorElement
2049 for (; node; node = node->parentNode()) { 2082 for (; node; node = node->parentNode()) {
2050 if (isHTMLAnchorElement(*node) || 2083 if (isHTMLAnchorElement(*node) ||
2051 (node->layoutObject() && 2084 (node->layoutObject() &&
2052 cache.getOrCreate(node->layoutObject())->isAnchor())) 2085 cache.getOrCreate(node->layoutObject())->isAnchor()))
2053 return toElement(node); 2086 return toElement(node);
2054 } 2087 }
2055 2088
2056 return 0; 2089 return 0;
2057 } 2090 }
2058 2091
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2103 void AXNodeObject::setFocused(bool on) { 2136 void AXNodeObject::setFocused(bool on) {
2104 if (!canSetFocusAttribute()) 2137 if (!canSetFocusAttribute())
2105 return; 2138 return;
2106 2139
2107 Document* document = this->getDocument(); 2140 Document* document = this->getDocument();
2108 if (!on) { 2141 if (!on) {
2109 document->clearFocusedElement(); 2142 document->clearFocusedElement();
2110 } else { 2143 } else {
2111 Node* node = this->getNode(); 2144 Node* node = this->getNode();
2112 if (node && node->isElementNode()) { 2145 if (node && node->isElementNode()) {
2113 // If this node is already the currently focused node, then calling focus( ) won't do anything. 2146 // If this node is already the currently focused node, then calling
2114 // That is a problem when focus is removed from the webpage to chrome, and then returns. 2147 // focus() won't do anything. That is a problem when focus is removed
2115 // In these cases, we need to do what keyboard and mouse focus do, which i s reset focus first. 2148 // from the webpage to chrome, and then returns. In these cases, we need
2149 // to do what keyboard and mouse focus do, which is reset focus first.
2116 if (document->focusedElement() == node) 2150 if (document->focusedElement() == node)
2117 document->clearFocusedElement(); 2151 document->clearFocusedElement();
2118 2152
2119 toElement(node)->focus(); 2153 toElement(node)->focus();
2120 } else { 2154 } else {
2121 document->clearFocusedElement(); 2155 document->clearFocusedElement();
2122 } 2156 }
2123 } 2157 }
2124 } 2158 }
2125 2159
2126 void AXNodeObject::increment() { 2160 void AXNodeObject::increment() {
2127 UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture); 2161 UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);
2128 alterSliderValue(true); 2162 alterSliderValue(true);
2129 } 2163 }
2130 2164
2131 void AXNodeObject::decrement() { 2165 void AXNodeObject::decrement() {
2132 UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture); 2166 UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);
2133 alterSliderValue(false); 2167 alterSliderValue(false);
2134 } 2168 }
2135 2169
2136 void AXNodeObject::childrenChanged() { 2170 void AXNodeObject::childrenChanged() {
2137 // This method is meant as a quick way of marking a portion of the accessibili ty tree dirty. 2171 // This method is meant as a quick way of marking a portion of the
2172 // accessibility tree dirty.
2138 if (!getNode() && !getLayoutObject()) 2173 if (!getNode() && !getLayoutObject())
2139 return; 2174 return;
2140 2175
2141 // If this is not part of the accessibility tree because an ancestor 2176 // If this is not part of the accessibility tree because an ancestor
2142 // has only presentational children, invalidate this object's children but 2177 // has only presentational children, invalidate this object's children but
2143 // skip sending a notification and skip walking up the ancestors. 2178 // skip sending a notification and skip walking up the ancestors.
2144 if (ancestorForWhichThisIsAPresentationalChild()) { 2179 if (ancestorForWhichThisIsAPresentationalChild()) {
2145 setNeedsToUpdateChildren(); 2180 setNeedsToUpdateChildren();
2146 return; 2181 return;
2147 } 2182 }
2148 2183
2149 axObjectCache().postNotification(this, AXObjectCacheImpl::AXChildrenChanged); 2184 axObjectCache().postNotification(this, AXObjectCacheImpl::AXChildrenChanged);
2150 2185
2151 // Go up the accessibility parent chain, but only if the element already exist s. This method is 2186 // Go up the accessibility parent chain, but only if the element already
2152 // called during layout, minimal work should be done. 2187 // exists. This method is called during layout, minimal work should be done.
2153 // If AX elements are created now, they could interrogate the layout tree whil e it's in a funky state. 2188 // If AX elements are created now, they could interrogate the layout tree
2154 // At the same time, process ARIA live region changes. 2189 // while it's in a funky state. At the same time, process ARIA live region
2190 // changes.
2155 for (AXObject* parent = this; parent; 2191 for (AXObject* parent = this; parent;
2156 parent = parent->parentObjectIfExists()) { 2192 parent = parent->parentObjectIfExists()) {
2157 parent->setNeedsToUpdateChildren(); 2193 parent->setNeedsToUpdateChildren();
2158 2194
2159 // These notifications always need to be sent because screenreaders are reli ant on them to perform. 2195 // These notifications always need to be sent because screenreaders are
2160 // In other words, they need to be sent even when the screen reader has not accessed this live region since the last update. 2196 // reliant on them to perform. In other words, they need to be sent even
2197 // when the screen reader has not accessed this live region since the last
2198 // update.
2161 2199
2162 // If this element supports ARIA live regions, then notify the AT of changes . 2200 // If this element supports ARIA live regions, then notify the AT of
2201 // changes.
2163 if (parent->isLiveRegion()) 2202 if (parent->isLiveRegion())
2164 axObjectCache().postNotification(parent, 2203 axObjectCache().postNotification(parent,
2165 AXObjectCacheImpl::AXLiveRegionChanged); 2204 AXObjectCacheImpl::AXLiveRegionChanged);
2166 2205
2167 // If this element is an ARIA text box or content editable, post a "value ch anged" notification on it 2206 // If this element is an ARIA text box or content editable, post a "value
2168 // so that it behaves just like a native input element or textarea. 2207 // changed" notification on it so that it behaves just like a native input
2208 // element or textarea.
2169 if (isNonNativeTextControl()) 2209 if (isNonNativeTextControl())
2170 axObjectCache().postNotification(parent, 2210 axObjectCache().postNotification(parent,
2171 AXObjectCacheImpl::AXValueChanged); 2211 AXObjectCacheImpl::AXValueChanged);
2172 } 2212 }
2173 } 2213 }
2174 2214
2175 void AXNodeObject::selectionChanged() { 2215 void AXNodeObject::selectionChanged() {
2176 // Post the selected text changed event on the first ancestor that's 2216 // Post the selected text changed event on the first ancestor that's
2177 // focused (to handle form controls, ARIA text boxes and contentEditable), 2217 // focused (to handle form controls, ARIA text boxes and contentEditable),
2178 // or the web area if the selection is just in the document somewhere. 2218 // or the web area if the selection is just in the document somewhere.
2179 if (isFocused() || isWebArea()) { 2219 if (isFocused() || isWebArea()) {
2180 axObjectCache().postNotification(this, 2220 axObjectCache().postNotification(this,
2181 AXObjectCacheImpl::AXSelectedTextChanged); 2221 AXObjectCacheImpl::AXSelectedTextChanged);
2182 if (getDocument()) { 2222 if (getDocument()) {
2183 AXObject* documentObject = axObjectCache().getOrCreate(getDocument()); 2223 AXObject* documentObject = axObjectCache().getOrCreate(getDocument());
2184 axObjectCache().postNotification( 2224 axObjectCache().postNotification(
2185 documentObject, AXObjectCacheImpl::AXDocumentSelectionChanged); 2225 documentObject, AXObjectCacheImpl::AXDocumentSelectionChanged);
2186 } 2226 }
2187 } else { 2227 } else {
2188 AXObject::selectionChanged(); // Calls selectionChanged on parent. 2228 AXObject::selectionChanged(); // Calls selectionChanged on parent.
2189 } 2229 }
2190 } 2230 }
2191 2231
2192 void AXNodeObject::textChanged() { 2232 void AXNodeObject::textChanged() {
2193 // If this element supports ARIA live regions, or is part of a region with an ARIA editable role, 2233 // If this element supports ARIA live regions, or is part of a region with an
2194 // then notify the AT of changes. 2234 // ARIA editable role, then notify the AT of changes.
2195 AXObjectCacheImpl& cache = axObjectCache(); 2235 AXObjectCacheImpl& cache = axObjectCache();
2196 for (Node* parentNode = getNode(); parentNode; 2236 for (Node* parentNode = getNode(); parentNode;
2197 parentNode = parentNode->parentNode()) { 2237 parentNode = parentNode->parentNode()) {
2198 AXObject* parent = cache.get(parentNode); 2238 AXObject* parent = cache.get(parentNode);
2199 if (!parent) 2239 if (!parent)
2200 continue; 2240 continue;
2201 2241
2202 if (parent->isLiveRegion()) 2242 if (parent->isLiveRegion())
2203 cache.postNotification(parentNode, 2243 cache.postNotification(parentNode,
2204 AXObjectCacheImpl::AXLiveRegionChanged); 2244 AXObjectCacheImpl::AXLiveRegionChanged);
2205 2245
2206 // If this element is an ARIA text box or content editable, post a "value ch anged" notification on it 2246 // If this element is an ARIA text box or content editable, post a "value
2207 // so that it behaves just like a native input element or textarea. 2247 // changed" notification on it so that it behaves just like a native input
2248 // element or textarea.
2208 if (parent->isNonNativeTextControl()) 2249 if (parent->isNonNativeTextControl())
2209 cache.postNotification(parentNode, AXObjectCacheImpl::AXValueChanged); 2250 cache.postNotification(parentNode, AXObjectCacheImpl::AXValueChanged);
2210 } 2251 }
2211 } 2252 }
2212 2253
2213 void AXNodeObject::updateAccessibilityRole() { 2254 void AXNodeObject::updateAccessibilityRole() {
2214 bool ignoredStatus = accessibilityIsIgnored(); 2255 bool ignoredStatus = accessibilityIsIgnored();
2215 m_role = determineAccessibilityRole(); 2256 m_role = determineAccessibilityRole();
2216 2257
2217 // The AX hierarchy only needs to be updated if the ignored status of an eleme nt has changed. 2258 // The AX hierarchy only needs to be updated if the ignored status of an
2259 // element has changed.
2218 if (ignoredStatus != accessibilityIsIgnored()) 2260 if (ignoredStatus != accessibilityIsIgnored())
2219 childrenChanged(); 2261 childrenChanged();
2220 } 2262 }
2221 2263
2222 void AXNodeObject::computeAriaOwnsChildren( 2264 void AXNodeObject::computeAriaOwnsChildren(
2223 HeapVector<Member<AXObject>>& ownedChildren) const { 2265 HeapVector<Member<AXObject>>& ownedChildren) const {
2224 if (!hasAttribute(aria_ownsAttr)) 2266 if (!hasAttribute(aria_ownsAttr))
2225 return; 2267 return;
2226 2268
2227 Vector<String> idVector; 2269 Vector<String> idVector;
2228 if (canHaveChildren() && !isNativeTextControl() && 2270 if (canHaveChildren() && !isNativeTextControl() &&
2229 !hasContentEditableAttributeSet()) 2271 !hasContentEditableAttributeSet())
2230 tokenVectorFromAttribute(idVector, aria_ownsAttr); 2272 tokenVectorFromAttribute(idVector, aria_ownsAttr);
2231 2273
2232 axObjectCache().updateAriaOwns(this, idVector, ownedChildren); 2274 axObjectCache().updateAriaOwns(this, idVector, ownedChildren);
2233 } 2275 }
2234 2276
2235 // Based on http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessible- name-and-description-calculation 2277 // Based on
2278 // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessible-name-and- description-calculation
2236 String AXNodeObject::nativeTextAlternative( 2279 String AXNodeObject::nativeTextAlternative(
2237 AXObjectSet& visited, 2280 AXObjectSet& visited,
2238 AXNameFrom& nameFrom, 2281 AXNameFrom& nameFrom,
2239 AXRelatedObjectVector* relatedObjects, 2282 AXRelatedObjectVector* relatedObjects,
2240 NameSources* nameSources, 2283 NameSources* nameSources,
2241 bool* foundTextAlternative) const { 2284 bool* foundTextAlternative) const {
2242 if (!getNode()) 2285 if (!getNode())
2243 return String(); 2286 return String();
2244 2287
2245 // If nameSources is non-null, relatedObjects is used in filling it in, so it must be non-null as well. 2288 // If nameSources is non-null, relatedObjects is used in filling it in, so it
2289 // must be non-null as well.
2246 if (nameSources) 2290 if (nameSources)
2247 ASSERT(relatedObjects); 2291 ASSERT(relatedObjects);
2248 2292
2249 String textAlternative; 2293 String textAlternative;
2250 AXRelatedObjectVector localRelatedObjects; 2294 AXRelatedObjectVector localRelatedObjects;
2251 2295
2252 const HTMLInputElement* inputElement = nullptr; 2296 const HTMLInputElement* inputElement = nullptr;
2253 if (isHTMLInputElement(getNode())) 2297 if (isHTMLInputElement(getNode()))
2254 inputElement = toHTMLInputElement(getNode()); 2298 inputElement = toHTMLInputElement(getNode());
2255 2299
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after
2663 description(nameFrom, descriptionFrom, nullptr, &relatedObjects); 2707 description(nameFrom, descriptionFrom, nullptr, &relatedObjects);
2664 if (descriptionObjects) { 2708 if (descriptionObjects) {
2665 descriptionObjects->clear(); 2709 descriptionObjects->clear();
2666 for (size_t i = 0; i < relatedObjects.size(); i++) 2710 for (size_t i = 0; i < relatedObjects.size(); i++)
2667 descriptionObjects->append(relatedObjects[i]->object); 2711 descriptionObjects->append(relatedObjects[i]->object);
2668 } 2712 }
2669 2713
2670 return collapseWhitespace(result); 2714 return collapseWhitespace(result);
2671 } 2715 }
2672 2716
2673 // Based on http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessible- name-and-description-calculation 2717 // Based on
2718 // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessible-name-and- description-calculation
2674 String AXNodeObject::description(AXNameFrom nameFrom, 2719 String AXNodeObject::description(AXNameFrom nameFrom,
2675 AXDescriptionFrom& descriptionFrom, 2720 AXDescriptionFrom& descriptionFrom,
2676 DescriptionSources* descriptionSources, 2721 DescriptionSources* descriptionSources,
2677 AXRelatedObjectVector* relatedObjects) const { 2722 AXRelatedObjectVector* relatedObjects) const {
2678 // If descriptionSources is non-null, relatedObjects is used in filling it in, so it must be non-null as well. 2723 // If descriptionSources is non-null, relatedObjects is used in filling it in,
2724 // so it must be non-null as well.
2679 if (descriptionSources) 2725 if (descriptionSources)
2680 ASSERT(relatedObjects); 2726 ASSERT(relatedObjects);
2681 2727
2682 if (!getNode()) 2728 if (!getNode())
2683 return String(); 2729 return String();
2684 2730
2685 String description; 2731 String description;
2686 bool foundDescription = false; 2732 bool foundDescription = false;
2687 2733
2688 descriptionFrom = AXDescriptionFromRelatedElement; 2734 descriptionFrom = AXDescriptionFromRelatedElement;
2689 if (descriptionSources) { 2735 if (descriptionSources) {
2690 descriptionSources->append( 2736 descriptionSources->append(
2691 DescriptionSource(foundDescription, aria_describedbyAttr)); 2737 DescriptionSource(foundDescription, aria_describedbyAttr));
2692 descriptionSources->last().type = descriptionFrom; 2738 descriptionSources->last().type = descriptionFrom;
2693 } 2739 }
2694 2740
2695 // aria-describedby overrides any other accessible description, from: http://r awgit.com/w3c/aria/master/html-aam/html-aam.html 2741 // aria-describedby overrides any other accessible description, from:
2742 // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
2696 const AtomicString& ariaDescribedby = getAttribute(aria_describedbyAttr); 2743 const AtomicString& ariaDescribedby = getAttribute(aria_describedbyAttr);
2697 if (!ariaDescribedby.isNull()) { 2744 if (!ariaDescribedby.isNull()) {
2698 if (descriptionSources) 2745 if (descriptionSources)
2699 descriptionSources->last().attributeValue = ariaDescribedby; 2746 descriptionSources->last().attributeValue = ariaDescribedby;
2700 2747
2701 description = textFromAriaDescribedby(relatedObjects); 2748 description = textFromAriaDescribedby(relatedObjects);
2702 2749
2703 if (!description.isNull()) { 2750 if (!description.isNull()) {
2704 if (descriptionSources) { 2751 if (descriptionSources) {
2705 DescriptionSource& source = descriptionSources->last(); 2752 DescriptionSource& source = descriptionSources->last();
2706 source.type = descriptionFrom; 2753 source.type = descriptionFrom;
2707 source.relatedObjects = *relatedObjects; 2754 source.relatedObjects = *relatedObjects;
2708 source.text = description; 2755 source.text = description;
2709 foundDescription = true; 2756 foundDescription = true;
2710 } else { 2757 } else {
2711 return description; 2758 return description;
2712 } 2759 }
2713 } else if (descriptionSources) { 2760 } else if (descriptionSources) {
2714 descriptionSources->last().invalid = true; 2761 descriptionSources->last().invalid = true;
2715 } 2762 }
2716 } 2763 }
2717 2764
2718 HTMLElement* htmlElement = nullptr; 2765 HTMLElement* htmlElement = nullptr;
2719 if (getNode()->isHTMLElement()) 2766 if (getNode()->isHTMLElement())
2720 htmlElement = toHTMLElement(getNode()); 2767 htmlElement = toHTMLElement(getNode());
2721 2768
2722 // placeholder, 5.1.2 from: http://rawgit.com/w3c/aria/master/html-aam/html-aa m.html 2769 // placeholder, 5.1.2 from:
2770 // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
2723 if (nameFrom != AXNameFromPlaceholder && htmlElement && 2771 if (nameFrom != AXNameFromPlaceholder && htmlElement &&
2724 htmlElement->isTextFormControl()) { 2772 htmlElement->isTextFormControl()) {
2725 descriptionFrom = AXDescriptionFromPlaceholder; 2773 descriptionFrom = AXDescriptionFromPlaceholder;
2726 if (descriptionSources) { 2774 if (descriptionSources) {
2727 descriptionSources->append( 2775 descriptionSources->append(
2728 DescriptionSource(foundDescription, placeholderAttr)); 2776 DescriptionSource(foundDescription, placeholderAttr));
2729 DescriptionSource& source = descriptionSources->last(); 2777 DescriptionSource& source = descriptionSources->last();
2730 source.type = descriptionFrom; 2778 source.type = descriptionFrom;
2731 } 2779 }
2732 HTMLElement* element = toHTMLElement(getNode()); 2780 HTMLElement* element = toHTMLElement(getNode());
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2764 if (descriptionSources) { 2812 if (descriptionSources) {
2765 DescriptionSource& source = descriptionSources->last(); 2813 DescriptionSource& source = descriptionSources->last();
2766 source.text = description; 2814 source.text = description;
2767 foundDescription = true; 2815 foundDescription = true;
2768 } else { 2816 } else {
2769 return description; 2817 return description;
2770 } 2818 }
2771 } 2819 }
2772 } 2820 }
2773 2821
2774 // table caption, 5.9.2 from: http://rawgit.com/w3c/aria/master/html-aam/html- aam.html 2822 // table caption, 5.9.2 from:
2823 // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
2775 if (nameFrom != AXNameFromCaption && isHTMLTableElement(getNode())) { 2824 if (nameFrom != AXNameFromCaption && isHTMLTableElement(getNode())) {
2776 HTMLTableElement* tableElement = toHTMLTableElement(getNode()); 2825 HTMLTableElement* tableElement = toHTMLTableElement(getNode());
2777 2826
2778 descriptionFrom = AXDescriptionFromRelatedElement; 2827 descriptionFrom = AXDescriptionFromRelatedElement;
2779 if (descriptionSources) { 2828 if (descriptionSources) {
2780 descriptionSources->append(DescriptionSource(foundDescription)); 2829 descriptionSources->append(DescriptionSource(foundDescription));
2781 descriptionSources->last().type = descriptionFrom; 2830 descriptionSources->last().type = descriptionFrom;
2782 descriptionSources->last().nativeSource = 2831 descriptionSources->last().nativeSource =
2783 AXTextFromNativeHTMLTableCaption; 2832 AXTextFromNativeHTMLTableCaption;
2784 } 2833 }
(...skipping 13 matching lines...) Expand all
2798 source.relatedObjects = *relatedObjects; 2847 source.relatedObjects = *relatedObjects;
2799 source.text = description; 2848 source.text = description;
2800 foundDescription = true; 2849 foundDescription = true;
2801 } else { 2850 } else {
2802 return description; 2851 return description;
2803 } 2852 }
2804 } 2853 }
2805 } 2854 }
2806 } 2855 }
2807 2856
2808 // summary, 5.6.2 from: http://rawgit.com/w3c/aria/master/html-aam/html-aam.ht ml 2857 // summary, 5.6.2 from:
2858 // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
2809 if (nameFrom != AXNameFromContents && isHTMLSummaryElement(getNode())) { 2859 if (nameFrom != AXNameFromContents && isHTMLSummaryElement(getNode())) {
2810 descriptionFrom = AXDescriptionFromContents; 2860 descriptionFrom = AXDescriptionFromContents;
2811 if (descriptionSources) { 2861 if (descriptionSources) {
2812 descriptionSources->append(DescriptionSource(foundDescription)); 2862 descriptionSources->append(DescriptionSource(foundDescription));
2813 descriptionSources->last().type = descriptionFrom; 2863 descriptionSources->last().type = descriptionFrom;
2814 } 2864 }
2815 2865
2816 AXObjectSet visited; 2866 AXObjectSet visited;
2817 description = textFromDescendants(visited, false); 2867 description = textFromDescendants(visited, false);
2818 2868
2819 if (!description.isEmpty()) { 2869 if (!description.isEmpty()) {
2820 if (descriptionSources) { 2870 if (descriptionSources) {
2821 foundDescription = true; 2871 foundDescription = true;
2822 descriptionSources->last().text = description; 2872 descriptionSources->last().text = description;
2823 } else { 2873 } else {
2824 return description; 2874 return description;
2825 } 2875 }
2826 } 2876 }
2827 } 2877 }
2828 2878
2829 // title attribute, from: http://rawgit.com/w3c/aria/master/html-aam/html-aam. html 2879 // title attribute, from:
2880 // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
2830 if (nameFrom != AXNameFromTitle) { 2881 if (nameFrom != AXNameFromTitle) {
2831 descriptionFrom = AXDescriptionFromAttribute; 2882 descriptionFrom = AXDescriptionFromAttribute;
2832 if (descriptionSources) { 2883 if (descriptionSources) {
2833 descriptionSources->append( 2884 descriptionSources->append(
2834 DescriptionSource(foundDescription, titleAttr)); 2885 DescriptionSource(foundDescription, titleAttr));
2835 descriptionSources->last().type = descriptionFrom; 2886 descriptionSources->last().type = descriptionFrom;
2836 } 2887 }
2837 const AtomicString& title = getAttribute(titleAttr); 2888 const AtomicString& title = getAttribute(titleAttr);
2838 if (!title.isEmpty()) { 2889 if (!title.isEmpty()) {
2839 description = title; 2890 description = title;
2840 if (descriptionSources) { 2891 if (descriptionSources) {
2841 foundDescription = true; 2892 foundDescription = true;
2842 descriptionSources->last().text = description; 2893 descriptionSources->last().text = description;
2843 } else { 2894 } else {
2844 return description; 2895 return description;
2845 } 2896 }
2846 } 2897 }
2847 } 2898 }
2848 2899
2849 // aria-help. 2900 // aria-help.
2850 // FIXME: this is not part of the official standard, but it's needed because t he built-in date/time controls use it. 2901 // FIXME: this is not part of the official standard, but it's needed because
2902 // the built-in date/time controls use it.
2851 descriptionFrom = AXDescriptionFromAttribute; 2903 descriptionFrom = AXDescriptionFromAttribute;
2852 if (descriptionSources) { 2904 if (descriptionSources) {
2853 descriptionSources->append( 2905 descriptionSources->append(
2854 DescriptionSource(foundDescription, aria_helpAttr)); 2906 DescriptionSource(foundDescription, aria_helpAttr));
2855 descriptionSources->last().type = descriptionFrom; 2907 descriptionSources->last().type = descriptionFrom;
2856 } 2908 }
2857 const AtomicString& help = getAttribute(aria_helpAttr); 2909 const AtomicString& help = getAttribute(aria_helpAttr);
2858 if (!help.isEmpty()) { 2910 if (!help.isEmpty()) {
2859 description = help; 2911 description = help;
2860 if (descriptionSources) { 2912 if (descriptionSources) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2904 } 2956 }
2905 return placeholder; 2957 return placeholder;
2906 } 2958 }
2907 2959
2908 DEFINE_TRACE(AXNodeObject) { 2960 DEFINE_TRACE(AXNodeObject) {
2909 visitor->trace(m_node); 2961 visitor->trace(m_node);
2910 AXObject::trace(visitor); 2962 AXObject::trace(visitor);
2911 } 2963 }
2912 2964
2913 } // namespace blink 2965 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698